]> xenbits.xensource.com Git - xen.git/commitdiff
hvm: Fix CR0.TS handling.
authorKeir Fraser <keir@xensource.com>
Thu, 11 Oct 2007 12:53:50 +0000 (13:53 +0100)
committerKeir Fraser <keir@xensource.com>
Thu, 11 Oct 2007 12:53:50 +0000 (13:53 +0100)
Signed-off-by: Keir Fraser <keir@xensource.com>
xen/arch/x86/hvm/svm/svm.c
xen/arch/x86/hvm/vmx/vmx.c

index c63d8168dfba275ee1cfd563383a0d6f6aaec8b5..204b746f6deb0022c6190d771d7074d9f6ccedac 100644 (file)
@@ -474,6 +474,14 @@ static void svm_update_guest_cr(struct vcpu *v, unsigned int cr)
     switch ( cr )
     {
     case 0:
+        /* TS cleared? Then initialise FPU now. */
+        if ( (v == current) && !(v->arch.hvm_vcpu.guest_cr[0] & X86_CR0_TS) &&
+             (vmcb->cr0 & X86_CR0_TS) )
+        {
+            setup_fpu(v);
+            vmcb->exception_intercepts &= ~(1U << TRAP_no_device);
+        }
+
         vmcb->cr0 = v->arch.hvm_vcpu.guest_cr[0];
         if ( !paging_mode_hap(v->domain) )
             vmcb->cr0 |= X86_CR0_PG | X86_CR0_WP;
@@ -1538,25 +1546,6 @@ static void svm_io_instruction(struct vcpu *v)
     }
 }
 
-static int svm_set_cr0(unsigned long value)
-{
-    struct vcpu *v = current;
-    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
-    int rc = hvm_set_cr0(value);
-
-    if ( rc == 0 )
-        return 0;
-
-    /* TS cleared? Then initialise FPU now. */
-    if ( !(value & X86_CR0_TS) )
-    {
-        setup_fpu(v);
-        vmcb->exception_intercepts &= ~(1U << TRAP_no_device);
-    }
-
-    return 1;
-}
-
 static void mov_from_cr(int cr, int gp, struct cpu_user_regs *regs)
 {
     unsigned long value = 0;
@@ -1603,7 +1592,7 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
     switch ( cr )
     {
     case 0: 
-        return svm_set_cr0(value);
+        return hvm_set_cr0(value);
     case 3:
         return hvm_set_cr3(value);
     case 4:
@@ -1688,7 +1677,7 @@ static void svm_cr_access(
         gpreg = decode_src_reg(prefix, buffer[index+2]);
         value = get_reg(gpreg, regs, vmcb) & 0xF;
         value = (v->arch.hvm_vcpu.guest_cr[0] & ~0xF) | value;
-        result = svm_set_cr0(value);
+        result = hvm_set_cr0(value);
         HVMTRACE_1D(LMSW, current, value);
         break;
 
index 62370ecfb9dcf91e9e8aea611ab48dc3da6588b1..d9a0efeaa6a9ed51322c61d3c4ac15aae3a95e5c 100644 (file)
@@ -1022,6 +1022,14 @@ static void vmx_update_guest_cr(struct vcpu *v, unsigned int cr)
     switch ( cr )
     {
     case 0:
+        /* TS cleared? Then initialise FPU now. */
+        if ( (v == current) && !(v->arch.hvm_vcpu.guest_cr[0] & X86_CR0_TS) &&
+             (v->arch.hvm_vcpu.hw_cr[0] & X86_CR0_TS) )
+        {
+            setup_fpu(v);
+            __vm_clear_bit(EXCEPTION_BITMAP, TRAP_no_device);
+        }
+
         v->arch.hvm_vcpu.hw_cr[0] =
             v->arch.hvm_vcpu.guest_cr[0] |
             X86_CR0_PE | X86_CR0_NE | X86_CR0_PG | X86_CR0_WP;
@@ -2046,13 +2054,6 @@ static int vmx_set_cr0(unsigned long value)
     if ( rc == 0 )
         return 0;
 
-    /* TS cleared? Then initialise FPU now. */
-    if ( !(value & X86_CR0_TS) )
-    {
-        setup_fpu(v);
-        __vm_clear_bit(EXCEPTION_BITMAP, TRAP_no_device);
-    }
-
     /*
      * VMX does not implement real-mode virtualization. We emulate
      * real-mode by performing a world switch to VMXAssist whenever