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: FPU management cleanups.

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] hvm: FPU management cleanups.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Sun, 03 Feb 2008 02:30:07 -0800
Delivery-date: Sun, 03 Feb 2008 02:30:28 -0800
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 Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1202034128 0
# Node ID e4edc310e949750065cb39588d87c335c7cd71a2
# Parent  aecbf98aa7099458fe6895bbd8f15d506e0901b3
hvm: FPU management cleanups.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 xen/arch/x86/hvm/hvm.c        |    3 -
 xen/arch/x86/hvm/svm/svm.c    |   88 ++++++++++++++++++++----------------
 xen/arch/x86/hvm/svm/vmcb.c   |    7 +-
 xen/arch/x86/hvm/vmx/vmcs.c   |    4 +
 xen/arch/x86/hvm/vmx/vmx.c    |  101 ++++++++++++++++++++----------------------
 xen/include/asm-x86/hvm/hvm.h |    6 --
 6 files changed, 105 insertions(+), 104 deletions(-)

diff -r aecbf98aa709 -r e4edc310e949 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Sun Feb 03 09:30:59 2008 +0000
+++ b/xen/arch/x86/hvm/hvm.c    Sun Feb 03 10:22:08 2008 +0000
@@ -123,9 +123,6 @@ void hvm_do_resume(struct vcpu *v)
 void hvm_do_resume(struct vcpu *v)
 {
     ioreq_t *p;
-
-    if ( !v->fpu_dirtied )
-        hvm_funcs.stts(v);
 
     pt_restore_timer(v);
 
diff -r aecbf98aa709 -r e4edc310e949 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Sun Feb 03 09:30:59 2008 +0000
+++ b/xen/arch/x86/hvm/svm/svm.c        Sun Feb 03 10:22:08 2008 +0000
@@ -426,6 +426,34 @@ static int svm_load_vmcb_ctxt(struct vcp
     return 0;
 }
 
+static void svm_fpu_enter(struct vcpu *v)
+{
+    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+
+    setup_fpu(v);
+    vmcb->exception_intercepts &= ~(1U << TRAP_no_device);
+}
+
+static void svm_fpu_leave(struct vcpu *v)
+{
+    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+
+    ASSERT(!v->fpu_dirtied);
+    ASSERT(read_cr0() & X86_CR0_TS);
+
+    /*
+     * If the guest does not have TS enabled then we must cause and handle an 
+     * exception on first use of the FPU. If the guest *does* have TS enabled 
+     * then this is not necessary: no FPU activity can occur until the guest 
+     * clears CR0.TS, and we will initialise the FPU when that happens.
+     */
+    if ( !(v->arch.hvm_vcpu.guest_cr[0] & X86_CR0_TS) )
+    {
+        v->arch.hvm_svm.vmcb->exception_intercepts |= 1U << TRAP_no_device;
+        vmcb->cr0 |= X86_CR0_TS;
+    }
+}
+
 static enum hvm_intblk svm_interrupt_blocked(
     struct vcpu *v, struct hvm_intack intack)
 {
@@ -470,19 +498,22 @@ static void svm_update_guest_cr(struct v
 
     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) )
+    case 0: {
+        unsigned long hw_cr0_mask = 0;
+
+        if ( !(v->arch.hvm_vcpu.guest_cr[0] & X86_CR0_TS) )
         {
-            setup_fpu(v);
-            vmcb->exception_intercepts &= ~(1U << TRAP_no_device);
-        }
-
-        vmcb->cr0 = v->arch.hvm_vcpu.guest_cr[0];
+            if ( v != current )
+                hw_cr0_mask |= X86_CR0_TS;
+            else if ( vmcb->cr0 & X86_CR0_TS )
+                svm_fpu_enter(v);
+        }
+
+        vmcb->cr0 = v->arch.hvm_vcpu.guest_cr[0] | hw_cr0_mask;
         if ( !paging_mode_hap(v->domain) )
             vmcb->cr0 |= X86_CR0_PG | X86_CR0_WP;
         break;
+    }
     case 2:
         vmcb->cr2 = v->arch.hvm_vcpu.guest_cr[2];
         break;
@@ -664,24 +695,6 @@ static void svm_set_segment_register(str
         svm_vmload(vmcb);
 }
 
