From: Andi Kleen <[email protected]> Every gs selector/index reload always paid an extra MFENCE between the two SWAPGS. This was to work around an old bug in early K8 steppings. All other CPUs don't need the extra mfence. Patch the extra MFENCE only in for K8.
v2: Use set_cpu_bug() v3: Use ALTERNATIVE directly Signed-off-by: Andi Kleen <[email protected]> --- arch/x86/entry/entry_64.S | 2 +- arch/x86/include/asm/cpufeatures.h | 1 + arch/x86/kernel/cpu/amd.c | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index c605710..252bce4 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -786,7 +786,7 @@ ENTRY(native_load_gs_index) SWAPGS gs_change: movl %edi, %gs -2: mfence /* workaround */ +2: ALTERNATIVE "", "mfence", X86_BUG_SWAPGS_MFENCE SWAPGS popfq ret diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index 074b760..f3b3ff8 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -288,6 +288,7 @@ #define X86_BUG_FXSAVE_LEAK X86_BUG(6) /* FXSAVE leaks FOP/FIP/FOP */ #define X86_BUG_CLFLUSH_MONITOR X86_BUG(7) /* AAI65, CLFLUSH required before MONITOR */ #define X86_BUG_SYSRET_SS_ATTRS X86_BUG(8) /* SYSRET doesn't fix up SS attrs */ +#define X86_BUG_SWAPGS_MFENCE X86_BUG(9) /* SWAPGS may need MFENCE */ #ifdef CONFIG_X86_32 /* diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 97c59fd..9cd932b 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -589,6 +589,9 @@ static void init_amd_k8(struct cpuinfo_x86 *c) if ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58) set_cpu_cap(c, X86_FEATURE_REP_GOOD); + /* Early steppings needed a mfence on swapgs. */ + set_cpu_bug(c, X86_BUG_SWAPGS_MFENCE); + /* * Some BIOSes incorrectly force this feature, but only K8 revision D * (model = 0x14) and later actually support it. -- 2.5.5

