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