From 3ff1030ea7d40e62edfe09b44dbdba44def5072a Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Mon, 18 Aug 2025 15:44:44 +0100 Subject: [PATCH] x86/fsgsbase: Make SHADOW_GS accesses safe under FRED Under FRED, the SWAPGS instruction is disallowed. Therefore we must use the MSR path instead. read_registers() is in the show_registers() path, so this change allows Xen to render it's current state without suffering #UD (and recursing until the stack guard page is hit). All hardware with FRED is expected to have some kind of non-serialising access to these registers. Signed-off-by: Andrew Cooper Reviewed-by: Jan Beulich --- xen/arch/x86/include/asm/fsgsbase.h | 8 ++++++-- xen/arch/x86/traps.c | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/xen/arch/x86/include/asm/fsgsbase.h b/xen/arch/x86/include/asm/fsgsbase.h index 24862a6bfe..5faa3a3243 100644 --- a/xen/arch/x86/include/asm/fsgsbase.h +++ b/xen/arch/x86/include/asm/fsgsbase.h @@ -79,7 +79,9 @@ static inline unsigned long read_gs_base(void) static inline unsigned long read_gs_shadow(void) { - if ( read_cr4() & X86_CR4_FSGSBASE ) + unsigned long cr4 = read_cr4(); + + if ( !(cr4 & X86_CR4_FRED) && (cr4 & X86_CR4_FSGSBASE) ) return __rdgs_shadow(); else return rdmsr(MSR_SHADOW_GS_BASE); @@ -103,7 +105,9 @@ static inline void write_gs_base(unsigned long base) static inline void write_gs_shadow(unsigned long base) { - if ( read_cr4() & X86_CR4_FSGSBASE ) + unsigned long cr4 = read_cr4(); + + if ( !(cr4 & X86_CR4_FRED) && (cr4 & X86_CR4_FSGSBASE) ) __wrgs_shadow(base); else wrmsrns(MSR_SHADOW_GS_BASE, base); diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index f621b99a5f..3c01c5eb53 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -123,7 +123,7 @@ static void read_registers(struct extra_state *state) * invalidate the read_cr4() address calculation (really cpu_info->cr4 * under the hood), forcing the cr4 check to be re-evaluated every time. */ - if ( state->cr4 & X86_CR4_FSGSBASE ) + if ( !(state->cr4 & X86_CR4_FRED) && (state->cr4 & X86_CR4_FSGSBASE) ) { state->fsb = __rdfsbase(); state->gsb = __rdgsbase();