Avoid save/restoring AMX registers to avoid a SPR erratum

Intel SPR erratum SPR4 says that if you trip into a vmexit while
doing FPU save/restore, your AMX register state might misbehave...
and by misbehave, I mean save all zeroes incorrectly, leading to
explosions if you restore it.

Since we're not using AMX for anything, the simple way to avoid
this is to just not save/restore those when we do anything, since
we're killing preemption of any sort across our save/restores.

If we ever decide to use AMX, it's not clear that we have any
way to mitigate this, on Linux...but I am not an expert.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Rich Ercolani <rincebrain@gmail.com>
Closes #14989
Closes #15168

Signed-off-by: Rich Ercolani <rincebrain@gmail.com>
This commit is contained in:
Rich Ercolani 2024-03-05 21:35:36 -05:00 committed by Brian Behlendorf
parent fb6d532066
commit f288fdb4bd
1 changed files with 16 additions and 7 deletions

View File

@ -157,6 +157,15 @@
#endif #endif
#endif #endif
#ifndef XFEATURE_MASK_XTILE
/*
* For kernels where this doesn't exist yet, we still don't want to break
* by save/restoring this broken nonsense.
* See issue #14989 or Intel errata SPR4 for why
*/
#define XFEATURE_MASK_XTILE 0x60000
#endif
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/slab.h> #include <linux/slab.h>
@ -290,7 +299,7 @@ kfpu_begin(void)
*/ */
union fpregs_state *state = zfs_kfpu_fpregs[smp_processor_id()]; union fpregs_state *state = zfs_kfpu_fpregs[smp_processor_id()];
if (static_cpu_has(X86_FEATURE_XSAVE)) { if (static_cpu_has(X86_FEATURE_XSAVE)) {
kfpu_save_xsave(&state->xsave, ~0); kfpu_save_xsave(&state->xsave, ~XFEATURE_MASK_XTILE);
} else if (static_cpu_has(X86_FEATURE_FXSR)) { } else if (static_cpu_has(X86_FEATURE_FXSR)) {
kfpu_save_fxsr(&state->fxsave); kfpu_save_fxsr(&state->fxsave);
} else { } else {
@ -319,18 +328,18 @@ kfpu_begin(void)
union fpregs_state *state = zfs_kfpu_fpregs[smp_processor_id()]; union fpregs_state *state = zfs_kfpu_fpregs[smp_processor_id()];
#if defined(HAVE_XSAVES) #if defined(HAVE_XSAVES)
if (static_cpu_has(X86_FEATURE_XSAVES)) { if (static_cpu_has(X86_FEATURE_XSAVES)) {
kfpu_do_xsave("xsaves", &state->xsave, ~0); kfpu_do_xsave("xsaves", &state->xsave, ~XFEATURE_MASK_XTILE);
return; return;
} }
#endif #endif
#if defined(HAVE_XSAVEOPT) #if defined(HAVE_XSAVEOPT)
if (static_cpu_has(X86_FEATURE_XSAVEOPT)) { if (static_cpu_has(X86_FEATURE_XSAVEOPT)) {
kfpu_do_xsave("xsaveopt", &state->xsave, ~0); kfpu_do_xsave("xsaveopt", &state->xsave, ~XFEATURE_MASK_XTILE);
return; return;
} }
#endif #endif
if (static_cpu_has(X86_FEATURE_XSAVE)) { if (static_cpu_has(X86_FEATURE_XSAVE)) {
kfpu_do_xsave("xsave", &state->xsave, ~0); kfpu_do_xsave("xsave", &state->xsave, ~XFEATURE_MASK_XTILE);
} else if (static_cpu_has(X86_FEATURE_FXSR)) { } else if (static_cpu_has(X86_FEATURE_FXSR)) {
kfpu_save_fxsr(&state->fxsave); kfpu_save_fxsr(&state->fxsave);
} else { } else {
@ -396,7 +405,7 @@ kfpu_end(void)
union fpregs_state *state = zfs_kfpu_fpregs[smp_processor_id()]; union fpregs_state *state = zfs_kfpu_fpregs[smp_processor_id()];
if (static_cpu_has(X86_FEATURE_XSAVE)) { if (static_cpu_has(X86_FEATURE_XSAVE)) {
kfpu_restore_xsave(&state->xsave, ~0); kfpu_restore_xsave(&state->xsave, ~XFEATURE_MASK_XTILE);
} else if (static_cpu_has(X86_FEATURE_FXSR)) { } else if (static_cpu_has(X86_FEATURE_FXSR)) {
kfpu_restore_fxsr(&state->fxsave); kfpu_restore_fxsr(&state->fxsave);
} else { } else {
@ -415,12 +424,12 @@ kfpu_end(void)
union fpregs_state *state = zfs_kfpu_fpregs[smp_processor_id()]; union fpregs_state *state = zfs_kfpu_fpregs[smp_processor_id()];
#if defined(HAVE_XSAVES) #if defined(HAVE_XSAVES)
if (static_cpu_has(X86_FEATURE_XSAVES)) { if (static_cpu_has(X86_FEATURE_XSAVES)) {
kfpu_do_xrstor("xrstors", &state->xsave, ~0); kfpu_do_xrstor("xrstors", &state->xsave, ~XFEATURE_MASK_XTILE);
goto out; goto out;
} }
#endif #endif
if (static_cpu_has(X86_FEATURE_XSAVE)) { if (static_cpu_has(X86_FEATURE_XSAVE)) {
kfpu_do_xrstor("xrstor", &state->xsave, ~0); kfpu_do_xrstor("xrstor", &state->xsave, ~XFEATURE_MASK_XTILE);
} else if (static_cpu_has(X86_FEATURE_FXSR)) { } else if (static_cpu_has(X86_FEATURE_FXSR)) {
kfpu_restore_fxsr(&state->fxsave); kfpu_restore_fxsr(&state->fxsave);
} else { } else {