Re: [PATCH v9 06/22] x86/cea: Export __this_cpu_ist_top_va() to KVM
From: Xin Li
Date: Mon Mar 09 2026 - 19:30:57 EST
> On Mar 9, 2026, at 8:24 AM, Sean Christopherson <seanjc@xxxxxxxxxx> wrote:
>
> 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.
It’s a bit weird to pass a u32 MSR index to this_cpu_fred_rsp().
We will want to rename it to this_cpu_fred_xsp() when FRED shadow stack
is supported.
>
>> #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.
I thought about it and checked AMD SVM FRED patches, but wasn't able to
find host RSPs get set explicitly during vCPU migration.
But anyway, I will make the change.
>
>> +
>> /* 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));
>> }