diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2006-06-23 13:39:00 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2006-06-29 16:10:54 -0400 |
commit | 92c7b62fd1a6898fbfaf1db790ba4e70e90f39d2 (patch) | |
tree | e02484e4db5a263cccf0c5578403ad665bfb3241 /arch/mips/oprofile | |
parent | a2c2bc4b263828a380813a236fa6fcf8185b460b (diff) |
[MIPS] Oprofile: Support VSMP on 34K.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/oprofile')
-rw-r--r-- | arch/mips/oprofile/op_model_mipsxx.c | 148 |
1 files changed, 106 insertions, 42 deletions
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c index f26a00e13204..a09c5f901233 100644 --- a/arch/mips/oprofile/op_model_mipsxx.c +++ b/arch/mips/oprofile/op_model_mipsxx.c | |||
@@ -12,16 +12,70 @@ | |||
12 | 12 | ||
13 | #include "op_impl.h" | 13 | #include "op_impl.h" |
14 | 14 | ||
15 | #define M_PERFCTL_EXL (1UL << 0) | 15 | #define M_PERFCTL_EXL (1UL << 0) |
16 | #define M_PERFCTL_KERNEL (1UL << 1) | 16 | #define M_PERFCTL_KERNEL (1UL << 1) |
17 | #define M_PERFCTL_SUPERVISOR (1UL << 2) | 17 | #define M_PERFCTL_SUPERVISOR (1UL << 2) |
18 | #define M_PERFCTL_USER (1UL << 3) | 18 | #define M_PERFCTL_USER (1UL << 3) |
19 | #define M_PERFCTL_INTERRUPT_ENABLE (1UL << 4) | 19 | #define M_PERFCTL_INTERRUPT_ENABLE (1UL << 4) |
20 | #define M_PERFCTL_EVENT(event) ((event) << 5) | 20 | #define M_PERFCTL_EVENT(event) ((event) << 5) |
21 | #define M_PERFCTL_WIDE (1UL << 30) | 21 | #define M_PERFCTL_VPEID(vpe) ((vpe) << 16) |
22 | #define M_PERFCTL_MORE (1UL << 31) | 22 | #define M_PERFCTL_MT_EN(filter) ((filter) << 20) |
23 | #define M_TC_EN_ALL M_PERFCTL_MT_EN(0) | ||
24 | #define M_TC_EN_VPE M_PERFCTL_MT_EN(1) | ||
25 | #define M_TC_EN_TC M_PERFCTL_MT_EN(2) | ||
26 | #define M_PERFCTL_TCID(tcid) ((tcid) << 22) | ||
27 | #define M_PERFCTL_WIDE (1UL << 30) | ||
28 | #define M_PERFCTL_MORE (1UL << 31) | ||
29 | |||
30 | #define M_COUNTER_OVERFLOW (1UL << 31) | ||
31 | |||
32 | #ifdef CONFIG_MIPS_MT_SMP | ||
33 | #define WHAT (M_TC_EN_VPE | M_PERFCTL_VPEID(smp_processor_id())) | ||
34 | #else | ||
35 | #define WHAT 0 | ||
36 | #endif | ||
23 | 37 | ||
24 | #define M_COUNTER_OVERFLOW (1UL << 31) | 38 | #define __define_perf_accessors(r, n, np) \ |
39 | \ | ||
40 | static inline unsigned int r_c0_ ## r ## n(void) \ | ||
41 | { \ | ||
42 | unsigned int cpu = smp_processor_id(); \ | ||
43 | \ | ||
44 | switch (cpu) { \ | ||
45 | case 0: \ | ||
46 | return read_c0_ ## r ## n(); \ | ||
47 | case 1: \ | ||
48 | return read_c0_ ## r ## np(); \ | ||
49 | default: \ | ||
50 | BUG(); \ | ||
51 | } \ | ||
52 | } \ | ||
53 | \ | ||
54 | static inline void w_c0_ ## r ## n(unsigned int value) \ | ||
55 | { \ | ||
56 | unsigned int cpu = smp_processor_id(); \ | ||
57 | \ | ||
58 | switch (cpu) { \ | ||
59 | case 0: \ | ||
60 | write_c0_ ## r ## n(value); \ | ||
61 | return; \ | ||
62 | case 1: \ | ||
63 | write_c0_ ## r ## np(value); \ | ||
64 | return; \ | ||
65 | default: \ | ||
66 | BUG(); \ | ||
67 | } \ | ||
68 | } \ | ||
69 | |||
70 | __define_perf_accessors(perfcntr, 0, 2) | ||
71 | __define_perf_accessors(perfcntr, 1, 3) | ||
72 | __define_perf_accessors(perfcntr, 2, 2) | ||
73 | __define_perf_accessors(perfcntr, 3, 2) | ||
74 | |||
75 | __define_perf_accessors(perfctrl, 0, 2) | ||
76 | __define_perf_accessors(perfctrl, 1, 3) | ||
77 | __define_perf_accessors(perfctrl, 2, 2) | ||
78 | __define_perf_accessors(perfctrl, 3, 2) | ||
25 | 79 | ||
26 | struct op_mips_model op_model_mipsxx_ops; | 80 | struct op_mips_model op_model_mipsxx_ops; |
27 | 81 | ||
@@ -66,17 +120,17 @@ static void mipsxx_cpu_setup (void *args) | |||
66 | 120 | ||
67 | switch (counters) { | 121 | switch (counters) { |
68 | case 4: | 122 | case 4: |
69 | write_c0_perfctrl3(0); | 123 | w_c0_perfctrl3(0); |
70 | write_c0_perfcntr3(reg.counter[3]); | 124 | w_c0_perfcntr3(reg.counter[3]); |
71 | case 3: | 125 | case 3: |
72 | write_c0_perfctrl2(0); | 126 | w_c0_perfctrl2(0); |
73 | write_c0_perfcntr2(reg.counter[2]); | 127 | w_c0_perfcntr2(reg.counter[2]); |
74 | case 2: | 128 | case 2: |
75 | write_c0_perfctrl1(0); | 129 | w_c0_perfctrl1(0); |
76 | write_c0_perfcntr1(reg.counter[1]); | 130 | w_c0_perfcntr1(reg.counter[1]); |
77 | case 1: | 131 | case 1: |
78 | write_c0_perfctrl0(0); | 132 | w_c0_perfctrl0(0); |
79 | write_c0_perfcntr0(reg.counter[0]); | 133 | w_c0_perfcntr0(reg.counter[0]); |
80 | } | 134 | } |
81 | } | 135 | } |
82 | 136 | ||
@@ -87,13 +141,13 @@ static void mipsxx_cpu_start(void *args) | |||
87 | 141 | ||
88 | switch (counters) { | 142 | switch (counters) { |
89 | case 4: | 143 | case 4: |
90 | write_c0_perfctrl3(reg.control[3]); | 144 | w_c0_perfctrl3(WHAT | reg.control[3]); |
91 | case 3: | 145 | case 3: |
92 | write_c0_perfctrl2(reg.control[2]); | 146 | w_c0_perfctrl2(WHAT | reg.control[2]); |
93 | case 2: | 147 | case 2: |
94 | write_c0_perfctrl1(reg.control[1]); | 148 | w_c0_perfctrl1(WHAT | reg.control[1]); |
95 | case 1: | 149 | case 1: |
96 | write_c0_perfctrl0(reg.control[0]); | 150 | w_c0_perfctrl0(WHAT | reg.control[0]); |
97 | } | 151 | } |
98 | } | 152 | } |
99 | 153 | ||
@@ -104,13 +158,13 @@ static void mipsxx_cpu_stop(void *args) | |||
104 | 158 | ||
105 | switch (counters) { | 159 | switch (counters) { |
106 | case 4: | 160 | case 4: |
107 | write_c0_perfctrl3(0); | 161 | w_c0_perfctrl3(0); |
108 | case 3: | 162 | case 3: |
109 | write_c0_perfctrl2(0); | 163 | w_c0_perfctrl2(0); |
110 | case 2: | 164 | case 2: |
111 | write_c0_perfctrl1(0); | 165 | w_c0_perfctrl1(0); |
112 | case 1: | 166 | case 1: |
113 | write_c0_perfctrl0(0); | 167 | w_c0_perfctrl0(0); |
114 | } | 168 | } |
115 | } | 169 | } |
116 | 170 | ||
@@ -124,12 +178,12 @@ static int mipsxx_perfcount_handler(struct pt_regs *regs) | |||
124 | switch (counters) { | 178 | switch (counters) { |
125 | #define HANDLE_COUNTER(n) \ | 179 | #define HANDLE_COUNTER(n) \ |
126 | case n + 1: \ | 180 | case n + 1: \ |
127 | control = read_c0_perfctrl ## n(); \ | 181 | control = r_c0_perfctrl ## n(); \ |
128 | counter = read_c0_perfcntr ## n(); \ | 182 | counter = r_c0_perfcntr ## n(); \ |
129 | if ((control & M_PERFCTL_INTERRUPT_ENABLE) && \ | 183 | if ((control & M_PERFCTL_INTERRUPT_ENABLE) && \ |
130 | (counter & M_COUNTER_OVERFLOW)) { \ | 184 | (counter & M_COUNTER_OVERFLOW)) { \ |
131 | oprofile_add_sample(regs, n); \ | 185 | oprofile_add_sample(regs, n); \ |
132 | write_c0_perfcntr ## n(reg.counter[n]); \ | 186 | w_c0_perfcntr ## n(reg.counter[n]); \ |
133 | handled = 1; \ | 187 | handled = 1; \ |
134 | } | 188 | } |
135 | HANDLE_COUNTER(3) | 189 | HANDLE_COUNTER(3) |
@@ -143,35 +197,47 @@ static int mipsxx_perfcount_handler(struct pt_regs *regs) | |||
143 | 197 | ||
144 | #define M_CONFIG1_PC (1 << 4) | 198 | #define M_CONFIG1_PC (1 << 4) |
145 | 199 | ||
146 | static inline int n_counters(void) | 200 | static inline int __n_counters(void) |
147 | { | 201 | { |
148 | if (!(read_c0_config1() & M_CONFIG1_PC)) | 202 | if (!(read_c0_config1() & M_CONFIG1_PC)) |
149 | return 0; | 203 | return 0; |
150 | if (!(read_c0_perfctrl0() & M_PERFCTL_MORE)) | 204 | if (!(r_c0_perfctrl0() & M_PERFCTL_MORE)) |
151 | return 1; | 205 | return 1; |
152 | if (!(read_c0_perfctrl1() & M_PERFCTL_MORE)) | 206 | if (!(r_c0_perfctrl1() & M_PERFCTL_MORE)) |
153 | return 2; | 207 | return 2; |
154 | if (!(read_c0_perfctrl2() & M_PERFCTL_MORE)) | 208 | if (!(r_c0_perfctrl2() & M_PERFCTL_MORE)) |
155 | return 3; | 209 | return 3; |
156 | 210 | ||
157 | return 4; | 211 | return 4; |
158 | } | 212 | } |
159 | 213 | ||
214 | static inline int n_counters(void) | ||
215 | { | ||
216 | int counters = __n_counters(); | ||
217 | |||
218 | #ifndef CONFIG_SMP | ||
219 | if (current_cpu_data.cputype == CPU_34K) | ||
220 | return counters >> 1; | ||
221 | #endif | ||
222 | |||
223 | return counters; | ||
224 | } | ||
225 | |||
160 | static inline void reset_counters(int counters) | 226 | static inline void reset_counters(int counters) |
161 | { | 227 | { |
162 | switch (counters) { | 228 | switch (counters) { |
163 | case 4: | 229 | case 4: |
164 | write_c0_perfctrl3(0); | 230 | w_c0_perfctrl3(0); |
165 | write_c0_perfcntr3(0); | 231 | w_c0_perfcntr3(0); |
166 | case 3: | 232 | case 3: |
167 | write_c0_perfctrl2(0); | 233 | w_c0_perfctrl2(0); |
168 | write_c0_perfcntr2(0); | 234 | w_c0_perfcntr2(0); |
169 | case 2: | 235 | case 2: |
170 | write_c0_perfctrl1(0); | 236 | w_c0_perfctrl1(0); |
171 | write_c0_perfcntr1(0); | 237 | w_c0_perfcntr1(0); |
172 | case 1: | 238 | case 1: |
173 | write_c0_perfctrl0(0); | 239 | w_c0_perfctrl0(0); |
174 | write_c0_perfcntr0(0); | 240 | w_c0_perfcntr0(0); |
175 | } | 241 | } |
176 | } | 242 | } |
177 | 243 | ||
@@ -201,7 +267,6 @@ static int __init mipsxx_init(void) | |||
201 | op_model_mipsxx_ops.cpu_type = "mips/25K"; | 267 | op_model_mipsxx_ops.cpu_type = "mips/25K"; |
202 | break; | 268 | break; |
203 | 269 | ||
204 | #ifndef CONFIG_SMP | ||
205 | case CPU_34K: | 270 | case CPU_34K: |
206 | op_model_mipsxx_ops.cpu_type = "mips/34K"; | 271 | op_model_mipsxx_ops.cpu_type = "mips/34K"; |
207 | break; | 272 | break; |
@@ -209,7 +274,6 @@ static int __init mipsxx_init(void) | |||
209 | case CPU_74K: | 274 | case CPU_74K: |
210 | op_model_mipsxx_ops.cpu_type = "mips/74K"; | 275 | op_model_mipsxx_ops.cpu_type = "mips/74K"; |
211 | break; | 276 | break; |
212 | #endif | ||
213 | 277 | ||
214 | case CPU_5KC: | 278 | case CPU_5KC: |
215 | op_model_mipsxx_ops.cpu_type = "mips/5K"; | 279 | op_model_mipsxx_ops.cpu_type = "mips/5K"; |