@@ -294,10 +294,29 @@ EXPORT_SYMBOL_GPL(fpu_enable_guest_xfd_features);
294294#ifdef CONFIG_X86_64
295295void fpu_update_guest_xfd (struct fpu_guest * guest_fpu , u64 xfd )
296296{
297+ struct fpstate * fpstate = guest_fpu -> fpstate ;
298+
297299 fpregs_lock ();
298- guest_fpu -> fpstate -> xfd = xfd ;
299- if (guest_fpu -> fpstate -> in_use )
300- xfd_update_state (guest_fpu -> fpstate );
300+
301+ /*
302+ * KVM's guest ABI is that setting XFD[i]=1 *can* immediately revert the
303+ * save state to its initial configuration. Likewise, KVM_GET_XSAVE does
304+ * the same as XSAVE and returns XSTATE_BV[i]=0 whenever XFD[i]=1.
305+ *
306+ * If the guest's FPU state is in hardware, just update XFD: the XSAVE
307+ * in fpu_swap_kvm_fpstate will clear XSTATE_BV[i] whenever XFD[i]=1.
308+ *
309+ * If however the guest's FPU state is NOT resident in hardware, clear
310+ * disabled components in XSTATE_BV now, or a subsequent XRSTOR will
311+ * attempt to load disabled components and generate #NM _in the host_.
312+ */
313+ if (xfd && test_thread_flag (TIF_NEED_FPU_LOAD ))
314+ fpstate -> regs .xsave .header .xfeatures &= ~xfd ;
315+
316+ fpstate -> xfd = xfd ;
317+ if (fpstate -> in_use )
318+ xfd_update_state (fpstate );
319+
301320 fpregs_unlock ();
302321}
303322EXPORT_SYMBOL_GPL (fpu_update_guest_xfd );
@@ -405,6 +424,13 @@ int fpu_copy_uabi_to_guest_fpstate(struct fpu_guest *gfpu, const void *buf,
405424 if (ustate -> xsave .header .xfeatures & ~xcr0 )
406425 return - EINVAL ;
407426
427+ /*
428+ * Disabled features must be in their initial state, otherwise XRSTOR
429+ * causes an exception.
430+ */
431+ if (WARN_ON_ONCE (ustate -> xsave .header .xfeatures & kstate -> xfd ))
432+ return - EINVAL ;
433+
408434 /*
409435 * Nullify @vpkru to preserve its current value if PKRU's bit isn't set
410436 * in the header. KVM's odd ABI is to leave PKRU untouched in this
0 commit comments