[RFC][PATCH 23/24] x86/entry: Populate FRED register for user=>kernel transitions
From: Dave Hansen
Date: Wed Oct 21 2026 - 15:57:32 EST
== Background ==
All the shadow stack work up until now has focused on running inside
the kernel. The work has manipulated the actual shadow stack pointer
(SSP) and prepared FRED hardware to update SSP across kernel=>kernel
event boundaries (the SSP values stashed in FRED_SSP[123]). Note that
the shadow stacks for event handling are fixed for a given CPU and
never change.
Once in place, this lets the kernel move SSP around for normal
CALL/RET operations and also handle FRED-delivered events like
interrupts and faults.
But, this all only covers kernel=>kernel event boundaries like when
the kernel takes an NMI or a page fault.
== Problem ==
There is currently no handling for user=>kernel transitions. Those
events must use the active kernel task's SSP which is *not* constant
on each CPU.
== Solution ==
Point FRED_SSP0 to the active kernel task's SSP before returning to
userspace. This ensures that the FRED hardware will set SSP to the
correct per-task value when doing the user=>kernel transition.
Mirror FRED RSP0 handling for SSP0. Avoid setting FRED_SSP0 during
context switching itself. It is not necessary to have a "good"
FRED_SSP0 value when running the kernel, only userspace.
---
b/arch/x86/include/asm/entry-common.h | 2 +-
b/arch/x86/include/asm/fred.h | 8 ++++++++
2 files changed, 9 insertions(+), 1 deletion(-)
diff -puN arch/x86/include/asm/entry-common.h~fred_update_ssp0 arch/x86/include/asm/entry-common.h
--- a/arch/x86/include/asm/entry-common.h~fred_update_ssp0 2026-10-21 12:36:44.081892846 -0700
+++ b/arch/x86/include/asm/entry-common.h 2026-10-21 12:36:44.086892856 -0700
@@ -65,7 +65,7 @@ static inline void arch_exit_to_user_mod
arch_exit_work(ti_work);
fred_update_rsp0();
-
+ fred_update_ssp0();
#ifdef CONFIG_COMPAT
/*
* Compat syscalls set TS_COMPAT. Make sure we clear it before
diff -puN arch/x86/include/asm/fred.h~fred_update_ssp0 arch/x86/include/asm/fred.h
--- a/arch/x86/include/asm/fred.h~fred_update_ssp0 2026-10-21 12:36:44.083892850 -0700
+++ b/arch/x86/include/asm/fred.h 2026-10-21 12:36:44.086892856 -0700
@@ -105,6 +105,13 @@ static __always_inline void fred_update_
__this_cpu_write(fred_rsp0, rsp0);
}
}
+static __always_inline void fred_update_ssp0(void)
+{
+#ifdef CONFIG_X86_KERN_SHADOW_STACK
+ if (current->thread.kshstk_ssp)
+ wrmsrns(MSR_IA32_FRED_SSP0, (u64)task_shstk_top(current));
+#endif
+}
#else /* CONFIG_X86_FRED */
static __always_inline unsigned long fred_event_data(struct pt_regs *regs) { return 0; }
static inline void cpu_init_fred_exceptions(void) { }
@@ -112,6 +119,7 @@ static inline void cpu_init_fred_rsps(vo
static inline void fred_complete_exception_setup(void) { }
static inline void fred_sync_rsp0(unsigned long rsp0) { }
static inline void fred_update_rsp0(void) { }
+static inline void fred_update_ssp0(void) { }
#endif /* CONFIG_X86_FRED */
#endif /* !__ASSEMBLER__ */
_