summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
authorneel <neel@FreeBSD.org>2012-10-26 03:12:40 +0000
committerneel <neel@FreeBSD.org>2012-10-26 03:12:40 +0000
commitcbd59fc940c5caaf0cde3410c8772176220fd1a1 (patch)
tree8339c439b29ae56bf2004ef0fa5884151017f138 /sys/amd64
parentbcb3589583c269dcc88504fcf7c0dedc7c03f123 (diff)
downloadFreeBSD-src-cbd59fc940c5caaf0cde3410c8772176220fd1a1.zip
FreeBSD-src-cbd59fc940c5caaf0cde3410c8772176220fd1a1.tar.gz
Unconditionally enable fpu emulation by setting CR0.TS in the host after the
guest does a vm exit. This allows us to trap any fpu access in the host context while the fpu still has "dirty" state belonging to the guest. Reported by: "s vas" on freebsd-virtualization@ Obtained from: NetApp
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/vmm/intel/vmcs.c10
-rw-r--r--sys/amd64/vmm/vmm.c13
2 files changed, 22 insertions, 1 deletions
diff --git a/sys/amd64/vmm/intel/vmcs.c b/sys/amd64/vmm/intel/vmcs.c
index 8c53465..26ac5f8 100644
--- a/sys/amd64/vmm/intel/vmcs.c
+++ b/sys/amd64/vmm/intel/vmcs.c
@@ -367,7 +367,15 @@ vmcs_set_defaults(struct vmcs *vmcs,
goto done;
/* Load the control registers */
- cr0 = rcr0();
+
+ /*
+ * We always want CR0.TS to be set when the processor does a VM exit.
+ *
+ * With emulation turned on unconditionally after a VM exit, we are
+ * able to trap inadvertent use of the FPU until the guest FPU state
+ * has been safely squirreled away.
+ */
+ cr0 = rcr0() | CR0_TS;
if ((error = vmwrite(VMCS_HOST_CR0, cr0)) != 0)
goto done;
diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c
index 8bc9581..6efc01f 100644
--- a/sys/amd64/vmm/vmm.c
+++ b/sys/amd64/vmm/vmm.c
@@ -640,14 +640,27 @@ restore_guest_fpustate(struct vcpu *vcpu)
/* flush host state to the pcb */
fpuexit(curthread);
+
+ /* restore guest FPU state */
fpu_stop_emulating();
fpurestore(vcpu->guestfpu);
+
+ /*
+ * The FPU is now "dirty" with the guest's state so turn on emulation
+ * to trap any access to the FPU by the host.
+ */
+ fpu_start_emulating();
}
static void
save_guest_fpustate(struct vcpu *vcpu)
{
+ if ((rcr0() & CR0_TS) == 0)
+ panic("fpu emulation not enabled in host!");
+
+ /* save guest FPU state */
+ fpu_stop_emulating();
fpusave(vcpu->guestfpu);
fpu_start_emulating();
}
OpenPOWER on IntegriCloud