Re: [PATCH v9 06/22] x86/cea: Export __this_cpu_ist_top_va() to KVM
From: Sean Christopherson
Date: Mon Mar 09 2026 - 11:24:31 EST
On Fri, Mar 06, 2026, Xin Li wrote:
> > On Jan 30, 2026, at 5:46 AM, Borislav Petkov <bp@xxxxxxxxx> wrote:
> diff --git a/arch/x86/include/asm/fred.h b/arch/x86/include/asm/fred.h
> index 2bb65677c079..7eea65bfc838 100644
> --- a/arch/x86/include/asm/fred.h
> +++ b/arch/x86/include/asm/fred.h
> @@ -35,6 +35,13 @@
>
> #ifndef __ASSEMBLER__
>
> +enum fred_stack_level {
> + FRED_STACK_LEVEL_0,
> + FRED_STACK_LEVEL_1,
> + FRED_STACK_LEVEL_2,
> + FRED_STACK_LEVEL_3
Why bother with a layer of indirection and more enums? Just pivot on the MSR
index.
> #ifdef CONFIG_X86_FRED
> #include <linux/kernel.h>
> #include <linux/sched/task_stack.h>
> @@ -105,6 +112,8 @@ static __always_inline void fred_update_rsp0(void)
> __this_cpu_write(fred_rsp0, rsp0);
> }
> }
> +
> +unsigned long this_cpu_fred_rsp(enum fred_stack_level lvl);
> #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) { }
> @@ -113,6 +122,7 @@ static inline void fred_complete_exception_setup(void) { }
> static inline void fred_entry_from_kvm(unsigned int type, unsigned int vector) { }
> static inline void fred_sync_rsp0(unsigned long rsp0) { }
> static inline void fred_update_rsp0(void) { }
> +static unsigned long this_cpu_fred_rsp(enum fred_stack_level lvl) { return 0; }
> #endif /* CONFIG_X86_FRED */
> #endif /* !__ASSEMBLER__ */
>
> diff --git a/arch/x86/kernel/fred.c b/arch/x86/kernel/fred.c
> index 433c4a6f1773..363c53701012 100644
> --- a/arch/x86/kernel/fred.c
> +++ b/arch/x86/kernel/fred.c
> @@ -72,6 +72,23 @@ void cpu_init_fred_exceptions(void)
> setup_clear_cpu_cap(X86_FEATURE_SYSCALL32);
> }
>
> +unsigned long this_cpu_fred_rsp(enum fred_stack_level lvl)
> +{
> + switch (lvl) {
> + case FRED_STACK_LEVEL_0:
> + return __this_cpu_read(fred_rsp0);
> + case FRED_STACK_LEVEL_1:
> + return __this_cpu_ist_top_va(ESTACK_DB);
> + case FRED_STACK_LEVEL_2:
> + return __this_cpu_ist_top_va(ESTACK_NMI);
> + case FRED_STACK_LEVEL_3:
> + return __this_cpu_ist_top_va(ESTACK_DF);
> + default:
> + BUG();
> + }
> +}
> +EXPORT_SYMBOL_FOR_MODULES(this_cpu_fred_rsp, "kvm-intel");
Meh, just do EXPORT_SYMBOL_FOR_KVM so that there's no export when KVM_X86=y|n.
And it's possible AMD may need to grab the MSRs too.
> +
> /* Must be called after setup_cpu_entry_areas() */
> void cpu_init_fred_rsps(void)
> {
> @@ -87,7 +104,7 @@ void cpu_init_fred_rsps(void)
> FRED_STKLVL(X86_TRAP_DF, FRED_DF_STACK_LEVEL));
>
> /* The FRED equivalents to IST stacks... */
> - wrmsrq(MSR_IA32_FRED_RSP1, __this_cpu_ist_top_va(ESTACK_DB));
> - wrmsrq(MSR_IA32_FRED_RSP2, __this_cpu_ist_top_va(ESTACK_NMI));
> - wrmsrq(MSR_IA32_FRED_RSP3, __this_cpu_ist_top_va(ESTACK_DF));
> + wrmsrq(MSR_IA32_FRED_RSP1, this_cpu_fred_rsp(FRED_STACK_LEVEL_1));
> + wrmsrq(MSR_IA32_FRED_RSP2, this_cpu_fred_rsp(FRED_STACK_LEVEL_2));
> + wrmsrq(MSR_IA32_FRED_RSP3, this_cpu_fred_rsp(FRED_STACK_LEVEL_3));
> }