# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 7d89f672aa49b0240bff86ad56992c888e4eca54
# Parent ee6f025fb264214047b152e5583d4d5da03a1c22
More fixes to HVM FPU management. Mostly for SVM, but also
fix VMX mov_to_cr0: must setup_fpu() if the new cr0 value
has TS clear, regardless of previous cr0.TS value.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
diff -r ee6f025fb264 -r 7d89f672aa49 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c Tue Feb 14 22:30:59 2006
+++ b/xen/arch/x86/hvm/svm/svm.c Tue Feb 14 23:15:11 2006
@@ -701,12 +701,21 @@
{
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
- ASSERT(vmcb);
-
- vmcb->cr0 |= X86_CR0_TS;
-
- if (!(v->arch.hvm_svm.cpu_shadow_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.
+ */
+ if ( !(v->arch.hvm_svm.cpu_shadow_cr0 & X86_CR0_TS) )
+ {
v->arch.hvm_svm.vmcb->exception_intercepts |= EXCEPTION_BITMAP_NM;
+ vmcb->cr0 |= X86_CR0_TS;
+ }
}
static void arch_svm_do_launch(struct vcpu *v)
@@ -884,14 +893,11 @@
{
struct vcpu *v = current;
- clts();
-
setup_fpu(v);
-
- if (!(v->arch.hvm_svm.cpu_shadow_cr0 & X86_CR0_TS))
+ vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM;
+
+ if ( !(v->arch.hvm_svm.cpu_shadow_cr0 & X86_CR0_TS) )
vmcb->cr0 &= ~X86_CR0_TS;
-
- vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM;
}
@@ -1350,10 +1356,11 @@
vmcb->cr0 = value | X86_CR0_PG;
v->arch.hvm_svm.cpu_shadow_cr0 = value;
- /* Check if FP Unit Trap need to be on */
- if (value & X86_CR0_TS)
- {
- vmcb->exception_intercepts |= EXCEPTION_BITMAP_NM;
+ /* TS cleared? Then initialise FPU now. */
+ if ( !(value & X86_CR0_TS) )
+ {
+ setup_fpu(v);
+ vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM;
}
HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR0 value = %lx\n", value);
@@ -1669,11 +1676,11 @@
break;
case INSTR_CLTS:
- clts();
+ /* TS being cleared means that it's time to restore fpu state. */
setup_fpu(current);
+ vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM;
vmcb->cr0 &= ~X86_CR0_TS; /* clear TS */
v->arch.hvm_svm.cpu_shadow_cr0 &= ~X86_CR0_TS; /* clear TS */
- vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM;
break;
case INSTR_LMSW:
@@ -1803,11 +1810,8 @@
struct vcpu *v = current;
struct hvm_virpit *vpit = &v->domain->arch.hvm_domain.vpit;
s_time_t next_pit = -1, next_wakeup;
- unsigned int inst_len;
-
- svm_stts(v);
- inst_len = __get_instruction_length(vmcb, INSTR_HLT, NULL);
- __update_guest_eip(vmcb, inst_len);
+
+ __update_guest_eip(vmcb, 1);
if ( !v->vcpu_id )
next_pit = get_pit_scheduled(v, vpit);
@@ -1822,7 +1826,6 @@
static inline void svm_vmexit_do_mwait(void)
{
- return;
}
@@ -2494,7 +2497,6 @@
break;
case VMEXIT_INTR:
- svm_stts(v);
raise_softirq(SCHEDULE_SOFTIRQ);
break;
diff -r ee6f025fb264 -r 7d89f672aa49 xen/arch/x86/hvm/svm/vmcb.c
--- a/xen/arch/x86/hvm/svm/vmcb.c Tue Feb 14 22:30:59 2006
+++ b/xen/arch/x86/hvm/svm/vmcb.c Tue Feb 14 23:15:11 2006
@@ -489,7 +489,9 @@
{
struct domain *d = v->domain;
struct hvm_virpit *vpit = &d->arch.hvm_domain.vpit;
-
+
+ svm_stts(v);
+
if ( test_bit(iopacket_port(d), &d->shared_info->evtchn_pending[0]) ||
test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags) )
hvm_wait_io();
@@ -498,7 +500,7 @@
if ( vpit->first_injected )
pickup_deactive_ticks(vpit);
svm_set_tsc_shift(v, vpit);
-
+
/* We can't resume the guest if we're waiting on I/O */
ASSERT(!test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags));
}
diff -r ee6f025fb264 -r 7d89f672aa49 xen/arch/x86/hvm/svm/x86_32/exits.S
--- a/xen/arch/x86/hvm/svm/x86_32/exits.S Tue Feb 14 22:30:59 2006
+++ b/xen/arch/x86/hvm/svm/x86_32/exits.S Tue Feb 14 23:15:11 2006
@@ -89,7 +89,7 @@
#define CLGI .byte 0x0F,0x01,0xDD
#define DO_TSC_OFFSET 0
-#define DO_FPUSAVE 1
+#define DO_FPUSAVE 0
ENTRY(svm_asm_do_launch)
sti
diff -r ee6f025fb264 -r 7d89f672aa49 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c Tue Feb 14 22:30:59 2006
+++ b/xen/arch/x86/hvm/vmx/vmx.c Tue Feb 14 23:15:11 2006
@@ -615,8 +615,8 @@
unsigned long cr0;
struct vcpu *v = current;
- clts();
setup_fpu(current);
+ __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_NM);
/* Disable TS in guest CR0 unless the guest wants the exception too. */
__vmread_vcpu(v, CR0_READ_SHADOW, &cr0);
@@ -626,9 +626,6 @@
cr0 &= ~X86_CR0_TS;
__vmwrite(GUEST_CR0, cr0);
}
-
- /* Xen itself doesn't need another exception. */
- __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_NM);
}
/* Reserved bits: [31:15], [12:11], [9], [6], [2:1] */
@@ -1158,14 +1155,11 @@
__vmread_vcpu(v, CR0_READ_SHADOW, &old_cr0);
paging_enabled = (old_cr0 & X86_CR0_PE) && (old_cr0 & X86_CR0_PG);
- /*
- * 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 )
+ /* TS cleared? Then initialise FPU now. */
+ if ( !(value & X86_CR0_TS) )
{
- clts();
setup_fpu(v);
+ __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_NM);
}
__vmwrite(GUEST_CR0, value | X86_CR0_PE | X86_CR0_PG | X86_CR0_NE);
@@ -1520,8 +1514,8 @@
TRACE_VMEXIT(1,TYPE_CLTS);
/* We initialise the FPU now, to avoid needing another vmexit. */
- clts();
- setup_fpu(current);
+ setup_fpu(v);
+ __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_NM);
__vmread_vcpu(v, GUEST_CR0, &value);
value &= ~X86_CR0_TS; /* clear TS */
diff -r ee6f025fb264 -r 7d89f672aa49 xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c Tue Feb 14 22:30:59 2006
+++ b/xen/arch/x86/traps.c Tue Feb 14 23:15:11 2006
@@ -1261,9 +1261,6 @@
struct trap_bounce *tb;
struct trap_info *ti;
- /* Prevent recursion. */
- clts();
-
setup_fpu(current);
if ( current->arch.guest_context.ctrlreg[0] & X86_CR0_TS )
diff -r ee6f025fb264 -r 7d89f672aa49 xen/include/asm-x86/i387.h
--- a/xen/include/asm-x86/i387.h Tue Feb 14 22:30:59 2006
+++ b/xen/include/asm-x86/i387.h Tue Feb 14 23:15:11 2006
@@ -33,6 +33,7 @@
{
if ( !test_and_set_bit(_VCPUF_fpu_dirtied, &v->vcpu_flags) )
{
+ clts();
if ( test_bit(_VCPUF_fpu_initialised, &v->vcpu_flags) )
restore_fpu(v);
else
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|