xref: /openbmc/linux/arch/ia64/kernel/palinfo.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
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  */
20 #include <linux/config.h>
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 	u64 i, levels, unique_caches;
222 	pal_cache_config_info_t cci;
223 	int j, k;
224 	s64 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           : %lu 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 	s64 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 		return 0;
311 	}
312 
313 
314 	p += sprintf(p,
315 		     "Physical Address Space         : %d bits\n"
316 		     "Virtual Address Space          : %d bits\n"
317 		     "Protection Key Registers(PKR)  : %d\n"
318 		     "Implemented bits in PKR.key    : %d\n"
319 		     "Hash Tag ID                    : 0x%x\n"
320 		     "Size of RR.rid                 : %d\n",
321 		     vm_info_1.pal_vm_info_1_s.phys_add_size,
322 		     vm_info_2.pal_vm_info_2_s.impl_va_msb+1, vm_info_1.pal_vm_info_1_s.max_pkr+1,
323 		     vm_info_1.pal_vm_info_1_s.key_size, vm_info_1.pal_vm_info_1_s.hash_tag_id,
324 		     vm_info_2.pal_vm_info_2_s.rid_size);
325 
326 	if (ia64_pal_mem_attrib(&attrib) != 0)
327 		return 0;
328 
329 	p += sprintf(p, "Supported memory attributes    : ");
330 	sep = "";
331 	for (i = 0; i < 8; i++) {
332 		if (attrib & (1 << i)) {
333 			p += sprintf(p, "%s%s", sep, mem_attrib[i]);
334 			sep = ", ";
335 		}
336 	}
337 	p += sprintf(p, "\n");
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 		return 0;
342 	}
343 
344 	p += sprintf(p,
345 		     "\nTLB walker                     : %simplemented\n"
346 		     "Number of DTR                  : %d\n"
347 		     "Number of ITR                  : %d\n"
348 		     "TLB insertable page sizes      : ",
349 		     vm_info_1.pal_vm_info_1_s.vw ? "" : "not ",
350 		     vm_info_1.pal_vm_info_1_s.max_dtr_entry+1,
351 		     vm_info_1.pal_vm_info_1_s.max_itr_entry+1);
352 
353 
354 	p = bitvector_process(p, tr_pages);
355 
356 	p += sprintf(p, "\nTLB purgeable page sizes       : ");
357 
358 	p = bitvector_process(p, vw_pages);
359 
360 	if ((status=ia64_get_ptce(&ptce)) != 0) {
361 		printk(KERN_ERR "ia64_get_ptce=%ld\n", status);
362 		return 0;
363 	}
364 
365 	p += sprintf(p,
366 		     "\nPurge base address             : 0x%016lx\n"
367 		     "Purge outer loop count         : %d\n"
368 		     "Purge inner loop count         : %d\n"
369 		     "Purge outer loop stride        : %d\n"
370 		     "Purge inner loop stride        : %d\n",
371 		     ptce.base, ptce.count[0], ptce.count[1], ptce.stride[0], ptce.stride[1]);
372 
373 	p += sprintf(p,
374 		     "TC Levels                      : %d\n"
375 		     "Unique TC(s)                   : %d\n",
376 		     vm_info_1.pal_vm_info_1_s.num_tc_levels,
377 		     vm_info_1.pal_vm_info_1_s.max_unique_tcs);
378 
379 	for(i=0; i < vm_info_1.pal_vm_info_1_s.num_tc_levels; i++) {
380 		for (j=2; j>0 ; j--) {
381 			tc_pages = 0; /* just in case */
382 
383 
384 			/* even without unification, some levels may not be present */
385 			if ((status=ia64_pal_vm_info(i,j, &tc_info, &tc_pages)) != 0) {
386 				continue;
387 			}
388 
389 			p += sprintf(p,
390 				     "\n%s Translation Cache Level %d:\n"
391 				     "\tHash sets           : %d\n"
392 				     "\tAssociativity       : %d\n"
393 				     "\tNumber of entries   : %d\n"
394 				     "\tFlags               : ",
395 				     cache_types[j+tc_info.tc_unified], i+1, tc_info.tc_num_sets,
396 				     tc_info.tc_associativity, tc_info.tc_num_entries);
397 
398 			if (tc_info.tc_pf) p += sprintf(p, "PreferredPageSizeOptimized ");
399 			if (tc_info.tc_unified) p += sprintf(p, "Unified ");
400 			if (tc_info.tc_reduce_tr) p += sprintf(p, "TCReduction");
401 
402 			p += sprintf(p, "\n\tSupported page sizes: ");
403 
404 			p = bitvector_process(p, tc_pages);
405 
406 			/* when unified date (j=2) is enough */
407 			if (tc_info.tc_unified) break;
408 		}
409 	}
410 	p += sprintf(p, "\n");
411 
412 	return p - page;
413 }
414 
415 
416 static int
417 register_info(char *page)
418 {
419 	char *p = page;
420 	u64 reg_info[2];
421 	u64 info;
422 	u64 phys_stacked;
423 	pal_hints_u_t hints;
424 	u64 iregs, dregs;
425 	char *info_type[]={
426 		"Implemented AR(s)",
427 		"AR(s) with read side-effects",
428 		"Implemented CR(s)",
429 		"CR(s) with read side-effects",
430 	};
431 
432 	for(info=0; info < 4; info++) {
433 
434 		if (ia64_pal_register_info(info, &reg_info[0], &reg_info[1]) != 0) return 0;
435 
436 		p += sprintf(p, "%-32s : ", info_type[info]);
437 
438 		p = bitregister_process(p, reg_info, 128);
439 
440 		p += sprintf(p, "\n");
441 	}
442 
443 	if (ia64_pal_rse_info(&phys_stacked, &hints) != 0) return 0;
444 
445 	p += sprintf(p,
446 		     "RSE stacked physical registers   : %ld\n"
447 		     "RSE load/store hints             : %ld (%s)\n",
448 		     phys_stacked, hints.ph_data,
449 		     hints.ph_data < RSE_HINTS_COUNT ? rse_hints[hints.ph_data]: "(??)");
450 
451 	if (ia64_pal_debug_info(&iregs, &dregs))
452 		return 0;
453 
454 	p += sprintf(p,
455 		     "Instruction debug register pairs : %ld\n"
456 		     "Data debug register pairs        : %ld\n", iregs, dregs);
457 
458 	return p - page;
459 }
460 
461 static const char *proc_features[]={
462 	NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
463 	NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,
464 	NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
465 	NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,
466 	NULL,NULL,NULL,NULL,NULL,
467 	"XIP,XPSR,XFS implemented",
468 	"XR1-XR3 implemented",
469 	"Disable dynamic predicate prediction",
470 	"Disable processor physical number",
471 	"Disable dynamic data cache prefetch",
472 	"Disable dynamic inst cache prefetch",
473 	"Disable dynamic branch prediction",
474 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
475 	"Disable BINIT on processor time-out",
476 	"Disable dynamic power management (DPM)",
477 	"Disable coherency",
478 	"Disable cache",
479 	"Enable CMCI promotion",
480 	"Enable MCA to BINIT promotion",
481 	"Enable MCA promotion",
482 	"Enable BERR promotion"
483 };
484 
485 
486 static int
487 processor_info(char *page)
488 {
489 	char *p = page;
490 	const char **v = proc_features;
491 	u64 avail=1, status=1, control=1;
492 	int i;
493 	s64 ret;
494 
495 	if ((ret=ia64_pal_proc_get_features(&avail, &status, &control)) != 0) return 0;
496 
497 	for(i=0; i < 64; i++, v++,avail >>=1, status >>=1, control >>=1) {
498 		if ( ! *v ) continue;
499 		p += sprintf(p, "%-40s : %s%s %s\n", *v,
500 				avail & 0x1 ? "" : "NotImpl",
501 				avail & 0x1 ? (status & 0x1 ? "On" : "Off"): "",
502 				avail & 0x1 ? (control & 0x1 ? "Ctrl" : "NoCtrl"): "");
503 	}
504 	return p - page;
505 }
506 
507 static const char *bus_features[]={
508 	NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
509 	NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,
510 	NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
511 	NULL,NULL,
512 	"Request  Bus Parking",
513 	"Bus Lock Mask",
514 	"Enable Half Transfer",
515 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
516 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
517 	NULL, NULL, NULL, NULL,
518 	"Enable Cache Line Repl. Shared",
519 	"Enable Cache Line Repl. Exclusive",
520 	"Disable Transaction Queuing",
521 	"Disable Response Error Checking",
522 	"Disable Bus Error Checking",
523 	"Disable Bus Requester Internal Error Signalling",
524 	"Disable Bus Requester Error Signalling",
525 	"Disable Bus Initialization Event Checking",
526 	"Disable Bus Initialization Event Signalling",
527 	"Disable Bus Address Error Checking",
528 	"Disable Bus Address Error Signalling",
529 	"Disable Bus Data Error Checking"
530 };
531 
532 
533 static int
534 bus_info(char *page)
535 {
536 	char *p = page;
537 	const char **v = bus_features;
538 	pal_bus_features_u_t av, st, ct;
539 	u64 avail, status, control;
540 	int i;
541 	s64 ret;
542 
543 	if ((ret=ia64_pal_bus_get_features(&av, &st, &ct)) != 0) return 0;
544 
545 	avail   = av.pal_bus_features_val;
546 	status  = st.pal_bus_features_val;
547 	control = ct.pal_bus_features_val;
548 
549 	for(i=0; i < 64; i++, v++, avail >>=1, status >>=1, control >>=1) {
550 		if ( ! *v ) continue;
551 		p += sprintf(p, "%-48s : %s%s %s\n", *v,
552 				avail & 0x1 ? "" : "NotImpl",
553 				avail & 0x1 ? (status  & 0x1 ? "On" : "Off"): "",
554 				avail & 0x1 ? (control & 0x1 ? "Ctrl" : "NoCtrl"): "");
555 	}
556 	return p - page;
557 }
558 
559 static int
560 version_info(char *page)
561 {
562 	pal_version_u_t min_ver, cur_ver;
563 	char *p = page;
564 
565 	/* The PAL_VERSION call is advertised as being able to support
566 	 * both physical and virtual mode calls. This seems to be a documentation
567 	 * bug rather than firmware bug. In fact, it does only support physical mode.
568 	 * So now the code reflects this fact and the pal_version() has been updated
569 	 * accordingly.
570 	 */
571 	if (ia64_pal_version(&min_ver, &cur_ver) != 0) return 0;
572 
573 	p += sprintf(p,
574 		     "PAL_vendor : 0x%02x (min=0x%02x)\n"
575 		     "PAL_A      : %x.%x.%x (min=%x.%x.%x)\n"
576 		     "PAL_B      : %x.%x.%x (min=%x.%x.%x)\n",
577 		     cur_ver.pal_version_s.pv_pal_vendor, min_ver.pal_version_s.pv_pal_vendor,
578 
579 		     cur_ver.pal_version_s.pv_pal_a_model>>4,
580 		     cur_ver.pal_version_s.pv_pal_a_model&0xf, cur_ver.pal_version_s.pv_pal_a_rev,
581 		     min_ver.pal_version_s.pv_pal_a_model>>4,
582 		     min_ver.pal_version_s.pv_pal_a_model&0xf, min_ver.pal_version_s.pv_pal_a_rev,
583 
584 		     cur_ver.pal_version_s.pv_pal_b_model>>4,
585 		     cur_ver.pal_version_s.pv_pal_b_model&0xf, cur_ver.pal_version_s.pv_pal_b_rev,
586 		     min_ver.pal_version_s.pv_pal_b_model>>4,
587 		     min_ver.pal_version_s.pv_pal_b_model&0xf, min_ver.pal_version_s.pv_pal_b_rev);
588 	return p - page;
589 }
590 
591 static int
592 perfmon_info(char *page)
593 {
594 	char *p = page;
595 	u64 pm_buffer[16];
596 	pal_perf_mon_info_u_t pm_info;
597 
598 	if (ia64_pal_perf_mon_info(pm_buffer, &pm_info) != 0) return 0;
599 
600 	p += sprintf(p,
601 		     "PMC/PMD pairs                 : %d\n"
602 		     "Counter width                 : %d bits\n"
603 		     "Cycle event number            : %d\n"
604 		     "Retired event number          : %d\n"
605 		     "Implemented PMC               : ",
606 		     pm_info.pal_perf_mon_info_s.generic, pm_info.pal_perf_mon_info_s.width,
607 		     pm_info.pal_perf_mon_info_s.cycles, pm_info.pal_perf_mon_info_s.retired);
608 
609 	p = bitregister_process(p, pm_buffer, 256);
610 	p += sprintf(p, "\nImplemented PMD               : ");
611 	p = bitregister_process(p, pm_buffer+4, 256);
612 	p += sprintf(p, "\nCycles count capable          : ");
613 	p = bitregister_process(p, pm_buffer+8, 256);
614 	p += sprintf(p, "\nRetired bundles count capable : ");
615 
616 #ifdef CONFIG_ITANIUM
617 	/*
618 	 * PAL_PERF_MON_INFO reports that only PMC4 can be used to count CPU_CYCLES
619 	 * which is wrong, both PMC4 and PMD5 support it.
620 	 */
621 	if (pm_buffer[12] == 0x10) pm_buffer[12]=0x30;
622 #endif
623 
624 	p = bitregister_process(p, pm_buffer+12, 256);
625 
626 	p += sprintf(p, "\n");
627 
628 	return p - page;
629 }
630 
631 static int
632 frequency_info(char *page)
633 {
634 	char *p = page;
635 	struct pal_freq_ratio proc, itc, bus;
636 	u64 base;
637 
638 	if (ia64_pal_freq_base(&base) == -1)
639 		p += sprintf(p, "Output clock            : not implemented\n");
640 	else
641 		p += sprintf(p, "Output clock            : %ld ticks/s\n", base);
642 
643 	if (ia64_pal_freq_ratios(&proc, &bus, &itc) != 0) return 0;
644 
645 	p += sprintf(p,
646 		     "Processor/Clock ratio   : %ld/%ld\n"
647 		     "Bus/Clock ratio         : %ld/%ld\n"
648 		     "ITC/Clock ratio         : %ld/%ld\n",
649 		     proc.num, proc.den, bus.num, bus.den, itc.num, itc.den);
650 
651 	return p - page;
652 }
653 
654 static int
655 tr_info(char *page)
656 {
657 	char *p = page;
658 	s64 status;
659 	pal_tr_valid_u_t tr_valid;
660 	u64 tr_buffer[4];
661 	pal_vm_info_1_u_t vm_info_1;
662 	pal_vm_info_2_u_t vm_info_2;
663 	u64 i, j;
664 	u64 max[3], pgm;
665 	struct ifa_reg {
666 		u64 valid:1;
667 		u64 ig:11;
668 		u64 vpn:52;
669 	} *ifa_reg;
670 	struct itir_reg {
671 		u64 rv1:2;
672 		u64 ps:6;
673 		u64 key:24;
674 		u64 rv2:32;
675 	} *itir_reg;
676 	struct gr_reg {
677 		u64 p:1;
678 		u64 rv1:1;
679 		u64 ma:3;
680 		u64 a:1;
681 		u64 d:1;
682 		u64 pl:2;
683 		u64 ar:3;
684 		u64 ppn:38;
685 		u64 rv2:2;
686 		u64 ed:1;
687 		u64 ig:11;
688 	} *gr_reg;
689 	struct rid_reg {
690 		u64 ig1:1;
691 		u64 rv1:1;
692 		u64 ig2:6;
693 		u64 rid:24;
694 		u64 rv2:32;
695 	} *rid_reg;
696 
697 	if ((status = ia64_pal_vm_summary(&vm_info_1, &vm_info_2)) !=0) {
698 		printk(KERN_ERR "ia64_pal_vm_summary=%ld\n", status);
699 		return 0;
700 	}
701 	max[0] = vm_info_1.pal_vm_info_1_s.max_itr_entry+1;
702 	max[1] = vm_info_1.pal_vm_info_1_s.max_dtr_entry+1;
703 
704 	for (i=0; i < 2; i++ ) {
705 		for (j=0; j < max[i]; j++) {
706 
707 		status = ia64_pal_tr_read(j, i, tr_buffer, &tr_valid);
708 		if (status != 0) {
709 			printk(KERN_ERR "palinfo: pal call failed on tr[%lu:%lu]=%ld\n",
710 			       i, j, status);
711 			continue;
712 		}
713 
714 		ifa_reg  = (struct ifa_reg *)&tr_buffer[2];
715 
716 		if (ifa_reg->valid == 0) continue;
717 
718 		gr_reg   = (struct gr_reg *)tr_buffer;
719 		itir_reg = (struct itir_reg *)&tr_buffer[1];
720 		rid_reg  = (struct rid_reg *)&tr_buffer[3];
721 
722 		pgm	 = -1 << (itir_reg->ps - 12);
723 		p += sprintf(p,
724 			     "%cTR%lu: av=%d pv=%d dv=%d mv=%d\n"
725 			     "\tppn  : 0x%lx\n"
726 			     "\tvpn  : 0x%lx\n"
727 			     "\tps   : ",
728 			     "ID"[i], j,
729 			     tr_valid.pal_tr_valid_s.access_rights_valid,
730 			     tr_valid.pal_tr_valid_s.priv_level_valid,
731 			     tr_valid.pal_tr_valid_s.dirty_bit_valid,
732 			     tr_valid.pal_tr_valid_s.mem_attr_valid,
733 			     (gr_reg->ppn & pgm)<< 12, (ifa_reg->vpn & pgm)<< 12);
734 
735 		p = bitvector_process(p, 1<< itir_reg->ps);
736 
737 		p += sprintf(p,
738 			     "\n\tpl   : %d\n"
739 			     "\tar   : %d\n"
740 			     "\trid  : %x\n"
741 			     "\tp    : %d\n"
742 			     "\tma   : %d\n"
743 			     "\td    : %d\n",
744 			     gr_reg->pl, gr_reg->ar, rid_reg->rid, gr_reg->p, gr_reg->ma,
745 			     gr_reg->d);
746 		}
747 	}
748 	return p - page;
749 }
750 
751 
752 
753 /*
754  * List {name,function} pairs for every entry in /proc/palinfo/cpu*
755  */
756 static palinfo_entry_t palinfo_entries[]={
757 	{ "version_info",	version_info, },
758 	{ "vm_info",		vm_info, },
759 	{ "cache_info",		cache_info, },
760 	{ "power_info",		power_info, },
761 	{ "register_info",	register_info, },
762 	{ "processor_info",	processor_info, },
763 	{ "perfmon_info",	perfmon_info, },
764 	{ "frequency_info",	frequency_info, },
765 	{ "bus_info",		bus_info },
766 	{ "tr_info",		tr_info, }
767 };
768 
769 #define NR_PALINFO_ENTRIES	(int) ARRAY_SIZE(palinfo_entries)
770 
771 /*
772  * this array is used to keep track of the proc entries we create. This is
773  * required in the module mode when we need to remove all entries. The procfs code
774  * does not do recursion of deletion
775  *
776  * Notes:
777  *	- +1 accounts for the cpuN directory entry in /proc/pal
778  */
779 #define NR_PALINFO_PROC_ENTRIES	(NR_CPUS*(NR_PALINFO_ENTRIES+1))
780 
781 static struct proc_dir_entry *palinfo_proc_entries[NR_PALINFO_PROC_ENTRIES];
782 static struct proc_dir_entry *palinfo_dir;
783 
784 /*
785  * This data structure is used to pass which cpu,function is being requested
786  * It must fit in a 64bit quantity to be passed to the proc callback routine
787  *
788  * In SMP mode, when we get a request for another CPU, we must call that
789  * other CPU using IPI and wait for the result before returning.
790  */
791 typedef union {
792 	u64 value;
793 	struct {
794 		unsigned	req_cpu: 32;	/* for which CPU this info is */
795 		unsigned	func_id: 32;	/* which function is requested */
796 	} pal_func_cpu;
797 } pal_func_cpu_u_t;
798 
799 #define req_cpu	pal_func_cpu.req_cpu
800 #define func_id pal_func_cpu.func_id
801 
802 #ifdef CONFIG_SMP
803 
804 /*
805  * used to hold information about final function to call
806  */
807 typedef struct {
808 	palinfo_func_t	func;	/* pointer to function to call */
809 	char		*page;	/* buffer to store results */
810 	int		ret;	/* return value from call */
811 } palinfo_smp_data_t;
812 
813 
814 /*
815  * this function does the actual final call and he called
816  * from the smp code, i.e., this is the palinfo callback routine
817  */
818 static void
819 palinfo_smp_call(void *info)
820 {
821 	palinfo_smp_data_t *data = (palinfo_smp_data_t *)info;
822 	if (data == NULL) {
823 		printk(KERN_ERR "palinfo: data pointer is NULL\n");
824 		data->ret = 0; /* no output */
825 		return;
826 	}
827 	/* does this actual call */
828 	data->ret = (*data->func)(data->page);
829 }
830 
831 /*
832  * function called to trigger the IPI, we need to access a remote CPU
833  * Return:
834  *	0 : error or nothing to output
835  *	otherwise how many bytes in the "page" buffer were written
836  */
837 static
838 int palinfo_handle_smp(pal_func_cpu_u_t *f, char *page)
839 {
840 	palinfo_smp_data_t ptr;
841 	int ret;
842 
843 	ptr.func = palinfo_entries[f->func_id].proc_read;
844 	ptr.page = page;
845 	ptr.ret  = 0; /* just in case */
846 
847 
848 	/* will send IPI to other CPU and wait for completion of remote call */
849 	if ((ret=smp_call_function_single(f->req_cpu, palinfo_smp_call, &ptr, 0, 1))) {
850 		printk(KERN_ERR "palinfo: remote CPU call from %d to %d on function %d: "
851 		       "error %d\n", smp_processor_id(), f->req_cpu, f->func_id, ret);
852 		return 0;
853 	}
854 	return ptr.ret;
855 }
856 #else /* ! CONFIG_SMP */
857 static
858 int palinfo_handle_smp(pal_func_cpu_u_t *f, char *page)
859 {
860 	printk(KERN_ERR "palinfo: should not be called with non SMP kernel\n");
861 	return 0;
862 }
863 #endif /* CONFIG_SMP */
864 
865 /*
866  * Entry point routine: all calls go through this function
867  */
868 static int
869 palinfo_read_entry(char *page, char **start, off_t off, int count, int *eof, void *data)
870 {
871 	int len=0;
872 	pal_func_cpu_u_t *f = (pal_func_cpu_u_t *)&data;
873 
874 	/*
875 	 * in SMP mode, we may need to call another CPU to get correct
876 	 * information. PAL, by definition, is processor specific
877 	 */
878 	if (f->req_cpu == get_cpu())
879 		len = (*palinfo_entries[f->func_id].proc_read)(page);
880 	else
881 		len = palinfo_handle_smp(f, page);
882 
883 	put_cpu();
884 
885 	if (len <= off+count) *eof = 1;
886 
887 	*start = page + off;
888 	len   -= off;
889 
890 	if (len>count) len = count;
891 	if (len<0) len = 0;
892 
893 	return len;
894 }
895 
896 static void
897 create_palinfo_proc_entries(unsigned int cpu)
898 {
899 #	define CPUSTR	"cpu%d"
900 
901 	pal_func_cpu_u_t f;
902 	struct proc_dir_entry **pdir;
903 	struct proc_dir_entry *cpu_dir;
904 	int j;
905 	char cpustr[sizeof(CPUSTR)];
906 
907 
908 	/*
909 	 * we keep track of created entries in a depth-first order for
910 	 * cleanup purposes. Each entry is stored into palinfo_proc_entries
911 	 */
912 	sprintf(cpustr,CPUSTR, cpu);
913 
914 	cpu_dir = proc_mkdir(cpustr, palinfo_dir);
915 
916 	f.req_cpu = cpu;
917 
918 	/*
919 	 * Compute the location to store per cpu entries
920 	 * We dont store the top level entry in this list, but
921 	 * remove it finally after removing all cpu entries.
922 	 */
923 	pdir = &palinfo_proc_entries[cpu*(NR_PALINFO_ENTRIES+1)];
924 	*pdir++ = cpu_dir;
925 	for (j=0; j < NR_PALINFO_ENTRIES; j++) {
926 		f.func_id = j;
927 		*pdir = create_proc_read_entry(
928 				palinfo_entries[j].name, 0, cpu_dir,
929 				palinfo_read_entry, (void *)f.value);
930 		if (*pdir)
931 			(*pdir)->owner = THIS_MODULE;
932 		pdir++;
933 	}
934 }
935 
936 static void
937 remove_palinfo_proc_entries(unsigned int hcpu)
938 {
939 	int j;
940 	struct proc_dir_entry *cpu_dir, **pdir;
941 
942 	pdir = &palinfo_proc_entries[hcpu*(NR_PALINFO_ENTRIES+1)];
943 	cpu_dir = *pdir;
944 	*pdir++=NULL;
945 	for (j=0; j < (NR_PALINFO_ENTRIES); j++) {
946 		if ((*pdir)) {
947 			remove_proc_entry ((*pdir)->name, cpu_dir);
948 			*pdir ++= NULL;
949 		}
950 	}
951 
952 	if (cpu_dir) {
953 		remove_proc_entry(cpu_dir->name, palinfo_dir);
954 	}
955 }
956 
957 static int __devinit palinfo_cpu_callback(struct notifier_block *nfb,
958 								unsigned long action,
959 								void *hcpu)
960 {
961 	unsigned int hotcpu = (unsigned long)hcpu;
962 
963 	switch (action) {
964 	case CPU_ONLINE:
965 		create_palinfo_proc_entries(hotcpu);
966 		break;
967 #ifdef CONFIG_HOTPLUG_CPU
968 	case CPU_DEAD:
969 		remove_palinfo_proc_entries(hotcpu);
970 		break;
971 #endif
972 	}
973 	return NOTIFY_OK;
974 }
975 
976 static struct notifier_block palinfo_cpu_notifier =
977 {
978 	.notifier_call = palinfo_cpu_callback,
979 	.priority = 0,
980 };
981 
982 static int __init
983 palinfo_init(void)
984 {
985 	int i = 0;
986 
987 	printk(KERN_INFO "PAL Information Facility v%s\n", PALINFO_VERSION);
988 	palinfo_dir = proc_mkdir("pal", NULL);
989 
990 	/* Create palinfo dirs in /proc for all online cpus */
991 	for_each_online_cpu(i) {
992 		create_palinfo_proc_entries(i);
993 	}
994 
995 	/* Register for future delivery via notify registration */
996 	register_cpu_notifier(&palinfo_cpu_notifier);
997 
998 	return 0;
999 }
1000 
1001 static void __exit
1002 palinfo_exit(void)
1003 {
1004 	int i = 0;
1005 
1006 	/* remove all nodes: depth first pass. Could optimize this  */
1007 	for_each_online_cpu(i) {
1008 		remove_palinfo_proc_entries(i);
1009 	}
1010 
1011 	/*
1012 	 * Remove the top level entry finally
1013 	 */
1014 	remove_proc_entry(palinfo_dir->name, NULL);
1015 
1016 	/*
1017 	 * Unregister from cpu notifier callbacks
1018 	 */
1019 	unregister_cpu_notifier(&palinfo_cpu_notifier);
1020 }
1021 
1022 module_init(palinfo_init);
1023 module_exit(palinfo_exit);
1024