Skip to content

Commit 0c23929

Browse files
committed
Merge tag 'x86-fpu-2025-07-29' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 FPU updates from Ingo Molnar: - Most of the changes are related to the implementation of CET supervisor state support for guests, and its preparatory changes (Chao Gao) - Improve/fix the debug output for unexpected FPU exceptions (Dave Hansen) * tag 'x86-fpu-2025-07-29' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/fpu: Delay instruction pointer fixup until after warning x86/fpu/xstate: Add CET supervisor xfeature support as a guest-only feature x86/fpu/xstate: Introduce "guest-only" supervisor xfeature set x86/fpu: Remove xfd argument from __fpstate_reset() x86/fpu: Initialize guest fpstate and FPU pseudo container from guest defaults x86/fpu: Initialize guest FPU permissions from guest defaults x86/fpu/xstate: Differentiate default features for host and guest FPUs
2 parents 4dd39dd + 1cec9ac commit 0c23929

File tree

6 files changed

+124
-33
lines changed

6 files changed

+124
-33
lines changed

arch/x86/include/asm/fpu/types.h

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ enum xfeature {
118118
XFEATURE_PKRU,
119119
XFEATURE_PASID,
120120
XFEATURE_CET_USER,
121-
XFEATURE_CET_KERNEL_UNUSED,
121+
XFEATURE_CET_KERNEL,
122122
XFEATURE_RSRVD_COMP_13,
123123
XFEATURE_RSRVD_COMP_14,
124124
XFEATURE_LBR,
@@ -142,7 +142,7 @@ enum xfeature {
142142
#define XFEATURE_MASK_PKRU (1 << XFEATURE_PKRU)
143143
#define XFEATURE_MASK_PASID (1 << XFEATURE_PASID)
144144
#define XFEATURE_MASK_CET_USER (1 << XFEATURE_CET_USER)
145-
#define XFEATURE_MASK_CET_KERNEL (1 << XFEATURE_CET_KERNEL_UNUSED)
145+
#define XFEATURE_MASK_CET_KERNEL (1 << XFEATURE_CET_KERNEL)
146146
#define XFEATURE_MASK_LBR (1 << XFEATURE_LBR)
147147
#define XFEATURE_MASK_XTILE_CFG (1 << XFEATURE_XTILE_CFG)
148148
#define XFEATURE_MASK_XTILE_DATA (1 << XFEATURE_XTILE_DATA)
@@ -268,6 +268,16 @@ struct cet_user_state {
268268
u64 user_ssp;
269269
};
270270

271+
/*
272+
* State component 12 is Control-flow Enforcement supervisor states.
273+
* This state includes SSP pointers for privilege levels 0 through 2.
274+
*/
275+
struct cet_supervisor_state {
276+
u64 pl0_ssp;
277+
u64 pl1_ssp;
278+
u64 pl2_ssp;
279+
} __packed;
280+
271281
/*
272282
* State component 15: Architectural LBR configuration state.
273283
* The size of Arch LBR state depends on the number of LBRs (lbr_depth).
@@ -551,6 +561,31 @@ struct fpu_guest {
551561
struct fpstate *fpstate;
552562
};
553563

564+
/*
565+
* FPU state configuration data for fpu_guest.
566+
* Initialized at boot time. Read only after init.
567+
*/
568+
struct vcpu_fpu_config {
569+
/*
570+
* @size:
571+
*
572+
* The default size of the register state buffer in guest FPUs.
573+
* Includes all supported features except independent managed
574+
* features and features which have to be requested by user space
575+
* before usage.
576+
*/
577+
unsigned int size;
578+
579+
/*
580+
* @features:
581+
*
582+
* The default supported features bitmap in guest FPUs. Does not
583+
* include independent managed features and features which have to
584+
* be requested by user space before usage.
585+
*/
586+
u64 features;
587+
};
588+
554589
/*
555590
* FPU state configuration data. Initialized at boot time. Read only after init.
556591
*/
@@ -567,8 +602,9 @@ struct fpu_state_config {
567602
* @default_size:
568603
*
569604
* The default size of the register state buffer. Includes all
570-
* supported features except independent managed features and
571-
* features which have to be requested by user space before usage.
605+
* supported features except independent managed features,
606+
* guest-only features and features which have to be requested by
607+
* user space before usage.
572608
*/
573609
unsigned int default_size;
574610

@@ -584,8 +620,8 @@ struct fpu_state_config {
584620
* @default_features:
585621
*
586622
* The default supported features bitmap. Does not include
587-
* independent managed features and features which have to
588-
* be requested by user space before usage.
623+
* independent managed features, guest-only features and features
624+
* which have to be requested by user space before usage.
589625
*/
590626
u64 default_features;
591627
/*
@@ -606,5 +642,6 @@ struct fpu_state_config {
606642

607643
/* FPU state configuration information */
608644
extern struct fpu_state_config fpu_kernel_cfg, fpu_user_cfg;
645+
extern struct vcpu_fpu_config guest_default_cfg;
609646

610647
#endif /* _ASM_X86_FPU_TYPES_H */

arch/x86/include/asm/fpu/xstate.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,13 @@
4646
/* Features which are dynamically enabled for a process on request */
4747
#define XFEATURE_MASK_USER_DYNAMIC XFEATURE_MASK_XTILE_DATA
4848

49+
/* Supervisor features which are enabled only in guest FPUs */
50+
#define XFEATURE_MASK_GUEST_SUPERVISOR XFEATURE_MASK_CET_KERNEL
51+
4952
/* All currently supported supervisor features */
5053
#define XFEATURE_MASK_SUPERVISOR_SUPPORTED (XFEATURE_MASK_PASID | \
51-
XFEATURE_MASK_CET_USER)
54+
XFEATURE_MASK_CET_USER | \
55+
XFEATURE_MASK_GUEST_SUPERVISOR)
5256

5357
/*
5458
* A supervisor state component may not always contain valuable information,
@@ -75,8 +79,7 @@
7579
* Unsupported supervisor features. When a supervisor feature in this mask is
7680
* supported in the future, move it to the supported supervisor feature mask.
7781
*/
78-
#define XFEATURE_MASK_SUPERVISOR_UNSUPPORTED (XFEATURE_MASK_PT | \
79-
XFEATURE_MASK_CET_KERNEL)
82+
#define XFEATURE_MASK_SUPERVISOR_UNSUPPORTED (XFEATURE_MASK_PT)
8083

8184
/* All supervisor states including supported and unsupported states. */
8285
#define XFEATURE_MASK_SUPERVISOR_ALL (XFEATURE_MASK_SUPERVISOR_SUPPORTED | \

arch/x86/kernel/fpu/core.c

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ DEFINE_PER_CPU(u64, xfd_state);
3737
/* The FPU state configuration data for kernel and user space */
3838
struct fpu_state_config fpu_kernel_cfg __ro_after_init;
3939
struct fpu_state_config fpu_user_cfg __ro_after_init;
40+
struct vcpu_fpu_config guest_default_cfg __ro_after_init;
4041

4142
/*
4243
* Represents the initial FPU state. It's mostly (but not completely) zeroes,
@@ -217,7 +218,7 @@ void fpu_reset_from_exception_fixup(void)
217218
}
218219

219220
#if IS_ENABLED(CONFIG_KVM)
220-
static void __fpstate_reset(struct fpstate *fpstate, u64 xfd);
221+
static void __fpstate_reset(struct fpstate *fpstate);
221222

222223
static void fpu_lock_guest_permissions(void)
223224
{
@@ -242,19 +243,21 @@ bool fpu_alloc_guest_fpstate(struct fpu_guest *gfpu)
242243
struct fpstate *fpstate;
243244
unsigned int size;
244245

245-
size = fpu_kernel_cfg.default_size + ALIGN(offsetof(struct fpstate, regs), 64);
246+
size = guest_default_cfg.size + ALIGN(offsetof(struct fpstate, regs), 64);
247+
246248
fpstate = vzalloc(size);
247249
if (!fpstate)
248250
return false;
249251

250-
/* Leave xfd to 0 (the reset value defined by spec) */
251-
__fpstate_reset(fpstate, 0);
252-
fpstate_init_user(fpstate);
252+
/* Initialize indicators to reflect properties of the fpstate */
253253
fpstate->is_valloc = true;
254254
fpstate->is_guest = true;
255255

256+
__fpstate_reset(fpstate);
257+
fpstate_init_user(fpstate);
258+
256259
gfpu->fpstate = fpstate;
257-
gfpu->xfeatures = fpu_kernel_cfg.default_features;
260+
gfpu->xfeatures = guest_default_cfg.features;
258261

259262
/*
260263
* KVM sets the FP+SSE bits in the XSAVE header when copying FPU state
@@ -541,28 +544,50 @@ void fpstate_init_user(struct fpstate *fpstate)
541544
fpstate_init_fstate(fpstate);
542545
}
543546

544-
static void __fpstate_reset(struct fpstate *fpstate, u64 xfd)
547+
static void __fpstate_reset(struct fpstate *fpstate)
545548
{
546-
/* Initialize sizes and feature masks */
547-
fpstate->size = fpu_kernel_cfg.default_size;
549+
/*
550+
* Supervisor features (and thus sizes) may diverge between guest
551+
* FPUs and host FPUs, as some supervisor features are supported
552+
* for guests despite not being utilized by the host. User
553+
* features and sizes are always identical, which allows for
554+
* common guest and userspace ABI.
555+
*
556+
* For the host, set XFD to the kernel's desired initialization
557+
* value. For guests, set XFD to its architectural RESET value.
558+
*/
559+
if (fpstate->is_guest) {
560+
fpstate->size = guest_default_cfg.size;
561+
fpstate->xfeatures = guest_default_cfg.features;
562+
fpstate->xfd = 0;
563+
} else {
564+
fpstate->size = fpu_kernel_cfg.default_size;
565+
fpstate->xfeatures = fpu_kernel_cfg.default_features;
566+
fpstate->xfd = init_fpstate.xfd;
567+
}
568+
548569
fpstate->user_size = fpu_user_cfg.default_size;
549-
fpstate->xfeatures = fpu_kernel_cfg.default_features;
550570
fpstate->user_xfeatures = fpu_user_cfg.default_features;
551-
fpstate->xfd = xfd;
552571
}
553572

