X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fpowerpc%2Foprofile%2Fop_model_power4.c;h=4c2beab1fdc199dd14e562cde95ea5d05a809e45;hb=9464c7cf61b9433057924c36e6e02f303a00e768;hp=506f6b79f893225df5fcc093f146d3d9656f3e7f;hpb=3944158a6d33f94668dbd6bdc32ff5c67bb53ec2;p=linux-2.6.git diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c index 506f6b79f..4c2beab1f 100644 --- a/arch/powerpc/oprofile/op_model_power4.c +++ b/arch/powerpc/oprofile/op_model_power4.c @@ -24,6 +24,10 @@ 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; @@ -36,6 +40,16 @@ 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 @@ -188,19 +202,18 @@ static unsigned long get_pc(struct pt_regs *regs) unsigned long mmcra; /* Cant do much about it */ - if (!cur_cpu_spec->oprofile_mmcra_sihv) + if (!mmcra_has_sihv) return pc; mmcra = mfspr(SPRN_MMCRA); /* Were we in the hypervisor? */ - if (firmware_has_feature(FW_FEATURE_LPAR) && - (mmcra & cur_cpu_spec->oprofile_mmcra_sihv)) + if (firmware_has_feature(FW_FEATURE_LPAR) && (mmcra & mmcra_sihv)) /* function descriptor madness */ return *((unsigned long *)hypervisor_bucket); /* We were in userspace, nothing to do */ - if (mmcra & cur_cpu_spec->oprofile_mmcra_sipr) + if (mmcra & mmcra_sipr) return pc; #ifdef CONFIG_PPC_RTAS @@ -222,14 +235,15 @@ static unsigned long get_pc(struct pt_regs *regs) return pc; } -static int get_kernel(unsigned long pc, unsigned long mmcra) +static int get_kernel(unsigned long pc) { int is_kernel; - if (!cur_cpu_spec->oprofile_mmcra_sihv) { + if (!mmcra_has_sihv) { is_kernel = is_kernel_addr(pc); } else { - is_kernel = ((mmcra & cur_cpu_spec->oprofile_mmcra_sipr) == 0); + unsigned long mmcra = mfspr(SPRN_MMCRA); + is_kernel = ((mmcra & mmcra_sipr) == 0); } return is_kernel; @@ -243,12 +257,9 @@ 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, mmcra); + is_kernel = get_kernel(pc); /* set the PMM bit (see comment below) */ mtmsrd(mfmsr() | MSR_PMM); @@ -276,10 +287,6 @@ 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