# HG changeset patch
# User Keir Fraser <keir@xxxxxxxxxxxxx>
# Date 1182974037 -3600
# Node ID 6e934c7990514adfe6f882f37a71a26fbe3cd2d4
# Parent 87d34c8c2fe1a444b24c4f6a7a3cde3d1baebb93
vmx: Make use of VMX_INSTRUCTION_INFO field to obtain the segment
register of OUTS
Signed-off-by: Weidong Han <weidong.han@xxxxxxxxx>
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
xen/arch/x86/hvm/vmx/vmcs.c | 3 ++
xen/arch/x86/hvm/vmx/vmx.c | 49 ++++++++++++++++++++++++++-----------
xen/include/asm-x86/hvm/vmx/vmcs.h | 2 +
3 files changed, 40 insertions(+), 14 deletions(-)
diff -r 87d34c8c2fe1 -r 6e934c799051 xen/arch/x86/hvm/vmx/vmcs.c
--- a/xen/arch/x86/hvm/vmx/vmcs.c Wed Jun 27 20:17:54 2007 +0100
+++ b/xen/arch/x86/hvm/vmx/vmcs.c Wed Jun 27 20:53:57 2007 +0100
@@ -43,6 +43,7 @@ u32 vmx_secondary_exec_control __read_mo
u32 vmx_secondary_exec_control __read_mostly;
u32 vmx_vmexit_control __read_mostly;
u32 vmx_vmentry_control __read_mostly;
+bool_t cpu_has_vmx_ins_outs_instr_info __read_mostly;
static u32 vmcs_revision_id __read_mostly;
@@ -133,6 +134,7 @@ void vmx_init_vmcs_config(void)
vmx_secondary_exec_control = _vmx_secondary_exec_control;
vmx_vmexit_control = _vmx_vmexit_control;
vmx_vmentry_control = _vmx_vmentry_control;
+ cpu_has_vmx_ins_outs_instr_info = !!(vmx_msr_high & (1U<<22));
}
else
{
@@ -142,6 +144,7 @@ void vmx_init_vmcs_config(void)
BUG_ON(vmx_secondary_exec_control != _vmx_secondary_exec_control);
BUG_ON(vmx_vmexit_control != _vmx_vmexit_control);
BUG_ON(vmx_vmentry_control != _vmx_vmentry_control);
+ BUG_ON(cpu_has_vmx_ins_outs_instr_info != !!(vmx_msr_high & (1U<<22)));
}
/* IA-32 SDM Vol 3B: VMCS size is never greater than 4kB. */
diff -r 87d34c8c2fe1 -r 6e934c799051 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c Wed Jun 27 20:17:54 2007 +0100
+++ b/xen/arch/x86/hvm/vmx/vmx.c Wed Jun 27 20:53:57 2007 +0100
@@ -1466,16 +1466,34 @@ static void vmx_do_invlpg(unsigned long
paging_invlpg(v, va);
}
-/*
- * get segment for string pio according to guest instruction
- */
-static void vmx_str_pio_get_segment(int long_mode, unsigned long eip,
- int inst_len, enum x86_segment *seg)
+/* Get segment for OUTS according to guest instruction. */
+static enum x86_segment vmx_outs_get_segment(
+ int long_mode, unsigned long eip, int inst_len)
{
unsigned char inst[MAX_INST_LEN];
+ enum x86_segment seg = x86_seg_ds;
int i;
extern int inst_copy_from_guest(unsigned char *, unsigned long, int);
+ if ( likely(cpu_has_vmx_ins_outs_instr_info) )
+ {
+ unsigned int instr_info = __vmread(VMX_INSTRUCTION_INFO);
+
+ /* Get segment register according to bits 17:15. */
+ switch ( (instr_info >> 15) & 7 )
+ {
+ case 0: seg = x86_seg_es; break;
+ case 1: seg = x86_seg_cs; break;
+ case 2: seg = x86_seg_ss; break;
+ case 3: seg = x86_seg_ds; break;
+ case 4: seg = x86_seg_fs; break;
+ case 5: seg = x86_seg_gs; break;
+ default: BUG();
+ }
+
+ goto out;
+ }
+
if ( !long_mode )
eip += __vmread(GUEST_CS_BASE);
@@ -1484,7 +1502,7 @@ static void vmx_str_pio_get_segment(int
{
gdprintk(XENLOG_ERR, "Get guest instruction failed\n");
domain_crash(current->domain);
- return;
+ goto out;
}
for ( i = 0; i < inst_len; i++ )
@@ -1501,25 +1519,28 @@ static void vmx_str_pio_get_segment(int
#endif
continue;
case 0x2e: /* CS */
- *seg = x86_seg_cs;
+ seg = x86_seg_cs;
continue;
case 0x36: /* SS */
- *seg = x86_seg_ss;
+ seg = x86_seg_ss;
continue;
case 0x26: /* ES */
- *seg = x86_seg_es;
+ seg = x86_seg_es;
continue;
case 0x64: /* FS */
- *seg = x86_seg_fs;
+ seg = x86_seg_fs;
continue;
case 0x65: /* GS */
- *seg = x86_seg_gs;
+ seg = x86_seg_gs;
continue;
case 0x3e: /* DS */
- *seg = x86_seg_ds;
+ seg = x86_seg_ds;
continue;
}
}
+
+ out:
+ return seg;
}
static int vmx_str_pio_check_descriptor(int long_mode, unsigned long eip,
@@ -1532,7 +1553,7 @@ static int vmx_str_pio_check_descriptor(
*base = 0;
*limit = 0;
if ( seg != x86_seg_es )
- vmx_str_pio_get_segment(long_mode, eip, inst_len, &seg);
+ seg = vmx_outs_get_segment(long_mode, eip, inst_len);
switch ( seg )
{
@@ -1578,7 +1599,7 @@ static int vmx_str_pio_check_descriptor(
}
*ar_bytes = __vmread(ar_field);
- return !(*ar_bytes & 0x10000);
+ return !(*ar_bytes & X86_SEG_AR_SEG_UNUSABLE);
}
diff -r 87d34c8c2fe1 -r 6e934c799051 xen/include/asm-x86/hvm/vmx/vmcs.h
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h Wed Jun 27 20:17:54 2007 +0100
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h Wed Jun 27 20:53:57 2007 +0100
@@ -130,6 +130,8 @@ extern u32 vmx_vmentry_control;
#define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001
extern u32 vmx_secondary_exec_control;
+
+extern bool_t cpu_has_vmx_ins_outs_instr_info;
#define cpu_has_vmx_virtualize_apic_accesses \
(vmx_secondary_exec_control & SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|