Skip to content

Commit 6afbb58

Browse files
KAGA-KOKOsuryasaimadhu
authored andcommitted
x86/fpu: Cache xfeature flags from CPUID
In preparation for runtime calculation of XSAVE offsets cache the feature flags for each XSTATE component during feature enumeration via CPUID(0xD). EDX has two relevant bits: 0 Supervisor component 1 Feature storage must be 64 byte aligned These bits are currently only evaluated during init, but the alignment bit must be cached to make runtime calculation of XSAVE offsets efficient. Cache the full EDX content and use it for the existing alignment and supervisor checks. Signed-off-by: Thomas Gleixner <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 35a77d4 commit 6afbb58

File tree

1 file changed

+13
-36
lines changed

1 file changed

+13
-36
lines changed

arch/x86/kernel/fpu/xstate.c

Lines changed: 13 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ static unsigned int xstate_sizes[XFEATURE_MAX] __ro_after_init =
8383
{ [ 0 ... XFEATURE_MAX - 1] = -1};
8484
static unsigned int xstate_comp_offsets[XFEATURE_MAX] __ro_after_init =
8585
{ [ 0 ... XFEATURE_MAX - 1] = -1};
86+
static unsigned int xstate_flags[XFEATURE_MAX] __ro_after_init;
87+
88+
#define XSTATE_FLAG_SUPERVISOR BIT(0)
89+
#define XSTATE_FLAG_ALIGNED64 BIT(1)
8690

8791
/*
8892
* Return whether the system supports a given xfeature.
@@ -122,17 +126,14 @@ int cpu_has_xfeatures(u64 xfeatures_needed, const char **feature_name)
122126
}
123127
EXPORT_SYMBOL_GPL(cpu_has_xfeatures);
124128

125-
static bool xfeature_is_supervisor(int xfeature_nr)
129+
static bool xfeature_is_aligned64(int xfeature_nr)
126130
{
127-
/*
128-
* Extended State Enumeration Sub-leaves (EAX = 0DH, ECX = n, n > 1)
129-
* returns ECX[0] set to (1) for a supervisor state, and cleared (0)
130-
* for a user state.
131-
*/
132-
u32 eax, ebx, ecx, edx;
131+
return xstate_flags[xfeature_nr] & XSTATE_FLAG_ALIGNED64;
132+
}
133133

134-
cpuid_count(XSTATE_CPUID, xfeature_nr, &eax, &ebx, &ecx, &edx);
135-
return ecx & 1;
134+
static bool xfeature_is_supervisor(int xfeature_nr)
135+
{
136+
return xstate_flags[xfeature_nr] & XSTATE_FLAG_SUPERVISOR;
136137
}
137138

138139
/*
@@ -203,6 +204,7 @@ static void __init setup_xstate_cache(void)
203204
cpuid_count(XSTATE_CPUID, i, &eax, &ebx, &ecx, &edx);
204205

205206
xstate_sizes[i] = eax;
207+
xstate_flags[i] = ecx;
206208

207209
/*
208210
* If an xfeature is supervisor state, the offset in EBX is
@@ -261,31 +263,6 @@ static void __init print_xstate_features(void)
261263
WARN_ON(nr >= XFEATURE_MAX); \
262264
} while (0)
263265

264-
/*
265-
* We could cache this like xstate_size[], but we only use
266-
* it here, so it would be a waste of space.
267-
*/
268-
static int xfeature_is_aligned(int xfeature_nr)
269-
{
270-
u32 eax, ebx, ecx, edx;
271-
272-
CHECK_XFEATURE(xfeature_nr);
273-
274-
if (!xfeature_enabled(xfeature_nr)) {
275-
WARN_ONCE(1, "Checking alignment of disabled xfeature %d\n",
276-
xfeature_nr);
277-
return 0;
278-
}
279-
280-
cpuid_count(XSTATE_CPUID, xfeature_nr, &eax, &ebx, &ecx, &edx);
281-
/*
282-
* The value returned by ECX[1] indicates the alignment
283-
* of state component 'i' when the compacted format
284-
* of the extended region of an XSAVE area is used:
285-
*/
286-
return !!(ecx & 2);
287-
}
288-
289266
/*
290267
* This function sets up offsets and sizes of all extended states in
291268
* xsave area. This supports both standard format and compacted format
@@ -314,7 +291,7 @@ static void __init setup_xstate_comp_offsets(void)
314291
next_offset = FXSAVE_SIZE + XSAVE_HDR_SIZE;
315292

316293
for_each_extended_xfeature(i, fpu_kernel_cfg.max_features) {
317-
if (xfeature_is_aligned(i))
294+
if (xfeature_is_aligned64(i))
318295
next_offset = ALIGN(next_offset, 64);
319296

320297
xstate_comp_offsets[i] = next_offset;
@@ -619,7 +596,7 @@ static unsigned int xstate_calculate_size(u64 xfeatures, bool compacted)
619596

620597
for_each_extended_xfeature(i, xfeatures) {
621598
/* Align from the end of the previous feature */
622-
if (xfeature_is_aligned(i))
599+
if (xfeature_is_aligned64(i))
623600
size = ALIGN(size, 64);
624601
/*
625602
* In compacted format the enabled features are packed,

0 commit comments

Comments
 (0)