Merge branch 'linus' into timers/core
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / arch / ia64 / kernel / palinfo.c
1 /*
2 * palinfo.c
3 *
4 * Prints processor specific information reported by PAL.
5 * This code is based on specification of PAL as of the
6 * Intel IA-64 Architecture Software Developer's Manual v1.0.
7 *
8 *
9 * Copyright (C) 2000-2001, 2003 Hewlett-Packard Co
10 * Stephane Eranian <eranian@hpl.hp.com>
11 * Copyright (C) 2004 Intel Corporation
12 * Ashok Raj <ashok.raj@intel.com>
13 *
14 * 05/26/2000 S.Eranian initial release
15 * 08/21/2000 S.Eranian updated to July 2000 PAL specs
16 * 02/05/2001 S.Eranian fixed module support
17 * 10/23/2001 S.Eranian updated pal_perf_mon_info bug fixes
18 * 03/24/2004 Ashok Raj updated to work with CPU Hotplug
19 * 10/26/2006 Russ Anderson updated processor features to rev 2.2 spec
20 */
21 #include <linux/types.h>
22 #include <linux/errno.h>
23 #include <linux/init.h>
24 #include <linux/proc_fs.h>
25 #include <linux/mm.h>
26 #include <linux/module.h>
27 #include <linux/efi.h>
28 #include <linux/notifier.h>
29 #include <linux/cpu.h>
30 #include <linux/cpumask.h>
31
32 #include <asm/pal.h>
33 #include <asm/sal.h>
34 #include <asm/page.h>
35 #include <asm/processor.h>
36 #include <linux/smp.h>
37
38 MODULE_AUTHOR("Stephane Eranian <eranian@hpl.hp.com>");
39 MODULE_DESCRIPTION("/proc interface to IA-64 PAL");
40 MODULE_LICENSE("GPL");
41
42 #define PALINFO_VERSION "0.5"
43
44 typedef int (*palinfo_func_t)(char*);
45
46 typedef struct {
47 const char *name; /* name of the proc entry */
48 palinfo_func_t proc_read; /* function to call for reading */
49 struct proc_dir_entry *entry; /* registered entry (removal) */
50 } palinfo_entry_t;
51
52
53 /*
54 * A bunch of string array to get pretty printing
55 */
56
57 static char *cache_types[] = {
58 "", /* not used */
59 "Instruction",
60 "Data",
61 "Data/Instruction" /* unified */
62 };
63
64 static const char *cache_mattrib[]={
65 "WriteThrough",
66 "WriteBack",
67 "", /* reserved */
68 "" /* reserved */
69 };
70
71 static const char *cache_st_hints[]={
72 "Temporal, level 1",
73 "Reserved",
74 "Reserved",
75 "Non-temporal, all levels",
76 "Reserved",
77 "Reserved",
78 "Reserved",
79 "Reserved"
80 };
81
82 static const char *cache_ld_hints[]={
83 "Temporal, level 1",
84 "Non-temporal, level 1",
85 "Reserved",
86 "Non-temporal, all levels",
87 "Reserved",
88 "Reserved",
89 "Reserved",
90 "Reserved"
91 };
92
93 static const char *rse_hints[]={
94 "enforced lazy",
95 "eager stores",
96 "eager loads",
97 "eager loads and stores"
98 };
99
100 #define RSE_HINTS_COUNT ARRAY_SIZE(rse_hints)
101
102 static const char *mem_attrib[]={
103 "WB", /* 000 */
104 "SW", /* 001 */
105 "010", /* 010 */
106 "011", /* 011 */
107 "UC", /* 100 */
108 "UCE", /* 101 */
109 "WC", /* 110 */
110 "NaTPage" /* 111 */
111 };
112
113 /*
114 * Take a 64bit vector and produces a string such that
115 * if bit n is set then 2^n in clear text is generated. The adjustment
116 * to the right unit is also done.
117 *
118 * Input:
119 * - a pointer to a buffer to hold the string
120 * - a 64-bit vector
121 * Ouput:
122 * - a pointer to the end of the buffer
123 *
124 */
125 static char *
126 bitvector_process(char *p, u64 vector)
127 {
128 int i,j;
129 const char *units[]={ "", "K", "M", "G", "T" };
130
131 for (i=0, j=0; i < 64; i++ , j=i/10) {
132 if (vector & 0x1) {
133 p += sprintf(p, "%d%s ", 1 << (i-j*10), units[j]);
134 }
135 vector >>= 1;
136 }
137 return p;
138 }
139
140 /*
141 * Take a 64bit vector and produces a string such that
142 * if bit n is set then register n is present. The function
143 * takes into account consecutive registers and prints out ranges.
144 *
145 * Input:
146 * - a pointer to a buffer to hold the string
147 * - a 64-bit vector
148 * Ouput:
149 * - a pointer to the end of the buffer
150 *
151 */
152 static char *
153 bitregister_process(char *p, u64 *reg_info, int max)
154 {
155 int i, begin, skip = 0;
156 u64 value = reg_info[0];
157
158 value >>= i = begin = ffs(value) - 1;
159
160 for(; i < max; i++ ) {
161
162 if (i != 0 && (i%64) == 0) value = *++reg_info;
163
164 if ((value & 0x1) == 0 && skip == 0) {
165 if (begin <= i - 2)
166 p += sprintf(p, "%d-%d ", begin, i-1);
167 else
168 p += sprintf(p, "%d ", i-1);
169 skip = 1;
170 begin = -1;
171 } else if ((value & 0x1) && skip == 1) {
172 skip = 0;
173 begin = i;
174 }
175 value >>=1;
176 }
177 if (begin > -1) {
178 if (begin < 127)
179 p += sprintf(p, "%d-127", begin);
180 else
181 p += sprintf(p, "127");
182 }
183
184 return p;
185 }
186
187 static int
188 power_info(char *page)
189 {
190 s64 status;
191 char *p = page;
192 u64 halt_info_buffer[8];
193 pal_power_mgmt_info_u_t *halt_info =(pal_power_mgmt_info_u_t *)halt_info_buffer;
194 int i;
195
196 status = ia64_pal_halt_info(halt_info);
197 if (status != 0) return 0;
198
199 for (i=0; i < 8 ; i++ ) {
200 if (halt_info[i].pal_power_mgmt_info_s.im == 1) {
201 p += sprintf(p, "Power level %d:\n"
202 "\tentry_latency : %d cycles\n"
203 "\texit_latency : %d cycles\n"
204 "\tpower consumption : %d mW\n"
205 "\tCache+TLB coherency : %s\n", i,
206 halt_info[i].pal_power_mgmt_info_s.entry_latency,
207 halt_info[i].pal_power_mgmt_info_s.exit_latency,
208 halt_info[i].pal_power_mgmt_info_s.power_consumption,
209 halt_info[i].pal_power_mgmt_info_s.co ? "Yes" : "No");
210 } else {
211 p += sprintf(p,"Power level %d: not implemented\n",i);
212 }
213 }
214 return p - page;
215 }
216
217 static int
218 cache_info(char *page)
219 {
220 char *p = page;
221 unsigned long i, levels, unique_caches;
222 pal_cache_config_info_t cci;
223 int j, k;
224 long status;
225
226 if ((status = ia64_pal_cache_summary(&levels, &unique_caches)) != 0) {
227 printk(KERN_ERR "ia64_pal_cache_summary=%ld\n", status);
228 return 0;
229 }
230
231 p += sprintf(p, "Cache levels : %ld\nUnique caches : %ld\n\n", levels, unique_caches);
232
233 for (i=0; i < levels; i++) {
234
235 for (j=2; j >0 ; j--) {
236
237 /* even without unification some level may not be present */
238 if ((status=ia64_pal_cache_config_info(i,j, &cci)) != 0) {
239 continue;
240 }
241 p += sprintf(p,
242 "%s Cache level %lu:\n"
243 "\tSize : %u bytes\n"
244 "\tAttributes : ",
245 cache_types[j+cci.pcci_unified], i+1,
246 cci.pcci_cache_size);
247
248 if (cci.pcci_unified) p += sprintf(p, "Unified ");
249
250 p += sprintf(p, "%s\n", cache_mattrib[cci.pcci_cache_attr]);
251
252 p += sprintf(p,
253 "\tAssociativity : %d\n"
254 "\tLine size : %d bytes\n"
255 "\tStride : %d bytes\n",
256 cci.pcci_assoc, 1<<cci.pcci_line_size, 1<<cci.pcci_stride);
257 if (j == 1)
258 p += sprintf(p, "\tStore latency : N/A\n");
259 else
260 p += sprintf(p, "\tStore latency : %d cycle(s)\n",
261 cci.pcci_st_latency);
262
263 p += sprintf(p,
264 "\tLoad latency : %d cycle(s)\n"
265 "\tStore hints : ", cci.pcci_ld_latency);
266
267 for(k=0; k < 8; k++ ) {
268 if ( cci.pcci_st_hints & 0x1)
269 p += sprintf(p, "[%s]", cache_st_hints[k]);
270 cci.pcci_st_hints >>=1;
271 }
272 p += sprintf(p, "\n\tLoad hints : ");
273
274 for(k=0; k < 8; k++ ) {
275 if (cci.pcci_ld_hints & 0x1)
276 p += sprintf(p, "[%s]", cache_ld_hints[k]);
277 cci.pcci_ld_hints >>=1;
278 }
279 p += sprintf(p,
280 "\n\tAlias boundary : %d byte(s)\n"
281 "\tTag LSB : %d\n"
282 "\tTag MSB : %d\n",
283 1<<cci.pcci_alias_boundary, cci.pcci_tag_lsb,
284 cci.pcci_tag_msb);
285
286 /* when unified, data(j=2) is enough */
287 if (cci.pcci_unified) break;
288 }
289 }
290 return p - page;
291 }
292
293
294 static int
295 vm_info(char *page)
296 {
297 char *p = page;
298 u64 tr_pages =0, vw_pages=0, tc_pages;
299 u64 attrib;
300 pal_vm_info_1_u_t vm_info_1;
301 pal_vm_info_2_u_t vm_info_2;
302 pal_tc_info_u_t tc_info;
303 ia64_ptce_info_t ptce;
304 const char *sep;
305 int i, j;
306 long status;
307
308 if ((status = ia64_pal_vm_summary(&vm_info_1, &vm_info_2)) !=0) {
309 printk(KERN_ERR "ia64_pal_vm_summary=%ld\n", status);
310 } else {
311
312 p += sprintf(p,
313 "Physical Address Space : %d bits\n"
314 "Virtual Address Space : %d bits\n"
315 "Protection Key Registers(PKR) : %d\n"
316 "Implemented bits in PKR.key : %d\n"
317 "Hash Tag ID : 0x%x\n"
318 "Size of RR.rid : %d\n"
319 "Max Purges : ",
320 vm_info_1.pal_vm_info_1_s.phys_add_size,
321 vm_info_2.pal_vm_info_2_s.impl_va_msb+1,
322 vm_info_1.pal_vm_info_1_s.max_pkr+1,
323 vm_info_1.pal_vm_info_1_s.key_size,
324 vm_info_1.pal_vm_info_1_s.hash_tag_id,
325 vm_info_2.pal_vm_info_2_s.rid_size);
326 if (vm_info_2.pal_vm_info_2_s.max_purges == PAL_MAX_PURGES)
327 p += sprintf(p, "unlimited\n");
328 else
329 p += sprintf(p, "%d\n",
330 vm_info_2.pal_vm_info_2_s.max_purges ?
331 vm_info_2.pal_vm_info_2_s.max_purges : 1);
332 }
333
334 if (ia64_pal_mem_attrib(&attrib) == 0) {
335 p += sprintf(p, "Supported memory attributes : ");
336 sep = "";
337 for (i = 0; i < 8; i++) {
338 if (attrib & (1 << i)) {
339 p += sprintf(p, "%s%s", sep, mem_attrib[i]);
340 sep = ", ";
341 }
342 }
343 p += sprintf(p, "\n");
344 }
345
346 if ((status = ia64_pal_vm_page_size(&tr_pages, &vw_pages)) !=0) {
347 printk(KERN_ERR "ia64_pal_vm_page_size=%ld\n", status);
348 } else {
349
350 p += sprintf(p,
351 "\nTLB walker : %simplemented\n"
352 "Number of DTR : %d\n"
353 "Number of ITR : %d\n"
354 "TLB insertable page sizes : ",
355 vm_info_1.pal_vm_info_1_s.vw ? "" : "not ",
356 vm_info_1.pal_vm_info_1_s.max_dtr_entry+1,
357 vm_info_1.pal_vm_info_1_s.max_itr_entry+1);
358
359
360 p = bitvector_process(p, tr_pages);
361
362 p += sprintf(p, "\nTLB purgeable page sizes : ");
363
364 p = bitvector_process(p, vw_pages);
365 }
366 if ((status=ia64_get_ptce(&ptce)) != 0) {
367 printk(KERN_ERR "ia64_get_ptce=%ld\n", status);
368 } else {
369 p += sprintf(p,
370 "\nPurge base address : 0x%016lx\n"
371 "Purge outer loop count : %d\n"
372 "Purge inner loop count : %d\n"
373 "Purge outer loop stride : %d\n"
374 "Purge inner loop stride : %d\n",
375 ptce.base, ptce.count[0], ptce.count[1],
376 ptce.stride[0], ptce.stride[1]);
377
378 p += sprintf(p,
379 "TC Levels : %d\n"
380 "Unique TC(s) : %d\n",
381 vm_info_1.pal_vm_info_1_s.num_tc_levels,
382 vm_info_1.pal_vm_info_1_s.max_unique_tcs);
383
384 for(i=0; i < vm_info_1.pal_vm_info_1_s.num_tc_levels; i++) {
385 for (j=2; j>0 ; j--) {
386 tc_pages = 0; /* just in case */
387
388
389 /* even without unification, some levels may not be present */
390 if ((status=ia64_pal_vm_info(i,j, &tc_info, &tc_pages)) != 0) {
391 continue;
392 }
393
394 p += sprintf(p,
395 "\n%s Translation Cache Level %d:\n"
396 "\tHash sets : %d\n"
397 "\tAssociativity : %d\n"
398 "\tNumber of entries : %d\n"
399 "\tFlags : ",
400 cache_types[j+tc_info.tc_unified], i+1,
401 tc_info.tc_num_sets,
402 tc_info.tc_associativity,
403 tc_info.tc_num_entries);
404
405 if (tc_info.tc_pf)
406 p += sprintf(p, "PreferredPageSizeOptimized ");
407 if (tc_info.tc_unified)
408 p += sprintf(p, "Unified ");
409 if (tc_info.tc_reduce_tr)
410 p += sprintf(p, "TCReduction");
411
412 p += sprintf(p, "\n\tSupported page sizes: ");
413
414 p = bitvector_process(p, tc_pages);
415
416 /* when unified date (j=2) is enough */
417 if (tc_info.tc_unified)
418 break;
419 }
420 }
421 }
422 p += sprintf(p, "\n");
423
424 return p - page;
425 }
426
427
428 static int
429 register_info(char *page)
430 {
431 char *p = page;
432 u64 reg_info[2];
433 u64 info;
434 unsigned long phys_stacked;
435 pal_hints_u_t hints;
436 unsigned long iregs, dregs;
437 static const char * const info_type[] = {
438 "Implemented AR(s)",
439 "AR(s) with read side-effects",
440 "Implemented CR(s)",
441 "CR(s) with read side-effects",
442 };
443
444 for(info=0; info < 4; info++) {
445
446 if (ia64_pal_register_info(info, &reg_info[0], &reg_info[1]) != 0) return 0;
447
448 p += sprintf(p, "%-32s : ", info_type[info]);
449
450 p = bitregister_process(p, reg_info, 128);
451
452 p += sprintf(p, "\n");
453 }
454
455 if (ia64_pal_rse_info(&phys_stacked, &hints) == 0) {
456
457 p += sprintf(p,
458 "RSE stacked physical registers : %ld\n"
459 "RSE load/store hints : %ld (%s)\n",
460 phys_stacked, hints.ph_data,
461 hints.ph_data < RSE_HINTS_COUNT ? rse_hints[hints.ph_data]: "(??)");
462 }
463 if (ia64_pal_debug_info(&iregs, &dregs))
464 return 0;
465
466 p += sprintf(p,
467 "Instruction debug register pairs : %ld\n"
468 "Data debug register pairs : %ld\n", iregs, dregs);
469
470 return p - page;
471 }
472
473 static char *proc_features_0[]={ /* Feature set 0 */
474 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
475 NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,
476 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
477 NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,
478 "Unimplemented instruction address fault",
479 "INIT, PMI, and LINT pins",
480 "Simple unimplemented instr addresses",
481 "Variable P-state performance",
482 "Virtual machine features implemented",
483 "XIP,XPSR,XFS implemented",
484 "XR1-XR3 implemented",
485 "Disable dynamic predicate prediction",
486 "Disable processor physical number",
487 "Disable dynamic data cache prefetch",
488 "Disable dynamic inst cache prefetch",
489 "Disable dynamic branch prediction",
490 NULL, NULL, NULL, NULL,
491 "Disable P-states",
492 "Enable MCA on Data Poisoning",
493 "Enable vmsw instruction",
494 "Enable extern environmental notification",
495 "Disable BINIT on processor time-out",
496 "Disable dynamic power management (DPM)",
497 "Disable coherency",
498 "Disable cache",
499 "Enable CMCI promotion",
500 "Enable MCA to BINIT promotion",
501 "Enable MCA promotion",
502 "Enable BERR promotion"
503 };
504
505 static char *proc_features_16[]={ /* Feature set 16 */
506 "Disable ETM",
507 "Enable ETM",
508 "Enable MCA on half-way timer",
509 "Enable snoop WC",
510 NULL,
511 "Enable Fast Deferral",
512 "Disable MCA on memory aliasing",
513 "Enable RSB",
514 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
515 "DP system processor",
516 "Low Voltage",
517 "HT supported",
518 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
519 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
520 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
521 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
522 NULL, NULL, NULL, NULL, NULL
523 };
524
525 static char **proc_features[]={
526 proc_features_0,
527 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
528 NULL, NULL, NULL, NULL,
529 proc_features_16,
530 NULL, NULL, NULL, NULL,
531 };
532
533 static char * feature_set_info(char *page, u64 avail, u64 status, u64 control,
534 unsigned long set)
535 {
536 char *p = page;
537 char **vf, **v;
538 int i;
539
540 vf = v = proc_features[set];
541 for(i=0; i < 64; i++, avail >>=1, status >>=1, control >>=1) {
542
543 if (!(control)) /* No remaining bits set */
544 break;
545 if (!(avail & 0x1)) /* Print only bits that are available */
546 continue;
547 if (vf)
548 v = vf + i;
549 if ( v && *v ) {
550 p += sprintf(p, "%-40s : %s %s\n", *v,
551 avail & 0x1 ? (status & 0x1 ?
552 "On " : "Off"): "",
553 avail & 0x1 ? (control & 0x1 ?
554 "Ctrl" : "NoCtrl"): "");
555 } else {
556 p += sprintf(p, "Feature set %2ld bit %2d\t\t\t"
557 " : %s %s\n",
558 set, i,
559 avail & 0x1 ? (status & 0x1 ?
560 "On " : "Off"): "",
561 avail & 0x1 ? (control & 0x1 ?
562 "Ctrl" : "NoCtrl"): "");
563 }
564 }
565 return p;
566 }
567
568 static int
569 processor_info(char *page)
570 {
571 char *p = page;
572 u64 avail=1, status=1, control=1, feature_set=0;
573 s64 ret;
574
575 do {
576 ret = ia64_pal_proc_get_features(&avail, &status, &control,
577 feature_set);
578 if (ret < 0) {
579 return p - page;
580 }
581 if (ret == 1) {
582 feature_set++;
583 continue;
584 }
585
586 p = feature_set_info(p, avail, status, control, feature_set);
587
588 feature_set++;
589 } while(1);
590
591 return p - page;
592 }
593
594 static const char *bus_features[]={
595 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
596 NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,
597 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
598 NULL,NULL,
599 "Request Bus Parking",
600 "Bus Lock Mask",
601 "Enable Half Transfer",
602 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
603 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
604 NULL, NULL, NULL, NULL,
605 "Enable Cache Line Repl. Shared",
606 "Enable Cache Line Repl. Exclusive",
607 "Disable Transaction Queuing",
608 "Disable Response Error Checking",
609 "Disable Bus Error Checking",
610 "Disable Bus Requester Internal Error Signalling",
611 "Disable Bus Requester Error Signalling",
612 "Disable Bus Initialization Event Checking",
613 "Disable Bus Initialization Event Signalling",
614 "Disable Bus Address Error Checking",
615 "Disable Bus Address Error Signalling",
616 "Disable Bus Data Error Checking"
617 };
618
619
620 static int
621 bus_info(char *page)
622 {
623 char *p = page;
624 const char **v = bus_features;
625 pal_bus_features_u_t av, st, ct;
626 u64 avail, status, control;
627 int i;
628 s64 ret;
629
630 if ((ret=ia64_pal_bus_get_features(&av, &st, &ct)) != 0) return 0;
631
632 avail = av.pal_bus_features_val;
633 status = st.pal_bus_features_val;
634 control = ct.pal_bus_features_val;
635
636 for(i=0; i < 64; i++, v++, avail >>=1, status >>=1, control >>=1) {
637 if ( ! *v ) continue;
638 p += sprintf(p, "%-48s : %s%s %s\n", *v,
639 avail & 0x1 ? "" : "NotImpl",
640 avail & 0x1 ? (status & 0x1 ? "On" : "Off"): "",
641 avail & 0x1 ? (control & 0x1 ? "Ctrl" : "NoCtrl"): "");
642 }
643 return p - page;
644 }
645
646 static int
647 version_info(char *page)
648 {
649 pal_version_u_t min_ver, cur_ver;
650 char *p = page;
651
652 if (ia64_pal_version(&min_ver, &cur_ver) != 0)
653 return 0;
654
655 p += sprintf(p,
656 "PAL_vendor : 0x%02x (min=0x%02x)\n"
657 "PAL_A : %02x.%02x (min=%02x.%02x)\n"
658 "PAL_B : %02x.%02x (min=%02x.%02x)\n",
659 cur_ver.pal_version_s.pv_pal_vendor,
660 min_ver.pal_version_s.pv_pal_vendor,
661 cur_ver.pal_version_s.pv_pal_a_model,
662 cur_ver.pal_version_s.pv_pal_a_rev,
663 min_ver.pal_version_s.pv_pal_a_model,
664 min_ver.pal_version_s.pv_pal_a_rev,
665 cur_ver.pal_version_s.pv_pal_b_model,
666 cur_ver.pal_version_s.pv_pal_b_rev,
667 min_ver.pal_version_s.pv_pal_b_model,
668 min_ver.pal_version_s.pv_pal_b_rev);
669 return p - page;
670 }
671
672 static int
673 perfmon_info(char *page)
674 {
675 char *p = page;
676 u64 pm_buffer[16];
677 pal_perf_mon_info_u_t pm_info;
678
679 if (ia64_pal_perf_mon_info(pm_buffer, &pm_info) != 0) return 0;
680
681 p += sprintf(p,
682 "PMC/PMD pairs : %d\n"
683 "Counter width : %d bits\n"
684 "Cycle event number : %d\n"
685 "Retired event number : %d\n"
686 "Implemented PMC : ",
687 pm_info.pal_perf_mon_info_s.generic, pm_info.pal_perf_mon_info_s.width,
688 pm_info.pal_perf_mon_info_s.cycles, pm_info.pal_perf_mon_info_s.retired);
689
690 p = bitregister_process(p, pm_buffer, 256);
691 p += sprintf(p, "\nImplemented PMD : ");
692 p = bitregister_process(p, pm_buffer+4, 256);
693 p += sprintf(p, "\nCycles count capable : ");
694 p = bitregister_process(p, pm_buffer+8, 256);
695 p += sprintf(p, "\nRetired bundles count capable : ");
696
697 #ifdef CONFIG_ITANIUM
698 /*
699 * PAL_PERF_MON_INFO reports that only PMC4 can be used to count CPU_CYCLES
700 * which is wrong, both PMC4 and PMD5 support it.
701 */
702 if (pm_buffer[12] == 0x10) pm_buffer[12]=0x30;
703 #endif
704
705 p = bitregister_process(p, pm_buffer+12, 256);
706
707 p += sprintf(p, "\n");
708
709 return p - page;
710 }
711
712 static int
713 frequency_info(char *page)
714 {
715 char *p = page;
716 struct pal_freq_ratio proc, itc, bus;
717 unsigned long base;
718
719 if (ia64_pal_freq_base(&base) == -1)
720 p += sprintf(p, "Output clock : not implemented\n");
721 else
722 p += sprintf(p, "Output clock : %ld ticks/s\n", base);
723
724 if (ia64_pal_freq_ratios(&proc, &bus, &itc) != 0) return 0;
725
726 p += sprintf(p,
727 "Processor/Clock ratio : %d/%d\n"
728 "Bus/Clock ratio : %d/%d\n"
729 "ITC/Clock ratio : %d/%d\n",
730 proc.num, proc.den, bus.num, bus.den, itc.num, itc.den);
731
732 return p - page;
733 }
734
735 static int
736 tr_info(char *page)
737 {
738 char *p = page;
739 long status;
740 pal_tr_valid_u_t tr_valid;
741 u64 tr_buffer[4];
742 pal_vm_info_1_u_t vm_info_1;
743 pal_vm_info_2_u_t vm_info_2;
744 unsigned long i, j;
745 unsigned long max[3], pgm;
746 struct ifa_reg {
747 unsigned long valid:1;
748 unsigned long ig:11;
749 unsigned long vpn:52;
750 } *ifa_reg;
751 struct itir_reg {
752 unsigned long rv1:2;
753 unsigned long ps:6;
754 unsigned long key:24;
755 unsigned long rv2:32;
756 } *itir_reg;
757 struct gr_reg {
758 unsigned long p:1;
759 unsigned long rv1:1;
760 unsigned long ma:3;
761 unsigned long a:1;
762 unsigned long d:1;
763 unsigned long pl:2;
764 unsigned long ar:3;
765 unsigned long ppn:38;
766 unsigned long rv2:2;
767 unsigned long ed:1;
768 unsigned long ig:11;
769 } *gr_reg;
770 struct rid_reg {
771 unsigned long ig1:1;
772 unsigned long rv1:1;
773 unsigned long ig2:6;
774 unsigned long rid:24;
775 unsigned long rv2:32;
776 } *rid_reg;
777
778 if ((status = ia64_pal_vm_summary(&vm_info_1, &vm_info_2)) !=0) {
779 printk(KERN_ERR "ia64_pal_vm_summary=%ld\n", status);
780 return 0;
781 }
782 max[0] = vm_info_1.pal_vm_info_1_s.max_itr_entry+1;
783 max[1] = vm_info_1.pal_vm_info_1_s.max_dtr_entry+1;
784
785 for (i=0; i < 2; i++ ) {
786 for (j=0; j < max[i]; j++) {
787
788 status = ia64_pal_tr_read(j, i, tr_buffer, &tr_valid);
789 if (status != 0) {
790 printk(KERN_ERR "palinfo: pal call failed on tr[%lu:%lu]=%ld\n",
791 i, j, status);
792 continue;
793 }
794
795 ifa_reg = (struct ifa_reg *)&tr_buffer[2];
796
797 if (ifa_reg->valid == 0) continue;
798
799 gr_reg = (struct gr_reg *)tr_buffer;
800 itir_reg = (struct itir_reg *)&tr_buffer[1];
801 rid_reg = (struct rid_reg *)&tr_buffer[3];
802
803 pgm = -1 << (itir_reg->ps - 12);
804 p += sprintf(p,
805 "%cTR%lu: av=%d pv=%d dv=%d mv=%d\n"
806 "\tppn : 0x%lx\n"
807 "\tvpn : 0x%lx\n"
808 "\tps : ",
809 "ID"[i], j,
810 tr_valid.pal_tr_valid_s.access_rights_valid,
811 tr_valid.pal_tr_valid_s.priv_level_valid,
812 tr_valid.pal_tr_valid_s.dirty_bit_valid,
813 tr_valid.pal_tr_valid_s.mem_attr_valid,
814 (gr_reg->ppn & pgm)<< 12, (ifa_reg->vpn & pgm)<< 12);
815
816 p = bitvector_process(p, 1<< itir_reg->ps);
817
818 p += sprintf(p,
819 "\n\tpl : %d\n"
820 "\tar : %d\n"
821 "\trid : %x\n"
822 "\tp : %d\n"
823 "\tma : %d\n"
824 "\td : %d\n",
825 gr_reg->pl, gr_reg->ar, rid_reg->rid, gr_reg->p, gr_reg->ma,
826 gr_reg->d);
827 }
828 }
829 return p - page;
830 }
831
832
833
834 /*
835 * List {name,function} pairs for every entry in /proc/palinfo/cpu*
836 */
837 static palinfo_entry_t palinfo_entries[]={
838 { "version_info", version_info, },
839 { "vm_info", vm_info, },
840 { "cache_info", cache_info, },
841 { "power_info", power_info, },
842 { "register_info", register_info, },
843 { "processor_info", processor_info, },
844 { "perfmon_info", perfmon_info, },
845 { "frequency_info", frequency_info, },
846 { "bus_info", bus_info },
847 { "tr_info", tr_info, }
848 };
849
850 #define NR_PALINFO_ENTRIES (int) ARRAY_SIZE(palinfo_entries)
851
852 static struct proc_dir_entry *palinfo_dir;
853
854 /*
855 * This data structure is used to pass which cpu,function is being requested
856 * It must fit in a 64bit quantity to be passed to the proc callback routine
857 *
858 * In SMP mode, when we get a request for another CPU, we must call that
859 * other CPU using IPI and wait for the result before returning.
860 */
861 typedef union {
862 u64 value;
863 struct {
864 unsigned req_cpu: 32; /* for which CPU this info is */
865 unsigned func_id: 32; /* which function is requested */
866 } pal_func_cpu;
867 } pal_func_cpu_u_t;
868
869 #define req_cpu pal_func_cpu.req_cpu
870 #define func_id pal_func_cpu.func_id
871
872 #ifdef CONFIG_SMP
873
874 /*
875 * used to hold information about final function to call
876 */
877 typedef struct {
878 palinfo_func_t func; /* pointer to function to call */
879 char *page; /* buffer to store results */
880 int ret; /* return value from call */
881 } palinfo_smp_data_t;
882
883
884 /*
885 * this function does the actual final call and he called
886 * from the smp code, i.e., this is the palinfo callback routine
887 */
888 static void
889 palinfo_smp_call(void *info)
890 {
891 palinfo_smp_data_t *data = (palinfo_smp_data_t *)info;
892 data->ret = (*data->func)(data->page);
893 }
894
895 /*
896 * function called to trigger the IPI, we need to access a remote CPU
897 * Return:
898 * 0 : error or nothing to output
899 * otherwise how many bytes in the "page" buffer were written
900 */
901 static
902 int palinfo_handle_smp(pal_func_cpu_u_t *f, char *page)
903 {
904 palinfo_smp_data_t ptr;
905 int ret;
906
907 ptr.func = palinfo_entries[f->func_id].proc_read;
908 ptr.page = page;
909 ptr.ret = 0; /* just in case */
910
911
912 /* will send IPI to other CPU and wait for completion of remote call */
913 if ((ret=smp_call_function_single(f->req_cpu, palinfo_smp_call, &ptr, 1))) {
914 printk(KERN_ERR "palinfo: remote CPU call from %d to %d on function %d: "
915 "error %d\n", smp_processor_id(), f->req_cpu, f->func_id, ret);
916 return 0;
917 }
918 return ptr.ret;
919 }
920 #else /* ! CONFIG_SMP */
921 static
922 int palinfo_handle_smp(pal_func_cpu_u_t *f, char *page)
923 {
924 printk(KERN_ERR "palinfo: should not be called with non SMP kernel\n");
925 return 0;
926 }
927 #endif /* CONFIG_SMP */
928
929 /*
930 * Entry point routine: all calls go through this function
931 */
932 static int
933 palinfo_read_entry(char *page, char **start, off_t off, int count, int *eof, void *data)
934 {
935 int len=0;
936 pal_func_cpu_u_t *f = (pal_func_cpu_u_t *)&data;
937
938 /*
939 * in SMP mode, we may need to call another CPU to get correct
940 * information. PAL, by definition, is processor specific
941 */
942 if (f->req_cpu == get_cpu())
943 len = (*palinfo_entries[f->func_id].proc_read)(page);
944 else
945 len = palinfo_handle_smp(f, page);
946
947 put_cpu();
948
949 if (len <= off+count) *eof = 1;
950
951 *start = page + off;
952 len -= off;
953
954 if (len>count) len = count;
955 if (len<0) len = 0;
956
957 return len;
958 }
959
960 static void __cpuinit
961 create_palinfo_proc_entries(unsigned int cpu)
962 {
963 pal_func_cpu_u_t f;
964 struct proc_dir_entry *cpu_dir;
965 int j;
966 char cpustr[3+4+1]; /* cpu numbers are up to 4095 on itanic */
967 sprintf(cpustr, "cpu%d", cpu);
968
969 cpu_dir = proc_mkdir(cpustr, palinfo_dir);
970 if (!cpu_dir)
971 return;
972
973 f.req_cpu = cpu;
974
975 for (j=0; j < NR_PALINFO_ENTRIES; j++) {
976 f.func_id = j;
977 create_proc_read_entry(
978 palinfo_entries[j].name, 0, cpu_dir,
979 palinfo_read_entry, (void *)f.value);
980 }
981 }
982
983 static void
984 remove_palinfo_proc_entries(unsigned int hcpu)
985 {
986 char cpustr[3+4+1]; /* cpu numbers are up to 4095 on itanic */
987 sprintf(cpustr, "cpu%d", hcpu);
988 remove_proc_subtree(cpustr, palinfo_dir);
989 }
990
991 static int __cpuinit palinfo_cpu_callback(struct notifier_block *nfb,
992 unsigned long action, void *hcpu)
993 {
994 unsigned int hotcpu = (unsigned long)hcpu;
995
996 switch (action) {
997 case CPU_ONLINE:
998 case CPU_ONLINE_FROZEN:
999 create_palinfo_proc_entries(hotcpu);
1000 break;
1001 case CPU_DEAD:
1002 case CPU_DEAD_FROZEN:
1003 remove_palinfo_proc_entries(hotcpu);
1004 break;
1005 }
1006 return NOTIFY_OK;
1007 }
1008
1009 static struct notifier_block __refdata palinfo_cpu_notifier =
1010 {
1011 .notifier_call = palinfo_cpu_callback,
1012 .priority = 0,
1013 };
1014
1015 static int __init
1016 palinfo_init(void)
1017 {
1018 int i = 0;
1019
1020 printk(KERN_INFO "PAL Information Facility v%s\n", PALINFO_VERSION);
1021 palinfo_dir = proc_mkdir("pal", NULL);
1022 if (!palinfo_dir)
1023 return -ENOMEM;
1024
1025 /* Create palinfo dirs in /proc for all online cpus */
1026 for_each_online_cpu(i) {
1027 create_palinfo_proc_entries(i);
1028 }
1029
1030 /* Register for future delivery via notify registration */
1031 register_hotcpu_notifier(&palinfo_cpu_notifier);
1032
1033 return 0;
1034 }
1035
1036 static void __exit
1037 palinfo_exit(void)
1038 {
1039 unregister_hotcpu_notifier(&palinfo_cpu_notifier);
1040 remove_proc_subtree("pal", NULL);
1041 }
1042
1043 module_init(palinfo_init);
1044 module_exit(palinfo_exit);