Path: blob/master/arch/powerpc/oprofile/op_model_rs64.c
10817 views
/*1* Copyright (C) 2004 Anton Blanchard <[email protected]>, IBM2*3* This program is free software; you can redistribute it and/or4* modify it under the terms of the GNU General Public License5* as published by the Free Software Foundation; either version6* 2 of the License, or (at your option) any later version.7*/89#include <linux/oprofile.h>10#include <linux/init.h>11#include <linux/smp.h>12#include <asm/ptrace.h>13#include <asm/system.h>14#include <asm/processor.h>15#include <asm/cputable.h>16#include <asm/oprofile_impl.h>1718#define dbg(args...)1920static void ctrl_write(unsigned int i, unsigned int val)21{22unsigned int tmp = 0;23unsigned long shift = 0, mask = 0;2425dbg("ctrl_write %d %x\n", i, val);2627switch(i) {28case 0:29tmp = mfspr(SPRN_MMCR0);30shift = 6;31mask = 0x7F;32break;33case 1:34tmp = mfspr(SPRN_MMCR0);35shift = 0;36mask = 0x3F;37break;38case 2:39tmp = mfspr(SPRN_MMCR1);40shift = 31 - 4;41mask = 0x1F;42break;43case 3:44tmp = mfspr(SPRN_MMCR1);45shift = 31 - 9;46mask = 0x1F;47break;48case 4:49tmp = mfspr(SPRN_MMCR1);50shift = 31 - 14;51mask = 0x1F;52break;53case 5:54tmp = mfspr(SPRN_MMCR1);55shift = 31 - 19;56mask = 0x1F;57break;58case 6:59tmp = mfspr(SPRN_MMCR1);60shift = 31 - 24;61mask = 0x1F;62break;63case 7:64tmp = mfspr(SPRN_MMCR1);65shift = 31 - 28;66mask = 0xF;67break;68}6970tmp = tmp & ~(mask << shift);71tmp |= val << shift;7273switch(i) {74case 0:75case 1:76mtspr(SPRN_MMCR0, tmp);77break;78default:79mtspr(SPRN_MMCR1, tmp);80}8182dbg("ctrl_write mmcr0 %lx mmcr1 %lx\n", mfspr(SPRN_MMCR0),83mfspr(SPRN_MMCR1));84}8586static unsigned long reset_value[OP_MAX_COUNTER];8788static int num_counters;8990static int rs64_reg_setup(struct op_counter_config *ctr,91struct op_system_config *sys,92int num_ctrs)93{94int i;9596num_counters = num_ctrs;9798for (i = 0; i < num_counters; ++i)99reset_value[i] = 0x80000000UL - ctr[i].count;100101/* XXX setup user and kernel profiling */102return 0;103}104105static int rs64_cpu_setup(struct op_counter_config *ctr)106{107unsigned int mmcr0;108109/* reset MMCR0 and set the freeze bit */110mmcr0 = MMCR0_FC;111mtspr(SPRN_MMCR0, mmcr0);112113/* reset MMCR1, MMCRA */114mtspr(SPRN_MMCR1, 0);115116if (cpu_has_feature(CPU_FTR_MMCRA))117mtspr(SPRN_MMCRA, 0);118119mmcr0 |= MMCR0_FCM1|MMCR0_PMXE|MMCR0_FCECE;120/* Only applies to POWER3, but should be safe on RS64 */121mmcr0 |= MMCR0_PMC1CE|MMCR0_PMCjCE;122mtspr(SPRN_MMCR0, mmcr0);123124dbg("setup on cpu %d, mmcr0 %lx\n", smp_processor_id(),125mfspr(SPRN_MMCR0));126dbg("setup on cpu %d, mmcr1 %lx\n", smp_processor_id(),127mfspr(SPRN_MMCR1));128129return 0;130}131132static int rs64_start(struct op_counter_config *ctr)133{134int i;135unsigned int mmcr0;136137/* set the PMM bit (see comment below) */138mtmsrd(mfmsr() | MSR_PMM);139140for (i = 0; i < num_counters; ++i) {141if (ctr[i].enabled) {142classic_ctr_write(i, reset_value[i]);143ctrl_write(i, ctr[i].event);144} else {145classic_ctr_write(i, 0);146}147}148149mmcr0 = mfspr(SPRN_MMCR0);150151/*152* now clear the freeze bit, counting will not start until we153* rfid from this excetion, because only at that point will154* the PMM bit be cleared155*/156mmcr0 &= ~MMCR0_FC;157mtspr(SPRN_MMCR0, mmcr0);158159dbg("start on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0);160return 0;161}162163static void rs64_stop(void)164{165unsigned int mmcr0;166167/* freeze counters */168mmcr0 = mfspr(SPRN_MMCR0);169mmcr0 |= MMCR0_FC;170mtspr(SPRN_MMCR0, mmcr0);171172dbg("stop on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0);173174mb();175}176177static void rs64_handle_interrupt(struct pt_regs *regs,178struct op_counter_config *ctr)179{180unsigned int mmcr0;181int is_kernel;182int val;183int i;184unsigned long pc = mfspr(SPRN_SIAR);185186is_kernel = is_kernel_addr(pc);187188/* set the PMM bit (see comment below) */189mtmsrd(mfmsr() | MSR_PMM);190191for (i = 0; i < num_counters; ++i) {192val = classic_ctr_read(i);193if (val < 0) {194if (ctr[i].enabled) {195oprofile_add_ext_sample(pc, regs, i, is_kernel);196classic_ctr_write(i, reset_value[i]);197} else {198classic_ctr_write(i, 0);199}200}201}202203mmcr0 = mfspr(SPRN_MMCR0);204205/* reset the perfmon trigger */206mmcr0 |= MMCR0_PMXE;207208/*209* now clear the freeze bit, counting will not start until we210* rfid from this exception, because only at that point will211* the PMM bit be cleared212*/213mmcr0 &= ~MMCR0_FC;214mtspr(SPRN_MMCR0, mmcr0);215}216217struct op_powerpc_model op_model_rs64 = {218.reg_setup = rs64_reg_setup,219.cpu_setup = rs64_cpu_setup,220.start = rs64_start,221.stop = rs64_stop,222.handle_interrupt = rs64_handle_interrupt,223};224225226