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 | |
| parent | a2c2bc4b263828a380813a236fa6fcf8185b460b (diff) | |
[MIPS] Oprofile: Support VSMP on 34K.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
| -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"; |
