Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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, &regs[0], &regs[1], &regs[2], &regs[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.