From: Andrew Cooper Date: Fri, 23 Sep 2016 14:03:08 +0000 (+0100) Subject: x86/vmx: Shorten vmx_{get,set}_segment_register() for user segments X-Git-Tag: archive/raspbian/4.11.1-1+rpi1~1^2~66^2~3377 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=da2209921e509d809f049b98467b019b4600aebb;p=xen.git x86/vmx: Shorten vmx_{get,set}_segment_register() for user segments The x86_segment enumeration matches hardware SReg encoding, which can be used to calculate the appropriate VMCS fields, rather than open coding every instance. This reduces the size of the switch statement, and the number of embedded BUG frames from the __vm{read,write}() calls. In the unlikely case that a call does fault, the field can unambiguously be retrieved from the GPR state printed. Signed-off-by: Andrew Cooper Reviewed-by: Jan Beulich Acked-by: Kevin Tian --- diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 7b2c50cf44..47de37585e 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -969,41 +969,11 @@ void vmx_get_segment_register(struct vcpu *v, enum x86_segment seg, switch ( seg ) { - case x86_seg_cs: - __vmread(GUEST_CS_SELECTOR, &sel); - __vmread(GUEST_CS_LIMIT, &limit); - __vmread(GUEST_CS_BASE, ®->base); - __vmread(GUEST_CS_AR_BYTES, &attr); - break; - case x86_seg_ds: - __vmread(GUEST_DS_SELECTOR, &sel); - __vmread(GUEST_DS_LIMIT, &limit); - __vmread(GUEST_DS_BASE, ®->base); - __vmread(GUEST_DS_AR_BYTES, &attr); - break; - case x86_seg_es: - __vmread(GUEST_ES_SELECTOR, &sel); - __vmread(GUEST_ES_LIMIT, &limit); - __vmread(GUEST_ES_BASE, ®->base); - __vmread(GUEST_ES_AR_BYTES, &attr); - break; - case x86_seg_fs: - __vmread(GUEST_FS_SELECTOR, &sel); - __vmread(GUEST_FS_LIMIT, &limit); - __vmread(GUEST_FS_BASE, ®->base); - __vmread(GUEST_FS_AR_BYTES, &attr); - break; - case x86_seg_gs: - __vmread(GUEST_GS_SELECTOR, &sel); - __vmread(GUEST_GS_LIMIT, &limit); - __vmread(GUEST_GS_BASE, ®->base); - __vmread(GUEST_GS_AR_BYTES, &attr); - break; - case x86_seg_ss: - __vmread(GUEST_SS_SELECTOR, &sel); - __vmread(GUEST_SS_LIMIT, &limit); - __vmread(GUEST_SS_BASE, ®->base); - __vmread(GUEST_SS_AR_BYTES, &attr); + case x86_seg_es ... x86_seg_gs: + __vmread(GUEST_SEG_SELECTOR(seg), &sel); + __vmread(GUEST_SEG_LIMIT(seg), &limit); + __vmread(GUEST_SEG_BASE(seg), ®->base); + __vmread(GUEST_SEG_AR_BYTES(seg), &attr); break; case x86_seg_tr: __vmread(GUEST_TR_SELECTOR, &sel); @@ -1133,41 +1103,11 @@ static void vmx_set_segment_register(struct vcpu *v, enum x86_segment seg, switch ( seg ) { - case x86_seg_cs: - __vmwrite(GUEST_CS_SELECTOR, sel); - __vmwrite(GUEST_CS_LIMIT, limit); - __vmwrite(GUEST_CS_BASE, base); - __vmwrite(GUEST_CS_AR_BYTES, attr); - break; - case x86_seg_ds: - __vmwrite(GUEST_DS_SELECTOR, sel); - __vmwrite(GUEST_DS_LIMIT, limit); - __vmwrite(GUEST_DS_BASE, base); - __vmwrite(GUEST_DS_AR_BYTES, attr); - break; - case x86_seg_es: - __vmwrite(GUEST_ES_SELECTOR, sel); - __vmwrite(GUEST_ES_LIMIT, limit); - __vmwrite(GUEST_ES_BASE, base); - __vmwrite(GUEST_ES_AR_BYTES, attr); - break; - case x86_seg_fs: - __vmwrite(GUEST_FS_SELECTOR, sel); - __vmwrite(GUEST_FS_LIMIT, limit); - __vmwrite(GUEST_FS_BASE, base); - __vmwrite(GUEST_FS_AR_BYTES, attr); - break; - case x86_seg_gs: - __vmwrite(GUEST_GS_SELECTOR, sel); - __vmwrite(GUEST_GS_LIMIT, limit); - __vmwrite(GUEST_GS_BASE, base); - __vmwrite(GUEST_GS_AR_BYTES, attr); - break; - case x86_seg_ss: - __vmwrite(GUEST_SS_SELECTOR, sel); - __vmwrite(GUEST_SS_LIMIT, limit); - __vmwrite(GUEST_SS_BASE, base); - __vmwrite(GUEST_SS_AR_BYTES, attr); + case x86_seg_es ... x86_seg_gs: + __vmwrite(GUEST_SEG_SELECTOR(seg), sel); + __vmwrite(GUEST_SEG_LIMIT(seg), limit); + __vmwrite(GUEST_SEG_BASE(seg), base); + __vmwrite(GUEST_SEG_AR_BYTES(seg), attr); break; case x86_seg_tr: __vmwrite(GUEST_TR_SELECTOR, sel); diff --git a/xen/include/asm-x86/hvm/vmx/vmcs.h b/xen/include/asm-x86/hvm/vmx/vmcs.h index 997f4f55fa..894093d629 100644 --- a/xen/include/asm-x86/hvm/vmx/vmcs.h +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h @@ -420,6 +420,7 @@ enum vmcs_field { VIRTUAL_PROCESSOR_ID = 0x00000000, POSTED_INTR_NOTIFICATION_VECTOR = 0x00000002, EPTP_INDEX = 0x00000004, +#define GUEST_SEG_SELECTOR(sel) (GUEST_ES_SELECTOR + (sel) * 2) /* ES ... GS */ GUEST_ES_SELECTOR = 0x00000800, GUEST_CS_SELECTOR = 0x00000802, GUEST_SS_SELECTOR = 0x00000804, @@ -496,6 +497,7 @@ enum vmcs_field { IDT_VECTORING_ERROR_CODE = 0x0000440a, VM_EXIT_INSTRUCTION_LEN = 0x0000440c, VMX_INSTRUCTION_INFO = 0x0000440e, +#define GUEST_SEG_LIMIT(sel) (GUEST_ES_LIMIT + (sel) * 2) /* ES ... GS */ GUEST_ES_LIMIT = 0x00004800, GUEST_CS_LIMIT = 0x00004802, GUEST_SS_LIMIT = 0x00004804, @@ -506,6 +508,7 @@ enum vmcs_field { GUEST_TR_LIMIT = 0x0000480e, GUEST_GDTR_LIMIT = 0x00004810, GUEST_IDTR_LIMIT = 0x00004812, +#define GUEST_SEG_AR_BYTES(sel) (GUEST_ES_AR_BYTES + (sel) * 2) /* ES ... GS */ GUEST_ES_AR_BYTES = 0x00004814, GUEST_CS_AR_BYTES = 0x00004816, GUEST_SS_AR_BYTES = 0x00004818, @@ -531,6 +534,7 @@ enum vmcs_field { GUEST_CR0 = 0x00006800, GUEST_CR3 = 0x00006802, GUEST_CR4 = 0x00006804, +#define GUEST_SEG_BASE(sel) (GUEST_ES_BASE + (sel) * 2) /* ES ... GS */ GUEST_ES_BASE = 0x00006806, GUEST_CS_BASE = 0x00006808, GUEST_SS_BASE = 0x0000680a,