Mailing List Archive

Clarify lazy FPU management in VMX domains.
# HG changeset patch
# User kaf24@firebug.cl.cam.ac.uk
# Node ID 70024ebbdf55585230fa7656ea79ecb2960779c5
# Parent 39b392a220025993cfb9dfa6ae5554ac3c88a340
Clarify lazy FPU management in VMX domains.

Signed-off-by: Keir Fraser <keir@xensource.com>

diff -r 39b392a22002 -r 70024ebbdf55 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c Tue Feb 14 18:43:45 2006
+++ b/xen/arch/x86/hvm/vmx/vmx.c Tue Feb 14 19:17:26 2006
@@ -617,12 +617,17 @@

clts();
setup_fpu(current);
+
+ /* Disable TS in guest CR0 unless the guest wants the exception too. */
__vmread_vcpu(v, CR0_READ_SHADOW, &cr0);
- if (!(cr0 & X86_CR0_TS)) {
+ if ( !(cr0 & X86_CR0_TS) )
+ {
__vmread_vcpu(v, GUEST_CR0, &cr0);
cr0 &= ~X86_CR0_TS;
__vmwrite(GUEST_CR0, cr0);
}
+
+ /* Xen itself doesn't need another exception. */
__vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_NM);
}

@@ -1152,13 +1157,16 @@
*/
__vmread_vcpu(v, CR0_READ_SHADOW, &old_cr0);
paging_enabled = (old_cr0 & X86_CR0_PE) && (old_cr0 & X86_CR0_PG);
- /* If OS don't use clts to clear TS bit...*/
- if((old_cr0 & X86_CR0_TS) && !(value & X86_CR0_TS))
+
+ /*
+ * Disable TS? Then we do so at the same time, and initialise FPU.
+ * This avoids needing another vmexit.
+ */
+ if ( (old_cr0 & ~value & X86_CR0_TS) != 0 )
{
- clts();
- setup_fpu(v);
- }
-
+ clts();
+ setup_fpu(v);
+ }

__vmwrite(GUEST_CR0, value | X86_CR0_PE | X86_CR0_PG | X86_CR0_NE);
__vmwrite(CR0_READ_SHADOW, value);
@@ -1510,6 +1518,8 @@
break;
case TYPE_CLTS:
TRACE_VMEXIT(1,TYPE_CLTS);
+
+ /* We initialise the FPU now, to avoid needing another vmexit. */
clts();
setup_fpu(current);

diff -r 39b392a22002 -r 70024ebbdf55 xen/include/asm-x86/hvm/vmx/vmx.h
--- a/xen/include/asm-x86/hvm/vmx/vmx.h Tue Feb 14 18:43:45 2006
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h Tue Feb 14 19:17:26 2006
@@ -382,14 +382,22 @@
unsigned long cr0;
struct vcpu *v = current;

- __vmread_vcpu(v, GUEST_CR0, &cr0);
- if (!(cr0 & X86_CR0_TS)) {
+ /* FPU state already dirty? Then no need to setup_fpu() lazily. */
+ if ( test_bit(_VCPUF_fpu_dirtied, &v->vcpu_flags) )
+ return;
+
+ /*
+ * 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.
+ */
+ __vmread_vcpu(v, CR0_READ_SHADOW, &cr0);
+ if ( !(cr0 & X86_CR0_TS) )
+ {
__vmwrite(GUEST_CR0, cr0 | X86_CR0_TS);
- }
-
- __vmread_vcpu(v, CR0_READ_SHADOW, &cr0);
- if (!(cr0 & X86_CR0_TS))
- __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_NM);
+ __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_NM);
+ }
}

/* Works only for vcpu == current */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog