1
2
3
4
5
6
7
8
9
10#include <linux/oprofile.h>
11#include <linux/init.h>
12#include <linux/smp.h>
13#include <asm/ptrace.h>
14#include <asm/system.h>
15
16#include "op_impl.h"
17
18
19
20
21
22
23
24
25
26static void
27common_reg_setup(struct op_register_config *reg,
28 struct op_counter_config *ctr,
29 struct op_system_config *sys,
30 int cbox1_ofs, int cbox2_ofs)
31{
32 int i, ctl, reset, need_reset;
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 ctl = 0;
48 for (i = 0; i < 3; ++i) {
49 unsigned long event = ctr[i].event;
50 if (!ctr[i].enabled)
51 continue;
52
53
54 if (i == 2) {
55 if (event == 0)
56 event = 12+48;
57 else if (event == 2+41)
58 event = 4+65;
59 }
60
61
62 if (event < 2)
63 ctl |= event << 31;
64 else if (event < 24)
65 ;
66 else if (event < 40)
67 ctl |= (event - 24) << 4;
68 else if (event < 48)
69 ctl |= (event - 40) << cbox1_ofs | 15 << 4;
70 else if (event < 64)
71 ctl |= event - 48;
72 else if (event < 72)
73 ctl |= (event - 64) << cbox2_ofs | 15;
74 }
75 reg->mux_select = ctl;
76
77
78
79
80 ctl = 0;
81 ctl |= !sys->enable_pal << 9;
82 ctl |= !sys->enable_kernel << 8;
83 ctl |= !sys->enable_user << 30;
84 reg->proc_mode = ctl;
85
86
87
88
89
90
91 ctl = reset = need_reset = 0;
92 for (i = 0; i < 3; ++i) {
93 unsigned long max, hilo, count = ctr[i].count;
94 if (!ctr[i].enabled)
95 continue;
96
97 if (count <= 256)
98 count = 256, hilo = 3, max = 256;
99 else {
100 max = (i == 2 ? 16384 : 65536);
101 hilo = 2;
102 if (count > max)
103 count = max;
104 }
105 ctr[i].count = count;
106
107 ctl |= hilo << (8 - i*2);
108 reset |= (max - count) << (48 - 16*i);
109 if (count != max)
110 need_reset |= 1 << i;
111 }
112 reg->freq = ctl;
113 reg->reset_values = reset;
114 reg->need_reset = need_reset;
115}
116
117static void
118ev5_reg_setup(struct op_register_config *reg,
119 struct op_counter_config *ctr,
120 struct op_system_config *sys)
121{
122 common_reg_setup(reg, ctr, sys, 19, 22);
123}
124
125static void
126pca56_reg_setup(struct op_register_config *reg,
127 struct op_counter_config *ctr,
128 struct op_system_config *sys)
129{
130 common_reg_setup(reg, ctr, sys, 8, 11);
131}
132
133
134
135static void
136ev5_cpu_setup (void *x)
137{
138 struct op_register_config *reg = x;
139
140 wrperfmon(2, reg->mux_select);
141 wrperfmon(3, reg->proc_mode);
142 wrperfmon(4, reg->freq);
143 wrperfmon(6, reg->reset_values);
144}
145
146
147
148
149
150
151
152
153
154
155
156
157
158static void
159ev5_reset_ctr(struct op_register_config *reg, unsigned long ctr)
160{
161 unsigned long values, mask, not_pk, reset_values;
162
163 mask = (ctr == 0 ? 0xfffful << 48
164 : ctr == 1 ? 0xfffful << 32
165 : 0x3fff << 16);
166
167 not_pk = 1 << 9 | 1 << 8;
168
169 reset_values = reg->reset_values;
170
171 if ((reg->proc_mode & not_pk) == not_pk) {
172 values = wrperfmon(5, 0);
173 values = (reset_values & mask) | (values & ~mask & -2);
174 wrperfmon(6, values);
175 } else {
176 wrperfmon(0, -1);
177 values = wrperfmon(5, 0);
178 values = (reset_values & mask) | (values & ~mask & -2);
179 wrperfmon(6, values);
180 wrperfmon(1, reg->enable);
181 }
182}
183
184static void
185ev5_handle_interrupt(unsigned long which, struct pt_regs *regs,
186 struct op_counter_config *ctr)
187{
188
189 oprofile_add_sample(regs, which);
190}
191
192
193struct op_axp_model op_model_ev5 = {
194 .reg_setup = ev5_reg_setup,
195 .cpu_setup = ev5_cpu_setup,
196 .reset_ctr = ev5_reset_ctr,
197 .handle_interrupt = ev5_handle_interrupt,
198 .cpu_type = "alpha/ev5",
199 .num_counters = 3,
200 .can_set_proc_mode = 1,
201};
202
203struct op_axp_model op_model_pca56 = {
204 .reg_setup = pca56_reg_setup,
205 .cpu_setup = ev5_cpu_setup,
206 .reset_ctr = ev5_reset_ctr,
207 .handle_interrupt = ev5_handle_interrupt,
208 .cpu_type = "alpha/pca56",
209 .num_counters = 3,
210 .can_set_proc_mode = 1,
211};
212