X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fpowerpc%2Foprofile%2Fop_model_fsl_booke.c;fp=arch%2Fpowerpc%2Foprofile%2Fop_model_fsl_booke.c;h=0b3c31f5209ef4377e6be0bd48030d321734c07e;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=26539cda602360ed1438b212ff6893e3a33d2818;hpb=76828883507a47dae78837ab5dec5a5b4513c667;p=linux-2.6.git diff --git a/arch/powerpc/oprofile/op_model_fsl_booke.c b/arch/powerpc/oprofile/op_model_fsl_booke.c index 26539cda6..0b3c31f52 100644 --- a/arch/powerpc/oprofile/op_model_fsl_booke.c +++ b/arch/powerpc/oprofile/op_model_fsl_booke.c @@ -1,5 +1,5 @@ /* - * oprofile/op_model_e500.c + * arch/powerpc/oprofile/op_model_fsl_booke.c * * Freescale Book-E oprofile support, based on ppc64 oprofile support * Copyright (C) 2004 Anton Blanchard , IBM @@ -32,42 +32,152 @@ static unsigned long reset_value[OP_MAX_COUNTER]; static int num_counters; static int oprofile_running; -static inline unsigned int ctr_read(unsigned int i) +static void init_pmc_stop(int ctr) { - switch(i) { - case 0: - return mfpmr(PMRN_PMC0); - case 1: - return mfpmr(PMRN_PMC1); - case 2: - return mfpmr(PMRN_PMC2); - case 3: - return mfpmr(PMRN_PMC3); - default: - return 0; - } -} + u32 pmlca = (PMLCA_FC | PMLCA_FCS | PMLCA_FCU | + PMLCA_FCM1 | PMLCA_FCM0); + u32 pmlcb = 0; -static inline void ctr_write(unsigned int i, unsigned int val) -{ - switch(i) { + switch (ctr) { case 0: - mtpmr(PMRN_PMC0, val); + mtpmr(PMRN_PMLCA0, pmlca); + mtpmr(PMRN_PMLCB0, pmlcb); break; case 1: - mtpmr(PMRN_PMC1, val); + mtpmr(PMRN_PMLCA1, pmlca); + mtpmr(PMRN_PMLCB1, pmlcb); break; case 2: - mtpmr(PMRN_PMC2, val); + mtpmr(PMRN_PMLCA2, pmlca); + mtpmr(PMRN_PMLCB2, pmlcb); break; case 3: - mtpmr(PMRN_PMC3, val); + mtpmr(PMRN_PMLCA3, pmlca); + mtpmr(PMRN_PMLCB3, pmlcb); break; default: - break; + panic("Bad ctr number!\n"); } } +static void set_pmc_event(int ctr, int event) +{ + u32 pmlca; + + pmlca = get_pmlca(ctr); + + pmlca = (pmlca & ~PMLCA_EVENT_MASK) | + ((event << PMLCA_EVENT_SHIFT) & + PMLCA_EVENT_MASK); + + set_pmlca(ctr, pmlca); +} + +static void set_pmc_user_kernel(int ctr, int user, int kernel) +{ + u32 pmlca; + + pmlca = get_pmlca(ctr); + + if(user) + pmlca &= ~PMLCA_FCU; + else + pmlca |= PMLCA_FCU; + + if(kernel) + pmlca &= ~PMLCA_FCS; + else + pmlca |= PMLCA_FCS; + + set_pmlca(ctr, pmlca); +} + +static void set_pmc_marked(int ctr, int mark0, int mark1) +{ + u32 pmlca = get_pmlca(ctr); + + if(mark0) + pmlca &= ~PMLCA_FCM0; + else + pmlca |= PMLCA_FCM0; + + if(mark1) + pmlca &= ~PMLCA_FCM1; + else + pmlca |= PMLCA_FCM1; + + set_pmlca(ctr, pmlca); +} + +static void pmc_start_ctr(int ctr, int enable) +{ + u32 pmlca = get_pmlca(ctr); + + pmlca &= ~PMLCA_FC; + + if (enable) + pmlca |= PMLCA_CE; + else + pmlca &= ~PMLCA_CE; + + set_pmlca(ctr, pmlca); +} + +static void pmc_start_ctrs(int enable) +{ + u32 pmgc0 = mfpmr(PMRN_PMGC0); + + pmgc0 &= ~PMGC0_FAC; + pmgc0 |= PMGC0_FCECE; + + if (enable) + pmgc0 |= PMGC0_PMIE; + else + pmgc0 &= ~PMGC0_PMIE; + + mtpmr(PMRN_PMGC0, pmgc0); +} + +static void pmc_stop_ctrs(void) +{ + u32 pmgc0 = mfpmr(PMRN_PMGC0); + + pmgc0 |= PMGC0_FAC; + + pmgc0 &= ~(PMGC0_PMIE | PMGC0_FCECE); + + mtpmr(PMRN_PMGC0, pmgc0); +} + +static void dump_pmcs(void) +{ + printk("pmgc0: %x\n", mfpmr(PMRN_PMGC0)); + printk("pmc\t\tpmlca\t\tpmlcb\n"); + printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC0), + mfpmr(PMRN_PMLCA0), mfpmr(PMRN_PMLCB0)); + printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC1), + mfpmr(PMRN_PMLCA1), mfpmr(PMRN_PMLCB1)); + printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC2), + mfpmr(PMRN_PMLCA2), mfpmr(PMRN_PMLCB2)); + printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC3), + mfpmr(PMRN_PMLCA3), mfpmr(PMRN_PMLCB3)); +} + +static void fsl_booke_cpu_setup(struct op_counter_config *ctr) +{ + int i; + + /* freeze all counters */ + pmc_stop_ctrs(); + + for (i = 0;i < num_counters;i++) { + init_pmc_stop(i); + + set_pmc_event(i, ctr[i].event); + + set_pmc_user_kernel(i, ctr[i].user, ctr[i].kernel); + } +} static void fsl_booke_reg_setup(struct op_counter_config *ctr, struct op_system_config *sys, @@ -77,23 +187,14 @@ static void fsl_booke_reg_setup(struct op_counter_config *ctr, num_counters = num_ctrs; - /* freeze all counters */ - pmc_stop_ctrs(); - /* Our counters count up, and "count" refers to * how much before the next interrupt, and we interrupt * on overflow. So we calculate the starting value * which will give us "count" until overflow. * Then we set the events on the enabled counters */ - for (i = 0; i < num_counters; ++i) { + for (i = 0; i < num_counters; ++i) reset_value[i] = 0x80000000UL - ctr[i].count; - init_pmc_stop(i); - - set_pmc_event(i, ctr[i].event); - - set_pmc_user_kernel(i, ctr[i].user, ctr[i].kernel); - } } static void fsl_booke_start(struct op_counter_config *ctr) @@ -105,8 +206,8 @@ static void fsl_booke_start(struct op_counter_config *ctr) for (i = 0; i < num_counters; ++i) { if (ctr[i].enabled) { ctr_write(i, reset_value[i]); - /* Set Each enabled counterd to only - * count when the Mark bit is not set */ + /* Set each enabled counter to only + * count when the Mark bit is *not* set */ set_pmc_marked(i, 1, 0); pmc_start_ctr(i, 1); } else { @@ -154,13 +255,13 @@ static void fsl_booke_handle_interrupt(struct pt_regs *regs, mtmsr(mfmsr() | MSR_PMM); pc = regs->nip; - is_kernel = (pc >= KERNELBASE); + is_kernel = is_kernel_addr(pc); for (i = 0; i < num_counters; ++i) { val = ctr_read(i); if (val < 0) { if (oprofile_running && ctr[i].enabled) { - oprofile_add_pc(pc, is_kernel, i); + oprofile_add_ext_sample(pc, regs, i, is_kernel); ctr_write(i, reset_value[i]); } else { ctr_write(i, 0); @@ -177,6 +278,7 @@ static void fsl_booke_handle_interrupt(struct pt_regs *regs, struct op_powerpc_model op_model_fsl_booke = { .reg_setup = fsl_booke_reg_setup, + .cpu_setup = fsl_booke_cpu_setup, .start = fsl_booke_start, .stop = fsl_booke_stop, .handle_interrupt = fsl_booke_handle_interrupt,