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