1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2011 Justin Hibbits 5 * Copyright (c) 2005, Joseph Koshy 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 */ 30 31 #include <sys/cdefs.h> 32 __FBSDID("$FreeBSD$"); 33 34 #include <sys/param.h> 35 #include <sys/pmc.h> 36 #include <sys/pmckern.h> 37 #include <sys/systm.h> 38 39 #include <machine/pmc_mdep.h> 40 #include <machine/spr.h> 41 #include <machine/cpu.h> 42 43 #include "hwpmc_powerpc.h" 44 45 #define POWERPC_PMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_USER | \ 46 PMC_CAP_SYSTEM | PMC_CAP_EDGE | \ 47 PMC_CAP_THRESHOLD | PMC_CAP_READ | \ 48 PMC_CAP_WRITE | PMC_CAP_INVERT | \ 49 PMC_CAP_QUALIFIER) 50 51 #define PPC_SET_PMC1SEL(r, x) ((r & ~(SPR_MMCR0_PMC1SEL(0x3f))) | SPR_MMCR0_PMC1SEL(x)) 52 #define PPC_SET_PMC2SEL(r, x) ((r & ~(SPR_MMCR0_PMC2SEL(0x3f))) | SPR_MMCR0_PMC2SEL(x)) 53 #define PPC_SET_PMC3SEL(r, x) ((r & ~(SPR_MMCR1_PMC3SEL(0x1f))) | SPR_MMCR1_PMC3SEL(x)) 54 #define PPC_SET_PMC4SEL(r, x) ((r & ~(SPR_MMCR1_PMC4SEL(0x1f))) | SPR_MMCR1_PMC4SEL(x)) 55 #define PPC_SET_PMC5SEL(r, x) ((r & ~(SPR_MMCR1_PMC5SEL(0x1f))) | SPR_MMCR1_PMC5SEL(x)) 56 #define PPC_SET_PMC6SEL(r, x) ((r & ~(SPR_MMCR1_PMC6SEL(0x3f))) | SPR_MMCR1_PMC6SEL(x)) 57 58 /* Change this when we support more than just the 7450. */ 59 #define MPC7XXX_MAX_PMCS 6 60 61 #define MPC7XXX_PMC_HAS_OVERFLOWED(x) (mpc7xxx_pmcn_read(x) & (0x1 << 31)) 62 63 /* 64 * Things to improve on this: 65 * - It stops (clears to 0) the PMC and resets it at every context switch 66 * currently. 67 */ 68 69 /* 70 * This should work for every 32-bit PowerPC implementation I know of (G3 and G4 71 * specifically). 72 */ 73 74 struct mpc7xxx_event_code_map { 75 enum pmc_event pe_ev; /* enum value */ 76 uint8_t pe_counter_mask; /* Which counter this can be counted in. */ 77 uint8_t pe_code; /* numeric code */ 78 }; 79 80 #define PPC_PMC_MASK1 0 81 #define PPC_PMC_MASK2 1 82 #define PPC_PMC_MASK3 2 83 #define PPC_PMC_MASK4 3 84 #define PPC_PMC_MASK5 4 85 #define PPC_PMC_MASK6 5 86 #define PPC_PMC_MASK_ALL 0x3f 87 #define PMC_POWERPC_EVENT(id, mask, number) \ 88 { .pe_ev = PMC_EV_PPC7450_##id, .pe_counter_mask = mask, .pe_code = number } 89 90 static struct mpc7xxx_event_code_map mpc7xxx_event_codes[] = { 91 PMC_POWERPC_EVENT(CYCLE,PPC_PMC_MASK_ALL, 1), 92 PMC_POWERPC_EVENT(INSTR_COMPLETED, 0x0f, 2), 93 PMC_POWERPC_EVENT(TLB_BIT_TRANSITIONS, 0x0f, 3), 94 PMC_POWERPC_EVENT(INSTR_DISPATCHED, 0x0f, 4), 95 PMC_POWERPC_EVENT(PMON_EXCEPT, 0x0f, 5), 96 PMC_POWERPC_EVENT(PMON_SIG, 0x0f, 7), 97 PMC_POWERPC_EVENT(VPU_INSTR_COMPLETED, 0x03, 8), 98 PMC_POWERPC_EVENT(VFPU_INSTR_COMPLETED, 0x03, 9), 99 PMC_POWERPC_EVENT(VIU1_INSTR_COMPLETED, 0x03, 10), 100 PMC_POWERPC_EVENT(VIU2_INSTR_COMPLETED, 0x03, 11), 101 PMC_POWERPC_EVENT(MTVSCR_INSTR_COMPLETED, 0x03, 12), 102 PMC_POWERPC_EVENT(MTVRSAVE_INSTR_COMPLETED, 0x03, 13), 103 PMC_POWERPC_EVENT(VPU_INSTR_WAIT_CYCLES, 0x03, 14), 104 PMC_POWERPC_EVENT(VFPU_INSTR_WAIT_CYCLES, 0x03, 15), 105 PMC_POWERPC_EVENT(VIU1_INSTR_WAIT_CYCLES, 0x03, 16), 106 PMC_POWERPC_EVENT(VIU2_INSTR_WAIT_CYCLES, 0x03, 17), 107 PMC_POWERPC_EVENT(MFVSCR_SYNC_CYCLES, 0x03, 18), 108 PMC_POWERPC_EVENT(VSCR_SAT_SET, 0x03, 19), 109 PMC_POWERPC_EVENT(STORE_INSTR_COMPLETED, 0x03, 20), 110 PMC_POWERPC_EVENT(L1_INSTR_CACHE_MISSES, 0x03, 21), 111 PMC_POWERPC_EVENT(L1_DATA_SNOOPS, 0x03, 22), 112 PMC_POWERPC_EVENT(UNRESOLVED_BRANCHES, 0x01, 23), 113 PMC_POWERPC_EVENT(SPEC_BUFFER_CYCLES, 0x01, 24), 114 PMC_POWERPC_EVENT(BRANCH_UNIT_STALL_CYCLES, 0x01, 25), 115 PMC_POWERPC_EVENT(TRUE_BRANCH_TARGET_HITS, 0x01, 26), 116 PMC_POWERPC_EVENT(BRANCH_LINK_STAC_PREDICTED, 0x01, 27), 117 PMC_POWERPC_EVENT(GPR_ISSUE_QUEUE_DISPATCHES, 0x01, 28), 118 PMC_POWERPC_EVENT(CYCLES_THREE_INSTR_DISPATCHED, 0x01, 29), 119 PMC_POWERPC_EVENT(THRESHOLD_INSTR_QUEUE_ENTRIES_CYCLES, 0x01, 30), 120 PMC_POWERPC_EVENT(THRESHOLD_VEC_INSTR_QUEUE_ENTRIES_CYCLES, 0x01, 31), 121 PMC_POWERPC_EVENT(CYCLES_NO_COMPLETED_INSTRS, 0x01, 32), 122 PMC_POWERPC_EVENT(IU2_INSTR_COMPLETED, 0x01, 33), 123 PMC_POWERPC_EVENT(BRANCHES_COMPLETED, 0x01, 34), 124 PMC_POWERPC_EVENT(EIEIO_INSTR_COMPLETED, 0x01, 35), 125 PMC_POWERPC_EVENT(MTSPR_INSTR_COMPLETED, 0x01, 36), 126 PMC_POWERPC_EVENT(SC_INSTR_COMPLETED, 0x01, 37), 127 PMC_POWERPC_EVENT(LS_LM_COMPLETED, 0x01, 38), 128 PMC_POWERPC_EVENT(ITLB_HW_TABLE_SEARCH_CYCLES, 0x01, 39), 129 PMC_POWERPC_EVENT(DTLB_HW_SEARCH_CYCLES_OVER_THRESHOLD, 0x01, 40), 130 PMC_POWERPC_EVENT(L1_INSTR_CACHE_ACCESSES, 0x01, 41), 131 PMC_POWERPC_EVENT(INSTR_BKPT_MATCHES, 0x01, 42), 132 PMC_POWERPC_EVENT(L1_DATA_CACHE_LOAD_MISS_CYCLES_OVER_THRESHOLD, 0x01, 43), 133 PMC_POWERPC_EVENT(L1_DATA_SNOOP_HIT_ON_MODIFIED, 0x01, 44), 134 PMC_POWERPC_EVENT(LOAD_MISS_ALIAS, 0x01, 45), 135 PMC_POWERPC_EVENT(LOAD_MISS_ALIAS_ON_TOUCH, 0x01, 46), 136 PMC_POWERPC_EVENT(TOUCH_ALIAS, 0x01, 47), 137 PMC_POWERPC_EVENT(L1_DATA_SNOOP_HIT_CASTOUT_QUEUE, 0x01, 48), 138 PMC_POWERPC_EVENT(L1_DATA_SNOOP_HIT_CASTOUT, 0x01, 49), 139 PMC_POWERPC_EVENT(L1_DATA_SNOOP_HITS, 0x01, 50), 140 PMC_POWERPC_EVENT(WRITE_THROUGH_STORES, 0x01, 51), 141 PMC_POWERPC_EVENT(CACHE_INHIBITED_STORES, 0x01, 52), 142 PMC_POWERPC_EVENT(L1_DATA_LOAD_HIT, 0x01, 53), 143 PMC_POWERPC_EVENT(L1_DATA_TOUCH_HIT, 0x01, 54), 144 PMC_POWERPC_EVENT(L1_DATA_STORE_HIT, 0x01, 55), 145 PMC_POWERPC_EVENT(L1_DATA_TOTAL_HITS, 0x01, 56), 146 PMC_POWERPC_EVENT(DST_INSTR_DISPATCHED, 0x01, 57), 147 PMC_POWERPC_EVENT(REFRESHED_DSTS, 0x01, 58), 148 PMC_POWERPC_EVENT(SUCCESSFUL_DST_TABLE_SEARCHES, 0x01, 59), 149 PMC_POWERPC_EVENT(DSS_INSTR_COMPLETED, 0x01, 60), 150 PMC_POWERPC_EVENT(DST_STREAM_0_CACHE_LINE_FETCHES, 0x01, 61), 151 PMC_POWERPC_EVENT(VTQ_SUSPENDS_DUE_TO_CTX_CHANGE, 0x01, 62), 152 PMC_POWERPC_EVENT(VTQ_LINE_FETCH_HIT, 0x01, 63), 153 PMC_POWERPC_EVENT(VEC_LOAD_INSTR_COMPLETED, 0x01, 64), 154 PMC_POWERPC_EVENT(FP_STORE_INSTR_COMPLETED_IN_LSU, 0x01, 65), 155 PMC_POWERPC_EVENT(FPU_RENORMALIZATION, 0x01, 66), 156 PMC_POWERPC_EVENT(FPU_DENORMALIZATION, 0x01, 67), 157 PMC_POWERPC_EVENT(FP_STORE_CAUSES_STALL_IN_LSU, 0x01, 68), 158 PMC_POWERPC_EVENT(LD_ST_TRUE_ALIAS_STALL, 0x01, 70), 159 PMC_POWERPC_EVENT(LSU_INDEXED_ALIAS_STALL, 0x01, 71), 160 PMC_POWERPC_EVENT(LSU_ALIAS_VS_FSQ_WB0_WB1, 0x01, 72), 161 PMC_POWERPC_EVENT(LSU_ALIAS_VS_CSQ, 0x01, 73), 162 PMC_POWERPC_EVENT(LSU_LOAD_HIT_LINE_ALIAS_VS_CSQ0, 0x01, 74), 163 PMC_POWERPC_EVENT(LSU_LOAD_MISS_LINE_ALIAS_VS_CSQ0, 0x01, 75), 164 PMC_POWERPC_EVENT(LSU_TOUCH_LINE_ALIAS_VS_FSQ_WB0_WB1, 0x01, 76), 165 PMC_POWERPC_EVENT(LSU_TOUCH_ALIAS_VS_CSQ, 0x01, 77), 166 PMC_POWERPC_EVENT(LSU_LMQ_FULL_STALL, 0x01, 78), 167 PMC_POWERPC_EVENT(FP_LOAD_INSTR_COMPLETED_IN_LSU, 0x01, 79), 168 PMC_POWERPC_EVENT(FP_LOAD_SINGLE_INSTR_COMPLETED_IN_LSU, 0x01, 80), 169 PMC_POWERPC_EVENT(FP_LOAD_DOUBLE_COMPLETED_IN_LSU, 0x01, 81), 170 PMC_POWERPC_EVENT(LSU_RA_LATCH_STALL, 0x01, 82), 171 PMC_POWERPC_EVENT(LSU_LOAD_VS_STORE_QUEUE_ALIAS_STALL, 0x01, 83), 172 PMC_POWERPC_EVENT(LSU_LMQ_INDEX_ALIAS, 0x01, 84), 173 PMC_POWERPC_EVENT(LSU_STORE_QUEUE_INDEX_ALIAS, 0x01, 85), 174 PMC_POWERPC_EVENT(LSU_CSQ_FORWARDING, 0x01, 86), 175 PMC_POWERPC_EVENT(LSU_MISALIGNED_LOAD_FINISH, 0x01, 87), 176 PMC_POWERPC_EVENT(LSU_MISALIGN_STORE_COMPLETED, 0x01, 88), 177 PMC_POWERPC_EVENT(LSU_MISALIGN_STALL, 0x01, 89), 178 PMC_POWERPC_EVENT(FP_ONE_QUARTER_FPSCR_RENAMES_BUSY, 0x01, 90), 179 PMC_POWERPC_EVENT(FP_ONE_HALF_FPSCR_RENAMES_BUSY, 0x01, 91), 180 PMC_POWERPC_EVENT(FP_THREE_QUARTERS_FPSCR_RENAMES_BUSY, 0x01, 92), 181 PMC_POWERPC_EVENT(FP_ALL_FPSCR_RENAMES_BUSY, 0x01, 93), 182 PMC_POWERPC_EVENT(FP_DENORMALIZED_RESULT, 0x01, 94), 183 PMC_POWERPC_EVENT(L1_DATA_TOTAL_MISSES, 0x02, 23), 184 PMC_POWERPC_EVENT(DISPATCHES_TO_FPR_ISSUE_QUEUE, 0x02, 24), 185 PMC_POWERPC_EVENT(LSU_INSTR_COMPLETED, 0x02, 25), 186 PMC_POWERPC_EVENT(LOAD_INSTR_COMPLETED, 0x02, 26), 187 PMC_POWERPC_EVENT(SS_SM_INSTR_COMPLETED, 0x02, 27), 188 PMC_POWERPC_EVENT(TLBIE_INSTR_COMPLETED, 0x02, 28), 189 PMC_POWERPC_EVENT(LWARX_INSTR_COMPLETED, 0x02, 29), 190 PMC_POWERPC_EVENT(MFSPR_INSTR_COMPLETED, 0x02, 30), 191 PMC_POWERPC_EVENT(REFETCH_SERIALIZATION, 0x02, 31), 192 PMC_POWERPC_EVENT(COMPLETION_QUEUE_ENTRIES_OVER_THRESHOLD, 0x02, 32), 193 PMC_POWERPC_EVENT(CYCLES_ONE_INSTR_DISPATCHED, 0x02, 33), 194 PMC_POWERPC_EVENT(CYCLES_TWO_INSTR_COMPLETED, 0x02, 34), 195 PMC_POWERPC_EVENT(ITLB_NON_SPECULATIVE_MISSES, 0x02, 35), 196 PMC_POWERPC_EVENT(CYCLES_WAITING_FROM_L1_INSTR_CACHE_MISS, 0x02, 36), 197 PMC_POWERPC_EVENT(L1_DATA_LOAD_ACCESS_MISS, 0x02, 37), 198 PMC_POWERPC_EVENT(L1_DATA_TOUCH_MISS, 0x02, 38), 199 PMC_POWERPC_EVENT(L1_DATA_STORE_MISS, 0x02, 39), 200 PMC_POWERPC_EVENT(L1_DATA_TOUCH_MISS_CYCLES, 0x02, 40), 201 PMC_POWERPC_EVENT(L1_DATA_CYCLES_USED, 0x02, 41), 202 PMC_POWERPC_EVENT(DST_STREAM_1_CACHE_LINE_FETCHES, 0x02, 42), 203 PMC_POWERPC_EVENT(VTQ_STREAM_CANCELED_PREMATURELY, 0x02, 43), 204 PMC_POWERPC_EVENT(VTQ_RESUMES_DUE_TO_CTX_CHANGE, 0x02, 44), 205 PMC_POWERPC_EVENT(VTQ_LINE_FETCH_MISS, 0x02, 45), 206 PMC_POWERPC_EVENT(VTQ_LINE_FETCH, 0x02, 46), 207 PMC_POWERPC_EVENT(TLBIE_SNOOPS, 0x02, 47), 208 PMC_POWERPC_EVENT(L1_INSTR_CACHE_RELOADS, 0x02, 48), 209 PMC_POWERPC_EVENT(L1_DATA_CACHE_RELOADS, 0x02, 49), 210 PMC_POWERPC_EVENT(L1_DATA_CACHE_CASTOUTS_TO_L2, 0x02, 50), 211 PMC_POWERPC_EVENT(STORE_MERGE_GATHER, 0x02, 51), 212 PMC_POWERPC_EVENT(CACHEABLE_STORE_MERGE_TO_32_BYTES, 0x02, 52), 213 PMC_POWERPC_EVENT(DATA_BKPT_MATCHES, 0x02, 53), 214 PMC_POWERPC_EVENT(FALL_THROUGH_BRANCHES_PROCESSED, 0x02, 54), 215 PMC_POWERPC_EVENT(FIRST_SPECULATIVE_BRANCH_BUFFER_RESOLVED_CORRECTLY, 0x02, 55), 216 PMC_POWERPC_EVENT(SECOND_SPECULATION_BUFFER_ACTIVE, 0x02, 56), 217 PMC_POWERPC_EVENT(BPU_STALL_ON_LR_DEPENDENCY, 0x02, 57), 218 PMC_POWERPC_EVENT(BTIC_MISS, 0x02, 58), 219 PMC_POWERPC_EVENT(BRANCH_LINK_STACK_CORRECTLY_RESOLVED, 0x02, 59), 220 PMC_POWERPC_EVENT(FPR_ISSUE_STALLED, 0x02, 60), 221 PMC_POWERPC_EVENT(SWITCHES_BETWEEN_PRIV_USER, 0x02, 61), 222 PMC_POWERPC_EVENT(LSU_COMPLETES_FP_STORE_SINGLE, 0x02, 62), 223 PMC_POWERPC_EVENT(CYCLES_TWO_INSTR_COMPLETED, 0x04, 8), 224 PMC_POWERPC_EVENT(CYCLES_ONE_INSTR_DISPATCHED, 0x04, 9), 225 PMC_POWERPC_EVENT(VR_ISSUE_QUEUE_DISPATCHES, 0x04, 10), 226 PMC_POWERPC_EVENT(VR_STALLS, 0x04, 11), 227 PMC_POWERPC_EVENT(GPR_RENAME_BUFFER_ENTRIES_OVER_THRESHOLD, 0x04, 12), 228 PMC_POWERPC_EVENT(FPR_ISSUE_QUEUE_ENTRIES, 0x04, 13), 229 PMC_POWERPC_EVENT(FPU_INSTR_COMPLETED, 0x04, 14), 230 PMC_POWERPC_EVENT(STWCX_INSTR_COMPLETED, 0x04, 15), 231 PMC_POWERPC_EVENT(LS_LM_INSTR_PIECES, 0x04, 16), 232 PMC_POWERPC_EVENT(ITLB_HW_SEARCH_CYCLES_OVER_THRESHOLD, 0x04, 17), 233 PMC_POWERPC_EVENT(DTLB_MISSES, 0x04, 18), 234 PMC_POWERPC_EVENT(CANCELLED_L1_INSTR_CACHE_MISSES, 0x04, 19), 235 PMC_POWERPC_EVENT(L1_DATA_CACHE_OP_HIT, 0x04, 20), 236 PMC_POWERPC_EVENT(L1_DATA_LOAD_MISS_CYCLES, 0x04, 21), 237 PMC_POWERPC_EVENT(L1_DATA_PUSHES, 0x04, 22), 238 PMC_POWERPC_EVENT(L1_DATA_TOTAL_MISS, 0x04, 23), 239 PMC_POWERPC_EVENT(VT2_FETCHES, 0x04, 24), 240 PMC_POWERPC_EVENT(TAKEN_BRANCHES_PROCESSED, 0x04, 25), 241 PMC_POWERPC_EVENT(BRANCH_FLUSHES, 0x04, 26), 242 PMC_POWERPC_EVENT(SECOND_SPECULATIVE_BRANCH_BUFFER_RESOLVED_CORRECTLY, 0x04, 27), 243 PMC_POWERPC_EVENT(THIRD_SPECULATION_BUFFER_ACTIVE, 0x04, 28), 244 PMC_POWERPC_EVENT(BRANCH_UNIT_STALL_ON_CTR_DEPENDENCY, 0x04, 29), 245 PMC_POWERPC_EVENT(FAST_BTIC_HIT, 0x04, 30), 246 PMC_POWERPC_EVENT(BRANCH_LINK_STACK_MISPREDICTED, 0x04, 31), 247 PMC_POWERPC_EVENT(CYCLES_THREE_INSTR_COMPLETED, 0x08, 14), 248 PMC_POWERPC_EVENT(CYCLES_NO_INSTR_DISPATCHED, 0x08, 15), 249 PMC_POWERPC_EVENT(GPR_ISSUE_QUEUE_ENTRIES_OVER_THRESHOLD, 0x08, 16), 250 PMC_POWERPC_EVENT(GPR_ISSUE_QUEUE_STALLED, 0x08, 17), 251 PMC_POWERPC_EVENT(IU1_INSTR_COMPLETED, 0x08, 18), 252 PMC_POWERPC_EVENT(DSSALL_INSTR_COMPLETED, 0x08, 19), 253 PMC_POWERPC_EVENT(TLBSYNC_INSTR_COMPLETED, 0x08, 20), 254 PMC_POWERPC_EVENT(SYNC_INSTR_COMPLETED, 0x08, 21), 255 PMC_POWERPC_EVENT(SS_SM_INSTR_PIECES, 0x08, 22), 256 PMC_POWERPC_EVENT(DTLB_HW_SEARCH_CYCLES, 0x08, 23), 257 PMC_POWERPC_EVENT(SNOOP_RETRIES, 0x08, 24), 258 PMC_POWERPC_EVENT(SUCCESSFUL_STWCX, 0x08, 25), 259 PMC_POWERPC_EVENT(DST_STREAM_3_CACHE_LINE_FETCHES, 0x08, 26), 260 PMC_POWERPC_EVENT(THIRD_SPECULATIVE_BRANCH_BUFFER_RESOLVED_CORRECTLY, 0x08, 27), 261 PMC_POWERPC_EVENT(MISPREDICTED_BRANCHES, 0x08, 28), 262 PMC_POWERPC_EVENT(FOLDED_BRANCHES, 0x08, 29), 263 PMC_POWERPC_EVENT(FP_STORE_DOUBLE_COMPLETES_IN_LSU, 0x08, 30), 264 PMC_POWERPC_EVENT(L2_CACHE_HITS, 0x30, 2), 265 PMC_POWERPC_EVENT(L3_CACHE_HITS, 0x30, 3), 266 PMC_POWERPC_EVENT(L2_INSTR_CACHE_MISSES, 0x30, 4), 267 PMC_POWERPC_EVENT(L3_INSTR_CACHE_MISSES, 0x30, 5), 268 PMC_POWERPC_EVENT(L2_DATA_CACHE_MISSES, 0x30, 6), 269 PMC_POWERPC_EVENT(L3_DATA_CACHE_MISSES, 0x30, 7), 270 PMC_POWERPC_EVENT(L2_LOAD_HITS, 0x10, 8), 271 PMC_POWERPC_EVENT(L2_STORE_HITS, 0x10, 9), 272 PMC_POWERPC_EVENT(L3_LOAD_HITS, 0x10, 10), 273 PMC_POWERPC_EVENT(L3_STORE_HITS, 0x10, 11), 274 PMC_POWERPC_EVENT(L2_TOUCH_HITS, 0x30, 13), 275 PMC_POWERPC_EVENT(L3_TOUCH_HITS, 0x30, 14), 276 PMC_POWERPC_EVENT(SNOOP_RETRIES, 0x30, 15), 277 PMC_POWERPC_EVENT(SNOOP_MODIFIED, 0x10, 16), 278 PMC_POWERPC_EVENT(SNOOP_VALID, 0x10, 17), 279 PMC_POWERPC_EVENT(INTERVENTION, 0x30, 18), 280 PMC_POWERPC_EVENT(L2_CACHE_MISSES, 0x10, 19), 281 PMC_POWERPC_EVENT(L3_CACHE_MISSES, 0x10, 20), 282 PMC_POWERPC_EVENT(L2_CACHE_CASTOUTS, 0x20, 8), 283 PMC_POWERPC_EVENT(L3_CACHE_CASTOUTS, 0x20, 9), 284 PMC_POWERPC_EVENT(L2SQ_FULL_CYCLES, 0x20, 10), 285 PMC_POWERPC_EVENT(L3SQ_FULL_CYCLES, 0x20, 11), 286 PMC_POWERPC_EVENT(RAQ_FULL_CYCLES, 0x20, 16), 287 PMC_POWERPC_EVENT(WAQ_FULL_CYCLES, 0x20, 17), 288 PMC_POWERPC_EVENT(L1_EXTERNAL_INTERVENTIONS, 0x20, 19), 289 PMC_POWERPC_EVENT(L2_EXTERNAL_INTERVENTIONS, 0x20, 20), 290 PMC_POWERPC_EVENT(L3_EXTERNAL_INTERVENTIONS, 0x20, 21), 291 PMC_POWERPC_EVENT(EXTERNAL_INTERVENTIONS, 0x20, 22), 292 PMC_POWERPC_EVENT(EXTERNAL_PUSHES, 0x20, 23), 293 PMC_POWERPC_EVENT(EXTERNAL_SNOOP_RETRY, 0x20, 24), 294 PMC_POWERPC_EVENT(DTQ_FULL_CYCLES, 0x20, 25), 295 PMC_POWERPC_EVENT(BUS_RETRY, 0x20, 26), 296 PMC_POWERPC_EVENT(L2_VALID_REQUEST, 0x20, 27), 297 PMC_POWERPC_EVENT(BORDQ_FULL, 0x20, 28), 298 PMC_POWERPC_EVENT(BUS_TAS_FOR_READS, 0x20, 42), 299 PMC_POWERPC_EVENT(BUS_TAS_FOR_WRITES, 0x20, 43), 300 PMC_POWERPC_EVENT(BUS_READS_NOT_RETRIED, 0x20, 44), 301 PMC_POWERPC_EVENT(BUS_WRITES_NOT_RETRIED, 0x20, 45), 302 PMC_POWERPC_EVENT(BUS_READS_WRITES_NOT_RETRIED, 0x20, 46), 303 PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_L1_RETRY, 0x20, 47), 304 PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_PREVIOUS_ADJACENT, 0x20, 48), 305 PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_COLLISION, 0x20, 49), 306 PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_INTERVENTION_ORDERING, 0x20, 50), 307 PMC_POWERPC_EVENT(SNOOP_REQUESTS, 0x20, 51), 308 PMC_POWERPC_EVENT(PREFETCH_ENGINE_REQUEST, 0x20, 52), 309 PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_LOAD, 0x20, 53), 310 PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_STORE, 0x20, 54), 311 PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_INSTR_FETCH, 0x20, 55), 312 PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_LOAD_STORE_INSTR_FETCH, 0x20, 56), 313 PMC_POWERPC_EVENT(PREFETCH_ENGINE_FULL, 0x20, 57) 314 }; 315 316 static pmc_value_t 317 mpc7xxx_pmcn_read(unsigned int pmc) 318 { 319 switch (pmc) { 320 case 0: 321 return mfspr(SPR_PMC1); 322 break; 323 case 1: 324 return mfspr(SPR_PMC2); 325 break; 326 case 2: 327 return mfspr(SPR_PMC3); 328 break; 329 case 3: 330 return mfspr(SPR_PMC4); 331 break; 332 case 4: 333 return mfspr(SPR_PMC5); 334 break; 335 case 5: 336 return mfspr(SPR_PMC6); 337 default: 338 panic("Invalid PMC number: %d\n", pmc); 339 } 340 } 341 342 static void 343 mpc7xxx_pmcn_write(unsigned int pmc, uint32_t val) 344 { 345 switch (pmc) { 346 case 0: 347 mtspr(SPR_PMC1, val); 348 break; 349 case 1: 350 mtspr(SPR_PMC2, val); 351 break; 352 case 2: 353 mtspr(SPR_PMC3, val); 354 break; 355 case 3: 356 mtspr(SPR_PMC4, val); 357 break; 358 case 4: 359 mtspr(SPR_PMC5, val); 360 break; 361 case 5: 362 mtspr(SPR_PMC6, val); 363 break; 364 default: 365 panic("Invalid PMC number: %d\n", pmc); 366 } 367 } 368 369 static int 370 mpc7xxx_read_pmc(int cpu, int ri, pmc_value_t *v) 371 { 372 struct pmc *pm; 373 pmc_value_t tmp; 374 375 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 376 ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); 377 KASSERT(ri >= 0 && ri < MPC7XXX_MAX_PMCS, 378 ("[powerpc,%d] illegal row index %d", __LINE__, ri)); 379 380 pm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc; 381 KASSERT(pm, 382 ("[core,%d] cpu %d ri %d pmc not configured", __LINE__, cpu, 383 ri)); 384 385 tmp = mpc7xxx_pmcn_read(ri); 386 PMCDBG2(MDP,REA,2,"ppc-read id=%d -> %jd", ri, tmp); 387 if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) 388 *v = POWERPC_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp); 389 else 390 *v = tmp; 391 392 return 0; 393 } 394 395 static int 396 mpc7xxx_write_pmc(int cpu, int ri, pmc_value_t v) 397 { 398 struct pmc *pm; 399 400 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 401 ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); 402 KASSERT(ri >= 0 && ri < MPC7XXX_MAX_PMCS, 403 ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); 404 405 pm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc; 406 407 if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) 408 v = POWERPC_RELOAD_COUNT_TO_PERFCTR_VALUE(v); 409 410 PMCDBG3(MDP,WRI,1,"powerpc-write cpu=%d ri=%d v=%jx", cpu, ri, v); 411 412 mpc7xxx_pmcn_write(ri, v); 413 414 return 0; 415 } 416 417 static int 418 mpc7xxx_config_pmc(int cpu, int ri, struct pmc *pm) 419 { 420 struct pmc_hw *phw; 421 422 PMCDBG3(MDP,CFG,1, "cpu=%d ri=%d pm=%p", cpu, ri, pm); 423 424 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 425 ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); 426 KASSERT(ri >= 0 && ri < MPC7XXX_MAX_PMCS, 427 ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); 428 429 phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; 430 431 KASSERT(pm == NULL || phw->phw_pmc == NULL, 432 ("[powerpc,%d] pm=%p phw->pm=%p hwpmc not unconfigured", 433 __LINE__, pm, phw->phw_pmc)); 434 435 phw->phw_pmc = pm; 436 437 return 0; 438 } 439 440 static int 441 mpc7xxx_start_pmc(int cpu, int ri) 442 { 443 uint32_t config; 444 struct pmc *pm; 445 struct pmc_hw *phw; 446 register_t pmc_mmcr; 447 448 phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; 449 pm = phw->phw_pmc; 450 config = pm->pm_md.pm_powerpc.pm_powerpc_evsel & ~POWERPC_PMC_ENABLE; 451 452 /* Enable the PMC. */ 453 switch (ri) { 454 case 0: 455 pmc_mmcr = mfspr(SPR_MMCR0); 456 pmc_mmcr = PPC_SET_PMC1SEL(pmc_mmcr, config); 457 mtspr(SPR_MMCR0, pmc_mmcr); 458 break; 459 case 1: 460 pmc_mmcr = mfspr(SPR_MMCR0); 461 pmc_mmcr = PPC_SET_PMC2SEL(pmc_mmcr, config); 462 mtspr(SPR_MMCR0, pmc_mmcr); 463 break; 464 case 2: 465 pmc_mmcr = mfspr(SPR_MMCR1); 466 pmc_mmcr = PPC_SET_PMC3SEL(pmc_mmcr, config); 467 mtspr(SPR_MMCR1, pmc_mmcr); 468 break; 469 case 3: 470 pmc_mmcr = mfspr(SPR_MMCR0); 471 pmc_mmcr = PPC_SET_PMC4SEL(pmc_mmcr, config); 472 mtspr(SPR_MMCR0, pmc_mmcr); 473 break; 474 case 4: 475 pmc_mmcr = mfspr(SPR_MMCR1); 476 pmc_mmcr = PPC_SET_PMC5SEL(pmc_mmcr, config); 477 mtspr(SPR_MMCR1, pmc_mmcr); 478 break; 479 case 5: 480 pmc_mmcr = mfspr(SPR_MMCR1); 481 pmc_mmcr = PPC_SET_PMC6SEL(pmc_mmcr, config); 482 mtspr(SPR_MMCR1, pmc_mmcr); 483 break; 484 default: 485 break; 486 } 487 488 /* The mask is inverted (enable is 1) compared to the flags in MMCR0, which 489 * are Freeze flags. 490 */ 491 config = ~pm->pm_md.pm_powerpc.pm_powerpc_evsel & POWERPC_PMC_ENABLE; 492 493 pmc_mmcr = mfspr(SPR_MMCR0); 494 pmc_mmcr &= ~SPR_MMCR0_FC; 495 pmc_mmcr |= config; 496 mtspr(SPR_MMCR0, pmc_mmcr); 497 498 return 0; 499 } 500 501 static int 502 mpc7xxx_stop_pmc(int cpu, int ri) 503 { 504 struct pmc *pm; 505 struct pmc_hw *phw; 506 register_t pmc_mmcr; 507 508 phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; 509 pm = phw->phw_pmc; 510 511 /* 512 * Disable the PMCs. 513 */ 514 switch (ri) { 515 case 0: 516 pmc_mmcr = mfspr(SPR_MMCR0); 517 pmc_mmcr = PPC_SET_PMC1SEL(pmc_mmcr, 0); 518 mtspr(SPR_MMCR0, pmc_mmcr); 519 break; 520 case 1: 521 pmc_mmcr = mfspr(SPR_MMCR0); 522 pmc_mmcr = PPC_SET_PMC2SEL(pmc_mmcr, 0); 523 mtspr(SPR_MMCR0, pmc_mmcr); 524 break; 525 case 2: 526 pmc_mmcr = mfspr(SPR_MMCR1); 527 pmc_mmcr = PPC_SET_PMC3SEL(pmc_mmcr, 0); 528 mtspr(SPR_MMCR1, pmc_mmcr); 529 break; 530 case 3: 531 pmc_mmcr = mfspr(SPR_MMCR0); 532 pmc_mmcr = PPC_SET_PMC4SEL(pmc_mmcr, 0); 533 mtspr(SPR_MMCR0, pmc_mmcr); 534 break; 535 case 4: 536 pmc_mmcr = mfspr(SPR_MMCR1); 537 pmc_mmcr = PPC_SET_PMC5SEL(pmc_mmcr, 0); 538 mtspr(SPR_MMCR1, pmc_mmcr); 539 break; 540 case 5: 541 pmc_mmcr = mfspr(SPR_MMCR1); 542 pmc_mmcr = PPC_SET_PMC6SEL(pmc_mmcr, 0); 543 mtspr(SPR_MMCR1, pmc_mmcr); 544 break; 545 default: 546 break; 547 } 548 return 0; 549 } 550 551 static int 552 mpc7xxx_pcpu_init(struct pmc_mdep *md, int cpu) 553 { 554 int first_ri, i; 555 struct pmc_cpu *pc; 556 struct powerpc_cpu *pac; 557 struct pmc_hw *phw; 558 559 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 560 ("[powerpc,%d] wrong cpu number %d", __LINE__, cpu)); 561 PMCDBG1(MDP,INI,1,"powerpc-init cpu=%d", cpu); 562 563 powerpc_pcpu[cpu] = pac = malloc(sizeof(struct powerpc_cpu), M_PMC, 564 M_WAITOK|M_ZERO); 565 pac->pc_ppcpmcs = malloc(sizeof(struct pmc_hw) * MPC7XXX_MAX_PMCS, 566 M_PMC, M_WAITOK|M_ZERO); 567 pac->pc_class = PMC_CLASS_PPC7450; 568 pc = pmc_pcpu[cpu]; 569 first_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_POWERPC].pcd_ri; 570 KASSERT(pc != NULL, ("[powerpc,%d] NULL per-cpu pointer", __LINE__)); 571 572 for (i = 0, phw = pac->pc_ppcpmcs; i < MPC7XXX_MAX_PMCS; i++, phw++) { 573 phw->phw_state = PMC_PHW_FLAG_IS_ENABLED | 574 PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(i); 575 phw->phw_pmc = NULL; 576 pc->pc_hwpmcs[i + first_ri] = phw; 577 } 578 579 /* Clear the MMCRs, and set FC, to disable all PMCs. */ 580 mtspr(SPR_MMCR0, SPR_MMCR0_FC | SPR_MMCR0_PMXE | 581 SPR_MMCR0_FCECE | SPR_MMCR0_PMC1CE | SPR_MMCR0_PMCNCE); 582 mtspr(SPR_MMCR1, 0); 583 584 return 0; 585 } 586 587 static int 588 mpc7xxx_pcpu_fini(struct pmc_mdep *md, int cpu) 589 { 590 uint32_t mmcr0 = mfspr(SPR_MMCR0); 591 592 mtmsr(mfmsr() & ~PSL_PMM); 593 mmcr0 |= SPR_MMCR0_FC; 594 mtspr(SPR_MMCR0, mmcr0); 595 596 free(powerpc_pcpu[cpu]->pc_ppcpmcs, M_PMC); 597 free(powerpc_pcpu[cpu], M_PMC); 598 599 return 0; 600 } 601 602 static int 603 mpc7xxx_allocate_pmc(int cpu, int ri, struct pmc *pm, 604 const struct pmc_op_pmcallocate *a) 605 { 606 enum pmc_event pe; 607 uint32_t caps, config, counter; 608 int i; 609 610 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 611 ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); 612 KASSERT(ri >= 0 && ri < MPC7XXX_MAX_PMCS, 613 ("[powerpc,%d] illegal row index %d", __LINE__, ri)); 614 615 caps = a->pm_caps; 616 617 pe = a->pm_ev; 618 for (i = 0; i < nitems(mpc7xxx_event_codes); i++) { 619 if (mpc7xxx_event_codes[i].pe_ev == pe) { 620 config = mpc7xxx_event_codes[i].pe_code; 621 counter = mpc7xxx_event_codes[i].pe_counter_mask; 622 break; 623 } 624 } 625 if (i == nitems(mpc7xxx_event_codes)) 626 return (EINVAL); 627 628 if ((counter & (1 << ri)) == 0) 629 return (EINVAL); 630 631 if (caps & PMC_CAP_SYSTEM) 632 config |= POWERPC_PMC_KERNEL_ENABLE; 633 if (caps & PMC_CAP_USER) 634 config |= POWERPC_PMC_USER_ENABLE; 635 if ((caps & (PMC_CAP_USER | PMC_CAP_SYSTEM)) == 0) 636 config |= POWERPC_PMC_ENABLE; 637 638 pm->pm_md.pm_powerpc.pm_powerpc_evsel = config; 639 640 PMCDBG2(MDP,ALL,2,"powerpc-allocate ri=%d -> config=0x%x", ri, config); 641 642 return 0; 643 } 644 645 static int 646 mpc7xxx_release_pmc(int cpu, int ri, struct pmc *pmc) 647 { 648 struct pmc_hw *phw; 649 650 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 651 ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); 652 KASSERT(ri >= 0 && ri < MPC7XXX_MAX_PMCS, 653 ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); 654 655 phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; 656 KASSERT(phw->phw_pmc == NULL, 657 ("[powerpc,%d] PHW pmc %p non-NULL", __LINE__, phw->phw_pmc)); 658 659 return 0; 660 } 661 662 static int 663 mpc7xxx_intr(struct trapframe *tf) 664 { 665 int i, error, retval, cpu; 666 uint32_t config; 667 struct pmc *pm; 668 struct powerpc_cpu *pac; 669 670 cpu = curcpu; 671 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 672 ("[powerpc,%d] out of range CPU %d", __LINE__, cpu)); 673 674 PMCDBG3(MDP,INT,1, "cpu=%d tf=%p um=%d", cpu, (void *) tf, 675 TRAPF_USERMODE(tf)); 676 677 retval = 0; 678 679 pac = powerpc_pcpu[cpu]; 680 681 config = mfspr(SPR_MMCR0) & ~SPR_MMCR0_FC; 682 683 /* 684 * look for all PMCs that have interrupted: 685 * - look for a running, sampling PMC which has overflowed 686 * and which has a valid 'struct pmc' association 687 * 688 * If found, we call a helper to process the interrupt. 689 */ 690 691 for (i = 0; i < MPC7XXX_MAX_PMCS; i++) { 692 if ((pm = pac->pc_ppcpmcs[i].phw_pmc) == NULL || 693 !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) { 694 continue; 695 } 696 697 if (!MPC7XXX_PMC_HAS_OVERFLOWED(i)) 698 continue; 699 700 retval = 1; /* Found an interrupting PMC. */ 701 702 if (pm->pm_state != PMC_STATE_RUNNING) 703 continue; 704 705 /* Stop the counter if logging fails. */ 706 error = pmc_process_interrupt(PMC_HR, pm, tf); 707 if (error != 0) 708 mpc7xxx_stop_pmc(cpu, i); 709 710 /* reload count. */ 711 mpc7xxx_write_pmc(cpu, i, pm->pm_sc.pm_reloadcount); 712 } 713 if (retval) 714 counter_u64_add(pmc_stats.pm_intr_processed, 1); 715 else 716 counter_u64_add(pmc_stats.pm_intr_ignored, 1); 717 718 /* Re-enable PERF exceptions. */ 719 if (retval) 720 mtspr(SPR_MMCR0, config | SPR_MMCR0_PMXE); 721 722 return (retval); 723 } 724 725 int 726 pmc_mpc7xxx_initialize(struct pmc_mdep *pmc_mdep) 727 { 728 struct pmc_classdep *pcd; 729 730 pmc_mdep->pmd_cputype = PMC_CPU_PPC_7450; 731 732 pcd = &pmc_mdep->pmd_classdep[PMC_MDEP_CLASS_INDEX_POWERPC]; 733 pcd->pcd_caps = POWERPC_PMC_CAPS; 734 pcd->pcd_class = PMC_CLASS_PPC7450; 735 pcd->pcd_num = MPC7XXX_MAX_PMCS; 736 pcd->pcd_ri = pmc_mdep->pmd_npmc; 737 pcd->pcd_width = 32; /* All PMCs, even in ppc970, are 32-bit */ 738 739 pcd->pcd_allocate_pmc = mpc7xxx_allocate_pmc; 740 pcd->pcd_config_pmc = mpc7xxx_config_pmc; 741 pcd->pcd_pcpu_fini = mpc7xxx_pcpu_fini; 742 pcd->pcd_pcpu_init = mpc7xxx_pcpu_init; 743 pcd->pcd_describe = powerpc_describe; 744 pcd->pcd_get_config = powerpc_get_config; 745 pcd->pcd_read_pmc = mpc7xxx_read_pmc; 746 pcd->pcd_release_pmc = mpc7xxx_release_pmc; 747 pcd->pcd_start_pmc = mpc7xxx_start_pmc; 748 pcd->pcd_stop_pmc = mpc7xxx_stop_pmc; 749 pcd->pcd_write_pmc = mpc7xxx_write_pmc; 750 751 pmc_mdep->pmd_npmc += MPC7XXX_MAX_PMCS; 752 pmc_mdep->pmd_intr = mpc7xxx_intr; 753 754 return (0); 755 } 756