aboutsummaryrefslogtreecommitdiff
path: root/sys/amd64/vmm/vmm.c
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2014-02-08 16:37:54 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2014-02-08 16:37:54 +0000
commitabb023fb95ef488264c73d655238475b2e2ade7d (patch)
treefd49cf1b4fce6e5d303e3b692d2f6382e0eb2016 /sys/amd64/vmm/vmm.c
parent0b57dd6bde6a5828384886d519b1b9fc02d427f1 (diff)
downloadsrc-abb023fb95ef488264c73d655238475b2e2ade7d.tar.gz
src-abb023fb95ef488264c73d655238475b2e2ade7d.zip
Add virtualized XSAVE support to bhyve which permits guests to use XSAVE and
XSAVE-enabled features like AVX. - Store a per-cpu guest xcr0 register. When switching to the guest FPU state, switch to the guest xcr0 value. Note that the guest FPU state is saved and restored using the host's xcr0 value and xcr0 is saved/restored "inside" of saving/restoring the guest FPU state. - Handle VM exits for the xsetbv instruction by updating the guest xcr0. - Expose the XSAVE feature to the guest only if the host has enabled XSAVE, and only advertise XSAVE features enabled by the host to the guest. This ensures that the guest will only adjust FPU state that is a subset of the guest FPU state saved and restored by the host. Reviewed by: grehan
Notes
Notes: svn path=/head/; revision=261638
Diffstat (limited to 'sys/amd64/vmm/vmm.c')
-rw-r--r--sys/amd64/vmm/vmm.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c
index 30f8dd36ea69..4ae691563fec 100644
--- a/sys/amd64/vmm/vmm.c
+++ b/sys/amd64/vmm/vmm.c
@@ -89,6 +89,7 @@ struct vcpu {
struct vlapic *vlapic;
int vcpuid;
struct savefpu *guestfpu; /* guest fpu state */
+ uint64_t guest_xcr0;
void *stats;
struct vm_exit exitinfo;
enum x2apic_state x2apic_state;
@@ -206,6 +207,7 @@ vcpu_init(struct vm *vm, uint32_t vcpu_id)
vcpu->vcpuid = vcpu_id;
vcpu->vlapic = VLAPIC_INIT(vm->cookie, vcpu_id);
vm_set_x2apic_state(vm, vcpu_id, X2APIC_ENABLED);
+ vcpu->guest_xcr0 = XFEATURE_ENABLED_X87;
vcpu->guestfpu = fpu_save_area_alloc();
fpu_save_area_reset(vcpu->guestfpu);
vcpu->stats = vmm_stat_alloc();
@@ -815,6 +817,10 @@ restore_guest_fpustate(struct vcpu *vcpu)
fpu_stop_emulating();
fpurestore(vcpu->guestfpu);
+ /* restore guest XCR0 if XSAVE is enabled in the host */
+ if (rcr4() & CR4_XSAVE)
+ load_xcr(0, vcpu->guest_xcr0);
+
/*
* The FPU is now "dirty" with the guest's state so turn on emulation
* to trap any access to the FPU by the host.
@@ -829,6 +835,12 @@ save_guest_fpustate(struct vcpu *vcpu)
if ((rcr0() & CR0_TS) == 0)
panic("fpu emulation not enabled in host!");
+ /* save guest XCR0 and restore host XCR0 */
+ if (rcr4() & CR4_XSAVE) {
+ vcpu->guest_xcr0 = rxcr(0);
+ load_xcr(0, vmm_get_host_xcr0());
+ }
+
/* save guest FPU state */
fpu_stop_emulating();
fpusave(vcpu->guestfpu);