From e1d84ea373de0d9bf4195cbf29d9fcf46c02d1ca Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Tue, 12 Aug 2025 12:48:06 +0100 Subject: [PATCH] x86/fsgsbase: Improve code generation in read_registers() It turns out that using the higher level helpers adjacent like this leads to terrible code generation. Due to -fno-strict-aliasing, the store into state invalidates the read_cr4() address calculation (which is really cpu_info->cr4 under the hood), meaning that it can't be hoisted. As a result we get "locate the top of stack block, get cr4, and see if FSGSBASE is set" repeated 3 times, and an unreasonable number of basic blocks. Hoist the calculation manually, which results in two basic blocks. Signed-off-by: Andrew Cooper Acked-by: Jan Beulich (cherry picked from commit 42a0709f374966573851236589583c86b603e704) --- xen/arch/x86/traps.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 6f6ce387a1..5a0a16a6b3 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -118,9 +118,24 @@ static void read_registers(struct extra_state *state) state->cr3 = read_cr3(); state->cr4 = read_cr4(); - state->fsb = read_fs_base(); - state->gsb = read_gs_base(); - state->gss = read_gs_shadow(); + /* + * Help the optimiser out by opencoding read_*_base() and rearranging the + * expression. -fno-strict-aliasing causes the store into state to + * 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 ) + { + state->fsb = __rdfsbase(); + state->gsb = __rdgsbase(); + state->gss = __rdgs_shadow(); + } + else + { + state->fsb = rdmsr(MSR_FS_BASE); + state->gsb = rdmsr(MSR_GS_BASE); + state->gss = rdmsr(MSR_SHADOW_GS_BASE); + } asm ( "mov %%ds, %0" : "=m" (state->ds) ); asm ( "mov %%es, %0" : "=m" (state->es) );