From bd8572e0bea40093c0be13d9544328644cbc7376 Mon Sep 17 00:00:00 2001 From: Neel Natu Date: Fri, 26 Oct 2012 03:12:40 +0000 Subject: [PATCH] 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 --- sys/amd64/vmm/intel/vmcs.c | 10 +++++++++- sys/amd64/vmm/vmm.c | 13 +++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/sys/amd64/vmm/intel/vmcs.c b/sys/amd64/vmm/intel/vmcs.c index 8c5346570f21..26ac5f891c71 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 8bc958192ad2..6efc01fd2e74 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(); }