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