Save a WRMSR GS.base?
From: Borislav Petkov
Date: Wed Jun 03 2026 - 21:54:20 EST
Hi,
so here:
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index b85e715ebb30..ffa894bdb4ee 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -400,7 +400,9 @@ static __always_inline void x86_fsgsbase_load(struct thread_struct *prev,
/* Update the bases. */
wrfsbase(next->fsbase);
- __wrgsbase_inactive(next->gsbase);
+
+ if (!cpu_feature_enabled(X86_FEATURE_LKGS))
+ __wrgsbase_inactive(next->gsbase);
} else {
load_seg_legacy(prev->fsindex, prev->fsbase,
next->fsindex, next->fsbase, FS);
a couple of lines above in that function we have:
if (unlikely(prev->gsindex || next->gsindex))
loadseg(GS, next->gsindex);
which, on a FRED machine, would do LKGS. Now that insn does:
GS.selector := SRC;
GS.attributes := descriptor.attributes;
IA32_KERNEL_GS_BASE := descriptor.base; // bits 63:32 cleared
so I can save myself the __wrgsbase_inactive() which ends up doing WRMSR
GS.base.
Right? I.e., the diff above.
We're also not doing the optimization of checking whether prev.GS.base and
next.GS.base are equal. I see them both 0 in a trace here but I guess
luserpace can change them so I guess we wanna overwrite GS.base on context
switch unconditionally.
But LKGS does that for us so we don't need the WRMSR GS.base there, right?
Or am I missing something?
Thx.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette