x86: L3 cache index disable for 2.6.26
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / arch / x86 / kernel / cpu / intel_cacheinfo.c
bloba0c6c6ffed4687c41e87f53aef7858ef85a4c63a
1 /*
2 * Routines to indentify caches on Intel CPU.
4 * Changes:
5 * Venkatesh Pallipadi : Adding cache identification through cpuid(4)
6 * Ashok Raj <ashok.raj@intel.com>: Work with CPU hotplug infrastructure.
7 * Andi Kleen / Andreas Herrmann : CPUID4 emulation on AMD.
8 */
10 #include <linux/init.h>
11 #include <linux/slab.h>
12 #include <linux/device.h>
13 #include <linux/compiler.h>
14 #include <linux/cpu.h>
15 #include <linux/sched.h>
16 #include <linux/pci.h>
18 #include <asm/processor.h>
19 #include <asm/smp.h>
21 #define LVL_1_INST 1
22 #define LVL_1_DATA 2
23 #define LVL_2 3
24 #define LVL_3 4
25 #define LVL_TRACE 5
27 struct _cache_table
29 unsigned char descriptor;
30 char cache_type;
31 short size;
34 /* all the cache descriptor types we care about (no TLB or trace cache entries) */
35 static struct _cache_table cache_table[] __cpuinitdata =
37 { 0x06, LVL_1_INST, 8 }, /* 4-way set assoc, 32 byte line size */
38 { 0x08, LVL_1_INST, 16 }, /* 4-way set assoc, 32 byte line size */
39 { 0x0a, LVL_1_DATA, 8 }, /* 2 way set assoc, 32 byte line size */
40 { 0x0c, LVL_1_DATA, 16 }, /* 4-way set assoc, 32 byte line size */
41 { 0x22, LVL_3, 512 }, /* 4-way set assoc, sectored cache, 64 byte line size */
42 { 0x23, LVL_3, 1024 }, /* 8-way set assoc, sectored cache, 64 byte line size */
43 { 0x25, LVL_3, 2048 }, /* 8-way set assoc, sectored cache, 64 byte line size */
44 { 0x29, LVL_3, 4096 }, /* 8-way set assoc, sectored cache, 64 byte line size */
45 { 0x2c, LVL_1_DATA, 32 }, /* 8-way set assoc, 64 byte line size */
46 { 0x30, LVL_1_INST, 32 }, /* 8-way set assoc, 64 byte line size */
47 { 0x39, LVL_2, 128 }, /* 4-way set assoc, sectored cache, 64 byte line size */
48 { 0x3a, LVL_2, 192 }, /* 6-way set assoc, sectored cache, 64 byte line size */
49 { 0x3b, LVL_2, 128 }, /* 2-way set assoc, sectored cache, 64 byte line size */
50 { 0x3c, LVL_2, 256 }, /* 4-way set assoc, sectored cache, 64 byte line size */
51 { 0x3d, LVL_2, 384 }, /* 6-way set assoc, sectored cache, 64 byte line size */
52 { 0x3e, LVL_2, 512 }, /* 4-way set assoc, sectored cache, 64 byte line size */
53 { 0x3f, LVL_2, 256 }, /* 2-way set assoc, 64 byte line size */
54 { 0x41, LVL_2, 128 }, /* 4-way set assoc, 32 byte line size */
55 { 0x42, LVL_2, 256 }, /* 4-way set assoc, 32 byte line size */
56 { 0x43, LVL_2, 512 }, /* 4-way set assoc, 32 byte line size */
57 { 0x44, LVL_2, 1024 }, /* 4-way set assoc, 32 byte line size */
58 { 0x45, LVL_2, 2048 }, /* 4-way set assoc, 32 byte line size */
59 { 0x46, LVL_3, 4096 }, /* 4-way set assoc, 64 byte line size */
60 { 0x47, LVL_3, 8192 }, /* 8-way set assoc, 64 byte line size */
61 { 0x49, LVL_3, 4096 }, /* 16-way set assoc, 64 byte line size */
62 { 0x4a, LVL_3, 6144 }, /* 12-way set assoc, 64 byte line size */
63 { 0x4b, LVL_3, 8192 }, /* 16-way set assoc, 64 byte line size */
64 { 0x4c, LVL_3, 12288 }, /* 12-way set assoc, 64 byte line size */
65 { 0x4d, LVL_3, 16384 }, /* 16-way set assoc, 64 byte line size */
66 { 0x4e, LVL_2, 6144 }, /* 24-way set assoc, 64 byte line size */
67 { 0x60, LVL_1_DATA, 16 }, /* 8-way set assoc, sectored cache, 64 byte line size */
68 { 0x66, LVL_1_DATA, 8 }, /* 4-way set assoc, sectored cache, 64 byte line size */
69 { 0x67, LVL_1_DATA, 16 }, /* 4-way set assoc, sectored cache, 64 byte line size */
70 { 0x68, LVL_1_DATA, 32 }, /* 4-way set assoc, sectored cache, 64 byte line size */
71 { 0x70, LVL_TRACE, 12 }, /* 8-way set assoc */
72 { 0x71, LVL_TRACE, 16 }, /* 8-way set assoc */
73 { 0x72, LVL_TRACE, 32 }, /* 8-way set assoc */
74 { 0x73, LVL_TRACE, 64 }, /* 8-way set assoc */
75 { 0x78, LVL_2, 1024 }, /* 4-way set assoc, 64 byte line size */
76 { 0x79, LVL_2, 128 }, /* 8-way set assoc, sectored cache, 64 byte line size */
77 { 0x7a, LVL_2, 256 }, /* 8-way set assoc, sectored cache, 64 byte line size */
78 { 0x7b, LVL_2, 512 }, /* 8-way set assoc, sectored cache, 64 byte line size */
79 { 0x7c, LVL_2, 1024 }, /* 8-way set assoc, sectored cache, 64 byte line size */
80 { 0x7d, LVL_2, 2048 }, /* 8-way set assoc, 64 byte line size */
81 { 0x7f, LVL_2, 512 }, /* 2-way set assoc, 64 byte line size */
82 { 0x82, LVL_2, 256 }, /* 8-way set assoc, 32 byte line size */
83 { 0x83, LVL_2, 512 }, /* 8-way set assoc, 32 byte line size */
84 { 0x84, LVL_2, 1024 }, /* 8-way set assoc, 32 byte line size */
85 { 0x85, LVL_2, 2048 }, /* 8-way set assoc, 32 byte line size */
86 { 0x86, LVL_2, 512 }, /* 4-way set assoc, 64 byte line size */
87 { 0x87, LVL_2, 1024 }, /* 8-way set assoc, 64 byte line size */
88 { 0x00, 0, 0}
92 enum _cache_type
94 CACHE_TYPE_NULL = 0,
95 CACHE_TYPE_DATA = 1,
96 CACHE_TYPE_INST = 2,
97 CACHE_TYPE_UNIFIED = 3
100 union _cpuid4_leaf_eax {
101 struct {
102 enum _cache_type type:5;
103 unsigned int level:3;
104 unsigned int is_self_initializing:1;
105 unsigned int is_fully_associative:1;
106 unsigned int reserved:4;
107 unsigned int num_threads_sharing:12;
108 unsigned int num_cores_on_die:6;
109 } split;
110 u32 full;
113 union _cpuid4_leaf_ebx {
114 struct {
115 unsigned int coherency_line_size:12;
116 unsigned int physical_line_partition:10;
117 unsigned int ways_of_associativity:10;
118 } split;
119 u32 full;
122 union _cpuid4_leaf_ecx {
123 struct {
124 unsigned int number_of_sets:32;
125 } split;
126 u32 full;
129 struct _cpuid4_info {
130 union _cpuid4_leaf_eax eax;
131 union _cpuid4_leaf_ebx ebx;
132 union _cpuid4_leaf_ecx ecx;
133 unsigned long size;
134 unsigned long can_disable;
135 cpumask_t shared_cpu_map; /* future?: only cpus/node is needed */
138 static struct pci_device_id k8_nb_id[] = {
139 { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1103) },
140 { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1203) },
144 unsigned short num_cache_leaves;
146 /* AMD doesn't have CPUID4. Emulate it here to report the same
147 information to the user. This makes some assumptions about the machine:
148 L2 not shared, no SMT etc. that is currently true on AMD CPUs.
150 In theory the TLBs could be reported as fake type (they are in "dummy").
151 Maybe later */
152 union l1_cache {
153 struct {
154 unsigned line_size : 8;
155 unsigned lines_per_tag : 8;
156 unsigned assoc : 8;
157 unsigned size_in_kb : 8;
159 unsigned val;
162 union l2_cache {
163 struct {
164 unsigned line_size : 8;
165 unsigned lines_per_tag : 4;
166 unsigned assoc : 4;
167 unsigned size_in_kb : 16;
169 unsigned val;
172 union l3_cache {
173 struct {
174 unsigned line_size : 8;
175 unsigned lines_per_tag : 4;
176 unsigned assoc : 4;
177 unsigned res : 2;
178 unsigned size_encoded : 14;
180 unsigned val;
183 static unsigned short assocs[] __cpuinitdata = {
184 [1] = 1, [2] = 2, [4] = 4, [6] = 8,
185 [8] = 16, [0xa] = 32, [0xb] = 48,
186 [0xc] = 64,
187 [0xf] = 0xffff // ??
190 static unsigned char levels[] __cpuinitdata = { 1, 1, 2, 3 };
191 static unsigned char types[] __cpuinitdata = { 1, 2, 3, 3 };
193 static void __cpuinit amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax,
194 union _cpuid4_leaf_ebx *ebx,
195 union _cpuid4_leaf_ecx *ecx)
197 unsigned dummy;
198 unsigned line_size, lines_per_tag, assoc, size_in_kb;
199 union l1_cache l1i, l1d;
200 union l2_cache l2;
201 union l3_cache l3;
202 union l1_cache *l1 = &l1d;
204 eax->full = 0;
205 ebx->full = 0;
206 ecx->full = 0;
208 cpuid(0x80000005, &dummy, &dummy, &l1d.val, &l1i.val);
209 cpuid(0x80000006, &dummy, &dummy, &l2.val, &l3.val);
211 switch (leaf) {
212 case 1:
213 l1 = &l1i;
214 case 0:
215 if (!l1->val)
216 return;
217 assoc = l1->assoc;
218 line_size = l1->line_size;
219 lines_per_tag = l1->lines_per_tag;
220 size_in_kb = l1->size_in_kb;
221 break;
222 case 2:
223 if (!l2.val)
224 return;
225 assoc = l2.assoc;
226 line_size = l2.line_size;
227 lines_per_tag = l2.lines_per_tag;
228 /* cpu_data has errata corrections for K7 applied */
229 size_in_kb = current_cpu_data.x86_cache_size;
230 break;
231 case 3:
232 if (!l3.val)
233 return;
234 assoc = l3.assoc;
235 line_size = l3.line_size;
236 lines_per_tag = l3.lines_per_tag;
237 size_in_kb = l3.size_encoded * 512;
238 break;
239 default:
240 return;
243 eax->split.is_self_initializing = 1;
244 eax->split.type = types[leaf];
245 eax->split.level = levels[leaf];
246 if (leaf == 3)
247 eax->split.num_threads_sharing = current_cpu_data.x86_max_cores - 1;
248 else
249 eax->split.num_threads_sharing = 0;
250 eax->split.num_cores_on_die = current_cpu_data.x86_max_cores - 1;
253 if (assoc == 0xf)
254 eax->split.is_fully_associative = 1;
255 ebx->split.coherency_line_size = line_size - 1;
256 ebx->split.ways_of_associativity = assocs[assoc] - 1;
257 ebx->split.physical_line_partition = lines_per_tag - 1;
258 ecx->split.number_of_sets = (size_in_kb * 1024) / line_size /
259 (ebx->split.ways_of_associativity + 1) - 1;
262 static void __cpuinit
263 amd_check_l3_disable(int index, struct _cpuid4_info *this_leaf)
265 if (index < 3)
266 return;
267 this_leaf->can_disable = 1;
270 static int
271 __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
273 union _cpuid4_leaf_eax eax;
274 union _cpuid4_leaf_ebx ebx;
275 union _cpuid4_leaf_ecx ecx;
276 unsigned edx;
278 if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
279 amd_cpuid4(index, &eax, &ebx, &ecx);
280 if (boot_cpu_data.x86 >= 0x10)
281 amd_check_l3_disable(index, this_leaf);
282 } else {
283 cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx);
286 if (eax.split.type == CACHE_TYPE_NULL)
287 return -EIO; /* better error ? */
289 this_leaf->eax = eax;
290 this_leaf->ebx = ebx;
291 this_leaf->ecx = ecx;
292 this_leaf->size = (ecx.split.number_of_sets + 1) *
293 (ebx.split.coherency_line_size + 1) *
294 (ebx.split.physical_line_partition + 1) *
295 (ebx.split.ways_of_associativity + 1);
296 return 0;
299 static int __cpuinit find_num_cache_leaves(void)
301 unsigned int eax, ebx, ecx, edx;
302 union _cpuid4_leaf_eax cache_eax;
303 int i = -1;
305 do {
306 ++i;
307 /* Do cpuid(4) loop to find out num_cache_leaves */
308 cpuid_count(4, i, &eax, &ebx, &ecx, &edx);
309 cache_eax.full = eax;
310 } while (cache_eax.split.type != CACHE_TYPE_NULL);
311 return i;
314 unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
316 unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */
317 unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */
318 unsigned int new_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */
319 unsigned int l2_id = 0, l3_id = 0, num_threads_sharing, index_msb;
320 #ifdef CONFIG_X86_HT
321 unsigned int cpu = c->cpu_index;
322 #endif
324 if (c->cpuid_level > 3) {
325 static int is_initialized;
327 if (is_initialized == 0) {
328 /* Init num_cache_leaves from boot CPU */
329 num_cache_leaves = find_num_cache_leaves();
330 is_initialized++;
334 * Whenever possible use cpuid(4), deterministic cache
335 * parameters cpuid leaf to find the cache details
337 for (i = 0; i < num_cache_leaves; i++) {
338 struct _cpuid4_info this_leaf;
340 int retval;
342 retval = cpuid4_cache_lookup(i, &this_leaf);
343 if (retval >= 0) {
344 switch(this_leaf.eax.split.level) {
345 case 1:
346 if (this_leaf.eax.split.type ==
347 CACHE_TYPE_DATA)
348 new_l1d = this_leaf.size/1024;
349 else if (this_leaf.eax.split.type ==
350 CACHE_TYPE_INST)
351 new_l1i = this_leaf.size/1024;
352 break;
353 case 2:
354 new_l2 = this_leaf.size/1024;
355 num_threads_sharing = 1 + this_leaf.eax.split.num_threads_sharing;
356 index_msb = get_count_order(num_threads_sharing);
357 l2_id = c->apicid >> index_msb;
358 break;
359 case 3:
360 new_l3 = this_leaf.size/1024;
361 num_threads_sharing = 1 + this_leaf.eax.split.num_threads_sharing;
362 index_msb = get_count_order(num_threads_sharing);
363 l3_id = c->apicid >> index_msb;
364 break;
365 default:
366 break;
372 * Don't use cpuid2 if cpuid4 is supported. For P4, we use cpuid2 for
373 * trace cache
375 if ((num_cache_leaves == 0 || c->x86 == 15) && c->cpuid_level > 1) {
376 /* supports eax=2 call */
377 int j, n;
378 unsigned int regs[4];
379 unsigned char *dp = (unsigned char *)regs;
380 int only_trace = 0;
382 if (num_cache_leaves != 0 && c->x86 == 15)
383 only_trace = 1;
385 /* Number of times to iterate */
386 n = cpuid_eax(2) & 0xFF;
388 for ( i = 0 ; i < n ; i++ ) {
389 cpuid(2, &regs[0], &regs[1], &regs[2], &regs[3]);
391 /* If bit 31 is set, this is an unknown format */
392 for ( j = 0 ; j < 3 ; j++ ) {
393 if (regs[j] & (1 << 31)) regs[j] = 0;
396 /* Byte 0 is level count, not a descriptor */
397 for ( j = 1 ; j < 16 ; j++ ) {
398 unsigned char des = dp[j];
399 unsigned char k = 0;
401 /* look up this descriptor in the table */
402 while (cache_table[k].descriptor != 0)
404 if (cache_table[k].descriptor == des) {
405 if (only_trace && cache_table[k].cache_type != LVL_TRACE)
406 break;
407 switch (cache_table[k].cache_type) {
408 case LVL_1_INST:
409 l1i += cache_table[k].size;
410 break;
411 case LVL_1_DATA:
412 l1d += cache_table[k].size;
413 break;
414 case LVL_2:
415 l2 += cache_table[k].size;
416 break;
417 case LVL_3:
418 l3 += cache_table[k].size;
419 break;
420 case LVL_TRACE:
421 trace += cache_table[k].size;
422 break;
425 break;
428 k++;
434 if (new_l1d)
435 l1d = new_l1d;
437 if (new_l1i)
438 l1i = new_l1i;
440 if (new_l2) {
441 l2 = new_l2;
442 #ifdef CONFIG_X86_HT
443 per_cpu(cpu_llc_id, cpu) = l2_id;
444 #endif
447 if (new_l3) {
448 l3 = new_l3;
449 #ifdef CONFIG_X86_HT
450 per_cpu(cpu_llc_id, cpu) = l3_id;
451 #endif
454 if (trace)
455 printk (KERN_INFO "CPU: Trace cache: %dK uops", trace);
456 else if ( l1i )
457 printk (KERN_INFO "CPU: L1 I cache: %dK", l1i);
459 if (l1d)
460 printk(", L1 D cache: %dK\n", l1d);
461 else
462 printk("\n");
464 if (l2)
465 printk(KERN_INFO "CPU: L2 cache: %dK\n", l2);
467 if (l3)
468 printk(KERN_INFO "CPU: L3 cache: %dK\n", l3);
470 c->x86_cache_size = l3 ? l3 : (l2 ? l2 : (l1i+l1d));
472 return l2;
475 /* pointer to _cpuid4_info array (for each cache leaf) */
476 static DEFINE_PER_CPU(struct _cpuid4_info *, cpuid4_info);
477 #define CPUID4_INFO_IDX(x, y) (&((per_cpu(cpuid4_info, x))[y]))
479 #ifdef CONFIG_SMP
480 static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
482 struct _cpuid4_info *this_leaf, *sibling_leaf;
483 unsigned long num_threads_sharing;
484 int index_msb, i;
485 struct cpuinfo_x86 *c = &cpu_data(cpu);
487 this_leaf = CPUID4_INFO_IDX(cpu, index);
488 num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing;
490 if (num_threads_sharing == 1)
491 cpu_set(cpu, this_leaf->shared_cpu_map);
492 else {
493 index_msb = get_count_order(num_threads_sharing);
495 for_each_online_cpu(i) {
496 if (cpu_data(i).apicid >> index_msb ==
497 c->apicid >> index_msb) {
498 cpu_set(i, this_leaf->shared_cpu_map);
499 if (i != cpu && per_cpu(cpuid4_info, i)) {
500 sibling_leaf = CPUID4_INFO_IDX(i, index);
501 cpu_set(cpu, sibling_leaf->shared_cpu_map);
507 static void __cpuinit cache_remove_shared_cpu_map(unsigned int cpu, int index)
509 struct _cpuid4_info *this_leaf, *sibling_leaf;
510 int sibling;
512 this_leaf = CPUID4_INFO_IDX(cpu, index);
513 for_each_cpu_mask(sibling, this_leaf->shared_cpu_map) {
514 sibling_leaf = CPUID4_INFO_IDX(sibling, index);
515 cpu_clear(cpu, sibling_leaf->shared_cpu_map);
518 #else
519 static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) {}
520 static void __cpuinit cache_remove_shared_cpu_map(unsigned int cpu, int index) {}
521 #endif
523 static void __cpuinit free_cache_attributes(unsigned int cpu)
525 int i;
527 for (i = 0; i < num_cache_leaves; i++)
528 cache_remove_shared_cpu_map(cpu, i);
530 kfree(per_cpu(cpuid4_info, cpu));
531 per_cpu(cpuid4_info, cpu) = NULL;
534 static int __cpuinit detect_cache_attributes(unsigned int cpu)
536 struct _cpuid4_info *this_leaf;
537 unsigned long j;
538 int retval;
539 cpumask_t oldmask;
541 if (num_cache_leaves == 0)
542 return -ENOENT;
544 per_cpu(cpuid4_info, cpu) = kzalloc(
545 sizeof(struct _cpuid4_info) * num_cache_leaves, GFP_KERNEL);
546 if (per_cpu(cpuid4_info, cpu) == NULL)
547 return -ENOMEM;
549 oldmask = current->cpus_allowed;
550 retval = set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
551 if (retval)
552 goto out;
554 /* Do cpuid and store the results */
555 for (j = 0; j < num_cache_leaves; j++) {
556 this_leaf = CPUID4_INFO_IDX(cpu, j);
557 retval = cpuid4_cache_lookup(j, this_leaf);
558 if (unlikely(retval < 0)) {
559 int i;
561 for (i = 0; i < j; i++)
562 cache_remove_shared_cpu_map(cpu, i);
563 break;
565 cache_shared_cpu_map_setup(cpu, j);
567 set_cpus_allowed_ptr(current, &oldmask);
569 out:
570 if (retval) {
571 kfree(per_cpu(cpuid4_info, cpu));
572 per_cpu(cpuid4_info, cpu) = NULL;
575 return retval;
578 #ifdef CONFIG_SYSFS
580 #include <linux/kobject.h>
581 #include <linux/sysfs.h>
583 extern struct sysdev_class cpu_sysdev_class; /* from drivers/base/cpu.c */
585 /* pointer to kobject for cpuX/cache */
586 static DEFINE_PER_CPU(struct kobject *, cache_kobject);
588 struct _index_kobject {
589 struct kobject kobj;
590 unsigned int cpu;
591 unsigned short index;
594 /* pointer to array of kobjects for cpuX/cache/indexY */
595 static DEFINE_PER_CPU(struct _index_kobject *, index_kobject);
596 #define INDEX_KOBJECT_PTR(x, y) (&((per_cpu(index_kobject, x))[y]))
598 #define show_one_plus(file_name, object, val) \
599 static ssize_t show_##file_name \
600 (struct _cpuid4_info *this_leaf, char *buf) \
602 return sprintf (buf, "%lu\n", (unsigned long)this_leaf->object + val); \
605 show_one_plus(level, eax.split.level, 0);
606 show_one_plus(coherency_line_size, ebx.split.coherency_line_size, 1);
607 show_one_plus(physical_line_partition, ebx.split.physical_line_partition, 1);
608 show_one_plus(ways_of_associativity, ebx.split.ways_of_associativity, 1);
609 show_one_plus(number_of_sets, ecx.split.number_of_sets, 1);
611 static ssize_t show_size(struct _cpuid4_info *this_leaf, char *buf)
613 return sprintf (buf, "%luK\n", this_leaf->size / 1024);
616 static ssize_t show_shared_cpu_map_func(struct _cpuid4_info *this_leaf,
617 int type, char *buf)
619 ptrdiff_t len = PTR_ALIGN(buf + PAGE_SIZE - 1, PAGE_SIZE) - buf;
620 int n = 0;
622 if (len > 1) {
623 cpumask_t *mask = &this_leaf->shared_cpu_map;
625 n = type?
626 cpulist_scnprintf(buf, len-2, *mask):
627 cpumask_scnprintf(buf, len-2, *mask);
628 buf[n++] = '\n';
629 buf[n] = '\0';
631 return n;
634 static inline ssize_t show_shared_cpu_map(struct _cpuid4_info *leaf, char *buf)
636 return show_shared_cpu_map_func(leaf, 0, buf);
639 static inline ssize_t show_shared_cpu_list(struct _cpuid4_info *leaf, char *buf)
641 return show_shared_cpu_map_func(leaf, 1, buf);
644 static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf) {
645 switch(this_leaf->eax.split.type) {
646 case CACHE_TYPE_DATA:
647 return sprintf(buf, "Data\n");
648 break;
649 case CACHE_TYPE_INST:
650 return sprintf(buf, "Instruction\n");
651 break;
652 case CACHE_TYPE_UNIFIED:
653 return sprintf(buf, "Unified\n");
654 break;
655 default:
656 return sprintf(buf, "Unknown\n");
657 break;
661 #define to_object(k) container_of(k, struct _index_kobject, kobj)
662 #define to_attr(a) container_of(a, struct _cache_attr, attr)
664 static struct pci_dev *get_k8_northbridge(int node)
666 struct pci_dev *dev = NULL;
667 int i;
669 for (i = 0; i <= node; i++) {
670 do {
671 dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
672 if (!dev)
673 break;
674 } while (!pci_match_id(&k8_nb_id[0], dev));
675 if (!dev)
676 break;
678 return dev;
681 static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf)
683 int node = cpu_to_node(first_cpu(this_leaf->shared_cpu_map));
684 struct pci_dev *dev = NULL;
685 ssize_t ret = 0;
686 int i;
688 if (!this_leaf->can_disable)
689 return sprintf(buf, "Feature not enabled\n");
691 dev = get_k8_northbridge(node);
692 if (!dev) {
693 printk(KERN_ERR "Attempting AMD northbridge operation on a system with no northbridge\n");
694 return -EINVAL;
697 for (i = 0; i < 2; i++) {
698 unsigned int reg;
700 pci_read_config_dword(dev, 0x1BC + i * 4, &reg);
702 ret += sprintf(buf, "%sEntry: %d\n", buf, i);
703 ret += sprintf(buf, "%sReads: %s\tNew Entries: %s\n",
704 buf,
705 reg & 0x80000000 ? "Disabled" : "Allowed",
706 reg & 0x40000000 ? "Disabled" : "Allowed");
707 ret += sprintf(buf, "%sSubCache: %x\tIndex: %x\n",
708 buf, (reg & 0x30000) >> 16, reg & 0xfff);
710 return ret;
713 static ssize_t
714 store_cache_disable(struct _cpuid4_info *this_leaf, const char *buf,
715 size_t count)
717 int node = cpu_to_node(first_cpu(this_leaf->shared_cpu_map));
718 struct pci_dev *dev = NULL;
719 unsigned int ret, index, val;
721 if (!this_leaf->can_disable)
722 return 0;
724 if (strlen(buf) > 15)
725 return -EINVAL;
727 ret = sscanf(buf, "%x %x", &index, &val);
728 if (ret != 2)
729 return -EINVAL;
730 if (index > 1)
731 return -EINVAL;
733 val |= 0xc0000000;
734 dev = get_k8_northbridge(node);
735 if (!dev) {
736 printk(KERN_ERR "Attempting AMD northbridge operation on a system with no northbridge\n");
737 return -EINVAL;
740 pci_write_config_dword(dev, 0x1BC + index * 4, val & ~0x40000000);
741 wbinvd();
742 pci_write_config_dword(dev, 0x1BC + index * 4, val);
744 return 1;
747 struct _cache_attr {
748 struct attribute attr;
749 ssize_t (*show)(struct _cpuid4_info *, char *);
750 ssize_t (*store)(struct _cpuid4_info *, const char *, size_t count);
753 #define define_one_ro(_name) \
754 static struct _cache_attr _name = \
755 __ATTR(_name, 0444, show_##_name, NULL)
757 define_one_ro(level);
758 define_one_ro(type);
759 define_one_ro(coherency_line_size);
760 define_one_ro(physical_line_partition);
761 define_one_ro(ways_of_associativity);
762 define_one_ro(number_of_sets);
763 define_one_ro(size);
764 define_one_ro(shared_cpu_map);
765 define_one_ro(shared_cpu_list);
767 static struct _cache_attr cache_disable = __ATTR(cache_disable, 0644, show_cache_disable, store_cache_disable);
769 static struct attribute * default_attrs[] = {
770 &type.attr,
771 &level.attr,
772 &coherency_line_size.attr,
773 &physical_line_partition.attr,
774 &ways_of_associativity.attr,
775 &number_of_sets.attr,
776 &size.attr,
777 &shared_cpu_map.attr,
778 &shared_cpu_list.attr,
779 &cache_disable.attr,
780 NULL
783 static ssize_t show(struct kobject * kobj, struct attribute * attr, char * buf)
785 struct _cache_attr *fattr = to_attr(attr);
786 struct _index_kobject *this_leaf = to_object(kobj);
787 ssize_t ret;
789 ret = fattr->show ?
790 fattr->show(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index),
791 buf) :
793 return ret;
796 static ssize_t store(struct kobject * kobj, struct attribute * attr,
797 const char * buf, size_t count)
799 struct _cache_attr *fattr = to_attr(attr);
800 struct _index_kobject *this_leaf = to_object(kobj);
801 ssize_t ret;
803 ret = fattr->store ?
804 fattr->store(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index),
805 buf, count) :
807 return ret;
810 static struct sysfs_ops sysfs_ops = {
811 .show = show,
812 .store = store,
815 static struct kobj_type ktype_cache = {
816 .sysfs_ops = &sysfs_ops,
817 .default_attrs = default_attrs,
820 static struct kobj_type ktype_percpu_entry = {
821 .sysfs_ops = &sysfs_ops,
824 static void __cpuinit cpuid4_cache_sysfs_exit(unsigned int cpu)
826 kfree(per_cpu(cache_kobject, cpu));
827 kfree(per_cpu(index_kobject, cpu));
828 per_cpu(cache_kobject, cpu) = NULL;
829 per_cpu(index_kobject, cpu) = NULL;
830 free_cache_attributes(cpu);
833 static int __cpuinit cpuid4_cache_sysfs_init(unsigned int cpu)
835 int err;
837 if (num_cache_leaves == 0)
838 return -ENOENT;
840 err = detect_cache_attributes(cpu);
841 if (err)
842 return err;
844 /* Allocate all required memory */
845 per_cpu(cache_kobject, cpu) =
846 kzalloc(sizeof(struct kobject), GFP_KERNEL);
847 if (unlikely(per_cpu(cache_kobject, cpu) == NULL))
848 goto err_out;
850 per_cpu(index_kobject, cpu) = kzalloc(
851 sizeof(struct _index_kobject ) * num_cache_leaves, GFP_KERNEL);
852 if (unlikely(per_cpu(index_kobject, cpu) == NULL))
853 goto err_out;
855 return 0;
857 err_out:
858 cpuid4_cache_sysfs_exit(cpu);
859 return -ENOMEM;
862 static cpumask_t cache_dev_map = CPU_MASK_NONE;
864 /* Add/Remove cache interface for CPU device */
865 static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
867 unsigned int cpu = sys_dev->id;
868 unsigned long i, j;
869 struct _index_kobject *this_object;
870 int retval;
872 retval = cpuid4_cache_sysfs_init(cpu);
873 if (unlikely(retval < 0))
874 return retval;
876 retval = kobject_init_and_add(per_cpu(cache_kobject, cpu),
877 &ktype_percpu_entry,
878 &sys_dev->kobj, "%s", "cache");
879 if (retval < 0) {
880 cpuid4_cache_sysfs_exit(cpu);
881 return retval;
884 for (i = 0; i < num_cache_leaves; i++) {
885 this_object = INDEX_KOBJECT_PTR(cpu,i);
886 this_object->cpu = cpu;
887 this_object->index = i;
888 retval = kobject_init_and_add(&(this_object->kobj),
889 &ktype_cache,
890 per_cpu(cache_kobject, cpu),
891 "index%1lu", i);
892 if (unlikely(retval)) {
893 for (j = 0; j < i; j++) {
894 kobject_put(&(INDEX_KOBJECT_PTR(cpu,j)->kobj));
896 kobject_put(per_cpu(cache_kobject, cpu));
897 cpuid4_cache_sysfs_exit(cpu);
898 return retval;
900 kobject_uevent(&(this_object->kobj), KOBJ_ADD);
902 cpu_set(cpu, cache_dev_map);
904 kobject_uevent(per_cpu(cache_kobject, cpu), KOBJ_ADD);
905 return 0;
908 static void __cpuinit cache_remove_dev(struct sys_device * sys_dev)
910 unsigned int cpu = sys_dev->id;
911 unsigned long i;
913 if (per_cpu(cpuid4_info, cpu) == NULL)
914 return;
915 if (!cpu_isset(cpu, cache_dev_map))
916 return;
917 cpu_clear(cpu, cache_dev_map);
919 for (i = 0; i < num_cache_leaves; i++)
920 kobject_put(&(INDEX_KOBJECT_PTR(cpu,i)->kobj));
921 kobject_put(per_cpu(cache_kobject, cpu));
922 cpuid4_cache_sysfs_exit(cpu);
925 static int __cpuinit cacheinfo_cpu_callback(struct notifier_block *nfb,
926 unsigned long action, void *hcpu)
928 unsigned int cpu = (unsigned long)hcpu;
929 struct sys_device *sys_dev;
931 sys_dev = get_cpu_sysdev(cpu);
932 switch (action) {
933 case CPU_ONLINE:
934 case CPU_ONLINE_FROZEN:
935 cache_add_dev(sys_dev);
936 break;
937 case CPU_DEAD:
938 case CPU_DEAD_FROZEN:
939 cache_remove_dev(sys_dev);
940 break;
942 return NOTIFY_OK;
945 static struct notifier_block __cpuinitdata cacheinfo_cpu_notifier =
947 .notifier_call = cacheinfo_cpu_callback,
950 static int __cpuinit cache_sysfs_init(void)
952 int i;
954 if (num_cache_leaves == 0)
955 return 0;
957 for_each_online_cpu(i) {
958 int err;
959 struct sys_device *sys_dev = get_cpu_sysdev(i);
961 err = cache_add_dev(sys_dev);
962 if (err)
963 return err;
965 register_hotcpu_notifier(&cacheinfo_cpu_notifier);
966 return 0;
969 device_initcall(cache_sysfs_init);
971 #endif