diff options
| -rw-r--r-- | arch/x86/kernel/cpu/intel_cacheinfo.c | 35 |
1 files changed, 31 insertions, 4 deletions
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index 3976ce95095f..589b705e80ed 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c | |||
| @@ -151,7 +151,8 @@ struct _cpuid4_info { | |||
| 151 | union _cpuid4_leaf_ebx ebx; | 151 | union _cpuid4_leaf_ebx ebx; |
| 152 | union _cpuid4_leaf_ecx ecx; | 152 | union _cpuid4_leaf_ecx ecx; |
| 153 | unsigned long size; | 153 | unsigned long size; |
| 154 | unsigned long can_disable; | 154 | bool can_disable; |
| 155 | unsigned int l3_indices; | ||
| 155 | DECLARE_BITMAP(shared_cpu_map, NR_CPUS); | 156 | DECLARE_BITMAP(shared_cpu_map, NR_CPUS); |
| 156 | }; | 157 | }; |
| 157 | 158 | ||
| @@ -161,7 +162,8 @@ struct _cpuid4_info_regs { | |||
| 161 | union _cpuid4_leaf_ebx ebx; | 162 | union _cpuid4_leaf_ebx ebx; |
| 162 | union _cpuid4_leaf_ecx ecx; | 163 | union _cpuid4_leaf_ecx ecx; |
| 163 | unsigned long size; | 164 | unsigned long size; |
| 164 | unsigned long can_disable; | 165 | bool can_disable; |
| 166 | unsigned int l3_indices; | ||
| 165 | }; | 167 | }; |
| 166 | 168 | ||
| 167 | unsigned short num_cache_leaves; | 169 | unsigned short num_cache_leaves; |
| @@ -291,6 +293,29 @@ amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax, | |||
| 291 | (ebx->split.ways_of_associativity + 1) - 1; | 293 | (ebx->split.ways_of_associativity + 1) - 1; |
| 292 | } | 294 | } |
| 293 | 295 | ||
| 296 | static unsigned int __cpuinit amd_calc_l3_indices(void) | ||
| 297 | { | ||
| 298 | /* | ||
| 299 | * We're called over smp_call_function_single() and therefore | ||
| 300 | * are on the correct cpu. | ||
| 301 | */ | ||
| 302 | int cpu = smp_processor_id(); | ||
| 303 | int node = cpu_to_node(cpu); | ||
| 304 | struct pci_dev *dev = node_to_k8_nb_misc(node); | ||
| 305 | unsigned int sc0, sc1, sc2, sc3; | ||
| 306 | u32 val; | ||
| 307 | |||
| 308 | pci_read_config_dword(dev, 0x1C4, &val); | ||
| 309 | |||
| 310 | /* calculate subcache sizes */ | ||
| 311 | sc0 = !(val & BIT(0)); | ||
| 312 | sc1 = !(val & BIT(4)); | ||
| 313 | sc2 = !(val & BIT(8)) + !(val & BIT(9)); | ||
| 314 | sc3 = !(val & BIT(12)) + !(val & BIT(13)); | ||
| 315 | |||
| 316 | return (max(max(max(sc0, sc1), sc2), sc3) << 10) - 1; | ||
| 317 | } | ||
| 318 | |||
| 294 | static void __cpuinit | 319 | static void __cpuinit |
| 295 | amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf) | 320 | amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf) |
| 296 | { | 321 | { |
| @@ -306,7 +331,8 @@ amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf) | |||
| 306 | (boot_cpu_data.x86_mask < 0x1))) | 331 | (boot_cpu_data.x86_mask < 0x1))) |
| 307 | return; | 332 | return; |
| 308 | 333 | ||
| 309 | this_leaf->can_disable = 1; | 334 | this_leaf->can_disable = true; |
| 335 | this_leaf->l3_indices = amd_calc_l3_indices(); | ||
| 310 | } | 336 | } |
| 311 | 337 | ||
| 312 | static int | 338 | static int |
| @@ -765,7 +791,8 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, | |||
| 765 | return -EINVAL; | 791 | return -EINVAL; |
| 766 | 792 | ||
| 767 | /* do not allow writes outside of allowed bits */ | 793 | /* do not allow writes outside of allowed bits */ |
| 768 | if (val & ~(SUBCACHE_MASK | SUBCACHE_INDEX)) | 794 | if ((val & ~(SUBCACHE_MASK | SUBCACHE_INDEX)) || |
| 795 | ((val & SUBCACHE_INDEX) > this_leaf->l3_indices)) | ||
| 769 | return -EINVAL; | 796 | return -EINVAL; |
| 770 | 797 | ||
| 771 | val |= BIT(30); | 798 | val |= BIT(30); |
