aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/oprofile
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/oprofile')
-rw-r--r--arch/powerpc/oprofile/op_model_power4.c37
1 files changed, 15 insertions, 22 deletions
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