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

[Xen-changelog] [xen-unstable] hvm: Clean ups and fix MSR access functions.



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1184000663 -3600
# Node ID 1d1ccf6b861405805f46b5f17b973a05e138c871
# Parent  aa640601575fb4b509befd9f032f0f3d577a46fc
hvm: Clean ups and fix MSR access functions.
Signed-off-by: Xin Li <xin.b.li@xxxxxxxxx>
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/hvm/svm/svm.c |   37 +++++-----
 xen/arch/x86/hvm/vmx/vmx.c |  158 ++++++++++++++++++++++++++-------------------
 2 files changed, 113 insertions(+), 82 deletions(-)

diff -r aa640601575f -r 1d1ccf6b8614 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Mon Jul 09 14:51:44 2007 +0100
+++ b/xen/arch/x86/hvm/svm/svm.c        Mon Jul 09 18:04:23 2007 +0100
@@ -53,6 +53,8 @@
 #define set_segment_register(name, value)  \
     asm volatile ( "movw %%ax ,%%" STR(name) "" : : "a" (value) )
 
+enum handler_return { HNDL_done, HNDL_unhandled, HNDL_exception_raised };
+
 int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip,
                          int inst_len);
 asmlinkage void do_IRQ(struct cpu_user_regs *);
@@ -173,7 +175,7 @@ static void svm_store_cpu_guest_regs(
     }
 }
 
-static int long_mode_do_msr_write(struct cpu_user_regs *regs)
+static enum handler_return long_mode_do_msr_write(struct cpu_user_regs *regs)
 {
     u64 msr_content = (u32)regs->eax | ((u64)regs->edx << 32);
     u32 ecx = regs->ecx;
@@ -237,14 +239,14 @@ static int long_mode_do_msr_write(struct
         break;
 
     default:
-        return 0;
-    }
-
-    return 1;
+        return HNDL_unhandled;
+    }
+
+    return HNDL_done;
 
  gp_fault:
     svm_inject_exception(v, TRAP_gp_fault, 1, 0);
-    return 0;
+    return HNDL_exception_raised;
 }
 
 
@@ -1716,8 +1718,8 @@ static int svm_set_cr0(unsigned long val
             if ( old_base_mfn )
                 put_page(mfn_to_page(old_base_mfn));
 
-            HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx", 
-                        (unsigned long) (mfn << PAGE_SHIFT));
+            HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx",
+                        v->arch.hvm_vmx.cpu_cr3, mfn);
         }
     }
     else if ( !(value & X86_CR0_PG) && (old_value & X86_CR0_PG) )
