WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

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

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] hvm: Clean ups and fix MSR access functions.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Tue, 10 Jul 2007 04:30:17 -0700
Delivery-date: Tue, 10 Jul 2007 04:28:30 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] hvm: Clean ups and fix MSR access functions., Xen patchbot-unstable <=