Skip to content

Commit 8b05b3c

Browse files
yang-weijianghansendc
authored andcommitted
x86/fpu/xstate: Add CET supervisor xfeature support as a guest-only feature
== Background == CET defines two register states: CET user, which includes user-mode control registers, and CET supervisor, which consists of shadow-stack pointers for privilege levels 0-2. Current kernels disable shadow stacks in kernel mode, making the CET supervisor state unused and eliminating the need for context switching. == Problem == To virtualize CET for guests, KVM must accurately emulate hardware behavior. A key challenge arises because there is no CPUID flag to indicate that shadow stack is supported only in user mode. Therefore, KVM cannot assume guests will not enable shadow stacks in kernel mode and must preserve the CET supervisor state of vCPUs. == Solution == An initial proposal to manually save and restore CET supervisor states using raw RDMSR/WRMSR in KVM was rejected due to performance concerns and its impact on KVM's ABI. Instead, leveraging the kernel's FPU infrastructure for context switching was favored [1]. The main question then became whether to enable the CET supervisor state globally for all processes or restrict it to vCPU processes. This decision involves a trade-off between a 24-byte XSTATE buffer waste for all non-vCPU processes and approximately 100 lines of code complexity in the kernel [2]. The agreed approach is to first try this optimal solution [3], i.e., restricting the CET supervisor state to guest FPUs only and eliminating unnecessary space waste. The guest-only xfeature infrastructure has already been added. Now, introduce CET supervisor xstate support as the first guest-only feature to prepare for the upcoming CET virtualization in KVM. Signed-off-by: Yang Weijiang <[email protected]> Signed-off-by: Chao Gao <[email protected]> Signed-off-by: Dave Hansen <[email protected]> Reviewed-by: Rick Edgecombe <[email protected]> Reviewed-by: Maxim Levitsky <[email protected]> Reviewed-by: John Allen <[email protected]> Link: https://lore.kernel.org/kvm/[email protected]/ [1] Link: https://lore.kernel.org/kvm/[email protected]/ [2] Link: https://lore.kernel.org/kvm/[email protected]/ [3] Link: https://lore.kernel.org/all/20250522151031.426788-7-chao.gao%40intel.com
1 parent 151bf23 commit 8b05b3c

File tree

3 files changed

+18
-6
lines changed

3 files changed

+18
-6
lines changed

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

Lines changed: 12 additions & 2 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).

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
#define XFEATURE_MASK_USER_DYNAMIC XFEATURE_MASK_XTILE_DATA
4848

4949
/* Supervisor features which are enabled only in guest FPUs */
50-
#define XFEATURE_MASK_GUEST_SUPERVISOR 0
50+
#define XFEATURE_MASK_GUEST_SUPERVISOR XFEATURE_MASK_CET_KERNEL
5151

5252
/* All currently supported supervisor features */
5353
#define XFEATURE_MASK_SUPERVISOR_SUPPORTED (XFEATURE_MASK_PASID | \
@@ -79,8 +79,7 @@
7979
* Unsupported supervisor features. When a supervisor feature in this mask is
8080
* supported in the future, move it to the supported supervisor feature mask.
8181
*/
82-
#define XFEATURE_MASK_SUPERVISOR_UNSUPPORTED (XFEATURE_MASK_PT | \
83-
XFEATURE_MASK_CET_KERNEL)
82+
#define XFEATURE_MASK_SUPERVISOR_UNSUPPORTED (XFEATURE_MASK_PT)
8483

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

arch/x86/kernel/fpu/xstate.c

Lines changed: 4 additions & 1 deletion
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:

0 commit comments

Comments
 (0)