1255164Sjhibbits/*- 2255164Sjhibbits * Copyright (c) 2011 Justin Hibbits 3255164Sjhibbits * Copyright (c) 2005, Joseph Koshy 4255164Sjhibbits * All rights reserved. 5255164Sjhibbits * 6255164Sjhibbits * Redistribution and use in source and binary forms, with or without 7255164Sjhibbits * modification, are permitted provided that the following conditions 8255164Sjhibbits * are met: 9255164Sjhibbits * 1. Redistributions of source code must retain the above copyright 10255164Sjhibbits * notice, this list of conditions and the following disclaimer. 11255164Sjhibbits * 2. Redistributions in binary form must reproduce the above copyright 12255164Sjhibbits * notice, this list of conditions and the following disclaimer in the 13255164Sjhibbits * documentation and/or other materials provided with the distribution. 14255164Sjhibbits * 15255164Sjhibbits * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16255164Sjhibbits * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17255164Sjhibbits * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18255164Sjhibbits * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19255164Sjhibbits * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20255164Sjhibbits * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21255164Sjhibbits * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22255164Sjhibbits * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23255164Sjhibbits * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24255164Sjhibbits * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25255164Sjhibbits * SUCH DAMAGE. 26255164Sjhibbits * 27255164Sjhibbits */ 28255164Sjhibbits 29255164Sjhibbits#include <sys/cdefs.h> 30255164Sjhibbits__FBSDID("$FreeBSD$"); 31255164Sjhibbits 32255164Sjhibbits#include <sys/param.h> 33255164Sjhibbits#include <sys/pmc.h> 34255164Sjhibbits#include <sys/pmckern.h> 35255164Sjhibbits#include <sys/systm.h> 36255164Sjhibbits 37255164Sjhibbits#include <machine/pmc_mdep.h> 38255164Sjhibbits#include <machine/spr.h> 39255164Sjhibbits#include <machine/cpu.h> 40255164Sjhibbits 41255164Sjhibbits#include "hwpmc_powerpc.h" 42255164Sjhibbits 43255164Sjhibbits#define POWERPC_PMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_USER | \ 44255164Sjhibbits PMC_CAP_SYSTEM | PMC_CAP_EDGE | \ 45255164Sjhibbits PMC_CAP_THRESHOLD | PMC_CAP_READ | \ 46255164Sjhibbits PMC_CAP_WRITE | PMC_CAP_INVERT | \ 47255164Sjhibbits PMC_CAP_QUALIFIER) 48255164Sjhibbits 49255164Sjhibbits#define PPC_SET_PMC1SEL(r, x) ((r & ~(SPR_MMCR0_PMC1SEL(0x3f))) | SPR_MMCR0_PMC1SEL(x)) 50255164Sjhibbits#define PPC_SET_PMC2SEL(r, x) ((r & ~(SPR_MMCR0_PMC2SEL(0x3f))) | SPR_MMCR0_PMC2SEL(x)) 51255164Sjhibbits#define PPC_SET_PMC3SEL(r, x) ((r & ~(SPR_MMCR1_PMC3SEL(0x1f))) | SPR_MMCR1_PMC3SEL(x)) 52255164Sjhibbits#define PPC_SET_PMC4SEL(r, x) ((r & ~(SPR_MMCR1_PMC4SEL(0x1f))) | SPR_MMCR1_PMC4SEL(x)) 53255164Sjhibbits#define PPC_SET_PMC5SEL(r, x) ((r & ~(SPR_MMCR1_PMC5SEL(0x1f))) | SPR_MMCR1_PMC5SEL(x)) 54255164Sjhibbits#define PPC_SET_PMC6SEL(r, x) ((r & ~(SPR_MMCR1_PMC6SEL(0x3f))) | SPR_MMCR1_PMC6SEL(x)) 55255164Sjhibbits 56255164Sjhibbits/* Change this when we support more than just the 7450. */ 57255164Sjhibbits#define MPC7XXX_MAX_PMCS 6 58255164Sjhibbits 59255164Sjhibbits#define MPC7XXX_PMC_HAS_OVERFLOWED(x) (mpc7xxx_pmcn_read(x) & (0x1 << 31)) 60255164Sjhibbits 61255164Sjhibbits/* 62255164Sjhibbits * Things to improve on this: 63255164Sjhibbits * - It stops (clears to 0) the PMC and resets it at every context switch 64255164Sjhibbits * currently. 65255164Sjhibbits */ 66255164Sjhibbits 67255164Sjhibbits/* 68255164Sjhibbits * This should work for every 32-bit PowerPC implementation I know of (G3 and G4 69255164Sjhibbits * specifically). 70255164Sjhibbits */ 71255164Sjhibbits 72263122Sjhibbitsstruct mpc7xxx_event_code_map { 73255164Sjhibbits enum pmc_event pe_ev; /* enum value */ 74255164Sjhibbits uint8_t pe_counter_mask; /* Which counter this can be counted in. */ 75263122Sjhibbits uint8_t pe_code; /* numeric code */ 76255164Sjhibbits}; 77255164Sjhibbits 78255164Sjhibbits#define PPC_PMC_MASK1 0 79255164Sjhibbits#define PPC_PMC_MASK2 1 80255164Sjhibbits#define PPC_PMC_MASK3 2 81255164Sjhibbits#define PPC_PMC_MASK4 3 82255164Sjhibbits#define PPC_PMC_MASK5 4 83255164Sjhibbits#define PPC_PMC_MASK6 5 84255164Sjhibbits#define PPC_PMC_MASK_ALL 0x3f 85255164Sjhibbits#define PMC_POWERPC_EVENT(id, mask, number) \ 86255164Sjhibbits { .pe_ev = PMC_EV_PPC7450_##id, .pe_counter_mask = mask, .pe_code = number } 87255164Sjhibbits 88263122Sjhibbitsstatic struct mpc7xxx_event_code_map mpc7xxx_event_codes[] = { 89255164Sjhibbits PMC_POWERPC_EVENT(CYCLE,PPC_PMC_MASK_ALL, 1), 90255164Sjhibbits PMC_POWERPC_EVENT(INSTR_COMPLETED, 0x0f, 2), 91255164Sjhibbits PMC_POWERPC_EVENT(TLB_BIT_TRANSITIONS, 0x0f, 3), 92255164Sjhibbits PMC_POWERPC_EVENT(INSTR_DISPATCHED, 0x0f, 4), 93255164Sjhibbits PMC_POWERPC_EVENT(PMON_EXCEPT, 0x0f, 5), 94255164Sjhibbits PMC_POWERPC_EVENT(PMON_SIG, 0x0f, 7), 95255164Sjhibbits PMC_POWERPC_EVENT(VPU_INSTR_COMPLETED, 0x03, 8), 96255164Sjhibbits PMC_POWERPC_EVENT(VFPU_INSTR_COMPLETED, 0x03, 9), 97255164Sjhibbits PMC_POWERPC_EVENT(VIU1_INSTR_COMPLETED, 0x03, 10), 98255164Sjhibbits PMC_POWERPC_EVENT(VIU2_INSTR_COMPLETED, 0x03, 11), 99255164Sjhibbits PMC_POWERPC_EVENT(MTVSCR_INSTR_COMPLETED, 0x03, 12), 100255164Sjhibbits PMC_POWERPC_EVENT(MTVRSAVE_INSTR_COMPLETED, 0x03, 13), 101255164Sjhibbits PMC_POWERPC_EVENT(VPU_INSTR_WAIT_CYCLES, 0x03, 14), 102255164Sjhibbits PMC_POWERPC_EVENT(VFPU_INSTR_WAIT_CYCLES, 0x03, 15), 103255164Sjhibbits PMC_POWERPC_EVENT(VIU1_INSTR_WAIT_CYCLES, 0x03, 16), 104255164Sjhibbits PMC_POWERPC_EVENT(VIU2_INSTR_WAIT_CYCLES, 0x03, 17), 105255164Sjhibbits PMC_POWERPC_EVENT(MFVSCR_SYNC_CYCLES, 0x03, 18), 106255164Sjhibbits PMC_POWERPC_EVENT(VSCR_SAT_SET, 0x03, 19), 107255164Sjhibbits PMC_POWERPC_EVENT(STORE_INSTR_COMPLETED, 0x03, 20), 108255164Sjhibbits PMC_POWERPC_EVENT(L1_INSTR_CACHE_MISSES, 0x03, 21), 109255164Sjhibbits PMC_POWERPC_EVENT(L1_DATA_SNOOPS, 0x03, 22), 110255164Sjhibbits PMC_POWERPC_EVENT(UNRESOLVED_BRANCHES, 0x01, 23), 111255164Sjhibbits PMC_POWERPC_EVENT(SPEC_BUFFER_CYCLES, 0x01, 24), 112255164Sjhibbits PMC_POWERPC_EVENT(BRANCH_UNIT_STALL_CYCLES, 0x01, 25), 113255164Sjhibbits PMC_POWERPC_EVENT(TRUE_BRANCH_TARGET_HITS, 0x01, 26), 114255164Sjhibbits PMC_POWERPC_EVENT(BRANCH_LINK_STAC_PREDICTED, 0x01, 27), 115255164Sjhibbits PMC_POWERPC_EVENT(GPR_ISSUE_QUEUE_DISPATCHES, 0x01, 28), 116255164Sjhibbits PMC_POWERPC_EVENT(CYCLES_THREE_INSTR_DISPATCHED, 0x01, 29), 117255164Sjhibbits PMC_POWERPC_EVENT(THRESHOLD_INSTR_QUEUE_ENTRIES_CYCLES, 0x01, 30), 118255164Sjhibbits PMC_POWERPC_EVENT(THRESHOLD_VEC_INSTR_QUEUE_ENTRIES_CYCLES, 0x01, 31), 119255164Sjhibbits PMC_POWERPC_EVENT(CYCLES_NO_COMPLETED_INSTRS, 0x01, 32), 120255164Sjhibbits PMC_POWERPC_EVENT(IU2_INSTR_COMPLETED, 0x01, 33), 121255164Sjhibbits PMC_POWERPC_EVENT(BRANCHES_COMPLETED, 0x01, 34), 122255164Sjhibbits PMC_POWERPC_EVENT(EIEIO_INSTR_COMPLETED, 0x01, 35), 123255164Sjhibbits PMC_POWERPC_EVENT(MTSPR_INSTR_COMPLETED, 0x01, 36), 124255164Sjhibbits PMC_POWERPC_EVENT(SC_INSTR_COMPLETED, 0x01, 37), 125255164Sjhibbits PMC_POWERPC_EVENT(LS_LM_COMPLETED, 0x01, 38), 126255164Sjhibbits PMC_POWERPC_EVENT(ITLB_HW_TABLE_SEARCH_CYCLES, 0x01, 39), 127255164Sjhibbits PMC_POWERPC_EVENT(DTLB_HW_SEARCH_CYCLES_OVER_THRESHOLD, 0x01, 40), 128255164Sjhibbits PMC_POWERPC_EVENT(L1_INSTR_CACHE_ACCESSES, 0x01, 41), 129255164Sjhibbits PMC_POWERPC_EVENT(INSTR_BKPT_MATCHES, 0x01, 42), 130255164Sjhibbits PMC_POWERPC_EVENT(L1_DATA_CACHE_LOAD_MISS_CYCLES_OVER_THRESHOLD, 0x01, 43), 131255164Sjhibbits PMC_POWERPC_EVENT(L1_DATA_SNOOP_HIT_ON_MODIFIED, 0x01, 44), 132255164Sjhibbits PMC_POWERPC_EVENT(LOAD_MISS_ALIAS, 0x01, 45), 133255164Sjhibbits PMC_POWERPC_EVENT(LOAD_MISS_ALIAS_ON_TOUCH, 0x01, 46), 134255164Sjhibbits PMC_POWERPC_EVENT(TOUCH_ALIAS, 0x01, 47), 135255164Sjhibbits PMC_POWERPC_EVENT(L1_DATA_SNOOP_HIT_CASTOUT_QUEUE, 0x01, 48), 136255164Sjhibbits PMC_POWERPC_EVENT(L1_DATA_SNOOP_HIT_CASTOUT, 0x01, 49), 137255164Sjhibbits PMC_POWERPC_EVENT(L1_DATA_SNOOP_HITS, 0x01, 50), 138255164Sjhibbits PMC_POWERPC_EVENT(WRITE_THROUGH_STORES, 0x01, 51), 139255164Sjhibbits PMC_POWERPC_EVENT(CACHE_INHIBITED_STORES, 0x01, 52), 140255164Sjhibbits PMC_POWERPC_EVENT(L1_DATA_LOAD_HIT, 0x01, 53), 141255164Sjhibbits PMC_POWERPC_EVENT(L1_DATA_TOUCH_HIT, 0x01, 54), 142255164Sjhibbits PMC_POWERPC_EVENT(L1_DATA_STORE_HIT, 0x01, 55), 143255164Sjhibbits PMC_POWERPC_EVENT(L1_DATA_TOTAL_HITS, 0x01, 56), 144255164Sjhibbits PMC_POWERPC_EVENT(DST_INSTR_DISPATCHED, 0x01, 57), 145255164Sjhibbits PMC_POWERPC_EVENT(REFRESHED_DSTS, 0x01, 58), 146255164Sjhibbits PMC_POWERPC_EVENT(SUCCESSFUL_DST_TABLE_SEARCHES, 0x01, 59), 147255164Sjhibbits PMC_POWERPC_EVENT(DSS_INSTR_COMPLETED, 0x01, 60), 148255164Sjhibbits PMC_POWERPC_EVENT(DST_STREAM_0_CACHE_LINE_FETCHES, 0x01, 61), 149255164Sjhibbits PMC_POWERPC_EVENT(VTQ_SUSPENDS_DUE_TO_CTX_CHANGE, 0x01, 62), 150255164Sjhibbits PMC_POWERPC_EVENT(VTQ_LINE_FETCH_HIT, 0x01, 63), 151255164Sjhibbits PMC_POWERPC_EVENT(VEC_LOAD_INSTR_COMPLETED, 0x01, 64), 152255164Sjhibbits PMC_POWERPC_EVENT(FP_STORE_INSTR_COMPLETED_IN_LSU, 0x01, 65), 153255164Sjhibbits PMC_POWERPC_EVENT(FPU_RENORMALIZATION, 0x01, 66), 154255164Sjhibbits PMC_POWERPC_EVENT(FPU_DENORMALIZATION, 0x01, 67), 155255164Sjhibbits PMC_POWERPC_EVENT(FP_STORE_CAUSES_STALL_IN_LSU, 0x01, 68), 156255164Sjhibbits PMC_POWERPC_EVENT(LD_ST_TRUE_ALIAS_STALL, 0x01, 70), 157255164Sjhibbits PMC_POWERPC_EVENT(LSU_INDEXED_ALIAS_STALL, 0x01, 71), 158255164Sjhibbits PMC_POWERPC_EVENT(LSU_ALIAS_VS_FSQ_WB0_WB1, 0x01, 72), 159255164Sjhibbits PMC_POWERPC_EVENT(LSU_ALIAS_VS_CSQ, 0x01, 73), 160255164Sjhibbits PMC_POWERPC_EVENT(LSU_LOAD_HIT_LINE_ALIAS_VS_CSQ0, 0x01, 74), 161255164Sjhibbits PMC_POWERPC_EVENT(LSU_LOAD_MISS_LINE_ALIAS_VS_CSQ0, 0x01, 75), 162255164Sjhibbits PMC_POWERPC_EVENT(LSU_TOUCH_LINE_ALIAS_VS_FSQ_WB0_WB1, 0x01, 76), 163255164Sjhibbits PMC_POWERPC_EVENT(LSU_TOUCH_ALIAS_VS_CSQ, 0x01, 77), 164255164Sjhibbits PMC_POWERPC_EVENT(LSU_LMQ_FULL_STALL, 0x01, 78), 165255164Sjhibbits PMC_POWERPC_EVENT(FP_LOAD_INSTR_COMPLETED_IN_LSU, 0x01, 79), 166255164Sjhibbits PMC_POWERPC_EVENT(FP_LOAD_SINGLE_INSTR_COMPLETED_IN_LSU, 0x01, 80), 167255164Sjhibbits PMC_POWERPC_EVENT(FP_LOAD_DOUBLE_COMPLETED_IN_LSU, 0x01, 81), 168255164Sjhibbits PMC_POWERPC_EVENT(LSU_RA_LATCH_STALL, 0x01, 82), 169255164Sjhibbits PMC_POWERPC_EVENT(LSU_LOAD_VS_STORE_QUEUE_ALIAS_STALL, 0x01, 83), 170255164Sjhibbits PMC_POWERPC_EVENT(LSU_LMQ_INDEX_ALIAS, 0x01, 84), 171255164Sjhibbits PMC_POWERPC_EVENT(LSU_STORE_QUEUE_INDEX_ALIAS, 0x01, 85), 172255164Sjhibbits PMC_POWERPC_EVENT(LSU_CSQ_FORWARDING, 0x01, 86), 173255164Sjhibbits PMC_POWERPC_EVENT(LSU_MISALIGNED_LOAD_FINISH, 0x01, 87), 174255164Sjhibbits PMC_POWERPC_EVENT(LSU_MISALIGN_STORE_COMPLETED, 0x01, 88), 175255164Sjhibbits PMC_POWERPC_EVENT(LSU_MISALIGN_STALL, 0x01, 89), 176255164Sjhibbits PMC_POWERPC_EVENT(FP_ONE_QUARTER_FPSCR_RENAMES_BUSY, 0x01, 90), 177255164Sjhibbits PMC_POWERPC_EVENT(FP_ONE_HALF_FPSCR_RENAMES_BUSY, 0x01, 91), 178255164Sjhibbits PMC_POWERPC_EVENT(FP_THREE_QUARTERS_FPSCR_RENAMES_BUSY, 0x01, 92), 179255164Sjhibbits PMC_POWERPC_EVENT(FP_ALL_FPSCR_RENAMES_BUSY, 0x01, 93), 180255164Sjhibbits PMC_POWERPC_EVENT(FP_DENORMALIZED_RESULT, 0x01, 94), 181255164Sjhibbits PMC_POWERPC_EVENT(L1_DATA_TOTAL_MISSES, 0x02, 23), 182255164Sjhibbits PMC_POWERPC_EVENT(DISPATCHES_TO_FPR_ISSUE_QUEUE, 0x02, 24), 183255164Sjhibbits PMC_POWERPC_EVENT(LSU_INSTR_COMPLETED, 0x02, 25), 184255164Sjhibbits PMC_POWERPC_EVENT(LOAD_INSTR_COMPLETED, 0x02, 26), 185255164Sjhibbits PMC_POWERPC_EVENT(SS_SM_INSTR_COMPLETED, 0x02, 27), 186255164Sjhibbits PMC_POWERPC_EVENT(TLBIE_INSTR_COMPLETED, 0x02, 28), 187255164Sjhibbits PMC_POWERPC_EVENT(LWARX_INSTR_COMPLETED, 0x02, 29), 188255164Sjhibbits PMC_POWERPC_EVENT(MFSPR_INSTR_COMPLETED, 0x02, 30), 189255164Sjhibbits PMC_POWERPC_EVENT(REFETCH_SERIALIZATION, 0x02, 31), 190255164Sjhibbits PMC_POWERPC_EVENT(COMPLETION_QUEUE_ENTRIES_OVER_THRESHOLD, 0x02, 32), 191255164Sjhibbits PMC_POWERPC_EVENT(CYCLES_ONE_INSTR_DISPATCHED, 0x02, 33), 192255164Sjhibbits PMC_POWERPC_EVENT(CYCLES_TWO_INSTR_COMPLETED, 0x02, 34), 193255164Sjhibbits PMC_POWERPC_EVENT(ITLB_NON_SPECULATIVE_MISSES, 0x02, 35), 194255164Sjhibbits PMC_POWERPC_EVENT(CYCLES_WAITING_FROM_L1_INSTR_CACHE_MISS, 0x02, 36), 195255164Sjhibbits PMC_POWERPC_EVENT(L1_DATA_LOAD_ACCESS_MISS, 0x02, 37), 196255164Sjhibbits PMC_POWERPC_EVENT(L1_DATA_TOUCH_MISS, 0x02, 38), 197255164Sjhibbits PMC_POWERPC_EVENT(L1_DATA_STORE_MISS, 0x02, 39), 198255164Sjhibbits PMC_POWERPC_EVENT(L1_DATA_TOUCH_MISS_CYCLES, 0x02, 40), 199255164Sjhibbits PMC_POWERPC_EVENT(L1_DATA_CYCLES_USED, 0x02, 41), 200255164Sjhibbits PMC_POWERPC_EVENT(DST_STREAM_1_CACHE_LINE_FETCHES, 0x02, 42), 201255164Sjhibbits PMC_POWERPC_EVENT(VTQ_STREAM_CANCELED_PREMATURELY, 0x02, 43), 202255164Sjhibbits PMC_POWERPC_EVENT(VTQ_RESUMES_DUE_TO_CTX_CHANGE, 0x02, 44), 203255164Sjhibbits PMC_POWERPC_EVENT(VTQ_LINE_FETCH_MISS, 0x02, 45), 204255164Sjhibbits PMC_POWERPC_EVENT(VTQ_LINE_FETCH, 0x02, 46), 205255164Sjhibbits PMC_POWERPC_EVENT(TLBIE_SNOOPS, 0x02, 47), 206255164Sjhibbits PMC_POWERPC_EVENT(L1_INSTR_CACHE_RELOADS, 0x02, 48), 207255164Sjhibbits PMC_POWERPC_EVENT(L1_DATA_CACHE_RELOADS, 0x02, 49), 208255164Sjhibbits PMC_POWERPC_EVENT(L1_DATA_CACHE_CASTOUTS_TO_L2, 0x02, 50), 209255164Sjhibbits PMC_POWERPC_EVENT(STORE_MERGE_GATHER, 0x02, 51), 210255164Sjhibbits PMC_POWERPC_EVENT(CACHEABLE_STORE_MERGE_TO_32_BYTES, 0x02, 52), 211255164Sjhibbits PMC_POWERPC_EVENT(DATA_BKPT_MATCHES, 0x02, 53), 212255164Sjhibbits PMC_POWERPC_EVENT(FALL_THROUGH_BRANCHES_PROCESSED, 0x02, 54), 213255164Sjhibbits PMC_POWERPC_EVENT(FIRST_SPECULATIVE_BRANCH_BUFFER_RESOLVED_CORRECTLY, 0x02, 55), 214255164Sjhibbits PMC_POWERPC_EVENT(SECOND_SPECULATION_BUFFER_ACTIVE, 0x02, 56), 215255164Sjhibbits PMC_POWERPC_EVENT(BPU_STALL_ON_LR_DEPENDENCY, 0x02, 57), 216255164Sjhibbits PMC_POWERPC_EVENT(BTIC_MISS, 0x02, 58), 217255164Sjhibbits PMC_POWERPC_EVENT(BRANCH_LINK_STACK_CORRECTLY_RESOLVED, 0x02, 59), 218255164Sjhibbits PMC_POWERPC_EVENT(FPR_ISSUE_STALLED, 0x02, 60), 219255164Sjhibbits PMC_POWERPC_EVENT(SWITCHES_BETWEEN_PRIV_USER, 0x02, 61), 220255164Sjhibbits PMC_POWERPC_EVENT(LSU_COMPLETES_FP_STORE_SINGLE, 0x02, 62), 221255164Sjhibbits PMC_POWERPC_EVENT(CYCLES_TWO_INSTR_COMPLETED, 0x04, 8), 222255164Sjhibbits PMC_POWERPC_EVENT(CYCLES_ONE_INSTR_DISPATCHED, 0x04, 9), 223255164Sjhibbits PMC_POWERPC_EVENT(VR_ISSUE_QUEUE_DISPATCHES, 0x04, 10), 224255164Sjhibbits PMC_POWERPC_EVENT(VR_STALLS, 0x04, 11), 225255164Sjhibbits PMC_POWERPC_EVENT(GPR_RENAME_BUFFER_ENTRIES_OVER_THRESHOLD, 0x04, 12), 226255164Sjhibbits PMC_POWERPC_EVENT(FPR_ISSUE_QUEUE_ENTRIES, 0x04, 13), 227255164Sjhibbits PMC_POWERPC_EVENT(FPU_INSTR_COMPLETED, 0x04, 14), 228255164Sjhibbits PMC_POWERPC_EVENT(STWCX_INSTR_COMPLETED, 0x04, 15), 229255164Sjhibbits PMC_POWERPC_EVENT(LS_LM_INSTR_PIECES, 0x04, 16), 230255164Sjhibbits PMC_POWERPC_EVENT(ITLB_HW_SEARCH_CYCLES_OVER_THRESHOLD, 0x04, 17), 231255164Sjhibbits PMC_POWERPC_EVENT(DTLB_MISSES, 0x04, 18), 232255164Sjhibbits PMC_POWERPC_EVENT(CANCELLED_L1_INSTR_CACHE_MISSES, 0x04, 19), 233255164Sjhibbits PMC_POWERPC_EVENT(L1_DATA_CACHE_OP_HIT, 0x04, 20), 234255164Sjhibbits PMC_POWERPC_EVENT(L1_DATA_LOAD_MISS_CYCLES, 0x04, 21), 235255164Sjhibbits PMC_POWERPC_EVENT(L1_DATA_PUSHES, 0x04, 22), 236255164Sjhibbits PMC_POWERPC_EVENT(L1_DATA_TOTAL_MISS, 0x04, 23), 237255164Sjhibbits PMC_POWERPC_EVENT(VT2_FETCHES, 0x04, 24), 238255164Sjhibbits PMC_POWERPC_EVENT(TAKEN_BRANCHES_PROCESSED, 0x04, 25), 239255164Sjhibbits PMC_POWERPC_EVENT(BRANCH_FLUSHES, 0x04, 26), 240255164Sjhibbits PMC_POWERPC_EVENT(SECOND_SPECULATIVE_BRANCH_BUFFER_RESOLVED_CORRECTLY, 0x04, 27), 241255164Sjhibbits PMC_POWERPC_EVENT(THIRD_SPECULATION_BUFFER_ACTIVE, 0x04, 28), 242255164Sjhibbits PMC_POWERPC_EVENT(BRANCH_UNIT_STALL_ON_CTR_DEPENDENCY, 0x04, 29), 243255164Sjhibbits PMC_POWERPC_EVENT(FAST_BTIC_HIT, 0x04, 30), 244255164Sjhibbits PMC_POWERPC_EVENT(BRANCH_LINK_STACK_MISPREDICTED, 0x04, 31), 245255164Sjhibbits PMC_POWERPC_EVENT(CYCLES_THREE_INSTR_COMPLETED, 0x08, 14), 246255164Sjhibbits PMC_POWERPC_EVENT(CYCLES_NO_INSTR_DISPATCHED, 0x08, 15), 247255164Sjhibbits PMC_POWERPC_EVENT(GPR_ISSUE_QUEUE_ENTRIES_OVER_THRESHOLD, 0x08, 16), 248255164Sjhibbits PMC_POWERPC_EVENT(GPR_ISSUE_QUEUE_STALLED, 0x08, 17), 249255164Sjhibbits PMC_POWERPC_EVENT(IU1_INSTR_COMPLETED, 0x08, 18), 250255164Sjhibbits PMC_POWERPC_EVENT(DSSALL_INSTR_COMPLETED, 0x08, 19), 251255164Sjhibbits PMC_POWERPC_EVENT(TLBSYNC_INSTR_COMPLETED, 0x08, 20), 252255164Sjhibbits PMC_POWERPC_EVENT(SYNC_INSTR_COMPLETED, 0x08, 21), 253255164Sjhibbits PMC_POWERPC_EVENT(SS_SM_INSTR_PIECES, 0x08, 22), 254255164Sjhibbits PMC_POWERPC_EVENT(DTLB_HW_SEARCH_CYCLES, 0x08, 23), 255255164Sjhibbits PMC_POWERPC_EVENT(SNOOP_RETRIES, 0x08, 24), 256255164Sjhibbits PMC_POWERPC_EVENT(SUCCESSFUL_STWCX, 0x08, 25), 257255164Sjhibbits PMC_POWERPC_EVENT(DST_STREAM_3_CACHE_LINE_FETCHES, 0x08, 26), 258255164Sjhibbits PMC_POWERPC_EVENT(THIRD_SPECULATIVE_BRANCH_BUFFER_RESOLVED_CORRECTLY, 0x08, 27), 259255164Sjhibbits PMC_POWERPC_EVENT(MISPREDICTED_BRANCHES, 0x08, 28), 260255164Sjhibbits PMC_POWERPC_EVENT(FOLDED_BRANCHES, 0x08, 29), 261255164Sjhibbits PMC_POWERPC_EVENT(FP_STORE_DOUBLE_COMPLETES_IN_LSU, 0x08, 30), 262255164Sjhibbits PMC_POWERPC_EVENT(L2_CACHE_HITS, 0x30, 2), 263255164Sjhibbits PMC_POWERPC_EVENT(L3_CACHE_HITS, 0x30, 3), 264255164Sjhibbits PMC_POWERPC_EVENT(L2_INSTR_CACHE_MISSES, 0x30, 4), 265255164Sjhibbits PMC_POWERPC_EVENT(L3_INSTR_CACHE_MISSES, 0x30, 5), 266255164Sjhibbits PMC_POWERPC_EVENT(L2_DATA_CACHE_MISSES, 0x30, 6), 267255164Sjhibbits PMC_POWERPC_EVENT(L3_DATA_CACHE_MISSES, 0x30, 7), 268255164Sjhibbits PMC_POWERPC_EVENT(L2_LOAD_HITS, 0x10, 8), 269255164Sjhibbits PMC_POWERPC_EVENT(L2_STORE_HITS, 0x10, 9), 270255164Sjhibbits PMC_POWERPC_EVENT(L3_LOAD_HITS, 0x10, 10), 271255164Sjhibbits PMC_POWERPC_EVENT(L3_STORE_HITS, 0x10, 11), 272255164Sjhibbits PMC_POWERPC_EVENT(L2_TOUCH_HITS, 0x30, 13), 273255164Sjhibbits PMC_POWERPC_EVENT(L3_TOUCH_HITS, 0x30, 14), 274255164Sjhibbits PMC_POWERPC_EVENT(SNOOP_RETRIES, 0x30, 15), 275255164Sjhibbits PMC_POWERPC_EVENT(SNOOP_MODIFIED, 0x10, 16), 276255164Sjhibbits PMC_POWERPC_EVENT(SNOOP_VALID, 0x10, 17), 277255164Sjhibbits PMC_POWERPC_EVENT(INTERVENTION, 0x30, 18), 278255164Sjhibbits PMC_POWERPC_EVENT(L2_CACHE_MISSES, 0x10, 19), 279255164Sjhibbits PMC_POWERPC_EVENT(L3_CACHE_MISSES, 0x10, 20), 280255164Sjhibbits PMC_POWERPC_EVENT(L2_CACHE_CASTOUTS, 0x20, 8), 281255164Sjhibbits PMC_POWERPC_EVENT(L3_CACHE_CASTOUTS, 0x20, 9), 282255164Sjhibbits PMC_POWERPC_EVENT(L2SQ_FULL_CYCLES, 0x20, 10), 283255164Sjhibbits PMC_POWERPC_EVENT(L3SQ_FULL_CYCLES, 0x20, 11), 284255164Sjhibbits PMC_POWERPC_EVENT(RAQ_FULL_CYCLES, 0x20, 16), 285255164Sjhibbits PMC_POWERPC_EVENT(WAQ_FULL_CYCLES, 0x20, 17), 286255164Sjhibbits PMC_POWERPC_EVENT(L1_EXTERNAL_INTERVENTIONS, 0x20, 19), 287255164Sjhibbits PMC_POWERPC_EVENT(L2_EXTERNAL_INTERVENTIONS, 0x20, 20), 288255164Sjhibbits PMC_POWERPC_EVENT(L3_EXTERNAL_INTERVENTIONS, 0x20, 21), 289255164Sjhibbits PMC_POWERPC_EVENT(EXTERNAL_INTERVENTIONS, 0x20, 22), 290255164Sjhibbits PMC_POWERPC_EVENT(EXTERNAL_PUSHES, 0x20, 23), 291255164Sjhibbits PMC_POWERPC_EVENT(EXTERNAL_SNOOP_RETRY, 0x20, 24), 292255164Sjhibbits PMC_POWERPC_EVENT(DTQ_FULL_CYCLES, 0x20, 25), 293255164Sjhibbits PMC_POWERPC_EVENT(BUS_RETRY, 0x20, 26), 294255164Sjhibbits PMC_POWERPC_EVENT(L2_VALID_REQUEST, 0x20, 27), 295255164Sjhibbits PMC_POWERPC_EVENT(BORDQ_FULL, 0x20, 28), 296255164Sjhibbits PMC_POWERPC_EVENT(BUS_TAS_FOR_READS, 0x20, 42), 297255164Sjhibbits PMC_POWERPC_EVENT(BUS_TAS_FOR_WRITES, 0x20, 43), 298255164Sjhibbits PMC_POWERPC_EVENT(BUS_READS_NOT_RETRIED, 0x20, 44), 299255164Sjhibbits PMC_POWERPC_EVENT(BUS_WRITES_NOT_RETRIED, 0x20, 45), 300255164Sjhibbits PMC_POWERPC_EVENT(BUS_READS_WRITES_NOT_RETRIED, 0x20, 46), 301255164Sjhibbits PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_L1_RETRY, 0x20, 47), 302255164Sjhibbits PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_PREVIOUS_ADJACENT, 0x20, 48), 303255164Sjhibbits PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_COLLISION, 0x20, 49), 304255164Sjhibbits PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_INTERVENTION_ORDERING, 0x20, 50), 305255164Sjhibbits PMC_POWERPC_EVENT(SNOOP_REQUESTS, 0x20, 51), 306255164Sjhibbits PMC_POWERPC_EVENT(PREFETCH_ENGINE_REQUEST, 0x20, 52), 307255164Sjhibbits PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_LOAD, 0x20, 53), 308255164Sjhibbits PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_STORE, 0x20, 54), 309255164Sjhibbits PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_INSTR_FETCH, 0x20, 55), 310255164Sjhibbits PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_LOAD_STORE_INSTR_FETCH, 0x20, 56), 311255164Sjhibbits PMC_POWERPC_EVENT(PREFETCH_ENGINE_FULL, 0x20, 57) 312255164Sjhibbits}; 313255164Sjhibbits 314263122Sjhibbitsconst size_t mpc7xxx_event_codes_size = 315263122Sjhibbits sizeof(mpc7xxx_event_codes) / sizeof(mpc7xxx_event_codes[0]); 316255164Sjhibbits 317255164Sjhibbitsstatic pmc_value_t 318255164Sjhibbitsmpc7xxx_pmcn_read(unsigned int pmc) 319255164Sjhibbits{ 320255164Sjhibbits switch (pmc) { 321255164Sjhibbits case 0: 322255164Sjhibbits return mfspr(SPR_PMC1); 323255164Sjhibbits break; 324255164Sjhibbits case 1: 325255164Sjhibbits return mfspr(SPR_PMC2); 326255164Sjhibbits break; 327255164Sjhibbits case 2: 328255164Sjhibbits return mfspr(SPR_PMC3); 329255164Sjhibbits break; 330255164Sjhibbits case 3: 331255164Sjhibbits return mfspr(SPR_PMC4); 332255164Sjhibbits break; 333255164Sjhibbits case 4: 334255164Sjhibbits return mfspr(SPR_PMC5); 335255164Sjhibbits break; 336255164Sjhibbits case 5: 337255164Sjhibbits return mfspr(SPR_PMC6); 338255164Sjhibbits default: 339255164Sjhibbits panic("Invalid PMC number: %d\n", pmc); 340255164Sjhibbits } 341255164Sjhibbits} 342255164Sjhibbits 343255164Sjhibbitsstatic void 344255164Sjhibbitsmpc7xxx_pmcn_write(unsigned int pmc, uint32_t val) 345255164Sjhibbits{ 346255164Sjhibbits switch (pmc) { 347255164Sjhibbits case 0: 348255164Sjhibbits mtspr(SPR_PMC1, val); 349255164Sjhibbits break; 350255164Sjhibbits case 1: 351255164Sjhibbits mtspr(SPR_PMC2, val); 352255164Sjhibbits break; 353255164Sjhibbits case 2: 354255164Sjhibbits mtspr(SPR_PMC3, val); 355255164Sjhibbits break; 356255164Sjhibbits case 3: 357255164Sjhibbits mtspr(SPR_PMC4, val); 358255164Sjhibbits break; 359255164Sjhibbits case 4: 360255164Sjhibbits mtspr(SPR_PMC5, val); 361255164Sjhibbits break; 362255164Sjhibbits case 5: 363255164Sjhibbits mtspr(SPR_PMC6, val); 364255164Sjhibbits break; 365255164Sjhibbits default: 366255164Sjhibbits panic("Invalid PMC number: %d\n", pmc); 367255164Sjhibbits } 368255164Sjhibbits} 369255164Sjhibbits 370255164Sjhibbitsstatic int 371255164Sjhibbitsmpc7xxx_read_pmc(int cpu, int ri, pmc_value_t *v) 372255164Sjhibbits{ 373255164Sjhibbits struct pmc *pm; 374255164Sjhibbits pmc_value_t tmp; 375255164Sjhibbits 376255164Sjhibbits KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 377255164Sjhibbits ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); 378255164Sjhibbits KASSERT(ri >= 0 && ri < MPC7XXX_MAX_PMCS, 379255164Sjhibbits ("[powerpc,%d] illegal row index %d", __LINE__, ri)); 380255164Sjhibbits 381255164Sjhibbits pm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc; 382255164Sjhibbits KASSERT(pm, 383255164Sjhibbits ("[core,%d] cpu %d ri %d pmc not configured", __LINE__, cpu, 384255164Sjhibbits ri)); 385255164Sjhibbits 386255164Sjhibbits tmp = mpc7xxx_pmcn_read(ri); 387283884Sjhb PMCDBG2(MDP,REA,2,"ppc-read id=%d -> %jd", ri, tmp); 388255164Sjhibbits if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) 389255164Sjhibbits *v = POWERPC_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp); 390255164Sjhibbits else 391255164Sjhibbits *v = tmp; 392255164Sjhibbits 393255164Sjhibbits return 0; 394255164Sjhibbits} 395255164Sjhibbits 396255164Sjhibbitsstatic int 397255164Sjhibbitsmpc7xxx_write_pmc(int cpu, int ri, pmc_value_t v) 398255164Sjhibbits{ 399255164Sjhibbits struct pmc *pm; 400255164Sjhibbits 401255164Sjhibbits KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 402255164Sjhibbits ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); 403255164Sjhibbits KASSERT(ri >= 0 && ri < MPC7XXX_MAX_PMCS, 404255164Sjhibbits ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); 405255164Sjhibbits 406255164Sjhibbits pm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc; 407255164Sjhibbits 408255164Sjhibbits if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) 409255164Sjhibbits v = POWERPC_RELOAD_COUNT_TO_PERFCTR_VALUE(v); 410255164Sjhibbits 411283884Sjhb PMCDBG3(MDP,WRI,1,"powerpc-write cpu=%d ri=%d v=%jx", cpu, ri, v); 412255164Sjhibbits 413255164Sjhibbits mpc7xxx_pmcn_write(ri, v); 414255164Sjhibbits 415255164Sjhibbits return 0; 416255164Sjhibbits} 417255164Sjhibbits 418255164Sjhibbitsstatic int 419255164Sjhibbitsmpc7xxx_config_pmc(int cpu, int ri, struct pmc *pm) 420255164Sjhibbits{ 421255164Sjhibbits struct pmc_hw *phw; 422255164Sjhibbits 423283884Sjhb PMCDBG3(MDP,CFG,1, "cpu=%d ri=%d pm=%p", cpu, ri, pm); 424255164Sjhibbits 425255164Sjhibbits KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 426255164Sjhibbits ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); 427255164Sjhibbits KASSERT(ri >= 0 && ri < MPC7XXX_MAX_PMCS, 428255164Sjhibbits ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); 429255164Sjhibbits 430255164Sjhibbits phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; 431255164Sjhibbits 432255164Sjhibbits KASSERT(pm == NULL || phw->phw_pmc == NULL, 433255164Sjhibbits ("[powerpc,%d] pm=%p phw->pm=%p hwpmc not unconfigured", 434255164Sjhibbits __LINE__, pm, phw->phw_pmc)); 435255164Sjhibbits 436255164Sjhibbits phw->phw_pmc = pm; 437255164Sjhibbits 438255164Sjhibbits return 0; 439255164Sjhibbits} 440255164Sjhibbits 441255164Sjhibbitsstatic int 442255164Sjhibbitsmpc7xxx_start_pmc(int cpu, int ri) 443255164Sjhibbits{ 444255164Sjhibbits uint32_t config; 445255164Sjhibbits struct pmc *pm; 446255164Sjhibbits struct pmc_hw *phw; 447255164Sjhibbits register_t pmc_mmcr; 448255164Sjhibbits 449255164Sjhibbits phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; 450255164Sjhibbits pm = phw->phw_pmc; 451255164Sjhibbits config = pm->pm_md.pm_powerpc.pm_powerpc_evsel & ~POWERPC_PMC_ENABLE; 452255164Sjhibbits 453255164Sjhibbits /* Enable the PMC. */ 454255164Sjhibbits switch (ri) { 455255164Sjhibbits case 0: 456255164Sjhibbits pmc_mmcr = mfspr(SPR_MMCR0); 457255164Sjhibbits pmc_mmcr = PPC_SET_PMC1SEL(pmc_mmcr, config); 458255164Sjhibbits mtspr(SPR_MMCR0, pmc_mmcr); 459255164Sjhibbits break; 460255164Sjhibbits case 1: 461255164Sjhibbits pmc_mmcr = mfspr(SPR_MMCR0); 462255164Sjhibbits pmc_mmcr = PPC_SET_PMC2SEL(pmc_mmcr, config); 463255164Sjhibbits mtspr(SPR_MMCR0, pmc_mmcr); 464255164Sjhibbits break; 465255164Sjhibbits case 2: 466255164Sjhibbits pmc_mmcr = mfspr(SPR_MMCR1); 467255164Sjhibbits pmc_mmcr = PPC_SET_PMC3SEL(pmc_mmcr, config); 468255164Sjhibbits mtspr(SPR_MMCR1, pmc_mmcr); 469255164Sjhibbits break; 470255164Sjhibbits case 3: 471255164Sjhibbits pmc_mmcr = mfspr(SPR_MMCR0); 472255164Sjhibbits pmc_mmcr = PPC_SET_PMC4SEL(pmc_mmcr, config); 473255164Sjhibbits mtspr(SPR_MMCR0, pmc_mmcr); 474255164Sjhibbits break; 475255164Sjhibbits case 4: 476255164Sjhibbits pmc_mmcr = mfspr(SPR_MMCR1); 477255164Sjhibbits pmc_mmcr = PPC_SET_PMC5SEL(pmc_mmcr, config); 478255164Sjhibbits mtspr(SPR_MMCR1, pmc_mmcr); 479255164Sjhibbits break; 480255164Sjhibbits case 5: 481255164Sjhibbits pmc_mmcr = mfspr(SPR_MMCR1); 482255164Sjhibbits pmc_mmcr = PPC_SET_PMC6SEL(pmc_mmcr, config); 483255164Sjhibbits mtspr(SPR_MMCR1, pmc_mmcr); 484255164Sjhibbits break; 485255164Sjhibbits default: 486255164Sjhibbits break; 487255164Sjhibbits } 488255164Sjhibbits 489255164Sjhibbits /* The mask is inverted (enable is 1) compared to the flags in MMCR0, which 490255164Sjhibbits * are Freeze flags. 491255164Sjhibbits */ 492255164Sjhibbits config = ~pm->pm_md.pm_powerpc.pm_powerpc_evsel & POWERPC_PMC_ENABLE; 493255164Sjhibbits 494255164Sjhibbits pmc_mmcr = mfspr(SPR_MMCR0); 495255164Sjhibbits pmc_mmcr &= ~SPR_MMCR0_FC; 496255164Sjhibbits pmc_mmcr |= config; 497255164Sjhibbits mtspr(SPR_MMCR0, pmc_mmcr); 498255164Sjhibbits 499255164Sjhibbits return 0; 500255164Sjhibbits} 501255164Sjhibbits 502255164Sjhibbitsstatic int 503255164Sjhibbitsmpc7xxx_stop_pmc(int cpu, int ri) 504255164Sjhibbits{ 505255164Sjhibbits struct pmc *pm; 506255164Sjhibbits struct pmc_hw *phw; 507255164Sjhibbits register_t pmc_mmcr; 508255164Sjhibbits 509255164Sjhibbits phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; 510255164Sjhibbits pm = phw->phw_pmc; 511255164Sjhibbits 512255164Sjhibbits /* 513255164Sjhibbits * Disable the PMCs. 514255164Sjhibbits */ 515255164Sjhibbits switch (ri) { 516255164Sjhibbits case 0: 517255164Sjhibbits pmc_mmcr = mfspr(SPR_MMCR0); 518255164Sjhibbits pmc_mmcr = PPC_SET_PMC1SEL(pmc_mmcr, 0); 519255164Sjhibbits mtspr(SPR_MMCR0, pmc_mmcr); 520255164Sjhibbits break; 521255164Sjhibbits case 1: 522255164Sjhibbits pmc_mmcr = mfspr(SPR_MMCR0); 523255164Sjhibbits pmc_mmcr = PPC_SET_PMC2SEL(pmc_mmcr, 0); 524255164Sjhibbits mtspr(SPR_MMCR0, pmc_mmcr); 525255164Sjhibbits break; 526255164Sjhibbits case 2: 527255164Sjhibbits pmc_mmcr = mfspr(SPR_MMCR1); 528255164Sjhibbits pmc_mmcr = PPC_SET_PMC3SEL(pmc_mmcr, 0); 529255164Sjhibbits mtspr(SPR_MMCR1, pmc_mmcr); 530255164Sjhibbits break; 531255164Sjhibbits case 3: 532255164Sjhibbits pmc_mmcr = mfspr(SPR_MMCR0); 533255164Sjhibbits pmc_mmcr = PPC_SET_PMC4SEL(pmc_mmcr, 0); 534255164Sjhibbits mtspr(SPR_MMCR0, pmc_mmcr); 535255164Sjhibbits break; 536255164Sjhibbits case 4: 537255164Sjhibbits pmc_mmcr = mfspr(SPR_MMCR1); 538255164Sjhibbits pmc_mmcr = PPC_SET_PMC5SEL(pmc_mmcr, 0); 539255164Sjhibbits mtspr(SPR_MMCR1, pmc_mmcr); 540255164Sjhibbits break; 541255164Sjhibbits case 5: 542255164Sjhibbits pmc_mmcr = mfspr(SPR_MMCR1); 543255164Sjhibbits pmc_mmcr = PPC_SET_PMC6SEL(pmc_mmcr, 0); 544255164Sjhibbits mtspr(SPR_MMCR1, pmc_mmcr); 545255164Sjhibbits break; 546255164Sjhibbits default: 547255164Sjhibbits break; 548255164Sjhibbits } 549255164Sjhibbits return 0; 550255164Sjhibbits} 551255164Sjhibbits 552255164Sjhibbitsstatic int 553255164Sjhibbitsmpc7xxx_pcpu_init(struct pmc_mdep *md, int cpu) 554255164Sjhibbits{ 555255164Sjhibbits int first_ri, i; 556255164Sjhibbits struct pmc_cpu *pc; 557255164Sjhibbits struct powerpc_cpu *pac; 558255164Sjhibbits struct pmc_hw *phw; 559255164Sjhibbits 560255164Sjhibbits KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 561255164Sjhibbits ("[powerpc,%d] wrong cpu number %d", __LINE__, cpu)); 562283884Sjhb PMCDBG1(MDP,INI,1,"powerpc-init cpu=%d", cpu); 563255164Sjhibbits 564255164Sjhibbits powerpc_pcpu[cpu] = pac = malloc(sizeof(struct powerpc_cpu), M_PMC, 565255164Sjhibbits M_WAITOK|M_ZERO); 566255164Sjhibbits pac->pc_ppcpmcs = malloc(sizeof(struct pmc_hw) * MPC7XXX_MAX_PMCS, 567255164Sjhibbits M_PMC, M_WAITOK|M_ZERO); 568263122Sjhibbits pac->pc_class = PMC_CLASS_PPC7450; 569255164Sjhibbits pc = pmc_pcpu[cpu]; 570255164Sjhibbits first_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_PPC7450].pcd_ri; 571255164Sjhibbits KASSERT(pc != NULL, ("[powerpc,%d] NULL per-cpu pointer", __LINE__)); 572255164Sjhibbits 573255164Sjhibbits for (i = 0, phw = pac->pc_ppcpmcs; i < MPC7XXX_MAX_PMCS; i++, phw++) { 574255164Sjhibbits phw->phw_state = PMC_PHW_FLAG_IS_ENABLED | 575255164Sjhibbits PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(i); 576255164Sjhibbits phw->phw_pmc = NULL; 577255164Sjhibbits pc->pc_hwpmcs[i + first_ri] = phw; 578255164Sjhibbits } 579255164Sjhibbits 580255164Sjhibbits /* Clear the MMCRs, and set FC, to disable all PMCs. */ 581255164Sjhibbits mtspr(SPR_MMCR0, SPR_MMCR0_FC | SPR_MMCR0_PMXE | SPR_MMCR0_PMC1CE | SPR_MMCR0_PMCNCE); 582255164Sjhibbits mtspr(SPR_MMCR1, 0); 583255164Sjhibbits 584255164Sjhibbits return 0; 585255164Sjhibbits} 586255164Sjhibbits 587255164Sjhibbitsstatic int 588255164Sjhibbitsmpc7xxx_pcpu_fini(struct pmc_mdep *md, int cpu) 589255164Sjhibbits{ 590255164Sjhibbits uint32_t mmcr0 = mfspr(SPR_MMCR0); 591255164Sjhibbits 592255164Sjhibbits mmcr0 |= SPR_MMCR0_FC; 593255164Sjhibbits mtspr(SPR_MMCR0, mmcr0); 594255164Sjhibbits free(powerpc_pcpu[cpu]->pc_ppcpmcs, M_PMC); 595255164Sjhibbits free(powerpc_pcpu[cpu], M_PMC); 596255164Sjhibbits return 0; 597255164Sjhibbits} 598255164Sjhibbits 599255164Sjhibbitsstatic int 600255164Sjhibbitsmpc7xxx_allocate_pmc(int cpu, int ri, struct pmc *pm, 601255164Sjhibbits const struct pmc_op_pmcallocate *a) 602255164Sjhibbits{ 603255164Sjhibbits enum pmc_event pe; 604255164Sjhibbits uint32_t caps, config, counter; 605255164Sjhibbits int i; 606255164Sjhibbits 607255164Sjhibbits KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 608255164Sjhibbits ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); 609255164Sjhibbits KASSERT(ri >= 0 && ri < MPC7XXX_MAX_PMCS, 610255164Sjhibbits ("[powerpc,%d] illegal row index %d", __LINE__, ri)); 611255164Sjhibbits 612255164Sjhibbits caps = a->pm_caps; 613255164Sjhibbits 614255164Sjhibbits pe = a->pm_ev; 615263122Sjhibbits for (i = 0; i < mpc7xxx_event_codes_size; i++) { 616263122Sjhibbits if (mpc7xxx_event_codes[i].pe_ev == pe) { 617263122Sjhibbits config = mpc7xxx_event_codes[i].pe_code; 618263122Sjhibbits counter = mpc7xxx_event_codes[i].pe_counter_mask; 619255164Sjhibbits break; 620255164Sjhibbits } 621255164Sjhibbits } 622263122Sjhibbits if (i == mpc7xxx_event_codes_size) 623255164Sjhibbits return (EINVAL); 624255164Sjhibbits 625255164Sjhibbits if ((counter & (1 << ri)) == 0) 626255164Sjhibbits return (EINVAL); 627255164Sjhibbits 628255164Sjhibbits if (caps & PMC_CAP_SYSTEM) 629255164Sjhibbits config |= POWERPC_PMC_KERNEL_ENABLE; 630255164Sjhibbits if (caps & PMC_CAP_USER) 631255164Sjhibbits config |= POWERPC_PMC_USER_ENABLE; 632255164Sjhibbits if ((caps & (PMC_CAP_USER | PMC_CAP_SYSTEM)) == 0) 633255164Sjhibbits config |= POWERPC_PMC_ENABLE; 634255164Sjhibbits 635255164Sjhibbits pm->pm_md.pm_powerpc.pm_powerpc_evsel = config; 636255164Sjhibbits 637283884Sjhb PMCDBG2(MDP,ALL,2,"powerpc-allocate ri=%d -> config=0x%x", ri, config); 638255164Sjhibbits 639255164Sjhibbits return 0; 640255164Sjhibbits} 641255164Sjhibbits 642255164Sjhibbitsstatic int 643255164Sjhibbitsmpc7xxx_release_pmc(int cpu, int ri, struct pmc *pmc) 644255164Sjhibbits{ 645255164Sjhibbits struct pmc_hw *phw; 646255164Sjhibbits 647255164Sjhibbits KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 648255164Sjhibbits ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); 649255164Sjhibbits KASSERT(ri >= 0 && ri < MPC7XXX_MAX_PMCS, 650255164Sjhibbits ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); 651255164Sjhibbits 652255164Sjhibbits phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; 653255164Sjhibbits KASSERT(phw->phw_pmc == NULL, 654255164Sjhibbits ("[powerpc,%d] PHW pmc %p non-NULL", __LINE__, phw->phw_pmc)); 655255164Sjhibbits 656255164Sjhibbits return 0; 657255164Sjhibbits} 658255164Sjhibbits 659255164Sjhibbitsstatic int 660255164Sjhibbitsmpc7xxx_intr(int cpu, struct trapframe *tf) 661255164Sjhibbits{ 662255164Sjhibbits int i, error, retval; 663255164Sjhibbits uint32_t config; 664255164Sjhibbits struct pmc *pm; 665255164Sjhibbits struct powerpc_cpu *pac; 666255164Sjhibbits pmc_value_t v; 667255164Sjhibbits 668255164Sjhibbits KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 669255164Sjhibbits ("[powerpc,%d] out of range CPU %d", __LINE__, cpu)); 670255164Sjhibbits 671283884Sjhb PMCDBG3(MDP,INT,1, "cpu=%d tf=%p um=%d", cpu, (void *) tf, 672255164Sjhibbits TRAPF_USERMODE(tf)); 673255164Sjhibbits 674255164Sjhibbits retval = 0; 675255164Sjhibbits 676255164Sjhibbits pac = powerpc_pcpu[cpu]; 677255164Sjhibbits 678255164Sjhibbits config = mfspr(SPR_MMCR0); 679255164Sjhibbits mtspr(SPR_MMCR0, config | SPR_MMCR0_FC); 680255164Sjhibbits 681255164Sjhibbits /* 682255164Sjhibbits * look for all PMCs that have interrupted: 683255164Sjhibbits * - look for a running, sampling PMC which has overflowed 684255164Sjhibbits * and which has a valid 'struct pmc' association 685255164Sjhibbits * 686255164Sjhibbits * If found, we call a helper to process the interrupt. 687255164Sjhibbits */ 688255164Sjhibbits 689255164Sjhibbits for (i = 0; i < MPC7XXX_MAX_PMCS; i++) { 690255164Sjhibbits if ((pm = pac->pc_ppcpmcs[i].phw_pmc) == NULL || 691255164Sjhibbits !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) { 692255164Sjhibbits continue; 693255164Sjhibbits } 694255164Sjhibbits 695255164Sjhibbits if (!MPC7XXX_PMC_HAS_OVERFLOWED(i)) 696255164Sjhibbits continue; 697255164Sjhibbits 698255164Sjhibbits retval = 1; /* Found an interrupting PMC. */ 699255164Sjhibbits 700255164Sjhibbits if (pm->pm_state != PMC_STATE_RUNNING) 701255164Sjhibbits continue; 702255164Sjhibbits 703255164Sjhibbits /* Stop the PMC, reload count. */ 704255164Sjhibbits v = pm->pm_sc.pm_reloadcount; 705255164Sjhibbits mpc7xxx_pmcn_write(i, v); 706255164Sjhibbits 707255164Sjhibbits /* Restart the counter if logging succeeded. */ 708255164Sjhibbits error = pmc_process_interrupt(cpu, PMC_HR, pm, tf, 709255164Sjhibbits TRAPF_USERMODE(tf)); 710255164Sjhibbits if (error != 0) 711255164Sjhibbits mpc7xxx_stop_pmc(cpu, i); 712255164Sjhibbits atomic_add_int(retval ? &pmc_stats.pm_intr_processed : 713255164Sjhibbits &pmc_stats.pm_intr_ignored, 1); 714255164Sjhibbits 715255164Sjhibbits } 716255164Sjhibbits 717255164Sjhibbits /* Re-enable PERF exceptions. */ 718255164Sjhibbits mtspr(SPR_MMCR0, config | SPR_MMCR0_PMXE); 719255164Sjhibbits 720255164Sjhibbits return (retval); 721255164Sjhibbits} 722255164Sjhibbits 723255164Sjhibbitsint 724255164Sjhibbitspmc_mpc7xxx_initialize(struct pmc_mdep *pmc_mdep) 725255164Sjhibbits{ 726255164Sjhibbits struct pmc_classdep *pcd; 727255164Sjhibbits 728263122Sjhibbits pmc_mdep->pmd_cputype = PMC_CPU_PPC_7450; 729263122Sjhibbits 730255164Sjhibbits pcd = &pmc_mdep->pmd_classdep[PMC_MDEP_CLASS_INDEX_PPC7450]; 731255164Sjhibbits pcd->pcd_caps = POWERPC_PMC_CAPS; 732255164Sjhibbits pcd->pcd_class = PMC_CLASS_PPC7450; 733255164Sjhibbits pcd->pcd_num = MPC7XXX_MAX_PMCS; 734255164Sjhibbits pcd->pcd_ri = pmc_mdep->pmd_npmc; 735255164Sjhibbits pcd->pcd_width = 32; /* All PMCs, even in ppc970, are 32-bit */ 736255164Sjhibbits 737255164Sjhibbits pcd->pcd_allocate_pmc = mpc7xxx_allocate_pmc; 738255164Sjhibbits pcd->pcd_config_pmc = mpc7xxx_config_pmc; 739255164Sjhibbits pcd->pcd_pcpu_fini = mpc7xxx_pcpu_fini; 740255164Sjhibbits pcd->pcd_pcpu_init = mpc7xxx_pcpu_init; 741263122Sjhibbits pcd->pcd_describe = powerpc_describe; 742263122Sjhibbits pcd->pcd_get_config = powerpc_get_config; 743255164Sjhibbits pcd->pcd_read_pmc = mpc7xxx_read_pmc; 744255164Sjhibbits pcd->pcd_release_pmc = mpc7xxx_release_pmc; 745255164Sjhibbits pcd->pcd_start_pmc = mpc7xxx_start_pmc; 746255164Sjhibbits pcd->pcd_stop_pmc = mpc7xxx_stop_pmc; 747255164Sjhibbits pcd->pcd_write_pmc = mpc7xxx_write_pmc; 748255164Sjhibbits 749255164Sjhibbits pmc_mdep->pmd_npmc += MPC7XXX_MAX_PMCS; 750263122Sjhibbits pmc_mdep->pmd_intr = mpc7xxx_intr; 751255164Sjhibbits 752263122Sjhibbits return (0); 753255164Sjhibbits} 754