-/* Make sure that xen intercepts any FP accesses from current */
-static void svm_stts(struct vcpu *v) 
-{
-    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
-
-    /*
-     * If the guest does not have TS enabled then we must cause and handle an 
-     * exception on first use of the FPU. If the guest *does* have TS enabled 
-     * then this is not necessary: no FPU activity can occur until the guest 
-     * clears CR0.TS, and we will initialise the FPU when that happens.
-     */
-    if ( !(v->arch.hvm_vcpu.guest_cr[0] & X86_CR0_TS) )
-    {
-        v->arch.hvm_svm.vmcb->exception_intercepts |= 1U << TRAP_no_device;
-        vmcb->cr0 |= X86_CR0_TS;
-    }
-}
-
 static void svm_set_tsc_offset(struct vcpu *v, u64 offset)
 {
     v->arch.hvm_svm.vmcb->tsc_offset = offset;
@@ -710,6 +723,8 @@ static void svm_ctxt_switch_from(struct 
 static void svm_ctxt_switch_from(struct vcpu *v)
 {
     int cpu = smp_processor_id();
+
+    svm_fpu_leave(v);
 
     svm_save_dr(v);
 
@@ -883,7 +898,6 @@ static struct hvm_function_table svm_fun
     .update_guest_cr      = svm_update_guest_cr,
     .update_guest_efer    = svm_update_guest_efer,
     .flush_guest_tlbs     = svm_flush_guest_tlbs,
-    .stts                 = svm_stts,
     .set_tsc_offset       = svm_set_tsc_offset,
     .inject_exception     = svm_inject_exception,
     .init_hypercall_page  = svm_init_hypercall_page,
@@ -964,12 +978,11 @@ static void svm_do_nested_pgfault(paddr_
 
 static void svm_do_no_device_fault(struct vmcb_struct *vmcb)
 {
-    struct vcpu *v = current;
-
-    setup_fpu(v);    
-    vmcb->exception_intercepts &= ~(1U << TRAP_no_device);
-
-    if ( !(v->arch.hvm_vcpu.guest_cr[0] & X86_CR0_TS) )
+    struct vcpu *curr = current;
+
+    svm_fpu_enter(curr);
+
+    if ( !(curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_TS) )
         vmcb->cr0 &= ~X86_CR0_TS;
 }
 
@@ -1647,11 +1660,8 @@ static void svm_cr_access(
         break;
 
     case INSTR_CLTS:
-        /* TS being cleared means that it's time to restore fpu state. */
-        setup_fpu(current);
-        vmcb->exception_intercepts &= ~(1U << TRAP_no_device);
-        vmcb->cr0 &= ~X86_CR0_TS; /* clear TS */
-        v->arch.hvm_vcpu.guest_cr[0] &= ~X86_CR0_TS; /* clear TS */
+        v->arch.hvm_vcpu.guest_cr[0] &= ~X86_CR0_TS;
+        svm_update_guest_cr(v, 0);
         HVMTRACE_0D(CLTS, current);
         break;
 
diff -r aecbf98aa709 -r e4edc310e949 xen/arch/x86/hvm/svm/vmcb.c
--- a/xen/arch/x86/hvm/svm/vmcb.c       Sun Feb 03 09:30:59 2008 +0000
+++ b/xen/arch/x86/hvm/svm/vmcb.c       Sun Feb 03 10:22:08 2008 +0000
@@ -212,20 +212,21 @@ static int construct_vmcb(struct vcpu *v
     vmcb->tr.base = 0;
     vmcb->tr.limit = 0xff;
 
-    v->arch.hvm_vcpu.guest_cr[0] = X86_CR0_PE | X86_CR0_TS;
+    v->arch.hvm_vcpu.guest_cr[0] = X86_CR0_PE | X86_CR0_ET;
     hvm_update_guest_cr(v, 0);
 
     v->arch.hvm_vcpu.guest_cr[4] = 0;
     hvm_update_guest_cr(v, 4);
 
     paging_update_paging_modes(v);
+
+    vmcb->exception_intercepts = HVM_TRAP_MASK | (1U << TRAP_no_device);
 
     if ( paging_mode_hap(v->domain) )
     {
         vmcb->np_enable = 1; /* enable nested paging */
         vmcb->g_pat = 0x0007040600070406ULL; /* guest PAT */
         vmcb->h_cr3 = pagetable_get_paddr(v->domain->arch.phys_table);
-        vmcb->exception_intercepts = HVM_TRAP_MASK;
 
         /*
          * No point in intercepting CR3 reads, because the hardware will return
@@ -241,7 +242,7 @@ static int construct_vmcb(struct vcpu *v
     }
     else
     {
-        vmcb->exception_intercepts = HVM_TRAP_MASK | (1U << TRAP_page_fault);
+        vmcb->exception_intercepts |= (1U << TRAP_page_fault);
     }
 
     return 0;
diff -r aecbf98aa709 -r e4edc310e949 xen/arch/x86/hvm/vmx/vmcs.c
--- a/xen/arch/x86/hvm/vmx/vmcs.c       Sun Feb 03 09:30:59 2008 +0000
+++ b/xen/arch/x86/hvm/vmx/vmcs.c       Sun Feb 03 10:22:08 2008 +0000
@@ -570,7 +570,9 @@ static int construct_vmcs(struct vcpu *v
     __vmwrite(VMCS_LINK_POINTER_HIGH, ~0UL);
 #endif
 
-    __vmwrite(EXCEPTION_BITMAP, HVM_TRAP_MASK | (1U << TRAP_page_fault));
+    __vmwrite(EXCEPTION_BITMAP, (HVM_TRAP_MASK |
+                                 (1U << TRAP_page_fault) |
+                                 (1U << TRAP_no_device)));
 
     v->arch.hvm_vcpu.guest_cr[0] = X86_CR0_PE | X86_CR0_ET;
     hvm_update_guest_cr(v, 0);
diff -r aecbf98aa709 -r e4edc310e949 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Sun Feb 03 09:30:59 2008 +0000
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Sun Feb 03 10:22:08 2008 +0000
@@ -740,15 +740,42 @@ static int vmx_load_vmcs_ctxt(struct vcp
     return 0;
 }
 
-static void vmx_ctxt_switch_from(struct vcpu *v)
-{
+static void vmx_fpu_enter(struct vcpu *v)
+{
+    setup_fpu(v);
+    __vm_clear_bit(EXCEPTION_BITMAP, TRAP_no_device);
+    v->arch.hvm_vmx.host_cr0 &= ~X86_CR0_TS;
+    __vmwrite(HOST_CR0, v->arch.hvm_vmx.host_cr0);
+}
+
+static void vmx_fpu_leave(struct vcpu *v)
+{
+    ASSERT(!v->fpu_dirtied);
     ASSERT(read_cr0() & X86_CR0_TS);
+
     if ( !(v->arch.hvm_vmx.host_cr0 & X86_CR0_TS) )
     {
         v->arch.hvm_vmx.host_cr0 |= X86_CR0_TS;
         __vmwrite(HOST_CR0, v->arch.hvm_vmx.host_cr0);
     }
 
+    /*
+     * If the guest does not have TS enabled then we must cause and handle an
+     * exception on first use of the FPU. If the guest *does* have TS enabled
+     * then this is not necessary: no FPU activity can occur until the guest
+     * clears CR0.TS, and we will initialise the FPU when that happens.
+     */
+    if ( !(v->arch.hvm_vcpu.guest_cr[0] & X86_CR0_TS) )
+    {
+        v->arch.hvm_vcpu.hw_cr[0] |= X86_CR0_TS;
+        __vmwrite(GUEST_CR0, v->arch.hvm_vcpu.hw_cr[0]);
+        __vm_set_bit(EXCEPTION_BITMAP, TRAP_no_device);
+    }
+}
+
+static void vmx_ctxt_switch_from(struct vcpu *v)
+{
+    vmx_fpu_leave(v);
     vmx_save_guest_msrs(v);
     vmx_restore_host_msrs();
     vmx_save_dr(v);
@@ -951,26 +978,6 @@ static void vmx_set_segment_register(str
     vmx_vmcs_exit(v);
 }
 
-/* Make sure that xen intercepts any FP accesses from current */
-static void vmx_stts(struct vcpu *v)
-{
-    /* VMX depends on operating on the current vcpu */
-    ASSERT(v == current);
-
-    /*
-     * If the guest does not have TS enabled then we must cause and handle an
-     * exception on first use of the FPU. If the guest *does* have TS enabled
-     * then this is not necessary: no FPU activity can occur until the guest
-     * clears CR0.TS, and we will initialise the FPU when that happens.
-     */
-    if ( !(v->arch.hvm_vcpu.guest_cr[0] & X86_CR0_TS) )
-    {
-        v->arch.hvm_vcpu.hw_cr[0] |= X86_CR0_TS;
-        __vmwrite(GUEST_CR0, v->arch.hvm_vcpu.hw_cr[0]);
-        __vm_set_bit(EXCEPTION_BITMAP, TRAP_no_device);
-    }
-}
-
 static void vmx_set_tsc_offset(struct vcpu *v, u64 offset)
 {
     vmx_vmcs_enter(v);
@@ -1042,21 +1049,24 @@ static void vmx_update_guest_cr(struct v
 
     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) )
+    case 0: {
+        unsigned long hw_cr0_mask =
+            X86_CR0_NE | X86_CR0_PG | X86_CR0_WP | X86_CR0_PE;
+
+        if ( !(v->arch.hvm_vcpu.guest_cr[0] & X86_CR0_TS) )
         {
-            setup_fpu(v);
-            __vm_clear_bit(EXCEPTION_BITMAP, TRAP_no_device);
+            if ( v != current )
+                hw_cr0_mask |= X86_CR0_TS;
+            else if ( v->arch.hvm_vcpu.hw_cr[0] & X86_CR0_TS )
+                vmx_fpu_enter(v);
         }
 
         v->arch.hvm_vcpu.hw_cr[0] =
-            v->arch.hvm_vcpu.guest_cr[0] |
-            X86_CR0_NE | X86_CR0_PG | X86_CR0_WP | X86_CR0_PE;
+            v->arch.hvm_vcpu.guest_cr[0] | hw_cr0_mask;
         __vmwrite(GUEST_CR0, v->arch.hvm_vcpu.hw_cr[0]);
         __vmwrite(CR0_READ_SHADOW, v->arch.hvm_vcpu.guest_cr[0]);
         break;
+    }
     case 2:
         /* CR2 is updated in exit stub. */
         break;
@@ -1153,7 +1163,6 @@ static struct hvm_function_table vmx_fun
     .update_guest_cr      = vmx_update_guest_cr,
     .update_guest_efer    = vmx_update_guest_efer,
     .flush_guest_tlbs     = vmx_flush_guest_tlbs,
-    .stts                 = vmx_stts,
     .set_tsc_offset       = vmx_set_tsc_offset,
     .inject_exception     = vmx_inject_exception,
     .init_hypercall_page  = vmx_init_hypercall_page,
@@ -1234,20 +1243,15 @@ static void __update_guest_eip(unsigned 
 
 void vmx_do_no_device_fault(void)
 {
-    struct vcpu *v = current;
-
-    setup_fpu(current);
-    __vm_clear_bit(EXCEPTION_BITMAP, TRAP_no_device);
-
-    ASSERT(v->arch.hvm_vmx.host_cr0 & X86_CR0_TS);
-    v->arch.hvm_vmx.host_cr0 &= ~X86_CR0_TS;
-    __vmwrite(HOST_CR0, v->arch.hvm_vmx.host_cr0);
+    struct vcpu *curr = current;
+
+    vmx_fpu_enter(curr);
 
     /* Disable TS in guest CR0 unless the guest wants the exception too. */
-    if ( !(v->arch.hvm_vcpu.guest_cr[0] & X86_CR0_TS) )
-    {
-        v->arch.hvm_vcpu.hw_cr[0] &= ~X86_CR0_TS;
-        __vmwrite(GUEST_CR0, v->arch.hvm_vcpu.hw_cr[0]);
+    if ( !(curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_TS) )
+    {
+        curr->arch.hvm_vcpu.hw_cr[0] &= ~X86_CR0_TS;
+        __vmwrite(GUEST_CR0, curr->arch.hvm_vcpu.hw_cr[0]);
     }
 }
 
@@ -2226,15 +2230,8 @@ static int vmx_cr_access(unsigned long e
         mov_from_cr(cr, gp, regs);
         break;
     case TYPE_CLTS:
-        /* We initialise the FPU now, to avoid needing another vmexit. */
-        setup_fpu(v);
-        __vm_clear_bit(EXCEPTION_BITMAP, TRAP_no_device);
-
-        v->arch.hvm_vcpu.hw_cr[0] &= ~X86_CR0_TS; /* clear TS */
-        __vmwrite(GUEST_CR0, v->arch.hvm_vcpu.hw_cr[0]);
-
-        v->arch.hvm_vcpu.guest_cr[0] &= ~X86_CR0_TS; /* clear TS */
-        __vmwrite(CR0_READ_SHADOW, v->arch.hvm_vcpu.guest_cr[0]);
+        v->arch.hvm_vcpu.guest_cr[0] &= ~X86_CR0_TS;
+        vmx_update_guest_cr(v, 0);
         HVMTRACE_0D(CLTS, current);
         break;
     case TYPE_LMSW:
diff -r aecbf98aa709 -r e4edc310e949 xen/include/asm-x86/hvm/hvm.h
--- a/xen/include/asm-x86/hvm/hvm.h     Sun Feb 03 09:30:59 2008 +0000
+++ b/xen/include/asm-x86/hvm/hvm.h     Sun Feb 03 10:22:08 2008 +0000
@@ -105,12 +105,6 @@ struct hvm_function_table {
      */
     void (*flush_guest_tlbs)(void);
 
-    /*
-     * Update specifics of the guest state:
-     * 1) TS bit in guest cr0 
-     * 2) TSC offset in guest
-     */
-    void (*stts)(struct vcpu *v);
     void (*set_tsc_offset)(struct vcpu *v, u64 offset);
 
     void (*inject_exception)(unsigned int trapnr, int errcode,

_______________________________________________
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: FPU management cleanups., Xen patchbot-unstable <=