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