Skip to content

Commit e36ae22

Browse files
committed
Merge tag 'x86_fpu_for_v5.19_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fpu updates from Borislav Petkov: - Add support for XSAVEC - the Compacted XSTATE saving variant - and thus allow for guests to use this compacted XSTATE variant when the hypervisor exports that support - A variable shadowing cleanup * tag 'x86_fpu_for_v5.19_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/fpu: Cleanup variable shadowing x86/fpu/xsave: Support XSAVEC in the kernel
2 parents de8ac81 + b91c092 commit e36ae22

File tree

3 files changed

+49
-27
lines changed

3 files changed

+49
-27
lines changed

arch/x86/include/asm/cpufeatures.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@
201201
#define X86_FEATURE_INVPCID_SINGLE ( 7*32+ 7) /* Effectively INVPCID && CR4.PCIDE=1 */
202202
#define X86_FEATURE_HW_PSTATE ( 7*32+ 8) /* AMD HW-PState */
203203
#define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */
204-
/* FREE! ( 7*32+10) */
204+
#define X86_FEATURE_XCOMPACTED ( 7*32+10) /* "" Use compacted XSTATE (XSAVES or XSAVEC) */
205205
#define X86_FEATURE_PTI ( 7*32+11) /* Kernel Page Table Isolation enabled */
206206
#define X86_FEATURE_RETPOLINE ( 7*32+12) /* "" Generic Retpoline mitigation for Spectre variant 2 */
207207
#define X86_FEATURE_RETPOLINE_LFENCE ( 7*32+13) /* "" Use LFENCE for Spectre variant 2 */

arch/x86/kernel/fpu/xstate.c

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,8 @@ static unsigned int xfeature_get_offset(u64 xcomp_bv, int xfeature)
142142
* Non-compacted format and legacy features use the cached fixed
143143
* offsets.
144144
*/
145-
if (!cpu_feature_enabled(X86_FEATURE_XSAVES) || xfeature <= XFEATURE_SSE)
145+
if (!cpu_feature_enabled(X86_FEATURE_XCOMPACTED) ||
146+
xfeature <= XFEATURE_SSE)
146147
return xstate_offsets[xfeature];
147148

