aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorMichael Neuling <mikey@neuling.org>2006-06-08 00:42:34 -0400
committerPaul Mackerras <paulus@samba.org>2006-06-09 07:24:05 -0400
commite78dbc800c37f035d476c4fdebdf43cdecfcb731 (patch)
tree3b5ff1242c284e0c77e755b62d7e8600aafceb25 /arch/powerpc
parent8eb6c6e3b9c8bfed3d75536ab142d7694627c2e5 (diff)
[PATCH] powerpc: oprofile support for POWER6
POWER6 moves some of the MMCRA bits and also requires some bits to be cleared each PMU interrupt. Signed-off-by: Michael Neuling <mikey@neuling.org> Acked-by: Anton Blanchard <anton@samba.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/kernel/cputable.c13
-rw-r--r--arch/powerpc/oprofile/op_model_power4.c37
2 files changed, 27 insertions, 23 deletions
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 7dcc01be4b09..83f9ab139d4c 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -237,6 +237,11 @@ struct cpu_spec cpu_specs[] = {
237 .num_pmcs = 6, 237 .num_pmcs = 6,
238 .oprofile_cpu_type = "ppc64/power5", 238 .oprofile_cpu_type = "ppc64/power5",
239 .oprofile_type = PPC_OPROFILE_POWER4, 239 .oprofile_type = PPC_OPROFILE_POWER4,
240 /* SIHV / SIPR bits are implemented on POWER4+ (GQ)
241 * and above but only works on POWER5 and above
242 */
243 .oprofile_mmcra_sihv = MMCRA_SIHV,
244 .oprofile_mmcra_sipr = MMCRA_SIPR,
240 .platform = "power5", 245 .platform = "power5",
241 }, 246 },
242 { /* Power5 GS */ 247 { /* Power5 GS */
@@ -250,6 +255,8 @@ struct cpu_spec cpu_specs[] = {
250 .num_pmcs = 6, 255 .num_pmcs = 6,
251 .oprofile_cpu_type = "ppc64/power5+", 256 .oprofile_cpu_type = "ppc64/power5+",
252 .oprofile_type = PPC_OPROFILE_POWER4, 257 .oprofile_type = PPC_OPROFILE_POWER4,
258 .oprofile_mmcra_sihv = MMCRA_SIHV,
259 .oprofile_mmcra_sipr = MMCRA_SIPR,
253 .platform = "power5+", 260 .platform = "power5+",
254 }, 261 },
255 { /* Power6 */ 262 { /* Power6 */
@@ -260,9 +267,13 @@ struct cpu_spec cpu_specs[] = {
260 .cpu_user_features = COMMON_USER_POWER6, 267 .cpu_user_features = COMMON_USER_POWER6,
261 .icache_bsize = 128, 268 .icache_bsize = 128,
262 .dcache_bsize = 128, 269 .dcache_bsize = 128,
263 .num_pmcs = 6, 270 .num_pmcs = 8,
264 .oprofile_cpu_type = "ppc64/power6", 271 .oprofile_cpu_type = "ppc64/power6",
265 .oprofile_type = PPC_OPROFILE_POWER4, 272 .oprofile_type = PPC_OPROFILE_POWER4,
273 .oprofile_mmcra_sihv = POWER6_MMCRA_SIHV,
274 .oprofile_mmcra_sipr = POWER6_MMCRA_SIPR,
275 .oprofile_mmcra_clear = POWER6_MMCRA_THRM |
276 POWER6_MMCRA_OTHER,
266 .platform = "power6", 277 .platform = "power6",
267 }, 278 },
268 { /* Cell Broadband Engine */ 279 { /* Cell Broadband Engine */
diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c
index 4c2beab1fdc1..506f6b79f893 100644
--- a/arch/powerpc/oprofile/op_model_power4.c
+++ b/arch/powerpc/oprofile/op_model_power4.c
@@ -24,10 +24,6 @@
24static unsigned long reset_value[OP_MAX_COUNTER]; 24static unsigned long reset_value[OP_MAX_COUNTER];
25 25
26static int oprofile_running; 26static int oprofile_running;
27static int mmcra_has_sihv;
28/* Unfortunately these bits vary between CPUs */
29static unsigned long mmcra_sihv = MMCRA_SIHV;
30static unsigned long mmcra_sipr = MMCRA_SIPR;
31 27
32/* mmcr values are set in power4_reg_setup, used in power4_cpu_setup */ 28/* mmcr values are set in power4_reg_setup, used in power4_cpu_setup */
33static u32 mmcr0_val; 29static u32 mmcr0_val;
@@ -41,16 +37,6 @@ static void power4_reg_setup(struct op_counter_config *ctr,
41 int i; 37 int i;
42 38
43 /* 39 /*
44 * SIHV / SIPR bits are only implemented on POWER4+ (GQ) and above.
45 * However we disable it on all POWER4 until we verify it works
46 * (I was seeing some strange behaviour last time I tried).
47 *
48 * It has been verified to work on POWER5 so we enable it there.
49 */
50 if (cpu_has_feature(CPU_FTR_MMCRA_SIHV))
51 mmcra_has_sihv = 1;
52
53 /*
54 * The performance counter event settings are given in the mmcr0, 40 * The performance counter event settings are given in the mmcr0,
55 * mmcr1 and mmcra values passed from the user in the 41 * mmcr1 and mmcra values passed from the user in the
56 * op_system_config structure (sys variable). 42 * op_system_config structure (sys variable).
@@ -202,18 +188,19 @@ static unsigned long get_pc(struct pt_regs *regs)
202 unsigned long mmcra; 188 unsigned long mmcra;
203 189
204 /* Cant do much about it */ 190 /* Cant do much about it */
205 if (!mmcra_has_sihv) 191 if (!cur_cpu_spec->oprofile_mmcra_sihv)
206 return pc; 192 return pc;
207 193
208 mmcra = mfspr(SPRN_MMCRA); 194 mmcra = mfspr(SPRN_MMCRA);
209 195
210 /* Were we in the hypervisor? */ 196 /* Were we in the hypervisor? */
211 if (firmware_has_feature(FW_FEATURE_LPAR) && (mmcra & mmcra_sihv)) 197 if (firmware_has_feature(FW_FEATURE_LPAR) &&
198 (mmcra & cur_cpu_spec->oprofile_mmcra_sihv))
212 /* function descriptor madness */ 199 /* function descriptor madness */
213 return *((unsigned long *)hypervisor_bucket); 200 return *((unsigned long *)hypervisor_bucket);
214 201
215 /* We were in userspace, nothing to do */ 202 /* We were in userspace, nothing to do */
216 if (mmcra & mmcra_sipr) 203 if (mmcra & cur_cpu_spec->oprofile_mmcra_sipr)
217 return pc; 204 return pc;
218 205
219#ifdef CONFIG_PPC_RTAS 206#ifdef CONFIG_PPC_RTAS
@@ -235,15 +222,14 @@ static unsigned long get_pc(struct pt_regs *regs)
235 return pc; 222 return pc;
236} 223}
237 224
238static int get_kernel(unsigned long pc) 225static int get_kernel(unsigned long pc, unsigned long mmcra)
239{ 226{
240 int is_kernel; 227 int is_kernel;
241 228
242 if (!mmcra_has_sihv) { 229 if (!cur_cpu_spec->oprofile_mmcra_sihv) {
243 is_kernel = is_kernel_addr(pc); 230 is_kernel = is_kernel_addr(pc);
244 } else { 231 } else {
245 unsigned long mmcra = mfspr(SPRN_MMCRA); 232 is_kernel = ((mmcra & cur_cpu_spec->oprofile_mmcra_sipr) == 0);
246 is_kernel = ((mmcra & mmcra_sipr) == 0);
247 } 233 }
248 234
249 return is_kernel; 235 return is_kernel;
@@ -257,9 +243,12 @@ static void power4_handle_interrupt(struct pt_regs *regs,
257 int val; 243 int val;
258 int i; 244 int i;
259 unsigned int mmcr0; 245 unsigned int mmcr0;
246 unsigned long mmcra;
247
248 mmcra = mfspr(SPRN_MMCRA);
260 249
261 pc = get_pc(regs); 250 pc = get_pc(regs);
262 is_kernel = get_kernel(pc); 251 is_kernel = get_kernel(pc, mmcra);
263 252
264 /* set the PMM bit (see comment below) */ 253 /* set the PMM bit (see comment below) */
265 mtmsrd(mfmsr() | MSR_PMM); 254 mtmsrd(mfmsr() | MSR_PMM);
@@ -287,6 +276,10 @@ static void power4_handle_interrupt(struct pt_regs *regs,
287 */ 276 */
288 mmcr0 &= ~MMCR0_PMAO; 277 mmcr0 &= ~MMCR0_PMAO;
289 278
279 /* Clear the appropriate bits in the MMCRA */
280 mmcra &= ~cur_cpu_spec->oprofile_mmcra_clear;
281 mtspr(SPRN_MMCRA, mmcra);
282
290 /* 283 /*
291 * now clear the freeze bit, counting will not start until we 284 * now clear the freeze bit, counting will not start until we
292 * rfid from this exception, because only at that point will 285 * rfid from this exception, because only at that point will