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