diff options
| author | Borislav Petkov (AMD) <bp@alien8.de> | 2026-08-20 17:02:10 -0700 |
|---|---|---|
| committer | Borislav Petkov (AMD) <bp@alien8.de> | 2026-09-14 19:10:24 -0700 |
| commit | 228200f695c0f92c5fd06ff0bdcf94bb0d2ca7f5 (patch) | |
| tree | dd9a6d8e382d1209be4b5cca648d376a87365d33 /arch/x86/kernel | |
| parent | 9025f3bf73f0565eaa271ecc15f468b1d1e4cbaa (diff) | |
x86/CPU/AMD: Fix Zen5 TLB sizes reporting
Starting with Zen5, TLB sizes in CPUID_Fn80000006_E[AB]X are reported
as multiples of 32. There's a CPUID bit which determines that:
CPUID_Fn80000021_EAX [Extended Feature 2 EAX] (Core::X86::Cpuid::FeatureExt2Eax)
...
14: L2TlbSizeX32. Read-only. Reset: 1. Indicates that L2TLB sizes are encoded as multiples of 32.
Update the places which report that information.
With it, the numbers look correct now:
-Last level iTLB entries: 4KB 64, 2MB 64, 4MB 32
-Last level dTLB entries: 4KB 128, 2MB 128, 4MB 64, 1GB 0
+Last level iTLB entries: 4KB 2048, 2MB 2048, 4MB 1024
+Last level dTLB entries: 4KB 4096, 2MB 4096, 4MB 2048, 1GB 0
/proc/cpuinfo
-TLB size : 192 4K pages
+TLB size : 6144 4K pages
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Link: https://lore.kernel.org/r/20260821022031.946311-1-bp@kernel.org
Diffstat (limited to 'arch/x86/kernel')
| -rw-r--r-- | arch/x86/kernel/cpu/amd.c | 21 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/common.c | 4 |
2 files changed, 16 insertions, 9 deletions
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 54e14ed276b5..e5279bc648d3 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -1192,7 +1192,7 @@ static unsigned int amd_size_cache(struct cpuinfo_x86 *c, unsigned int size) static void cpu_detect_tlb_amd(struct cpuinfo_x86 *c) { - u32 ebx, eax, ecx, edx; + u32 ebx, eax, ecx, edx, shift, tmp; u16 mask = 0xfff; if (c->x86 < 0xf) @@ -1201,10 +1201,12 @@ static void cpu_detect_tlb_amd(struct cpuinfo_x86 *c) if (c->extended_cpuid_level < 0x80000006) return; + shift = !!cpu_has(c, X86_FEATURE_L2_TLB_SIZE_X32) * 5; + cpuid(0x80000006, &eax, &ebx, &ecx, &edx); - tlb_lld_4k = (ebx >> 16) & mask; - tlb_lli_4k = ebx & mask; + tlb_lld_4k = ((ebx >> 16) & mask) << shift; + tlb_lli_4k = (ebx & mask) << shift; /* * K8 doesn't have 2M/4M entries in the L2 TLB so read out the L1 TLB @@ -1216,16 +1218,18 @@ static void cpu_detect_tlb_amd(struct cpuinfo_x86 *c) } /* Handle DTLB 2M and 4M sizes, fall back to L1 if L2 is disabled */ - if (!((eax >> 16) & mask)) + tmp = ((eax >> 16) & mask) << shift; + if (!tmp) tlb_lld_2m = (cpuid_eax(0x80000005) >> 16) & 0xff; else - tlb_lld_2m = (eax >> 16) & mask; + tlb_lld_2m = tmp; /* a 4M entry uses two 2M entries */ tlb_lld_4m = tlb_lld_2m >> 1; /* Handle ITLB 2M and 4M sizes, fall back to L1 if L2 is disabled */ - if (!(eax & mask)) { + tmp = (eax & mask) << shift; + if (!tmp) { /* Erratum 658 */ if (c->x86 == 0x15 && c->x86_model <= 0x1f) { tlb_lli_2m = 1024; @@ -1233,8 +1237,9 @@ static void cpu_detect_tlb_amd(struct cpuinfo_x86 *c) cpuid(0x80000005, &eax, &ebx, &ecx, &edx); tlb_lli_2m = eax & 0xff; } - } else - tlb_lli_2m = eax & mask; + } else { + tlb_lli_2m = tmp; + } tlb_lli_4m = tlb_lli_2m >> 1; diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index c7352827f491..3716a6af13cb 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -857,7 +857,7 @@ static void get_model_name(struct cpuinfo_x86 *c) void cpu_detect_cache_sizes(struct cpuinfo_x86 *c) { - unsigned int n, dummy, ebx, ecx, edx, l2size; + unsigned int n, dummy, ebx, ecx, edx, l2size, shift __maybe_unused; n = c->extended_cpuid_level; @@ -877,7 +877,9 @@ void cpu_detect_cache_sizes(struct cpuinfo_x86 *c) l2size = ecx >> 16; #ifdef CONFIG_X86_64 + shift = !!cpu_has(c, X86_FEATURE_L2_TLB_SIZE_X32) * 5; c->x86_tlbsize += ((ebx >> 16) & 0xfff) + (ebx & 0xfff); + c->x86_tlbsize <<= shift; #else /* do processor-specific cache resizing */ if (this_cpu->legacy_cache_size) |
