96 lines
3.1 KiB
Diff
96 lines
3.1 KiB
Diff
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
|
|
--- a/arch/x86/include/asm/cpufeatures.h
|
|
+++ b/arch/x86/include/asm/cpufeatures.h
|
|
@@ -471,6 +471,8 @@
|
|
#define X86_FEATURE_AUTOIBRS (20*32+ 8) /* Automatic IBRS */
|
|
#define X86_FEATURE_NO_SMM_CTL_MSR (20*32+ 9) /* SMM_CTL MSR is not present */
|
|
|
|
+#define X86_FEATURE_L2_TLB_SIZE_X32 (20*32+14) /* L2 TLB sizes are encoded as multiples of 32 */
|
|
+
|
|
#define X86_FEATURE_GP_ON_USER_CPUID (20*32+17) /* User CPUID faulting */
|
|
|
|
#define X86_FEATURE_PREFETCHI (20*32+20) /* Prefetch Data/Instruction to Cache Level */
|
|
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
|
|
--- a/arch/x86/kernel/cpu/amd.c
|
|
+++ b/arch/x86/kernel/cpu/amd.c
|
|
@@ -1190,7 +1190,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)
|
|
@@ -1199,10 +1199,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
|
|
@@ -1214,16 +1216,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;
|
|
@@ -1231,8 +1235,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
|
|
--- 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)
|