x86: Macroise x86 cache descriptors
[deliverable/linux.git] / arch / x86 / kernel / cpu / intel_cacheinfo.c
1 /*
2 * Routines to indentify caches on Intel CPU.
3 *
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 */
9
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>
17
18 #include <asm/processor.h>
19 #include <linux/smp.h>
20 #include <asm/k8.h>
21
22 #define LVL_1_INST 1
23 #define LVL_1_DATA 2
24 #define LVL_2 3
25 #define LVL_3 4
26 #define LVL_TRACE 5
27
28 struct _cache_table {
29 unsigned char descriptor;
30 char cache_type;
31 short size;
32 };
33
34 #define MB(x) ((x) * 1024)
35
36 /* All the cache descriptor types we care about (no TLB or
37 trace cache entries) */
38
39 static const struct _cache_table __cpuinitconst cache_table[] =
40 {
41 { 0x06, LVL_1_INST, 8 }, /* 4-way set assoc, 32 byte line size */
42 { 0x08, LVL_1_INST, 16 }, /* 4-way set assoc, 32 byte line size */
43 { 0x09, LVL_1_INST, 32 }, /* 4-way set assoc, 64 byte line size */
44 { 0x0a, LVL_1_DATA, 8 }, /* 2 way set assoc, 32 byte line size */
45 { 0x0c, LVL_1_DATA, 16 }, /* 4-way set assoc, 32 byte line size */
46 { 0x0d, LVL_1_DATA, 16 }, /* 4-way set assoc, 64 byte line size */
47 { 0x21, LVL_2, 256 }, /* 8-way set assoc, 64 byte line size */
48 { 0x22, LVL_3, 512 }, /* 4-way set assoc, sectored cache, 64 byte line size */
49 { 0x23, LVL_3, MB(1) }, /* 8-way set assoc, sectored cache, 64 byte line size */
50 { 0x25, LVL_3, MB(2) }, /* 8-way set assoc, sectored cache, 64 byte line size */
51 { 0x29, LVL_3, MB(4) }, /* 8-way set assoc, sectored cache, 64 byte line size */
52 { 0x2c, LVL_1_DATA, 32 }, /* 8-way set assoc, 64 byte line size */
53 { 0x30, LVL_1_INST, 32 }, /* 8-way set assoc, 64 byte line size */
54 { 0x39, LVL_2, 128 }, /* 4-way set assoc, sectored cache, 64 byte line size */
55 { 0x3a, LVL_2, 192 }, /* 6-way set assoc, sectored cache, 64 byte line size */
56 { 0x3b, LVL_2, 128 }, /* 2-way set assoc, sectored cache, 64 byte line size */
57 { 0x3c, LVL_2, 256 }, /* 4-way set assoc, sectored cache, 64 byte line size */
58 { 0x3d, LVL_2, 384 }, /* 6-way set assoc, sectored cache, 64 byte line size */
59 { 0x3e, LVL_2, 512 }, /* 4-way set assoc, sectored cache, 64 byte line size */
60 { 0x3f, LVL_2, 256 }, /* 2-way set assoc, 64 byte line size */
61 { 0x41, LVL_2, 128 }, /* 4-way set assoc, 32 byte line size */
62 { 0x42, LVL_2, 256 }, /* 4-way set assoc, 32 byte line size */
63 { 0x43, LVL_2, 512 }, /* 4-way set assoc, 32 byte line size */
64 { 0x44, LVL_2, MB(1) }, /* 4-way set assoc, 32 byte line size */
65 { 0x45, LVL_2, MB(2) }, /* 4-way set assoc, 32 byte line size */
66 { 0x46, LVL_3, MB(4) }, /* 4-way set assoc, 64 byte line size */
67 { 0x47, LVL_3, MB(8) }, /* 8-way set assoc, 64 byte line size */
68 { 0x49, LVL_3, MB(4) }, /* 16-way set assoc, 64 byte line size */
69 { 0x4a, LVL_3, MB(6) }, /* 12-way set assoc, 64 byte line size */
70 { 0x4b, LVL_3, MB(8) }, /* 16-way set assoc, 64 byte line size */
71 { 0x4c, LVL_3, MB(12) }, /* 12-way set assoc, 64 byte line size */
72 { 0x4d, LVL_3, MB(16) }, /* 16-way set assoc, 64 byte line size */
73 { 0x4e, LVL_2, MB(6) }, /* 24-way set assoc, 64 byte line size */
74 { 0x60, LVL_1_DATA, 16 }, /* 8-way set assoc, sectored cache, 64 byte line size */
75 { 0x66, LVL_1_DATA, 8 }, /* 4-way set assoc, sectored cache, 64 byte line size */
76 { 0x67, LVL_1_DATA, 16 }, /* 4-way set assoc, sectored cache, 64 byte line size */
77 { 0x68, LVL_1_DATA, 32 }, /* 4-way set assoc, sectored cache, 64 byte line size */
78 { 0x70, LVL_TRACE, 12 }, /* 8-way set assoc */
79 { 0x71, LVL_TRACE, 16 }, /* 8-way set assoc */
80 { 0x72, LVL_TRACE, 32 }, /* 8-way set assoc */
81 { 0x73, LVL_TRACE, 64 }, /* 8-way set assoc */
82 { 0x78, LVL_2, MB(1) }, /* 4-way set assoc, 64 byte line size */
83 { 0x79, LVL_2, 128 }, /* 8-way set assoc, sectored cache, 64 byte line size */
84 { 0x7a, LVL_2, 256 }, /* 8-way set assoc, sectored cache, 64 byte line size */
85 { 0x7b, LVL_2, 512 }, /* 8-way set assoc, sectored cache, 64 byte line size */
86 { 0x7c, LVL_2, MB(1) }, /* 8-way set assoc, sectored cache, 64 byte line size */
87 { 0x7d, LVL_2, MB(2) }, /* 8-way set assoc, 64 byte line size */
88 { 0x7f, LVL_2, 512 }, /* 2-way set assoc, 64 byte line size */
89 { 0x82, LVL_2, 256 }, /* 8-way set assoc, 32 byte line size */
90 { 0x83, LVL_2, 512 }, /* 8-way set assoc, 32 byte line size */
91 { 0x84, LVL_2, MB(1) }, /* 8-way set assoc, 32 byte line size */
92 { 0x85, LVL_2, MB(2) }, /* 8-way set assoc, 32 byte line size */
93 { 0x86, LVL_2, 512 }, /* 4-way set assoc, 64 byte line size */
94 { 0x87, LVL_2, MB(1) }, /* 8-way set assoc, 64 byte line size */
95 { 0xd0, LVL_3, 512 }, /* 4-way set assoc, 64 byte line size */
96 { 0xd1, LVL_3, MB(1) }, /* 4-way set assoc, 64 byte line size */
97 { 0xd2, LVL_3, MB(2) }, /* 4-way set assoc, 64 byte line size */
98 { 0xd6, LVL_3, MB(1) }, /* 8-way set assoc, 64 byte line size */
99 { 0xd7, LVL_3, MB(2) }, /* 8-way set assoc, 64 byte line size */
100 { 0xd8, LVL_3, MB(4) }, /* 12-way set assoc, 64 byte line size */
101 { 0xdc, LVL_3, MB(2) }, /* 12-way set assoc, 64 byte line size */
102 { 0xdd, LVL_3, MB(4) }, /* 12-way set assoc, 64 byte line size */
103 { 0xde, LVL_3, MB(8) }, /* 12-way set assoc, 64 byte line size */
104 { 0xe2, LVL_3, MB(2) }, /* 16-way set assoc, 64 byte line size */
105 { 0xe3, LVL_3, MB(4) }, /* 16-way set assoc, 64 byte line size */
106 { 0xe4, LVL_3, MB(8) }, /* 16-way set assoc, 64 byte line size */
107 { 0xea, LVL_3, MB(12) }, /* 24-way set assoc, 64 byte line size */
108 { 0xeb, LVL_3, MB(18) }, /* 24-way set assoc, 64 byte line size */
109 { 0xec, LVL_3, MB(24) }, /* 24-way set assoc, 64 byte line size */
110 { 0x00, 0, 0}
111 };
112
113
114 enum _cache_type {
115 CACHE_TYPE_NULL = 0,
116 CACHE_TYPE_DATA = 1,
117 CACHE_TYPE_INST = 2,
118 CACHE_TYPE_UNIFIED = 3
119 };
120
121 union _cpuid4_leaf_eax {
122 struct {
123 enum _cache_type type:5;
124 unsigned int level:3;
125 unsigned int is_self_initializing:1;
126 unsigned int is_fully_associative:1;
127 unsigned int reserved:4;
128 unsigned int num_threads_sharing:12;
129 unsigned int num_cores_on_die:6;
130 } split;
131 u32 full;
132 };
133
134 union _cpuid4_leaf_ebx {
135 struct {
136 unsigned int coherency_line_size:12;
137 unsigned int physical_line_partition:10;
138 unsigned int ways_of_associativity:10;
139 } split;
140 u32 full;
141 };
142
143 union _cpuid4_leaf_ecx {
144 struct {
145 unsigned int number_of_sets:32;
146 } split;
147 u32 full;
148 };
149
150 struct _cpuid4_info {
151 union _cpuid4_leaf_eax eax;
152 union _cpuid4_leaf_ebx ebx;
153 union _cpuid4_leaf_ecx ecx;
154 unsigned long size;
155 unsigned long can_disable;
156 DECLARE_BITMAP(shared_cpu_map, NR_CPUS);
157 };
158
159 /* subset of above _cpuid4_info w/o shared_cpu_map */
160 struct _cpuid4_info_regs {
161 union _cpuid4_leaf_eax eax;
162 union _cpuid4_leaf_ebx ebx;
163 union _cpuid4_leaf_ecx ecx;
164 unsigned long size;
165 unsigned long can_disable;
166 };
167
168 unsigned short num_cache_leaves;
169
170 /* AMD doesn't have CPUID4. Emulate it here to report the same
171 information to the user. This makes some assumptions about the machine:
172 L2 not shared, no SMT etc. that is currently true on AMD CPUs.
173
174 In theory the TLBs could be reported as fake type (they are in "dummy").
175 Maybe later */
176 union l1_cache {
177 struct {
178 unsigned line_size:8;
179 unsigned lines_per_tag:8;
180 unsigned assoc:8;
181 unsigned size_in_kb:8;
182 };
183 unsigned val;
184 };
185
186 union l2_cache {
187 struct {
188 unsigned line_size:8;
189 unsigned lines_per_tag:4;
190 unsigned assoc:4;
191 unsigned size_in_kb:16;
192 };
193 unsigned val;
194 };
195
196 union l3_cache {
197 struct {
198 unsigned line_size:8;
199 unsigned lines_per_tag:4;
200 unsigned assoc:4;
201 unsigned res:2;
202 unsigned size_encoded:14;
203 };
204 unsigned val;
205 };
206
207 static const unsigned short __cpuinitconst assocs[] = {
208 [1] = 1,
209 [2] = 2,
210 [4] = 4,
211 [6] = 8,
212 [8] = 16,
213 [0xa] = 32,
214 [0xb] = 48,
215 [0xc] = 64,
216 [0xd] = 96,
217 [0xe] = 128,
218 [0xf] = 0xffff /* fully associative - no way to show this currently */
219 };
220
221 static const unsigned char __cpuinitconst levels[] = { 1, 1, 2, 3 };
222 static const unsigned char __cpuinitconst types[] = { 1, 2, 3, 3 };
223
224 static void __cpuinit
225 amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax,
226 union _cpuid4_leaf_ebx *ebx,
227 union _cpuid4_leaf_ecx *ecx)
228 {
229 unsigned dummy;
230 unsigned line_size, lines_per_tag, assoc, size_in_kb;
231 union l1_cache l1i, l1d;
232 union l2_cache l2;
233 union l3_cache l3;
234 union l1_cache *l1 = &l1d;
235
236 eax->full = 0;
237 ebx->full = 0;
238 ecx->full = 0;
239
240 cpuid(0x80000005, &dummy, &dummy, &l1d.val, &l1i.val);
241 cpuid(0x80000006, &dummy, &dummy, &l2.val, &l3.val);
242
243 switch (leaf) {
244 case 1:
245 l1 = &l1i;
246 case 0:
247 if (!l1->val)
248 return;
249 assoc = assocs[l1->assoc];
250 line_size = l1->line_size;
251 lines_per_tag = l1->lines_per_tag;
252 size_in_kb = l1->size_in_kb;
253 break;
254 case 2:
255 if (!l2.val)
256 return;
257 assoc = assocs[l2.assoc];
258 line_size = l2.line_size;
259 lines_per_tag = l2.lines_per_tag;
260 /* cpu_data has errata corrections for K7 applied */
261 size_in_kb = current_cpu_data.x86_cache_size;
262 break;
263 case 3:
264 if (!l3.val)
265 return;
266 assoc = assocs[l3.assoc];
267 line_size = l3.line_size;
268 lines_per_tag = l3.lines_per_tag;
269 size_in_kb = l3.size_encoded * 512;
270 if (boot_cpu_has(X86_FEATURE_AMD_DCM)) {
271 size_in_kb = size_in_kb >> 1;
272 assoc = assoc >> 1;
273 }
274 break;
275 default:
276 return;
277 }
278
279 eax->split.is_self_initializing = 1;
280 eax->split.type = types[leaf];
281 eax->split.level = levels[leaf];
282 eax->split.num_threads_sharing = 0;
283 eax->split.num_cores_on_die = current_cpu_data.x86_max_cores - 1;
284
285
286 if (assoc == 0xffff)
287 eax->split.is_fully_associative = 1;
288 ebx->split.coherency_line_size = line_size - 1;
289 ebx->split.ways_of_associativity = assoc - 1;
290 ebx->split.physical_line_partition = lines_per_tag - 1;
291 ecx->split.number_of_sets = (size_in_kb * 1024) / line_size /
292 (ebx->split.ways_of_associativity + 1) - 1;
293 }
294
295 static void __cpuinit
296 amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
297 {
298 if (index < 3)
299 return;
300
301 if (boot_cpu_data.x86 == 0x11)
302 return;
303
304 /* see erratum #382 */
305 if ((boot_cpu_data.x86 == 0x10) && (boot_cpu_data.x86_model < 0x8))
306 return;
307
308 this_leaf->can_disable = 1;
309 }
310
311 static int
312 __cpuinit cpuid4_cache_lookup_regs(int index,
313 struct _cpuid4_info_regs *this_leaf)
314 {
315 union _cpuid4_leaf_eax eax;
316 union _cpuid4_leaf_ebx ebx;
317 union _cpuid4_leaf_ecx ecx;
318 unsigned edx;
319
320 if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
321 amd_cpuid4(index, &eax, &ebx, &ecx);
322 if (boot_cpu_data.x86 >= 0x10)
323 amd_check_l3_disable(index, this_leaf);
324 } else {
325 cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx);
326 }
327
328 if (eax.split.type == CACHE_TYPE_NULL)
329 return -EIO; /* better error ? */
330
331 this_leaf->eax = eax;
332 this_leaf->ebx = ebx;
333 this_leaf->ecx = ecx;
334 this_leaf->size = (ecx.split.number_of_sets + 1) *
335 (ebx.split.coherency_line_size + 1) *
336 (ebx.split.physical_line_partition + 1) *
337 (ebx.split.ways_of_associativity + 1);
338 return 0;
339 }
340
341 static int __cpuinit find_num_cache_leaves(void)
342 {
343 unsigned int eax, ebx, ecx, edx;
344 union _cpuid4_leaf_eax cache_eax;
345 int i = -1;
346
347 do {
348 ++i;
349 /* Do cpuid(4) loop to find out num_cache_leaves */
350 cpuid_count(4, i, &eax, &ebx, &ecx, &edx);
351 cache_eax.full = eax;
352 } while (cache_eax.split.type != CACHE_TYPE_NULL);
353 return i;
354 }
355
356 unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
357 {
358 /* Cache sizes */
359 unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0;
360 unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */
361 unsigned int new_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */
362 unsigned int l2_id = 0, l3_id = 0, num_threads_sharing, index_msb;
363 #ifdef CONFIG_X86_HT
364 unsigned int cpu = c->cpu_index;
365 #endif
366
367 if (c->cpuid_level > 3) {
368 static int is_initialized;
369
370 if (is_initialized == 0) {
371 /* Init num_cache_leaves from boot CPU */
372 num_cache_leaves = find_num_cache_leaves();
373 is_initialized++;
374 }
375
376 /*
377 * Whenever possible use cpuid(4), deterministic cache
378 * parameters cpuid leaf to find the cache details
379 */
380 for (i = 0; i < num_cache_leaves; i++) {
381 struct _cpuid4_info_regs this_leaf;
382 int retval;
383
384 retval = cpuid4_cache_lookup_regs(i, &this_leaf);
385 if (retval >= 0) {
386 switch (this_leaf.eax.split.level) {
387 case 1:
388 if (this_leaf.eax.split.type ==
389 CACHE_TYPE_DATA)
390 new_l1d = this_leaf.size/1024;
391 else if (this_leaf.eax.split.type ==
392 CACHE_TYPE_INST)
393 new_l1i = this_leaf.size/1024;
394 break;
395 case 2:
396 new_l2 = this_leaf.size/1024;
397 num_threads_sharing = 1 + this_leaf.eax.split.num_threads_sharing;
398 index_msb = get_count_order(num_threads_sharing);
399 l2_id = c->apicid >> index_msb;
400 break;
401 case 3:
402 new_l3 = this_leaf.size/1024;
403 num_threads_sharing = 1 + this_leaf.eax.split.num_threads_sharing;
404 index_msb = get_count_order(
405 num_threads_sharing);
406 l3_id = c->apicid >> index_msb;
407 break;
408 default:
409 break;
410 }
411 }
412 }
413 }
414 /*
415 * Don't use cpuid2 if cpuid4 is supported. For P4, we use cpuid2 for
416 * trace cache
417 */
418 if ((num_cache_leaves == 0 || c->x86 == 15) && c->cpuid_level > 1) {
419 /* supports eax=2 call */
420 int j, n;
421 unsigned int regs[4];
422 unsigned char *dp = (unsigned char *)regs;
423 int only_trace = 0;
424
425 if (num_cache_leaves != 0 && c->x86 == 15)
426 only_trace = 1;
427
428 /* Number of times to iterate */
429 n = cpuid_eax(2) & 0xFF;
430
431 for (i = 0 ; i < n ; i++) {
432 cpuid(2, &regs[0], &regs[1], &regs[2], &regs[3]);
433
434 /* If bit 31 is set, this is an unknown format */
435 for (j = 0 ; j < 3 ; j++)
436 if (regs[j] & (1 << 31))
437 regs[j] = 0;
438
439 /* Byte 0 is level count, not a descriptor */
440 for (j = 1 ; j < 16 ; j++) {
441 unsigned char des = dp[j];
442 unsigned char k = 0;
443
444 /* look up this descriptor in the table */
445 while (cache_table[k].descriptor != 0) {
446 if (cache_table[k].descriptor == des) {
447 if (only_trace && cache_table[k].cache_type != LVL_TRACE)
448 break;
449 switch (cache_table[k].cache_type) {
450 case LVL_1_INST:
451 l1i += cache_table[k].size;
452 break;
453 case LVL_1_DATA:
454 l1d += cache_table[k].size;
455 break;
456 case LVL_2:
457 l2 += cache_table[k].size;
458 break;
459 case LVL_3:
460 l3 += cache_table[k].size;
461 break;
462 case LVL_TRACE:
463 trace += cache_table[k].size;
464 break;
465 }
466
467 break;
468 }
469
470 k++;
471 }
472 }
473 }
474 }
475
476 if (new_l1d)
477 l1d = new_l1d;
478
479 if (new_l1i)
480 l1i = new_l1i;
481
482 if (new_l2) {
483 l2 = new_l2;
484 #ifdef CONFIG_X86_HT
485 per_cpu(cpu_llc_id, cpu) = l2_id;
486 #endif
487 }
488
489 if (new_l3) {
490 l3 = new_l3;
491 #ifdef CONFIG_X86_HT
492 per_cpu(cpu_llc_id, cpu) = l3_id;
493 #endif
494 }
495
496 c->x86_cache_size = l3 ? l3 : (l2 ? l2 : (l1i+l1d));
497
498 return l2;
499 }
500
501 #ifdef CONFIG_SYSFS
502
503 /* pointer to _cpuid4_info array (for each cache leaf) */
504 static DEFINE_PER_CPU(struct _cpuid4_info *, ici_cpuid4_info);
505 #define CPUID4_INFO_IDX(x, y) (&((per_cpu(ici_cpuid4_info, x))[y]))
506
507 #ifdef CONFIG_SMP
508 static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
509 {
510 struct _cpuid4_info *this_leaf, *sibling_leaf;
511 unsigned long num_threads_sharing;
512 int index_msb, i, sibling;
513 struct cpuinfo_x86 *c = &cpu_data(cpu);
514
515 if ((index == 3) && (c->x86_vendor == X86_VENDOR_AMD)) {
516 for_each_cpu(i, c->llc_shared_map) {
517 if (!per_cpu(ici_cpuid4_info, i))
518 continue;
519 this_leaf = CPUID4_INFO_IDX(i, index);
520 for_each_cpu(sibling, c->llc_shared_map) {
521 if (!cpu_online(sibling))
522 continue;
523 set_bit(sibling, this_leaf->shared_cpu_map);
524 }
525 }
526 return;
527 }
528 this_leaf = CPUID4_INFO_IDX(cpu, index);
529 num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing;
530
531 if (num_threads_sharing == 1)
532 cpumask_set_cpu(cpu, to_cpumask(this_leaf->shared_cpu_map));
533 else {
534 index_msb = get_count_order(num_threads_sharing);
535
536 for_each_online_cpu(i) {
537 if (cpu_data(i).apicid >> index_msb ==
538 c->apicid >> index_msb) {
539 cpumask_set_cpu(i,
540 to_cpumask(this_leaf->shared_cpu_map));
541 if (i != cpu && per_cpu(ici_cpuid4_info, i)) {
542 sibling_leaf =
543 CPUID4_INFO_IDX(i, index);
544 cpumask_set_cpu(cpu, to_cpumask(
545 sibling_leaf->shared_cpu_map));
546 }
547 }
548 }
549 }
550 }
551 static void __cpuinit cache_remove_shared_cpu_map(unsigned int cpu, int index)
552 {
553 struct _cpuid4_info *this_leaf, *sibling_leaf;
554 int sibling;
555
556 this_leaf = CPUID4_INFO_IDX(cpu, index);
557 for_each_cpu(sibling, to_cpumask(this_leaf->shared_cpu_map)) {
558 sibling_leaf = CPUID4_INFO_IDX(sibling, index);
559 cpumask_clear_cpu(cpu,
560 to_cpumask(sibling_leaf->shared_cpu_map));
561 }
562 }
563 #else
564 static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
565 {
566 }
567
568 static void __cpuinit cache_remove_shared_cpu_map(unsigned int cpu, int index)
569 {
570 }
571 #endif
572
573 static void __cpuinit free_cache_attributes(unsigned int cpu)
574 {
575 int i;
576
577 for (i = 0; i < num_cache_leaves; i++)
578 cache_remove_shared_cpu_map(cpu, i);
579
580 kfree(per_cpu(ici_cpuid4_info, cpu));
581 per_cpu(ici_cpuid4_info, cpu) = NULL;
582 }
583
584 static int
585 __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
586 {
587 struct _cpuid4_info_regs *leaf_regs =
588 (struct _cpuid4_info_regs *)this_leaf;
589
590 return cpuid4_cache_lookup_regs(index, leaf_regs);
591 }
592
593 static void __cpuinit get_cpu_leaves(void *_retval)
594 {
595 int j, *retval = _retval, cpu = smp_processor_id();
596
597 /* Do cpuid and store the results */
598 for (j = 0; j < num_cache_leaves; j++) {
599 struct _cpuid4_info *this_leaf;
600 this_leaf = CPUID4_INFO_IDX(cpu, j);
601 *retval = cpuid4_cache_lookup(j, this_leaf);
602 if (unlikely(*retval < 0)) {
603 int i;
604
605 for (i = 0; i < j; i++)
606 cache_remove_shared_cpu_map(cpu, i);
607 break;
608 }
609 cache_shared_cpu_map_setup(cpu, j);
610 }
611 }
612
613 static int __cpuinit detect_cache_attributes(unsigned int cpu)
614 {
615 int retval;
616
617 if (num_cache_leaves == 0)
618 return -ENOENT;
619
620 per_cpu(ici_cpuid4_info, cpu) = kzalloc(
621 sizeof(struct _cpuid4_info) * num_cache_leaves, GFP_KERNEL);
622 if (per_cpu(ici_cpuid4_info, cpu) == NULL)
623 return -ENOMEM;
624
625 smp_call_function_single(cpu, get_cpu_leaves, &retval, true);
626 if (retval) {
627 kfree(per_cpu(ici_cpuid4_info, cpu));
628 per_cpu(ici_cpuid4_info, cpu) = NULL;
629 }
630
631 return retval;
632 }
633
634 #include <linux/kobject.h>
635 #include <linux/sysfs.h>
636
637 extern struct sysdev_class cpu_sysdev_class; /* from drivers/base/cpu.c */
638
639 /* pointer to kobject for cpuX/cache */
640 static DEFINE_PER_CPU(struct kobject *, ici_cache_kobject);
641
642 struct _index_kobject {
643 struct kobject kobj;
644 unsigned int cpu;
645 unsigned short index;
646 };
647
648 /* pointer to array of kobjects for cpuX/cache/indexY */
649 static DEFINE_PER_CPU(struct _index_kobject *, ici_index_kobject);
650 #define INDEX_KOBJECT_PTR(x, y) (&((per_cpu(ici_index_kobject, x))[y]))
651
652 #define show_one_plus(file_name, object, val) \
653 static ssize_t show_##file_name \
654 (struct _cpuid4_info *this_leaf, char *buf) \
655 { \
656 return sprintf(buf, "%lu\n", (unsigned long)this_leaf->object + val); \
657 }
658
659 show_one_plus(level, eax.split.level, 0);
660 show_one_plus(coherency_line_size, ebx.split.coherency_line_size, 1);
661 show_one_plus(physical_line_partition, ebx.split.physical_line_partition, 1);
662 show_one_plus(ways_of_associativity, ebx.split.ways_of_associativity, 1);
663 show_one_plus(number_of_sets, ecx.split.number_of_sets, 1);
664
665 static ssize_t show_size(struct _cpuid4_info *this_leaf, char *buf)
666 {
667 return sprintf(buf, "%luK\n", this_leaf->size / 1024);
668 }
669
670 static ssize_t show_shared_cpu_map_func(struct _cpuid4_info *this_leaf,
671 int type, char *buf)
672 {
673 ptrdiff_t len = PTR_ALIGN(buf + PAGE_SIZE - 1, PAGE_SIZE) - buf;
674 int n = 0;
675
676 if (len > 1) {
677 const struct cpumask *mask;
678
679 mask = to_cpumask(this_leaf->shared_cpu_map);
680 n = type ?
681 cpulist_scnprintf(buf, len-2, mask) :
682 cpumask_scnprintf(buf, len-2, mask);
683 buf[n++] = '\n';
684 buf[n] = '\0';
685 }
686 return n;
687 }
688
689 static inline ssize_t show_shared_cpu_map(struct _cpuid4_info *leaf, char *buf)
690 {
691 return show_shared_cpu_map_func(leaf, 0, buf);
692 }
693
694 static inline ssize_t show_shared_cpu_list(struct _cpuid4_info *leaf, char *buf)
695 {
696 return show_shared_cpu_map_func(leaf, 1, buf);
697 }
698
699 static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf)
700 {
701 switch (this_leaf->eax.split.type) {
702 case CACHE_TYPE_DATA:
703 return sprintf(buf, "Data\n");
704 case CACHE_TYPE_INST:
705 return sprintf(buf, "Instruction\n");
706 case CACHE_TYPE_UNIFIED:
707 return sprintf(buf, "Unified\n");
708 default:
709 return sprintf(buf, "Unknown\n");
710 }
711 }
712
713 #define to_object(k) container_of(k, struct _index_kobject, kobj)
714 #define to_attr(a) container_of(a, struct _cache_attr, attr)
715
716 static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf,
717 unsigned int index)
718 {
719 int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
720 int node = cpu_to_node(cpu);
721 struct pci_dev *dev = node_to_k8_nb_misc(node);
722 unsigned int reg = 0;
723
724 if (!this_leaf->can_disable)
725 return -EINVAL;
726
727 if (!dev)
728 return -EINVAL;
729
730 pci_read_config_dword(dev, 0x1BC + index * 4, &reg);
731 return sprintf(buf, "%x\n", reg);
732 }
733
734 #define SHOW_CACHE_DISABLE(index) \
735 static ssize_t \
736 show_cache_disable_##index(struct _cpuid4_info *this_leaf, char *buf) \
737 { \
738 return show_cache_disable(this_leaf, buf, index); \
739 }
740 SHOW_CACHE_DISABLE(0)
741 SHOW_CACHE_DISABLE(1)
742
743 static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
744 const char *buf, size_t count, unsigned int index)
745 {
746 int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
747 int node = cpu_to_node(cpu);
748 struct pci_dev *dev = node_to_k8_nb_misc(node);
749 unsigned long val = 0;
750 unsigned int scrubber = 0;
751
752 if (!this_leaf->can_disable)
753 return -EINVAL;
754
755 if (!capable(CAP_SYS_ADMIN))
756 return -EPERM;
757
758 if (!dev)
759 return -EINVAL;
760
761 if (strict_strtoul(buf, 10, &val) < 0)
762 return -EINVAL;
763
764 val |= 0xc0000000;
765
766 pci_read_config_dword(dev, 0x58, &scrubber);
767 scrubber &= ~0x1f000000;
768 pci_write_config_dword(dev, 0x58, scrubber);
769
770 pci_write_config_dword(dev, 0x1BC + index * 4, val & ~0x40000000);
771 wbinvd();
772 pci_write_config_dword(dev, 0x1BC + index * 4, val);
773 return count;
774 }
775
776 #define STORE_CACHE_DISABLE(index) \
777 static ssize_t \
778 store_cache_disable_##index(struct _cpuid4_info *this_leaf, \
779 const char *buf, size_t count) \
780 { \
781 return store_cache_disable(this_leaf, buf, count, index); \
782 }
783 STORE_CACHE_DISABLE(0)
784 STORE_CACHE_DISABLE(1)
785
786 struct _cache_attr {
787 struct attribute attr;
788 ssize_t (*show)(struct _cpuid4_info *, char *);
789 ssize_t (*store)(struct _cpuid4_info *, const char *, size_t count);
790 };
791
792 #define define_one_ro(_name) \
793 static struct _cache_attr _name = \
794 __ATTR(_name, 0444, show_##_name, NULL)
795
796 define_one_ro(level);
797 define_one_ro(type);
798 define_one_ro(coherency_line_size);
799 define_one_ro(physical_line_partition);
800 define_one_ro(ways_of_associativity);
801 define_one_ro(number_of_sets);
802 define_one_ro(size);
803 define_one_ro(shared_cpu_map);
804 define_one_ro(shared_cpu_list);
805
806 static struct _cache_attr cache_disable_0 = __ATTR(cache_disable_0, 0644,
807 show_cache_disable_0, store_cache_disable_0);
808 static struct _cache_attr cache_disable_1 = __ATTR(cache_disable_1, 0644,
809 show_cache_disable_1, store_cache_disable_1);
810
811 static struct attribute *default_attrs[] = {
812 &type.attr,
813 &level.attr,
814 &coherency_line_size.attr,
815 &physical_line_partition.attr,
816 &ways_of_associativity.attr,
817 &number_of_sets.attr,
818 &size.attr,
819 &shared_cpu_map.attr,
820 &shared_cpu_list.attr,
821 &cache_disable_0.attr,
822 &cache_disable_1.attr,
823 NULL
824 };
825
826 static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
827 {
828 struct _cache_attr *fattr = to_attr(attr);
829 struct _index_kobject *this_leaf = to_object(kobj);
830 ssize_t ret;
831
832 ret = fattr->show ?
833 fattr->show(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index),
834 buf) :
835 0;
836 return ret;
837 }
838
839 static ssize_t store(struct kobject *kobj, struct attribute *attr,
840 const char *buf, size_t count)
841 {
842 struct _cache_attr *fattr = to_attr(attr);
843 struct _index_kobject *this_leaf = to_object(kobj);
844 ssize_t ret;
845
846 ret = fattr->store ?
847 fattr->store(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index),
848 buf, count) :
849 0;
850 return ret;
851 }
852
853 static struct sysfs_ops sysfs_ops = {
854 .show = show,
855 .store = store,
856 };
857
858 static struct kobj_type ktype_cache = {
859 .sysfs_ops = &sysfs_ops,
860 .default_attrs = default_attrs,
861 };
862
863 static struct kobj_type ktype_percpu_entry = {
864 .sysfs_ops = &sysfs_ops,
865 };
866
867 static void __cpuinit cpuid4_cache_sysfs_exit(unsigned int cpu)
868 {
869 kfree(per_cpu(ici_cache_kobject, cpu));
870 kfree(per_cpu(ici_index_kobject, cpu));
871 per_cpu(ici_cache_kobject, cpu) = NULL;
872 per_cpu(ici_index_kobject, cpu) = NULL;
873 free_cache_attributes(cpu);
874 }
875
876 static int __cpuinit cpuid4_cache_sysfs_init(unsigned int cpu)
877 {
878 int err;
879
880 if (num_cache_leaves == 0)
881 return -ENOENT;
882
883 err = detect_cache_attributes(cpu);
884 if (err)
885 return err;
886
887 /* Allocate all required memory */
888 per_cpu(ici_cache_kobject, cpu) =
889 kzalloc(sizeof(struct kobject), GFP_KERNEL);
890 if (unlikely(per_cpu(ici_cache_kobject, cpu) == NULL))
891 goto err_out;
892
893 per_cpu(ici_index_kobject, cpu) = kzalloc(
894 sizeof(struct _index_kobject) * num_cache_leaves, GFP_KERNEL);
895 if (unlikely(per_cpu(ici_index_kobject, cpu) == NULL))
896 goto err_out;
897
898 return 0;
899
900 err_out:
901 cpuid4_cache_sysfs_exit(cpu);
902 return -ENOMEM;
903 }
904
905 static DECLARE_BITMAP(cache_dev_map, NR_CPUS);
906
907 /* Add/Remove cache interface for CPU device */
908 static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
909 {
910 unsigned int cpu = sys_dev->id;
911 unsigned long i, j;
912 struct _index_kobject *this_object;
913 int retval;
914
915 retval = cpuid4_cache_sysfs_init(cpu);
916 if (unlikely(retval < 0))
917 return retval;
918
919 retval = kobject_init_and_add(per_cpu(ici_cache_kobject, cpu),
920 &ktype_percpu_entry,
921 &sys_dev->kobj, "%s", "cache");
922 if (retval < 0) {
923 cpuid4_cache_sysfs_exit(cpu);
924 return retval;
925 }
926
927 for (i = 0; i < num_cache_leaves; i++) {
928 this_object = INDEX_KOBJECT_PTR(cpu, i);
929 this_object->cpu = cpu;
930 this_object->index = i;
931 retval = kobject_init_and_add(&(this_object->kobj),
932 &ktype_cache,
933 per_cpu(ici_cache_kobject, cpu),
934 "index%1lu", i);
935 if (unlikely(retval)) {
936 for (j = 0; j < i; j++)
937 kobject_put(&(INDEX_KOBJECT_PTR(cpu, j)->kobj));
938 kobject_put(per_cpu(ici_cache_kobject, cpu));
939 cpuid4_cache_sysfs_exit(cpu);
940 return retval;
941 }
942 kobject_uevent(&(this_object->kobj), KOBJ_ADD);
943 }
944 cpumask_set_cpu(cpu, to_cpumask(cache_dev_map));
945
946 kobject_uevent(per_cpu(ici_cache_kobject, cpu), KOBJ_ADD);
947 return 0;
948 }
949
950 static void __cpuinit cache_remove_dev(struct sys_device * sys_dev)
951 {
952 unsigned int cpu = sys_dev->id;
953 unsigned long i;
954
955 if (per_cpu(ici_cpuid4_info, cpu) == NULL)
956 return;
957 if (!cpumask_test_cpu(cpu, to_cpumask(cache_dev_map)))
958 return;
959 cpumask_clear_cpu(cpu, to_cpumask(cache_dev_map));
960
961 for (i = 0; i < num_cache_leaves; i++)
962 kobject_put(&(INDEX_KOBJECT_PTR(cpu, i)->kobj));
963 kobject_put(per_cpu(ici_cache_kobject, cpu));
964 cpuid4_cache_sysfs_exit(cpu);
965 }
966
967 static int __cpuinit cacheinfo_cpu_callback(struct notifier_block *nfb,
968 unsigned long action, void *hcpu)
969 {
970 unsigned int cpu = (unsigned long)hcpu;
971 struct sys_device *sys_dev;
972
973 sys_dev = get_cpu_sysdev(cpu);
974 switch (action) {
975 case CPU_ONLINE:
976 case CPU_ONLINE_FROZEN:
977 cache_add_dev(sys_dev);
978 break;
979 case CPU_DEAD:
980 case CPU_DEAD_FROZEN:
981 cache_remove_dev(sys_dev);
982 break;
983 }
984 return NOTIFY_OK;
985 }
986
987 static struct notifier_block __cpuinitdata cacheinfo_cpu_notifier = {
988 .notifier_call = cacheinfo_cpu_callback,
989 };
990
991 static int __cpuinit cache_sysfs_init(void)
992 {
993 int i;
994
995 if (num_cache_leaves == 0)
996 return 0;
997
998 for_each_online_cpu(i) {
999 int err;
1000 struct sys_device *sys_dev = get_cpu_sysdev(i);
1001
1002 err = cache_add_dev(sys_dev);
1003 if (err)
1004 return err;
1005 }
1006 register_hotcpu_notifier(&cacheinfo_cpu_notifier);
1007 return 0;
1008 }
1009
1010 device_initcall(cache_sysfs_init);
1011
1012 #endif
This page took 0.071245 seconds and 5 git commands to generate.