aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/mips/oprofile/op_model_mipsxx.c148
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 \
40static 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 \
54static 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
26struct op_mips_model op_model_mipsxx_ops; 80struct 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
146static inline int n_counters(void) 200static 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
214static 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
160static inline void reset_counters(int counters) 226static 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";