@@ -1744,8 +1746,7 @@ static int svm_set_cr0(unsigned long val
     if ( (value ^ old_value) & X86_CR0_PG )
     {
         paging_update_paging_modes(v);
-        /* signal paging update to ASID handler */
-        svm_asid_g_update_paging (v);
+        svm_asid_g_update_paging(v);
     }
 
     return 1;
@@ -1894,8 +1895,8 @@ static int mov_to_cr(int gpreg, int cr, 
         {
             if ( svm_pgbit_test(v) )
             {
+#if CONFIG_PAGING_LEVELS >= 3
                 /* The guest is a 32-bit PAE guest. */
-#if CONFIG_PAGING_LEVELS >= 3
                 unsigned long mfn, old_base_mfn;
                 mfn = get_mfn_from_gpfn(v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT);
                 if ( !mfn_valid(mfn) || 
@@ -1905,7 +1906,6 @@ static int mov_to_cr(int gpreg, int cr, 
                 /*
                  * Now arch.guest_table points to machine physical.
                  */
-
                 old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
                 v->arch.guest_table = pagetable_from_pfn(mfn);
                 if ( old_base_mfn )
@@ -1913,9 +1913,6 @@ static int mov_to_cr(int gpreg, int cr, 
                 paging_update_paging_modes(v);
                 /* signal paging update to ASID handler */
                 svm_asid_g_update_paging (v);
-
-                HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx",
-                            (unsigned long) (mfn << PAGE_SHIFT));
 
                 HVM_DBG_LOG(DBG_LEVEL_VMMU, 
                             "Update CR3 value = %lx, mfn = %lx",
@@ -2201,8 +2198,16 @@ static void svm_do_msr_access(
             break;
 
         default:
-            if ( !long_mode_do_msr_write(regs) )
+            switch ( long_mode_do_msr_write(regs) )
+            {
+            case HNDL_unhandled:
                 wrmsr_hypervisor_regs(ecx, regs->eax, regs->edx);
+                break;
+            case HNDL_exception_raised:
+                return;
+            case HNDL_done:
+                break;
+            }
             break;
         }
 
diff -r aa640601575f -r 1d1ccf6b8614 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Mon Jul 09 14:51:44 2007 +0100
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Mon Jul 09 18:04:23 2007 +0100
@@ -51,6 +51,8 @@
 #include <public/hvm/save.h>
 #include <asm/hvm/trace.h>
 
+enum handler_return { HNDL_done, HNDL_unhandled, HNDL_exception_raised };
+
 char *vmx_msr_bitmap;
 
 static void vmx_ctxt_switch_from(struct vcpu *v);
@@ -178,14 +180,15 @@ static void vmx_save_host_msrs(void)
         set_bit(VMX_INDEX_MSR_ ## address, &host_msr_state->flags);     \
         break
 
-static int long_mode_do_msr_read(struct cpu_user_regs *regs)
+static enum handler_return long_mode_do_msr_read(struct cpu_user_regs *regs)
 {
     u64 msr_content = 0;
     u32 ecx = regs->ecx;
     struct vcpu *v = current;
     struct vmx_msr_state *guest_msr_state = &v->arch.hvm_vmx.msr_state;
 
-    switch ( ecx ) {
+    switch ( ecx )
+    {
     case MSR_EFER:
         msr_content = v->arch.hvm_vmx.efer;
         break;
@@ -204,7 +207,7 @@ static int long_mode_do_msr_read(struct 
         if ( !(vmx_long_mode_enabled(v)) )
         {
             vmx_inject_hw_exception(v, TRAP_gp_fault, 0);
-            return 0;
+            return HNDL_exception_raised;
         }
         break;
 
@@ -225,7 +228,7 @@ static int long_mode_do_msr_read(struct 
         break;
 
     default:
-        return 0;
+        return HNDL_unhandled;
     }
 
     HVM_DBG_LOG(DBG_LEVEL_0, "msr 0x%x content 0x%"PRIx64, ecx, msr_content);
@@ -233,10 +236,10 @@ static int long_mode_do_msr_read(struct 
     regs->eax = (u32)(msr_content >>  0);
     regs->edx = (u32)(msr_content >> 32);
 
-    return 1;
-}
-
-static int long_mode_do_msr_write(struct cpu_user_regs *regs)
+    return HNDL_done;
+}
+
+static enum handler_return long_mode_do_msr_write(struct cpu_user_regs *regs)
 {
     u64 msr_content = (u32)regs->eax | ((u64)regs->edx << 32);
     u32 ecx = regs->ecx;
@@ -326,16 +329,16 @@ static int long_mode_do_msr_write(struct
         WRITE_MSR(SYSCALL_MASK);
 
     default:
-        return 0;
-    }
-
-    return 1;
+        return HNDL_unhandled;
+    }
+
+    return HNDL_done;
 
  uncanonical_address:
     HVM_DBG_LOG(DBG_LEVEL_0, "Not cano address of msr write %x", ecx);
  gp_fault:
     vmx_inject_hw_exception(v, TRAP_gp_fault, 0);
-    return 0;
+    return HNDL_exception_raised;
 }
 
 /*
@@ -434,7 +437,7 @@ static void vmx_restore_guest_msrs(struc
     }
 }
 
-static int long_mode_do_msr_read(struct cpu_user_regs *regs)
+static enum handler_return long_mode_do_msr_read(struct cpu_user_regs *regs)
 {
     u64 msr_content = 0;
     struct vcpu *v = current;
@@ -445,16 +448,16 @@ static int long_mode_do_msr_read(struct 
         break;
 
     default:
-        return 0;
+        return HNDL_unhandled;
     }
 
     regs->eax = msr_content >>  0;
     regs->edx = msr_content >> 32;
 
-    return 1;
-}
-
-static int long_mode_do_msr_write(struct cpu_user_regs *regs)
+    return HNDL_done;
+}
+
+static enum handler_return long_mode_do_msr_write(struct cpu_user_regs *regs)
 {
     u64 msr_content = regs->eax | ((u64)regs->edx << 32);
     struct vcpu *v = current;
@@ -469,7 +472,7 @@ static int long_mode_do_msr_write(struct
             gdprintk(XENLOG_WARNING, "Trying to set reserved bit in "
                      "EFER: %"PRIx64"\n", msr_content);
             vmx_inject_hw_exception(v, TRAP_gp_fault, 0);
-            return 0;
+            return HNDL_exception_raised;
         }
 
         if ( (msr_content ^ v->arch.hvm_vmx.efer) & EFER_NX )
@@ -479,10 +482,10 @@ static int long_mode_do_msr_write(struct
         break;
 
     default:
-        return 0;
-    }
-
-    return 1;
+        return HNDL_unhandled;
+    }
+
+    return HNDL_done;
 }
 
 #endif /* __i386__ */
@@ -683,9 +686,9 @@ int vmx_vmcs_restore(struct vcpu *v, str
     if ( old_base_mfn )
         put_page(mfn_to_page(old_base_mfn));
 
+ skip_cr3:
     v->arch.hvm_vmx.cpu_cr3 = c->cr3;
 
- skip_cr3:
     if ( vmx_long_mode_enabled(v) )
         vmx_enable_long_mode(v);
 
@@ -1663,10 +1666,10 @@ static int vmx_str_pio_check_descriptor(
 }
 
 
-static void vmx_str_pio_check_limit(u32 limit, unsigned int size,
-                                    u32 ar_bytes, unsigned long addr,
-                                    unsigned long base, int df,
-                                    unsigned long *count)
+static int vmx_str_pio_check_limit(u32 limit, unsigned int size,
+                                   u32 ar_bytes, unsigned long addr,
+                                   unsigned long base, int df,
+                                   unsigned long *count)
 {
     unsigned long ea = addr - base;
 
@@ -1675,10 +1678,7 @@ static void vmx_str_pio_check_limit(u32 
     if ( (u32)(ea + size - 1) < (u32)ea ||
          (ar_bytes & 0xc) != 0x4 ? ea + size - 1 > limit
                                  : ea <= limit )
-    {
-        vmx_inject_hw_exception(current, TRAP_gp_fault, 0);
-        return;
-    }
+        return 0;
 
     /* Check the limit for repeated instructions, as above we checked
        only the first instance. Truncate the count if a limit violation
@@ -1719,22 +1719,23 @@ static void vmx_str_pio_check_limit(u32 
         }
         ASSERT(*count);
     }
+
+    return 1;
 }
 
 #ifdef __x86_64__
-static void vmx_str_pio_lm_check_limit(struct cpu_user_regs *regs,
-                                       unsigned int size,
-                                       unsigned long addr,
-                                       unsigned long *count)
+static int vmx_str_pio_lm_check_limit(struct cpu_user_regs *regs,
+                                      unsigned int size,
+                                      unsigned long addr,
+                                      unsigned long *count)
 {
     if ( !is_canonical_address(addr) ||
          !is_canonical_address(addr + size - 1) )
-    {
-        vmx_inject_hw_exception(current, TRAP_gp_fault, 0);
-        return;
-    }
+        return 0;
+
     if ( *count > (1UL << 48) / size )
         *count = (1UL << 48) / size;
+
     if ( !(regs->eflags & EF_DF) )
     {
         if ( addr + *count * size - 1 < addr ||
@@ -1747,7 +1748,10 @@ static void vmx_str_pio_lm_check_limit(s
              !is_canonical_address(addr + (*count - 1) * size) )
             *count = (addr & ~((1UL << 48) - 1)) / size + 1;
     }
+
     ASSERT(*count);
+
+    return 1;
 }
 #endif
 
@@ -1875,18 +1879,21 @@ static void vmx_do_str_pio(unsigned long
     if ( !long_mode )
     {
         /* Segment must be readable for outs and writeable for ins. */
-        if ( dir == IOREQ_WRITE ? (ar_bytes & 0xa) == 0x8
-                                : (ar_bytes & 0xa) != 0x2 ) {
+        if ( ((dir == IOREQ_WRITE)
+              ? ((ar_bytes & 0xa) == 0x8)
+              : ((ar_bytes & 0xa) != 0x2)) ||
+             !vmx_str_pio_check_limit(limit, size, ar_bytes,
+                                      addr, base, df, &count) )
+        {
             vmx_inject_hw_exception(current, TRAP_gp_fault, 0);
             return;
         }
-
-        vmx_str_pio_check_limit(limit, size, ar_bytes, addr, base, df, &count);
     }
 #ifdef __x86_64__
-    else
-    {
-        vmx_str_pio_lm_check_limit(regs, size, addr, &count);
+    else if ( !vmx_str_pio_lm_check_limit(regs, size, addr, &count) )
+    {
+        vmx_inject_hw_exception(current, TRAP_gp_fault, 0);
+        return;
     }
 #endif
 
@@ -2133,12 +2140,20 @@ static int vmx_assist(struct vcpu *v, in
     struct hvm_hw_vpic *vpic = v->domain->arch.hvm_domain.vpic;
     u32 magic, cp;
 
-    /* make sure vmxassist exists (this is not an error) */
     if ( hvm_copy_from_guest_phys(&magic, VMXASSIST_MAGIC_OFFSET,
                                   sizeof(magic)) )
+    {
+        gdprintk(XENLOG_ERR, "No vmxassist: can't execute real mode code\n");
+        domain_crash(v->domain);
         return 0;
+    }
+
     if ( magic != VMXASSIST_MAGIC )
+    {
+        gdprintk(XENLOG_ERR, "vmxassist magic number not match\n");
+        domain_crash(v->domain);
         return 0;
+    }
 
     switch ( mode ) {
         /*
@@ -2280,28 +2295,26 @@ static int vmx_set_cr0(unsigned long val
         if ( old_base_mfn )
             put_page(mfn_to_page(old_base_mfn));
 
-        paging_update_paging_modes(v);
-
-        HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx",
-                    (unsigned long) (mfn << PAGE_SHIFT));
-
         HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx",
                     v->arch.hvm_vmx.cpu_cr3, mfn);
+
+        paging_update_paging_modes(v);
     }
 
     /* Trying to disable paging. */
     if ( ((value & (X86_CR0_PE | X86_CR0_PG)) != (X86_CR0_PE | X86_CR0_PG)) &&
          paging_enabled )
     {
+        /* When CR0.PG is cleared, LMA is cleared immediately. */
+        if ( vmx_long_mode_enabled(v) )
+            vmx_disable_long_mode(v);
+
         if ( v->arch.hvm_vmx.cpu_cr3 )
         {
             put_page(mfn_to_page(get_mfn_from_gpfn(
                       v->arch.hvm_vmx.cpu_cr3 >> PAGE_SHIFT)));
             v->arch.guest_table = pagetable_null();
         }
-
-        if ( vmx_long_mode_enabled(v) )
-            vmx_disable_long_mode(v);
     }
 
     /*
@@ -2461,8 +2474,8 @@ static int mov_to_cr(int gp, int cr, str
         {
             if ( vmx_pgbit_test(v) )
             {
+#if CONFIG_PAGING_LEVELS >= 3
                 /* The guest is a 32-bit PAE guest. */
-#if CONFIG_PAGING_LEVELS >= 3
                 unsigned long mfn, old_base_mfn;
                 mfn = get_mfn_from_gpfn(v->arch.hvm_vmx.cpu_cr3 >> PAGE_SHIFT);
                 if ( !mfn_valid(mfn) ||
@@ -2476,9 +2489,6 @@ static int mov_to_cr(int gp, int cr, str
                 v->arch.guest_table = pagetable_from_pfn(mfn);
                 if ( old_base_mfn )
                     put_page(mfn_to_page(old_base_mfn));
-
-                HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx",
-                            (unsigned long) (mfn << PAGE_SHIFT));
 
                 HVM_DBG_LOG(DBG_LEVEL_VMMU,
                             "Update CR3 value = %lx, mfn = %lx",
@@ -2645,8 +2655,15 @@ static int vmx_do_msr_read(struct cpu_us
     case MSR_IA32_VMX_BASIC...MSR_IA32_VMX_PROCBASED_CTLS2:
         goto gp_fault;
     default:
-        if ( long_mode_do_msr_read(regs) )
-            goto done;
+        switch ( long_mode_do_msr_read(regs) )
+        {
+            case HNDL_unhandled:
+                break;
+            case HNDL_exception_raised:
+                return 0;
+            case HNDL_done:
+                goto done;
+        }
 
         if ( rdmsr_hypervisor_regs(ecx, &eax, &edx) ||
              rdmsr_safe(ecx, eax, edx) == 0 )
@@ -2771,8 +2788,16 @@ static int vmx_do_msr_write(struct cpu_u
     case MSR_IA32_VMX_BASIC...MSR_IA32_VMX_PROCBASED_CTLS2:
         goto gp_fault;
     default:
-        if ( !long_mode_do_msr_write(regs) )
-            wrmsr_hypervisor_regs(ecx, regs->eax, regs->edx);
+        switch ( long_mode_do_msr_write(regs) )
+        {
+            case HNDL_unhandled:
+                wrmsr_hypervisor_regs(ecx, regs->eax, regs->edx);
+                break;
+            case HNDL_exception_raised:
+                return 0;
+            case HNDL_done:
+                break;
+        }
         break;
     }
 
@@ -2812,7 +2837,8 @@ static void vmx_do_extint(struct cpu_use
     vector &= INTR_INFO_VECTOR_MASK;
     HVMTRACE_1D(INTR, current, vector);
 
-    switch(vector) {
+    switch ( vector )
+    {
     case LOCAL_TIMER_VECTOR:
         smp_apic_timer_interrupt(regs);
         break;

_______________________________________________
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®.