1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include <linux/oprofile.h>
17#include <linux/init.h>
18#include <linux/smp.h>
19#include <linux/errno.h>
20#include <asm/ptrace.h>
21#include <asm/pmc.h>
22#include <asm/cputable.h>
23#include <asm/oprofile_impl.h>
24#include <asm/firmware.h>
25
26static struct op_powerpc_model *model;
27
28static struct op_counter_config ctr[OP_MAX_COUNTER];
29static struct op_system_config sys;
30
31static int op_per_cpu_rc;
32
33static void op_handle_interrupt(struct pt_regs *regs)
34{
35 model->handle_interrupt(regs, ctr);
36}
37
38static void op_powerpc_cpu_setup(void *dummy)
39{
40 int ret;
41
42 ret = model->cpu_setup(ctr);
43
44 if (ret != 0)
45 op_per_cpu_rc = ret;
46}
47
48static int op_powerpc_setup(void)
49{
50 int err;
51
52 op_per_cpu_rc = 0;
53
54
55 err = reserve_pmc_hardware(op_handle_interrupt);
56 if (err)
57 return err;
58
59
60 op_per_cpu_rc = model->reg_setup(ctr, &sys, model->num_counters);
61
62 if (op_per_cpu_rc)
63 goto out;
64
65
66
67 on_each_cpu(op_powerpc_cpu_setup, NULL, 1);
68
69out: if (op_per_cpu_rc) {
70
71 release_pmc_hardware();
72 }
73
74 return op_per_cpu_rc;
75}
76
77static void op_powerpc_shutdown(void)
78{
79 release_pmc_hardware();
80}
81
82static void op_powerpc_cpu_start(void *dummy)
83{
84
85
86
87
88 int ret;
89
90 ret = model->start(ctr);
91 if (ret != 0)
92 op_per_cpu_rc = ret;
93}
94
95static int op_powerpc_start(void)
96{
97 op_per_cpu_rc = 0;
98
99 if (model->global_start)
100 return model->global_start(ctr);
101 if (model->start) {
102 on_each_cpu(op_powerpc_cpu_start, NULL, 1);
103 return op_per_cpu_rc;
104 }
105 return -EIO;
106
107}
108
109static inline void op_powerpc_cpu_stop(void *dummy)
110{
111 model->stop();
112}
113
114static void op_powerpc_stop(void)
115{
116 if (model->stop)
117 on_each_cpu(op_powerpc_cpu_stop, NULL, 1);
118 if (model->global_stop)
119 model->global_stop();
120}
121
122static int op_powerpc_create_files(struct dentry *root)
123{
124 int i;
125
126#ifdef CONFIG_PPC64
127
128
129
130
131 oprofilefs_create_ulong(root, "mmcr0", &sys.mmcr0);
132 oprofilefs_create_ulong(root, "mmcr1", &sys.mmcr1);
133 oprofilefs_create_ulong(root, "mmcra", &sys.mmcra);
134#ifdef CONFIG_OPROFILE_CELL
135
136
137
138
139
140
141
142
143
144
145 oprofilefs_create_ulong(root, "cell_support", &sys.cell_support);
146 sys.cell_support = 0x1;
147
148
149
150
151
152
153
154
155#endif
156#endif
157
158 for (i = 0; i < model->num_counters; ++i) {
159 struct dentry *dir;
160 char buf[4];
161
162 snprintf(buf, sizeof buf, "%d", i);
163 dir = oprofilefs_mkdir(root, buf);
164
165 oprofilefs_create_ulong(dir, "enabled", &ctr[i].enabled);
166 oprofilefs_create_ulong(dir, "event", &ctr[i].event);
167 oprofilefs_create_ulong(dir, "count", &ctr[i].count);
168
169
170
171
172
173
174
175
176 oprofilefs_create_ulong(dir, "kernel", &ctr[i].kernel);
177 oprofilefs_create_ulong(dir, "user", &ctr[i].user);
178
179 oprofilefs_create_ulong(dir, "unit_mask", &ctr[i].unit_mask);
180 }
181
182 oprofilefs_create_ulong(root, "enable_kernel", &sys.enable_kernel);
183 oprofilefs_create_ulong(root, "enable_user", &sys.enable_user);
184
185
186 sys.enable_kernel = 1;
187 sys.enable_user = 1;
188
189 return 0;
190}
191
192int __init oprofile_arch_init(struct oprofile_operations *ops)
193{
194 if (!cur_cpu_spec->oprofile_cpu_type)
195 return -ENODEV;
196
197 switch (cur_cpu_spec->oprofile_type) {
198#ifdef CONFIG_PPC_BOOK3S_64
199#ifdef CONFIG_OPROFILE_CELL
200 case PPC_OPROFILE_CELL:
201 if (firmware_has_feature(FW_FEATURE_LPAR))
202 return -ENODEV;
203 model = &op_model_cell;
204 ops->sync_start = model->sync_start;
205 ops->sync_stop = model->sync_stop;
206 break;
207#endif
208 case PPC_OPROFILE_POWER4:
209 model = &op_model_power4;
210 break;
211 case PPC_OPROFILE_PA6T:
212 model = &op_model_pa6t;
213 break;
214#endif
215#ifdef CONFIG_6xx
216 case PPC_OPROFILE_G4:
217 model = &op_model_7450;
218 break;
219#endif
220#if defined(CONFIG_FSL_EMB_PERFMON)
221 case PPC_OPROFILE_FSL_EMB:
222 model = &op_model_fsl_emb;
223 break;
224#endif
225 default:
226 return -ENODEV;
227 }
228
229 model->num_counters = cur_cpu_spec->num_pmcs;
230
231 ops->cpu_type = cur_cpu_spec->oprofile_cpu_type;
232 ops->create_files = op_powerpc_create_files;
233 ops->setup = op_powerpc_setup;
234 ops->shutdown = op_powerpc_shutdown;
235 ops->start = op_powerpc_start;
236 ops->stop = op_powerpc_stop;
237 ops->backtrace = op_powerpc_backtrace;
238
239 printk(KERN_DEBUG "oprofile: using %s performance monitoring.\n",
240 ops->cpu_type);
241
242 return 0;
243}
244
245void oprofile_arch_exit(void)
246{
247}
248