[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] vmx: Make use of VMX_INSTRUCTION_INFO field to obtain the segment



# 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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.