diff options
author | neel <neel@FreeBSD.org> | 2012-10-26 03:12:40 +0000 |
---|---|---|
committer | neel <neel@FreeBSD.org> | 2012-10-26 03:12:40 +0000 |
commit | cbd59fc940c5caaf0cde3410c8772176220fd1a1 (patch) | |
tree | 8339c439b29ae56bf2004ef0fa5884151017f138 /sys/amd64 | |
parent | bcb3589583c269dcc88504fcf7c0dedc7c03f123 (diff) | |
download | FreeBSD-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.c | 10 | ||||
-rw-r--r-- | sys/amd64/vmm/vmm.c | 13 |
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(); } |