From: Dave Hansen <dave.hansen@xxxxxxxxxxxxxxx> The goal of this series is to create a new class of xfeature: one which is enabled in XCR0 so that XSAVE/XRSTOR continue to work on it, but where the kernel does not use XSAVE*/XRSTOR* to manage the state or to maintain it in the thread FPU buffer (fpstate). Create a new helper in the XSAVE setup code: xstate_fpstate_enabled(). This helper returns whether or not an xfeature is being maintained inside of the thread's fpstate. For now, make xstate_fpstate_enabled() function identically to xfeature_enabled(). This ensures that this series is bisectable between this point and where PKRU is actually removed from xfeature_fpstate_enabled(). This series originally introduced xfeatures_mask_fpstate() to mean: "the set of features found in the kernel fpstate and managed by XSAVE". However, upstream ripped me off and made an identically- named function which refers to the features managed by XSAVE, which *excludes* PKRU at this juncture. That means that xfeature_fpstate_enabled() and xfeatures_mask_fpstate() will diverge until the end of the series. Signed-off-by: Dave Hansen <dave.hansen@xxxxxxxxxxxxxxx> Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx> Cc: Ingo Molnar <mingo@xxxxxxxxxx> Cc: Borislav Petkov <bp@xxxxxxxxx> Cc: x86@xxxxxxxxxx Cc: Andy Lutomirski <luto@xxxxxxxxxx> --- b/arch/x86/kernel/fpu/xstate.c | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff -puN arch/x86/kernel/fpu/xstate.c~xfeature-setup-fpstate arch/x86/kernel/fpu/xstate.c --- a/arch/x86/kernel/fpu/xstate.c~xfeature-setup-fpstate 2021-06-22 14:49:08.956051757 -0700 +++ b/arch/x86/kernel/fpu/xstate.c 2021-06-22 14:49:08.965051757 -0700 @@ -156,16 +156,32 @@ void fpu__init_cpu_xstate(void) } } +/* Can the XSAVE architecture be used to manage this feature? */ static bool xfeature_enabled(enum xfeature xfeature) { return xfeatures_mask_all & BIT_ULL(xfeature); } /* + * Is space for the feature present in the task->thread.fpu + * fpstate buffer and is the using XSAVE to context-switch it? + */ +static bool xfeature_fpstate_enabled(enum xfeature xfeature) +{ + // For bisectability, mirror xfeature_enabled() for now. + //return xfeatures_mask_fpstate() & BIT_ULL(xfeature); + return xfeature_enabled(xfeature); +} + +/* * Record the offsets and sizes of various xstates contained - * in the XSAVE state memory layout. + * in the non-compacted XSAVE state memory layout. + * + * These are always used in the XSAVE ABIs and are used for + * the kernel xstate buffer in cases where XSAVES (and thus + * the compacted format) is not supported. */ -static void __init setup_xstate_features(void) +static void __init setup_xfeature_offsets(void) { u32 eax, ebx, ecx, edx, i; /* start at the beginning of the "extended state" */ @@ -185,6 +201,10 @@ static void __init setup_xstate_features xmm_space); for (i = FIRST_EXTENDED_XFEATURE; i < XFEATURE_MAX; i++) { + /* + * Set up any features enabled that are in the kernel + * xstate buffer *or* the user XSAVE ABIs. + */ if (!xfeature_enabled(i)) continue; @@ -257,7 +277,7 @@ static int xfeature_is_aligned(int xfeat CHECK_XFEATURE(xfeature_nr); - if (!xfeature_enabled(xfeature_nr)) { + if (!xfeature_fpstate_enabled(xfeature_nr)) { WARN_ONCE(1, "Checking alignment of disabled xfeature %d\n", xfeature_nr); return 0; @@ -293,7 +313,7 @@ static void __init setup_xstate_comp_off if (!boot_cpu_has(X86_FEATURE_XSAVES)) { for (i = FIRST_EXTENDED_XFEATURE; i < XFEATURE_MAX; i++) { - if (xfeature_enabled(i)) + if (xfeature_fpstate_enabled(i)) xstate_comp_offsets[i] = xstate_offsets[i]; } return; @@ -302,7 +322,7 @@ static void __init setup_xstate_comp_off next_offset = FXSAVE_SIZE + XSAVE_HDR_SIZE; for (i = FIRST_EXTENDED_XFEATURE; i < XFEATURE_MAX; i++) { - if (!xfeature_enabled(i)) + if (!xfeature_fpstate_enabled(i)) continue; if (xfeature_is_aligned(i)) @@ -329,7 +349,7 @@ static void __init setup_supervisor_only next_offset = FXSAVE_SIZE + XSAVE_HDR_SIZE; for (i = FIRST_EXTENDED_XFEATURE; i < XFEATURE_MAX; i++) { - if (!xfeature_enabled(i) || !xfeature_is_supervisor(i)) + if (!xfeature_fpstate_enabled(i) || !xfeature_is_supervisor(i)) continue; if (xfeature_is_aligned(i)) @@ -348,7 +368,7 @@ static void __init print_xstate_offset_s int i; for (i = FIRST_EXTENDED_XFEATURE; i < XFEATURE_MAX; i++) { - if (!xfeature_enabled(i)) + if (!xfeature_fpstate_enabled(i)) continue; pr_info("x86/fpu: xstate_offset[%d]: %4d, xstate_sizes[%d]: %4d\n", i, xstate_comp_offsets[i], i, xstate_sizes[i]); @@ -391,7 +411,7 @@ static void __init setup_init_fpu_buf(vo if (!boot_cpu_has(X86_FEATURE_XSAVE)) return; - setup_xstate_features(); + setup_xfeature_offsets(); print_xstate_features(); if (boot_cpu_has(X86_FEATURE_XSAVES)) @@ -562,7 +582,7 @@ static void do_extra_xstate_size_checks( int i; for (i = FIRST_EXTENDED_XFEATURE; i < XFEATURE_MAX; i++) { - if (!xfeature_enabled(i)) + if (!xfeature_fpstate_enabled(i)) continue; check_xstate_against_struct(i); @@ -849,7 +869,7 @@ void fpu__resume_cpu(void) */ static void *__raw_xsave_addr(struct xregs_state *xsave, int xfeature_nr) { - if (!xfeature_enabled(xfeature_nr)) { + if (!xfeature_fpstate_enabled(xfeature_nr)) { WARN_ON_FPU(1); return NULL; } _