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
17 #include <asm/processor.h>
18 #include <asm/smp.h>
19
20 #define LVL_1_INST 1
21 #define LVL_1_DATA 2
22 #define LVL_2 3
23 #define LVL_3 4
24 #define LVL_TRACE 5
25
26 struct _cache_table
27 {
28 unsigned char descriptor;
29 char cache_type;
30 short size;
31 };
32
33 /* all the cache descriptor types we care about (no TLB or trace cache entries) */
34 static struct _cache_table cache_table[] __cpuinitdata =
35 {
36 { 0x06, LVL_1_INST, 8 }, /* 4-way set assoc, 32 byte line size */
37 { 0x08, LVL_1_INST, 16 }, /* 4-way set assoc, 32 byte line size */
38 { 0x0a, LVL_1_DATA, 8 }, /* 2 way set assoc, 32 byte line size */
39 { 0x0c, LVL_1_DATA, 16 }, /* 4-way set assoc, 32 byte line size */
40 { 0x22, LVL_3, 512 }, /* 4-way set assoc, sectored cache, 64 byte line size */
41 { 0x23, LVL_3, 1024 }, /* 8-way set assoc, sectored cache, 64 byte line size */
42 { 0x25, LVL_3, 2048 }, /* 8-way set assoc, sectored cache, 64 byte line size */
43 { 0x29, LVL_3, 4096 }, /* 8-way set assoc, sectored cache, 64 byte line size */
44 { 0x2c, LVL_1_DATA, 32 }, /* 8-way set assoc, 64 byte line size */
45 { 0x30, LVL_1_INST, 32 }, /* 8-way set assoc, 64 byte line size */
46 { 0x39, LVL_2, 128 }, /* 4-way set assoc, sectored cache, 64 byte line size */
47 { 0x3a, LVL_2, 192 }, /* 6-way set assoc, sectored cache, 64 byte line size */
48 { 0x3b, LVL_2, 128 }, /* 2-way set assoc, sectored cache, 64 byte line size */
49 { 0x3c, LVL_2, 256 }, /* 4-way set assoc, sectored cache, 64 byte line size */
50 { 0x3d, LVL_2, 384 }, /* 6-way set assoc, sectored cache, 64 byte line size */
51 { 0x3e, LVL_2, 512 }, /* 4-way set assoc, sectored cache, 64 byte line size */
52 { 0x3f, LVL_2, 256 }, /* 2-way set assoc, 64 byte line size */
53 { 0x41, LVL_2, 128 }, /* 4-way set assoc, 32 byte line size */
54 { 0x42, LVL_2, 256 }, /* 4-way set assoc, 32 byte line size */
55 { 0x43, LVL_2, 512 }, /* 4-way set assoc, 32 byte line size */
56 { 0x44, LVL_2, 1024 }, /* 4-way set assoc, 32 byte line size */
57 { 0x45, LVL_2, 2048 }, /* 4-way set assoc, 32 byte line size */
58 { 0x46, LVL_3, 4096 }, /* 4-way set assoc, 64 byte line size */
59 { 0x47, LVL_3, 8192 }, /* 8-way set assoc, 64 byte line size */
60 { 0x49, LVL_3, 4096 }, /* 16-way set assoc, 64 byte line size */
61 { 0x4a, LVL_3, 6144 }, /* 12-way set assoc, 64 byte line size */
62 { 0x4b, LVL_3, 8192 }, /* 16-way set assoc, 64 byte line size */
63 { 0x4c, LVL_3, 12288 }, /* 12-way set assoc, 64 byte line size */
64 { 0x4d, LVL_3, 16384 }, /* 16-way set assoc, 64 byte line size */
65 { 0x60, LVL_1_DATA, 16 }, /* 8-way set assoc, sectored cache, 64 byte line size */
66 { 0x66, LVL_1_DATA, 8 }, /* 4-way set assoc, sectored cache, 64 byte line size */
67 { 0x67, LVL_1_DATA, 16 }, /* 4-way set assoc, sectored cache, 64 byte line size */
68 { 0x68, LVL_1_DATA, 32 }, /* 4-way set assoc, sectored cache, 64 byte line size */
69 { 0x70, LVL_TRACE, 12 }, /* 8-way set assoc */
70 { 0x71, LVL_TRACE, 16 }, /* 8-way set assoc */
71 { 0x72, LVL_TRACE, 32 }, /* 8-way set assoc */
72 { 0x73, LVL_TRACE, 64 }, /* 8-way set assoc */
73 { 0x78, LVL_2, 1024 }, /* 4-way set assoc, 64 byte line size */
74 { 0x79, LVL_2, 128 }, /* 8-way set assoc, sectored cache, 64 byte line size */
75 { 0x7a, LVL_2, 256 }, /* 8-way set assoc, sectored cache, 64 byte line size */
76 { 0x7b, LVL_2, 512 }, /* 8-way set assoc, sectored cache, 64 byte line size */
77 { 0x7c, LVL_2, 1024 }, /* 8-way set assoc, sectored cache, 64 byte line size */
78 { 0x7d, LVL_2, 2048 }, /* 8-way set assoc, 64 byte line size */
79 { 0x7f, LVL_2, 512 }, /* 2-way set assoc, 64 byte line size */
80 { 0x82, LVL_2, 256 }, /* 8-way set assoc, 32 byte line size */
81 { 0x83, LVL_2, 512 }, /* 8-way set assoc, 32 byte line size */
82 { 0x84, LVL_2, 1024 }, /* 8-way set assoc, 32 byte line size */
83 { 0x85, LVL_2, 2048 }, /* 8-way set assoc, 32 byte line size */
84 { 0x86, LVL_2, 512 }, /* 4-way set assoc, 64 byte line size */
85 { 0x87, LVL_2, 1024 }, /* 8-way set assoc, 64 byte line size */
86 { 0x00, 0, 0}
87 };
88
89
90 enum _cache_type
91 {
92 CACHE_TYPE_NULL = 0,
93 CACHE_TYPE_DATA = 1,
94 CACHE_TYPE_INST = 2,
95 CACHE_TYPE_UNIFIED = 3
96 };
97
98 union _cpuid4_leaf_eax {
99 struct {
100 enum _cache_type type:5;
101 unsigned int level:3;
102 unsigned int is_self_initializing:1;
103 unsigned int is_fully_associative:1;
104 unsigned int reserved:4;
105 unsigned int num_threads_sharing:12;
106 unsigned int num_cores_on_die:6;
107 } split;
108 u32 full;
109 };
110
111 union _cpuid4_leaf_ebx {
112 struct {
113 unsigned int coherency_line_size:12;
114 unsigned int physical_line_partition:10;
115 unsigned int ways_of_associativity:10;
116 } split;
117 u32 full;
118 };
119
120 union _cpuid4_leaf_ecx {
121 struct {
122 unsigned int number_of_sets:32;
123 } split;
124 u32 full;
125 };
126
127 struct _cpuid4_info {
128 union _cpuid4_leaf_eax eax;
129 union _cpuid4_leaf_ebx ebx;
130 union _cpuid4_leaf_ecx ecx;
131 unsigned long size;
132 cpumask_t shared_cpu_map;
133 };
134
135 unsigned short num_cache_leaves;
136
137 /* AMD doesn't have CPUID4. Emulate it here to report the same
138 information to the user. This makes some assumptions about the machine:
139 L2 not shared, no SMT etc. that is currently true on AMD CPUs.
140
141 In theory the TLBs could be reported as fake type (they are in "dummy").
142 Maybe later */
143 union l1_cache {
144 struct {
145 unsigned line_size : 8;
146 unsigned lines_per_tag : 8;
147 unsigned assoc : 8;
148 unsigned size_in_kb : 8;
149 };
150 unsigned val;
151 };
152
153 union l2_cache {
154 struct {
155 unsigned line_size : 8;
156 unsigned lines_per_tag : 4;
157 unsigned assoc : 4;
158 unsigned size_in_kb : 16;
159 };
160 unsigned val;
161 };
162
163 union l3_cache {
164 struct {
165 unsigned line_size : 8;
166 unsigned lines_per_tag : 4;
167 unsigned assoc : 4;
168 unsigned res : 2;
169 unsigned size_encoded : 14;
170 };
171 unsigned val;
172 };
173
174 static unsigned short assocs[] __cpuinitdata = {
175 [1] = 1, [2] = 2, [4] = 4, [6] = 8,
176 [8] = 16, [0xa] = 32, [0xb] = 48,
177 [0xc] = 64,
178 [0xf] = 0xffff // ??
179 };
180
181 static unsigned char levels[] __cpuinitdata = { 1, 1, 2, 3 };
182 static unsigned char types[] __cpuinitdata = { 1, 2, 3, 3 };
183
184 static void __cpuinit amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax,
185 union _cpuid4_leaf_ebx *ebx,
186 union _cpuid4_leaf_ecx *ecx)
187 {
188 unsigned dummy;
189 unsigned line_size, lines_per_tag, assoc, size_in_kb;
190 union l1_cache l1i, l1d;
191 union l2_cache l2;
192 union l3_cache l3;
193 union l1_cache *l1 = &l1d;
194
195 eax->full = 0;
196 ebx->full = 0;
197 ecx->full = 0;
198
199 cpuid(0x80000005, &dummy, &dummy, &l1d.val, &l1i.val);
200 cpuid(0x80000006, &dummy, &dummy, &l2.val, &l3.val);
201
202 switch (leaf) {
203 case 1:
204 l1 = &l1i;
205 case 0:
206 if (!l1->val)
207 return;
208 assoc = l1->assoc;
209 line_size = l1->line_size;
210 lines_per_tag = l1->lines_per_tag;
211 size_in_kb = l1->size_in_kb;
212 break;
213 case 2:
214 if (!l2.val)
215 return;
216 assoc = l2.assoc;
217 line_size = l2.line_size;
218 lines_per_tag = l2.lines_per_tag;
219 /* cpu_data has errata corrections for K7 applied */
220 size_in_kb = current_cpu_data.x86_cache_size;
221 break;
222 case 3:
223 if (!l3.val)
224 return;
225 assoc = l3.assoc;
226 line_size = l3.line_size;
227 lines_per_tag = l3.lines_per_tag;
228 size_in_kb = l3.size_encoded * 512;
229 break;
230 default:
231 return;
232 }
233
234 eax->split.is_self_initializing = 1;
235 eax->split.type = types[leaf];
236 eax->split.level = levels[leaf];
237 if (leaf == 3)
238 eax->split.num_threads_sharing = current_cpu_data.x86_max_cores - 1;
239 else
240 eax->split.num_threads_sharing = 0;
241 eax->split.num_cores_on_die = current_cpu_data.x86_max_cores - 1;
242
243
244 if (assoc == 0xf)
245 eax->split.is_fully_associative = 1;
246 ebx->split.coherency_line_size = line_size - 1;
247 ebx->split.ways_of_associativity = assocs[assoc] - 1;
248 ebx->split.physical_line_partition = lines_per_tag - 1;
249 ecx->split.number_of_sets = (size_in_kb * 1024) / line_size /
250 (ebx->split.ways_of_associativity + 1) - 1;
251 }
252
253 static int __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
254 {
255 union _cpuid4_leaf_eax eax;
256 union _cpuid4_leaf_ebx ebx;
257 union _cpuid4_leaf_ecx ecx;
258 unsigned edx;
259
260 if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
261 amd_cpuid4(index, &eax, &ebx, &ecx);
262 else
263 cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx);
264 if (eax.split.type == CACHE_TYPE_NULL)
265 return -EIO; /* better error ? */
266
267 this_leaf->eax = eax;
268 this_leaf->ebx = ebx;
269 this_leaf->ecx = ecx;
270 this_leaf->size = (ecx.split.number_of_sets + 1) *
271 (ebx.split.coherency_line_size + 1) *
272 (ebx.split.physical_line_partition + 1) *
273 (ebx.split.ways_of_associativity + 1);
274 return 0;
275 }
276
277 static int __cpuinit find_num_cache_leaves(void)
278 {
279 unsigned int eax, ebx, ecx, edx;
280 union _cpuid4_leaf_eax cache_eax;
281 int i = -1;
282
283 do {
284 ++i;
285 /* Do cpuid(4) loop to find out num_cache_leaves */
286 cpuid_count(4, i, &eax, &ebx, &ecx, &edx);
287 cache_eax.full = eax;
288 } while (cache_eax.split.type != CACHE_TYPE_NULL);
289 return i;
290 }
291
292 unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
293 {
294 unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */
295 unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */
296 unsigned int new_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */
297 unsigned int l2_id = 0, l3_id = 0, num_threads_sharing, index_msb;
298 #ifdef CONFIG_X86_HT
299 unsigned int cpu = c->cpu_index;
300 #endif
301
302 if (c->cpuid_level > 3) {
303 static int is_initialized;
304
305 if (is_initialized == 0) {
306 /* Init num_cache_leaves from boot CPU */
307 num_cache_leaves = find_num_cache_leaves();
308 is_initialized++;
309 }
310
311 /*
312 * Whenever possible use cpuid(4), deterministic cache
313 * parameters cpuid leaf to find the cache details
314 */
315 for (i = 0; i < num_cache_leaves; i++) {
316 struct _cpuid4_info this_leaf;
317
318 int retval;
319
320 retval = cpuid4_cache_lookup(i, &this_leaf);
321 if (retval >= 0) {
322 switch(this_leaf.eax.split.level) {
323 case 1:
324 if (this_leaf.eax.split.type ==
325 CACHE_TYPE_DATA)
326 new_l1d = this_leaf.size/1024;
327 else if (this_leaf.eax.split.type ==
328 CACHE_TYPE_INST)
329 new_l1i = this_leaf.size/1024;
330 break;
331 case 2:
332 new_l2 = this_leaf.size/1024;
333 num_threads_sharing = 1 + this_leaf.eax.split.num_threads_sharing;
334 index_msb = get_count_order(num_threads_sharing);
335 l2_id = c->apicid >> index_msb;
336 break;
337 case 3:
338 new_l3 = this_leaf.size/1024;
339 num_threads_sharing = 1 + this_leaf.eax.split.num_threads_sharing;
340 index_msb = get_count_order(num_threads_sharing);
341 l3_id = c->apicid >> index_msb;
342 break;
343 default:
344 break;
345 }
346 }
347 }
348 }
349 /*
350 * Don't use cpuid2 if cpuid4 is supported. For P4, we use cpuid2 for
351 * trace cache
352 */
353 if ((num_cache_leaves == 0 || c->x86 == 15) && c->cpuid_level > 1) {
354 /* supports eax=2 call */
355 int j, n;
356 unsigned int regs[4];
357 unsigned char *dp = (unsigned char *)regs;
358 int only_trace = 0;
359
360 if (num_cache_leaves != 0 && c->x86 == 15)
361 only_trace = 1;
362
363 /* Number of times to iterate */
364 n = cpuid_eax(2) & 0xFF;
365
366 for ( i = 0 ; i < n ; i++ ) {
367 cpuid(2, ®s[0], ®s[1], ®s[2], ®s[3]);
368
369 /* If bit 31 is set, this is an unknown format */
370 for ( j = 0 ; j < 3 ; j++ ) {
371 if (regs[j] & (1 << 31)) regs[j] = 0;
372 }
373
374 /* Byte 0 is level count, not a descriptor */
375 for ( j = 1 ; j < 16 ; j++ ) {
376 unsigned char des = dp[j];
377 unsigned char k = 0;
378
379 /* look up this descriptor in the table */
380 while (cache_table[k].descriptor != 0)
381 {
382 if (cache_table[k].descriptor == des) {
383 if (only_trace && cache_table[k].cache_type != LVL_TRACE)
384 break;
385 switch (cache_table[k].cache_type) {
386 case LVL_1_INST:
387 l1i += cache_table[k].size;
388 break;
389 case LVL_1_DATA:
390 l1d += cache_table[k].size;
391 break;
392 case LVL_2:
393 l2 += cache_table[k].size;
394 break;
395 case LVL_3:
396 l3 += cache_table[k].size;
397 break;
398 case LVL_TRACE:
399 trace += cache_table[k].size;
400 break;
401 }
402
403 break;
404 }
405
406 k++;
407 }
408 }
409 }
410 }
411
412 if (new_l1d)
413 l1d = new_l1d;
414
415 if (new_l1i)
416 l1i = new_l1i;
417
418 if (new_l2) {
419 l2 = new_l2;
420 #ifdef CONFIG_X86_HT
421 per_cpu(cpu_llc_id, cpu) = l2_id;
422 #endif
423 }
424
425 if (new_l3) {
426 l3 = new_l3;
427 #ifdef CONFIG_X86_HT
428 per_cpu(cpu_llc_id, cpu) = l3_id;
429 #endif
430 }
431
432 if (trace)
433 printk (KERN_INFO "CPU: Trace cache: %dK uops", trace);
434 else if ( l1i )
435 printk (KERN_INFO "CPU: L1 I cache: %dK", l1i);
436
437 if (l1d)
438 printk(", L1 D cache: %dK\n", l1d);
439 else
440 printk("\n");
441
442 if (l2)
443 printk(KERN_INFO "CPU: L2 cache: %dK\n", l2);
444
445 if (l3)
446 printk(KERN_INFO "CPU: L3 cache: %dK\n", l3);
447
448 c->x86_cache_size = l3 ? l3 : (l2 ? l2 : (l1i+l1d));
449
450 return l2;
451 }
452
453 /* pointer to _cpuid4_info array (for each cache leaf) */
454 static struct _cpuid4_info *cpuid4_info[NR_CPUS];
455 #define CPUID4_INFO_IDX(x,y) (&((cpuid4_info[x])[y]))
456
457 #ifdef CONFIG_SMP
458 static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
459 {
460 struct _cpuid4_info *this_leaf, *sibling_leaf;
461 unsigned long num_threads_sharing;
462 int index_msb, i;
463 struct cpuinfo_x86 *c = &cpu_data(cpu);
464
465 this_leaf = CPUID4_INFO_IDX(cpu, index);
466 num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing;
467
468 if (num_threads_sharing == 1)
469 cpu_set(cpu, this_leaf->shared_cpu_map);
470 else {
471 index_msb = get_count_order(num_threads_sharing);
472
473 for_each_online_cpu(i) {
474 if (cpu_data(i).apicid >> index_msb ==
475 c->apicid >> index_msb) {
476 cpu_set(i, this_leaf->shared_cpu_map);
477 if (i != cpu && cpuid4_info[i]) {
478 sibling_leaf = CPUID4_INFO_IDX(i, index);
479 cpu_set(cpu, sibling_leaf->shared_cpu_map);
480 }
481 }
482 }
483 }
484 }
485 static void __cpuinit cache_remove_shared_cpu_map(unsigned int cpu, int index)
486 {
487 struct _cpuid4_info *this_leaf, *sibling_leaf;
488 int sibling;
489
490 this_leaf = CPUID4_INFO_IDX(cpu, index);
491 for_each_cpu_mask(sibling, this_leaf->shared_cpu_map) {
492 sibling_leaf = CPUID4_INFO_IDX(sibling, index);
493 cpu_clear(cpu, sibling_leaf->shared_cpu_map);
494 }
495 }
496 #else
497 static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) {}
498 static void __cpuinit cache_remove_shared_cpu_map(unsigned int cpu, int index) {}
499 #endif
500
501 static void __cpuinit free_cache_attributes(unsigned int cpu)
502 {
503 int i;
504
505 for (i = 0; i < num_cache_leaves; i++)
506 cache_remove_shared_cpu_map(cpu, i);
507
508 kfree(cpuid4_info[cpu]);
509 cpuid4_info[cpu] = NULL;
510 }
511
512 static int __cpuinit detect_cache_attributes(unsigned int cpu)
513 {
514 struct _cpuid4_info *this_leaf;
515 unsigned long j;
516 int retval;
517 cpumask_t oldmask;
518
519 if (num_cache_leaves == 0)
520 return -ENOENT;
521
522 cpuid4_info[cpu] = kzalloc(
523 sizeof(struct _cpuid4_info) * num_cache_leaves, GFP_KERNEL);
524 if (cpuid4_info[cpu] == NULL)
525 return -ENOMEM;
526
527 oldmask = current->cpus_allowed;
528 retval = set_cpus_allowed(current, cpumask_of_cpu(cpu));
529 if (retval)
530 goto out;
531
532 /* Do cpuid and store the results */
533 for (j = 0; j < num_cache_leaves; j++) {
534 this_leaf = CPUID4_INFO_IDX(cpu, j);
535 retval = cpuid4_cache_lookup(j, this_leaf);
536 if (unlikely(retval < 0)) {
537 int i;
538
539 for (i = 0; i < j; i++)
540 cache_remove_shared_cpu_map(cpu, i);
541 break;
542 }
543 cache_shared_cpu_map_setup(cpu, j);
544 }
545 set_cpus_allowed(current, oldmask);
546
547 out:
548 if (retval) {
549 kfree(cpuid4_info[cpu]);
550 cpuid4_info[cpu] = NULL;
551 }
552
553 return retval;
554 }
555
556 #ifdef CONFIG_SYSFS
557
558 #include <linux/kobject.h>
559 #include <linux/sysfs.h>
560
561 extern struct sysdev_class cpu_sysdev_class; /* from drivers/base/cpu.c */
562
563 /* pointer to kobject for cpuX/cache */
564 static struct kobject * cache_kobject[NR_CPUS];
565
566 struct _index_kobject {
567 struct kobject kobj;
568 unsigned int cpu;
569 unsigned short index;
570 };
571
572 /* pointer to array of kobjects for cpuX/cache/indexY */
573 static struct _index_kobject *index_kobject[NR_CPUS];
574 #define INDEX_KOBJECT_PTR(x,y) (&((index_kobject[x])[y]))
575
576 #define show_one_plus(file_name, object, val) \
577 static ssize_t show_##file_name \
578 (struct _cpuid4_info *this_leaf, char *buf) \
579 { \
580 return sprintf (buf, "%lu\n", (unsigned long)this_leaf->object + val); \
581 }
582
583 show_one_plus(level, eax.split.level, 0);
584 show_one_plus(coherency_line_size, ebx.split.coherency_line_size, 1);
585 show_one_plus(physical_line_partition, ebx.split.physical_line_partition, 1);
586 show_one_plus(ways_of_associativity, ebx.split.ways_of_associativity, 1);
587 show_one_plus(number_of_sets, ecx.split.number_of_sets, 1);
588
589 static ssize_t show_size(struct _cpuid4_info *this_leaf, char *buf)
590 {
591 return sprintf (buf, "%luK\n", this_leaf->size / 1024);
592 }
593
594 static ssize_t show_shared_cpu_map(struct _cpuid4_info *this_leaf, char *buf)
595 {
596 char mask_str[NR_CPUS];
597 cpumask_scnprintf(mask_str, NR_CPUS, this_leaf->shared_cpu_map);
598 return sprintf(buf, "%s\n", mask_str);
599 }
600
601 static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf) {
602 switch(this_leaf->eax.split.type) {
603 case CACHE_TYPE_DATA:
604 return sprintf(buf, "Data\n");
605 break;
606 case CACHE_TYPE_INST:
607 return sprintf(buf, "Instruction\n");
608 break;
609 case CACHE_TYPE_UNIFIED:
610 return sprintf(buf, "Unified\n");
611 break;
612 default:
613 return sprintf(buf, "Unknown\n");
614 break;
615 }
616 }
617
618 struct _cache_attr {
619 struct attribute attr;
620 ssize_t (*show)(struct _cpuid4_info *, char *);
621 ssize_t (*store)(struct _cpuid4_info *, const char *, size_t count);
622 };
623
624 #define define_one_ro(_name) \
625 static struct _cache_attr _name = \
626 __ATTR(_name, 0444, show_##_name, NULL)
627
628 define_one_ro(level);
629 define_one_ro(type);
630 define_one_ro(coherency_line_size);
631 define_one_ro(physical_line_partition);
632 define_one_ro(ways_of_associativity);
633 define_one_ro(number_of_sets);
634 define_one_ro(size);
635 define_one_ro(shared_cpu_map);
636
637 static struct attribute * default_attrs[] = {
638 &type.attr,
639 &level.attr,
640 &coherency_line_size.attr,
641 &physical_line_partition.attr,
642 &ways_of_associativity.attr,
643 &number_of_sets.attr,
644 &size.attr,
645 &shared_cpu_map.attr,
646 NULL
647 };
648
649 #define to_object(k) container_of(k, struct _index_kobject, kobj)
650 #define to_attr(a) container_of(a, struct _cache_attr, attr)
651
652 static ssize_t show(struct kobject * kobj, struct attribute * attr, char * buf)
653 {
654 struct _cache_attr *fattr = to_attr(attr);
655 struct _index_kobject *this_leaf = to_object(kobj);
656 ssize_t ret;
657
658 ret = fattr->show ?
659 fattr->show(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index),
660 buf) :
661 0;
662 return ret;
663 }
664
665 static ssize_t store(struct kobject * kobj, struct attribute * attr,
666 const char * buf, size_t count)
667 {
668 return 0;
669 }
670
671 static struct sysfs_ops sysfs_ops = {
672 .show = show,
673 .store = store,
674 };
675
676 static struct kobj_type ktype_cache = {
677 .sysfs_ops = &sysfs_ops,
678 .default_attrs = default_attrs,
679 };
680
681 static struct kobj_type ktype_percpu_entry = {
682 .sysfs_ops = &sysfs_ops,
683 };
684
685 static void __cpuinit cpuid4_cache_sysfs_exit(unsigned int cpu)
686 {
687 kfree(cache_kobject[cpu]);
688 kfree(index_kobject[cpu]);
689 cache_kobject[cpu] = NULL;
690 index_kobject[cpu] = NULL;
691 free_cache_attributes(cpu);
692 }
693
694 static int __cpuinit cpuid4_cache_sysfs_init(unsigned int cpu)
695 {
696 int err;
697
698 if (num_cache_leaves == 0)
699 return -ENOENT;
700
701 err = detect_cache_attributes(cpu);
702 if (err)
703 return err;
704
705 /* Allocate all required memory */
706 cache_kobject[cpu] = kzalloc(sizeof(struct kobject), GFP_KERNEL);
707 if (unlikely(cache_kobject[cpu] == NULL))
708 goto err_out;
709
710 index_kobject[cpu] = kzalloc(
711 sizeof(struct _index_kobject ) * num_cache_leaves, GFP_KERNEL);
712 if (unlikely(index_kobject[cpu] == NULL))
713 goto err_out;
714
715 return 0;
716
717 err_out:
718 cpuid4_cache_sysfs_exit(cpu);
719 return -ENOMEM;
720 }
721
722 static cpumask_t cache_dev_map = CPU_MASK_NONE;
723
724 /* Add/Remove cache interface for CPU device */
725 static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
726 {
727 unsigned int cpu = sys_dev->id;
728 unsigned long i, j;
729 struct _index_kobject *this_object;
730 int retval;
731
732 retval = cpuid4_cache_sysfs_init(cpu);
733 if (unlikely(retval < 0))
734 return retval;
735
736 retval = kobject_init_and_add(cache_kobject[cpu], &ktype_percpu_entry,
737 &sys_dev->kobj, "%s", "cache");
738 if (retval < 0) {
739 cpuid4_cache_sysfs_exit(cpu);
740 return retval;
741 }
742
743 for (i = 0; i < num_cache_leaves; i++) {
744 this_object = INDEX_KOBJECT_PTR(cpu,i);
745 this_object->cpu = cpu;
746 this_object->index = i;
747 retval = kobject_init_and_add(&(this_object->kobj),
748 &ktype_cache, cache_kobject[cpu],
749 "index%1lu", i);
750 if (unlikely(retval)) {
751 for (j = 0; j < i; j++) {
752 kobject_put(&(INDEX_KOBJECT_PTR(cpu,j)->kobj));
753 }
754 kobject_put(cache_kobject[cpu]);
755 cpuid4_cache_sysfs_exit(cpu);
756 break;
757 }
758 kobject_uevent(&(this_object->kobj), KOBJ_ADD);
759 }
760 if (!retval)
761 cpu_set(cpu, cache_dev_map);
762
763 kobject_uevent(cache_kobject[cpu], KOBJ_ADD);
764 return retval;
765 }
766
767 static void __cpuinit cache_remove_dev(struct sys_device * sys_dev)
768 {
769 unsigned int cpu = sys_dev->id;
770 unsigned long i;
771
772 if (cpuid4_info[cpu] == NULL)
773 return;
774 if (!cpu_isset(cpu, cache_dev_map))
775 return;
776 cpu_clear(cpu, cache_dev_map);
777
778 for (i = 0; i < num_cache_leaves; i++)
779 kobject_put(&(INDEX_KOBJECT_PTR(cpu,i)->kobj));
780 kobject_put(cache_kobject[cpu]);
781 cpuid4_cache_sysfs_exit(cpu);
782 }
783
784 static int __cpuinit cacheinfo_cpu_callback(struct notifier_block *nfb,
785 unsigned long action, void *hcpu)
786 {
787 unsigned int cpu = (unsigned long)hcpu;
788 struct sys_device *sys_dev;
789
790 sys_dev = get_cpu_sysdev(cpu);
791 switch (action) {
792 case CPU_ONLINE:
793 case CPU_ONLINE_FROZEN:
794 cache_add_dev(sys_dev);
795 break;
796 case CPU_DEAD:
797 case CPU_DEAD_FROZEN:
798 cache_remove_dev(sys_dev);
799 break;
800 }
801 return NOTIFY_OK;
802 }
803
804 static struct notifier_block __cpuinitdata cacheinfo_cpu_notifier =
805 {
806 .notifier_call = cacheinfo_cpu_callback,
807 };
808
809 static int __cpuinit cache_sysfs_init(void)
810 {
811 int i;
812
813 if (num_cache_leaves == 0)
814 return 0;
815
816 for_each_online_cpu(i) {
817 int err;
818 struct sys_device *sys_dev = get_cpu_sysdev(i);
819
820 err = cache_add_dev(sys_dev);
821 if (err)
822 return err;
823 }
824 register_hotcpu_notifier(&cacheinfo_cpu_notifier);
825 return 0;
826 }
827
828 device_initcall(cache_sysfs_init);
829
830 #endif
831
|
This page was automatically generated by the
LXR engine.
|