148149
/*
@@ -369,12 +370,12 @@ static void __init setup_init_fpu_buf(void)
369370
/*
370371
* All components are now in init state. Read the state back so
371372
* that init_fpstate contains all non-zero init state. This only
372-
* works with XSAVE, but not with XSAVEOPT and XSAVES because
373+
* works with XSAVE, but not with XSAVEOPT and XSAVEC/S because
373374
* those use the init optimization which skips writing data for
374375
* components in init state.
375376
*
376377
* XSAVE could be used, but that would require to reshuffle the
377-
* data when XSAVES is available because XSAVES uses xstate
378+
* data when XSAVEC/S is available because XSAVEC/S uses xstate
378379
* compaction. But doing so is a pointless exercise because most
379380
* components have an all zeros init state except for the legacy
380381
* ones (FP and SSE). Those can be saved with FXSAVE into the
@@ -584,7 +585,8 @@ static unsigned int xstate_calculate_size(u64 xfeatures, bool compacted)
584585
*/
585586
static bool __init paranoid_xstate_size_valid(unsigned int kernel_size)
586587
{
587-
bool compacted = cpu_feature_enabled(X86_FEATURE_XSAVES);
588+
bool compacted = cpu_feature_enabled(X86_FEATURE_XCOMPACTED);
589+
bool xsaves = cpu_feature_enabled(X86_FEATURE_XSAVES);
588590
unsigned int size = FXSAVE_SIZE + XSAVE_HDR_SIZE;
589591
int i;
590592

@@ -595,7 +597,7 @@ static bool __init paranoid_xstate_size_valid(unsigned int kernel_size)
595597
* Supervisor state components can be managed only by
596598
* XSAVES.
597599
*/
598-
if (!compacted && xfeature_is_supervisor(i)) {
600+
if (!xsaves && xfeature_is_supervisor(i)) {
599601
XSTATE_WARN_ON(1);
600602
return false;
601603
}
@@ -612,8 +614,11 @@ static bool __init paranoid_xstate_size_valid(unsigned int kernel_size)
612614
* the size of the *user* states. If we use it to size a buffer
613615
* that we use 'XSAVES' on, we could potentially overflow the
614616
* buffer because 'XSAVES' saves system states too.
617+
*
618+
* This also takes compaction into account. So this works for
619+
* XSAVEC as well.
615620
*/
616-
static unsigned int __init get_xsaves_size(void)
621+
static unsigned int __init get_compacted_size(void)
617622
{
618623
unsigned int eax, ebx, ecx, edx;
619624
/*
@@ -623,6 +628,10 @@ static unsigned int __init get_xsaves_size(void)
623628
* containing all the state components
624629
* corresponding to bits currently set in
625630
* XCR0 | IA32_XSS.
631+
*
632+
* When XSAVES is not available but XSAVEC is (virt), then there
633+
* are no supervisor states, but XSAVEC still uses compacted
634+
* format.
626635
*/
627636
cpuid_count(XSTATE_CPUID, 1, &eax, &ebx, &ecx, &edx);
628637
return ebx;
@@ -632,13 +641,13 @@ static unsigned int __init get_xsaves_size(void)
632641
* Get the total size of the enabled xstates without the independent supervisor
633642
* features.
634643
*/
635-
static unsigned int __init get_xsaves_size_no_independent(void)
644+
static unsigned int __init get_xsave_compacted_size(void)
636645
{
637646
u64 mask = xfeatures_mask_independent();
638647
unsigned int size;
639648

640649
if (!mask)
641-
return get_xsaves_size();
650+
return get_compacted_size();
642651

643652
/* Disable independent features. */
644653
wrmsrl(MSR_IA32_XSS, xfeatures_mask_supervisor());
@@ -647,7 +656,7 @@ static unsigned int __init get_xsaves_size_no_independent(void)
647656
* Ask the hardware what size is required of the buffer.
648657
* This is the size required for the task->fpu buffer.
649658
*/
650-
size = get_xsaves_size();
659+
size = get_compacted_size();
651660

652661
/* Re-enable independent features so XSAVES will work on them again. */
653662
wrmsrl(MSR_IA32_XSS, xfeatures_mask_supervisor() | mask);
@@ -687,20 +696,21 @@ static int __init init_xstate_size(void)
687696
{
688697
/* Recompute the context size for enabled features: */
689698
unsigned int user_size, kernel_size, kernel_default_size;
690-
bool compacted = cpu_feature_enabled(X86_FEATURE_XSAVES);
699+
bool compacted = cpu_feature_enabled(X86_FEATURE_XCOMPACTED);
691700

692701
/* Uncompacted user space size */
693702
user_size = get_xsave_size_user();
694703

695704
/*
696-
* XSAVES kernel size includes supervisor states and
697-
* uses compacted format when available.
705+
* XSAVES kernel size includes supervisor states and uses compacted
706+
* format. XSAVEC uses compacted format, but does not save
707+
* supervisor states.
698708
*
699-
* XSAVE does not support supervisor states so
700-
* kernel and user size is identical.
709+
* XSAVE[OPT] do not support supervisor states so kernel and user
710+
* size is identical.
701711
*/
702712
if (compacted)
703-
kernel_size = get_xsaves_size_no_independent();
713+
kernel_size = get_xsave_compacted_size();
704714
else
705715
kernel_size = user_size;
706716

@@ -813,8 +823,11 @@ void __init fpu__init_system_xstate(unsigned int legacy_size)
813823
if (!cpu_feature_enabled(X86_FEATURE_XFD))
814824
fpu_kernel_cfg.max_features &= ~XFEATURE_MASK_USER_DYNAMIC;
815825

816-
fpu_kernel_cfg.max_features &= XFEATURE_MASK_USER_SUPPORTED |
817-
XFEATURE_MASK_SUPERVISOR_SUPPORTED;
826+
if (!cpu_feature_enabled(X86_FEATURE_XSAVES))
827+
fpu_kernel_cfg.max_features &= XFEATURE_MASK_USER_SUPPORTED;
828+
else
829+
fpu_kernel_cfg.max_features &= XFEATURE_MASK_USER_SUPPORTED |
830+
XFEATURE_MASK_SUPERVISOR_SUPPORTED;
818831

819832
fpu_user_cfg.max_features = fpu_kernel_cfg.max_features;
820833
fpu_user_cfg.max_features &= XFEATURE_MASK_USER_SUPPORTED;
@@ -837,6 +850,11 @@ void __init fpu__init_system_xstate(unsigned int legacy_size)
837850
*/
838851
init_fpstate.xfd = fpu_user_cfg.max_features & XFEATURE_MASK_USER_DYNAMIC;
839852

853+
/* Set up compaction feature bit */
854+
if (cpu_feature_enabled(X86_FEATURE_XSAVEC) ||
855+
cpu_feature_enabled(X86_FEATURE_XSAVES))
856+
setup_force_cpu_cap(X86_FEATURE_XCOMPACTED);
857+
840858
/* Enable xstate instructions to be able to continue with initialization: */
841859
fpu__init_cpu_xstate();
842860

@@ -873,7 +891,7 @@ void __init fpu__init_system_xstate(unsigned int legacy_size)
873891
pr_info("x86/fpu: Enabled xstate features 0x%llx, context size is %d bytes, using '%s' format.\n",
874892
fpu_kernel_cfg.max_features,
875893
fpu_kernel_cfg.max_size,
876-
boot_cpu_has(X86_FEATURE_XSAVES) ? "compacted" : "standard");
894+
boot_cpu_has(X86_FEATURE_XCOMPACTED) ? "compacted" : "standard");
877895
return;
878896

879897
out_disable:
@@ -917,7 +935,7 @@ static void *__raw_xsave_addr(struct xregs_state *xsave, int xfeature_nr)
917935
if (WARN_ON_ONCE(!xfeature_enabled(xfeature_nr)))
918936
return NULL;
919937

920-
if (cpu_feature_enabled(X86_FEATURE_XSAVES)) {
938+
if (cpu_feature_enabled(X86_FEATURE_XCOMPACTED)) {
921939
if (WARN_ON_ONCE(!(xcomp_bv & BIT_ULL(xfeature_nr))))
922940
return NULL;
923941
}
@@ -1215,7 +1233,7 @@ static int copy_uabi_to_xstate(struct fpstate *fpstate, const void *kbuf,
12151233
}
12161234

12171235
for (i = 0; i < XFEATURE_MAX; i++) {
1218-
u64 mask = ((u64)1 << i);
1236+
mask = BIT_ULL(i);
12191237

12201238
if (hdr.xfeatures & mask) {
12211239
void *dst = __raw_xsave_addr(xsave, i);
@@ -1525,7 +1543,7 @@ static int __xstate_request_perm(u64 permitted, u64 requested, bool guest)
15251543
* vendors into extending XFD for the pre AMX states, especially
15261544
* AVX512.
15271545
*/
1528-
bool compacted = cpu_feature_enabled(X86_FEATURE_XSAVES);
1546+
bool compacted = cpu_feature_enabled(X86_FEATURE_XCOMPACTED);
15291547
struct fpu *fpu = &current->group_leader->thread.fpu;
15301548
struct fpu_state_perm *perm;
15311549
unsigned int ksize, usize;

arch/x86/kernel/fpu/xstate.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ static inline void xstate_init_xcomp_bv(struct xregs_state *xsave, u64 mask)
1616
* XRSTORS requires these bits set in xcomp_bv, or it will
1717
* trigger #GP:
1818
*/
19-
if (cpu_feature_enabled(X86_FEATURE_XSAVES))
19+
if (cpu_feature_enabled(X86_FEATURE_XCOMPACTED))
2020
xsave->header.xcomp_bv = mask | XCOMP_BV_COMPACTED_FORMAT;
2121
}
2222

@@ -79,6 +79,7 @@ static inline u64 xfeatures_mask_independent(void)
7979
/* These macros all use (%edi)/(%rdi) as the single memory argument. */
8080
#define XSAVE ".byte " REX_PREFIX "0x0f,0xae,0x27"
8181
#define XSAVEOPT ".byte " REX_PREFIX "0x0f,0xae,0x37"
82+
#define XSAVEC ".byte " REX_PREFIX "0x0f,0xc7,0x27"
8283
#define XSAVES ".byte " REX_PREFIX "0x0f,0xc7,0x2f"
8384
#define XRSTOR ".byte " REX_PREFIX "0x0f,0xae,0x2f"
8485
#define XRSTORS ".byte " REX_PREFIX "0x0f,0xc7,0x1f"
@@ -97,9 +98,11 @@ static inline u64 xfeatures_mask_independent(void)
9798
: "memory")
9899

99100
/*
100-
* If XSAVES is enabled, it replaces XSAVEOPT because it supports a compact
101-
* format and supervisor states in addition to modified optimization in
102-
* XSAVEOPT.
101+
* If XSAVES is enabled, it replaces XSAVEC because it supports supervisor
102+
* states in addition to XSAVEC.
103+
*
104+
* Otherwise if XSAVEC is enabled, it replaces XSAVEOPT because it supports
105+
* compacted storage format in addition to XSAVEOPT.
103106
*
104107
* Otherwise, if XSAVEOPT is enabled, XSAVEOPT replaces XSAVE because XSAVEOPT
105108
* supports modified optimization which is not supported by XSAVE.
@@ -111,8 +114,9 @@ static inline u64 xfeatures_mask_independent(void)
111114
* address of the instruction where we might get an exception at.
112115
*/
113116
#define XSTATE_XSAVE(st, lmask, hmask, err) \
114-
asm volatile(ALTERNATIVE_2(XSAVE, \
117+
asm volatile(ALTERNATIVE_3(XSAVE, \
115118
XSAVEOPT, X86_FEATURE_XSAVEOPT, \
119+
XSAVEC, X86_FEATURE_XSAVEC, \
116120
XSAVES, X86_FEATURE_XSAVES) \
117121
"\n" \
118122
"xor %[err], %[err]\n" \

0 commit comments

Comments
 (0)