1281713Sjhibbits/*- 2281713Sjhibbits * Copyright (c) 2015 Justin Hibbits 3281713Sjhibbits * Copyright (c) 2005, Joseph Koshy 4281713Sjhibbits * All rights reserved. 5281713Sjhibbits * 6281713Sjhibbits * Redistribution and use in source and binary forms, with or without 7281713Sjhibbits * modification, are permitted provided that the following conditions 8281713Sjhibbits * are met: 9281713Sjhibbits * 1. Redistributions of source code must retain the above copyright 10281713Sjhibbits * notice, this list of conditions and the following disclaimer. 11281713Sjhibbits * 2. Redistributions in binary form must reproduce the above copyright 12281713Sjhibbits * notice, this list of conditions and the following disclaimer in the 13281713Sjhibbits * documentation and/or other materials provided with the distribution. 14281713Sjhibbits * 15281713Sjhibbits * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16281713Sjhibbits * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17281713Sjhibbits * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18281713Sjhibbits * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19281713Sjhibbits * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20281713Sjhibbits * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21281713Sjhibbits * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22281713Sjhibbits * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23281713Sjhibbits * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24281713Sjhibbits * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25281713Sjhibbits * SUCH DAMAGE. 26281713Sjhibbits * 27281713Sjhibbits */ 28281713Sjhibbits 29281713Sjhibbits#include <sys/cdefs.h> 30281713Sjhibbits__FBSDID("$FreeBSD: releng/11.0/sys/dev/hwpmc/hwpmc_e500.c 298365 2016-04-20 20:37:58Z pfg $"); 31281713Sjhibbits 32281713Sjhibbits#include <sys/param.h> 33281713Sjhibbits#include <sys/pmc.h> 34281713Sjhibbits#include <sys/pmckern.h> 35281713Sjhibbits#include <sys/systm.h> 36281713Sjhibbits 37281713Sjhibbits#include <machine/pmc_mdep.h> 38281713Sjhibbits#include <machine/cpu.h> 39281713Sjhibbits 40281713Sjhibbits#include <ddb/ddb.h> 41281713Sjhibbits 42281713Sjhibbits#include "hwpmc_powerpc.h" 43281713Sjhibbits 44281713Sjhibbits#define POWERPC_PMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_USER | \ 45281713Sjhibbits PMC_CAP_SYSTEM | PMC_CAP_EDGE | \ 46281713Sjhibbits PMC_CAP_THRESHOLD | PMC_CAP_READ | \ 47281713Sjhibbits PMC_CAP_WRITE | PMC_CAP_INVERT | \ 48281713Sjhibbits PMC_CAP_QUALIFIER) 49281713Sjhibbits 50281713Sjhibbits#define E500_PMC_HAS_OVERFLOWED(x) (e500_pmcn_read(x) & (0x1 << 31)) 51281713Sjhibbits 52281713Sjhibbitsstruct e500_event_code_map { 53281713Sjhibbits enum pmc_event pe_ev; /* enum value */ 54281713Sjhibbits uint8_t pe_counter_mask; /* Which counter this can be counted in. */ 55281713Sjhibbits uint8_t pe_code; /* numeric code */ 56281713Sjhibbits uint8_t pe_cpu; /* e500 core (v1,v2,mc), mask */ 57281713Sjhibbits}; 58281713Sjhibbits 59281713Sjhibbits#define E500_MAX_PMCS 4 60281713Sjhibbits#define PMC_PPC_MASK0 0 61281713Sjhibbits#define PMC_PPC_MASK1 1 62281713Sjhibbits#define PMC_PPC_MASK2 2 63281713Sjhibbits#define PMC_PPC_MASK3 3 64281713Sjhibbits#define PMC_PPC_MASK_ALL 0x0f 65281713Sjhibbits#define PMC_PPC_E500V1 1 66281713Sjhibbits#define PMC_PPC_E500V2 2 67281713Sjhibbits#define PMC_PPC_E500MC 4 68281713Sjhibbits#define PMC_PPC_E500_ANY 7 69281713Sjhibbits#define PMC_E500_EVENT(id, mask, number, core) \ 70281713Sjhibbits [PMC_EV_E500_##id - PMC_EV_E500_FIRST] = \ 71281713Sjhibbits { .pe_ev = PMC_EV_E500_##id, .pe_counter_mask = mask, \ 72281713Sjhibbits .pe_code = number, .pe_cpu = core } 73281713Sjhibbits#define PMC_E500MC_ONLY(id, number) \ 74281713Sjhibbits PMC_E500_EVENT(id, PMC_PPC_MASK_ALL, number, PMC_PPC_E500MC) 75281713Sjhibbits#define PMC_E500_COMMON(id, number) \ 76281713Sjhibbits PMC_E500_EVENT(id, PMC_PPC_MASK_ALL, number, PMC_PPC_E500_ANY) 77281713Sjhibbits 78281713Sjhibbitsstatic struct e500_event_code_map e500_event_codes[] = { 79281713Sjhibbits PMC_E500_COMMON(CYCLES, 1), 80281713Sjhibbits PMC_E500_COMMON(INSTR_COMPLETED, 2), 81281713Sjhibbits PMC_E500_COMMON(UOPS_COMPLETED, 3), 82281713Sjhibbits PMC_E500_COMMON(INSTR_FETCHED, 4), 83281713Sjhibbits PMC_E500_COMMON(UOPS_DECODED, 5), 84281713Sjhibbits PMC_E500_COMMON(PM_EVENT_TRANSITIONS, 6), 85281713Sjhibbits PMC_E500_COMMON(PM_EVENT_CYCLES, 7), 86281713Sjhibbits PMC_E500_COMMON(BRANCH_INSTRS_COMPLETED, 8), 87281713Sjhibbits PMC_E500_COMMON(LOAD_UOPS_COMPLETED, 9), 88281713Sjhibbits PMC_E500_COMMON(STORE_UOPS_COMPLETED, 10), 89281713Sjhibbits PMC_E500_COMMON(CQ_REDIRECTS, 11), 90281713Sjhibbits PMC_E500_COMMON(BRANCHES_FINISHED, 12), 91281713Sjhibbits PMC_E500_COMMON(TAKEN_BRANCHES_FINISHED, 13), 92281713Sjhibbits PMC_E500_COMMON(FINISHED_UNCOND_BRANCHES_MISS_BTB, 14), 93281713Sjhibbits PMC_E500_COMMON(BRANCH_MISPRED, 15), 94281713Sjhibbits PMC_E500_COMMON(BTB_BRANCH_MISPRED_FROM_DIRECTION, 16), 95281713Sjhibbits PMC_E500_COMMON(BTB_HITS_PSEUDO_HITS, 17), 96281713Sjhibbits PMC_E500_COMMON(CYCLES_DECODE_STALLED, 18), 97281713Sjhibbits PMC_E500_COMMON(CYCLES_ISSUE_STALLED, 19), 98281713Sjhibbits PMC_E500_COMMON(CYCLES_BRANCH_ISSUE_STALLED, 20), 99281713Sjhibbits PMC_E500_COMMON(CYCLES_SU1_SCHED_STALLED, 21), 100281713Sjhibbits PMC_E500_COMMON(CYCLES_SU2_SCHED_STALLED, 22), 101281713Sjhibbits PMC_E500_COMMON(CYCLES_MU_SCHED_STALLED, 23), 102281713Sjhibbits PMC_E500_COMMON(CYCLES_LRU_SCHED_STALLED, 24), 103281713Sjhibbits PMC_E500_COMMON(CYCLES_BU_SCHED_STALLED, 25), 104281713Sjhibbits PMC_E500_COMMON(TOTAL_TRANSLATED, 26), 105281713Sjhibbits PMC_E500_COMMON(LOADS_TRANSLATED, 27), 106281713Sjhibbits PMC_E500_COMMON(STORES_TRANSLATED, 28), 107281713Sjhibbits PMC_E500_COMMON(TOUCHES_TRANSLATED, 29), 108281713Sjhibbits PMC_E500_COMMON(CACHEOPS_TRANSLATED, 30), 109281713Sjhibbits PMC_E500_COMMON(CACHE_INHIBITED_ACCESS_TRANSLATED, 31), 110281713Sjhibbits PMC_E500_COMMON(GUARDED_LOADS_TRANSLATED, 32), 111281713Sjhibbits PMC_E500_COMMON(WRITE_THROUGH_STORES_TRANSLATED, 33), 112281713Sjhibbits PMC_E500_COMMON(MISALIGNED_LOAD_STORE_ACCESS_TRANSLATED, 34), 113281713Sjhibbits PMC_E500_COMMON(TOTAL_ALLOCATED_TO_DLFB, 35), 114281713Sjhibbits PMC_E500_COMMON(LOADS_TRANSLATED_ALLOCATED_TO_DLFB, 36), 115281713Sjhibbits PMC_E500_COMMON(STORES_COMPLETED_ALLOCATED_TO_DLFB, 37), 116281713Sjhibbits PMC_E500_COMMON(TOUCHES_TRANSLATED_ALLOCATED_TO_DLFB, 38), 117281713Sjhibbits PMC_E500_COMMON(STORES_COMPLETED, 39), 118281713Sjhibbits PMC_E500_COMMON(DATA_L1_CACHE_LOCKS, 40), 119281713Sjhibbits PMC_E500_COMMON(DATA_L1_CACHE_RELOADS, 41), 120281713Sjhibbits PMC_E500_COMMON(DATA_L1_CACHE_CASTOUTS, 42), 121281713Sjhibbits PMC_E500_COMMON(LOAD_MISS_DLFB_FULL, 43), 122281713Sjhibbits PMC_E500_COMMON(LOAD_MISS_LDQ_FULL, 44), 123281713Sjhibbits PMC_E500_COMMON(LOAD_GUARDED_MISS, 45), 124281713Sjhibbits PMC_E500_COMMON(STORE_TRANSLATE_WHEN_QUEUE_FULL, 46), 125281713Sjhibbits PMC_E500_COMMON(ADDRESS_COLLISION, 47), 126281713Sjhibbits PMC_E500_COMMON(DATA_MMU_MISS, 48), 127281713Sjhibbits PMC_E500_COMMON(DATA_MMU_BUSY, 49), 128281713Sjhibbits PMC_E500_COMMON(PART2_MISALIGNED_CACHE_ACCESS, 50), 129281713Sjhibbits PMC_E500_COMMON(LOAD_MISS_DLFB_FULL_CYCLES, 51), 130281713Sjhibbits PMC_E500_COMMON(LOAD_MISS_LDQ_FULL_CYCLES, 52), 131281713Sjhibbits PMC_E500_COMMON(LOAD_GUARDED_MISS_CYCLES, 53), 132281713Sjhibbits PMC_E500_COMMON(STORE_TRANSLATE_WHEN_QUEUE_FULL_CYCLES, 54), 133281713Sjhibbits PMC_E500_COMMON(ADDRESS_COLLISION_CYCLES, 55), 134281713Sjhibbits PMC_E500_COMMON(DATA_MMU_MISS_CYCLES, 56), 135281713Sjhibbits PMC_E500_COMMON(DATA_MMU_BUSY_CYCLES, 57), 136281713Sjhibbits PMC_E500_COMMON(PART2_MISALIGNED_CACHE_ACCESS_CYCLES, 58), 137281713Sjhibbits PMC_E500_COMMON(INSTR_L1_CACHE_LOCKS, 59), 138281713Sjhibbits PMC_E500_COMMON(INSTR_L1_CACHE_RELOADS, 60), 139281713Sjhibbits PMC_E500_COMMON(INSTR_L1_CACHE_FETCHES, 61), 140281713Sjhibbits PMC_E500_COMMON(INSTR_MMU_TLB4K_RELOADS, 62), 141281713Sjhibbits PMC_E500_COMMON(INSTR_MMU_VSP_RELOADS, 63), 142281713Sjhibbits PMC_E500_COMMON(DATA_MMU_TLB4K_RELOADS, 64), 143281713Sjhibbits PMC_E500_COMMON(DATA_MMU_VSP_RELOADS, 65), 144281713Sjhibbits PMC_E500_COMMON(L2MMU_MISSES, 66), 145281713Sjhibbits PMC_E500_COMMON(BIU_MASTER_REQUESTS, 67), 146281713Sjhibbits PMC_E500_COMMON(BIU_MASTER_INSTR_SIDE_REQUESTS, 68), 147281713Sjhibbits PMC_E500_COMMON(BIU_MASTER_DATA_SIDE_REQUESTS, 69), 148281713Sjhibbits PMC_E500_COMMON(BIU_MASTER_DATA_SIDE_CASTOUT_REQUESTS, 70), 149281713Sjhibbits PMC_E500_COMMON(BIU_MASTER_RETRIES, 71), 150281713Sjhibbits PMC_E500_COMMON(SNOOP_REQUESTS, 72), 151281713Sjhibbits PMC_E500_COMMON(SNOOP_HITS, 73), 152281713Sjhibbits PMC_E500_COMMON(SNOOP_PUSHES, 74), 153281713Sjhibbits PMC_E500_COMMON(SNOOP_RETRIES, 75), 154281713Sjhibbits PMC_E500_EVENT(DLFB_LOAD_MISS_CYCLES, PMC_PPC_MASK0|PMC_PPC_MASK1, 155281713Sjhibbits 76, PMC_PPC_E500_ANY), 156281713Sjhibbits PMC_E500_EVENT(ILFB_FETCH_MISS_CYCLES, PMC_PPC_MASK0|PMC_PPC_MASK1, 157281713Sjhibbits 77, PMC_PPC_E500_ANY), 158281713Sjhibbits PMC_E500_EVENT(EXT_INPU_INTR_LATENCY_CYCLES, PMC_PPC_MASK0|PMC_PPC_MASK1, 159281713Sjhibbits 78, PMC_PPC_E500_ANY), 160281713Sjhibbits PMC_E500_EVENT(CRIT_INPUT_INTR_LATENCY_CYCLES, PMC_PPC_MASK0|PMC_PPC_MASK1, 161281713Sjhibbits 79, PMC_PPC_E500_ANY), 162281713Sjhibbits PMC_E500_EVENT(EXT_INPUT_INTR_PENDING_LATENCY_CYCLES, 163281713Sjhibbits PMC_PPC_MASK0|PMC_PPC_MASK1, 80, PMC_PPC_E500_ANY), 164281713Sjhibbits PMC_E500_EVENT(CRIT_INPUT_INTR_PENDING_LATENCY_CYCLES, 165281713Sjhibbits PMC_PPC_MASK0|PMC_PPC_MASK1, 81, PMC_PPC_E500_ANY), 166281713Sjhibbits PMC_E500_COMMON(PMC0_OVERFLOW, 82), 167281713Sjhibbits PMC_E500_COMMON(PMC1_OVERFLOW, 83), 168281713Sjhibbits PMC_E500_COMMON(PMC2_OVERFLOW, 84), 169281713Sjhibbits PMC_E500_COMMON(PMC3_OVERFLOW, 85), 170281713Sjhibbits PMC_E500_COMMON(INTERRUPTS_TAKEN, 86), 171281713Sjhibbits PMC_E500_COMMON(EXT_INPUT_INTR_TAKEN, 87), 172281713Sjhibbits PMC_E500_COMMON(CRIT_INPUT_INTR_TAKEN, 88), 173281713Sjhibbits PMC_E500_COMMON(SYSCALL_TRAP_INTR, 89), 174281713Sjhibbits PMC_E500_EVENT(TLB_BIT_TRANSITIONS, PMC_PPC_MASK_ALL, 90, 175281713Sjhibbits PMC_PPC_E500V2 | PMC_PPC_E500MC), 176281713Sjhibbits PMC_E500MC_ONLY(L2_LINEFILL_BUFFER, 91), 177281713Sjhibbits PMC_E500MC_ONLY(LV2_VS, 92), 178281713Sjhibbits PMC_E500MC_ONLY(CASTOUTS_RELEASED, 93), 179281713Sjhibbits PMC_E500MC_ONLY(INTV_ALLOCATIONS, 94), 180281713Sjhibbits PMC_E500MC_ONLY(DLFB_RETRIES_TO_MBAR, 95), 181281713Sjhibbits PMC_E500MC_ONLY(STORE_RETRIES, 96), 182281713Sjhibbits PMC_E500MC_ONLY(STASH_L1_HITS, 97), 183281713Sjhibbits PMC_E500MC_ONLY(STASH_L2_HITS, 98), 184281713Sjhibbits PMC_E500MC_ONLY(STASH_BUSY_1, 99), 185281713Sjhibbits PMC_E500MC_ONLY(STASH_BUSY_2, 100), 186281713Sjhibbits PMC_E500MC_ONLY(STASH_BUSY_3, 101), 187281713Sjhibbits PMC_E500MC_ONLY(STASH_HITS, 102), 188281713Sjhibbits PMC_E500MC_ONLY(STASH_HIT_DLFB, 103), 189281713Sjhibbits PMC_E500MC_ONLY(STASH_REQUESTS, 106), 190281713Sjhibbits PMC_E500MC_ONLY(STASH_REQUESTS_L1, 107), 191281713Sjhibbits PMC_E500MC_ONLY(STASH_REQUESTS_L2, 108), 192281713Sjhibbits PMC_E500MC_ONLY(STALLS_NO_CAQ_OR_COB, 109), 193281713Sjhibbits PMC_E500MC_ONLY(L2_CACHE_ACCESSES, 110), 194281713Sjhibbits PMC_E500MC_ONLY(L2_HIT_CACHE_ACCESSES, 111), 195281713Sjhibbits PMC_E500MC_ONLY(L2_CACHE_DATA_ACCESSES, 112), 196281713Sjhibbits PMC_E500MC_ONLY(L2_CACHE_DATA_HITS, 113), 197281713Sjhibbits PMC_E500MC_ONLY(L2_CACHE_INSTR_ACCESSES, 114), 198281713Sjhibbits PMC_E500MC_ONLY(L2_CACHE_INSTR_HITS, 115), 199281713Sjhibbits PMC_E500MC_ONLY(L2_CACHE_ALLOCATIONS, 116), 200281713Sjhibbits PMC_E500MC_ONLY(L2_CACHE_DATA_ALLOCATIONS, 117), 201281713Sjhibbits PMC_E500MC_ONLY(L2_CACHE_DIRTY_DATA_ALLOCATIONS, 118), 202281713Sjhibbits PMC_E500MC_ONLY(L2_CACHE_INSTR_ALLOCATIONS, 119), 203281713Sjhibbits PMC_E500MC_ONLY(L2_CACHE_UPDATES, 120), 204281713Sjhibbits PMC_E500MC_ONLY(L2_CACHE_CLEAN_UPDATES, 121), 205281713Sjhibbits PMC_E500MC_ONLY(L2_CACHE_DIRTY_UPDATES, 122), 206281713Sjhibbits PMC_E500MC_ONLY(L2_CACHE_CLEAN_REDUNDANT_UPDATES, 123), 207281713Sjhibbits PMC_E500MC_ONLY(L2_CACHE_DIRTY_REDUNDANT_UPDATES, 124), 208281713Sjhibbits PMC_E500MC_ONLY(L2_CACHE_LOCKS, 125), 209281713Sjhibbits PMC_E500MC_ONLY(L2_CACHE_CASTOUTS, 126), 210281713Sjhibbits PMC_E500MC_ONLY(L2_CACHE_DATA_DIRTY_HITS, 127), 211281713Sjhibbits PMC_E500MC_ONLY(INSTR_LFB_WENT_HIGH_PRIORITY, 128), 212281713Sjhibbits PMC_E500MC_ONLY(SNOOP_THROTTLING_TURNED_ON, 129), 213281713Sjhibbits PMC_E500MC_ONLY(L2_CLEAN_LINE_INVALIDATIONS, 130), 214281713Sjhibbits PMC_E500MC_ONLY(L2_INCOHERENT_LINE_INVALIDATIONS, 131), 215281713Sjhibbits PMC_E500MC_ONLY(L2_COHERENT_LINE_INVALIDATIONS, 132), 216281713Sjhibbits PMC_E500MC_ONLY(COHERENT_LOOKUP_MISS_DUE_TO_VALID_BUT_INCOHERENT_MATCHES, 133), 217281713Sjhibbits PMC_E500MC_ONLY(IAC1S_DETECTED, 140), 218281713Sjhibbits PMC_E500MC_ONLY(IAC2S_DETECTED, 141), 219281713Sjhibbits PMC_E500MC_ONLY(DAC1S_DTECTED, 144), 220281713Sjhibbits PMC_E500MC_ONLY(DAC2S_DTECTED, 145), 221281713Sjhibbits PMC_E500MC_ONLY(DVT0_DETECTED, 148), 222281713Sjhibbits PMC_E500MC_ONLY(DVT1_DETECTED, 149), 223281713Sjhibbits PMC_E500MC_ONLY(DVT2_DETECTED, 150), 224281713Sjhibbits PMC_E500MC_ONLY(DVT3_DETECTED, 151), 225281713Sjhibbits PMC_E500MC_ONLY(DVT4_DETECTED, 152), 226281713Sjhibbits PMC_E500MC_ONLY(DVT5_DETECTED, 153), 227281713Sjhibbits PMC_E500MC_ONLY(DVT6_DETECTED, 154), 228281713Sjhibbits PMC_E500MC_ONLY(DVT7_DETECTED, 155), 229281713Sjhibbits PMC_E500MC_ONLY(CYCLES_COMPLETION_STALLED_NEXUS_FIFO_FULL, 156), 230281713Sjhibbits PMC_E500MC_ONLY(FPU_DOUBLE_PUMP, 160), 231281713Sjhibbits PMC_E500MC_ONLY(FPU_FINISH, 161), 232281713Sjhibbits PMC_E500MC_ONLY(FPU_DIVIDE_CYCLES, 162), 233281713Sjhibbits PMC_E500MC_ONLY(FPU_DENORM_INPUT_CYCLES, 163), 234281713Sjhibbits PMC_E500MC_ONLY(FPU_RESULT_STALL_CYCLES, 164), 235281713Sjhibbits PMC_E500MC_ONLY(FPU_FPSCR_FULL_STALL, 165), 236281713Sjhibbits PMC_E500MC_ONLY(FPU_PIPE_SYNC_STALLS, 166), 237281713Sjhibbits PMC_E500MC_ONLY(FPU_INPUT_DATA_STALLS, 167), 238281713Sjhibbits PMC_E500MC_ONLY(DECORATED_LOADS, 176), 239281713Sjhibbits PMC_E500MC_ONLY(DECORATED_STORES, 177), 240281713Sjhibbits PMC_E500MC_ONLY(LOAD_RETRIES, 178), 241281713Sjhibbits PMC_E500MC_ONLY(STWCX_SUCCESSES, 179), 242281713Sjhibbits PMC_E500MC_ONLY(STWCX_FAILURES, 180), 243281713Sjhibbits}; 244281713Sjhibbits 245281713Sjhibbitsstatic pmc_value_t 246281713Sjhibbitse500_pmcn_read(unsigned int pmc) 247281713Sjhibbits{ 248281713Sjhibbits switch (pmc) { 249281713Sjhibbits case 0: 250281713Sjhibbits return mfpmr(PMR_PMC0); 251281713Sjhibbits break; 252281713Sjhibbits case 1: 253281713Sjhibbits return mfpmr(PMR_PMC1); 254281713Sjhibbits break; 255281713Sjhibbits case 2: 256281713Sjhibbits return mfpmr(PMR_PMC2); 257281713Sjhibbits break; 258281713Sjhibbits case 3: 259281713Sjhibbits return mfpmr(PMR_PMC3); 260281713Sjhibbits break; 261281713Sjhibbits default: 262281713Sjhibbits panic("Invalid PMC number: %d\n", pmc); 263281713Sjhibbits } 264281713Sjhibbits} 265281713Sjhibbits 266281713Sjhibbitsstatic void 267281713Sjhibbitse500_pmcn_write(unsigned int pmc, uint32_t val) 268281713Sjhibbits{ 269281713Sjhibbits switch (pmc) { 270281713Sjhibbits case 0: 271281713Sjhibbits mtpmr(PMR_PMC0, val); 272281713Sjhibbits break; 273281713Sjhibbits case 1: 274281713Sjhibbits mtpmr(PMR_PMC1, val); 275281713Sjhibbits break; 276281713Sjhibbits case 2: 277281713Sjhibbits mtpmr(PMR_PMC2, val); 278281713Sjhibbits break; 279281713Sjhibbits case 3: 280281713Sjhibbits mtpmr(PMR_PMC3, val); 281281713Sjhibbits break; 282281713Sjhibbits default: 283281713Sjhibbits panic("Invalid PMC number: %d\n", pmc); 284281713Sjhibbits } 285281713Sjhibbits} 286281713Sjhibbits 287281713Sjhibbitsstatic int 288281713Sjhibbitse500_read_pmc(int cpu, int ri, pmc_value_t *v) 289281713Sjhibbits{ 290281713Sjhibbits struct pmc *pm; 291281713Sjhibbits pmc_value_t tmp; 292281713Sjhibbits 293281713Sjhibbits KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 294281713Sjhibbits ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); 295281713Sjhibbits KASSERT(ri >= 0 && ri < E500_MAX_PMCS, 296281713Sjhibbits ("[powerpc,%d] illegal row index %d", __LINE__, ri)); 297281713Sjhibbits 298281713Sjhibbits pm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc; 299281713Sjhibbits KASSERT(pm, 300281713Sjhibbits ("[core,%d] cpu %d ri %d pmc not configured", __LINE__, cpu, 301281713Sjhibbits ri)); 302281713Sjhibbits 303281713Sjhibbits tmp = e500_pmcn_read(ri); 304282676Sbz PMCDBG2(MDP,REA,2,"ppc-read id=%d -> %jd", ri, tmp); 305281713Sjhibbits if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) 306281713Sjhibbits *v = POWERPC_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp); 307281713Sjhibbits else 308281713Sjhibbits *v = tmp; 309281713Sjhibbits 310281713Sjhibbits return 0; 311281713Sjhibbits} 312281713Sjhibbits 313281713Sjhibbitsstatic int 314281713Sjhibbitse500_write_pmc(int cpu, int ri, pmc_value_t v) 315281713Sjhibbits{ 316281713Sjhibbits struct pmc *pm; 317281713Sjhibbits 318281713Sjhibbits KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 319281713Sjhibbits ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); 320281713Sjhibbits KASSERT(ri >= 0 && ri < E500_MAX_PMCS, 321281713Sjhibbits ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); 322281713Sjhibbits 323281713Sjhibbits pm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc; 324281713Sjhibbits 325281713Sjhibbits if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) 326281713Sjhibbits v = POWERPC_RELOAD_COUNT_TO_PERFCTR_VALUE(v); 327281713Sjhibbits 328282676Sbz PMCDBG3(MDP,WRI,1,"powerpc-write cpu=%d ri=%d v=%jx", cpu, ri, v); 329281713Sjhibbits 330281713Sjhibbits e500_pmcn_write(ri, v); 331281713Sjhibbits 332281713Sjhibbits return 0; 333281713Sjhibbits} 334281713Sjhibbits 335281713Sjhibbitsstatic int 336281713Sjhibbitse500_config_pmc(int cpu, int ri, struct pmc *pm) 337281713Sjhibbits{ 338281713Sjhibbits struct pmc_hw *phw; 339281713Sjhibbits 340282676Sbz PMCDBG3(MDP,CFG,1, "cpu=%d ri=%d pm=%p", cpu, ri, pm); 341281713Sjhibbits 342281713Sjhibbits KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 343281713Sjhibbits ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); 344281713Sjhibbits KASSERT(ri >= 0 && ri < E500_MAX_PMCS, 345281713Sjhibbits ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); 346281713Sjhibbits 347281713Sjhibbits phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; 348281713Sjhibbits 349281713Sjhibbits KASSERT(pm == NULL || phw->phw_pmc == NULL, 350281713Sjhibbits ("[powerpc,%d] pm=%p phw->pm=%p hwpmc not unconfigured", 351281713Sjhibbits __LINE__, pm, phw->phw_pmc)); 352281713Sjhibbits 353281713Sjhibbits phw->phw_pmc = pm; 354281713Sjhibbits 355281713Sjhibbits return 0; 356281713Sjhibbits} 357281713Sjhibbits 358281713Sjhibbitsstatic int 359281713Sjhibbitse500_start_pmc(int cpu, int ri) 360281713Sjhibbits{ 361281713Sjhibbits uint32_t config; 362281713Sjhibbits struct pmc *pm; 363281713Sjhibbits struct pmc_hw *phw; 364281713Sjhibbits 365281713Sjhibbits phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; 366281713Sjhibbits pm = phw->phw_pmc; 367281713Sjhibbits config = pm->pm_md.pm_powerpc.pm_powerpc_evsel; 368281713Sjhibbits 369281713Sjhibbits if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) 370281713Sjhibbits config |= PMLCax_CE; 371281713Sjhibbits 372281713Sjhibbits /* Enable the PMC. */ 373281713Sjhibbits switch (ri) { 374281713Sjhibbits case 0: 375281713Sjhibbits mtpmr(PMR_PMLCa0, config); 376281713Sjhibbits break; 377281713Sjhibbits case 1: 378281713Sjhibbits mtpmr(PMR_PMLCa1, config); 379281713Sjhibbits break; 380281713Sjhibbits case 2: 381281713Sjhibbits mtpmr(PMR_PMLCa2, config); 382281713Sjhibbits break; 383281713Sjhibbits case 3: 384281713Sjhibbits mtpmr(PMR_PMLCa3, config); 385281713Sjhibbits break; 386281713Sjhibbits default: 387281713Sjhibbits break; 388281713Sjhibbits } 389281713Sjhibbits 390281713Sjhibbits return 0; 391281713Sjhibbits} 392281713Sjhibbits 393281713Sjhibbitsstatic int 394281713Sjhibbitse500_stop_pmc(int cpu, int ri) 395281713Sjhibbits{ 396281713Sjhibbits struct pmc *pm; 397281713Sjhibbits struct pmc_hw *phw; 398281713Sjhibbits register_t pmc_pmlc; 399281713Sjhibbits 400281713Sjhibbits phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; 401281713Sjhibbits pm = phw->phw_pmc; 402281713Sjhibbits 403281713Sjhibbits /* 404281713Sjhibbits * Disable the PMCs. 405281713Sjhibbits */ 406281713Sjhibbits switch (ri) { 407281713Sjhibbits case 0: 408281713Sjhibbits pmc_pmlc = mfpmr(PMR_PMLCa0); 409281713Sjhibbits pmc_pmlc |= PMLCax_FC; 410281713Sjhibbits mtpmr(PMR_PMLCa0, pmc_pmlc); 411281713Sjhibbits break; 412281713Sjhibbits case 1: 413281713Sjhibbits pmc_pmlc = mfpmr(PMR_PMLCa1); 414281713Sjhibbits pmc_pmlc |= PMLCax_FC; 415281713Sjhibbits mtpmr(PMR_PMLCa1, pmc_pmlc); 416281713Sjhibbits break; 417281713Sjhibbits case 2: 418281713Sjhibbits pmc_pmlc = mfpmr(PMR_PMLCa2); 419281713Sjhibbits pmc_pmlc |= PMLCax_FC; 420281713Sjhibbits mtpmr(PMR_PMLCa2, pmc_pmlc); 421281713Sjhibbits break; 422281713Sjhibbits case 3: 423281713Sjhibbits pmc_pmlc = mfpmr(PMR_PMLCa3); 424281713Sjhibbits pmc_pmlc |= PMLCax_FC; 425281713Sjhibbits mtpmr(PMR_PMLCa3, pmc_pmlc); 426281713Sjhibbits break; 427281713Sjhibbits default: 428281713Sjhibbits break; 429281713Sjhibbits } 430281713Sjhibbits return 0; 431281713Sjhibbits} 432281713Sjhibbits 433281713Sjhibbitsstatic int 434281713Sjhibbitse500_pcpu_init(struct pmc_mdep *md, int cpu) 435281713Sjhibbits{ 436281713Sjhibbits int first_ri, i; 437281713Sjhibbits struct pmc_cpu *pc; 438281713Sjhibbits struct powerpc_cpu *pac; 439281713Sjhibbits struct pmc_hw *phw; 440281713Sjhibbits 441281713Sjhibbits KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 442281713Sjhibbits ("[powerpc,%d] wrong cpu number %d", __LINE__, cpu)); 443282676Sbz PMCDBG1(MDP,INI,1,"powerpc-init cpu=%d", cpu); 444281713Sjhibbits 445281713Sjhibbits /* Freeze all counters. */ 446281713Sjhibbits mtpmr(PMR_PMGC0, PMGC_FAC | PMGC_PMIE | PMGC_FCECE); 447281713Sjhibbits 448281713Sjhibbits powerpc_pcpu[cpu] = pac = malloc(sizeof(struct powerpc_cpu), M_PMC, 449281713Sjhibbits M_WAITOK|M_ZERO); 450281713Sjhibbits pac->pc_ppcpmcs = malloc(sizeof(struct pmc_hw) * E500_MAX_PMCS, 451281713Sjhibbits M_PMC, M_WAITOK|M_ZERO); 452281713Sjhibbits pac->pc_class = PMC_CLASS_E500; 453281713Sjhibbits pc = pmc_pcpu[cpu]; 454281713Sjhibbits first_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_POWERPC].pcd_ri; 455281713Sjhibbits KASSERT(pc != NULL, ("[powerpc,%d] NULL per-cpu pointer", __LINE__)); 456281713Sjhibbits 457281713Sjhibbits for (i = 0, phw = pac->pc_ppcpmcs; i < E500_MAX_PMCS; i++, phw++) { 458281713Sjhibbits phw->phw_state = PMC_PHW_FLAG_IS_ENABLED | 459281713Sjhibbits PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(i); 460281713Sjhibbits phw->phw_pmc = NULL; 461281713Sjhibbits pc->pc_hwpmcs[i + first_ri] = phw; 462281713Sjhibbits 463281713Sjhibbits /* Initialize the PMC to stopped */ 464281713Sjhibbits e500_stop_pmc(cpu, i); 465281713Sjhibbits } 466281713Sjhibbits /* Unfreeze global register. */ 467281713Sjhibbits mtpmr(PMR_PMGC0, PMGC_PMIE | PMGC_FCECE); 468281713Sjhibbits 469281713Sjhibbits return 0; 470281713Sjhibbits} 471281713Sjhibbits 472281713Sjhibbitsstatic int 473281713Sjhibbitse500_pcpu_fini(struct pmc_mdep *md, int cpu) 474281713Sjhibbits{ 475281713Sjhibbits uint32_t pmgc0 = mfpmr(PMR_PMGC0); 476281713Sjhibbits 477281713Sjhibbits pmgc0 |= PMGC_FAC; 478281713Sjhibbits mtpmr(PMR_PMGC0, pmgc0); 479281713Sjhibbits mtmsr(mfmsr() & ~PSL_PMM); 480281713Sjhibbits 481281713Sjhibbits free(powerpc_pcpu[cpu]->pc_ppcpmcs, M_PMC); 482281713Sjhibbits free(powerpc_pcpu[cpu], M_PMC); 483281713Sjhibbits 484281713Sjhibbits return 0; 485281713Sjhibbits} 486281713Sjhibbits 487281713Sjhibbitsstatic int 488281713Sjhibbitse500_allocate_pmc(int cpu, int ri, struct pmc *pm, 489281713Sjhibbits const struct pmc_op_pmcallocate *a) 490281713Sjhibbits{ 491281713Sjhibbits enum pmc_event pe; 492281713Sjhibbits uint32_t caps, config, counter; 493281713Sjhibbits struct e500_event_code_map *ev; 494281713Sjhibbits uint16_t vers; 495281713Sjhibbits uint8_t pe_cpu_mask; 496281713Sjhibbits 497281713Sjhibbits KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 498281713Sjhibbits ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); 499281713Sjhibbits KASSERT(ri >= 0 && ri < E500_MAX_PMCS, 500281713Sjhibbits ("[powerpc,%d] illegal row index %d", __LINE__, ri)); 501281713Sjhibbits 502281713Sjhibbits caps = a->pm_caps; 503281713Sjhibbits 504281713Sjhibbits pe = a->pm_ev; 505281713Sjhibbits config = PMLCax_FCS | PMLCax_FCU | 506281713Sjhibbits PMLCax_FCM1 | PMLCax_FCM1; 507297730Sjhibbits 508281713Sjhibbits if (pe < PMC_EV_E500_FIRST || pe > PMC_EV_E500_LAST) 509281713Sjhibbits return (EINVAL); 510281713Sjhibbits 511281713Sjhibbits ev = &e500_event_codes[pe-PMC_EV_E500_FIRST]; 512281713Sjhibbits if (ev->pe_code == 0) 513281713Sjhibbits return (EINVAL); 514281713Sjhibbits 515281713Sjhibbits vers = mfpvr() >> 16; 516281713Sjhibbits switch (vers) { 517281713Sjhibbits case FSL_E500v1: 518297730Sjhibbits pe_cpu_mask = ev->pe_cpu & PMC_PPC_E500V1; 519281713Sjhibbits break; 520281713Sjhibbits case FSL_E500v2: 521297730Sjhibbits pe_cpu_mask = ev->pe_cpu & PMC_PPC_E500V2; 522281713Sjhibbits break; 523281713Sjhibbits case FSL_E500mc: 524294197Sjhibbits case FSL_E5500: 525297730Sjhibbits pe_cpu_mask = ev->pe_cpu & PMC_PPC_E500MC; 526281713Sjhibbits break; 527281713Sjhibbits } 528281713Sjhibbits if (pe_cpu_mask == 0) 529281713Sjhibbits return (EINVAL); 530281713Sjhibbits 531281713Sjhibbits config |= PMLCax_EVENT(ev->pe_code); 532281713Sjhibbits counter = ev->pe_counter_mask; 533281713Sjhibbits if ((counter & (1 << ri)) == 0) 534281713Sjhibbits return (EINVAL); 535281713Sjhibbits 536281713Sjhibbits if (caps & PMC_CAP_SYSTEM) 537281713Sjhibbits config &= ~PMLCax_FCS; 538281713Sjhibbits if (caps & PMC_CAP_USER) 539281713Sjhibbits config &= ~PMLCax_FCU; 540281713Sjhibbits if ((caps & (PMC_CAP_USER | PMC_CAP_SYSTEM)) == 0) 541281713Sjhibbits config &= ~(PMLCax_FCS|PMLCax_FCU); 542281713Sjhibbits 543281713Sjhibbits pm->pm_md.pm_powerpc.pm_powerpc_evsel = config; 544281713Sjhibbits 545282676Sbz PMCDBG2(MDP,ALL,2,"powerpc-allocate ri=%d -> config=0x%x", ri, config); 546281713Sjhibbits 547281713Sjhibbits return 0; 548281713Sjhibbits} 549281713Sjhibbits 550281713Sjhibbitsstatic int 551281713Sjhibbitse500_release_pmc(int cpu, int ri, struct pmc *pmc) 552281713Sjhibbits{ 553281713Sjhibbits struct pmc_hw *phw; 554281713Sjhibbits 555281713Sjhibbits KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 556281713Sjhibbits ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); 557281713Sjhibbits KASSERT(ri >= 0 && ri < E500_MAX_PMCS, 558281713Sjhibbits ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); 559281713Sjhibbits 560281713Sjhibbits phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; 561281713Sjhibbits KASSERT(phw->phw_pmc == NULL, 562281713Sjhibbits ("[powerpc,%d] PHW pmc %p non-NULL", __LINE__, phw->phw_pmc)); 563281713Sjhibbits 564281713Sjhibbits return 0; 565281713Sjhibbits} 566281713Sjhibbits 567281713Sjhibbitsstatic int 568281713Sjhibbitse500_intr(int cpu, struct trapframe *tf) 569281713Sjhibbits{ 570281713Sjhibbits int i, error, retval; 571281713Sjhibbits uint32_t config; 572281713Sjhibbits struct pmc *pm; 573281713Sjhibbits struct powerpc_cpu *pac; 574281713Sjhibbits 575281713Sjhibbits KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 576281713Sjhibbits ("[powerpc,%d] out of range CPU %d", __LINE__, cpu)); 577281713Sjhibbits 578282676Sbz PMCDBG3(MDP,INT,1, "cpu=%d tf=%p um=%d", cpu, (void *) tf, 579281713Sjhibbits TRAPF_USERMODE(tf)); 580281713Sjhibbits 581281713Sjhibbits retval = 0; 582281713Sjhibbits 583281713Sjhibbits pac = powerpc_pcpu[cpu]; 584281713Sjhibbits 585281713Sjhibbits config = mfpmr(PMR_PMGC0) & ~PMGC_FAC; 586281713Sjhibbits 587281713Sjhibbits /* 588281713Sjhibbits * look for all PMCs that have interrupted: 589281713Sjhibbits * - look for a running, sampling PMC which has overflowed 590281713Sjhibbits * and which has a valid 'struct pmc' association 591281713Sjhibbits * 592281713Sjhibbits * If found, we call a helper to process the interrupt. 593281713Sjhibbits */ 594281713Sjhibbits 595281713Sjhibbits for (i = 0; i < E500_MAX_PMCS; i++) { 596281713Sjhibbits if ((pm = pac->pc_ppcpmcs[i].phw_pmc) == NULL || 597281713Sjhibbits !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) { 598281713Sjhibbits continue; 599281713Sjhibbits } 600281713Sjhibbits 601281713Sjhibbits if (!E500_PMC_HAS_OVERFLOWED(i)) 602281713Sjhibbits continue; 603281713Sjhibbits 604281713Sjhibbits retval = 1; /* Found an interrupting PMC. */ 605281713Sjhibbits 606281713Sjhibbits if (pm->pm_state != PMC_STATE_RUNNING) 607281713Sjhibbits continue; 608281713Sjhibbits 609281713Sjhibbits /* Stop the counter if logging fails. */ 610281713Sjhibbits error = pmc_process_interrupt(cpu, PMC_HR, pm, tf, 611281713Sjhibbits TRAPF_USERMODE(tf)); 612281713Sjhibbits if (error != 0) 613281713Sjhibbits e500_stop_pmc(cpu, i); 614281713Sjhibbits 615281713Sjhibbits /* reload count. */ 616281713Sjhibbits e500_write_pmc(cpu, i, pm->pm_sc.pm_reloadcount); 617281713Sjhibbits } 618281713Sjhibbits 619281713Sjhibbits atomic_add_int(retval ? &pmc_stats.pm_intr_processed : 620281713Sjhibbits &pmc_stats.pm_intr_ignored, 1); 621281713Sjhibbits 622281713Sjhibbits /* Re-enable PERF exceptions. */ 623281713Sjhibbits if (retval) 624281713Sjhibbits mtpmr(PMR_PMGC0, config | PMGC_PMIE); 625281713Sjhibbits 626281713Sjhibbits return (retval); 627281713Sjhibbits} 628281713Sjhibbits 629281713Sjhibbitsint 630281713Sjhibbitspmc_e500_initialize(struct pmc_mdep *pmc_mdep) 631281713Sjhibbits{ 632281713Sjhibbits struct pmc_classdep *pcd; 633281713Sjhibbits 634281713Sjhibbits pmc_mdep->pmd_cputype = PMC_CPU_PPC_E500; 635281713Sjhibbits 636281713Sjhibbits pcd = &pmc_mdep->pmd_classdep[PMC_MDEP_CLASS_INDEX_POWERPC]; 637281713Sjhibbits pcd->pcd_caps = POWERPC_PMC_CAPS; 638281713Sjhibbits pcd->pcd_class = PMC_CLASS_E500; 639281713Sjhibbits pcd->pcd_num = E500_MAX_PMCS; 640281713Sjhibbits pcd->pcd_ri = pmc_mdep->pmd_npmc; 641281713Sjhibbits pcd->pcd_width = 32; 642281713Sjhibbits 643281713Sjhibbits pcd->pcd_allocate_pmc = e500_allocate_pmc; 644281713Sjhibbits pcd->pcd_config_pmc = e500_config_pmc; 645281713Sjhibbits pcd->pcd_pcpu_fini = e500_pcpu_fini; 646281713Sjhibbits pcd->pcd_pcpu_init = e500_pcpu_init; 647281713Sjhibbits pcd->pcd_describe = powerpc_describe; 648281713Sjhibbits pcd->pcd_get_config = powerpc_get_config; 649281713Sjhibbits pcd->pcd_read_pmc = e500_read_pmc; 650281713Sjhibbits pcd->pcd_release_pmc = e500_release_pmc; 651281713Sjhibbits pcd->pcd_start_pmc = e500_start_pmc; 652281713Sjhibbits pcd->pcd_stop_pmc = e500_stop_pmc; 653281713Sjhibbits pcd->pcd_write_pmc = e500_write_pmc; 654281713Sjhibbits 655281713Sjhibbits pmc_mdep->pmd_npmc += E500_MAX_PMCS; 656281713Sjhibbits pmc_mdep->pmd_intr = e500_intr; 657281713Sjhibbits 658281713Sjhibbits return (0); 659281713Sjhibbits} 660