aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--arch/powerpc/kernel/cputable.c13
-rw-r--r--arch/powerpc/oprofile/op_model_power4.c37
-rw-r--r--include/asm-powerpc/cputable.h11
-rw-r--r--include/asm-powerpc/reg.h4
4 files changed, 39 insertions, 26 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
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h
index 9fcf0162d859..defc166379d2 100644
--- a/include/asm-powerpc/cputable.h
+++ b/include/asm-powerpc/cputable.h
@@ -69,6 +69,13 @@ struct cpu_spec {
69 /* Processor specific oprofile operations */ 69 /* Processor specific oprofile operations */
70 enum powerpc_oprofile_type oprofile_type; 70 enum powerpc_oprofile_type oprofile_type;
71 71
72 /* Bit locations inside the mmcra change */
73 unsigned long oprofile_mmcra_sihv;
74 unsigned long oprofile_mmcra_sipr;
75
76 /* Bits to clear during an oprofile exception */
77 unsigned long oprofile_mmcra_clear;
78
72 /* Name of processor class, for the ELF AT_PLATFORM entry */ 79 /* Name of processor class, for the ELF AT_PLATFORM entry */
73 char *platform; 80 char *platform;
74}; 81};
@@ -117,7 +124,6 @@ extern void do_cpu_ftr_fixups(unsigned long offset);
117#define CPU_FTR_SMT ASM_CONST(0x0000010000000000) 124#define CPU_FTR_SMT ASM_CONST(0x0000010000000000)
118#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0000020000000000) 125#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0000020000000000)
119#define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0000040000000000) 126#define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0000040000000000)
120#define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0000080000000000)
121#define CPU_FTR_CI_LARGE_PAGE ASM_CONST(0x0000100000000000) 127#define CPU_FTR_CI_LARGE_PAGE ASM_CONST(0x0000100000000000)
122#define CPU_FTR_PAUSE_ZERO ASM_CONST(0x0000200000000000) 128#define CPU_FTR_PAUSE_ZERO ASM_CONST(0x0000200000000000)
123#define CPU_FTR_PURR ASM_CONST(0x0000400000000000) 129#define CPU_FTR_PURR ASM_CONST(0x0000400000000000)
@@ -134,7 +140,6 @@ extern void do_cpu_ftr_fixups(unsigned long offset);
134#define CPU_FTR_SMT ASM_CONST(0x0) 140#define CPU_FTR_SMT ASM_CONST(0x0)
135#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0) 141#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0)
136#define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0) 142#define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0)
137#define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0)
138#define CPU_FTR_CI_LARGE_PAGE ASM_CONST(0x0) 143#define CPU_FTR_CI_LARGE_PAGE ASM_CONST(0x0)
139#define CPU_FTR_PURR ASM_CONST(0x0) 144#define CPU_FTR_PURR ASM_CONST(0x0)
140#endif 145#endif
@@ -320,7 +325,7 @@ extern void do_cpu_ftr_fixups(unsigned long offset);
320 CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \ 325 CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
321 CPU_FTR_MMCRA | CPU_FTR_SMT | \ 326 CPU_FTR_MMCRA | CPU_FTR_SMT | \
322 CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ 327 CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
323 CPU_FTR_MMCRA_SIHV | CPU_FTR_PURR) 328 CPU_FTR_PURR)
324#define CPU_FTRS_POWER6 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ 329#define CPU_FTRS_POWER6 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
325 CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \ 330 CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
326 CPU_FTR_MMCRA | CPU_FTR_SMT | \ 331 CPU_FTR_MMCRA | CPU_FTR_SMT | \
diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h
index 0257189d5017..3779b21a7c71 100644
--- a/include/asm-powerpc/reg.h
+++ b/include/asm-powerpc/reg.h
@@ -443,6 +443,10 @@
443#define MMCRA_SIHV 0x10000000UL /* state of MSR HV when SIAR set */ 443#define MMCRA_SIHV 0x10000000UL /* state of MSR HV when SIAR set */
444#define MMCRA_SIPR 0x08000000UL /* state of MSR PR when SIAR set */ 444#define MMCRA_SIPR 0x08000000UL /* state of MSR PR when SIAR set */
445#define MMCRA_SAMPLE_ENABLE 0x00000001UL /* enable sampling */ 445#define MMCRA_SAMPLE_ENABLE 0x00000001UL /* enable sampling */
446#define POWER6_MMCRA_SIHV 0x0000040000000000ULL
447#define POWER6_MMCRA_SIPR 0x0000020000000000ULL
448#define POWER6_MMCRA_THRM 0x00000020UL
449#define POWER6_MMCRA_OTHER 0x0000000EUL
446#define SPRN_PMC1 787 450#define SPRN_PMC1 787
447#define SPRN_PMC2 788 451#define SPRN_PMC2 788
448#define SPRN_PMC3 789 452#define SPRN_PMC3 789