diff options
Diffstat (limited to 'arch/powerpc/platforms/pseries/hvCall_inst.c')
-rw-r--r-- | arch/powerpc/platforms/pseries/hvCall_inst.c | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/pseries/hvCall_inst.c b/arch/powerpc/platforms/pseries/hvCall_inst.c new file mode 100644 index 000000000000..641e6511cf06 --- /dev/null +++ b/arch/powerpc/platforms/pseries/hvCall_inst.c | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2006 Mike Kravetz IBM Corporation | ||
3 | * | ||
4 | * Hypervisor Call Instrumentation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/percpu.h> | ||
23 | #include <linux/debugfs.h> | ||
24 | #include <linux/seq_file.h> | ||
25 | #include <linux/cpumask.h> | ||
26 | #include <asm/hvcall.h> | ||
27 | #include <asm/firmware.h> | ||
28 | #include <asm/cputable.h> | ||
29 | |||
30 | DEFINE_PER_CPU(struct hcall_stats[HCALL_STAT_ARRAY_SIZE], hcall_stats); | ||
31 | |||
32 | /* | ||
33 | * Routines for displaying the statistics in debugfs | ||
34 | */ | ||
35 | static void *hc_start(struct seq_file *m, loff_t *pos) | ||
36 | { | ||
37 | if ((int)*pos < HCALL_STAT_ARRAY_SIZE) | ||
38 | return (void *)(unsigned long)(*pos + 1); | ||
39 | |||
40 | return NULL; | ||
41 | } | ||
42 | |||
43 | static void *hc_next(struct seq_file *m, void *p, loff_t * pos) | ||
44 | { | ||
45 | ++*pos; | ||
46 | |||
47 | return hc_start(m, pos); | ||
48 | } | ||
49 | |||
50 | static void hc_stop(struct seq_file *m, void *p) | ||
51 | { | ||
52 | } | ||
53 | |||
54 | static int hc_show(struct seq_file *m, void *p) | ||
55 | { | ||
56 | unsigned long h_num = (unsigned long)p; | ||
57 | struct hcall_stats *hs = (struct hcall_stats *)m->private; | ||
58 | |||
59 | if (hs[h_num].num_calls) { | ||
60 | if (!cpu_has_feature(CPU_FTR_PURR)) | ||
61 | seq_printf(m, "%lu %lu %lu %lu\n", h_num<<2, | ||
62 | hs[h_num].num_calls, | ||
63 | hs[h_num].tb_total, | ||
64 | hs[h_num].purr_total); | ||
65 | else | ||
66 | seq_printf(m, "%lu %lu %lu\n", h_num<<2, | ||
67 | hs[h_num].num_calls, | ||
68 | hs[h_num].tb_total); | ||
69 | } | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | static struct seq_operations hcall_inst_seq_ops = { | ||
75 | .start = hc_start, | ||
76 | .next = hc_next, | ||
77 | .stop = hc_stop, | ||
78 | .show = hc_show | ||
79 | }; | ||
80 | |||
81 | static int hcall_inst_seq_open(struct inode *inode, struct file *file) | ||
82 | { | ||
83 | int rc; | ||
84 | struct seq_file *seq; | ||
85 | |||
86 | rc = seq_open(file, &hcall_inst_seq_ops); | ||
87 | seq = file->private_data; | ||
88 | seq->private = file->f_dentry->d_inode->u.generic_ip; | ||
89 | |||
90 | return rc; | ||
91 | } | ||
92 | |||
93 | static struct file_operations hcall_inst_seq_fops = { | ||
94 | .open = hcall_inst_seq_open, | ||
95 | .read = seq_read, | ||
96 | .llseek = seq_lseek, | ||
97 | .release = seq_release, | ||
98 | }; | ||
99 | |||
100 | #define HCALL_ROOT_DIR "hcall_inst" | ||
101 | #define CPU_NAME_BUF_SIZE 32 | ||
102 | |||
103 | static int __init hcall_inst_init(void) | ||
104 | { | ||
105 | struct dentry *hcall_root; | ||
106 | struct dentry *hcall_file; | ||
107 | char cpu_name_buf[CPU_NAME_BUF_SIZE]; | ||
108 | int cpu; | ||
109 | |||
110 | if (!firmware_has_feature(FW_FEATURE_LPAR)) | ||
111 | return 0; | ||
112 | |||
113 | hcall_root = debugfs_create_dir(HCALL_ROOT_DIR, NULL); | ||
114 | if (!hcall_root) | ||
115 | return -ENOMEM; | ||
116 | |||
117 | for_each_possible_cpu(cpu) { | ||
118 | snprintf(cpu_name_buf, CPU_NAME_BUF_SIZE, "cpu%d", cpu); | ||
119 | hcall_file = debugfs_create_file(cpu_name_buf, S_IRUGO, | ||
120 | hcall_root, | ||
121 | per_cpu(hcall_stats, cpu), | ||
122 | &hcall_inst_seq_fops); | ||
123 | if (!hcall_file) | ||
124 | return -ENOMEM; | ||
125 | } | ||
126 | |||
127 | return 0; | ||
128 | } | ||
129 | __initcall(hcall_inst_init); | ||