1/* 2 * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 */ 9 10#include <linux/oprofile.h> 11#include <linux/init.h> 12#include <linux/smp.h> 13#include <asm/ptrace.h> 14#include <asm/system.h> 15#include <asm/processor.h> 16#include <asm/cputable.h> 17#include <asm/oprofile_impl.h> 18 19#define dbg(args...) 20 21static void ctrl_write(unsigned int i, unsigned int val) 22{ 23 unsigned int tmp = 0; 24 unsigned long shift = 0, mask = 0; 25 26 dbg("ctrl_write %d %x\n", i, val); 27 28 switch(i) { 29 case 0: 30 tmp = mfspr(SPRN_MMCR0); 31 shift = 6; 32 mask = 0x7F; 33 break; 34 case 1: 35 tmp = mfspr(SPRN_MMCR0); 36 shift = 0; 37 mask = 0x3F; 38 break; 39 case 2: 40 tmp = mfspr(SPRN_MMCR1); 41 shift = 31 - 4; 42 mask = 0x1F; 43 break; 44 case 3: 45 tmp = mfspr(SPRN_MMCR1); 46 shift = 31 - 9; 47 mask = 0x1F; 48 break; 49 case 4: 50 tmp = mfspr(SPRN_MMCR1); 51 shift = 31 - 14; 52 mask = 0x1F; 53 break; 54 case 5: 55 tmp = mfspr(SPRN_MMCR1); 56 shift = 31 - 19; 57 mask = 0x1F; 58 break; 59 case 6: 60 tmp = mfspr(SPRN_MMCR1); 61 shift = 31 - 24; 62 mask = 0x1F; 63 break; 64 case 7: 65 tmp = mfspr(SPRN_MMCR1); 66 shift = 31 - 28; 67 mask = 0xF; 68 break; 69 } 70 71 tmp = tmp & ~(mask << shift); 72 tmp |= val << shift; 73 74 switch(i) { 75 case 0: 76 case 1: 77 mtspr(SPRN_MMCR0, tmp); 78 break; 79 default: 80 mtspr(SPRN_MMCR1, tmp); 81 } 82 83 dbg("ctrl_write mmcr0 %lx mmcr1 %lx\n", mfspr(SPRN_MMCR0), 84 mfspr(SPRN_MMCR1)); 85} 86 87static unsigned long reset_value[OP_MAX_COUNTER]; 88 89static int num_counters; 90 91static void rs64_reg_setup(struct op_counter_config *ctr, 92 struct op_system_config *sys, 93 int num_ctrs) 94{ 95 int i; 96 97 num_counters = num_ctrs; 98 99 for (i = 0; i < num_counters; ++i) 100 reset_value[i] = 0x80000000UL - ctr[i].count; 101 102} 103 104static void rs64_cpu_setup(struct op_counter_config *ctr) 105{ 106 unsigned int mmcr0; 107 108 /* reset MMCR0 and set the freeze bit */ 109 mmcr0 = MMCR0_FC; 110 mtspr(SPRN_MMCR0, mmcr0); 111 112 /* reset MMCR1, MMCRA */ 113 mtspr(SPRN_MMCR1, 0); 114 115 if (cpu_has_feature(CPU_FTR_MMCRA)) 116 mtspr(SPRN_MMCRA, 0); 117 118 mmcr0 |= MMCR0_FCM1|MMCR0_PMXE|MMCR0_FCECE; 119 /* Only applies to POWER3, but should be safe on RS64 */ 120 mmcr0 |= MMCR0_PMC1CE|MMCR0_PMCjCE; 121 mtspr(SPRN_MMCR0, mmcr0); 122 123 dbg("setup on cpu %d, mmcr0 %lx\n", smp_processor_id(), 124 mfspr(SPRN_MMCR0)); 125 dbg("setup on cpu %d, mmcr1 %lx\n", smp_processor_id(), 126 mfspr(SPRN_MMCR1)); 127} 128 129static void rs64_start(struct op_counter_config *ctr) 130{ 131 int i; 132 unsigned int mmcr0; 133 134 /* set the PMM bit (see comment below) */ 135 mtmsrd(mfmsr() | MSR_PMM); 136 137 for (i = 0; i < num_counters; ++i) { 138 if (ctr[i].enabled) { 139 classic_ctr_write(i, reset_value[i]); 140 ctrl_write(i, ctr[i].event); 141 } else { 142 classic_ctr_write(i, 0); 143 } 144 } 145 146 mmcr0 = mfspr(SPRN_MMCR0); 147 148 /* 149 * now clear the freeze bit, counting will not start until we 150 * rfid from this excetion, because only at that point will 151 * the PMM bit be cleared 152 */ 153 mmcr0 &= ~MMCR0_FC; 154 mtspr(SPRN_MMCR0, mmcr0); 155 156 dbg("start on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0); 157} 158 159static void rs64_stop(void) 160{ 161 unsigned int mmcr0; 162 163 /* freeze counters */ 164 mmcr0 = mfspr(SPRN_MMCR0); 165 mmcr0 |= MMCR0_FC; 166 mtspr(SPRN_MMCR0, mmcr0); 167 168 dbg("stop on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0); 169 170 mb(); 171} 172 173static void rs64_handle_interrupt(struct pt_regs *regs, 174 struct op_counter_config *ctr) 175{ 176 unsigned int mmcr0; 177 int is_kernel; 178 int val; 179 int i; 180 unsigned long pc = mfspr(SPRN_SIAR); 181 182 is_kernel = is_kernel_addr(pc); 183 184 /* set the PMM bit (see comment below) */ 185 mtmsrd(mfmsr() | MSR_PMM); 186 187 for (i = 0; i < num_counters; ++i) { 188 val = classic_ctr_read(i); 189 if (val < 0) { 190 if (ctr[i].enabled) { 191 oprofile_add_ext_sample(pc, regs, i, is_kernel); 192 classic_ctr_write(i, reset_value[i]); 193 } else { 194 classic_ctr_write(i, 0); 195 } 196 } 197 } 198 199 mmcr0 = mfspr(SPRN_MMCR0); 200 201 /* reset the perfmon trigger */ 202 mmcr0 |= MMCR0_PMXE; 203 204 /* 205 * now clear the freeze bit, counting will not start until we 206 * rfid from this exception, because only at that point will 207 * the PMM bit be cleared 208 */ 209 mmcr0 &= ~MMCR0_FC; 210 mtspr(SPRN_MMCR0, mmcr0); 211} 212 213struct op_powerpc_model op_model_rs64 = { 214 .reg_setup = rs64_reg_setup, 215 .cpu_setup = rs64_cpu_setup, 216 .start = rs64_start, 217 .stop = rs64_stop, 218 .handle_interrupt = rs64_handle_interrupt, 219}; 220