* The legacy FNSAVE instruction cleared all FPU state
* unconditionally, so registers are essentially destroyed.
* Modern FPU state can be kept in registers, if there are
- * no pending FP exceptions. (Note the FIXME below.)
+ * no pending FP exceptions.
*/
static inline int copy_fpregs_to_fpstate(struct fpu *fpu)
{
- if (use_xsave()) {
+ if (likely(use_xsave())) {
xsave_state(&fpu->state->xsave);
+ return 1;
+ }
- /*
- * xsave header may indicate the init state of the FP.
- */
- if (!(fpu->state->xsave.header.xfeatures & XSTATE_FP))
- goto keep_fpregs;
- } else {
- if (use_fxsr()) {
- fpu_fxsave(fpu);
- } else {
- /* FNSAVE always clears FPU registers: */
- asm volatile("fnsave %[fx]; fwait"
- : [fx] "=m" (fpu->state->fsave));
- goto drop_fpregs;
- }
+ if (likely(use_fxsr())) {
+ fpu_fxsave(fpu);
+ return 1;
}
/*
- * If exceptions are pending, we need to clear them so
- * that we don't randomly get exceptions later.
- *
- * FIXME! Is this perhaps only true for the old-style
- * irq13 case? Maybe we could leave the x87 state
- * intact otherwise?
+ * Legacy FPU register saving, FNSAVE always clears FPU registers,
+ * so we have to mark them inactive:
*/
- if (unlikely(fpu->state->fxsave.swd & X87_FSW_ES)) {
- asm volatile("fnclex");
- goto drop_fpregs;
- }
-
-keep_fpregs:
- return 1;
+ asm volatile("fnsave %[fx]; fwait" : [fx] "=m" (fpu->state->fsave));
-drop_fpregs:
return 0;
}