554573
void fpstate_reset(struct fpu *fpu)
555574
{
556575
/* Set the fpstate pointer to the default fpstate */
557576
fpu->fpstate = &fpu->__fpstate;
558-
__fpstate_reset(fpu->fpstate, init_fpstate.xfd);
577+
__fpstate_reset(fpu->fpstate);
559578

560579
/* Initialize the permission related info in fpu */
561580
fpu->perm.__state_perm = fpu_kernel_cfg.default_features;
562581
fpu->perm.__state_size = fpu_kernel_cfg.default_size;
563582
fpu->perm.__user_state_size = fpu_user_cfg.default_size;
564-
/* Same defaults for guests */
565-
fpu->guest_perm = fpu->perm;
583+
584+
fpu->guest_perm.__state_perm = guest_default_cfg.features;
585+
fpu->guest_perm.__state_size = guest_default_cfg.size;
586+
/*
587+
* User features and sizes are always identical between host and
588+
* guest FPUs, which allows for common guest and userspace ABI.
589+
*/
590+
fpu->guest_perm.__user_state_size = fpu_user_cfg.default_size;
566591
}
567592

568593
static inline void fpu_inherit_perms(struct fpu *dst_fpu)

arch/x86/kernel/fpu/init.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ static void __init fpu__init_system_xstate_size_legacy(void)
205205
fpu_kernel_cfg.default_size = size;
206206
fpu_user_cfg.max_size = size;
207207
fpu_user_cfg.default_size = size;
208+
guest_default_cfg.size = size;
208209
}
209210

