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 int 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 return 0; 103} 104 105static int rs64_cpu_setup(struct op_counter_config *ctr) 106{ 107 unsigned int mmcr0; 108 109 /* reset MMCR0 and set the freeze bit */ 110 mmcr0 = MMCR0_FC; 111 mtspr(SPRN_MMCR0, mmcr0); 112 113 /* reset MMCR1, MMCRA */ 114 mtspr(SPRN_MMCR1, 0); 115 116 if (cpu_has_feature(CPU_FTR_MMCRA)) 117 mtspr(SPRN_MMCRA, 0); 118 119 mmcr0 |= MMCR0_FCM1|MMCR0_PMXE|MMCR0_FCECE; 120 /* Only applies to POWER3, but should be safe on RS64 */ 121 mmcr0 |= MMCR0_PMC1CE|MMCR0_PMCjCE; 122 mtspr(SPRN_MMCR0, mmcr0); 123 124 dbg("setup on cpu %d, mmcr0 %lx\n", smp_processor_id(), 125 mfspr(SPRN_MMCR0)); 126 dbg("setup on cpu %d, mmcr1 %lx\n", smp_processor_id(), 127 mfspr(SPRN_MMCR1)); 128 129 return 0; 130} 131 132static int rs64_start(struct op_counter_config *ctr) 133{ 134 int i; 135 unsigned int mmcr0; 136 137 /* set the PMM bit (see comment below) */ 138 mtmsrd(mfmsr() | MSR_PMM); 139 140 for (i = 0; i < num_counters; ++i) { 141 if (ctr[i].enabled) { 142 classic_ctr_write(i, reset_value[i]); 143 ctrl_write(i, ctr[i].event); 144 } else { 145 classic_ctr_write(i, 0); 146 } 147 } 148 149 mmcr0 = mfspr(SPRN_MMCR0); 150 151 /* 152 * now clear the freeze bit, counting will not start until we 153 * rfid from this excetion, because only at that point will 154 * the PMM bit be cleared 155 */ 156 mmcr0 &= ~MMCR0_FC; 157 mtspr(SPRN_MMCR0, mmcr0); 158 159 dbg("start on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0); 160 return 0; 161} 162 163static void rs64_stop(void) 164{ 165 unsigned int mmcr0; 166 167 /* freeze counters */ 168 mmcr0 = mfspr(SPRN_MMCR0); 169 mmcr0 |= MMCR0_FC; 170 mtspr(SPRN_MMCR0, mmcr0); 171 172 dbg("stop on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0); 173 174 mb(); 175} 176 177static void rs64_handle_interrupt(struct pt_regs *regs, 178 struct op_counter_config *ctr) 179{ 180 unsigned int mmcr0; 181 int is_kernel; 182 int val; 183 int i; 184 unsigned long pc = mfspr(SPRN_SIAR); 185 186 is_kernel = is_kernel_addr(pc); 187 188 /* set the PMM bit (see comment below) */ 189 mtmsrd(mfmsr() | MSR_PMM); 190 191 for (i = 0; i < num_counters; ++i) { 192 val = classic_ctr_read(i); 193 if (val < 0) { 194 if (ctr[i].enabled) { 195 oprofile_add_ext_sample(pc, regs, i, is_kernel); 196 classic_ctr_write(i, reset_value[i]); 197 } else { 198 classic_ctr_write(i, 0); 199 } 200 } 201 } 202 203 mmcr0 = mfspr(SPRN_MMCR0); 204 205 /* reset the perfmon trigger */ 206 mmcr0 |= MMCR0_PMXE; 207 208 /* 209 * now clear the freeze bit, counting will not start until we 210 * rfid from this exception, because only at that point will 211 * the PMM bit be cleared 212 */ 213 mmcr0 &= ~MMCR0_FC; 214 mtspr(SPRN_MMCR0, mmcr0); 215} 216 217struct 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}; 224