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