diff options
Diffstat (limited to 'arch/powerpc/oprofile/op_model_power4.c')
-rw-r--r-- | arch/powerpc/oprofile/op_model_power4.c | 37 |
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 4c2beab1fdc..506f6b79f89 100644 --- a/arch/powerpc/oprofile/op_model_power4.c +++ b/arch/powerpc/oprofile/op_model_power4.c @@ -24,10 +24,6 @@ static unsigned long reset_value[OP_MAX_COUNTER]; static int oprofile_running; -static int mmcra_has_sihv; -/* Unfortunately these bits vary between CPUs */ -static unsigned long mmcra_sihv = MMCRA_SIHV; -static unsigned long mmcra_sipr = MMCRA_SIPR; /* mmcr values are set in power4_reg_setup, used in power4_cpu_setup */ static u32 mmcr0_val; @@ -41,16 +37,6 @@ static void power4_reg_setup(struct op_counter_config *ctr, int i; /* - * SIHV / SIPR bits are only implemented on POWER4+ (GQ) and above. - * However we disable it on all POWER4 until we verify it works - * (I was seeing some strange behaviour last time I tried). - * - * It has been verified to work on POWER5 so we enable it there. - */ - if (cpu_has_feature(CPU_FTR_MMCRA_SIHV)) - mmcra_has_sihv = 1; - - /* * The performance counter event settings are given in the mmcr0, * mmcr1 and mmcra values passed from the user in the * op_system_config structure (sys variable). @@ -202,18 +188,19 @@ static unsigned long get_pc(struct pt_regs *regs) unsigned long mmcra; /* Cant do much about it */ - if (!mmcra_has_sihv) + if (!cur_cpu_spec->oprofile_mmcra_sihv) return pc; mmcra = mfspr(SPRN_MMCRA); /* Were we in the hypervisor? */ - if (firmware_has_feature(FW_FEATURE_LPAR) && (mmcra & mmcra_sihv)) + if (firmware_has_feature(FW_FEATURE_LPAR) && + (mmcra & cur_cpu_spec->oprofile_mmcra_sihv)) /* function descriptor madness */ return *((unsigned long *)hypervisor_bucket); /* We were in userspace, nothing to do */ - if (mmcra & mmcra_sipr) + if (mmcra & cur_cpu_spec->oprofile_mmcra_sipr) return pc; #ifdef CONFIG_PPC_RTAS @@ -235,15 +222,14 @@ static unsigned long get_pc(struct pt_regs *regs) return pc; } -static int get_kernel(unsigned long pc) +static int get_kernel(unsigned long pc, unsigned long mmcra) { int is_kernel; - if (!mmcra_has_sihv) { + if (!cur_cpu_spec->oprofile_mmcra_sihv) { is_kernel = is_kernel_addr(pc); } else { - unsigned long mmcra = mfspr(SPRN_MMCRA); - is_kernel = ((mmcra & mmcra_sipr) == 0); + is_kernel = ((mmcra & cur_cpu_spec->oprofile_mmcra_sipr) == 0); } return is_kernel; @@ -257,9 +243,12 @@ static void power4_handle_interrupt(struct pt_regs *regs, int val; int i; unsigned int mmcr0; + unsigned long mmcra; + + mmcra = mfspr(SPRN_MMCRA); pc = get_pc(regs); - is_kernel = get_kernel(pc); + is_kernel = get_kernel(pc, mmcra); /* set the PMM bit (see comment below) */ mtmsrd(mfmsr() | MSR_PMM); @@ -287,6 +276,10 @@ static void power4_handle_interrupt(struct pt_regs *regs, */ mmcr0 &= ~MMCR0_PMAO; + /* Clear the appropriate bits in the MMCRA */ + mmcra &= ~cur_cpu_spec->oprofile_mmcra_clear; + mtspr(SPRN_MMCRA, mmcra); + /* * now clear the freeze bit, counting will not start until we * rfid from this exception, because only at that point will |