diff options
Diffstat (limited to 'arch/x86/kernel/cpu')
-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); |