1 // SPDX-License-Identifier: GPL-2.0-only
5 * Prints processor specific information reported by PAL.
6 * This code is based on specification of PAL as of the
7 * Intel IA-64 Architecture Software Developer's Manual v1.0.
10 * Copyright (C) 2000-2001, 2003 Hewlett-Packard Co
11 * Stephane Eranian <eranian@hpl.hp.com>
12 * Copyright (C) 2004 Intel Corporation
13 * Ashok Raj <ashok.raj@intel.com>
15 * 05/26/2000 S.Eranian initial release
16 * 08/21/2000 S.Eranian updated to July 2000 PAL specs
17 * 02/05/2001 S.Eranian fixed module support
18 * 10/23/2001 S.Eranian updated pal_perf_mon_info bug fixes
19 * 03/24/2004 Ashok Raj updated to work with CPU Hotplug
20 * 10/26/2006 Russ Anderson updated processor features to rev 2.2 spec
22 #include <linux/types.h>
23 #include <linux/errno.h>
24 #include <linux/init.h>
25 #include <linux/proc_fs.h>
26 #include <linux/seq_file.h>
28 #include <linux/module.h>
29 #include <linux/efi.h>
30 #include <linux/notifier.h>
31 #include <linux/cpu.h>
32 #include <linux/cpumask.h>
37 #include <asm/processor.h>
38 #include <linux/smp.h>
40 MODULE_AUTHOR("Stephane Eranian <eranian@hpl.hp.com>");
41 MODULE_DESCRIPTION("/proc interface to IA-64 PAL");
42 MODULE_LICENSE("GPL");
44 #define PALINFO_VERSION "0.5"
46 typedef int (*palinfo_func_t
)(struct seq_file
*);
49 const char *name
; /* name of the proc entry */
50 palinfo_func_t proc_read
; /* function to call for reading */
51 struct proc_dir_entry
*entry
; /* registered entry (removal) */
56 * A bunch of string array to get pretty printing
59 static const char *cache_types
[] = {
63 "Data/Instruction" /* unified */
66 static const char *cache_mattrib
[]={
73 static const char *cache_st_hints
[]={
77 "Non-temporal, all levels",
84 static const char *cache_ld_hints
[]={
86 "Non-temporal, level 1",
88 "Non-temporal, all levels",
95 static const char *rse_hints
[]={
99 "eager loads and stores"
102 #define RSE_HINTS_COUNT ARRAY_SIZE(rse_hints)
104 static const char *mem_attrib
[]={
116 * Take a 64bit vector and produces a string such that
117 * if bit n is set then 2^n in clear text is generated. The adjustment
118 * to the right unit is also done.
121 * - a pointer to a buffer to hold the string
124 * - a pointer to the end of the buffer
127 static void bitvector_process(struct seq_file
*m
, u64 vector
)
130 static const char *units
[]={ "", "K", "M", "G", "T" };
132 for (i
=0, j
=0; i
< 64; i
++ , j
=i
/10) {
134 seq_printf(m
, "%d%s ", 1 << (i
-j
*10), units
[j
]);
140 * Take a 64bit vector and produces a string such that
141 * if bit n is set then register n is present. The function
142 * takes into account consecutive registers and prints out ranges.
145 * - a pointer to a buffer to hold the string
148 * - a pointer to the end of the buffer
151 static void bitregister_process(struct seq_file
*m
, u64
*reg_info
, int max
)
153 int i
, begin
, skip
= 0;
154 u64 value
= reg_info
[0];
156 value
>>= i
= begin
= ffs(value
) - 1;
158 for(; i
< max
; i
++ ) {
160 if (i
!= 0 && (i
%64) == 0) value
= *++reg_info
;
162 if ((value
& 0x1) == 0 && skip
== 0) {
164 seq_printf(m
, "%d-%d ", begin
, i
-1);
166 seq_printf(m
, "%d ", i
-1);
169 } else if ((value
& 0x1) && skip
== 1) {
177 seq_printf(m
, "%d-127", begin
);
183 static int power_info(struct seq_file
*m
)
186 u64 halt_info_buffer
[8];
187 pal_power_mgmt_info_u_t
*halt_info
=(pal_power_mgmt_info_u_t
*)halt_info_buffer
;
190 status
= ia64_pal_halt_info(halt_info
);
191 if (status
!= 0) return 0;
193 for (i
=0; i
< 8 ; i
++ ) {
194 if (halt_info
[i
].pal_power_mgmt_info_s
.im
== 1) {
197 "\tentry_latency : %d cycles\n"
198 "\texit_latency : %d cycles\n"
199 "\tpower consumption : %d mW\n"
200 "\tCache+TLB coherency : %s\n", i
,
201 halt_info
[i
].pal_power_mgmt_info_s
.entry_latency
,
202 halt_info
[i
].pal_power_mgmt_info_s
.exit_latency
,
203 halt_info
[i
].pal_power_mgmt_info_s
.power_consumption
,
204 halt_info
[i
].pal_power_mgmt_info_s
.co
? "Yes" : "No");
206 seq_printf(m
,"Power level %d: not implemented\n", i
);
212 static int cache_info(struct seq_file
*m
)
214 unsigned long i
, levels
, unique_caches
;
215 pal_cache_config_info_t cci
;
219 if ((status
= ia64_pal_cache_summary(&levels
, &unique_caches
)) != 0) {
220 printk(KERN_ERR
"ia64_pal_cache_summary=%ld\n", status
);
224 seq_printf(m
, "Cache levels : %ld\nUnique caches : %ld\n\n",
225 levels
, unique_caches
);
227 for (i
=0; i
< levels
; i
++) {
228 for (j
=2; j
>0 ; j
--) {
229 /* even without unification some level may not be present */
230 if ((status
=ia64_pal_cache_config_info(i
,j
, &cci
)) != 0)
234 "%s Cache level %lu:\n"
235 "\tSize : %u bytes\n"
237 cache_types
[j
+cci
.pcci_unified
], i
+1,
238 cci
.pcci_cache_size
);
240 if (cci
.pcci_unified
)
241 seq_puts(m
, "Unified ");
243 seq_printf(m
, "%s\n", cache_mattrib
[cci
.pcci_cache_attr
]);
246 "\tAssociativity : %d\n"
247 "\tLine size : %d bytes\n"
248 "\tStride : %d bytes\n",
250 1<<cci
.pcci_line_size
,
253 seq_puts(m
, "\tStore latency : N/A\n");
255 seq_printf(m
, "\tStore latency : %d cycle(s)\n",
256 cci
.pcci_st_latency
);
259 "\tLoad latency : %d cycle(s)\n"
260 "\tStore hints : ", cci
.pcci_ld_latency
);
262 for(k
=0; k
< 8; k
++ ) {
263 if ( cci
.pcci_st_hints
& 0x1)
264 seq_printf(m
, "[%s]", cache_st_hints
[k
]);
265 cci
.pcci_st_hints
>>=1;
267 seq_puts(m
, "\n\tLoad hints : ");
269 for(k
=0; k
< 8; k
++ ) {
270 if (cci
.pcci_ld_hints
& 0x1)
271 seq_printf(m
, "[%s]", cache_ld_hints
[k
]);
272 cci
.pcci_ld_hints
>>=1;
275 "\n\tAlias boundary : %d byte(s)\n"
278 1<<cci
.pcci_alias_boundary
, cci
.pcci_tag_lsb
,
281 /* when unified, data(j=2) is enough */
282 if (cci
.pcci_unified
)
290 static int vm_info(struct seq_file
*m
)
292 u64 tr_pages
=0, vw_pages
=0, tc_pages
;
294 pal_vm_info_1_u_t vm_info_1
;
295 pal_vm_info_2_u_t vm_info_2
;
296 pal_tc_info_u_t tc_info
;
297 ia64_ptce_info_t ptce
;
302 if ((status
= ia64_pal_vm_summary(&vm_info_1
, &vm_info_2
)) !=0) {
303 printk(KERN_ERR
"ia64_pal_vm_summary=%ld\n", status
);
307 "Physical Address Space : %d bits\n"
308 "Virtual Address Space : %d bits\n"
309 "Protection Key Registers(PKR) : %d\n"
310 "Implemented bits in PKR.key : %d\n"
311 "Hash Tag ID : 0x%x\n"
312 "Size of RR.rid : %d\n"
314 vm_info_1
.pal_vm_info_1_s
.phys_add_size
,
315 vm_info_2
.pal_vm_info_2_s
.impl_va_msb
+1,
316 vm_info_1
.pal_vm_info_1_s
.max_pkr
+1,
317 vm_info_1
.pal_vm_info_1_s
.key_size
,
318 vm_info_1
.pal_vm_info_1_s
.hash_tag_id
,
319 vm_info_2
.pal_vm_info_2_s
.rid_size
);
320 if (vm_info_2
.pal_vm_info_2_s
.max_purges
== PAL_MAX_PURGES
)
321 seq_puts(m
, "unlimited\n");
323 seq_printf(m
, "%d\n",
324 vm_info_2
.pal_vm_info_2_s
.max_purges
?
325 vm_info_2
.pal_vm_info_2_s
.max_purges
: 1);
328 if (ia64_pal_mem_attrib(&attrib
) == 0) {
329 seq_puts(m
, "Supported memory attributes : ");
331 for (i
= 0; i
< 8; i
++) {
332 if (attrib
& (1 << i
)) {
333 seq_printf(m
, "%s%s", sep
, mem_attrib
[i
]);
340 if ((status
= ia64_pal_vm_page_size(&tr_pages
, &vw_pages
)) !=0) {
341 printk(KERN_ERR
"ia64_pal_vm_page_size=%ld\n", status
);
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);
353 bitvector_process(m
, tr_pages
);
355 seq_puts(m
, "\nTLB purgeable page sizes : ");
357 bitvector_process(m
, vw_pages
);
360 if ((status
= ia64_get_ptce(&ptce
)) != 0) {
361 printk(KERN_ERR
"ia64_get_ptce=%ld\n", status
);
364 "\nPurge base address : 0x%016lx\n"
365 "Purge outer loop count : %d\n"
366 "Purge inner loop count : %d\n"
367 "Purge outer loop stride : %d\n"
368 "Purge inner loop stride : %d\n",
369 ptce
.base
, ptce
.count
[0], ptce
.count
[1],
370 ptce
.stride
[0], ptce
.stride
[1]);
374 "Unique TC(s) : %d\n",
375 vm_info_1
.pal_vm_info_1_s
.num_tc_levels
,
376 vm_info_1
.pal_vm_info_1_s
.max_unique_tcs
);
378 for(i
=0; i
< vm_info_1
.pal_vm_info_1_s
.num_tc_levels
; i
++) {
379 for (j
=2; j
>0 ; j
--) {
380 tc_pages
= 0; /* just in case */
382 /* even without unification, some levels may not be present */
383 if ((status
=ia64_pal_vm_info(i
,j
, &tc_info
, &tc_pages
)) != 0)
387 "\n%s Translation Cache Level %d:\n"
389 "\tAssociativity : %d\n"
390 "\tNumber of entries : %d\n"
392 cache_types
[j
+tc_info
.tc_unified
], i
+1,
394 tc_info
.tc_associativity
,
395 tc_info
.tc_num_entries
);
398 seq_puts(m
, "PreferredPageSizeOptimized ");
399 if (tc_info
.tc_unified
)
400 seq_puts(m
, "Unified ");
401 if (tc_info
.tc_reduce_tr
)
402 seq_puts(m
, "TCReduction");
404 seq_puts(m
, "\n\tSupported page sizes: ");
406 bitvector_process(m
, tc_pages
);
408 /* when unified date (j=2) is enough */
409 if (tc_info
.tc_unified
)
420 static int register_info(struct seq_file
*m
)
424 unsigned long phys_stacked
;
426 unsigned long iregs
, dregs
;
427 static const char * const info_type
[] = {
429 "AR(s) with read side-effects",
431 "CR(s) with read side-effects",
434 for(info
=0; info
< 4; info
++) {
435 if (ia64_pal_register_info(info
, ®_info
[0], ®_info
[1]) != 0)
437 seq_printf(m
, "%-32s : ", info_type
[info
]);
438 bitregister_process(m
, reg_info
, 128);
442 if (ia64_pal_rse_info(&phys_stacked
, &hints
) == 0)
444 "RSE stacked physical registers : %ld\n"
445 "RSE load/store hints : %ld (%s)\n",
446 phys_stacked
, hints
.ph_data
,
447 hints
.ph_data
< RSE_HINTS_COUNT
? rse_hints
[hints
.ph_data
]: "(??)");
449 if (ia64_pal_debug_info(&iregs
, &dregs
))
453 "Instruction debug register pairs : %ld\n"
454 "Data debug register pairs : %ld\n", iregs
, dregs
);
459 static const char *const proc_features_0
[]={ /* Feature set 0 */
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 NULL
,NULL
,NULL
,NULL
,NULL
, NULL
,NULL
,NULL
,NULL
,
464 "Unimplemented instruction address fault",
465 "INIT, PMI, and LINT pins",
466 "Simple unimplemented instr addresses",
467 "Variable P-state performance",
468 "Virtual machine features implemented",
469 "XIP,XPSR,XFS implemented",
470 "XR1-XR3 implemented",
471 "Disable dynamic predicate prediction",
472 "Disable processor physical number",
473 "Disable dynamic data cache prefetch",
474 "Disable dynamic inst cache prefetch",
475 "Disable dynamic branch prediction",
476 NULL
, NULL
, NULL
, NULL
,
478 "Enable MCA on Data Poisoning",
479 "Enable vmsw instruction",
480 "Enable extern environmental notification",
481 "Disable BINIT on processor time-out",
482 "Disable dynamic power management (DPM)",
485 "Enable CMCI promotion",
486 "Enable MCA to BINIT promotion",
487 "Enable MCA promotion",
488 "Enable BERR promotion"
491 static const char *const proc_features_16
[]={ /* Feature set 16 */
494 "Enable MCA on half-way timer",
497 "Enable Fast Deferral",
498 "Disable MCA on memory aliasing",
500 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
501 "DP system processor",
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
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
508 NULL
, NULL
, NULL
, NULL
, NULL
511 static const char *const *const proc_features
[]={
513 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
514 NULL
, NULL
, NULL
, NULL
,
516 NULL
, NULL
, NULL
, NULL
,
519 static void feature_set_info(struct seq_file
*m
, u64 avail
, u64 status
, u64 control
,
522 const char *const *vf
, *const *v
;
525 vf
= v
= proc_features
[set
];
526 for(i
=0; i
< 64; i
++, avail
>>=1, status
>>=1, control
>>=1) {
528 if (!(control
)) /* No remaining bits set */
530 if (!(avail
& 0x1)) /* Print only bits that are available */
535 seq_printf(m
, "%-40s : %s %s\n", *v
,
536 avail
& 0x1 ? (status
& 0x1 ?
538 avail
& 0x1 ? (control
& 0x1 ?
539 "Ctrl" : "NoCtrl"): "");
541 seq_printf(m
, "Feature set %2ld bit %2d\t\t\t"
544 avail
& 0x1 ? (status
& 0x1 ?
546 avail
& 0x1 ? (control
& 0x1 ?
547 "Ctrl" : "NoCtrl"): "");
552 static int processor_info(struct seq_file
*m
)
554 u64 avail
=1, status
=1, control
=1, feature_set
=0;
558 ret
= ia64_pal_proc_get_features(&avail
, &status
, &control
,
568 feature_set_info(m
, avail
, status
, control
, feature_set
);
575 static const char *const bus_features
[]={
576 NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,
577 NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
, NULL
,NULL
,
578 NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,NULL
,
580 "Request Bus Parking",
582 "Enable Half Transfer",
583 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
584 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
585 NULL
, NULL
, NULL
, NULL
,
586 "Enable Cache Line Repl. Shared",
587 "Enable Cache Line Repl. Exclusive",
588 "Disable Transaction Queuing",
589 "Disable Response Error Checking",
590 "Disable Bus Error Checking",
591 "Disable Bus Requester Internal Error Signalling",
592 "Disable Bus Requester Error Signalling",
593 "Disable Bus Initialization Event Checking",
594 "Disable Bus Initialization Event Signalling",
595 "Disable Bus Address Error Checking",
596 "Disable Bus Address Error Signalling",
597 "Disable Bus Data Error Checking"
601 static int bus_info(struct seq_file
*m
)
603 const char *const *v
= bus_features
;
604 pal_bus_features_u_t av
, st
, ct
;
605 u64 avail
, status
, control
;
609 if ((ret
=ia64_pal_bus_get_features(&av
, &st
, &ct
)) != 0)
612 avail
= av
.pal_bus_features_val
;
613 status
= st
.pal_bus_features_val
;
614 control
= ct
.pal_bus_features_val
;
616 for(i
=0; i
< 64; i
++, v
++, avail
>>=1, status
>>=1, control
>>=1) {
619 seq_printf(m
, "%-48s : %s%s %s\n", *v
,
620 avail
& 0x1 ? "" : "NotImpl",
621 avail
& 0x1 ? (status
& 0x1 ? "On" : "Off"): "",
622 avail
& 0x1 ? (control
& 0x1 ? "Ctrl" : "NoCtrl"): "");
627 static int version_info(struct seq_file
*m
)
629 pal_version_u_t min_ver
, cur_ver
;
631 if (ia64_pal_version(&min_ver
, &cur_ver
) != 0)
635 "PAL_vendor : 0x%02x (min=0x%02x)\n"
636 "PAL_A : %02x.%02x (min=%02x.%02x)\n"
637 "PAL_B : %02x.%02x (min=%02x.%02x)\n",
638 cur_ver
.pal_version_s
.pv_pal_vendor
,
639 min_ver
.pal_version_s
.pv_pal_vendor
,
640 cur_ver
.pal_version_s
.pv_pal_a_model
,
641 cur_ver
.pal_version_s
.pv_pal_a_rev
,
642 min_ver
.pal_version_s
.pv_pal_a_model
,
643 min_ver
.pal_version_s
.pv_pal_a_rev
,
644 cur_ver
.pal_version_s
.pv_pal_b_model
,
645 cur_ver
.pal_version_s
.pv_pal_b_rev
,
646 min_ver
.pal_version_s
.pv_pal_b_model
,
647 min_ver
.pal_version_s
.pv_pal_b_rev
);
651 static int perfmon_info(struct seq_file
*m
)
654 pal_perf_mon_info_u_t pm_info
;
656 if (ia64_pal_perf_mon_info(pm_buffer
, &pm_info
) != 0)
660 "PMC/PMD pairs : %d\n"
661 "Counter width : %d bits\n"
662 "Cycle event number : %d\n"
663 "Retired event number : %d\n"
664 "Implemented PMC : ",
665 pm_info
.pal_perf_mon_info_s
.generic
,
666 pm_info
.pal_perf_mon_info_s
.width
,
667 pm_info
.pal_perf_mon_info_s
.cycles
,
668 pm_info
.pal_perf_mon_info_s
.retired
);
670 bitregister_process(m
, pm_buffer
, 256);
671 seq_puts(m
, "\nImplemented PMD : ");
672 bitregister_process(m
, pm_buffer
+4, 256);
673 seq_puts(m
, "\nCycles count capable : ");
674 bitregister_process(m
, pm_buffer
+8, 256);
675 seq_puts(m
, "\nRetired bundles count capable : ");
677 #ifdef CONFIG_ITANIUM
679 * PAL_PERF_MON_INFO reports that only PMC4 can be used to count CPU_CYCLES
680 * which is wrong, both PMC4 and PMD5 support it.
682 if (pm_buffer
[12] == 0x10)
686 bitregister_process(m
, pm_buffer
+12, 256);
691 static int frequency_info(struct seq_file
*m
)
693 struct pal_freq_ratio proc
, itc
, bus
;
696 if (ia64_pal_freq_base(&base
) == -1)
697 seq_puts(m
, "Output clock : not implemented\n");
699 seq_printf(m
, "Output clock : %ld ticks/s\n", base
);
701 if (ia64_pal_freq_ratios(&proc
, &bus
, &itc
) != 0) return 0;
704 "Processor/Clock ratio : %d/%d\n"
705 "Bus/Clock ratio : %d/%d\n"
706 "ITC/Clock ratio : %d/%d\n",
707 proc
.num
, proc
.den
, bus
.num
, bus
.den
, itc
.num
, itc
.den
);
711 static int tr_info(struct seq_file
*m
)
714 pal_tr_valid_u_t tr_valid
;
716 pal_vm_info_1_u_t vm_info_1
;
717 pal_vm_info_2_u_t vm_info_2
;
719 unsigned long max
[3], pgm
;
721 unsigned long valid
:1;
723 unsigned long vpn
:52;
728 unsigned long key
:24;
729 unsigned long rv2
:32;
739 unsigned long ppn
:38;
748 unsigned long rid
:24;
749 unsigned long rv2
:32;
752 if ((status
= ia64_pal_vm_summary(&vm_info_1
, &vm_info_2
)) !=0) {
753 printk(KERN_ERR
"ia64_pal_vm_summary=%ld\n", status
);
756 max
[0] = vm_info_1
.pal_vm_info_1_s
.max_itr_entry
+1;
757 max
[1] = vm_info_1
.pal_vm_info_1_s
.max_dtr_entry
+1;
759 for (i
=0; i
< 2; i
++ ) {
760 for (j
=0; j
< max
[i
]; j
++) {
762 status
= ia64_pal_tr_read(j
, i
, tr_buffer
, &tr_valid
);
764 printk(KERN_ERR
"palinfo: pal call failed on tr[%lu:%lu]=%ld\n",
769 ifa_reg
= (struct ifa_reg
*)&tr_buffer
[2];
771 if (ifa_reg
->valid
== 0)
774 gr_reg
= (struct gr_reg
*)tr_buffer
;
775 itir_reg
= (struct itir_reg
*)&tr_buffer
[1];
776 rid_reg
= (struct rid_reg
*)&tr_buffer
[3];
778 pgm
= -1 << (itir_reg
->ps
- 12);
780 "%cTR%lu: av=%d pv=%d dv=%d mv=%d\n"
785 tr_valid
.pal_tr_valid_s
.access_rights_valid
,
786 tr_valid
.pal_tr_valid_s
.priv_level_valid
,
787 tr_valid
.pal_tr_valid_s
.dirty_bit_valid
,
788 tr_valid
.pal_tr_valid_s
.mem_attr_valid
,
789 (gr_reg
->ppn
& pgm
)<< 12, (ifa_reg
->vpn
& pgm
)<< 12);
791 bitvector_process(m
, 1<< itir_reg
->ps
);
800 gr_reg
->pl
, gr_reg
->ar
, rid_reg
->rid
, gr_reg
->p
, gr_reg
->ma
,
810 * List {name,function} pairs for every entry in /proc/palinfo/cpu*
812 static const palinfo_entry_t palinfo_entries
[]={
813 { "version_info", version_info
, },
814 { "vm_info", vm_info
, },
815 { "cache_info", cache_info
, },
816 { "power_info", power_info
, },
817 { "register_info", register_info
, },
818 { "processor_info", processor_info
, },
819 { "perfmon_info", perfmon_info
, },
820 { "frequency_info", frequency_info
, },
821 { "bus_info", bus_info
},
822 { "tr_info", tr_info
, }
825 #define NR_PALINFO_ENTRIES (int) ARRAY_SIZE(palinfo_entries)
827 static struct proc_dir_entry
*palinfo_dir
;
830 * This data structure is used to pass which cpu,function is being requested
831 * It must fit in a 64bit quantity to be passed to the proc callback routine
833 * In SMP mode, when we get a request for another CPU, we must call that
834 * other CPU using IPI and wait for the result before returning.
839 unsigned req_cpu
: 32; /* for which CPU this info is */
840 unsigned func_id
: 32; /* which function is requested */
844 #define req_cpu pal_func_cpu.req_cpu
845 #define func_id pal_func_cpu.func_id
850 * used to hold information about final function to call
853 palinfo_func_t func
; /* pointer to function to call */
854 struct seq_file
*m
; /* buffer to store results */
855 int ret
; /* return value from call */
856 } palinfo_smp_data_t
;
860 * this function does the actual final call and he called
861 * from the smp code, i.e., this is the palinfo callback routine
864 palinfo_smp_call(void *info
)
866 palinfo_smp_data_t
*data
= (palinfo_smp_data_t
*)info
;
867 data
->ret
= (*data
->func
)(data
->m
);
871 * function called to trigger the IPI, we need to access a remote CPU
873 * 0 : error or nothing to output
874 * otherwise how many bytes in the "page" buffer were written
877 int palinfo_handle_smp(struct seq_file
*m
, pal_func_cpu_u_t
*f
)
879 palinfo_smp_data_t ptr
;
882 ptr
.func
= palinfo_entries
[f
->func_id
].proc_read
;
884 ptr
.ret
= 0; /* just in case */
887 /* will send IPI to other CPU and wait for completion of remote call */
888 if ((ret
=smp_call_function_single(f
->req_cpu
, palinfo_smp_call
, &ptr
, 1))) {
889 printk(KERN_ERR
"palinfo: remote CPU call from %d to %d on function %d: "
890 "error %d\n", smp_processor_id(), f
->req_cpu
, f
->func_id
, ret
);
895 #else /* ! CONFIG_SMP */
897 int palinfo_handle_smp(struct seq_file
*m
, pal_func_cpu_u_t
*f
)
899 printk(KERN_ERR
"palinfo: should not be called with non SMP kernel\n");
902 #endif /* CONFIG_SMP */
905 * Entry point routine: all calls go through this function
907 static int proc_palinfo_show(struct seq_file
*m
, void *v
)
909 pal_func_cpu_u_t
*f
= (pal_func_cpu_u_t
*)&m
->private;
912 * in SMP mode, we may need to call another CPU to get correct
913 * information. PAL, by definition, is processor specific
915 if (f
->req_cpu
== get_cpu())
916 (*palinfo_entries
[f
->func_id
].proc_read
)(m
);
918 palinfo_handle_smp(m
, f
);
924 static int palinfo_add_proc(unsigned int cpu
)
927 struct proc_dir_entry
*cpu_dir
;
929 char cpustr
[3+4+1]; /* cpu numbers are up to 4095 on itanic */
930 sprintf(cpustr
, "cpu%d", cpu
);
932 cpu_dir
= proc_mkdir(cpustr
, palinfo_dir
);
938 for (j
=0; j
< NR_PALINFO_ENTRIES
; j
++) {
940 proc_create_single_data(palinfo_entries
[j
].name
, 0, cpu_dir
,
941 proc_palinfo_show
, (void *)f
.value
);
946 static int palinfo_del_proc(unsigned int hcpu
)
948 char cpustr
[3+4+1]; /* cpu numbers are up to 4095 on itanic */
950 sprintf(cpustr
, "cpu%d", hcpu
);
951 remove_proc_subtree(cpustr
, palinfo_dir
);
955 static enum cpuhp_state hp_online
;
957 static int __init
palinfo_init(void)
961 printk(KERN_INFO
"PAL Information Facility v%s\n", PALINFO_VERSION
);
962 palinfo_dir
= proc_mkdir("pal", NULL
);
966 i
= cpuhp_setup_state(CPUHP_AP_ONLINE_DYN
, "ia64/palinfo:online",
967 palinfo_add_proc
, palinfo_del_proc
);
969 remove_proc_subtree("pal", NULL
);
976 static void __exit
palinfo_exit(void)
978 cpuhp_remove_state(hp_online
);
979 remove_proc_subtree("pal", NULL
);
982 module_init(palinfo_init
);
983 module_exit(palinfo_exit
);