diff options
Diffstat (limited to 'arch/powerpc/oprofile/op_model_pa6t.c')
-rw-r--r-- | arch/powerpc/oprofile/op_model_pa6t.c | 227 |
1 files changed, 0 insertions, 227 deletions
diff --git a/arch/powerpc/oprofile/op_model_pa6t.c b/arch/powerpc/oprofile/op_model_pa6t.c deleted file mode 100644 index d23061cf76bc..000000000000 --- a/arch/powerpc/oprofile/op_model_pa6t.c +++ /dev/null @@ -1,227 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2006-2007 PA Semi, Inc - * - * Author: Shashi Rao, PA Semi - * - * Maintained by: Olof Johansson <olof@lixom.net> - * - * Based on arch/powerpc/oprofile/op_model_power4.c - */ - -#include <linux/oprofile.h> -#include <linux/smp.h> -#include <linux/percpu.h> -#include <asm/processor.h> -#include <asm/cputable.h> -#include <asm/oprofile_impl.h> -#include <asm/reg.h> - -static unsigned char oprofile_running; - -/* mmcr values are set in pa6t_reg_setup, used in pa6t_cpu_setup */ -static u64 mmcr0_val; -static u64 mmcr1_val; - -/* inited in pa6t_reg_setup */ -static u64 reset_value[OP_MAX_COUNTER]; - -static inline u64 ctr_read(unsigned int i) -{ - switch (i) { - case 0: - return mfspr(SPRN_PA6T_PMC0); - case 1: - return mfspr(SPRN_PA6T_PMC1); - case 2: - return mfspr(SPRN_PA6T_PMC2); - case 3: - return mfspr(SPRN_PA6T_PMC3); - case 4: - return mfspr(SPRN_PA6T_PMC4); - case 5: - return mfspr(SPRN_PA6T_PMC5); - default: - printk(KERN_ERR "ctr_read called with bad arg %u\n", i); - return 0; - } -} - -static inline void ctr_write(unsigned int i, u64 val) -{ - switch (i) { - case 0: - mtspr(SPRN_PA6T_PMC0, val); - break; - case 1: - mtspr(SPRN_PA6T_PMC1, val); - break; - case 2: - mtspr(SPRN_PA6T_PMC2, val); - break; - case 3: - mtspr(SPRN_PA6T_PMC3, val); - break; - case 4: - mtspr(SPRN_PA6T_PMC4, val); - break; - case 5: - mtspr(SPRN_PA6T_PMC5, val); - break; - default: - printk(KERN_ERR "ctr_write called with bad arg %u\n", i); - break; - } -} - - -/* precompute the values to stuff in the hardware registers */ -static int pa6t_reg_setup(struct op_counter_config *ctr, - struct op_system_config *sys, - int num_ctrs) -{ - int pmc; - - /* - * adjust the mmcr0.en[0-5] and mmcr0.inten[0-5] values obtained from the - * event_mappings file by turning off the counters that the user doesn't - * care about - * - * setup user and kernel profiling - */ - for (pmc = 0; pmc < cur_cpu_spec->num_pmcs; pmc++) - if (!ctr[pmc].enabled) { - sys->mmcr0 &= ~(0x1UL << pmc); - sys->mmcr0 &= ~(0x1UL << (pmc+12)); - pr_debug("turned off counter %u\n", pmc); - } - - if (sys->enable_kernel) - sys->mmcr0 |= PA6T_MMCR0_SUPEN | PA6T_MMCR0_HYPEN; - else - sys->mmcr0 &= ~(PA6T_MMCR0_SUPEN | PA6T_MMCR0_HYPEN); - - if (sys->enable_user) - sys->mmcr0 |= PA6T_MMCR0_PREN; - else - sys->mmcr0 &= ~PA6T_MMCR0_PREN; - - /* - * The performance counter event settings are given in the mmcr0 and - * mmcr1 values passed from the user in the op_system_config - * structure (sys variable). - */ - mmcr0_val = sys->mmcr0; - mmcr1_val = sys->mmcr1; - pr_debug("mmcr0_val inited to %016lx\n", sys->mmcr0); - pr_debug("mmcr1_val inited to %016lx\n", sys->mmcr1); - - for (pmc = 0; pmc < cur_cpu_spec->num_pmcs; pmc++) { - /* counters are 40 bit. Move to cputable at some point? */ - reset_value[pmc] = (0x1UL << 39) - ctr[pmc].count; - pr_debug("reset_value for pmc%u inited to 0x%llx\n", - pmc, reset_value[pmc]); - } - - return 0; -} - -/* configure registers on this cpu */ -static int pa6t_cpu_setup(struct op_counter_config *ctr) -{ - u64 mmcr0 = mmcr0_val; - u64 mmcr1 = mmcr1_val; - - /* Default is all PMCs off */ - mmcr0 &= ~(0x3FUL); - mtspr(SPRN_PA6T_MMCR0, mmcr0); - - /* program selected programmable events in */ - mtspr(SPRN_PA6T_MMCR1, mmcr1); - - pr_debug("setup on cpu %d, mmcr0 %016lx\n", smp_processor_id(), - mfspr(SPRN_PA6T_MMCR0)); - pr_debug("setup on cpu %d, mmcr1 %016lx\n", smp_processor_id(), - mfspr(SPRN_PA6T_MMCR1)); - - return 0; -} - -static int pa6t_start(struct op_counter_config *ctr) -{ - int i; - - /* Hold off event counting until rfid */ - u64 mmcr0 = mmcr0_val | PA6T_MMCR0_HANDDIS; - - for (i = 0; i < cur_cpu_spec->num_pmcs; i++) - if (ctr[i].enabled) - ctr_write(i, reset_value[i]); - else - ctr_write(i, 0UL); - - mtspr(SPRN_PA6T_MMCR0, mmcr0); - - oprofile_running = 1; - - pr_debug("start on cpu %d, mmcr0 %llx\n", smp_processor_id(), mmcr0); - - return 0; -} - -static void pa6t_stop(void) -{ - u64 mmcr0; - - /* freeze counters */ - mmcr0 = mfspr(SPRN_PA6T_MMCR0); - mmcr0 |= PA6T_MMCR0_FCM0; - mtspr(SPRN_PA6T_MMCR0, mmcr0); - - oprofile_running = 0; - - pr_debug("stop on cpu %d, mmcr0 %llx\n", smp_processor_id(), mmcr0); -} - -/* handle the perfmon overflow vector */ -static void pa6t_handle_interrupt(struct pt_regs *regs, - struct op_counter_config *ctr) -{ - unsigned long pc = mfspr(SPRN_PA6T_SIAR); - int is_kernel = is_kernel_addr(pc); - u64 val; - int i; - u64 mmcr0; - - /* disable perfmon counting until rfid */ - mmcr0 = mfspr(SPRN_PA6T_MMCR0); - mtspr(SPRN_PA6T_MMCR0, mmcr0 | PA6T_MMCR0_HANDDIS); - - /* Record samples. We've got one global bit for whether a sample - * was taken, so add it for any counter that triggered overflow. - */ - for (i = 0; i < cur_cpu_spec->num_pmcs; i++) { - val = ctr_read(i); - if (val & (0x1UL << 39)) { /* Overflow bit set */ - if (oprofile_running && ctr[i].enabled) { - if (mmcr0 & PA6T_MMCR0_SIARLOG) - oprofile_add_ext_sample(pc, regs, i, is_kernel); - ctr_write(i, reset_value[i]); - } else { - ctr_write(i, 0UL); - } - } - } - - /* Restore mmcr0 to a good known value since the PMI changes it */ - mmcr0 = mmcr0_val | PA6T_MMCR0_HANDDIS; - mtspr(SPRN_PA6T_MMCR0, mmcr0); -} - -struct op_powerpc_model op_model_pa6t = { - .reg_setup = pa6t_reg_setup, - .cpu_setup = pa6t_cpu_setup, - .start = pa6t_start, - .stop = pa6t_stop, - .handle_interrupt = pa6t_handle_interrupt, -}; |