210211
/*

arch/x86/kernel/fpu/xstate.c

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ static const char *xfeature_names[] =
5757
"Protection Keys User registers",
5858
"PASID state",
5959
"Control-flow User registers",
60-
"Control-flow Kernel registers (unused)",
60+
"Control-flow Kernel registers (KVM only)",
6161
"unknown xstate feature",
6262
"unknown xstate feature",
6363
"unknown xstate feature",
@@ -81,6 +81,7 @@ static unsigned short xsave_cpuid_features[] __initdata = {
8181
[XFEATURE_PKRU] = X86_FEATURE_OSPKE,
8282
[XFEATURE_PASID] = X86_FEATURE_ENQCMD,
8383
[XFEATURE_CET_USER] = X86_FEATURE_SHSTK,
84+
[XFEATURE_CET_KERNEL] = X86_FEATURE_SHSTK,
8485
[XFEATURE_XTILE_CFG] = X86_FEATURE_AMX_TILE,
8586
[XFEATURE_XTILE_DATA] = X86_FEATURE_AMX_TILE,
8687
[XFEATURE_APX] = X86_FEATURE_APX,
@@ -372,6 +373,7 @@ static __init void os_xrstor_booting(struct xregs_state *xstate)
372373
XFEATURE_MASK_BNDCSR | \
373374
XFEATURE_MASK_PASID | \
374375
XFEATURE_MASK_CET_USER | \
376+
XFEATURE_MASK_CET_KERNEL | \
375377
XFEATURE_MASK_XTILE | \
376378
XFEATURE_MASK_APX)
377379

@@ -573,6 +575,7 @@ static bool __init check_xstate_against_struct(int nr)
573575
case XFEATURE_PASID: return XCHECK_SZ(sz, nr, struct ia32_pasid_state);
574576
case XFEATURE_XTILE_CFG: return XCHECK_SZ(sz, nr, struct xtile_cfg);
575577
case XFEATURE_CET_USER: return XCHECK_SZ(sz, nr, struct cet_user_state);
578+
case XFEATURE_CET_KERNEL: return XCHECK_SZ(sz, nr, struct cet_supervisor_state);
576579
case XFEATURE_APX: return XCHECK_SZ(sz, nr, struct apx_state);
577580
case XFEATURE_XTILE_DATA: check_xtile_data_against_struct(sz); return true;
578581
default:
@@ -743,6 +746,9 @@ static int __init init_xstate_size(void)
743746
fpu_user_cfg.default_size =
744747
xstate_calculate_size(fpu_user_cfg.default_features, false);
745748

749+
guest_default_cfg.size =
750+
xstate_calculate_size(guest_default_cfg.features, compacted);
751+
746752
return 0;
747753
}
748754

@@ -763,6 +769,7 @@ static void __init fpu__init_disable_system_xstate(unsigned int legacy_size)
763769
fpu_kernel_cfg.default_size = legacy_size;
764770
fpu_user_cfg.max_size = legacy_size;
765771
fpu_user_cfg.default_size = legacy_size;
772+
guest_default_cfg.size = legacy_size;
766773

767774
/*
768775
* Prevent enabling the static branch which enables writes to the
@@ -773,6 +780,24 @@ static void __init fpu__init_disable_system_xstate(unsigned int legacy_size)
773780
fpstate_reset(x86_task_fpu(current));
774781
}
775782

783+
static u64 __init host_default_mask(void)
784+
{
785+
/*
786+
* Exclude dynamic features (require userspace opt-in) and features
787+
* that are supported only for KVM guests.
788+
*/
789+
return ~((u64)XFEATURE_MASK_USER_DYNAMIC | XFEATURE_MASK_GUEST_SUPERVISOR);
790+
}
791+
792+
static u64 __init guest_default_mask(void)
793+
{
794+
/*
795+
* Exclude dynamic features, which require userspace opt-in even
796+
* for KVM guests.
797+
*/
798+
return ~(u64)XFEATURE_MASK_USER_DYNAMIC;
799+
}
800+
776801
/*
777802
* Enable and initialize the xsave feature.
778803
* Called once per system bootup.
@@ -855,12 +880,13 @@ void __init fpu__init_system_xstate(unsigned int legacy_size)
855880
fpu_user_cfg.max_features = fpu_kernel_cfg.max_features;
856881
fpu_user_cfg.max_features &= XFEATURE_MASK_USER_SUPPORTED;
857882

858-
/* Clean out dynamic features from default */
859-
fpu_kernel_cfg.default_features = fpu_kernel_cfg.max_features;
860-
fpu_kernel_cfg.default_features &= ~XFEATURE_MASK_USER_DYNAMIC;
861-
862-
fpu_user_cfg.default_features = fpu_user_cfg.max_features;
863-
fpu_user_cfg.default_features &= ~XFEATURE_MASK_USER_DYNAMIC;
883+
/*
884+
* Now, given maximum feature set, determine default values by
885+
* applying default masks.
886+
*/
887+
fpu_kernel_cfg.default_features = fpu_kernel_cfg.max_features & host_default_mask();
888+
fpu_user_cfg.default_features = fpu_user_cfg.max_features & host_default_mask();
889+
guest_default_cfg.features = fpu_kernel_cfg.max_features & guest_default_mask();
864890

865891
/* Store it for paranoia check at the end */
866892
xfeatures = fpu_kernel_cfg.max_features;

arch/x86/mm/extable.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,13 +122,12 @@ static bool ex_handler_sgx(const struct exception_table_entry *fixup,
122122
static bool ex_handler_fprestore(const struct exception_table_entry *fixup,
123123
struct pt_regs *regs)
124124
{
125-
regs->ip = ex_fixup_addr(fixup);
126-
127125
WARN_ONCE(1, "Bad FPU state detected at %pB, reinitializing FPU registers.",
128126
(void *)instruction_pointer(regs));
129127

130128
fpu_reset_from_exception_fixup();
131-
return true;
129+
130+
return ex_handler_default(fixup, regs);
132131
}
133132

134133
/*

0 commit comments

Comments
 (0)