x86, FPU: Handle obscure corner cases

Also release FPU when dissociating a vcpu, otherwise ksCurFPUOwner
may be wrong.

fpuRelease() sets ksCurFPUOwner to NULL, if this happens before
we return to the host, it may end up with the FPU disabled and no
FPU state loaded. Instead of hunting down and handling all obscure
corner cases where this might happen (dissociating vcpus, cross-core
operations), just check for this in vcpu_fpu_to_host().

Signed-off-by: Indan Zupancic <indan@nul.nu>
This commit is contained in:
Indan Zupancic
2024-09-18 22:48:58 +01:00
committed by Gerwin Klein
parent 8502701926
commit 88c25fe7fc

View File

@@ -512,6 +512,8 @@ static void dissociateVcpuTcb(tcb_t *tcb, vcpu_t *vcpu)
{
assert(tcb->tcbArch.tcbVCPU == vcpu);
assert(vcpu->vcpuTCB == tcb);
fpuRelease(tcb);
vcpu->fpu_active = false;
tcb->tcbArch.tcbVCPU = NULL;
vcpu->vcpuTCB = NULL;
}
@@ -1520,11 +1522,14 @@ void vcpu_fpu_to_host(tcb_t *tcb, vcpu_t *vcpu)
if (tcb->tcbFlags & seL4_TCBFlag_fpuDisabled) {
/* FPU may have been enabled for the guest, but host isn't allowed to use it */
disableFpu();
} else if (vcpu->fpu_active && nativeThreadUsingFPU(tcb)) {
} else if (nativeThreadUsingFPU(tcb) && vcpu->fpu_active) {
/* Guest was using the FPU, switch to host FPU state */
saveFpuState(tcb);
vcpu->fpu_active = false;
loadFpuState(tcb);
} else if (!nativeThreadUsingFPU(tcb)) {
/* Handle corner cases like dissociated vcpu */
switchLocalFpuOwner(tcb);
}
}