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