📄 op_model_fsl_booke.c
字号:
/* * oprofile/op_model_e500.c * * Freescale Book-E oprofile support, based on ppc64 oprofile support * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM * * Copyright (c) 2004 Freescale Semiconductor, Inc * * Author: Andy Fleming * Maintainer: Kumar Gala <Kumar.Gala@freescale.com> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */#include <linux/oprofile.h>#include <linux/init.h>#include <linux/smp.h>#include <asm/ptrace.h>#include <asm/system.h>#include <asm/processor.h>#include <asm/cputable.h>#include <asm/reg_booke.h>#include <asm/page.h>#include <asm/perfmon.h>#include "op_impl.h"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){ 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; }}static inline void ctr_write(unsigned int i, unsigned int val){ switch(i) { case 0: mtpmr(PMRN_PMC0, val); break; case 1: mtpmr(PMRN_PMC1, val); break; case 2: mtpmr(PMRN_PMC2, val); break; case 3: mtpmr(PMRN_PMC3, val); break; default: break; }}static void fsl_booke_reg_setup(struct op_counter_config *ctr, struct op_system_config *sys, int num_ctrs){ int i; 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) { 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){ int i; mtmsr(mfmsr() | MSR_PMM); 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_pmc_marked(i, 1, 0); pmc_start_ctr(i, 1); } else { ctr_write(i, 0); /* Set the ctr to be stopped */ pmc_start_ctr(i, 0); } } /* Clear the freeze bit, and enable the interrupt. * The counters won't actually start until the rfi clears * the PMM bit */ pmc_start_ctrs(1); oprofile_running = 1; pr_debug("start on cpu %d, pmgc0 %x\n", smp_processor_id(), mfpmr(PMRN_PMGC0));}static void fsl_booke_stop(void){ /* freeze counters */ pmc_stop_ctrs(); oprofile_running = 0; pr_debug("stop on cpu %d, pmgc0 %x\n", smp_processor_id(), mfpmr(PMRN_PMGC0)); mb();}static void fsl_booke_handle_interrupt(struct pt_regs *regs, struct op_counter_config *ctr){ unsigned long pc; int is_kernel; int val; int i; /* set the PMM bit (see comment below) */ mtmsr(mfmsr() | MSR_PMM); pc = regs->nip; is_kernel = (pc >= KERNELBASE); 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); ctr_write(i, reset_value[i]); } else { ctr_write(i, 0); } } } /* The freeze bit was set by the interrupt. */ /* Clear the freeze bit, and reenable the interrupt. * The counters won't actually start until the rfi clears * the PMM bit */ pmc_start_ctrs(1);}struct op_ppc32_model op_model_fsl_booke = { .reg_setup = fsl_booke_reg_setup, .start = fsl_booke_start, .stop = fsl_booke_stop, .handle_interrupt = fsl_booke_handle_interrupt,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -