Index: head/sys/dev/hwpmc/hwpmc_e500.c =================================================================== --- head/sys/dev/hwpmc/hwpmc_e500.c (revision 367389) +++ head/sys/dev/hwpmc/hwpmc_e500.c (revision 367390) @@ -1,661 +1,472 @@ /*- * Copyright (c) 2015 Justin Hibbits * Copyright (c) 2005, Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include "hwpmc_powerpc.h" -#define POWERPC_PMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_USER | \ - PMC_CAP_SYSTEM | PMC_CAP_EDGE | \ - PMC_CAP_THRESHOLD | PMC_CAP_READ | \ - PMC_CAP_WRITE | PMC_CAP_INVERT | \ - PMC_CAP_QUALIFIER) - -#define E500_PMC_HAS_OVERFLOWED(x) (e500_pmcn_read(x) & (0x1 << 31)) - struct e500_event_code_map { enum pmc_event pe_ev; /* enum value */ uint8_t pe_counter_mask; /* Which counter this can be counted in. */ uint8_t pe_code; /* numeric code */ uint8_t pe_cpu; /* e500 core (v1,v2,mc), mask */ }; #define E500_MAX_PMCS 4 #define PMC_PPC_MASK0 0 #define PMC_PPC_MASK1 1 #define PMC_PPC_MASK2 2 #define PMC_PPC_MASK3 3 #define PMC_PPC_MASK_ALL 0x0f #define PMC_PPC_E500V1 1 #define PMC_PPC_E500V2 2 #define PMC_PPC_E500MC 4 #define PMC_PPC_E500_ANY 7 #define PMC_E500_EVENT(id, mask, number, core) \ [PMC_EV_E500_##id - PMC_EV_E500_FIRST] = \ { .pe_ev = PMC_EV_E500_##id, .pe_counter_mask = mask, \ .pe_code = number, .pe_cpu = core } #define PMC_E500MC_ONLY(id, number) \ PMC_E500_EVENT(id, PMC_PPC_MASK_ALL, number, PMC_PPC_E500MC) #define PMC_E500_COMMON(id, number) \ PMC_E500_EVENT(id, PMC_PPC_MASK_ALL, number, PMC_PPC_E500_ANY) static struct e500_event_code_map e500_event_codes[] = { PMC_E500_COMMON(CYCLES, 1), PMC_E500_COMMON(INSTR_COMPLETED, 2), PMC_E500_COMMON(UOPS_COMPLETED, 3), PMC_E500_COMMON(INSTR_FETCHED, 4), PMC_E500_COMMON(UOPS_DECODED, 5), PMC_E500_COMMON(PM_EVENT_TRANSITIONS, 6), PMC_E500_COMMON(PM_EVENT_CYCLES, 7), PMC_E500_COMMON(BRANCH_INSTRS_COMPLETED, 8), PMC_E500_COMMON(LOAD_UOPS_COMPLETED, 9), PMC_E500_COMMON(STORE_UOPS_COMPLETED, 10), PMC_E500_COMMON(CQ_REDIRECTS, 11), PMC_E500_COMMON(BRANCHES_FINISHED, 12), PMC_E500_COMMON(TAKEN_BRANCHES_FINISHED, 13), PMC_E500_COMMON(FINISHED_UNCOND_BRANCHES_MISS_BTB, 14), PMC_E500_COMMON(BRANCH_MISPRED, 15), PMC_E500_COMMON(BTB_BRANCH_MISPRED_FROM_DIRECTION, 16), PMC_E500_COMMON(BTB_HITS_PSEUDO_HITS, 17), PMC_E500_COMMON(CYCLES_DECODE_STALLED, 18), PMC_E500_COMMON(CYCLES_ISSUE_STALLED, 19), PMC_E500_COMMON(CYCLES_BRANCH_ISSUE_STALLED, 20), PMC_E500_COMMON(CYCLES_SU1_SCHED_STALLED, 21), PMC_E500_COMMON(CYCLES_SU2_SCHED_STALLED, 22), PMC_E500_COMMON(CYCLES_MU_SCHED_STALLED, 23), PMC_E500_COMMON(CYCLES_LRU_SCHED_STALLED, 24), PMC_E500_COMMON(CYCLES_BU_SCHED_STALLED, 25), PMC_E500_COMMON(TOTAL_TRANSLATED, 26), PMC_E500_COMMON(LOADS_TRANSLATED, 27), PMC_E500_COMMON(STORES_TRANSLATED, 28), PMC_E500_COMMON(TOUCHES_TRANSLATED, 29), PMC_E500_COMMON(CACHEOPS_TRANSLATED, 30), PMC_E500_COMMON(CACHE_INHIBITED_ACCESS_TRANSLATED, 31), PMC_E500_COMMON(GUARDED_LOADS_TRANSLATED, 32), PMC_E500_COMMON(WRITE_THROUGH_STORES_TRANSLATED, 33), PMC_E500_COMMON(MISALIGNED_LOAD_STORE_ACCESS_TRANSLATED, 34), PMC_E500_COMMON(TOTAL_ALLOCATED_TO_DLFB, 35), PMC_E500_COMMON(LOADS_TRANSLATED_ALLOCATED_TO_DLFB, 36), PMC_E500_COMMON(STORES_COMPLETED_ALLOCATED_TO_DLFB, 37), PMC_E500_COMMON(TOUCHES_TRANSLATED_ALLOCATED_TO_DLFB, 38), PMC_E500_COMMON(STORES_COMPLETED, 39), PMC_E500_COMMON(DATA_L1_CACHE_LOCKS, 40), PMC_E500_COMMON(DATA_L1_CACHE_RELOADS, 41), PMC_E500_COMMON(DATA_L1_CACHE_CASTOUTS, 42), PMC_E500_COMMON(LOAD_MISS_DLFB_FULL, 43), PMC_E500_COMMON(LOAD_MISS_LDQ_FULL, 44), PMC_E500_COMMON(LOAD_GUARDED_MISS, 45), PMC_E500_COMMON(STORE_TRANSLATE_WHEN_QUEUE_FULL, 46), PMC_E500_COMMON(ADDRESS_COLLISION, 47), PMC_E500_COMMON(DATA_MMU_MISS, 48), PMC_E500_COMMON(DATA_MMU_BUSY, 49), PMC_E500_COMMON(PART2_MISALIGNED_CACHE_ACCESS, 50), PMC_E500_COMMON(LOAD_MISS_DLFB_FULL_CYCLES, 51), PMC_E500_COMMON(LOAD_MISS_LDQ_FULL_CYCLES, 52), PMC_E500_COMMON(LOAD_GUARDED_MISS_CYCLES, 53), PMC_E500_COMMON(STORE_TRANSLATE_WHEN_QUEUE_FULL_CYCLES, 54), PMC_E500_COMMON(ADDRESS_COLLISION_CYCLES, 55), PMC_E500_COMMON(DATA_MMU_MISS_CYCLES, 56), PMC_E500_COMMON(DATA_MMU_BUSY_CYCLES, 57), PMC_E500_COMMON(PART2_MISALIGNED_CACHE_ACCESS_CYCLES, 58), PMC_E500_COMMON(INSTR_L1_CACHE_LOCKS, 59), PMC_E500_COMMON(INSTR_L1_CACHE_RELOADS, 60), PMC_E500_COMMON(INSTR_L1_CACHE_FETCHES, 61), PMC_E500_COMMON(INSTR_MMU_TLB4K_RELOADS, 62), PMC_E500_COMMON(INSTR_MMU_VSP_RELOADS, 63), PMC_E500_COMMON(DATA_MMU_TLB4K_RELOADS, 64), PMC_E500_COMMON(DATA_MMU_VSP_RELOADS, 65), PMC_E500_COMMON(L2MMU_MISSES, 66), PMC_E500_COMMON(BIU_MASTER_REQUESTS, 67), PMC_E500_COMMON(BIU_MASTER_INSTR_SIDE_REQUESTS, 68), PMC_E500_COMMON(BIU_MASTER_DATA_SIDE_REQUESTS, 69), PMC_E500_COMMON(BIU_MASTER_DATA_SIDE_CASTOUT_REQUESTS, 70), PMC_E500_COMMON(BIU_MASTER_RETRIES, 71), PMC_E500_COMMON(SNOOP_REQUESTS, 72), PMC_E500_COMMON(SNOOP_HITS, 73), PMC_E500_COMMON(SNOOP_PUSHES, 74), PMC_E500_COMMON(SNOOP_RETRIES, 75), PMC_E500_EVENT(DLFB_LOAD_MISS_CYCLES, PMC_PPC_MASK0|PMC_PPC_MASK1, 76, PMC_PPC_E500_ANY), PMC_E500_EVENT(ILFB_FETCH_MISS_CYCLES, PMC_PPC_MASK0|PMC_PPC_MASK1, 77, PMC_PPC_E500_ANY), PMC_E500_EVENT(EXT_INPU_INTR_LATENCY_CYCLES, PMC_PPC_MASK0|PMC_PPC_MASK1, 78, PMC_PPC_E500_ANY), PMC_E500_EVENT(CRIT_INPUT_INTR_LATENCY_CYCLES, PMC_PPC_MASK0|PMC_PPC_MASK1, 79, PMC_PPC_E500_ANY), PMC_E500_EVENT(EXT_INPUT_INTR_PENDING_LATENCY_CYCLES, PMC_PPC_MASK0|PMC_PPC_MASK1, 80, PMC_PPC_E500_ANY), PMC_E500_EVENT(CRIT_INPUT_INTR_PENDING_LATENCY_CYCLES, PMC_PPC_MASK0|PMC_PPC_MASK1, 81, PMC_PPC_E500_ANY), PMC_E500_COMMON(PMC0_OVERFLOW, 82), PMC_E500_COMMON(PMC1_OVERFLOW, 83), PMC_E500_COMMON(PMC2_OVERFLOW, 84), PMC_E500_COMMON(PMC3_OVERFLOW, 85), PMC_E500_COMMON(INTERRUPTS_TAKEN, 86), PMC_E500_COMMON(EXT_INPUT_INTR_TAKEN, 87), PMC_E500_COMMON(CRIT_INPUT_INTR_TAKEN, 88), PMC_E500_COMMON(SYSCALL_TRAP_INTR, 89), PMC_E500_EVENT(TLB_BIT_TRANSITIONS, PMC_PPC_MASK_ALL, 90, PMC_PPC_E500V2 | PMC_PPC_E500MC), PMC_E500MC_ONLY(L2_LINEFILL_BUFFER, 91), PMC_E500MC_ONLY(LV2_VS, 92), PMC_E500MC_ONLY(CASTOUTS_RELEASED, 93), PMC_E500MC_ONLY(INTV_ALLOCATIONS, 94), PMC_E500MC_ONLY(DLFB_RETRIES_TO_MBAR, 95), PMC_E500MC_ONLY(STORE_RETRIES, 96), PMC_E500MC_ONLY(STASH_L1_HITS, 97), PMC_E500MC_ONLY(STASH_L2_HITS, 98), PMC_E500MC_ONLY(STASH_BUSY_1, 99), PMC_E500MC_ONLY(STASH_BUSY_2, 100), PMC_E500MC_ONLY(STASH_BUSY_3, 101), PMC_E500MC_ONLY(STASH_HITS, 102), PMC_E500MC_ONLY(STASH_HIT_DLFB, 103), PMC_E500MC_ONLY(STASH_REQUESTS, 106), PMC_E500MC_ONLY(STASH_REQUESTS_L1, 107), PMC_E500MC_ONLY(STASH_REQUESTS_L2, 108), PMC_E500MC_ONLY(STALLS_NO_CAQ_OR_COB, 109), PMC_E500MC_ONLY(L2_CACHE_ACCESSES, 110), PMC_E500MC_ONLY(L2_HIT_CACHE_ACCESSES, 111), PMC_E500MC_ONLY(L2_CACHE_DATA_ACCESSES, 112), PMC_E500MC_ONLY(L2_CACHE_DATA_HITS, 113), PMC_E500MC_ONLY(L2_CACHE_INSTR_ACCESSES, 114), PMC_E500MC_ONLY(L2_CACHE_INSTR_HITS, 115), PMC_E500MC_ONLY(L2_CACHE_ALLOCATIONS, 116), PMC_E500MC_ONLY(L2_CACHE_DATA_ALLOCATIONS, 117), PMC_E500MC_ONLY(L2_CACHE_DIRTY_DATA_ALLOCATIONS, 118), PMC_E500MC_ONLY(L2_CACHE_INSTR_ALLOCATIONS, 119), PMC_E500MC_ONLY(L2_CACHE_UPDATES, 120), PMC_E500MC_ONLY(L2_CACHE_CLEAN_UPDATES, 121), PMC_E500MC_ONLY(L2_CACHE_DIRTY_UPDATES, 122), PMC_E500MC_ONLY(L2_CACHE_CLEAN_REDUNDANT_UPDATES, 123), PMC_E500MC_ONLY(L2_CACHE_DIRTY_REDUNDANT_UPDATES, 124), PMC_E500MC_ONLY(L2_CACHE_LOCKS, 125), PMC_E500MC_ONLY(L2_CACHE_CASTOUTS, 126), PMC_E500MC_ONLY(L2_CACHE_DATA_DIRTY_HITS, 127), PMC_E500MC_ONLY(INSTR_LFB_WENT_HIGH_PRIORITY, 128), PMC_E500MC_ONLY(SNOOP_THROTTLING_TURNED_ON, 129), PMC_E500MC_ONLY(L2_CLEAN_LINE_INVALIDATIONS, 130), PMC_E500MC_ONLY(L2_INCOHERENT_LINE_INVALIDATIONS, 131), PMC_E500MC_ONLY(L2_COHERENT_LINE_INVALIDATIONS, 132), PMC_E500MC_ONLY(COHERENT_LOOKUP_MISS_DUE_TO_VALID_BUT_INCOHERENT_MATCHES, 133), PMC_E500MC_ONLY(IAC1S_DETECTED, 140), PMC_E500MC_ONLY(IAC2S_DETECTED, 141), PMC_E500MC_ONLY(DAC1S_DTECTED, 144), PMC_E500MC_ONLY(DAC2S_DTECTED, 145), PMC_E500MC_ONLY(DVT0_DETECTED, 148), PMC_E500MC_ONLY(DVT1_DETECTED, 149), PMC_E500MC_ONLY(DVT2_DETECTED, 150), PMC_E500MC_ONLY(DVT3_DETECTED, 151), PMC_E500MC_ONLY(DVT4_DETECTED, 152), PMC_E500MC_ONLY(DVT5_DETECTED, 153), PMC_E500MC_ONLY(DVT6_DETECTED, 154), PMC_E500MC_ONLY(DVT7_DETECTED, 155), PMC_E500MC_ONLY(CYCLES_COMPLETION_STALLED_NEXUS_FIFO_FULL, 156), PMC_E500MC_ONLY(FPU_DOUBLE_PUMP, 160), PMC_E500MC_ONLY(FPU_FINISH, 161), PMC_E500MC_ONLY(FPU_DIVIDE_CYCLES, 162), PMC_E500MC_ONLY(FPU_DENORM_INPUT_CYCLES, 163), PMC_E500MC_ONLY(FPU_RESULT_STALL_CYCLES, 164), PMC_E500MC_ONLY(FPU_FPSCR_FULL_STALL, 165), PMC_E500MC_ONLY(FPU_PIPE_SYNC_STALLS, 166), PMC_E500MC_ONLY(FPU_INPUT_DATA_STALLS, 167), PMC_E500MC_ONLY(DECORATED_LOADS, 176), PMC_E500MC_ONLY(DECORATED_STORES, 177), PMC_E500MC_ONLY(LOAD_RETRIES, 178), PMC_E500MC_ONLY(STWCX_SUCCESSES, 179), PMC_E500MC_ONLY(STWCX_FAILURES, 180), }; static pmc_value_t e500_pmcn_read(unsigned int pmc) { switch (pmc) { - case 0: - return mfpmr(PMR_PMC0); - break; - case 1: - return mfpmr(PMR_PMC1); - break; - case 2: - return mfpmr(PMR_PMC2); - break; - case 3: - return mfpmr(PMR_PMC3); - break; - default: - panic("Invalid PMC number: %d\n", pmc); + case 0: + return (mfpmr(PMR_PMC0)); + case 1: + return (mfpmr(PMR_PMC1)); + case 2: + return (mfpmr(PMR_PMC2)); + case 3: + return (mfpmr(PMR_PMC3)); + default: + panic("Invalid PMC number: %d\n", pmc); } } static void e500_pmcn_write(unsigned int pmc, uint32_t val) { switch (pmc) { - case 0: - mtpmr(PMR_PMC0, val); - break; - case 1: - mtpmr(PMR_PMC1, val); - break; - case 2: - mtpmr(PMR_PMC2, val); - break; - case 3: - mtpmr(PMR_PMC3, val); - break; - default: - panic("Invalid PMC number: %d\n", pmc); - } -} - -static int -e500_read_pmc(int cpu, int ri, pmc_value_t *v) -{ - struct pmc *pm; - pmc_value_t tmp; - - KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), - ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < E500_MAX_PMCS, - ("[powerpc,%d] illegal row index %d", __LINE__, ri)); - - pm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc; - KASSERT(pm, - ("[core,%d] cpu %d ri %d pmc not configured", __LINE__, cpu, - ri)); - - tmp = e500_pmcn_read(ri); - PMCDBG2(MDP,REA,2,"ppc-read id=%d -> %jd", ri, tmp); - if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) - *v = POWERPC_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp); - else - *v = tmp; - - return 0; -} - -static int -e500_write_pmc(int cpu, int ri, pmc_value_t v) -{ - struct pmc *pm; - - KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), - ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < E500_MAX_PMCS, - ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); - - pm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc; - - if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) - v = POWERPC_RELOAD_COUNT_TO_PERFCTR_VALUE(v); - - PMCDBG3(MDP,WRI,1,"powerpc-write cpu=%d ri=%d v=%jx", cpu, ri, v); - - e500_pmcn_write(ri, v); - - return 0; -} - -static int -e500_config_pmc(int cpu, int ri, struct pmc *pm) -{ - struct pmc_hw *phw; - - PMCDBG3(MDP,CFG,1, "cpu=%d ri=%d pm=%p", cpu, ri, pm); - - KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), - ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < E500_MAX_PMCS, - ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); - - phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; - - KASSERT(pm == NULL || phw->phw_pmc == NULL, - ("[powerpc,%d] pm=%p phw->pm=%p hwpmc not unconfigured", - __LINE__, pm, phw->phw_pmc)); - - phw->phw_pmc = pm; - - return 0; -} - -static int -e500_start_pmc(int cpu, int ri) -{ - uint32_t config; - struct pmc *pm; - struct pmc_hw *phw; - - phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; - pm = phw->phw_pmc; - config = pm->pm_md.pm_powerpc.pm_powerpc_evsel; - - if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) - config |= PMLCax_CE; - - /* Enable the PMC. */ - switch (ri) { case 0: - mtpmr(PMR_PMLCa0, config); + mtpmr(PMR_PMC0, val); break; case 1: - mtpmr(PMR_PMLCa1, config); + mtpmr(PMR_PMC1, val); break; case 2: - mtpmr(PMR_PMLCa2, config); + mtpmr(PMR_PMC2, val); break; case 3: - mtpmr(PMR_PMLCa3, config); + mtpmr(PMR_PMC3, val); break; default: - break; + panic("Invalid PMC number: %d\n", pmc); } - - return 0; } -static int -e500_stop_pmc(int cpu, int ri) +static void +e500_set_pmc(int cpu, int ri, int config) { - struct pmc *pm; - struct pmc_hw *phw; - register_t pmc_pmlc; + struct pmc *pm; + struct pmc_hw *phw; + register_t pmc_pmlc; phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; pm = phw->phw_pmc; + config &= ~POWERPC_PMC_ENABLE; - /* - * Disable the PMCs. - */ - switch (ri) { - case 0: - pmc_pmlc = mfpmr(PMR_PMLCa0); - pmc_pmlc |= PMLCax_FC; - mtpmr(PMR_PMLCa0, pmc_pmlc); - break; - case 1: - pmc_pmlc = mfpmr(PMR_PMLCa1); - pmc_pmlc |= PMLCax_FC; - mtpmr(PMR_PMLCa1, pmc_pmlc); - break; - case 2: - pmc_pmlc = mfpmr(PMR_PMLCa2); - pmc_pmlc |= PMLCax_FC; - mtpmr(PMR_PMLCa2, pmc_pmlc); - break; - case 3: - pmc_pmlc = mfpmr(PMR_PMLCa3); - pmc_pmlc |= PMLCax_FC; - mtpmr(PMR_PMLCa3, pmc_pmlc); - break; - default: - break; + if (config != PMCN_NONE) { + if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) + config |= PMLCax_CE; + + /* Enable the PMC. */ + switch (ri) { + case 0: + mtpmr(PMR_PMLCa0, config); + break; + case 1: + mtpmr(PMR_PMLCa1, config); + break; + case 2: + mtpmr(PMR_PMLCa2, config); + break; + case 3: + mtpmr(PMR_PMLCa3, config); + break; + } + } else { + /* Disable the PMC. */ + switch (ri) { + case 0: + pmc_pmlc = mfpmr(PMR_PMLCa0); + pmc_pmlc |= PMLCax_FC; + mtpmr(PMR_PMLCa0, pmc_pmlc); + break; + case 1: + pmc_pmlc = mfpmr(PMR_PMLCa1); + pmc_pmlc |= PMLCax_FC; + mtpmr(PMR_PMLCa1, pmc_pmlc); + break; + case 2: + pmc_pmlc = mfpmr(PMR_PMLCa2); + pmc_pmlc |= PMLCax_FC; + mtpmr(PMR_PMLCa2, pmc_pmlc); + break; + case 3: + pmc_pmlc = mfpmr(PMR_PMLCa3); + pmc_pmlc |= PMLCax_FC; + mtpmr(PMR_PMLCa3, pmc_pmlc); + break; + } } - return 0; } static int e500_pcpu_init(struct pmc_mdep *md, int cpu) { - int first_ri, i; - struct pmc_cpu *pc; - struct powerpc_cpu *pac; - struct pmc_hw *phw; + int i; - KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), - ("[powerpc,%d] wrong cpu number %d", __LINE__, cpu)); - PMCDBG1(MDP,INI,1,"powerpc-init cpu=%d", cpu); + powerpc_pcpu_init(md, cpu); /* Freeze all counters. */ mtpmr(PMR_PMGC0, PMGC_FAC | PMGC_PMIE | PMGC_FCECE); - powerpc_pcpu[cpu] = pac = malloc(sizeof(struct powerpc_cpu), M_PMC, - M_WAITOK|M_ZERO); - pac->pc_ppcpmcs = malloc(sizeof(struct pmc_hw) * E500_MAX_PMCS, - M_PMC, M_WAITOK|M_ZERO); - pac->pc_class = PMC_CLASS_E500; - pc = pmc_pcpu[cpu]; - first_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_POWERPC].pcd_ri; - KASSERT(pc != NULL, ("[powerpc,%d] NULL per-cpu pointer", __LINE__)); - - for (i = 0, phw = pac->pc_ppcpmcs; i < E500_MAX_PMCS; i++, phw++) { - phw->phw_state = PMC_PHW_FLAG_IS_ENABLED | - PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(i); - phw->phw_pmc = NULL; - pc->pc_hwpmcs[i + first_ri] = phw; - + for (i = 0; i < E500_MAX_PMCS; i++) /* Initialize the PMC to stopped */ - e500_stop_pmc(cpu, i); - } + powerpc_stop_pmc(cpu, i); + /* Unfreeze global register. */ mtpmr(PMR_PMGC0, PMGC_PMIE | PMGC_FCECE); - return 0; + return (0); } static int e500_pcpu_fini(struct pmc_mdep *md, int cpu) { uint32_t pmgc0 = mfpmr(PMR_PMGC0); pmgc0 |= PMGC_FAC; mtpmr(PMR_PMGC0, pmgc0); mtmsr(mfmsr() & ~PSL_PMM); - free(powerpc_pcpu[cpu]->pc_ppcpmcs, M_PMC); - free(powerpc_pcpu[cpu], M_PMC); - - return 0; + return (powerpc_pcpu_fini(md, cpu)); } static int e500_allocate_pmc(int cpu, int ri, struct pmc *pm, const struct pmc_op_pmcallocate *a) { enum pmc_event pe; uint32_t caps, config, counter; struct e500_event_code_map *ev; uint16_t vers; uint8_t pe_cpu_mask; KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); KASSERT(ri >= 0 && ri < E500_MAX_PMCS, ("[powerpc,%d] illegal row index %d", __LINE__, ri)); caps = a->pm_caps; pe = a->pm_ev; config = PMLCax_FCS | PMLCax_FCU | PMLCax_FCM1 | PMLCax_FCM1; if (pe < PMC_EV_E500_FIRST || pe > PMC_EV_E500_LAST) return (EINVAL); ev = &e500_event_codes[pe-PMC_EV_E500_FIRST]; if (ev->pe_code == 0) return (EINVAL); vers = mfpvr() >> 16; switch (vers) { case FSL_E500v1: pe_cpu_mask = ev->pe_cpu & PMC_PPC_E500V1; break; case FSL_E500v2: pe_cpu_mask = ev->pe_cpu & PMC_PPC_E500V2; break; case FSL_E500mc: case FSL_E5500: pe_cpu_mask = ev->pe_cpu & PMC_PPC_E500MC; break; } if (pe_cpu_mask == 0) return (EINVAL); config |= PMLCax_EVENT(ev->pe_code); counter = ev->pe_counter_mask; if ((counter & (1 << ri)) == 0) return (EINVAL); if (caps & PMC_CAP_SYSTEM) config &= ~PMLCax_FCS; if (caps & PMC_CAP_USER) config &= ~PMLCax_FCU; if ((caps & (PMC_CAP_USER | PMC_CAP_SYSTEM)) == 0) config &= ~(PMLCax_FCS|PMLCax_FCU); pm->pm_md.pm_powerpc.pm_powerpc_evsel = config; PMCDBG2(MDP,ALL,2,"powerpc-allocate ri=%d -> config=0x%x", ri, config); return 0; } -static int -e500_release_pmc(int cpu, int ri, struct pmc *pmc) +static void +e500_resume_pmc(bool ie) { - struct pmc_hw *phw; - - KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), - ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < E500_MAX_PMCS, - ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); - - phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; - KASSERT(phw->phw_pmc == NULL, - ("[powerpc,%d] PHW pmc %p non-NULL", __LINE__, phw->phw_pmc)); - - return 0; -} - -static int -e500_intr(struct trapframe *tf) -{ - int i, error, retval, cpu; - uint32_t config; - struct pmc *pm; - struct powerpc_cpu *pac; - - cpu = curcpu; - KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), - ("[powerpc,%d] out of range CPU %d", __LINE__, cpu)); - - PMCDBG3(MDP,INT,1, "cpu=%d tf=%p um=%d", cpu, (void *) tf, - TRAPF_USERMODE(tf)); - - retval = 0; - - pac = powerpc_pcpu[cpu]; - - config = mfpmr(PMR_PMGC0) & ~PMGC_FAC; - - /* - * look for all PMCs that have interrupted: - * - look for a running, sampling PMC which has overflowed - * and which has a valid 'struct pmc' association - * - * If found, we call a helper to process the interrupt. - */ - - for (i = 0; i < E500_MAX_PMCS; i++) { - if ((pm = pac->pc_ppcpmcs[i].phw_pmc) == NULL || - !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) { - continue; - } - - if (!E500_PMC_HAS_OVERFLOWED(i)) - continue; - - retval = 1; /* Found an interrupting PMC. */ - - if (pm->pm_state != PMC_STATE_RUNNING) - continue; - - /* Stop the counter if logging fails. */ - error = pmc_process_interrupt(PMC_HR, pm, tf); - if (error != 0) - e500_stop_pmc(cpu, i); - - /* reload count. */ - e500_write_pmc(cpu, i, pm->pm_sc.pm_reloadcount); - } - - if (retval) - counter_u64_add(pmc_stats.pm_intr_processed, 1); - else - counter_u64_add(pmc_stats.pm_intr_ignored, 1); - /* Re-enable PERF exceptions. */ - if (retval) - mtpmr(PMR_PMGC0, config | PMGC_PMIE); - - return (retval); + if (ie) + mtpmr(PMR_PMGC0, (mfpmr(PMR_PMGC0) & ~PMGC_FAC) | PMGC_PMIE); } int pmc_e500_initialize(struct pmc_mdep *pmc_mdep) { struct pmc_classdep *pcd; pmc_mdep->pmd_cputype = PMC_CPU_PPC_E500; pcd = &pmc_mdep->pmd_classdep[PMC_MDEP_CLASS_INDEX_POWERPC]; pcd->pcd_caps = POWERPC_PMC_CAPS; pcd->pcd_class = PMC_CLASS_E500; pcd->pcd_num = E500_MAX_PMCS; pcd->pcd_ri = pmc_mdep->pmd_npmc; pcd->pcd_width = 32; pcd->pcd_allocate_pmc = e500_allocate_pmc; - pcd->pcd_config_pmc = e500_config_pmc; + pcd->pcd_config_pmc = powerpc_config_pmc; pcd->pcd_pcpu_fini = e500_pcpu_fini; pcd->pcd_pcpu_init = e500_pcpu_init; pcd->pcd_describe = powerpc_describe; pcd->pcd_get_config = powerpc_get_config; - pcd->pcd_read_pmc = e500_read_pmc; - pcd->pcd_release_pmc = e500_release_pmc; - pcd->pcd_start_pmc = e500_start_pmc; - pcd->pcd_stop_pmc = e500_stop_pmc; - pcd->pcd_write_pmc = e500_write_pmc; + pcd->pcd_read_pmc = powerpc_read_pmc; + pcd->pcd_release_pmc = powerpc_release_pmc; + pcd->pcd_start_pmc = powerpc_start_pmc; + pcd->pcd_stop_pmc = powerpc_stop_pmc; + pcd->pcd_write_pmc = powerpc_write_pmc; pmc_mdep->pmd_npmc += E500_MAX_PMCS; - pmc_mdep->pmd_intr = e500_intr; + pmc_mdep->pmd_intr = powerpc_pmc_intr; + + ppc_max_pmcs = E500_MAX_PMCS; + + powerpc_set_pmc = e500_set_pmc; + powerpc_pmcn_read = e500_pmcn_read; + powerpc_pmcn_write = e500_pmcn_write; + powerpc_resume_pmc = e500_resume_pmc; return (0); } Index: head/sys/dev/hwpmc/hwpmc_mpc7xxx.c =================================================================== --- head/sys/dev/hwpmc/hwpmc_mpc7xxx.c (revision 367389) +++ head/sys/dev/hwpmc/hwpmc_mpc7xxx.c (revision 367390) @@ -1,758 +1,481 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2011 Justin Hibbits * Copyright (c) 2005, Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include "hwpmc_powerpc.h" -#define POWERPC_PMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_USER | \ - PMC_CAP_SYSTEM | PMC_CAP_EDGE | \ - PMC_CAP_THRESHOLD | PMC_CAP_READ | \ - PMC_CAP_WRITE | PMC_CAP_INVERT | \ - PMC_CAP_QUALIFIER) - #define PPC_SET_PMC1SEL(r, x) ((r & ~(SPR_MMCR0_74XX_PMC1SEL(0x3f))) | \ SPR_MMCR0_74XX_PMC1SEL(x)) #define PPC_SET_PMC2SEL(r, x) ((r & ~(SPR_MMCR0_74XX_PMC2SEL(0x3f))) | \ SPR_MMCR0_74XX_PMC2SEL(x)) #define PPC_SET_PMC3SEL(r, x) ((r & ~(SPR_MMCR1_PMC3SEL(0x1f))) | SPR_MMCR1_PMC3SEL(x)) #define PPC_SET_PMC4SEL(r, x) ((r & ~(SPR_MMCR1_PMC4SEL(0x1f))) | SPR_MMCR1_PMC4SEL(x)) #define PPC_SET_PMC5SEL(r, x) ((r & ~(SPR_MMCR1_PMC5SEL(0x1f))) | SPR_MMCR1_PMC5SEL(x)) #define PPC_SET_PMC6SEL(r, x) ((r & ~(SPR_MMCR1_74XX_PMC6SEL(0x3f))) | \ SPR_MMCR1_74XX_PMC6SEL(x)) /* Change this when we support more than just the 7450. */ #define MPC7XXX_MAX_PMCS 6 -#define MPC7XXX_PMC_HAS_OVERFLOWED(x) (mpc7xxx_pmcn_read(x) & (0x1 << 31)) - /* * Things to improve on this: * - It stops (clears to 0) the PMC and resets it at every context switch * currently. */ /* * This should work for every 32-bit PowerPC implementation I know of (G3 and G4 * specifically). */ -struct mpc7xxx_event_code_map { - enum pmc_event pe_ev; /* enum value */ - uint8_t pe_counter_mask; /* Which counter this can be counted in. */ - uint8_t pe_code; /* numeric code */ -}; - -#define PPC_PMC_MASK1 0 -#define PPC_PMC_MASK2 1 -#define PPC_PMC_MASK3 2 -#define PPC_PMC_MASK4 3 -#define PPC_PMC_MASK5 4 -#define PPC_PMC_MASK6 5 #define PPC_PMC_MASK_ALL 0x3f #define PMC_POWERPC_EVENT(id, mask, number) \ - { .pe_ev = PMC_EV_PPC7450_##id, .pe_counter_mask = mask, .pe_code = number } + { .pe_event = PMC_EV_PPC7450_##id, .pe_flags = mask, .pe_code = number } -static struct mpc7xxx_event_code_map mpc7xxx_event_codes[] = { +static struct pmc_ppc_event mpc7xxx_event_codes[] = { PMC_POWERPC_EVENT(CYCLE,PPC_PMC_MASK_ALL, 1), PMC_POWERPC_EVENT(INSTR_COMPLETED, 0x0f, 2), PMC_POWERPC_EVENT(TLB_BIT_TRANSITIONS, 0x0f, 3), PMC_POWERPC_EVENT(INSTR_DISPATCHED, 0x0f, 4), PMC_POWERPC_EVENT(PMON_EXCEPT, 0x0f, 5), PMC_POWERPC_EVENT(PMON_SIG, 0x0f, 7), PMC_POWERPC_EVENT(VPU_INSTR_COMPLETED, 0x03, 8), PMC_POWERPC_EVENT(VFPU_INSTR_COMPLETED, 0x03, 9), PMC_POWERPC_EVENT(VIU1_INSTR_COMPLETED, 0x03, 10), PMC_POWERPC_EVENT(VIU2_INSTR_COMPLETED, 0x03, 11), PMC_POWERPC_EVENT(MTVSCR_INSTR_COMPLETED, 0x03, 12), PMC_POWERPC_EVENT(MTVRSAVE_INSTR_COMPLETED, 0x03, 13), PMC_POWERPC_EVENT(VPU_INSTR_WAIT_CYCLES, 0x03, 14), PMC_POWERPC_EVENT(VFPU_INSTR_WAIT_CYCLES, 0x03, 15), PMC_POWERPC_EVENT(VIU1_INSTR_WAIT_CYCLES, 0x03, 16), PMC_POWERPC_EVENT(VIU2_INSTR_WAIT_CYCLES, 0x03, 17), PMC_POWERPC_EVENT(MFVSCR_SYNC_CYCLES, 0x03, 18), PMC_POWERPC_EVENT(VSCR_SAT_SET, 0x03, 19), PMC_POWERPC_EVENT(STORE_INSTR_COMPLETED, 0x03, 20), PMC_POWERPC_EVENT(L1_INSTR_CACHE_MISSES, 0x03, 21), PMC_POWERPC_EVENT(L1_DATA_SNOOPS, 0x03, 22), PMC_POWERPC_EVENT(UNRESOLVED_BRANCHES, 0x01, 23), PMC_POWERPC_EVENT(SPEC_BUFFER_CYCLES, 0x01, 24), PMC_POWERPC_EVENT(BRANCH_UNIT_STALL_CYCLES, 0x01, 25), PMC_POWERPC_EVENT(TRUE_BRANCH_TARGET_HITS, 0x01, 26), PMC_POWERPC_EVENT(BRANCH_LINK_STAC_PREDICTED, 0x01, 27), PMC_POWERPC_EVENT(GPR_ISSUE_QUEUE_DISPATCHES, 0x01, 28), PMC_POWERPC_EVENT(CYCLES_THREE_INSTR_DISPATCHED, 0x01, 29), PMC_POWERPC_EVENT(THRESHOLD_INSTR_QUEUE_ENTRIES_CYCLES, 0x01, 30), PMC_POWERPC_EVENT(THRESHOLD_VEC_INSTR_QUEUE_ENTRIES_CYCLES, 0x01, 31), PMC_POWERPC_EVENT(CYCLES_NO_COMPLETED_INSTRS, 0x01, 32), PMC_POWERPC_EVENT(IU2_INSTR_COMPLETED, 0x01, 33), PMC_POWERPC_EVENT(BRANCHES_COMPLETED, 0x01, 34), PMC_POWERPC_EVENT(EIEIO_INSTR_COMPLETED, 0x01, 35), PMC_POWERPC_EVENT(MTSPR_INSTR_COMPLETED, 0x01, 36), PMC_POWERPC_EVENT(SC_INSTR_COMPLETED, 0x01, 37), PMC_POWERPC_EVENT(LS_LM_COMPLETED, 0x01, 38), PMC_POWERPC_EVENT(ITLB_HW_TABLE_SEARCH_CYCLES, 0x01, 39), PMC_POWERPC_EVENT(DTLB_HW_SEARCH_CYCLES_OVER_THRESHOLD, 0x01, 40), PMC_POWERPC_EVENT(L1_INSTR_CACHE_ACCESSES, 0x01, 41), PMC_POWERPC_EVENT(INSTR_BKPT_MATCHES, 0x01, 42), PMC_POWERPC_EVENT(L1_DATA_CACHE_LOAD_MISS_CYCLES_OVER_THRESHOLD, 0x01, 43), PMC_POWERPC_EVENT(L1_DATA_SNOOP_HIT_ON_MODIFIED, 0x01, 44), PMC_POWERPC_EVENT(LOAD_MISS_ALIAS, 0x01, 45), PMC_POWERPC_EVENT(LOAD_MISS_ALIAS_ON_TOUCH, 0x01, 46), PMC_POWERPC_EVENT(TOUCH_ALIAS, 0x01, 47), PMC_POWERPC_EVENT(L1_DATA_SNOOP_HIT_CASTOUT_QUEUE, 0x01, 48), PMC_POWERPC_EVENT(L1_DATA_SNOOP_HIT_CASTOUT, 0x01, 49), PMC_POWERPC_EVENT(L1_DATA_SNOOP_HITS, 0x01, 50), PMC_POWERPC_EVENT(WRITE_THROUGH_STORES, 0x01, 51), PMC_POWERPC_EVENT(CACHE_INHIBITED_STORES, 0x01, 52), PMC_POWERPC_EVENT(L1_DATA_LOAD_HIT, 0x01, 53), PMC_POWERPC_EVENT(L1_DATA_TOUCH_HIT, 0x01, 54), PMC_POWERPC_EVENT(L1_DATA_STORE_HIT, 0x01, 55), PMC_POWERPC_EVENT(L1_DATA_TOTAL_HITS, 0x01, 56), PMC_POWERPC_EVENT(DST_INSTR_DISPATCHED, 0x01, 57), PMC_POWERPC_EVENT(REFRESHED_DSTS, 0x01, 58), PMC_POWERPC_EVENT(SUCCESSFUL_DST_TABLE_SEARCHES, 0x01, 59), PMC_POWERPC_EVENT(DSS_INSTR_COMPLETED, 0x01, 60), PMC_POWERPC_EVENT(DST_STREAM_0_CACHE_LINE_FETCHES, 0x01, 61), PMC_POWERPC_EVENT(VTQ_SUSPENDS_DUE_TO_CTX_CHANGE, 0x01, 62), PMC_POWERPC_EVENT(VTQ_LINE_FETCH_HIT, 0x01, 63), PMC_POWERPC_EVENT(VEC_LOAD_INSTR_COMPLETED, 0x01, 64), PMC_POWERPC_EVENT(FP_STORE_INSTR_COMPLETED_IN_LSU, 0x01, 65), PMC_POWERPC_EVENT(FPU_RENORMALIZATION, 0x01, 66), PMC_POWERPC_EVENT(FPU_DENORMALIZATION, 0x01, 67), PMC_POWERPC_EVENT(FP_STORE_CAUSES_STALL_IN_LSU, 0x01, 68), PMC_POWERPC_EVENT(LD_ST_TRUE_ALIAS_STALL, 0x01, 70), PMC_POWERPC_EVENT(LSU_INDEXED_ALIAS_STALL, 0x01, 71), PMC_POWERPC_EVENT(LSU_ALIAS_VS_FSQ_WB0_WB1, 0x01, 72), PMC_POWERPC_EVENT(LSU_ALIAS_VS_CSQ, 0x01, 73), PMC_POWERPC_EVENT(LSU_LOAD_HIT_LINE_ALIAS_VS_CSQ0, 0x01, 74), PMC_POWERPC_EVENT(LSU_LOAD_MISS_LINE_ALIAS_VS_CSQ0, 0x01, 75), PMC_POWERPC_EVENT(LSU_TOUCH_LINE_ALIAS_VS_FSQ_WB0_WB1, 0x01, 76), PMC_POWERPC_EVENT(LSU_TOUCH_ALIAS_VS_CSQ, 0x01, 77), PMC_POWERPC_EVENT(LSU_LMQ_FULL_STALL, 0x01, 78), PMC_POWERPC_EVENT(FP_LOAD_INSTR_COMPLETED_IN_LSU, 0x01, 79), PMC_POWERPC_EVENT(FP_LOAD_SINGLE_INSTR_COMPLETED_IN_LSU, 0x01, 80), PMC_POWERPC_EVENT(FP_LOAD_DOUBLE_COMPLETED_IN_LSU, 0x01, 81), PMC_POWERPC_EVENT(LSU_RA_LATCH_STALL, 0x01, 82), PMC_POWERPC_EVENT(LSU_LOAD_VS_STORE_QUEUE_ALIAS_STALL, 0x01, 83), PMC_POWERPC_EVENT(LSU_LMQ_INDEX_ALIAS, 0x01, 84), PMC_POWERPC_EVENT(LSU_STORE_QUEUE_INDEX_ALIAS, 0x01, 85), PMC_POWERPC_EVENT(LSU_CSQ_FORWARDING, 0x01, 86), PMC_POWERPC_EVENT(LSU_MISALIGNED_LOAD_FINISH, 0x01, 87), PMC_POWERPC_EVENT(LSU_MISALIGN_STORE_COMPLETED, 0x01, 88), PMC_POWERPC_EVENT(LSU_MISALIGN_STALL, 0x01, 89), PMC_POWERPC_EVENT(FP_ONE_QUARTER_FPSCR_RENAMES_BUSY, 0x01, 90), PMC_POWERPC_EVENT(FP_ONE_HALF_FPSCR_RENAMES_BUSY, 0x01, 91), PMC_POWERPC_EVENT(FP_THREE_QUARTERS_FPSCR_RENAMES_BUSY, 0x01, 92), PMC_POWERPC_EVENT(FP_ALL_FPSCR_RENAMES_BUSY, 0x01, 93), PMC_POWERPC_EVENT(FP_DENORMALIZED_RESULT, 0x01, 94), PMC_POWERPC_EVENT(L1_DATA_TOTAL_MISSES, 0x02, 23), PMC_POWERPC_EVENT(DISPATCHES_TO_FPR_ISSUE_QUEUE, 0x02, 24), PMC_POWERPC_EVENT(LSU_INSTR_COMPLETED, 0x02, 25), PMC_POWERPC_EVENT(LOAD_INSTR_COMPLETED, 0x02, 26), PMC_POWERPC_EVENT(SS_SM_INSTR_COMPLETED, 0x02, 27), PMC_POWERPC_EVENT(TLBIE_INSTR_COMPLETED, 0x02, 28), PMC_POWERPC_EVENT(LWARX_INSTR_COMPLETED, 0x02, 29), PMC_POWERPC_EVENT(MFSPR_INSTR_COMPLETED, 0x02, 30), PMC_POWERPC_EVENT(REFETCH_SERIALIZATION, 0x02, 31), PMC_POWERPC_EVENT(COMPLETION_QUEUE_ENTRIES_OVER_THRESHOLD, 0x02, 32), PMC_POWERPC_EVENT(CYCLES_ONE_INSTR_DISPATCHED, 0x02, 33), PMC_POWERPC_EVENT(CYCLES_TWO_INSTR_COMPLETED, 0x02, 34), PMC_POWERPC_EVENT(ITLB_NON_SPECULATIVE_MISSES, 0x02, 35), PMC_POWERPC_EVENT(CYCLES_WAITING_FROM_L1_INSTR_CACHE_MISS, 0x02, 36), PMC_POWERPC_EVENT(L1_DATA_LOAD_ACCESS_MISS, 0x02, 37), PMC_POWERPC_EVENT(L1_DATA_TOUCH_MISS, 0x02, 38), PMC_POWERPC_EVENT(L1_DATA_STORE_MISS, 0x02, 39), PMC_POWERPC_EVENT(L1_DATA_TOUCH_MISS_CYCLES, 0x02, 40), PMC_POWERPC_EVENT(L1_DATA_CYCLES_USED, 0x02, 41), PMC_POWERPC_EVENT(DST_STREAM_1_CACHE_LINE_FETCHES, 0x02, 42), PMC_POWERPC_EVENT(VTQ_STREAM_CANCELED_PREMATURELY, 0x02, 43), PMC_POWERPC_EVENT(VTQ_RESUMES_DUE_TO_CTX_CHANGE, 0x02, 44), PMC_POWERPC_EVENT(VTQ_LINE_FETCH_MISS, 0x02, 45), PMC_POWERPC_EVENT(VTQ_LINE_FETCH, 0x02, 46), PMC_POWERPC_EVENT(TLBIE_SNOOPS, 0x02, 47), PMC_POWERPC_EVENT(L1_INSTR_CACHE_RELOADS, 0x02, 48), PMC_POWERPC_EVENT(L1_DATA_CACHE_RELOADS, 0x02, 49), PMC_POWERPC_EVENT(L1_DATA_CACHE_CASTOUTS_TO_L2, 0x02, 50), PMC_POWERPC_EVENT(STORE_MERGE_GATHER, 0x02, 51), PMC_POWERPC_EVENT(CACHEABLE_STORE_MERGE_TO_32_BYTES, 0x02, 52), PMC_POWERPC_EVENT(DATA_BKPT_MATCHES, 0x02, 53), PMC_POWERPC_EVENT(FALL_THROUGH_BRANCHES_PROCESSED, 0x02, 54), PMC_POWERPC_EVENT(FIRST_SPECULATIVE_BRANCH_BUFFER_RESOLVED_CORRECTLY, 0x02, 55), PMC_POWERPC_EVENT(SECOND_SPECULATION_BUFFER_ACTIVE, 0x02, 56), PMC_POWERPC_EVENT(BPU_STALL_ON_LR_DEPENDENCY, 0x02, 57), PMC_POWERPC_EVENT(BTIC_MISS, 0x02, 58), PMC_POWERPC_EVENT(BRANCH_LINK_STACK_CORRECTLY_RESOLVED, 0x02, 59), PMC_POWERPC_EVENT(FPR_ISSUE_STALLED, 0x02, 60), PMC_POWERPC_EVENT(SWITCHES_BETWEEN_PRIV_USER, 0x02, 61), PMC_POWERPC_EVENT(LSU_COMPLETES_FP_STORE_SINGLE, 0x02, 62), PMC_POWERPC_EVENT(CYCLES_TWO_INSTR_COMPLETED, 0x04, 8), PMC_POWERPC_EVENT(CYCLES_ONE_INSTR_DISPATCHED, 0x04, 9), PMC_POWERPC_EVENT(VR_ISSUE_QUEUE_DISPATCHES, 0x04, 10), PMC_POWERPC_EVENT(VR_STALLS, 0x04, 11), PMC_POWERPC_EVENT(GPR_RENAME_BUFFER_ENTRIES_OVER_THRESHOLD, 0x04, 12), PMC_POWERPC_EVENT(FPR_ISSUE_QUEUE_ENTRIES, 0x04, 13), PMC_POWERPC_EVENT(FPU_INSTR_COMPLETED, 0x04, 14), PMC_POWERPC_EVENT(STWCX_INSTR_COMPLETED, 0x04, 15), PMC_POWERPC_EVENT(LS_LM_INSTR_PIECES, 0x04, 16), PMC_POWERPC_EVENT(ITLB_HW_SEARCH_CYCLES_OVER_THRESHOLD, 0x04, 17), PMC_POWERPC_EVENT(DTLB_MISSES, 0x04, 18), PMC_POWERPC_EVENT(CANCELLED_L1_INSTR_CACHE_MISSES, 0x04, 19), PMC_POWERPC_EVENT(L1_DATA_CACHE_OP_HIT, 0x04, 20), PMC_POWERPC_EVENT(L1_DATA_LOAD_MISS_CYCLES, 0x04, 21), PMC_POWERPC_EVENT(L1_DATA_PUSHES, 0x04, 22), PMC_POWERPC_EVENT(L1_DATA_TOTAL_MISS, 0x04, 23), PMC_POWERPC_EVENT(VT2_FETCHES, 0x04, 24), PMC_POWERPC_EVENT(TAKEN_BRANCHES_PROCESSED, 0x04, 25), PMC_POWERPC_EVENT(BRANCH_FLUSHES, 0x04, 26), PMC_POWERPC_EVENT(SECOND_SPECULATIVE_BRANCH_BUFFER_RESOLVED_CORRECTLY, 0x04, 27), PMC_POWERPC_EVENT(THIRD_SPECULATION_BUFFER_ACTIVE, 0x04, 28), PMC_POWERPC_EVENT(BRANCH_UNIT_STALL_ON_CTR_DEPENDENCY, 0x04, 29), PMC_POWERPC_EVENT(FAST_BTIC_HIT, 0x04, 30), PMC_POWERPC_EVENT(BRANCH_LINK_STACK_MISPREDICTED, 0x04, 31), PMC_POWERPC_EVENT(CYCLES_THREE_INSTR_COMPLETED, 0x08, 14), PMC_POWERPC_EVENT(CYCLES_NO_INSTR_DISPATCHED, 0x08, 15), PMC_POWERPC_EVENT(GPR_ISSUE_QUEUE_ENTRIES_OVER_THRESHOLD, 0x08, 16), PMC_POWERPC_EVENT(GPR_ISSUE_QUEUE_STALLED, 0x08, 17), PMC_POWERPC_EVENT(IU1_INSTR_COMPLETED, 0x08, 18), PMC_POWERPC_EVENT(DSSALL_INSTR_COMPLETED, 0x08, 19), PMC_POWERPC_EVENT(TLBSYNC_INSTR_COMPLETED, 0x08, 20), PMC_POWERPC_EVENT(SYNC_INSTR_COMPLETED, 0x08, 21), PMC_POWERPC_EVENT(SS_SM_INSTR_PIECES, 0x08, 22), PMC_POWERPC_EVENT(DTLB_HW_SEARCH_CYCLES, 0x08, 23), PMC_POWERPC_EVENT(SNOOP_RETRIES, 0x08, 24), PMC_POWERPC_EVENT(SUCCESSFUL_STWCX, 0x08, 25), PMC_POWERPC_EVENT(DST_STREAM_3_CACHE_LINE_FETCHES, 0x08, 26), PMC_POWERPC_EVENT(THIRD_SPECULATIVE_BRANCH_BUFFER_RESOLVED_CORRECTLY, 0x08, 27), PMC_POWERPC_EVENT(MISPREDICTED_BRANCHES, 0x08, 28), PMC_POWERPC_EVENT(FOLDED_BRANCHES, 0x08, 29), PMC_POWERPC_EVENT(FP_STORE_DOUBLE_COMPLETES_IN_LSU, 0x08, 30), PMC_POWERPC_EVENT(L2_CACHE_HITS, 0x30, 2), PMC_POWERPC_EVENT(L3_CACHE_HITS, 0x30, 3), PMC_POWERPC_EVENT(L2_INSTR_CACHE_MISSES, 0x30, 4), PMC_POWERPC_EVENT(L3_INSTR_CACHE_MISSES, 0x30, 5), PMC_POWERPC_EVENT(L2_DATA_CACHE_MISSES, 0x30, 6), PMC_POWERPC_EVENT(L3_DATA_CACHE_MISSES, 0x30, 7), PMC_POWERPC_EVENT(L2_LOAD_HITS, 0x10, 8), PMC_POWERPC_EVENT(L2_STORE_HITS, 0x10, 9), PMC_POWERPC_EVENT(L3_LOAD_HITS, 0x10, 10), PMC_POWERPC_EVENT(L3_STORE_HITS, 0x10, 11), PMC_POWERPC_EVENT(L2_TOUCH_HITS, 0x30, 13), PMC_POWERPC_EVENT(L3_TOUCH_HITS, 0x30, 14), PMC_POWERPC_EVENT(SNOOP_RETRIES, 0x30, 15), PMC_POWERPC_EVENT(SNOOP_MODIFIED, 0x10, 16), PMC_POWERPC_EVENT(SNOOP_VALID, 0x10, 17), PMC_POWERPC_EVENT(INTERVENTION, 0x30, 18), PMC_POWERPC_EVENT(L2_CACHE_MISSES, 0x10, 19), PMC_POWERPC_EVENT(L3_CACHE_MISSES, 0x10, 20), PMC_POWERPC_EVENT(L2_CACHE_CASTOUTS, 0x20, 8), PMC_POWERPC_EVENT(L3_CACHE_CASTOUTS, 0x20, 9), PMC_POWERPC_EVENT(L2SQ_FULL_CYCLES, 0x20, 10), PMC_POWERPC_EVENT(L3SQ_FULL_CYCLES, 0x20, 11), PMC_POWERPC_EVENT(RAQ_FULL_CYCLES, 0x20, 16), PMC_POWERPC_EVENT(WAQ_FULL_CYCLES, 0x20, 17), PMC_POWERPC_EVENT(L1_EXTERNAL_INTERVENTIONS, 0x20, 19), PMC_POWERPC_EVENT(L2_EXTERNAL_INTERVENTIONS, 0x20, 20), PMC_POWERPC_EVENT(L3_EXTERNAL_INTERVENTIONS, 0x20, 21), PMC_POWERPC_EVENT(EXTERNAL_INTERVENTIONS, 0x20, 22), PMC_POWERPC_EVENT(EXTERNAL_PUSHES, 0x20, 23), PMC_POWERPC_EVENT(EXTERNAL_SNOOP_RETRY, 0x20, 24), PMC_POWERPC_EVENT(DTQ_FULL_CYCLES, 0x20, 25), PMC_POWERPC_EVENT(BUS_RETRY, 0x20, 26), PMC_POWERPC_EVENT(L2_VALID_REQUEST, 0x20, 27), PMC_POWERPC_EVENT(BORDQ_FULL, 0x20, 28), PMC_POWERPC_EVENT(BUS_TAS_FOR_READS, 0x20, 42), PMC_POWERPC_EVENT(BUS_TAS_FOR_WRITES, 0x20, 43), PMC_POWERPC_EVENT(BUS_READS_NOT_RETRIED, 0x20, 44), PMC_POWERPC_EVENT(BUS_WRITES_NOT_RETRIED, 0x20, 45), PMC_POWERPC_EVENT(BUS_READS_WRITES_NOT_RETRIED, 0x20, 46), PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_L1_RETRY, 0x20, 47), PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_PREVIOUS_ADJACENT, 0x20, 48), PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_COLLISION, 0x20, 49), PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_INTERVENTION_ORDERING, 0x20, 50), PMC_POWERPC_EVENT(SNOOP_REQUESTS, 0x20, 51), PMC_POWERPC_EVENT(PREFETCH_ENGINE_REQUEST, 0x20, 52), PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_LOAD, 0x20, 53), PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_STORE, 0x20, 54), PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_INSTR_FETCH, 0x20, 55), PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_LOAD_STORE_INSTR_FETCH, 0x20, 56), PMC_POWERPC_EVENT(PREFETCH_ENGINE_FULL, 0x20, 57) }; +static size_t mpc7xxx_event_codes_size = nitems(mpc7xxx_event_codes); static pmc_value_t mpc7xxx_pmcn_read(unsigned int pmc) { switch (pmc) { - case 0: - return mfspr(SPR_PMC1_74XX); - break; - case 1: - return mfspr(SPR_PMC2_74XX); - break; - case 2: - return mfspr(SPR_PMC3_74XX); - break; - case 3: - return mfspr(SPR_PMC4_74XX); - break; - case 4: - return mfspr(SPR_PMC5_74XX); - break; - case 5: - return mfspr(SPR_PMC6_74XX); - default: - panic("Invalid PMC number: %d\n", pmc); + case 0: + return (mfspr(SPR_PMC1_74XX)); + case 1: + return (mfspr(SPR_PMC2_74XX)); + case 2: + return (mfspr(SPR_PMC3_74XX)); + case 3: + return (mfspr(SPR_PMC4_74XX)); + case 4: + return (mfspr(SPR_PMC5_74XX)); + case 5: + return (mfspr(SPR_PMC6_74XX)); + default: + panic("Invalid PMC number: %d\n", pmc); } } static void mpc7xxx_pmcn_write(unsigned int pmc, uint32_t val) { switch (pmc) { - case 0: - mtspr(SPR_PMC1_74XX, val); - break; - case 1: - mtspr(SPR_PMC2_74XX, val); - break; - case 2: - mtspr(SPR_PMC3_74XX, val); - break; - case 3: - mtspr(SPR_PMC4_74XX, val); - break; - case 4: - mtspr(SPR_PMC5_74XX, val); - break; - case 5: - mtspr(SPR_PMC6_74XX, val); - break; - default: - panic("Invalid PMC number: %d\n", pmc); - } -} - -static int -mpc7xxx_read_pmc(int cpu, int ri, pmc_value_t *v) -{ - struct pmc *pm; - pmc_value_t tmp; - - KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), - ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < MPC7XXX_MAX_PMCS, - ("[powerpc,%d] illegal row index %d", __LINE__, ri)); - - pm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc; - KASSERT(pm, - ("[core,%d] cpu %d ri %d pmc not configured", __LINE__, cpu, - ri)); - - tmp = mpc7xxx_pmcn_read(ri); - PMCDBG2(MDP,REA,2,"ppc-read id=%d -> %jd", ri, tmp); - if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) - *v = POWERPC_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp); - else - *v = tmp; - - return 0; -} - -static int -mpc7xxx_write_pmc(int cpu, int ri, pmc_value_t v) -{ - struct pmc *pm; - - KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), - ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < MPC7XXX_MAX_PMCS, - ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); - - pm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc; - - if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) - v = POWERPC_RELOAD_COUNT_TO_PERFCTR_VALUE(v); - - PMCDBG3(MDP,WRI,1,"powerpc-write cpu=%d ri=%d v=%jx", cpu, ri, v); - - mpc7xxx_pmcn_write(ri, v); - - return 0; -} - -static int -mpc7xxx_config_pmc(int cpu, int ri, struct pmc *pm) -{ - struct pmc_hw *phw; - - PMCDBG3(MDP,CFG,1, "cpu=%d ri=%d pm=%p", cpu, ri, pm); - - KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), - ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < MPC7XXX_MAX_PMCS, - ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); - - phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; - - KASSERT(pm == NULL || phw->phw_pmc == NULL, - ("[powerpc,%d] pm=%p phw->pm=%p hwpmc not unconfigured", - __LINE__, pm, phw->phw_pmc)); - - phw->phw_pmc = pm; - - return 0; -} - -static int -mpc7xxx_start_pmc(int cpu, int ri) -{ - uint32_t config; - struct pmc *pm; - struct pmc_hw *phw; - register_t pmc_mmcr; - - phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; - pm = phw->phw_pmc; - config = pm->pm_md.pm_powerpc.pm_powerpc_evsel & ~POWERPC_PMC_ENABLE; - - /* Enable the PMC. */ - switch (ri) { case 0: - pmc_mmcr = mfspr(SPR_MMCR0_74XX); - pmc_mmcr = PPC_SET_PMC1SEL(pmc_mmcr, config); - mtspr(SPR_MMCR0_74XX, pmc_mmcr); + mtspr(SPR_PMC1_74XX, val); break; case 1: - pmc_mmcr = mfspr(SPR_MMCR0_74XX); - pmc_mmcr = PPC_SET_PMC2SEL(pmc_mmcr, config); - mtspr(SPR_MMCR0_74XX, pmc_mmcr); + mtspr(SPR_PMC2_74XX, val); break; case 2: - pmc_mmcr = mfspr(SPR_MMCR1_74XX); - pmc_mmcr = PPC_SET_PMC3SEL(pmc_mmcr, config); - mtspr(SPR_MMCR1_74XX, pmc_mmcr); + mtspr(SPR_PMC3_74XX, val); break; case 3: - pmc_mmcr = mfspr(SPR_MMCR0_74XX); - pmc_mmcr = PPC_SET_PMC4SEL(pmc_mmcr, config); - mtspr(SPR_MMCR0_74XX, pmc_mmcr); + mtspr(SPR_PMC4_74XX, val); break; case 4: - pmc_mmcr = mfspr(SPR_MMCR1_74XX); - pmc_mmcr = PPC_SET_PMC5SEL(pmc_mmcr, config); - mtspr(SPR_MMCR1_74XX, pmc_mmcr); + mtspr(SPR_PMC5_74XX, val); break; case 5: - pmc_mmcr = mfspr(SPR_MMCR1_74XX); - pmc_mmcr = PPC_SET_PMC6SEL(pmc_mmcr, config); - mtspr(SPR_MMCR1_74XX, pmc_mmcr); + mtspr(SPR_PMC6_74XX, val); break; default: - break; + panic("Invalid PMC number: %d\n", pmc); } - - /* The mask is inverted (enable is 1) compared to the flags in MMCR0, which - * are Freeze flags. - */ - config = ~pm->pm_md.pm_powerpc.pm_powerpc_evsel & POWERPC_PMC_ENABLE; - - pmc_mmcr = mfspr(SPR_MMCR0_74XX); - pmc_mmcr &= ~SPR_MMCR0_FC; - pmc_mmcr |= config; - mtspr(SPR_MMCR0_74XX, pmc_mmcr); - - return 0; } -static int -mpc7xxx_stop_pmc(int cpu, int ri) +static void +mpc7xxx_set_pmc(int cpu, int ri, int config) { - struct pmc *pm; - struct pmc_hw *phw; - register_t pmc_mmcr; + struct pmc *pm; + struct pmc_hw *phw; + register_t pmc_mmcr; + uint32_t config_mask; phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; pm = phw->phw_pmc; - - /* - * Disable the PMCs. + /* The mask is inverted (enable is 1) compared to the flags in + * MMCR0, which are Freeze flags. */ + config_mask = ~config & POWERPC_PMC_ENABLE; + config &= ~POWERPC_PMC_ENABLE; + + /* Enable/disable the PMC. */ switch (ri) { case 0: pmc_mmcr = mfspr(SPR_MMCR0_74XX); - pmc_mmcr = PPC_SET_PMC1SEL(pmc_mmcr, 0); + pmc_mmcr = PPC_SET_PMC1SEL(pmc_mmcr, config); mtspr(SPR_MMCR0_74XX, pmc_mmcr); break; case 1: pmc_mmcr = mfspr(SPR_MMCR0_74XX); - pmc_mmcr = PPC_SET_PMC2SEL(pmc_mmcr, 0); + pmc_mmcr = PPC_SET_PMC2SEL(pmc_mmcr, config); mtspr(SPR_MMCR0_74XX, pmc_mmcr); break; case 2: pmc_mmcr = mfspr(SPR_MMCR1_74XX); - pmc_mmcr = PPC_SET_PMC3SEL(pmc_mmcr, 0); + pmc_mmcr = PPC_SET_PMC3SEL(pmc_mmcr, config); mtspr(SPR_MMCR1_74XX, pmc_mmcr); break; case 3: pmc_mmcr = mfspr(SPR_MMCR0_74XX); - pmc_mmcr = PPC_SET_PMC4SEL(pmc_mmcr, 0); + pmc_mmcr = PPC_SET_PMC4SEL(pmc_mmcr, config); mtspr(SPR_MMCR0_74XX, pmc_mmcr); break; case 4: pmc_mmcr = mfspr(SPR_MMCR1_74XX); - pmc_mmcr = PPC_SET_PMC5SEL(pmc_mmcr, 0); + pmc_mmcr = PPC_SET_PMC5SEL(pmc_mmcr, config); mtspr(SPR_MMCR1_74XX, pmc_mmcr); break; case 5: pmc_mmcr = mfspr(SPR_MMCR1_74XX); - pmc_mmcr = PPC_SET_PMC6SEL(pmc_mmcr, 0); + pmc_mmcr = PPC_SET_PMC6SEL(pmc_mmcr, config); mtspr(SPR_MMCR1_74XX, pmc_mmcr); break; - default: - break; } - return 0; + + if (config != PMCN_NONE) { + pmc_mmcr = mfspr(SPR_MMCR0_74XX); + pmc_mmcr &= ~SPR_MMCR0_FC; + pmc_mmcr |= config; + mtspr(SPR_MMCR0_74XX, pmc_mmcr); + } } static int mpc7xxx_pcpu_init(struct pmc_mdep *md, int cpu) { - int first_ri, i; - struct pmc_cpu *pc; - struct powerpc_cpu *pac; - struct pmc_hw *phw; + powerpc_pcpu_init(md, cpu); - KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), - ("[powerpc,%d] wrong cpu number %d", __LINE__, cpu)); - PMCDBG1(MDP,INI,1,"powerpc-init cpu=%d", cpu); - - powerpc_pcpu[cpu] = pac = malloc(sizeof(struct powerpc_cpu), M_PMC, - M_WAITOK|M_ZERO); - pac->pc_ppcpmcs = malloc(sizeof(struct pmc_hw) * MPC7XXX_MAX_PMCS, - M_PMC, M_WAITOK|M_ZERO); - pac->pc_class = PMC_CLASS_PPC7450; - pc = pmc_pcpu[cpu]; - first_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_POWERPC].pcd_ri; - KASSERT(pc != NULL, ("[powerpc,%d] NULL per-cpu pointer", __LINE__)); - - for (i = 0, phw = pac->pc_ppcpmcs; i < MPC7XXX_MAX_PMCS; i++, phw++) { - phw->phw_state = PMC_PHW_FLAG_IS_ENABLED | - PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(i); - phw->phw_pmc = NULL; - pc->pc_hwpmcs[i + first_ri] = phw; - } - /* Clear the MMCRs, and set FC, to disable all PMCs. */ mtspr(SPR_MMCR0_74XX, SPR_MMCR0_FC | SPR_MMCR0_PMXE | SPR_MMCR0_FCECE | SPR_MMCR0_PMC1CE | SPR_MMCR0_PMCNCE); mtspr(SPR_MMCR1_74XX, 0); - return 0; + return (0); } static int mpc7xxx_pcpu_fini(struct pmc_mdep *md, int cpu) { uint32_t mmcr0 = mfspr(SPR_MMCR0_74XX); mtmsr(mfmsr() & ~PSL_PMM); mmcr0 |= SPR_MMCR0_FC; mtspr(SPR_MMCR0_74XX, mmcr0); - free(powerpc_pcpu[cpu]->pc_ppcpmcs, M_PMC); - free(powerpc_pcpu[cpu], M_PMC); - - return 0; + return (powerpc_pcpu_fini(md, cpu)); } -static int -mpc7xxx_allocate_pmc(int cpu, int ri, struct pmc *pm, - const struct pmc_op_pmcallocate *a) +static void +mpc7xxx_resume_pmc(bool ie) { - enum pmc_event pe; - uint32_t caps, config, counter; - int i; - - KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), - ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < MPC7XXX_MAX_PMCS, - ("[powerpc,%d] illegal row index %d", __LINE__, ri)); - - caps = a->pm_caps; - - pe = a->pm_ev; - for (i = 0; i < nitems(mpc7xxx_event_codes); i++) { - if (mpc7xxx_event_codes[i].pe_ev == pe) { - config = mpc7xxx_event_codes[i].pe_code; - counter = mpc7xxx_event_codes[i].pe_counter_mask; - break; - } - } - if (i == nitems(mpc7xxx_event_codes)) - return (EINVAL); - - if ((counter & (1 << ri)) == 0) - return (EINVAL); - - if (caps & PMC_CAP_SYSTEM) - config |= POWERPC_PMC_KERNEL_ENABLE; - if (caps & PMC_CAP_USER) - config |= POWERPC_PMC_USER_ENABLE; - if ((caps & (PMC_CAP_USER | PMC_CAP_SYSTEM)) == 0) - config |= POWERPC_PMC_ENABLE; - - pm->pm_md.pm_powerpc.pm_powerpc_evsel = config; - - PMCDBG2(MDP,ALL,2,"powerpc-allocate ri=%d -> config=0x%x", ri, config); - - return 0; -} - -static int -mpc7xxx_release_pmc(int cpu, int ri, struct pmc *pmc) -{ - struct pmc_hw *phw; - - KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), - ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < MPC7XXX_MAX_PMCS, - ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); - - phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; - KASSERT(phw->phw_pmc == NULL, - ("[powerpc,%d] PHW pmc %p non-NULL", __LINE__, phw->phw_pmc)); - - return 0; -} - -static int -mpc7xxx_intr(struct trapframe *tf) -{ - int i, error, retval, cpu; - uint32_t config; - struct pmc *pm; - struct powerpc_cpu *pac; - - cpu = curcpu; - KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), - ("[powerpc,%d] out of range CPU %d", __LINE__, cpu)); - - PMCDBG3(MDP,INT,1, "cpu=%d tf=%p um=%d", cpu, (void *) tf, - TRAPF_USERMODE(tf)); - - retval = 0; - - pac = powerpc_pcpu[cpu]; - - config = mfspr(SPR_MMCR0_74XX) & ~SPR_MMCR0_FC; - - /* - * look for all PMCs that have interrupted: - * - look for a running, sampling PMC which has overflowed - * and which has a valid 'struct pmc' association - * - * If found, we call a helper to process the interrupt. - */ - - for (i = 0; i < MPC7XXX_MAX_PMCS; i++) { - if ((pm = pac->pc_ppcpmcs[i].phw_pmc) == NULL || - !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) { - continue; - } - - if (!MPC7XXX_PMC_HAS_OVERFLOWED(i)) - continue; - - retval = 1; /* Found an interrupting PMC. */ - - if (pm->pm_state != PMC_STATE_RUNNING) - continue; - - /* Stop the counter if logging fails. */ - error = pmc_process_interrupt(PMC_HR, pm, tf); - if (error != 0) - mpc7xxx_stop_pmc(cpu, i); - - /* reload count. */ - mpc7xxx_write_pmc(cpu, i, pm->pm_sc.pm_reloadcount); - } - if (retval) - counter_u64_add(pmc_stats.pm_intr_processed, 1); - else - counter_u64_add(pmc_stats.pm_intr_ignored, 1); - /* Re-enable PERF exceptions. */ - if (retval) - mtspr(SPR_MMCR0_74XX, config | SPR_MMCR0_PMXE); - - return (retval); + if (ie) + mtspr(SPR_MMCR0_74XX, + (mfspr(SPR_MMCR0_74XX) & ~SPR_MMCR0_FC) | SPR_MMCR0_PMXE); } int pmc_mpc7xxx_initialize(struct pmc_mdep *pmc_mdep) { struct pmc_classdep *pcd; pmc_mdep->pmd_cputype = PMC_CPU_PPC_7450; pcd = &pmc_mdep->pmd_classdep[PMC_MDEP_CLASS_INDEX_POWERPC]; pcd->pcd_caps = POWERPC_PMC_CAPS; pcd->pcd_class = PMC_CLASS_PPC7450; pcd->pcd_num = MPC7XXX_MAX_PMCS; pcd->pcd_ri = pmc_mdep->pmd_npmc; pcd->pcd_width = 32; /* All PMCs, even in ppc970, are 32-bit */ - pcd->pcd_allocate_pmc = mpc7xxx_allocate_pmc; - pcd->pcd_config_pmc = mpc7xxx_config_pmc; + pcd->pcd_allocate_pmc = powerpc_allocate_pmc; + pcd->pcd_config_pmc = powerpc_config_pmc; pcd->pcd_pcpu_fini = mpc7xxx_pcpu_fini; pcd->pcd_pcpu_init = mpc7xxx_pcpu_init; pcd->pcd_describe = powerpc_describe; pcd->pcd_get_config = powerpc_get_config; - pcd->pcd_read_pmc = mpc7xxx_read_pmc; - pcd->pcd_release_pmc = mpc7xxx_release_pmc; - pcd->pcd_start_pmc = mpc7xxx_start_pmc; - pcd->pcd_stop_pmc = mpc7xxx_stop_pmc; - pcd->pcd_write_pmc = mpc7xxx_write_pmc; + pcd->pcd_read_pmc = powerpc_read_pmc; + pcd->pcd_release_pmc = powerpc_release_pmc; + pcd->pcd_start_pmc = powerpc_start_pmc; + pcd->pcd_stop_pmc = powerpc_stop_pmc; + pcd->pcd_write_pmc = powerpc_write_pmc; pmc_mdep->pmd_npmc += MPC7XXX_MAX_PMCS; - pmc_mdep->pmd_intr = mpc7xxx_intr; + pmc_mdep->pmd_intr = powerpc_pmc_intr; + + ppc_event_codes = mpc7xxx_event_codes; + ppc_event_codes_size = mpc7xxx_event_codes_size; + ppc_event_first = PMC_EV_PPC7450_FIRST; + ppc_event_last = PMC_EV_PPC7450_LAST; + ppc_max_pmcs = MPC7XXX_MAX_PMCS; + + powerpc_set_pmc = mpc7xxx_set_pmc; + powerpc_pmcn_read = mpc7xxx_pmcn_read; + powerpc_pmcn_write = mpc7xxx_pmcn_write; + powerpc_resume_pmc = mpc7xxx_resume_pmc; return (0); } Index: head/sys/dev/hwpmc/hwpmc_power8.c =================================================================== --- head/sys/dev/hwpmc/hwpmc_power8.c (nonexistent) +++ head/sys/dev/hwpmc/hwpmc_power8.c (revision 367390) @@ -0,0 +1,319 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2013 Justin Hibbits + * Copyright (c) 2020 Leandro Lupori + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include +#include + +#include "hwpmc_powerpc.h" + +#define POWER8_MAX_PMCS 6 + +static struct pmc_ppc_event power8_event_codes[] = { + {PMC_EV_POWER8_INSTR_COMPLETED, + .pe_flags = PMC_FLAG_PMC5, + .pe_code = 0x00 + }, + /* + * PMC1 can also count cycles, but as PMC6 can only count cycles + * it's better to always use it and leave PMC1 free to count + * other events. + */ + {PMC_EV_POWER8_CYCLES, + .pe_flags = PMC_FLAG_PMC6, + .pe_code = 0xf0 + }, + {PMC_EV_POWER8_CYCLES_WITH_INSTRS_COMPLETED, + .pe_flags = PMC_FLAG_PMC1, + .pe_code = 0xf2 + }, + {PMC_EV_POWER8_FPU_INSTR_COMPLETED, + .pe_flags = PMC_FLAG_PMC1, + .pe_code = 0xf4 + }, + {PMC_EV_POWER8_ERAT_INSTR_MISS, + .pe_flags = PMC_FLAG_PMC1, + .pe_code = 0xf6 + }, + {PMC_EV_POWER8_CYCLES_IDLE, + .pe_flags = PMC_FLAG_PMC1, + .pe_code = 0xf8 + }, + {PMC_EV_POWER8_CYCLES_WITH_ANY_THREAD_RUNNING, + .pe_flags = PMC_FLAG_PMC1, + .pe_code = 0xfa + }, + {PMC_EV_POWER8_STORE_COMPLETED, + .pe_flags = PMC_FLAG_PMC2, + .pe_code = 0xf0 + }, + {PMC_EV_POWER8_INSTR_DISPATCHED, + .pe_flags = PMC_FLAG_PMC2 | PMC_FLAG_PMC3, + .pe_code = 0xf2 + }, + {PMC_EV_POWER8_CYCLES_RUNNING, + .pe_flags = PMC_FLAG_PMC2, + .pe_code = 0xf4 + }, + {PMC_EV_POWER8_ERAT_DATA_MISS, + .pe_flags = PMC_FLAG_PMC2, + .pe_code = 0xf6 + }, + {PMC_EV_POWER8_EXTERNAL_INTERRUPT, + .pe_flags = PMC_FLAG_PMC2, + .pe_code = 0xf8 + }, + {PMC_EV_POWER8_BRANCH_TAKEN, + .pe_flags = PMC_FLAG_PMC2, + .pe_code = 0xfa + }, + {PMC_EV_POWER8_L1_INSTR_MISS, + .pe_flags = PMC_FLAG_PMC2, + .pe_code = 0xfc + }, + {PMC_EV_POWER8_L2_LOAD_MISS, + .pe_flags = PMC_FLAG_PMC2, + .pe_code = 0xfe + }, + {PMC_EV_POWER8_STORE_NO_REAL_ADDR, + .pe_flags = PMC_FLAG_PMC3, + .pe_code = 0xf0 + }, + {PMC_EV_POWER8_INSTR_COMPLETED_WITH_ALL_THREADS_RUNNING, + .pe_flags = PMC_FLAG_PMC3, + .pe_code = 0xf4 + }, + {PMC_EV_POWER8_L1_LOAD_MISS, + .pe_flags = PMC_FLAG_PMC3, + .pe_code = 0xf6 + }, + {PMC_EV_POWER8_TIMEBASE_EVENT, + .pe_flags = PMC_FLAG_PMC3, + .pe_code = 0xf8 + }, + {PMC_EV_POWER8_L3_INSTR_MISS, + .pe_flags = PMC_FLAG_PMC3, + .pe_code = 0xfa + }, + {PMC_EV_POWER8_TLB_DATA_MISS, + .pe_flags = PMC_FLAG_PMC3, + .pe_code = 0xfc + }, + {PMC_EV_POWER8_L3_LOAD_MISS, + .pe_flags = PMC_FLAG_PMC3, + .pe_code = 0xfe + }, + {PMC_EV_POWER8_LOAD_NO_REAL_ADDR, + .pe_flags = PMC_FLAG_PMC4, + .pe_code = 0xf0 + }, + {PMC_EV_POWER8_CYCLES_WITH_INSTRS_DISPATCHED, + .pe_flags = PMC_FLAG_PMC4, + .pe_code = 0xf2 + }, + {PMC_EV_POWER8_CYCLES_RUNNING_PURR_INC, + .pe_flags = PMC_FLAG_PMC4, + .pe_code = 0xf4 + }, + {PMC_EV_POWER8_BRANCH_MISPREDICTED, + .pe_flags = PMC_FLAG_PMC4, + .pe_code = 0xf6 + }, + {PMC_EV_POWER8_PREFETCHED_INSTRS_DISCARDED, + .pe_flags = PMC_FLAG_PMC4, + .pe_code = 0xf8 + }, + {PMC_EV_POWER8_INSTR_COMPLETED_RUNNING, + .pe_flags = PMC_FLAG_PMC4, + .pe_code = 0xfa + }, + {PMC_EV_POWER8_TLB_INSTR_MISS, + .pe_flags = PMC_FLAG_PMC4, + .pe_code = 0xfc + }, + {PMC_EV_POWER8_CACHE_LOAD_MISS, + .pe_flags = PMC_FLAG_PMC4, + .pe_code = 0xfe + } +}; +static size_t power8_event_codes_size = nitems(power8_event_codes); + +static void +power8_set_pmc(int cpu, int ri, int config) +{ + register_t mmcr; + + /* Select event */ + switch (ri) { + case 0: + case 1: + case 2: + case 3: + mmcr = mfspr(SPR_MMCR1); + mmcr &= ~SPR_MMCR1_P8_PMCNSEL_MASK(ri); + mmcr |= SPR_MMCR1_P8_PMCNSEL(ri, config & ~POWERPC_PMC_ENABLE); + mtspr(SPR_MMCR1, mmcr); + break; + } + + /* + * By default, freeze counter in all states. + * If counter is being started, unfreeze it in selected states. + */ + mmcr = mfspr(SPR_MMCR2) | SPR_MMCR2_FCNHSP(ri); + if (config != PMCN_NONE) { + if (config & POWERPC_PMC_USER_ENABLE) + mmcr &= ~(SPR_MMCR2_FCNP0(ri) | + SPR_MMCR2_FCNP1(ri)); + if (config & POWERPC_PMC_KERNEL_ENABLE) + mmcr &= ~(SPR_MMCR2_FCNH(ri) | + SPR_MMCR2_FCNS(ri)); + } + mtspr(SPR_MMCR2, mmcr); +} + +static int +power8_pcpu_init(struct pmc_mdep *md, int cpu) +{ + register_t mmcr0; + int i; + + powerpc_pcpu_init(md, cpu); + + /* Freeze all counters before modifying PMC registers */ + mmcr0 = mfspr(SPR_MMCR0) | SPR_MMCR0_FC; + mtspr(SPR_MMCR0, mmcr0); + + /* + * Now setup MMCR0: + * - PMAO=0: clear alerts + * - FCPC=0, FCP=0: don't freeze counters in problem state + * - FCECE: Freeze Counters on Enabled Condition or Event + * - PMC1CE/PMCNCE: PMC1/N Condition Enable + */ + mmcr0 &= ~(SPR_MMCR0_PMAO | SPR_MMCR0_FCPC | SPR_MMCR0_FCP); + mmcr0 |= SPR_MMCR0_FCECE | SPR_MMCR0_PMC1CE | SPR_MMCR0_PMCNCE; + mtspr(SPR_MMCR0, mmcr0); + + /* Clear all PMCs to prevent enabled condition interrupts */ + for (i = 0; i < POWER8_MAX_PMCS; i++) + powerpc_pmcn_write(i, 0); + + /* Disable events in PMCs 1-4 */ + mtspr(SPR_MMCR1, mfspr(SPR_MMCR1) & ~SPR_MMCR1_P8_PMCSEL_ALL); + + /* Freeze each counter, in all states */ + mtspr(SPR_MMCR2, mfspr(SPR_MMCR2) | + SPR_MMCR2_FCNHSP(0) | SPR_MMCR2_FCNHSP(1) | SPR_MMCR2_FCNHSP(2) | + SPR_MMCR2_FCNHSP(3) | SPR_MMCR2_FCNHSP(4) | SPR_MMCR2_FCNHSP(5)); + + /* Enable interrupts, unset global freeze */ + mmcr0 &= ~SPR_MMCR0_FC; + mmcr0 |= SPR_MMCR0_PMAE; + mtspr(SPR_MMCR0, mmcr0); + return (0); +} + +static int +power8_pcpu_fini(struct pmc_mdep *md, int cpu) +{ + register_t mmcr0; + + /* Freeze counters, disable interrupts */ + mmcr0 = mfspr(SPR_MMCR0); + mmcr0 &= ~SPR_MMCR0_PMAE; + mmcr0 |= SPR_MMCR0_FC; + mtspr(SPR_MMCR0, mmcr0); + + return (powerpc_pcpu_fini(md, cpu)); +} + +static void +power8_resume_pmc(bool ie) +{ + register_t mmcr0; + + /* Unfreeze counters and re-enable PERF exceptions if requested. */ + mmcr0 = mfspr(SPR_MMCR0); + mmcr0 &= ~(SPR_MMCR0_FC | SPR_MMCR0_PMAO | SPR_MMCR0_PMAE); + if (ie) + mmcr0 |= SPR_MMCR0_PMAE; + mtspr(SPR_MMCR0, mmcr0); +} + +int +pmc_power8_initialize(struct pmc_mdep *pmc_mdep) +{ + struct pmc_classdep *pcd; + + pmc_mdep->pmd_cputype = PMC_CPU_PPC_POWER8; + + pcd = &pmc_mdep->pmd_classdep[PMC_MDEP_CLASS_INDEX_POWERPC]; + pcd->pcd_caps = POWERPC_PMC_CAPS; + pcd->pcd_class = PMC_CLASS_POWER8; + pcd->pcd_num = POWER8_MAX_PMCS; + pcd->pcd_ri = pmc_mdep->pmd_npmc; + pcd->pcd_width = 32; + + pcd->pcd_pcpu_init = power8_pcpu_init; + pcd->pcd_pcpu_fini = power8_pcpu_fini; + pcd->pcd_allocate_pmc = powerpc_allocate_pmc; + pcd->pcd_release_pmc = powerpc_release_pmc; + pcd->pcd_start_pmc = powerpc_start_pmc; + pcd->pcd_stop_pmc = powerpc_stop_pmc; + pcd->pcd_get_config = powerpc_get_config; + pcd->pcd_config_pmc = powerpc_config_pmc; + pcd->pcd_describe = powerpc_describe; + pcd->pcd_read_pmc = powerpc_read_pmc; + pcd->pcd_write_pmc = powerpc_write_pmc; + + pmc_mdep->pmd_npmc += POWER8_MAX_PMCS; + pmc_mdep->pmd_intr = powerpc_pmc_intr; + + ppc_event_codes = power8_event_codes; + ppc_event_codes_size = power8_event_codes_size; + ppc_event_first = PMC_EV_POWER8_FIRST; + ppc_event_last = PMC_EV_POWER8_LAST; + ppc_max_pmcs = POWER8_MAX_PMCS; + + powerpc_set_pmc = power8_set_pmc; + powerpc_pmcn_read = powerpc_pmcn_read_default; + powerpc_pmcn_write = powerpc_pmcn_write_default; + powerpc_resume_pmc = power8_resume_pmc; + + return (0); +} Property changes on: head/sys/dev/hwpmc/hwpmc_power8.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/sys/dev/hwpmc/hwpmc_powerpc.c =================================================================== --- head/sys/dev/hwpmc/hwpmc_powerpc.c (revision 367389) +++ head/sys/dev/hwpmc/hwpmc_powerpc.c (revision 367390) @@ -1,238 +1,648 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2011,2013 Justin Hibbits * Copyright (c) 2005, Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include __FBSDID("$FreeBSD$"); #include #include #include #include +#include #include #include #include #include #include #include #include #include "hwpmc_powerpc.h" #ifdef __powerpc64__ #define OFFSET 4 /* Account for the TOC reload slot */ #else #define OFFSET 0 #endif struct powerpc_cpu **powerpc_pcpu; +struct pmc_ppc_event *ppc_event_codes; +size_t ppc_event_codes_size; +int ppc_event_first; +int ppc_event_last; +int ppc_max_pmcs; +void (*powerpc_set_pmc)(int cpu, int ri, int config); +pmc_value_t (*powerpc_pmcn_read)(unsigned int pmc); +void (*powerpc_pmcn_write)(unsigned int pmc, uint32_t val); +void (*powerpc_resume_pmc)(bool ie); + + int pmc_save_kernel_callchain(uintptr_t *cc, int maxsamples, struct trapframe *tf) { uintptr_t *osp, *sp; uintptr_t pc; int frames = 0; cc[frames++] = PMC_TRAPFRAME_TO_PC(tf); sp = (uintptr_t *)PMC_TRAPFRAME_TO_FP(tf); osp = (uintptr_t *)PAGE_SIZE; for (; frames < maxsamples; frames++) { if (sp <= osp) break; #ifdef __powerpc64__ pc = sp[2]; #else pc = sp[1]; #endif if ((pc & 3) || (pc < 0x100)) break; /* * trapexit() and asttrapexit() are sentinels * for kernel stack tracing. * */ if (pc + OFFSET == (uintptr_t) &trapexit || pc + OFFSET == (uintptr_t) &asttrapexit) break; cc[frames] = pc; osp = sp; sp = (uintptr_t *)*sp; } return (frames); } static int powerpc_switch_in(struct pmc_cpu *pc, struct pmc_process *pp) { return (0); } static int powerpc_switch_out(struct pmc_cpu *pc, struct pmc_process *pp) { return (0); } int powerpc_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc) { int error; struct pmc_hw *phw; char powerpc_name[PMC_NAME_MAX]; KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), ("[powerpc,%d], illegal CPU %d", __LINE__, cpu)); phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; snprintf(powerpc_name, sizeof(powerpc_name), "POWERPC-%d", ri); if ((error = copystr(powerpc_name, pi->pm_name, PMC_NAME_MAX, NULL)) != 0) return error; pi->pm_class = powerpc_pcpu[cpu]->pc_class; if (phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) { pi->pm_enabled = TRUE; *ppmc = phw->phw_pmc; } else { pi->pm_enabled = FALSE; *ppmc = NULL; } return (0); } int powerpc_get_config(int cpu, int ri, struct pmc **ppm) { *ppm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc; return (0); } +int +powerpc_pcpu_init(struct pmc_mdep *md, int cpu) +{ + struct pmc_cpu *pc; + struct powerpc_cpu *pac; + struct pmc_hw *phw; + int first_ri, i; + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[powerpc,%d] wrong cpu number %d", __LINE__, cpu)); + PMCDBG1(MDP,INI,1,"powerpc-init cpu=%d", cpu); + + powerpc_pcpu[cpu] = pac = malloc(sizeof(struct powerpc_cpu), M_PMC, + M_WAITOK|M_ZERO); + pac->pc_ppcpmcs = malloc(sizeof(struct pmc_hw) * ppc_max_pmcs, + M_PMC, M_WAITOK|M_ZERO); + pac->pc_class = + md->pmd_classdep[PMC_MDEP_CLASS_INDEX_POWERPC].pcd_class; + + pc = pmc_pcpu[cpu]; + first_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_POWERPC].pcd_ri; + KASSERT(pc != NULL, ("[powerpc,%d] NULL per-cpu pointer", __LINE__)); + + for (i = 0, phw = pac->pc_ppcpmcs; i < ppc_max_pmcs; i++, phw++) { + phw->phw_state = PMC_PHW_FLAG_IS_ENABLED | + PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(i); + phw->phw_pmc = NULL; + pc->pc_hwpmcs[i + first_ri] = phw; + } + + return (0); +} + +int +powerpc_pcpu_fini(struct pmc_mdep *md, int cpu) +{ + PMCDBG1(MDP,INI,1,"powerpc-fini cpu=%d", cpu); + + free(powerpc_pcpu[cpu]->pc_ppcpmcs, M_PMC); + free(powerpc_pcpu[cpu], M_PMC); + + return (0); +} + +int +powerpc_allocate_pmc(int cpu, int ri, struct pmc *pm, + const struct pmc_op_pmcallocate *a) +{ + enum pmc_event pe; + uint32_t caps, config = 0, counter = 0; + int i; + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); + KASSERT(ri >= 0 && ri < ppc_max_pmcs, + ("[powerpc,%d] illegal row index %d", __LINE__, ri)); + + caps = a->pm_caps; + + pe = a->pm_ev; + + if (pe < ppc_event_first || pe > ppc_event_last) + return (EINVAL); + + for (i = 0; i < ppc_event_codes_size; i++) { + if (ppc_event_codes[i].pe_event == pe) { + config = ppc_event_codes[i].pe_code; + counter = ppc_event_codes[i].pe_flags; + break; + } + } + if (i == ppc_event_codes_size) + return (EINVAL); + + if ((counter & (1 << ri)) == 0) + return (EINVAL); + + if (caps & PMC_CAP_SYSTEM) + config |= POWERPC_PMC_KERNEL_ENABLE; + if (caps & PMC_CAP_USER) + config |= POWERPC_PMC_USER_ENABLE; + if ((caps & (PMC_CAP_USER | PMC_CAP_SYSTEM)) == 0) + config |= POWERPC_PMC_ENABLE; + + pm->pm_md.pm_powerpc.pm_powerpc_evsel = config; + + PMCDBG3(MDP,ALL,1,"powerpc-allocate cpu=%d ri=%d -> config=0x%x", + cpu, ri, config); + return (0); +} + +int +powerpc_release_pmc(int cpu, int ri, struct pmc *pmc) +{ + struct pmc_hw *phw; + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); + KASSERT(ri >= 0 && ri < ppc_max_pmcs, + ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); + + phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; + KASSERT(phw->phw_pmc == NULL, + ("[powerpc,%d] PHW pmc %p non-NULL", __LINE__, phw->phw_pmc)); + + return (0); +} + +int +powerpc_start_pmc(int cpu, int ri) +{ + struct pmc *pm; + + PMCDBG2(MDP,STA,1,"powerpc-start cpu=%d ri=%d", cpu, ri); + pm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc; + powerpc_set_pmc(cpu, ri, pm->pm_md.pm_powerpc.pm_powerpc_evsel); + + return (0); +} + +int +powerpc_stop_pmc(int cpu, int ri) +{ + PMCDBG2(MDP,STO,1, "powerpc-stop cpu=%d ri=%d", cpu, ri); + powerpc_set_pmc(cpu, ri, PMCN_NONE); + return (0); +} + +int +powerpc_config_pmc(int cpu, int ri, struct pmc *pm) +{ + struct pmc_hw *phw; + + PMCDBG3(MDP,CFG,1, "powerpc-config cpu=%d ri=%d pm=%p", cpu, ri, pm); + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); + KASSERT(ri >= 0 && ri < ppc_max_pmcs, + ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); + + phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; + + KASSERT(pm == NULL || phw->phw_pmc == NULL, + ("[powerpc,%d] pm=%p phw->pm=%p hwpmc not unconfigured", + __LINE__, pm, phw->phw_pmc)); + + phw->phw_pmc = pm; + + return (0); +} + +pmc_value_t +powerpc_pmcn_read_default(unsigned int pmc) +{ + pmc_value_t val; + + if (pmc > ppc_max_pmcs) + panic("Invalid PMC number: %d\n", pmc); + + switch (pmc) { + case 0: + val = mfspr(SPR_PMC1); + break; + case 1: + val = mfspr(SPR_PMC2); + break; + case 2: + val = mfspr(SPR_PMC3); + break; + case 3: + val = mfspr(SPR_PMC4); + break; + case 4: + val = mfspr(SPR_PMC5); + break; + case 5: + val = mfspr(SPR_PMC6); + break; + case 6: + val = mfspr(SPR_PMC7); + break; + case 7: + val = mfspr(SPR_PMC8); + break; + } + + return (val); +} + +void +powerpc_pmcn_write_default(unsigned int pmc, uint32_t val) +{ + if (pmc > ppc_max_pmcs) + panic("Invalid PMC number: %d\n", pmc); + + switch (pmc) { + case 0: + mtspr(SPR_PMC1, val); + break; + case 1: + mtspr(SPR_PMC2, val); + break; + case 2: + mtspr(SPR_PMC3, val); + break; + case 3: + mtspr(SPR_PMC4, val); + break; + case 4: + mtspr(SPR_PMC5, val); + break; + case 5: + mtspr(SPR_PMC6, val); + break; + case 6: + mtspr(SPR_PMC7, val); + break; + case 7: + mtspr(SPR_PMC8, val); + break; + } +} + +int +powerpc_read_pmc(int cpu, int ri, pmc_value_t *v) +{ + struct pmc *pm; + pmc_value_t p, r, tmp; + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); + KASSERT(ri >= 0 && ri < ppc_max_pmcs, + ("[powerpc,%d] illegal row index %d", __LINE__, ri)); + + pm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc; + KASSERT(pm, + ("[core,%d] cpu %d ri %d pmc not configured", __LINE__, cpu, + ri)); + + /* + * After an interrupt occurs because of a PMC overflow, the PMC value + * is not always MAX_PMC_VALUE + 1, but may be a little above it. + * This may mess up calculations and frustrate machine independent + * layer expectations, such as that no value read should be greater + * than reload count in sampling mode. + * To avoid these issues, use MAX_PMC_VALUE as an upper limit. + */ + p = MIN(powerpc_pmcn_read(ri), POWERPC_MAX_PMC_VALUE); + r = pm->pm_sc.pm_reloadcount; + + if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) { + /* + * Special case 1: r is too big + * This usually happens when a PMC write fails, the PMC is + * stopped and then it is read. + * + * Special case 2: PMC was reseted or has a value + * that should not be possible with current r. + * + * In the above cases, just return 0 instead of an arbitrary + * value. + */ + if (r > POWERPC_MAX_PMC_VALUE || p + r <= POWERPC_MAX_PMC_VALUE) + tmp = 0; + else + tmp = POWERPC_PERFCTR_VALUE_TO_RELOAD_COUNT(p); + } else + tmp = p + (POWERPC_MAX_PMC_VALUE + 1) * PPC_OVERFLOWCNT(pm); + + PMCDBG5(MDP,REA,1,"ppc-read cpu=%d ri=%d -> %jx (%jx,%jx)", + cpu, ri, (uintmax_t)tmp, (uintmax_t)PPC_OVERFLOWCNT(pm), + (uintmax_t)p); + *v = tmp; + return (0); +} + +int +powerpc_write_pmc(int cpu, int ri, pmc_value_t v) +{ + struct pmc *pm; + pmc_value_t vlo; + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); + KASSERT(ri >= 0 && ri < ppc_max_pmcs, + ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); + + pm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc; + + if (PMC_IS_COUNTING_MODE(PMC_TO_MODE(pm))) { + PPC_OVERFLOWCNT(pm) = v / (POWERPC_MAX_PMC_VALUE + 1); + vlo = v % (POWERPC_MAX_PMC_VALUE + 1); + } else if (v > POWERPC_MAX_PMC_VALUE) { + PMCDBG3(MDP,WRI,2, + "powerpc-write cpu=%d ri=%d: PMC value is too big: %jx", + cpu, ri, (uintmax_t)v); + return (EINVAL); + } else + vlo = POWERPC_RELOAD_COUNT_TO_PERFCTR_VALUE(v); + + PMCDBG5(MDP,WRI,1,"powerpc-write cpu=%d ri=%d -> %jx (%jx,%jx)", + cpu, ri, (uintmax_t)v, (uintmax_t)PPC_OVERFLOWCNT(pm), + (uintmax_t)vlo); + + powerpc_pmcn_write(ri, vlo); + return (0); +} + +int +powerpc_pmc_intr(struct trapframe *tf) +{ + struct pmc *pm; + struct powerpc_cpu *pc; + int cpu, error, i, retval; + + cpu = curcpu; + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[powerpc,%d] out of range CPU %d", __LINE__, cpu)); + + PMCDBG3(MDP,INT,1, "cpu=%d tf=%p um=%d", cpu, (void *) tf, + TRAPF_USERMODE(tf)); + + retval = 0; + pc = powerpc_pcpu[cpu]; + + /* + * Look for a running, sampling PMC which has overflowed + * and which has a valid 'struct pmc' association. + */ + for (i = 0; i < ppc_max_pmcs; i++) { + if (!POWERPC_PMC_HAS_OVERFLOWED(i)) + continue; + retval = 1; /* Found an interrupting PMC. */ + + /* + * Always clear the PMC, to make it stop interrupting. + * If pm is available and in sampling mode, use reload + * count, to make PMC read after stop correct. + * Otherwise, just reset the PMC. + */ + if ((pm = pc->pc_ppcpmcs[i].phw_pmc) != NULL && + PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) { + if (pm->pm_state != PMC_STATE_RUNNING) { + powerpc_write_pmc(cpu, i, + pm->pm_sc.pm_reloadcount); + continue; + } + } else { + if (pm != NULL) { /* !PMC_IS_SAMPLING_MODE */ + PPC_OVERFLOWCNT(pm) = (PPC_OVERFLOWCNT(pm) + + 1) % PPC_OVERFLOWCNT_MAX; + PMCDBG3(MDP,INT,2, + "cpu=%d ri=%d: overflowcnt=%d", + cpu, i, PPC_OVERFLOWCNT(pm)); + } + + powerpc_pmcn_write(i, 0); + continue; + } + + error = pmc_process_interrupt(PMC_HR, pm, tf); + if (error != 0) { + PMCDBG3(MDP,INT,3, + "cpu=%d ri=%d: error %d processing interrupt", + cpu, i, error); + powerpc_stop_pmc(cpu, i); + } + + /* Reload sampling count */ + powerpc_write_pmc(cpu, i, pm->pm_sc.pm_reloadcount); + } + + if (retval) + counter_u64_add(pmc_stats.pm_intr_processed, 1); + else + counter_u64_add(pmc_stats.pm_intr_ignored, 1); + + /* + * Re-enable PERF exceptions if we were able to find the interrupt + * source and handle it. Otherwise, it's better to disable PERF + * interrupts, to avoid the risk of processing the same interrupt + * forever. + */ + powerpc_resume_pmc(retval != 0); + if (retval == 0) + log(LOG_WARNING, + "pmc_intr: couldn't find interrupting PMC on cpu %d - " + "disabling PERF interrupts\n", cpu); + + return (retval); +} + struct pmc_mdep * pmc_md_initialize() { struct pmc_mdep *pmc_mdep; int error; uint16_t vers; /* * Allocate space for pointers to PMC HW descriptors and for * the MDEP structure used by MI code. */ powerpc_pcpu = malloc(sizeof(struct powerpc_cpu *) * pmc_cpu_max(), M_PMC, M_WAITOK|M_ZERO); /* Just one class */ pmc_mdep = pmc_mdep_alloc(1); vers = mfpvr() >> 16; pmc_mdep->pmd_switch_in = powerpc_switch_in; pmc_mdep->pmd_switch_out = powerpc_switch_out; switch (vers) { case MPC7447A: case MPC7448: case MPC7450: case MPC7455: case MPC7457: error = pmc_mpc7xxx_initialize(pmc_mdep); break; case IBM970: case IBM970FX: case IBM970MP: error = pmc_ppc970_initialize(pmc_mdep); + break; + case IBMPOWER8E: + case IBMPOWER8NVL: + case IBMPOWER8: + case IBMPOWER9: + error = pmc_power8_initialize(pmc_mdep); break; case FSL_E500v1: case FSL_E500v2: case FSL_E500mc: case FSL_E5500: error = pmc_e500_initialize(pmc_mdep); break; default: error = -1; break; } if (error != 0) { pmc_mdep_free(pmc_mdep); pmc_mdep = NULL; } return (pmc_mdep); } void pmc_md_finalize(struct pmc_mdep *md) { free(powerpc_pcpu, M_PMC); powerpc_pcpu = NULL; } int pmc_save_user_callchain(uintptr_t *cc, int maxsamples, struct trapframe *tf) { uintptr_t *osp, *sp; int frames = 0; cc[frames++] = PMC_TRAPFRAME_TO_PC(tf); sp = (uintptr_t *)PMC_TRAPFRAME_TO_FP(tf); osp = NULL; for (; frames < maxsamples; frames++) { if (sp <= osp) break; osp = sp; #ifdef __powerpc64__ /* Check if 32-bit mode. */ if (!(tf->srr1 & PSL_SF)) { cc[frames] = fuword32((uint32_t *)sp + 1); sp = (uintptr_t *)(uintptr_t)fuword32(sp); } else { cc[frames] = fuword(sp + 2); sp = (uintptr_t *)fuword(sp); } #else cc[frames] = fuword32((uint32_t *)sp + 1); sp = (uintptr_t *)fuword32(sp); #endif } return (frames); } Index: head/sys/dev/hwpmc/hwpmc_powerpc.h =================================================================== --- head/sys/dev/hwpmc/hwpmc_powerpc.h (revision 367389) +++ head/sys/dev/hwpmc/hwpmc_powerpc.h (revision 367390) @@ -1,64 +1,114 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2013 Justin Hibbits * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _DEV_HWPMC_POWERPC_H_ #define _DEV_HWPMC_POWERPC_H_ 1 #ifdef _KERNEL #define POWERPC_PMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_USER | \ PMC_CAP_SYSTEM | PMC_CAP_EDGE | \ PMC_CAP_THRESHOLD | PMC_CAP_READ | \ PMC_CAP_WRITE | PMC_CAP_INVERT | \ PMC_CAP_QUALIFIER) #define POWERPC_PMC_KERNEL_ENABLE (0x1 << 30) #define POWERPC_PMC_USER_ENABLE (0x1 << 31) #define POWERPC_PMC_ENABLE (POWERPC_PMC_KERNEL_ENABLE | POWERPC_PMC_USER_ENABLE) #define POWERPC_RELOAD_COUNT_TO_PERFCTR_VALUE(V) (0x80000000-(V)) #define POWERPC_PERFCTR_VALUE_TO_RELOAD_COUNT(P) (0x80000000-(P)) +#define POWERPC_MAX_PMC_VALUE 0x7fffffffUL + +#define POWERPC_PMC_HAS_OVERFLOWED(n) (powerpc_pmcn_read(n) & (0x1 << 31)) + +/* + * PMC value is used with OVERFLOWCNT to simulate a 64-bit counter to the + * machine independent part of hwpmc. + */ +#define PPC_OVERFLOWCNT(pm) (pm)->pm_md.pm_powerpc.pm_powerpc_overflowcnt +#define PPC_OVERFLOWCNT_MAX 0x200000000UL + struct powerpc_cpu { struct pmc_hw *pc_ppcpmcs; enum pmc_class pc_class; }; +struct pmc_ppc_event { + enum pmc_event pe_event; + uint32_t pe_flags; +#define PMC_FLAG_PMC1 0x01 +#define PMC_FLAG_PMC2 0x02 +#define PMC_FLAG_PMC3 0x04 +#define PMC_FLAG_PMC4 0x08 +#define PMC_FLAG_PMC5 0x10 +#define PMC_FLAG_PMC6 0x20 +#define PMC_FLAG_PMC7 0x40 +#define PMC_FLAG_PMC8 0x80 + uint32_t pe_code; +}; + extern struct powerpc_cpu **powerpc_pcpu; +extern struct pmc_ppc_event *ppc_event_codes; +extern size_t ppc_event_codes_size; +extern int ppc_event_first; +extern int ppc_event_last; +extern int ppc_max_pmcs; -extern int pmc_e500_initialize(struct pmc_mdep *pmc_mdep); -extern int pmc_mpc7xxx_initialize(struct pmc_mdep *pmc_mdep); -extern int pmc_ppc970_initialize(struct pmc_mdep *pmc_mdep); +extern void (*powerpc_set_pmc)(int cpu, int ri, int config); +extern pmc_value_t (*powerpc_pmcn_read)(unsigned int pmc); +extern void (*powerpc_pmcn_write)(unsigned int pmc, uint32_t val); +extern void (*powerpc_resume_pmc)(bool ie); -extern int powerpc_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc); -extern int powerpc_get_config(int cpu, int ri, struct pmc **ppm); +int pmc_e500_initialize(struct pmc_mdep *pmc_mdep); +int pmc_mpc7xxx_initialize(struct pmc_mdep *pmc_mdep); +int pmc_ppc970_initialize(struct pmc_mdep *pmc_mdep); +int pmc_power8_initialize(struct pmc_mdep *pmc_mdep); + +int powerpc_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc); +int powerpc_get_config(int cpu, int ri, struct pmc **ppm); +int powerpc_pcpu_init(struct pmc_mdep *md, int cpu); +int powerpc_pcpu_fini(struct pmc_mdep *md, int cpu); +int powerpc_allocate_pmc(int cpu, int ri, struct pmc *pm, + const struct pmc_op_pmcallocate *a); +int powerpc_release_pmc(int cpu, int ri, struct pmc *pmc); +int powerpc_start_pmc(int cpu, int ri); +int powerpc_stop_pmc(int cpu, int ri); +int powerpc_config_pmc(int cpu, int ri, struct pmc *pm); +pmc_value_t powerpc_pmcn_read_default(unsigned int pmc); +void powerpc_pmcn_write_default(unsigned int pmc, uint32_t val); +int powerpc_read_pmc(int cpu, int ri, pmc_value_t *v); +int powerpc_write_pmc(int cpu, int ri, pmc_value_t v); +int powerpc_pmc_intr(struct trapframe *tf); + #endif /* _KERNEL */ #endif /* _DEV_HWPMC_POWERPC_H_ */ Index: head/sys/dev/hwpmc/hwpmc_ppc970.c =================================================================== --- head/sys/dev/hwpmc/hwpmc_ppc970.c (revision 367389) +++ head/sys/dev/hwpmc/hwpmc_ppc970.c (revision 367390) @@ -1,691 +1,390 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2013 Justin Hibbits * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include "hwpmc_powerpc.h" -#define PPC970_MAX_PMCS 8 +#define PPC970_MAX_PMCS 8 +#define PMC_PPC970_FLAG_PMCS 0x000000ff /* MMCR0, PMC1 is 8 bytes in, PMC2 is 1 byte in. */ #define PPC970_SET_MMCR0_PMCSEL(r, x, i) \ ((r & ~(0x1f << (7 * (1 - i) + 1))) | (x << (7 * (1 - i) + 1))) /* MMCR1 has 6 PMC*SEL items (PMC3->PMC8), in sequence. */ #define PPC970_SET_MMCR1_PMCSEL(r, x, i) \ ((r & ~(0x1f << (5 * (7 - i) + 2))) | (x << (5 * (7 - i) + 2))) -#define PPC970_PMC_HAS_OVERFLOWED(x) (ppc970_pmcn_read(x) & (0x1 << 31)) - /* How PMC works on PPC970: * * Any PMC can count a direct event. Indirect events are handled specially. * Direct events: As published. * * Encoding 00 000 -- Add byte lane bit counters * MMCR1[24:31] -- select bit matching PMC being an adder. * Bus events: * PMCxSEL: 1x -- select from byte lane: 10 == lower lane (0/1), 11 == upper * lane (2/3). * PMCxSEL[2:4] -- bit in the byte lane selected. * * PMC[1,2,5,6] == lane 0/lane 2 * PMC[3,4,7,8] == lane 1,3 * * * Lanes: * Lane 0 -- TTM0(FPU,ISU,IFU,VPU) * TTM1(IDU,ISU,STS) * LSU0 byte 0 * LSU1 byte 0 * Lane 1 -- TTM0 * TTM1 * LSU0 byte 1 * LSU1 byte 1 * Lane 2 -- TTM0 * TTM1 * LSU0 byte 2 * LSU1 byte 2 or byte 6 * Lane 3 -- TTM0 * TTM1 * LSU0 byte 3 * LSU1 byte 3 or byte 7 * * Adders: * Add byte lane for PMC (above), bit 0+4, 1+5, 2+6, 3+7 */ -struct pmc_ppc970_event { - enum pmc_event pe_event; - uint32_t pe_flags; -#define PMC_PPC970_FLAG_PMCS 0x000000ff -#define PMC_PPC970_FLAG_PMC1 0x01 -#define PMC_PPC970_FLAG_PMC2 0x02 -#define PMC_PPC970_FLAG_PMC3 0x04 -#define PMC_PPC970_FLAG_PMC4 0x08 -#define PMC_PPC970_FLAG_PMC5 0x10 -#define PMC_PPC970_FLAG_PMC6 0x20 -#define PMC_PPC970_FLAG_PMC7 0x40 -#define PMC_PPC970_FLAG_PMC8 0x80 - uint32_t pe_code; -}; - -static struct pmc_ppc970_event ppc970_event_codes[] = { +static struct pmc_ppc_event ppc970_event_codes[] = { {PMC_EV_PPC970_INSTR_COMPLETED, .pe_flags = PMC_PPC970_FLAG_PMCS, .pe_code = 0x09 }, {PMC_EV_PPC970_MARKED_GROUP_DISPATCH, - .pe_flags = PMC_PPC970_FLAG_PMC1, + .pe_flags = PMC_FLAG_PMC1, .pe_code = 0x2 }, {PMC_EV_PPC970_MARKED_STORE_COMPLETED, - .pe_flags = PMC_PPC970_FLAG_PMC1, + .pe_flags = PMC_FLAG_PMC1, .pe_code = 0x03 }, {PMC_EV_PPC970_GCT_EMPTY, - .pe_flags = PMC_PPC970_FLAG_PMC1, + .pe_flags = PMC_FLAG_PMC1, .pe_code = 0x04 }, {PMC_EV_PPC970_RUN_CYCLES, - .pe_flags = PMC_PPC970_FLAG_PMC1, + .pe_flags = PMC_FLAG_PMC1, .pe_code = 0x05 }, {PMC_EV_PPC970_OVERFLOW, .pe_flags = PMC_PPC970_FLAG_PMCS, .pe_code = 0x0a }, {PMC_EV_PPC970_CYCLES, .pe_flags = PMC_PPC970_FLAG_PMCS, .pe_code = 0x0f }, {PMC_EV_PPC970_THRESHOLD_TIMEOUT, - .pe_flags = PMC_PPC970_FLAG_PMC2, + .pe_flags = PMC_FLAG_PMC2, .pe_code = 0x3 }, {PMC_EV_PPC970_GROUP_DISPATCH, - .pe_flags = PMC_PPC970_FLAG_PMC2, + .pe_flags = PMC_FLAG_PMC2, .pe_code = 0x4 }, {PMC_EV_PPC970_BR_MARKED_INSTR_FINISH, - .pe_flags = PMC_PPC970_FLAG_PMC2, + .pe_flags = PMC_FLAG_PMC2, .pe_code = 0x5 }, {PMC_EV_PPC970_GCT_EMPTY_BY_SRQ_FULL, - .pe_flags = PMC_PPC970_FLAG_PMC2, + .pe_flags = PMC_FLAG_PMC2, .pe_code = 0xb }, {PMC_EV_PPC970_STOP_COMPLETION, - .pe_flags = PMC_PPC970_FLAG_PMC3, + .pe_flags = PMC_FLAG_PMC3, .pe_code = 0x1 }, {PMC_EV_PPC970_LSU_EMPTY, - .pe_flags = PMC_PPC970_FLAG_PMC3, + .pe_flags = PMC_FLAG_PMC3, .pe_code = 0x2 }, {PMC_EV_PPC970_MARKED_STORE_WITH_INTR, - .pe_flags = PMC_PPC970_FLAG_PMC3, + .pe_flags = PMC_FLAG_PMC3, .pe_code = 0x3 }, {PMC_EV_PPC970_CYCLES_IN_SUPER, - .pe_flags = PMC_PPC970_FLAG_PMC3, + .pe_flags = PMC_FLAG_PMC3, .pe_code = 0x4 }, {PMC_EV_PPC970_VPU_MARKED_INSTR_COMPLETED, - .pe_flags = PMC_PPC970_FLAG_PMC3, + .pe_flags = PMC_FLAG_PMC3, .pe_code = 0x5 }, {PMC_EV_PPC970_FXU0_IDLE_FXU1_BUSY, - .pe_flags = PMC_PPC970_FLAG_PMC4, + .pe_flags = PMC_FLAG_PMC4, .pe_code = 0x2 }, {PMC_EV_PPC970_SRQ_EMPTY, - .pe_flags = PMC_PPC970_FLAG_PMC4, + .pe_flags = PMC_FLAG_PMC4, .pe_code = 0x3 }, {PMC_EV_PPC970_MARKED_GROUP_COMPLETED, - .pe_flags = PMC_PPC970_FLAG_PMC4, + .pe_flags = PMC_FLAG_PMC4, .pe_code = 0x4 }, {PMC_EV_PPC970_CR_MARKED_INSTR_FINISH, - .pe_flags = PMC_PPC970_FLAG_PMC4, + .pe_flags = PMC_FLAG_PMC4, .pe_code = 0x5 }, {PMC_EV_PPC970_DISPATCH_SUCCESS, - .pe_flags = PMC_PPC970_FLAG_PMC5, + .pe_flags = PMC_FLAG_PMC5, .pe_code = 0x1 }, {PMC_EV_PPC970_FXU0_IDLE_FXU1_IDLE, - .pe_flags = PMC_PPC970_FLAG_PMC5, + .pe_flags = PMC_FLAG_PMC5, .pe_code = 0x2 }, {PMC_EV_PPC970_ONE_PLUS_INSTR_COMPLETED, - .pe_flags = PMC_PPC970_FLAG_PMC5, + .pe_flags = PMC_FLAG_PMC5, .pe_code = 0x3 }, {PMC_EV_PPC970_GROUP_MARKED_IDU, - .pe_flags = PMC_PPC970_FLAG_PMC5, + .pe_flags = PMC_FLAG_PMC5, .pe_code = 0x4 }, {PMC_EV_PPC970_MARKED_GROUP_COMPLETE_TIMEOUT, - .pe_flags = PMC_PPC970_FLAG_PMC5, + .pe_flags = PMC_FLAG_PMC5, .pe_code = 0x5 }, {PMC_EV_PPC970_FXU0_BUSY_FXU1_BUSY, - .pe_flags = PMC_PPC970_FLAG_PMC6, + .pe_flags = PMC_FLAG_PMC6, .pe_code = 0x2 }, {PMC_EV_PPC970_MARKED_STORE_SENT_TO_STS, - .pe_flags = PMC_PPC970_FLAG_PMC6, + .pe_flags = PMC_FLAG_PMC6, .pe_code = 0x3 }, {PMC_EV_PPC970_FXU_MARKED_INSTR_FINISHED, - .pe_flags = PMC_PPC970_FLAG_PMC6, + .pe_flags = PMC_FLAG_PMC6, .pe_code = 0x4 }, {PMC_EV_PPC970_MARKED_GROUP_ISSUED, - .pe_flags = PMC_PPC970_FLAG_PMC6, + .pe_flags = PMC_FLAG_PMC6, .pe_code = 0x5 }, {PMC_EV_PPC970_FXU0_BUSY_FXU1_IDLE, - .pe_flags = PMC_PPC970_FLAG_PMC7, + .pe_flags = PMC_FLAG_PMC7, .pe_code = 0x2 }, {PMC_EV_PPC970_GROUP_COMPLETED, - .pe_flags = PMC_PPC970_FLAG_PMC7, + .pe_flags = PMC_FLAG_PMC7, .pe_code = 0x3 }, {PMC_EV_PPC970_FPU_MARKED_INSTR_COMPLETED, - .pe_flags = PMC_PPC970_FLAG_PMC7, + .pe_flags = PMC_FLAG_PMC7, .pe_code = 0x4 }, {PMC_EV_PPC970_MARKED_INSTR_FINISH_ANY_UNIT, - .pe_flags = PMC_PPC970_FLAG_PMC7, + .pe_flags = PMC_FLAG_PMC7, .pe_code = 0x5 }, {PMC_EV_PPC970_EXTERNAL_INTERRUPT, - .pe_flags = PMC_PPC970_FLAG_PMC8, + .pe_flags = PMC_FLAG_PMC8, .pe_code = 0x2 }, {PMC_EV_PPC970_GROUP_DISPATCH_REJECT, - .pe_flags = PMC_PPC970_FLAG_PMC8, + .pe_flags = PMC_FLAG_PMC8, .pe_code = 0x3 }, {PMC_EV_PPC970_LSU_MARKED_INSTR_FINISH, - .pe_flags = PMC_PPC970_FLAG_PMC8, + .pe_flags = PMC_FLAG_PMC8, .pe_code = 0x4 }, {PMC_EV_PPC970_TIMEBASE_EVENT, - .pe_flags = PMC_PPC970_FLAG_PMC8, + .pe_flags = PMC_FLAG_PMC8, .pe_code = 0x5 }, #if 0 {PMC_EV_PPC970_LSU_COMPLETION_STALL, }, {PMC_EV_PPC970_FXU_COMPLETION_STALL, }, {PMC_EV_PPC970_DCACHE_MISS_COMPLETION_STALL, }, {PMC_EV_PPC970_FPU_COMPLETION_STALL, }, {PMC_EV_PPC970_FXU_LONG_INSTR_COMPLETION_STALL, }, {PMC_EV_PPC970_REJECT_COMPLETION_STALL, }, {PMC_EV_PPC970_FPU_LONG_INSTR_COMPLETION_STALL, }, {PMC_EV_PPC970_GCT_EMPTY_BY_ICACHE_MISS, }, {PMC_EV_PPC970_REJECT_COMPLETION_STALL_ERAT_MISS, }, {PMC_EV_PPC970_GCT_EMPTY_BY_BRANCH_MISS_PREDICT, }, #endif }; static size_t ppc970_event_codes_size = nitems(ppc970_event_codes); -static pmc_value_t -ppc970_pmcn_read(unsigned int pmc) -{ - pmc_value_t val; - - switch (pmc) { - case 0: - val = mfspr(SPR_PMC1); - break; - case 1: - val = mfspr(SPR_PMC2); - break; - case 2: - val = mfspr(SPR_PMC3); - break; - case 3: - val = mfspr(SPR_PMC4); - break; - case 4: - val = mfspr(SPR_PMC5); - break; - case 5: - val = mfspr(SPR_PMC6); - break; - case 6: - val = mfspr(SPR_PMC7); - break; - case 7: - val = mfspr(SPR_PMC8); - break; - default: - panic("Invalid PMC number: %d\n", pmc); - } - - return (val); -} - static void -ppc970_pmcn_write(unsigned int pmc, uint32_t val) -{ - switch (pmc) { - case 0: - mtspr(SPR_PMC1, val); - break; - case 1: - mtspr(SPR_PMC2, val); - break; - case 2: - mtspr(SPR_PMC3, val); - break; - case 3: - mtspr(SPR_PMC4, val); - break; - case 4: - mtspr(SPR_PMC5, val); - break; - case 5: - mtspr(SPR_PMC6, val); - break; - case 6: - mtspr(SPR_PMC7, val); - break; - case 7: - mtspr(SPR_PMC8, val); - break; - default: - panic("Invalid PMC number: %d\n", pmc); - } -} - -static int -ppc970_config_pmc(int cpu, int ri, struct pmc *pm) -{ - struct pmc_hw *phw; - - PMCDBG3(MDP,CFG,1, "cpu=%d ri=%d pm=%p", cpu, ri, pm); - - KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), - ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < PPC970_MAX_PMCS, - ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); - - phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; - - KASSERT(pm == NULL || phw->phw_pmc == NULL, - ("[powerpc,%d] pm=%p phw->pm=%p hwpmc not unconfigured", - __LINE__, pm, phw->phw_pmc)); - - phw->phw_pmc = pm; - - return 0; -} - -static int ppc970_set_pmc(int cpu, int ri, int config) { struct pmc *pm; struct pmc_hw *phw; register_t pmc_mmcr; + int config_mask; - phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; - pm = phw->phw_pmc; + phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; + pm = phw->phw_pmc; + if (config == PMCN_NONE) + config = PMC970N_NONE; + /* + * The mask is inverted (enable is 1) compared to the flags in MMCR0, + * which are Freeze flags. + */ + config_mask = ~config & POWERPC_PMC_ENABLE; + config &= ~POWERPC_PMC_ENABLE; + + /* * Disable the PMCs. */ switch (ri) { case 0: case 1: pmc_mmcr = mfspr(SPR_MMCR0); pmc_mmcr = PPC970_SET_MMCR0_PMCSEL(pmc_mmcr, config, ri); mtspr(SPR_MMCR0, pmc_mmcr); break; case 2: case 3: case 4: case 5: case 6: case 7: pmc_mmcr = mfspr(SPR_MMCR1); pmc_mmcr = PPC970_SET_MMCR1_PMCSEL(pmc_mmcr, config, ri); mtspr(SPR_MMCR1, pmc_mmcr); break; } - return 0; -} -static int -ppc970_start_pmc(int cpu, int ri) -{ - struct pmc *pm; - struct pmc_hw *phw; - register_t pmc_mmcr; - uint32_t config; - int error; - - phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; - pm = phw->phw_pmc; - config = pm->pm_md.pm_powerpc.pm_powerpc_evsel & ~POWERPC_PMC_ENABLE; - - error = ppc970_set_pmc(cpu, ri, config); - - /* The mask is inverted (enable is 1) compared to the flags in MMCR0, which - * are Freeze flags. - */ - config = ~pm->pm_md.pm_powerpc.pm_powerpc_evsel & POWERPC_PMC_ENABLE; - - pmc_mmcr = mfspr(SPR_MMCR0); - pmc_mmcr &= ~SPR_MMCR0_FC; - pmc_mmcr |= config; - mtspr(SPR_MMCR0, pmc_mmcr); - - return 0; -} - -static int -ppc970_stop_pmc(int cpu, int ri) -{ - return ppc970_set_pmc(cpu, ri, PMC970N_NONE); -} - -static int -ppc970_read_pmc(int cpu, int ri, pmc_value_t *v) -{ - struct pmc *pm; - pmc_value_t tmp; - - KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), - ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < PPC970_MAX_PMCS, - ("[powerpc,%d] illegal row index %d", __LINE__, ri)); - - pm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc; - KASSERT(pm, - ("[core,%d] cpu %d ri %d pmc not configured", __LINE__, cpu, - ri)); - - tmp = ppc970_pmcn_read(ri); - PMCDBG2(MDP,REA,2,"ppc-read id=%d -> %jd", ri, tmp); - if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) - *v = POWERPC_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp); - else - *v = tmp; - - return 0; -} - -static int -ppc970_write_pmc(int cpu, int ri, pmc_value_t v) -{ - struct pmc *pm; - - KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), - ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < PPC970_MAX_PMCS, - ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); - - pm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc; - - if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) - v = POWERPC_RELOAD_COUNT_TO_PERFCTR_VALUE(v); - - PMCDBG3(MDP,WRI,1,"powerpc-write cpu=%d ri=%d v=%jx", cpu, ri, v); - - ppc970_pmcn_write(ri, v); - - return 0; -} - -static int -ppc970_intr(struct trapframe *tf) -{ - struct pmc *pm; - struct powerpc_cpu *pac; - uint32_t config; - int i, error, retval, cpu; - - cpu = curcpu; - KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), - ("[powerpc,%d] out of range CPU %d", __LINE__, cpu)); - - PMCDBG3(MDP,INT,1, "cpu=%d tf=%p um=%d", cpu, (void *) tf, - TRAPF_USERMODE(tf)); - - retval = 0; - - pac = powerpc_pcpu[cpu]; - - /* - * look for all PMCs that have interrupted: - * - look for a running, sampling PMC which has overflowed - * and which has a valid 'struct pmc' association - * - * If found, we call a helper to process the interrupt. - */ - - config = mfspr(SPR_MMCR0) & ~SPR_MMCR0_FC; - for (i = 0; i < PPC970_MAX_PMCS; i++) { - if ((pm = pac->pc_ppcpmcs[i].phw_pmc) == NULL || - !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) { - continue; - } - - if (!PPC970_PMC_HAS_OVERFLOWED(i)) - continue; - - retval = 1; /* Found an interrupting PMC. */ - - if (pm->pm_state != PMC_STATE_RUNNING) - continue; - - error = pmc_process_interrupt(PMC_HR, pm, tf); - if (error != 0) - ppc970_stop_pmc(cpu, i); - - /* reload sampling count. */ - ppc970_write_pmc(cpu, i, pm->pm_sc.pm_reloadcount); + if (config != PMC970N_NONE) { + pmc_mmcr = mfspr(SPR_MMCR0); + pmc_mmcr &= ~SPR_MMCR0_FC; + pmc_mmcr |= config_mask; + mtspr(SPR_MMCR0, pmc_mmcr); } - - if (retval) - counter_u64_add(pmc_stats.pm_intr_processed, 1); - else - counter_u64_add(pmc_stats.pm_intr_ignored, 1); - - /* Re-enable PERF exceptions. */ - if (retval) - mtspr(SPR_MMCR0, config | SPR_MMCR0_PMXE); - - return (retval); } static int ppc970_pcpu_init(struct pmc_mdep *md, int cpu) { - struct pmc_cpu *pc; - struct powerpc_cpu *pac; - struct pmc_hw *phw; - int first_ri, i; + powerpc_pcpu_init(md, cpu); - KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), - ("[powerpc,%d] wrong cpu number %d", __LINE__, cpu)); - PMCDBG1(MDP,INI,1,"powerpc-init cpu=%d", cpu); - - powerpc_pcpu[cpu] = pac = malloc(sizeof(struct powerpc_cpu), M_PMC, - M_WAITOK|M_ZERO); - pac->pc_ppcpmcs = malloc(sizeof(struct pmc_hw) * PPC970_MAX_PMCS, - M_PMC, M_WAITOK|M_ZERO); - pac->pc_class = PMC_CLASS_PPC970; - - pc = pmc_pcpu[cpu]; - first_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_POWERPC].pcd_ri; - KASSERT(pc != NULL, ("[powerpc,%d] NULL per-cpu pointer", __LINE__)); - - for (i = 0, phw = pac->pc_ppcpmcs; i < PPC970_MAX_PMCS; i++, phw++) { - phw->phw_state = PMC_PHW_FLAG_IS_ENABLED | - PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(i); - phw->phw_pmc = NULL; - pc->pc_hwpmcs[i + first_ri] = phw; - } - /* Clear the MMCRs, and set FC, to disable all PMCs. */ /* 970 PMC is not counted when set to 0x08 */ mtspr(SPR_MMCR0, SPR_MMCR0_FC | SPR_MMCR0_PMXE | SPR_MMCR0_FCECE | SPR_MMCR0_PMC1CE | SPR_MMCR0_PMCNCE | SPR_MMCR0_PMC1SEL(0x8) | SPR_MMCR0_PMC2SEL(0x8)); mtspr(SPR_MMCR1, 0x4218420); - return 0; + return (0); } static int ppc970_pcpu_fini(struct pmc_mdep *md, int cpu) { - register_t mmcr0 = mfspr(SPR_MMCR0); + register_t mmcr0; - mmcr0 |= SPR_MMCR0_FC; + /* Freeze counters, disable interrupts */ + mmcr0 = mfspr(SPR_MMCR0); mmcr0 &= ~SPR_MMCR0_PMXE; + mmcr0 |= SPR_MMCR0_FC; mtspr(SPR_MMCR0, mmcr0); - free(powerpc_pcpu[cpu]->pc_ppcpmcs, M_PMC); - free(powerpc_pcpu[cpu], M_PMC); - - return 0; + return (powerpc_pcpu_fini(md, cpu)); } -static int -ppc970_allocate_pmc(int cpu, int ri, struct pmc *pm, - const struct pmc_op_pmcallocate *a) +static void +ppc970_resume_pmc(bool ie) { - enum pmc_event pe; - uint32_t caps, config = 0, counter = 0; - int i; + register_t mmcr0; - KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), - ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < PPC970_MAX_PMCS, - ("[powerpc,%d] illegal row index %d", __LINE__, ri)); - - caps = a->pm_caps; - - pe = a->pm_ev; - - if (pe < PMC_EV_PPC970_FIRST || pe > PMC_EV_PPC970_LAST) - return (EINVAL); - - for (i = 0; i < ppc970_event_codes_size; i++) { - if (ppc970_event_codes[i].pe_event == pe) { - config = ppc970_event_codes[i].pe_code; - counter = ppc970_event_codes[i].pe_flags; - break; - } - } - if (i == ppc970_event_codes_size) - return (EINVAL); - - if ((counter & (1 << ri)) == 0) - return (EINVAL); - - if (caps & PMC_CAP_SYSTEM) - config |= POWERPC_PMC_KERNEL_ENABLE; - if (caps & PMC_CAP_USER) - config |= POWERPC_PMC_USER_ENABLE; - if ((caps & (PMC_CAP_USER | PMC_CAP_SYSTEM)) == 0) - config |= POWERPC_PMC_ENABLE; - - pm->pm_md.pm_powerpc.pm_powerpc_evsel = config; - - PMCDBG2(MDP,ALL,2,"powerpc-allocate ri=%d -> config=0x%x", ri, config); - - return 0; + /* Unfreeze counters and re-enable PERF exceptions if requested. */ + mmcr0 = mfspr(SPR_MMCR0); + mmcr0 &= ~(SPR_MMCR0_FC | SPR_MMCR0_PMXE); + if (ie) + mmcr0 |= SPR_MMCR0_PMXE; + mtspr(SPR_MMCR0, mmcr0); } -static int -ppc970_release_pmc(int cpu, int ri, struct pmc *pmc) -{ - struct pmc_hw *phw; - - KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), - ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < PPC970_MAX_PMCS, - ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); - - phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; - KASSERT(phw->phw_pmc == NULL, - ("[powerpc,%d] PHW pmc %p non-NULL", __LINE__, phw->phw_pmc)); - - return 0; -} - int pmc_ppc970_initialize(struct pmc_mdep *pmc_mdep) { struct pmc_classdep *pcd; pmc_mdep->pmd_cputype = PMC_CPU_PPC_970; pcd = &pmc_mdep->pmd_classdep[PMC_MDEP_CLASS_INDEX_POWERPC]; pcd->pcd_caps = POWERPC_PMC_CAPS; pcd->pcd_class = PMC_CLASS_PPC970; pcd->pcd_num = PPC970_MAX_PMCS; pcd->pcd_ri = pmc_mdep->pmd_npmc; pcd->pcd_width = 32; - pcd->pcd_allocate_pmc = ppc970_allocate_pmc; - pcd->pcd_config_pmc = ppc970_config_pmc; + pcd->pcd_allocate_pmc = powerpc_allocate_pmc; + pcd->pcd_config_pmc = powerpc_config_pmc; pcd->pcd_pcpu_fini = ppc970_pcpu_fini; pcd->pcd_pcpu_init = ppc970_pcpu_init; pcd->pcd_describe = powerpc_describe; pcd->pcd_get_config = powerpc_get_config; - pcd->pcd_read_pmc = ppc970_read_pmc; - pcd->pcd_release_pmc = ppc970_release_pmc; - pcd->pcd_start_pmc = ppc970_start_pmc; - pcd->pcd_stop_pmc = ppc970_stop_pmc; - pcd->pcd_write_pmc = ppc970_write_pmc; + pcd->pcd_read_pmc = powerpc_read_pmc; + pcd->pcd_release_pmc = powerpc_release_pmc; + pcd->pcd_start_pmc = powerpc_start_pmc; + pcd->pcd_stop_pmc = powerpc_stop_pmc; + pcd->pcd_write_pmc = powerpc_write_pmc; pmc_mdep->pmd_npmc += PPC970_MAX_PMCS; - pmc_mdep->pmd_intr = ppc970_intr; + pmc_mdep->pmd_intr = powerpc_pmc_intr; + + ppc_event_codes = ppc970_event_codes; + ppc_event_codes_size = ppc970_event_codes_size; + ppc_event_first = PMC_EV_PPC970_FIRST; + ppc_event_last = PMC_EV_PPC970_LAST; + ppc_max_pmcs = PPC970_MAX_PMCS; + + powerpc_set_pmc = ppc970_set_pmc; + powerpc_pmcn_read = powerpc_pmcn_read_default; + powerpc_pmcn_write = powerpc_pmcn_write_default; + powerpc_resume_pmc = ppc970_resume_pmc; return (0); } Index: head/sys/dev/hwpmc/pmc_events.h =================================================================== --- head/sys/dev/hwpmc/pmc_events.h (revision 367389) +++ head/sys/dev/hwpmc/pmc_events.h (revision 367390) @@ -1,1914 +1,1952 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2005 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _DEV_HWPMC_PMC_EVENTS_H_ #define _DEV_HWPMC_PMC_EVENTS_H_ /* * Note: Documentation on adding events can be found both in * the source tree at src/share/doc/papers/hwpmc/hwpmc.ms * as well as on-line at: * * https://wiki.freebsd.org/PmcTools/PmcHardwareHowTo * * Please refer to those resources before you attempt to modify * this file or the hwpmc driver/subsystem. */ /* * PMC event codes. * * __PMC_EV(CLASS, SYMBOLIC-NAME) * */ /* timestamp counters. */ #define __PMC_EV_TSC() \ __PMC_EV(TSC, TSC) #define PMC_EV_TSC_FIRST PMC_EV_TSC_TSC #define PMC_EV_TSC_LAST PMC_EV_TSC_TSC /* * Software events are dynamically defined. */ #define PMC_EV_DYN_COUNT 0x1000 #define PMC_EV_SOFT_FIRST 0x20000 #define PMC_EV_SOFT_LAST (PMC_EV_SOFT_FIRST + PMC_EV_DYN_COUNT - 1) /* * AMD K7 Events, from "The AMD Athlon(tm) Processor x86 Code * Optimization Guide" [Doc#22007K, Feb 2002] */ #define __PMC_EV_K7() \ __PMC_EV(K7, DC_ACCESSES) \ __PMC_EV(K7, DC_MISSES) \ __PMC_EV(K7, DC_REFILLS_FROM_L2) \ __PMC_EV(K7, DC_REFILLS_FROM_SYSTEM) \ __PMC_EV(K7, DC_WRITEBACKS) \ __PMC_EV(K7, L1_DTLB_MISS_AND_L2_DTLB_HITS) \ __PMC_EV(K7, L1_AND_L2_DTLB_MISSES) \ __PMC_EV(K7, MISALIGNED_REFERENCES) \ __PMC_EV(K7, IC_FETCHES) \ __PMC_EV(K7, IC_MISSES) \ __PMC_EV(K7, L1_ITLB_MISSES) \ __PMC_EV(K7, L1_L2_ITLB_MISSES) \ __PMC_EV(K7, RETIRED_INSTRUCTIONS) \ __PMC_EV(K7, RETIRED_OPS) \ __PMC_EV(K7, RETIRED_BRANCHES) \ __PMC_EV(K7, RETIRED_BRANCHES_MISPREDICTED) \ __PMC_EV(K7, RETIRED_TAKEN_BRANCHES) \ __PMC_EV(K7, RETIRED_TAKEN_BRANCHES_MISPREDICTED) \ __PMC_EV(K7, RETIRED_FAR_CONTROL_TRANSFERS) \ __PMC_EV(K7, RETIRED_RESYNC_BRANCHES) \ __PMC_EV(K7, INTERRUPTS_MASKED_CYCLES) \ __PMC_EV(K7, INTERRUPTS_MASKED_WHILE_PENDING_CYCLES) \ __PMC_EV(K7, HARDWARE_INTERRUPTS) #define PMC_EV_K7_FIRST PMC_EV_K7_DC_ACCESSES #define PMC_EV_K7_LAST PMC_EV_K7_HARDWARE_INTERRUPTS /* AMD K8 PMCs */ #define __PMC_EV_K8() \ __PMC_EV(K8, FP_DISPATCHED_FPU_OPS) \ __PMC_EV(K8, FP_CYCLES_WITH_NO_FPU_OPS_RETIRED) \ __PMC_EV(K8, FP_DISPATCHED_FPU_FAST_FLAG_OPS) \ __PMC_EV(K8, LS_SEGMENT_REGISTER_LOAD) \ __PMC_EV(K8, LS_MICROARCHITECTURAL_RESYNC_BY_SELF_MODIFYING_CODE) \ __PMC_EV(K8, LS_MICROARCHITECTURAL_RESYNC_BY_SNOOP) \ __PMC_EV(K8, LS_BUFFER2_FULL) \ __PMC_EV(K8, LS_LOCKED_OPERATION) \ __PMC_EV(K8, LS_MICROARCHITECTURAL_LATE_CANCEL) \ __PMC_EV(K8, LS_RETIRED_CFLUSH_INSTRUCTIONS) \ __PMC_EV(K8, LS_RETIRED_CPUID_INSTRUCTIONS) \ __PMC_EV(K8, DC_ACCESS) \ __PMC_EV(K8, DC_MISS) \ __PMC_EV(K8, DC_REFILL_FROM_L2) \ __PMC_EV(K8, DC_REFILL_FROM_SYSTEM) \ __PMC_EV(K8, DC_COPYBACK) \ __PMC_EV(K8, DC_L1_DTLB_MISS_AND_L2_DTLB_HIT) \ __PMC_EV(K8, DC_L1_DTLB_MISS_AND_L2_DTLB_MISS) \ __PMC_EV(K8, DC_MISALIGNED_DATA_REFERENCE) \ __PMC_EV(K8, DC_MICROARCHITECTURAL_LATE_CANCEL) \ __PMC_EV(K8, DC_MICROARCHITECTURAL_EARLY_CANCEL) \ __PMC_EV(K8, DC_ONE_BIT_ECC_ERROR) \ __PMC_EV(K8, DC_DISPATCHED_PREFETCH_INSTRUCTIONS) \ __PMC_EV(K8, DC_DCACHE_ACCESSES_BY_LOCKS) \ __PMC_EV(K8, BU_CPU_CLK_UNHALTED) \ __PMC_EV(K8, BU_INTERNAL_L2_REQUEST) \ __PMC_EV(K8, BU_FILL_REQUEST_L2_MISS) \ __PMC_EV(K8, BU_FILL_INTO_L2) \ __PMC_EV(K8, IC_FETCH) \ __PMC_EV(K8, IC_MISS) \ __PMC_EV(K8, IC_REFILL_FROM_L2) \ __PMC_EV(K8, IC_REFILL_FROM_SYSTEM) \ __PMC_EV(K8, IC_L1_ITLB_MISS_AND_L2_ITLB_HIT) \ __PMC_EV(K8, IC_L1_ITLB_MISS_AND_L2_ITLB_MISS) \ __PMC_EV(K8, IC_MICROARCHITECTURAL_RESYNC_BY_SNOOP) \ __PMC_EV(K8, IC_INSTRUCTION_FETCH_STALL) \ __PMC_EV(K8, IC_RETURN_STACK_HIT) \ __PMC_EV(K8, IC_RETURN_STACK_OVERFLOW) \ __PMC_EV(K8, FR_RETIRED_X86_INSTRUCTIONS) \ __PMC_EV(K8, FR_RETIRED_UOPS) \ __PMC_EV(K8, FR_RETIRED_BRANCHES) \ __PMC_EV(K8, FR_RETIRED_BRANCHES_MISPREDICTED) \ __PMC_EV(K8, FR_RETIRED_TAKEN_BRANCHES) \ __PMC_EV(K8, FR_RETIRED_TAKEN_BRANCHES_MISPREDICTED) \ __PMC_EV(K8, FR_RETIRED_FAR_CONTROL_TRANSFERS) \ __PMC_EV(K8, FR_RETIRED_RESYNCS) \ __PMC_EV(K8, FR_RETIRED_NEAR_RETURNS) \ __PMC_EV(K8, FR_RETIRED_NEAR_RETURNS_MISPREDICTED) \ __PMC_EV(K8, FR_RETIRED_TAKEN_BRANCHES_MISPREDICTED_BY_ADDR_MISCOMPARE) \ __PMC_EV(K8, FR_RETIRED_FPU_INSTRUCTIONS) \ __PMC_EV(K8, FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS) \ __PMC_EV(K8, FR_INTERRUPTS_MASKED_CYCLES) \ __PMC_EV(K8, FR_INTERRUPTS_MASKED_WHILE_PENDING_CYCLES) \ __PMC_EV(K8, FR_TAKEN_HARDWARE_INTERRUPTS) \ __PMC_EV(K8, FR_DECODER_EMPTY) \ __PMC_EV(K8, FR_DISPATCH_STALLS) \ __PMC_EV(K8, FR_DISPATCH_STALL_FROM_BRANCH_ABORT_TO_RETIRE) \ __PMC_EV(K8, FR_DISPATCH_STALL_FOR_SERIALIZATION) \ __PMC_EV(K8, FR_DISPATCH_STALL_FOR_SEGMENT_LOAD) \ __PMC_EV(K8, FR_DISPATCH_STALL_WHEN_REORDER_BUFFER_IS_FULL) \ __PMC_EV(K8, FR_DISPATCH_STALL_WHEN_RESERVATION_STATIONS_ARE_FULL) \ __PMC_EV(K8, FR_DISPATCH_STALL_WHEN_FPU_IS_FULL) \ __PMC_EV(K8, FR_DISPATCH_STALL_WHEN_LS_IS_FULL) \ __PMC_EV(K8, FR_DISPATCH_STALL_WHEN_WAITING_FOR_ALL_TO_BE_QUIET) \ __PMC_EV(K8, FR_DISPATCH_STALL_WHEN_FAR_XFER_OR_RESYNC_BRANCH_PENDING) \ __PMC_EV(K8, FR_FPU_EXCEPTIONS) \ __PMC_EV(K8, FR_NUMBER_OF_BREAKPOINTS_FOR_DR0) \ __PMC_EV(K8, FR_NUMBER_OF_BREAKPOINTS_FOR_DR1) \ __PMC_EV(K8, FR_NUMBER_OF_BREAKPOINTS_FOR_DR2) \ __PMC_EV(K8, FR_NUMBER_OF_BREAKPOINTS_FOR_DR3) \ __PMC_EV(K8, NB_MEMORY_CONTROLLER_PAGE_ACCESS_EVENT) \ __PMC_EV(K8, NB_MEMORY_CONTROLLER_PAGE_TABLE_OVERFLOW) \ __PMC_EV(K8, NB_MEMORY_CONTROLLER_DRAM_COMMAND_SLOTS_MISSED) \ __PMC_EV(K8, NB_MEMORY_CONTROLLER_TURNAROUND) \ __PMC_EV(K8, NB_MEMORY_CONTROLLER_BYPASS_SATURATION) \ __PMC_EV(K8, NB_SIZED_COMMANDS) \ __PMC_EV(K8, NB_PROBE_RESULT) \ __PMC_EV(K8, NB_HT_BUS0_BANDWIDTH) \ __PMC_EV(K8, NB_HT_BUS1_BANDWIDTH) \ __PMC_EV(K8, NB_HT_BUS2_BANDWIDTH) #define PMC_EV_K8_FIRST PMC_EV_K8_FP_DISPATCHED_FPU_OPS #define PMC_EV_K8_LAST PMC_EV_K8_NB_HT_BUS2_BANDWIDTH /* * Events supported by Intel architectural fixed function counters, * from the "Intel 64 and IA-32 Architectures Software Developer's * Manual Volume 3B: System Programming Guide, Part 2", July 2008. */ #define __PMC_EV_IAF() \ __PMC_EV(IAF, INSTR_RETIRED_ANY) \ __PMC_EV(IAF, CPU_CLK_UNHALTED_CORE) \ __PMC_EV(IAF, CPU_CLK_UNHALTED_REF) #define PMC_EV_IAF_FIRST PMC_EV_IAF_INSTR_RETIRED_ANY #define PMC_EV_IAF_LAST PMC_EV_IAF_CPU_CLK_UNHALTED_REF #define __PMC_EV_ALIAS_IAF() \ __PMC_EV_ALIAS("instruction-retired", IAF_INSTR_RETIRED_ANY) \ __PMC_EV_ALIAS("unhalted-core-cycles", IAF_CPU_CLK_UNHALTED_CORE) \ __PMC_EV_ALIAS("unhalted-reference-cycles", IAF_CPU_CLK_UNHALTED_REF) #define PMC_EV_IAP_FIRST PMC_EV_IAP_ARCH_BR_INS_RET #define PMC_EV_IAP_LAST PMC_EV_IAP_EVENT_FDH_40H /* * Map "architectural" event names to event ids. */ #define __PMC_EV_ALIAS_INTEL_ARCHITECTURAL() \ __PMC_EV_ALIAS("branch-instruction-retired", IAP_ARCH_BR_INS_RET) \ __PMC_EV_ALIAS("branch-misses-retired", IAP_ARCH_BR_MIS_RET) \ __PMC_EV_ALIAS("instruction-retired", IAP_ARCH_INS_RET) \ __PMC_EV_ALIAS("llc-misses", IAP_ARCH_LLC_MIS) \ __PMC_EV_ALIAS("llc-reference", IAP_ARCH_LLC_REF) \ __PMC_EV_ALIAS("unhalted-reference-cycles", IAP_ARCH_UNH_REF_CYC) \ __PMC_EV_ALIAS("unhalted-core-cycles", IAP_ARCH_UNH_COR_CYC) #define __PMC_EV_UCP() \ __PMC_EV(UCP, EVENT_0CH_04H_E) \ __PMC_EV(UCP, EVENT_0CH_04H_F) \ __PMC_EV(UCP, EVENT_0CH_04H_M) \ __PMC_EV(UCP, EVENT_0CH_04H_S) \ __PMC_EV(UCP, EVENT_0CH_08H_E) \ __PMC_EV(UCP, EVENT_0CH_08H_F) \ __PMC_EV(UCP, EVENT_0CH_08H_M) \ __PMC_EV(UCP, EVENT_0CH_08H_S) \ /* * Intel XScale events from: * * Intel XScale Core Developer's Manual * January, 2004, #27347302 * * 3rd Generation Intel XScale Microarchitecture * Developer's Manual * May 2007, #31628302 * * First 14 events are for 1st and 2nd Generation Intel XScale cores. The * remaining are available only on 3rd Generation Intel XScale cores. */ #define __PMC_EV_XSCALE() \ __PMC_EV(XSCALE, IC_FETCH) \ __PMC_EV(XSCALE, IC_MISS) \ __PMC_EV(XSCALE, DATA_DEPENDENCY_STALLED) \ __PMC_EV(XSCALE, ITLB_MISS) \ __PMC_EV(XSCALE, DTLB_MISS) \ __PMC_EV(XSCALE, BRANCH_RETIRED) \ __PMC_EV(XSCALE, BRANCH_MISPRED) \ __PMC_EV(XSCALE, INSTR_RETIRED) \ __PMC_EV(XSCALE, DC_FULL_CYCLE) \ __PMC_EV(XSCALE, DC_FULL_CONTIG) \ __PMC_EV(XSCALE, DC_ACCESS) \ __PMC_EV(XSCALE, DC_MISS) \ __PMC_EV(XSCALE, DC_WRITEBACK) \ __PMC_EV(XSCALE, PC_CHANGE) \ __PMC_EV(XSCALE, BRANCH_RETIRED_ALL) \ __PMC_EV(XSCALE, INSTR_CYCLE) \ __PMC_EV(XSCALE, CP_STALL) \ __PMC_EV(XSCALE, PC_CHANGE_ALL) \ __PMC_EV(XSCALE, PIPELINE_FLUSH) \ __PMC_EV(XSCALE, BACKEND_STALL) \ __PMC_EV(XSCALE, MULTIPLIER_USE) \ __PMC_EV(XSCALE, MULTIPLIER_STALLED) \ __PMC_EV(XSCALE, DATA_CACHE_STALLED) \ __PMC_EV(XSCALE, L2_CACHE_REQ) \ __PMC_EV(XSCALE, L2_CACHE_MISS) \ __PMC_EV(XSCALE, ADDRESS_BUS_TRANS) \ __PMC_EV(XSCALE, SELF_ADDRESS_BUS_TRANS) \ __PMC_EV(XSCALE, DATA_BUS_TRANS) #define PMC_EV_XSCALE_FIRST PMC_EV_XSCALE_IC_FETCH #define PMC_EV_XSCALE_LAST PMC_EV_XSCALE_DATA_BUS_TRANS /* * ARMv7 Events */ #define __PMC_EV_ARMV7() \ __PMC_EV(ARMV7, EVENT_00H) \ __PMC_EV(ARMV7, EVENT_01H) \ __PMC_EV(ARMV7, EVENT_02H) \ __PMC_EV(ARMV7, EVENT_03H) \ __PMC_EV(ARMV7, EVENT_04H) \ __PMC_EV(ARMV7, EVENT_05H) \ __PMC_EV(ARMV7, EVENT_06H) \ __PMC_EV(ARMV7, EVENT_07H) \ __PMC_EV(ARMV7, EVENT_08H) \ __PMC_EV(ARMV7, EVENT_09H) \ __PMC_EV(ARMV7, EVENT_0AH) \ __PMC_EV(ARMV7, EVENT_0BH) \ __PMC_EV(ARMV7, EVENT_0CH) \ __PMC_EV(ARMV7, EVENT_0DH) \ __PMC_EV(ARMV7, EVENT_0EH) \ __PMC_EV(ARMV7, EVENT_0FH) \ __PMC_EV(ARMV7, EVENT_10H) \ __PMC_EV(ARMV7, EVENT_11H) \ __PMC_EV(ARMV7, EVENT_12H) \ __PMC_EV(ARMV7, EVENT_13H) \ __PMC_EV(ARMV7, EVENT_14H) \ __PMC_EV(ARMV7, EVENT_15H) \ __PMC_EV(ARMV7, EVENT_16H) \ __PMC_EV(ARMV7, EVENT_17H) \ __PMC_EV(ARMV7, EVENT_18H) \ __PMC_EV(ARMV7, EVENT_19H) \ __PMC_EV(ARMV7, EVENT_1AH) \ __PMC_EV(ARMV7, EVENT_1BH) \ __PMC_EV(ARMV7, EVENT_1CH) \ __PMC_EV(ARMV7, EVENT_1DH) \ __PMC_EV(ARMV7, EVENT_1EH) \ __PMC_EV(ARMV7, EVENT_1FH) \ __PMC_EV(ARMV7, EVENT_20H) \ __PMC_EV(ARMV7, EVENT_21H) \ __PMC_EV(ARMV7, EVENT_22H) \ __PMC_EV(ARMV7, EVENT_23H) \ __PMC_EV(ARMV7, EVENT_24H) \ __PMC_EV(ARMV7, EVENT_25H) \ __PMC_EV(ARMV7, EVENT_26H) \ __PMC_EV(ARMV7, EVENT_27H) \ __PMC_EV(ARMV7, EVENT_28H) \ __PMC_EV(ARMV7, EVENT_29H) \ __PMC_EV(ARMV7, EVENT_2AH) \ __PMC_EV(ARMV7, EVENT_2BH) \ __PMC_EV(ARMV7, EVENT_2CH) \ __PMC_EV(ARMV7, EVENT_2DH) \ __PMC_EV(ARMV7, EVENT_2EH) \ __PMC_EV(ARMV7, EVENT_2FH) \ __PMC_EV(ARMV7, EVENT_30H) \ __PMC_EV(ARMV7, EVENT_31H) \ __PMC_EV(ARMV7, EVENT_32H) \ __PMC_EV(ARMV7, EVENT_33H) \ __PMC_EV(ARMV7, EVENT_34H) \ __PMC_EV(ARMV7, EVENT_35H) \ __PMC_EV(ARMV7, EVENT_36H) \ __PMC_EV(ARMV7, EVENT_37H) \ __PMC_EV(ARMV7, EVENT_38H) \ __PMC_EV(ARMV7, EVENT_39H) \ __PMC_EV(ARMV7, EVENT_3AH) \ __PMC_EV(ARMV7, EVENT_3BH) \ __PMC_EV(ARMV7, EVENT_3CH) \ __PMC_EV(ARMV7, EVENT_3DH) \ __PMC_EV(ARMV7, EVENT_3EH) \ __PMC_EV(ARMV7, EVENT_3FH) \ __PMC_EV(ARMV7, EVENT_40H) \ __PMC_EV(ARMV7, EVENT_41H) \ __PMC_EV(ARMV7, EVENT_42H) \ __PMC_EV(ARMV7, EVENT_43H) \ __PMC_EV(ARMV7, EVENT_44H) \ __PMC_EV(ARMV7, EVENT_45H) \ __PMC_EV(ARMV7, EVENT_46H) \ __PMC_EV(ARMV7, EVENT_47H) \ __PMC_EV(ARMV7, EVENT_48H) \ __PMC_EV(ARMV7, EVENT_49H) \ __PMC_EV(ARMV7, EVENT_4AH) \ __PMC_EV(ARMV7, EVENT_4BH) \ __PMC_EV(ARMV7, EVENT_4CH) \ __PMC_EV(ARMV7, EVENT_4DH) \ __PMC_EV(ARMV7, EVENT_4EH) \ __PMC_EV(ARMV7, EVENT_4FH) \ __PMC_EV(ARMV7, EVENT_50H) \ __PMC_EV(ARMV7, EVENT_51H) \ __PMC_EV(ARMV7, EVENT_52H) \ __PMC_EV(ARMV7, EVENT_53H) \ __PMC_EV(ARMV7, EVENT_54H) \ __PMC_EV(ARMV7, EVENT_55H) \ __PMC_EV(ARMV7, EVENT_56H) \ __PMC_EV(ARMV7, EVENT_57H) \ __PMC_EV(ARMV7, EVENT_58H) \ __PMC_EV(ARMV7, EVENT_59H) \ __PMC_EV(ARMV7, EVENT_5AH) \ __PMC_EV(ARMV7, EVENT_5BH) \ __PMC_EV(ARMV7, EVENT_5CH) \ __PMC_EV(ARMV7, EVENT_5DH) \ __PMC_EV(ARMV7, EVENT_5EH) \ __PMC_EV(ARMV7, EVENT_5FH) \ __PMC_EV(ARMV7, EVENT_60H) \ __PMC_EV(ARMV7, EVENT_61H) \ __PMC_EV(ARMV7, EVENT_62H) \ __PMC_EV(ARMV7, EVENT_63H) \ __PMC_EV(ARMV7, EVENT_64H) \ __PMC_EV(ARMV7, EVENT_65H) \ __PMC_EV(ARMV7, EVENT_66H) \ __PMC_EV(ARMV7, EVENT_67H) \ __PMC_EV(ARMV7, EVENT_68H) \ __PMC_EV(ARMV7, EVENT_69H) \ __PMC_EV(ARMV7, EVENT_6AH) \ __PMC_EV(ARMV7, EVENT_6BH) \ __PMC_EV(ARMV7, EVENT_6CH) \ __PMC_EV(ARMV7, EVENT_6DH) \ __PMC_EV(ARMV7, EVENT_6EH) \ __PMC_EV(ARMV7, EVENT_6FH) \ __PMC_EV(ARMV7, EVENT_70H) \ __PMC_EV(ARMV7, EVENT_71H) \ __PMC_EV(ARMV7, EVENT_72H) \ __PMC_EV(ARMV7, EVENT_73H) \ __PMC_EV(ARMV7, EVENT_74H) \ __PMC_EV(ARMV7, EVENT_75H) \ __PMC_EV(ARMV7, EVENT_76H) \ __PMC_EV(ARMV7, EVENT_77H) \ __PMC_EV(ARMV7, EVENT_78H) \ __PMC_EV(ARMV7, EVENT_79H) \ __PMC_EV(ARMV7, EVENT_7AH) \ __PMC_EV(ARMV7, EVENT_7BH) \ __PMC_EV(ARMV7, EVENT_7CH) \ __PMC_EV(ARMV7, EVENT_7DH) \ __PMC_EV(ARMV7, EVENT_7EH) \ __PMC_EV(ARMV7, EVENT_7FH) \ __PMC_EV(ARMV7, EVENT_80H) \ __PMC_EV(ARMV7, EVENT_81H) \ __PMC_EV(ARMV7, EVENT_82H) \ __PMC_EV(ARMV7, EVENT_83H) \ __PMC_EV(ARMV7, EVENT_84H) \ __PMC_EV(ARMV7, EVENT_85H) \ __PMC_EV(ARMV7, EVENT_86H) \ __PMC_EV(ARMV7, EVENT_87H) \ __PMC_EV(ARMV7, EVENT_88H) \ __PMC_EV(ARMV7, EVENT_89H) \ __PMC_EV(ARMV7, EVENT_8AH) \ __PMC_EV(ARMV7, EVENT_8BH) \ __PMC_EV(ARMV7, EVENT_8CH) \ __PMC_EV(ARMV7, EVENT_8DH) \ __PMC_EV(ARMV7, EVENT_8EH) \ __PMC_EV(ARMV7, EVENT_8FH) \ __PMC_EV(ARMV7, EVENT_90H) \ __PMC_EV(ARMV7, EVENT_91H) \ __PMC_EV(ARMV7, EVENT_92H) \ __PMC_EV(ARMV7, EVENT_93H) \ __PMC_EV(ARMV7, EVENT_94H) \ __PMC_EV(ARMV7, EVENT_95H) \ __PMC_EV(ARMV7, EVENT_96H) \ __PMC_EV(ARMV7, EVENT_97H) \ __PMC_EV(ARMV7, EVENT_98H) \ __PMC_EV(ARMV7, EVENT_99H) \ __PMC_EV(ARMV7, EVENT_9AH) \ __PMC_EV(ARMV7, EVENT_9BH) \ __PMC_EV(ARMV7, EVENT_9CH) \ __PMC_EV(ARMV7, EVENT_9DH) \ __PMC_EV(ARMV7, EVENT_9EH) \ __PMC_EV(ARMV7, EVENT_9FH) \ __PMC_EV(ARMV7, EVENT_A0H) \ __PMC_EV(ARMV7, EVENT_A1H) \ __PMC_EV(ARMV7, EVENT_A2H) \ __PMC_EV(ARMV7, EVENT_A3H) \ __PMC_EV(ARMV7, EVENT_A4H) \ __PMC_EV(ARMV7, EVENT_A5H) \ __PMC_EV(ARMV7, EVENT_A6H) \ __PMC_EV(ARMV7, EVENT_A7H) \ __PMC_EV(ARMV7, EVENT_A8H) \ __PMC_EV(ARMV7, EVENT_A9H) \ __PMC_EV(ARMV7, EVENT_AAH) \ __PMC_EV(ARMV7, EVENT_ABH) \ __PMC_EV(ARMV7, EVENT_ACH) \ __PMC_EV(ARMV7, EVENT_ADH) \ __PMC_EV(ARMV7, EVENT_AEH) \ __PMC_EV(ARMV7, EVENT_AFH) \ __PMC_EV(ARMV7, EVENT_B0H) \ __PMC_EV(ARMV7, EVENT_B1H) \ __PMC_EV(ARMV7, EVENT_B2H) \ __PMC_EV(ARMV7, EVENT_B3H) \ __PMC_EV(ARMV7, EVENT_B4H) \ __PMC_EV(ARMV7, EVENT_B5H) \ __PMC_EV(ARMV7, EVENT_B6H) \ __PMC_EV(ARMV7, EVENT_B7H) \ __PMC_EV(ARMV7, EVENT_B8H) \ __PMC_EV(ARMV7, EVENT_B9H) \ __PMC_EV(ARMV7, EVENT_BAH) \ __PMC_EV(ARMV7, EVENT_BBH) \ __PMC_EV(ARMV7, EVENT_BCH) \ __PMC_EV(ARMV7, EVENT_BDH) \ __PMC_EV(ARMV7, EVENT_BEH) \ __PMC_EV(ARMV7, EVENT_BFH) \ __PMC_EV(ARMV7, EVENT_C0H) \ __PMC_EV(ARMV7, EVENT_C1H) \ __PMC_EV(ARMV7, EVENT_C2H) \ __PMC_EV(ARMV7, EVENT_C3H) \ __PMC_EV(ARMV7, EVENT_C4H) \ __PMC_EV(ARMV7, EVENT_C5H) \ __PMC_EV(ARMV7, EVENT_C6H) \ __PMC_EV(ARMV7, EVENT_C7H) \ __PMC_EV(ARMV7, EVENT_C8H) \ __PMC_EV(ARMV7, EVENT_C9H) \ __PMC_EV(ARMV7, EVENT_CAH) \ __PMC_EV(ARMV7, EVENT_CBH) \ __PMC_EV(ARMV7, EVENT_CCH) \ __PMC_EV(ARMV7, EVENT_CDH) \ __PMC_EV(ARMV7, EVENT_CEH) \ __PMC_EV(ARMV7, EVENT_CFH) \ __PMC_EV(ARMV7, EVENT_D0H) \ __PMC_EV(ARMV7, EVENT_D1H) \ __PMC_EV(ARMV7, EVENT_D2H) \ __PMC_EV(ARMV7, EVENT_D3H) \ __PMC_EV(ARMV7, EVENT_D4H) \ __PMC_EV(ARMV7, EVENT_D5H) \ __PMC_EV(ARMV7, EVENT_D6H) \ __PMC_EV(ARMV7, EVENT_D7H) \ __PMC_EV(ARMV7, EVENT_D8H) \ __PMC_EV(ARMV7, EVENT_D9H) \ __PMC_EV(ARMV7, EVENT_DAH) \ __PMC_EV(ARMV7, EVENT_DBH) \ __PMC_EV(ARMV7, EVENT_DCH) \ __PMC_EV(ARMV7, EVENT_DDH) \ __PMC_EV(ARMV7, EVENT_DEH) \ __PMC_EV(ARMV7, EVENT_DFH) \ __PMC_EV(ARMV7, EVENT_E0H) \ __PMC_EV(ARMV7, EVENT_E1H) \ __PMC_EV(ARMV7, EVENT_E2H) \ __PMC_EV(ARMV7, EVENT_E3H) \ __PMC_EV(ARMV7, EVENT_E4H) \ __PMC_EV(ARMV7, EVENT_E5H) \ __PMC_EV(ARMV7, EVENT_E6H) \ __PMC_EV(ARMV7, EVENT_E7H) \ __PMC_EV(ARMV7, EVENT_E8H) \ __PMC_EV(ARMV7, EVENT_E9H) \ __PMC_EV(ARMV7, EVENT_EAH) \ __PMC_EV(ARMV7, EVENT_EBH) \ __PMC_EV(ARMV7, EVENT_ECH) \ __PMC_EV(ARMV7, EVENT_EDH) \ __PMC_EV(ARMV7, EVENT_EEH) \ __PMC_EV(ARMV7, EVENT_EFH) \ __PMC_EV(ARMV7, EVENT_F0H) \ __PMC_EV(ARMV7, EVENT_F1H) \ __PMC_EV(ARMV7, EVENT_F2H) \ __PMC_EV(ARMV7, EVENT_F3H) \ __PMC_EV(ARMV7, EVENT_F4H) \ __PMC_EV(ARMV7, EVENT_F5H) \ __PMC_EV(ARMV7, EVENT_F6H) \ __PMC_EV(ARMV7, EVENT_F7H) \ __PMC_EV(ARMV7, EVENT_F8H) \ __PMC_EV(ARMV7, EVENT_F9H) \ __PMC_EV(ARMV7, EVENT_FAH) \ __PMC_EV(ARMV7, EVENT_FBH) \ __PMC_EV(ARMV7, EVENT_FCH) \ __PMC_EV(ARMV7, EVENT_FDH) \ __PMC_EV(ARMV7, EVENT_FEH) \ __PMC_EV(ARMV7, EVENT_FFH) #define PMC_EV_ARMV7_FIRST PMC_EV_ARMV7_EVENT_00H #define PMC_EV_ARMV7_LAST PMC_EV_ARMV7_EVENT_FFH #define __PMC_EV_ALIAS_ARMV7_COMMON() \ __PMC_EV_ALIAS("PMNC_SW_INCR", ARMV7_EVENT_00H) \ __PMC_EV_ALIAS("L1_ICACHE_REFILL", ARMV7_EVENT_01H) \ __PMC_EV_ALIAS("ITLB_REFILL", ARMV7_EVENT_02H) \ __PMC_EV_ALIAS("L1_DCACHE_REFILL", ARMV7_EVENT_03H) \ __PMC_EV_ALIAS("L1_DCACHE_ACCESS", ARMV7_EVENT_04H) \ __PMC_EV_ALIAS("DTLB_REFILL", ARMV7_EVENT_05H) \ __PMC_EV_ALIAS("MEM_READ", ARMV7_EVENT_06H) \ __PMC_EV_ALIAS("MEM_WRITE", ARMV7_EVENT_07H) \ __PMC_EV_ALIAS("EXC_TAKEN", ARMV7_EVENT_09H) \ __PMC_EV_ALIAS("EXC_EXECUTED", ARMV7_EVENT_0AH) \ __PMC_EV_ALIAS("CID_WRITE", ARMV7_EVENT_0BH) \ __PMC_EV_ALIAS("PC_WRITE", ARMV7_EVENT_0CH) \ __PMC_EV_ALIAS("PC_IMM_BRANCH", ARMV7_EVENT_0DH) \ __PMC_EV_ALIAS("MEM_UNALIGNED_ACCESS", ARMV7_EVENT_0FH) \ __PMC_EV_ALIAS("PC_BRANCH_MIS_PRED", ARMV7_EVENT_10H) \ __PMC_EV_ALIAS("CLOCK_CYCLES", ARMV7_EVENT_11H) \ __PMC_EV_ALIAS("PC_BRANCH_PRED", ARMV7_EVENT_12H) #define __PMC_EV_ALIAS_ARMV7_COMMON_A8() \ __PMC_EV_ALIAS_ARMV7_COMMON() \ __PMC_EV_ALIAS("INSTR_EXECUTED", ARMV7_EVENT_08H) \ __PMC_EV_ALIAS("PC_PROC_RETURN", ARMV7_EVENT_0EH) \ __PMC_EV_ALIAS("MEM_ACCESS", ARMV7_EVENT_13H) \ __PMC_EV_ALIAS("L1_ICACHE_ACCESS", ARMV7_EVENT_14H) \ __PMC_EV_ALIAS("L1_DCACHE_WB", ARMV7_EVENT_15H) \ __PMC_EV_ALIAS("L2_CACHE_ACCESS", ARMV7_EVENT_16H) \ __PMC_EV_ALIAS("L2_CACHE_REFILL", ARMV7_EVENT_17H) \ __PMC_EV_ALIAS("L2_CACHE_WB", ARMV7_EVENT_18H) \ __PMC_EV_ALIAS("BUS_ACCESS", ARMV7_EVENT_19H) \ __PMC_EV_ALIAS("MEM_ERROR", ARMV7_EVENT_1AH) \ __PMC_EV_ALIAS("INSTR_SPEC", ARMV7_EVENT_1BH) \ __PMC_EV_ALIAS("TTBR_WRITE", ARMV7_EVENT_1CH) \ __PMC_EV_ALIAS("BUS_CYCLES", ARMV7_EVENT_1DH) \ __PMC_EV_ALIAS("CPU_CYCLES", ARMV7_EVENT_FFH) #define __PMC_EV_ALIAS_ARMV7_CORTEX_A8() \ __PMC_EV_ALIAS_ARMV7_COMMON_A8() \ __PMC_EV_ALIAS("WRITE_BUF_FULL", ARMV7_EVENT_40H) \ __PMC_EV_ALIAS("L2_STORE_MERGED", ARMV7_EVENT_41H) \ __PMC_EV_ALIAS("L2_STORE_BUFFERABLE", ARMV7_EVENT_42H) \ __PMC_EV_ALIAS("L2_ACCESS", ARMV7_EVENT_43H) \ __PMC_EV_ALIAS("L2_CACHE_MISS", ARMV7_EVENT_44H) \ __PMC_EV_ALIAS("AXI_READ", ARMV7_EVENT_45H) \ __PMC_EV_ALIAS("AXI_WRITE", ARMV7_EVENT_46H) \ __PMC_EV_ALIAS("MEM_REPLAY_EVT", ARMV7_EVENT_47H) \ __PMC_EV_ALIAS("MEM_UNALIGNED_ACCESS_REPLAY", ARMV7_EVENT_48H) \ __PMC_EV_ALIAS("L1_DCACHE_HASH_MISS", ARMV7_EVENT_49H) \ __PMC_EV_ALIAS("L1_ICACHE_HASH_MISS", ARMV7_EVENT_4AH) \ __PMC_EV_ALIAS("L1_CACHE_PAGECOL_ALIAS", ARMV7_EVENT_4BH) \ __PMC_EV_ALIAS("L1_DCACHE_NEON_ACCESS", ARMV7_EVENT_4CH) \ __PMC_EV_ALIAS("L1_DCACHE_NEON_CACHEABLE", ARMV7_EVENT_4DH) \ __PMC_EV_ALIAS("L2_CACHE_NEON_MEM_ACCESS", ARMV7_EVENT_4EH) \ __PMC_EV_ALIAS("L2_CACHE_NEON_HIT", ARMV7_EVENT_4FH) \ __PMC_EV_ALIAS("L1_CACHE_ACCESS_NOCP15", ARMV7_EVENT_50H) \ __PMC_EV_ALIAS("RET_STACK_MISPREDICT", ARMV7_EVENT_51H) \ __PMC_EV_ALIAS("BRANCH_DIR_MISPREDICT", ARMV7_EVENT_52H) \ __PMC_EV_ALIAS("PRED_BRANCH_PRED_TAKEN", ARMV7_EVENT_53H) \ __PMC_EV_ALIAS("PRED_BRANCH_EXEC_TAKEN", ARMV7_EVENT_54H) \ __PMC_EV_ALIAS("OPS_ISSUED", ARMV7_EVENT_55H) \ __PMC_EV_ALIAS("CYCLES_NO_INSTRUCTION", ARMV7_EVENT_56H) \ __PMC_EV_ALIAS("INSTRUCTIONS_ISSUED_CYCLE", ARMV7_EVENT_57H) \ __PMC_EV_ALIAS("CYCLES_STALLED_NEON_MRC", ARMV7_EVENT_58H) \ __PMC_EV_ALIAS("CYCLES_STALLED_NEON_FULLQ", ARMV7_EVENT_59H) \ __PMC_EV_ALIAS("CYCLES_NONIDLE_NEON_INT", ARMV7_EVENT_5AH) \ __PMC_EV_ALIAS("PMUEXTIN0_EVT", ARMV7_EVENT_70H) \ __PMC_EV_ALIAS("PMUEXTIN1_EVT", ARMV7_EVENT_71H) \ __PMC_EV_ALIAS("PMUEXTIN_EVT", ARMV7_EVENT_72H) #define PMC_EV_ARMV7_CORTEX_A8_FIRST PMC_EV_ARMV7_PMNC_SW_INCR #define PMC_EV_ARMV7_CORTEX_A8_LAST PMC_EV_ARMV7_PMUEXTIN_EVT #define __PMC_EV_ALIAS_ARMV7_CORTEX_A9() \ __PMC_EV_ALIAS_ARMV7_COMMON() \ __PMC_EV_ALIAS("JAVA_BYTECODE", ARMV7_EVENT_40H) \ __PMC_EV_ALIAS("SOFTWARE_JAVA_BYTECODE", ARMV7_EVENT_41H) \ __PMC_EV_ALIAS("JAZELLE_BACKWARD_BRANCH", ARMV7_EVENT_42H) \ __PMC_EV_ALIAS("COHERENT_LINEFILL_MISSC", ARMV7_EVENT_50H) \ __PMC_EV_ALIAS("COHERENT_LINEFILL_HITC", ARMV7_EVENT_51H) \ __PMC_EV_ALIAS("INSTR_CACHE_DEPENDENT_STALL", ARMV7_EVENT_60H) \ __PMC_EV_ALIAS("DATA_CACHE_DEPENDENT_STALL", ARMV7_EVENT_61H) \ __PMC_EV_ALIAS("MAIN_TLB_MISS_STALL", ARMV7_EVENT_62H) \ __PMC_EV_ALIAS("STREX_PASSED", ARMV7_EVENT_63H) \ __PMC_EV_ALIAS("STREX_FAILED", ARMV7_EVENT_64H) \ __PMC_EV_ALIAS("DATA_EVICTION", ARMV7_EVENT_65H) \ __PMC_EV_ALIAS("ISSUE_DNOT_DISPATCH_ANY_INSTR", ARMV7_EVENT_66H) \ __PMC_EV_ALIAS("ISSUE_IS_EMPTY", ARMV7_EVENT_67H) \ __PMC_EV_ALIAS("INSTR_RENAMED", ARMV7_EVENT_68H) \ __PMC_EV_ALIAS("PREDICTABLE_FUNCTION_RETURN", ARMV7_EVENT_6EH) \ __PMC_EV_ALIAS("MAIN_EXECUTION_UNIT_PIPE", ARMV7_EVENT_70H) \ __PMC_EV_ALIAS("SECOND_EXECUTION_UNIT_PIPE", ARMV7_EVENT_71H) \ __PMC_EV_ALIAS("LOAD_STORE_PIPE", ARMV7_EVENT_72H) \ __PMC_EV_ALIAS("FLOATING_POINT_INSTR_RENAMED", ARMV7_EVENT_73H) \ __PMC_EV_ALIAS("NEON_INSTRS_RENAMED", ARMV7_EVENT_74H) \ __PMC_EV_ALIAS("PLD_STALL", ARMV7_EVENT_80H) \ __PMC_EV_ALIAS("WRITE_STALL", ARMV7_EVENT_81H) \ __PMC_EV_ALIAS("INSTR_MAIN_TLB_MISS_STALL", ARMV7_EVENT_82H) \ __PMC_EV_ALIAS("DATA_MAIN_TLB_MISS_STALL", ARMV7_EVENT_83H) \ __PMC_EV_ALIAS("INSTR_MICRO_TLB_MISS_STALL", ARMV7_EVENT_84H) \ __PMC_EV_ALIAS("DATA_MICRO_TLB_MISS_STALL", ARMV7_EVENT_85H) \ __PMC_EV_ALIAS("DMB_STALL", ARMV7_EVENT_86H) \ __PMC_EV_ALIAS("INTEGER_CORE_CLOCK_ENABLED", ARMV7_EVENT_8AH) \ __PMC_EV_ALIAS("DATA_ENGINE_CLOCK_ENABLED", ARMV7_EVENT_8BH) \ __PMC_EV_ALIAS("ISB", ARMV7_EVENT_90H) \ __PMC_EV_ALIAS("DSB", ARMV7_EVENT_91H) \ __PMC_EV_ALIAS("DMB", ARMV7_EVENT_92H) \ __PMC_EV_ALIAS("EXTERNAL_INTERRUPT", ARMV7_EVENT_93H) \ __PMC_EV_ALIAS("PLE_CACHE_LINE_REQ_COMPLETED", ARMV7_EVENT_A0H) \ __PMC_EV_ALIAS("PLE_CACHE_LINE_REQ_SKIPPED", ARMV7_EVENT_A1H) \ __PMC_EV_ALIAS("PLE_FIFO_FLUSH", ARMV7_EVENT_A2H) \ __PMC_EV_ALIAS("PLE_REQUEST_COMPLETED", ARMV7_EVENT_A3H) \ __PMC_EV_ALIAS("PLE_FIFO_OVERFLOW", ARMV7_EVENT_A4H) \ __PMC_EV_ALIAS("PLE_REQUEST_PROGRAMMED", ARMV7_EVENT_A5H) /* * ARMv8 Events */ #define __PMC_EV_ARMV8() \ __PMC_EV(ARMV8, EVENT_00H) \ __PMC_EV(ARMV8, EVENT_01H) \ __PMC_EV(ARMV8, EVENT_02H) \ __PMC_EV(ARMV8, EVENT_03H) \ __PMC_EV(ARMV8, EVENT_04H) \ __PMC_EV(ARMV8, EVENT_05H) \ __PMC_EV(ARMV8, EVENT_06H) \ __PMC_EV(ARMV8, EVENT_07H) \ __PMC_EV(ARMV8, EVENT_08H) \ __PMC_EV(ARMV8, EVENT_09H) \ __PMC_EV(ARMV8, EVENT_0AH) \ __PMC_EV(ARMV8, EVENT_0BH) \ __PMC_EV(ARMV8, EVENT_0CH) \ __PMC_EV(ARMV8, EVENT_0DH) \ __PMC_EV(ARMV8, EVENT_0EH) \ __PMC_EV(ARMV8, EVENT_0FH) \ __PMC_EV(ARMV8, EVENT_10H) \ __PMC_EV(ARMV8, EVENT_11H) \ __PMC_EV(ARMV8, EVENT_12H) \ __PMC_EV(ARMV8, EVENT_13H) \ __PMC_EV(ARMV8, EVENT_14H) \ __PMC_EV(ARMV8, EVENT_15H) \ __PMC_EV(ARMV8, EVENT_16H) \ __PMC_EV(ARMV8, EVENT_17H) \ __PMC_EV(ARMV8, EVENT_18H) \ __PMC_EV(ARMV8, EVENT_19H) \ __PMC_EV(ARMV8, EVENT_1AH) \ __PMC_EV(ARMV8, EVENT_1BH) \ __PMC_EV(ARMV8, EVENT_1CH) \ __PMC_EV(ARMV8, EVENT_1DH) \ __PMC_EV(ARMV8, EVENT_1EH) \ __PMC_EV(ARMV8, EVENT_1FH) \ __PMC_EV(ARMV8, EVENT_20H) \ __PMC_EV(ARMV8, EVENT_21H) \ __PMC_EV(ARMV8, EVENT_22H) \ __PMC_EV(ARMV8, EVENT_23H) \ __PMC_EV(ARMV8, EVENT_24H) \ __PMC_EV(ARMV8, EVENT_25H) \ __PMC_EV(ARMV8, EVENT_26H) \ __PMC_EV(ARMV8, EVENT_27H) \ __PMC_EV(ARMV8, EVENT_28H) \ __PMC_EV(ARMV8, EVENT_29H) \ __PMC_EV(ARMV8, EVENT_2AH) \ __PMC_EV(ARMV8, EVENT_2BH) \ __PMC_EV(ARMV8, EVENT_2CH) \ __PMC_EV(ARMV8, EVENT_2DH) \ __PMC_EV(ARMV8, EVENT_2EH) \ __PMC_EV(ARMV8, EVENT_2FH) \ __PMC_EV(ARMV8, EVENT_30H) \ __PMC_EV(ARMV8, EVENT_31H) \ __PMC_EV(ARMV8, EVENT_32H) \ __PMC_EV(ARMV8, EVENT_33H) \ __PMC_EV(ARMV8, EVENT_34H) \ __PMC_EV(ARMV8, EVENT_35H) \ __PMC_EV(ARMV8, EVENT_36H) \ __PMC_EV(ARMV8, EVENT_37H) \ __PMC_EV(ARMV8, EVENT_38H) \ __PMC_EV(ARMV8, EVENT_39H) \ __PMC_EV(ARMV8, EVENT_3AH) \ __PMC_EV(ARMV8, EVENT_3BH) \ __PMC_EV(ARMV8, EVENT_3CH) \ __PMC_EV(ARMV8, EVENT_3DH) \ __PMC_EV(ARMV8, EVENT_3EH) \ __PMC_EV(ARMV8, EVENT_3FH) \ __PMC_EV(ARMV8, EVENT_40H) \ __PMC_EV(ARMV8, EVENT_41H) \ __PMC_EV(ARMV8, EVENT_42H) \ __PMC_EV(ARMV8, EVENT_43H) \ __PMC_EV(ARMV8, EVENT_44H) \ __PMC_EV(ARMV8, EVENT_45H) \ __PMC_EV(ARMV8, EVENT_46H) \ __PMC_EV(ARMV8, EVENT_47H) \ __PMC_EV(ARMV8, EVENT_48H) \ __PMC_EV(ARMV8, EVENT_49H) \ __PMC_EV(ARMV8, EVENT_4AH) \ __PMC_EV(ARMV8, EVENT_4BH) \ __PMC_EV(ARMV8, EVENT_4CH) \ __PMC_EV(ARMV8, EVENT_4DH) \ __PMC_EV(ARMV8, EVENT_4EH) \ __PMC_EV(ARMV8, EVENT_4FH) \ __PMC_EV(ARMV8, EVENT_50H) \ __PMC_EV(ARMV8, EVENT_51H) \ __PMC_EV(ARMV8, EVENT_52H) \ __PMC_EV(ARMV8, EVENT_53H) \ __PMC_EV(ARMV8, EVENT_54H) \ __PMC_EV(ARMV8, EVENT_55H) \ __PMC_EV(ARMV8, EVENT_56H) \ __PMC_EV(ARMV8, EVENT_57H) \ __PMC_EV(ARMV8, EVENT_58H) \ __PMC_EV(ARMV8, EVENT_59H) \ __PMC_EV(ARMV8, EVENT_5AH) \ __PMC_EV(ARMV8, EVENT_5BH) \ __PMC_EV(ARMV8, EVENT_5CH) \ __PMC_EV(ARMV8, EVENT_5DH) \ __PMC_EV(ARMV8, EVENT_5EH) \ __PMC_EV(ARMV8, EVENT_5FH) \ __PMC_EV(ARMV8, EVENT_60H) \ __PMC_EV(ARMV8, EVENT_61H) \ __PMC_EV(ARMV8, EVENT_62H) \ __PMC_EV(ARMV8, EVENT_63H) \ __PMC_EV(ARMV8, EVENT_64H) \ __PMC_EV(ARMV8, EVENT_65H) \ __PMC_EV(ARMV8, EVENT_66H) \ __PMC_EV(ARMV8, EVENT_67H) \ __PMC_EV(ARMV8, EVENT_68H) \ __PMC_EV(ARMV8, EVENT_69H) \ __PMC_EV(ARMV8, EVENT_6AH) \ __PMC_EV(ARMV8, EVENT_6BH) \ __PMC_EV(ARMV8, EVENT_6CH) \ __PMC_EV(ARMV8, EVENT_6DH) \ __PMC_EV(ARMV8, EVENT_6EH) \ __PMC_EV(ARMV8, EVENT_6FH) \ __PMC_EV(ARMV8, EVENT_70H) \ __PMC_EV(ARMV8, EVENT_71H) \ __PMC_EV(ARMV8, EVENT_72H) \ __PMC_EV(ARMV8, EVENT_73H) \ __PMC_EV(ARMV8, EVENT_74H) \ __PMC_EV(ARMV8, EVENT_75H) \ __PMC_EV(ARMV8, EVENT_76H) \ __PMC_EV(ARMV8, EVENT_77H) \ __PMC_EV(ARMV8, EVENT_78H) \ __PMC_EV(ARMV8, EVENT_79H) \ __PMC_EV(ARMV8, EVENT_7AH) \ __PMC_EV(ARMV8, EVENT_7BH) \ __PMC_EV(ARMV8, EVENT_7CH) \ __PMC_EV(ARMV8, EVENT_7DH) \ __PMC_EV(ARMV8, EVENT_7EH) \ __PMC_EV(ARMV8, EVENT_7FH) \ __PMC_EV(ARMV8, EVENT_80H) \ __PMC_EV(ARMV8, EVENT_81H) \ __PMC_EV(ARMV8, EVENT_82H) \ __PMC_EV(ARMV8, EVENT_83H) \ __PMC_EV(ARMV8, EVENT_84H) \ __PMC_EV(ARMV8, EVENT_85H) \ __PMC_EV(ARMV8, EVENT_86H) \ __PMC_EV(ARMV8, EVENT_87H) \ __PMC_EV(ARMV8, EVENT_88H) \ __PMC_EV(ARMV8, EVENT_89H) \ __PMC_EV(ARMV8, EVENT_8AH) \ __PMC_EV(ARMV8, EVENT_8BH) \ __PMC_EV(ARMV8, EVENT_8CH) \ __PMC_EV(ARMV8, EVENT_8DH) \ __PMC_EV(ARMV8, EVENT_8EH) \ __PMC_EV(ARMV8, EVENT_8FH) \ __PMC_EV(ARMV8, EVENT_90H) \ __PMC_EV(ARMV8, EVENT_91H) \ __PMC_EV(ARMV8, EVENT_92H) \ __PMC_EV(ARMV8, EVENT_93H) \ __PMC_EV(ARMV8, EVENT_94H) \ __PMC_EV(ARMV8, EVENT_95H) \ __PMC_EV(ARMV8, EVENT_96H) \ __PMC_EV(ARMV8, EVENT_97H) \ __PMC_EV(ARMV8, EVENT_98H) \ __PMC_EV(ARMV8, EVENT_99H) \ __PMC_EV(ARMV8, EVENT_9AH) \ __PMC_EV(ARMV8, EVENT_9BH) \ __PMC_EV(ARMV8, EVENT_9CH) \ __PMC_EV(ARMV8, EVENT_9DH) \ __PMC_EV(ARMV8, EVENT_9EH) \ __PMC_EV(ARMV8, EVENT_9FH) \ __PMC_EV(ARMV8, EVENT_A0H) \ __PMC_EV(ARMV8, EVENT_A1H) \ __PMC_EV(ARMV8, EVENT_A2H) \ __PMC_EV(ARMV8, EVENT_A3H) \ __PMC_EV(ARMV8, EVENT_A4H) \ __PMC_EV(ARMV8, EVENT_A5H) \ __PMC_EV(ARMV8, EVENT_A6H) \ __PMC_EV(ARMV8, EVENT_A7H) \ __PMC_EV(ARMV8, EVENT_A8H) \ __PMC_EV(ARMV8, EVENT_A9H) \ __PMC_EV(ARMV8, EVENT_AAH) \ __PMC_EV(ARMV8, EVENT_ABH) \ __PMC_EV(ARMV8, EVENT_ACH) \ __PMC_EV(ARMV8, EVENT_ADH) \ __PMC_EV(ARMV8, EVENT_AEH) \ __PMC_EV(ARMV8, EVENT_AFH) \ __PMC_EV(ARMV8, EVENT_B0H) \ __PMC_EV(ARMV8, EVENT_B1H) \ __PMC_EV(ARMV8, EVENT_B2H) \ __PMC_EV(ARMV8, EVENT_B3H) \ __PMC_EV(ARMV8, EVENT_B4H) \ __PMC_EV(ARMV8, EVENT_B5H) \ __PMC_EV(ARMV8, EVENT_B6H) \ __PMC_EV(ARMV8, EVENT_B7H) \ __PMC_EV(ARMV8, EVENT_B8H) \ __PMC_EV(ARMV8, EVENT_B9H) \ __PMC_EV(ARMV8, EVENT_BAH) \ __PMC_EV(ARMV8, EVENT_BBH) \ __PMC_EV(ARMV8, EVENT_BCH) \ __PMC_EV(ARMV8, EVENT_BDH) \ __PMC_EV(ARMV8, EVENT_BEH) \ __PMC_EV(ARMV8, EVENT_BFH) \ __PMC_EV(ARMV8, EVENT_C0H) \ __PMC_EV(ARMV8, EVENT_C1H) \ __PMC_EV(ARMV8, EVENT_C2H) \ __PMC_EV(ARMV8, EVENT_C3H) \ __PMC_EV(ARMV8, EVENT_C4H) \ __PMC_EV(ARMV8, EVENT_C5H) \ __PMC_EV(ARMV8, EVENT_C6H) \ __PMC_EV(ARMV8, EVENT_C7H) \ __PMC_EV(ARMV8, EVENT_C8H) \ __PMC_EV(ARMV8, EVENT_C9H) \ __PMC_EV(ARMV8, EVENT_CAH) \ __PMC_EV(ARMV8, EVENT_CBH) \ __PMC_EV(ARMV8, EVENT_CCH) \ __PMC_EV(ARMV8, EVENT_CDH) \ __PMC_EV(ARMV8, EVENT_CEH) \ __PMC_EV(ARMV8, EVENT_CFH) \ __PMC_EV(ARMV8, EVENT_D0H) \ __PMC_EV(ARMV8, EVENT_D1H) \ __PMC_EV(ARMV8, EVENT_D2H) \ __PMC_EV(ARMV8, EVENT_D3H) \ __PMC_EV(ARMV8, EVENT_D4H) \ __PMC_EV(ARMV8, EVENT_D5H) \ __PMC_EV(ARMV8, EVENT_D6H) \ __PMC_EV(ARMV8, EVENT_D7H) \ __PMC_EV(ARMV8, EVENT_D8H) \ __PMC_EV(ARMV8, EVENT_D9H) \ __PMC_EV(ARMV8, EVENT_DAH) \ __PMC_EV(ARMV8, EVENT_DBH) \ __PMC_EV(ARMV8, EVENT_DCH) \ __PMC_EV(ARMV8, EVENT_DDH) \ __PMC_EV(ARMV8, EVENT_DEH) \ __PMC_EV(ARMV8, EVENT_DFH) \ __PMC_EV(ARMV8, EVENT_E0H) \ __PMC_EV(ARMV8, EVENT_E1H) \ __PMC_EV(ARMV8, EVENT_E2H) \ __PMC_EV(ARMV8, EVENT_E3H) \ __PMC_EV(ARMV8, EVENT_E4H) \ __PMC_EV(ARMV8, EVENT_E5H) \ __PMC_EV(ARMV8, EVENT_E6H) \ __PMC_EV(ARMV8, EVENT_E7H) \ __PMC_EV(ARMV8, EVENT_E8H) \ __PMC_EV(ARMV8, EVENT_E9H) \ __PMC_EV(ARMV8, EVENT_EAH) \ __PMC_EV(ARMV8, EVENT_EBH) \ __PMC_EV(ARMV8, EVENT_ECH) \ __PMC_EV(ARMV8, EVENT_EDH) \ __PMC_EV(ARMV8, EVENT_EEH) \ __PMC_EV(ARMV8, EVENT_EFH) \ __PMC_EV(ARMV8, EVENT_F0H) \ __PMC_EV(ARMV8, EVENT_F1H) \ __PMC_EV(ARMV8, EVENT_F2H) \ __PMC_EV(ARMV8, EVENT_F3H) \ __PMC_EV(ARMV8, EVENT_F4H) \ __PMC_EV(ARMV8, EVENT_F5H) \ __PMC_EV(ARMV8, EVENT_F6H) \ __PMC_EV(ARMV8, EVENT_F7H) \ __PMC_EV(ARMV8, EVENT_F8H) \ __PMC_EV(ARMV8, EVENT_F9H) \ __PMC_EV(ARMV8, EVENT_FAH) \ __PMC_EV(ARMV8, EVENT_FBH) \ __PMC_EV(ARMV8, EVENT_FCH) \ __PMC_EV(ARMV8, EVENT_FDH) \ __PMC_EV(ARMV8, EVENT_FEH) \ __PMC_EV(ARMV8, EVENT_FFH) #define PMC_EV_ARMV8_FIRST PMC_EV_ARMV8_EVENT_00H #define PMC_EV_ARMV8_LAST PMC_EV_ARMV8_EVENT_FFH #define __PMC_EV_ALIAS_ARMV8_COMMON() \ __PMC_EV_ALIAS("SW_INCR", ARMV8_EVENT_00H) \ __PMC_EV_ALIAS("L1I_CACHE_REFILL", ARMV8_EVENT_01H) \ __PMC_EV_ALIAS("L1I_TLB_REFILL", ARMV8_EVENT_02H) \ __PMC_EV_ALIAS("L1D_CACHE_REFILL", ARMV8_EVENT_03H) \ __PMC_EV_ALIAS("L1D_CACHE", ARMV8_EVENT_04H) \ __PMC_EV_ALIAS("L1D_TLB_REFILL", ARMV8_EVENT_05H) \ __PMC_EV_ALIAS("INST_RETIRED", ARMV8_EVENT_08H) \ __PMC_EV_ALIAS("EXC_TAKEN", ARMV8_EVENT_09H) \ __PMC_EV_ALIAS("EXC_RETURN", ARMV8_EVENT_0AH) \ __PMC_EV_ALIAS("CID_WRITE_RETIRED", ARMV8_EVENT_0BH) \ __PMC_EV_ALIAS("BR_MIS_PRED", ARMV8_EVENT_10H) \ __PMC_EV_ALIAS("CPU_CYCLES", ARMV8_EVENT_11H) \ __PMC_EV_ALIAS("BR_PRED", ARMV8_EVENT_12H) \ __PMC_EV_ALIAS("MEM_ACCESS", ARMV8_EVENT_13H) \ __PMC_EV_ALIAS("L1I_CACHE", ARMV8_EVENT_14H) \ __PMC_EV_ALIAS("L1D_CACHE_WB", ARMV8_EVENT_15H) \ __PMC_EV_ALIAS("L2D_CACHE", ARMV8_EVENT_16H) \ __PMC_EV_ALIAS("L2D_CACHE_REFILL", ARMV8_EVENT_17H) \ __PMC_EV_ALIAS("L2D_CACHE_WB", ARMV8_EVENT_18H) \ __PMC_EV_ALIAS("BUS_ACCESS", ARMV8_EVENT_19H) \ __PMC_EV_ALIAS("MEMORY_ERROR", ARMV8_EVENT_1AH) \ __PMC_EV_ALIAS("BUS_CYCLES", ARMV8_EVENT_1DH) \ __PMC_EV_ALIAS("CHAIN", ARMV8_EVENT_1EH) \ __PMC_EV_ALIAS("BUS_ACCESS_LD", ARMV8_EVENT_60H) \ __PMC_EV_ALIAS("BUS_ACCESS_ST", ARMV8_EVENT_61H) \ __PMC_EV_ALIAS("BR_INDIRECT_SPEC", ARMV8_EVENT_7AH) \ __PMC_EV_ALIAS("EXC_IRQ", ARMV8_EVENT_86H) \ __PMC_EV_ALIAS("EXC_FIQ", ARMV8_EVENT_87H) #define __PMC_EV_ALIAS_ARMV8_CORTEX_A53() \ __PMC_EV_ALIAS_ARMV8_COMMON() \ __PMC_EV_ALIAS("LD_RETIRED", ARMV8_EVENT_06H) \ __PMC_EV_ALIAS("ST_RETIRED", ARMV8_EVENT_07H) \ __PMC_EV_ALIAS("PC_WRITE_RETIRED", ARMV8_EVENT_0CH) \ __PMC_EV_ALIAS("BR_IMMED_RETIRED", ARMV8_EVENT_0DH) \ __PMC_EV_ALIAS("BR_RETURN_RETIRED", ARMV8_EVENT_0EH) \ __PMC_EV_ALIAS("UNALIGNED_LDST_RETIRED",ARMV8_EVENT_0FH) #define __PMC_EV_ALIAS_ARMV8_CORTEX_A57_A76() \ __PMC_EV_ALIAS_ARMV8_COMMON() \ __PMC_EV_ALIAS("INST_SPEC", ARMV8_EVENT_1BH) \ __PMC_EV_ALIAS("TTBR_WRITE_RETIRED", ARMV8_EVENT_1CH) \ __PMC_EV_ALIAS("L1D_CACHE_LD", ARMV8_EVENT_40H) \ __PMC_EV_ALIAS("L1D_CACHE_ST", ARMV8_EVENT_41H) \ __PMC_EV_ALIAS("L1D_CACHE_REFILL_LD", ARMV8_EVENT_42H) \ __PMC_EV_ALIAS("L1D_CACHE_REFILL_ST", ARMV8_EVENT_43H) \ __PMC_EV_ALIAS("L1D_CACHE_WB_VICTIM", ARMV8_EVENT_46H) \ __PMC_EV_ALIAS("L1D_CACHE_WB_CLEAN", ARMV8_EVENT_47H) \ __PMC_EV_ALIAS("L1D_CACHE_INVAL", ARMV8_EVENT_48H) \ __PMC_EV_ALIAS("L1D_TLB_REFILL_LD", ARMV8_EVENT_4CH) \ __PMC_EV_ALIAS("L1D_TLB_REFILL_ST", ARMV8_EVENT_4DH) \ __PMC_EV_ALIAS("L2D_CACHE_LD", ARMV8_EVENT_50H) \ __PMC_EV_ALIAS("L2D_CACHE_ST", ARMV8_EVENT_51H) \ __PMC_EV_ALIAS("L2D_CACHE_REFILL_LD", ARMV8_EVENT_52H) \ __PMC_EV_ALIAS("L2D_CACHE_REFILL_ST", ARMV8_EVENT_53H) \ __PMC_EV_ALIAS("L2D_CACHE_WB_VICTIM", ARMV8_EVENT_56H) \ __PMC_EV_ALIAS("L2D_CACHE_WB_CLEAN", ARMV8_EVENT_57H) \ __PMC_EV_ALIAS("L2D_CACHE_INVAL", ARMV8_EVENT_58H) \ __PMC_EV_ALIAS("MEM_ACCESS_LD", ARMV8_EVENT_66H) \ __PMC_EV_ALIAS("MEM_ACCESS_ST", ARMV8_EVENT_67H) \ __PMC_EV_ALIAS("UNALIGNED_LD_SPEC", ARMV8_EVENT_68H) \ __PMC_EV_ALIAS("UNALIGNED_ST_SPEC", ARMV8_EVENT_69H) \ __PMC_EV_ALIAS("UNALIGNED_LDST_SPEC", ARMV8_EVENT_6AH) \ __PMC_EV_ALIAS("LDREX_SPEC", ARMV8_EVENT_6CH) \ __PMC_EV_ALIAS("STREX_PASS_SPEC", ARMV8_EVENT_6DH) \ __PMC_EV_ALIAS("STREX_FAIL_SPEC", ARMV8_EVENT_6EH) \ __PMC_EV_ALIAS("LD_SPEC", ARMV8_EVENT_70H) \ __PMC_EV_ALIAS("ST_SPEC", ARMV8_EVENT_71H) \ __PMC_EV_ALIAS("LDST_SPEC", ARMV8_EVENT_72H) \ __PMC_EV_ALIAS("DP_SPEC", ARMV8_EVENT_73H) \ __PMC_EV_ALIAS("ASE_SPEC", ARMV8_EVENT_74H) \ __PMC_EV_ALIAS("VFP_SPEC", ARMV8_EVENT_75H) \ __PMC_EV_ALIAS("PC_WRITE_SPEC", ARMV8_EVENT_76H) \ __PMC_EV_ALIAS("CRYPTO_SPEC", ARMV8_EVENT_77H) \ __PMC_EV_ALIAS("BR_IMMED_SPEC", ARMV8_EVENT_78H) \ __PMC_EV_ALIAS("BR_RETURN_SPEC", ARMV8_EVENT_79H) \ __PMC_EV_ALIAS("ISB_SPEC", ARMV8_EVENT_7CH) \ __PMC_EV_ALIAS("DSB_SPEC", ARMV8_EVENT_7DH) \ __PMC_EV_ALIAS("DMB_SPEC", ARMV8_EVENT_7EH) \ __PMC_EV_ALIAS("EXC_UNDEF", ARMV8_EVENT_81H) \ __PMC_EV_ALIAS("EXC_SVC", ARMV8_EVENT_82H) \ __PMC_EV_ALIAS("EXC_PABORT", ARMV8_EVENT_83H) \ __PMC_EV_ALIAS("EXC_DABORT", ARMV8_EVENT_84H) \ __PMC_EV_ALIAS("EXC_SMC", ARMV8_EVENT_88H) \ __PMC_EV_ALIAS("EXC_HVC", ARMV8_EVENT_8AH) \ __PMC_EV_ALIAS("EXC_TRAP_PABORT", ARMV8_EVENT_8BH) \ __PMC_EV_ALIAS("EXC_TRAP_DABORT", ARMV8_EVENT_8CH) \ __PMC_EV_ALIAS("EXC_TRAP_OTHER", ARMV8_EVENT_8DH) \ __PMC_EV_ALIAS("EXC_TRAP_IRQ", ARMV8_EVENT_8EH) \ __PMC_EV_ALIAS("EXC_TRAP_FIQ", ARMV8_EVENT_8FH) \ __PMC_EV_ALIAS("RC_LD_SPEC", ARMV8_EVENT_90H) \ __PMC_EV_ALIAS("RC_ST_SPEC", ARMV8_EVENT_91H) #define __PMC_EV_ALIAS_ARMV8_CORTEX_A57() \ __PMC_EV_ALIAS_ARMV8_CORTEX_A57_A76() \ __PMC_EV_ALIAS("BUS_ACCESS_SHARED", ARMV8_EVENT_62H) \ __PMC_EV_ALIAS("BUS_ACCESS_NOT_SHARED", ARMV8_EVENT_63H) \ __PMC_EV_ALIAS("BUS_ACCESS_NORMAL", ARMV8_EVENT_64H) \ __PMC_EV_ALIAS("BUS_ACCESS_PERIPH", ARMV8_EVENT_65H) #define __PMC_EV_ALIAS_ARMV8_CORTEX_A76() \ __PMC_EV_ALIAS_ARMV8_CORTEX_A57_A76() \ __PMC_EV_ALIAS("L2D_CACHE_ALLOCATE", ARMV8_EVENT_20H) \ __PMC_EV_ALIAS("BR_RETIRED", ARMV8_EVENT_21H) \ __PMC_EV_ALIAS("BR_MIS_PRED_RETIRED", ARMV8_EVENT_22H) \ __PMC_EV_ALIAS("STALL_FRONTEND", ARMV8_EVENT_23H) \ __PMC_EV_ALIAS("STALL_BACKEND", ARMV8_EVENT_24H) \ __PMC_EV_ALIAS("L1D_TLB", ARMV8_EVENT_25H) \ __PMC_EV_ALIAS("L1I_TLB", ARMV8_EVENT_26H) \ __PMC_EV_ALIAS("L3D_CACHE_ALLOCATE", ARMV8_EVENT_29H) \ __PMC_EV_ALIAS("L3D_CACHE_REFILL", ARMV8_EVENT_2AH) \ __PMC_EV_ALIAS("L3D_CACHE", ARMV8_EVENT_2BH) \ __PMC_EV_ALIAS("L2D_TLB_REFILL", ARMV8_EVENT_2DH) \ __PMC_EV_ALIAS("L2D_TLB", ARMV8_EVENT_2FH) \ __PMC_EV_ALIAS("REMOTE_ACCESS", ARMV8_EVENT_31H) \ __PMC_EV_ALIAS("DTLB_WALK", ARMV8_EVENT_34H) \ __PMC_EV_ALIAS("ITLB_WALK", ARMV8_EVENT_35H) \ __PMC_EV_ALIAS("LL_CACHE_RD", ARMV8_EVENT_36H) \ __PMC_EV_ALIAS("LL_CACHE_MISS_RD", ARMV8_EVENT_37H) \ __PMC_EV_ALIAS("L1D_CACHE_REFILL_INNER", ARMV8_EVENT_44H) \ __PMC_EV_ALIAS("L1D_CACHE_REFILL_OUTER", ARMV8_EVENT_45H) \ __PMC_EV_ALIAS("L1D_TLB_RD", ARMV8_EVENT_4EH) \ __PMC_EV_ALIAS("L1D_TLB_WR", ARMV8_EVENT_4FH) \ __PMC_EV_ALIAS("L2D_TLB_REFILL_RD", ARMV8_EVENT_5CH) \ __PMC_EV_ALIAS("L2D_TLB_REFILL_WR", ARMV8_EVENT_5DH) \ __PMC_EV_ALIAS("L2D_TLB_RD", ARMV8_EVENT_5EH) \ __PMC_EV_ALIAS("L2D_TLB_WR", ARMV8_EVENT_5FH) \ __PMC_EV_ALIAS("STREX_SPEC", ARMV8_EVENT_6FH) \ __PMC_EV_ALIAS("L3_CACHE_RD", ARMV8_EVENT_A0H) /* * MIPS Events from "Programming the MIPS32 24K Core Family", * Document Number: MD00355 Revision 04.63 December 19, 2008 * These events are kept in the order found in Table 7.4. * For counters which are different between the left hand * column (0/2) and the right hand column (1/3) the left * hand is given first, e.g. BRANCH_COMPLETED and BRANCH_MISPRED * in the definition below. */ #define __PMC_EV_MIPS24K() \ __PMC_EV(MIPS24K, CYCLE) \ __PMC_EV(MIPS24K, INSTR_EXECUTED) \ __PMC_EV(MIPS24K, BRANCH_COMPLETED) \ __PMC_EV(MIPS24K, BRANCH_MISPRED) \ __PMC_EV(MIPS24K, RETURN) \ __PMC_EV(MIPS24K, RETURN_MISPRED) \ __PMC_EV(MIPS24K, RETURN_NOT_31) \ __PMC_EV(MIPS24K, RETURN_NOTPRED) \ __PMC_EV(MIPS24K, ITLB_ACCESS) \ __PMC_EV(MIPS24K, ITLB_MISS) \ __PMC_EV(MIPS24K, DTLB_ACCESS) \ __PMC_EV(MIPS24K, DTLB_MISS) \ __PMC_EV(MIPS24K, JTLB_IACCESS) \ __PMC_EV(MIPS24K, JTLB_IMISS) \ __PMC_EV(MIPS24K, JTLB_DACCESS) \ __PMC_EV(MIPS24K, JTLB_DMISS) \ __PMC_EV(MIPS24K, IC_FETCH) \ __PMC_EV(MIPS24K, IC_MISS) \ __PMC_EV(MIPS24K, DC_LOADSTORE) \ __PMC_EV(MIPS24K, DC_WRITEBACK) \ __PMC_EV(MIPS24K, DC_MISS) \ __PMC_EV(MIPS24K, STORE_MISS) \ __PMC_EV(MIPS24K, LOAD_MISS) \ __PMC_EV(MIPS24K, INTEGER_COMPLETED) \ __PMC_EV(MIPS24K, FP_COMPLETED) \ __PMC_EV(MIPS24K, LOAD_COMPLETED) \ __PMC_EV(MIPS24K, STORE_COMPLETED) \ __PMC_EV(MIPS24K, BARRIER_COMPLETED) \ __PMC_EV(MIPS24K, MIPS16_COMPLETED) \ __PMC_EV(MIPS24K, NOP_COMPLETED) \ __PMC_EV(MIPS24K, INTEGER_MULDIV_COMPLETED)\ __PMC_EV(MIPS24K, RF_STALL) \ __PMC_EV(MIPS24K, INSTR_REFETCH) \ __PMC_EV(MIPS24K, STORE_COND_COMPLETED) \ __PMC_EV(MIPS24K, STORE_COND_FAILED) \ __PMC_EV(MIPS24K, ICACHE_REQUESTS) \ __PMC_EV(MIPS24K, ICACHE_HIT) \ __PMC_EV(MIPS24K, L2_WRITEBACK) \ __PMC_EV(MIPS24K, L2_ACCESS) \ __PMC_EV(MIPS24K, L2_MISS) \ __PMC_EV(MIPS24K, L2_ERR_CORRECTED) \ __PMC_EV(MIPS24K, EXCEPTIONS) \ __PMC_EV(MIPS24K, RF_CYCLES_STALLED) \ __PMC_EV(MIPS24K, IFU_CYCLES_STALLED) \ __PMC_EV(MIPS24K, ALU_CYCLES_STALLED) \ __PMC_EV(MIPS24K, UNCACHED_LOAD) \ __PMC_EV(MIPS24K, UNCACHED_STORE) \ __PMC_EV(MIPS24K, CP2_REG_TO_REG_COMPLETED)\ __PMC_EV(MIPS24K, MFTC_COMPLETED) \ __PMC_EV(MIPS24K, IC_BLOCKED_CYCLES) \ __PMC_EV(MIPS24K, DC_BLOCKED_CYCLES) \ __PMC_EV(MIPS24K, L2_IMISS_STALL_CYCLES) \ __PMC_EV(MIPS24K, L2_DMISS_STALL_CYCLES) \ __PMC_EV(MIPS24K, DMISS_CYCLES) \ __PMC_EV(MIPS24K, L2_MISS_CYCLES) \ __PMC_EV(MIPS24K, UNCACHED_BLOCK_CYCLES) \ __PMC_EV(MIPS24K, MDU_STALL_CYCLES) \ __PMC_EV(MIPS24K, FPU_STALL_CYCLES) \ __PMC_EV(MIPS24K, CP2_STALL_CYCLES) \ __PMC_EV(MIPS24K, COREXTEND_STALL_CYCLES) \ __PMC_EV(MIPS24K, ISPRAM_STALL_CYCLES) \ __PMC_EV(MIPS24K, DSPRAM_STALL_CYCLES) \ __PMC_EV(MIPS24K, CACHE_STALL_CYCLES) \ __PMC_EV(MIPS24K, LOAD_TO_USE_STALLS) \ __PMC_EV(MIPS24K, BASE_MISPRED_STALLS) \ __PMC_EV(MIPS24K, CPO_READ_STALLS) \ __PMC_EV(MIPS24K, BRANCH_MISPRED_CYCLES) \ __PMC_EV(MIPS24K, IFETCH_BUFFER_FULL) \ __PMC_EV(MIPS24K, FETCH_BUFFER_ALLOCATED) \ __PMC_EV(MIPS24K, EJTAG_ITRIGGER) \ __PMC_EV(MIPS24K, EJTAG_DTRIGGER) \ __PMC_EV(MIPS24K, FSB_LT_QUARTER) \ __PMC_EV(MIPS24K, FSB_QUARTER_TO_HALF) \ __PMC_EV(MIPS24K, FSB_GT_HALF) \ __PMC_EV(MIPS24K, FSB_FULL_PIPELINE_STALLS)\ __PMC_EV(MIPS24K, LDQ_LT_QUARTER) \ __PMC_EV(MIPS24K, LDQ_QUARTER_TO_HALF) \ __PMC_EV(MIPS24K, LDQ_GT_HALF) \ __PMC_EV(MIPS24K, LDQ_FULL_PIPELINE_STALLS)\ __PMC_EV(MIPS24K, WBB_LT_QUARTER) \ __PMC_EV(MIPS24K, WBB_QUARTER_TO_HALF) \ __PMC_EV(MIPS24K, WBB_GT_HALF) \ __PMC_EV(MIPS24K, WBB_FULL_PIPELINE_STALLS) \ __PMC_EV(MIPS24K, REQUEST_LATENCY) \ __PMC_EV(MIPS24K, REQUEST_COUNT) #define PMC_EV_MIPS24K_FIRST PMC_EV_MIPS24K_CYCLE #define PMC_EV_MIPS24K_LAST PMC_EV_MIPS24K_WBB_FULL_PIPELINE_STALLS /* * MIPS74k events. Similar to MIPS24k, the arrangement * is (0,2) then (1,3) events. */ #define __PMC_EV_MIPS74K() \ __PMC_EV(MIPS74K, CYCLES) \ __PMC_EV(MIPS74K, INSTR_EXECUTED) \ __PMC_EV(MIPS74K, PREDICTED_JR_31) \ __PMC_EV(MIPS74K, JR_31_MISPREDICTIONS) \ __PMC_EV(MIPS74K, REDIRECT_STALLS) \ __PMC_EV(MIPS74K, JR_31_NO_PREDICTIONS) \ __PMC_EV(MIPS74K, ITLB_ACCESSES) \ __PMC_EV(MIPS74K, ITLB_MISSES) \ __PMC_EV(MIPS74K, JTLB_INSN_MISSES) \ __PMC_EV(MIPS74K, ICACHE_ACCESSES) \ __PMC_EV(MIPS74K, ICACHE_MISSES) \ __PMC_EV(MIPS74K, ICACHE_MISS_STALLS) \ __PMC_EV(MIPS74K, UNCACHED_IFETCH_STALLS) \ __PMC_EV(MIPS74K, PDTRACE_BACK_STALLS) \ __PMC_EV(MIPS74K, IFU_REPLAYS) \ __PMC_EV(MIPS74K, KILLED_FETCH_SLOTS) \ __PMC_EV(MIPS74K, IFU_IDU_MISS_PRED_UPSTREAM_CYCLES) \ __PMC_EV(MIPS74K, IFU_IDU_NO_FETCH_CYCLES) \ __PMC_EV(MIPS74K, IFU_IDU_CLOGED_DOWNSTREAM_CYCLES) \ __PMC_EV(MIPS74K, DDQ0_FULL_DR_STALLS) \ __PMC_EV(MIPS74K, DDQ1_FULL_DR_STALLS) \ __PMC_EV(MIPS74K, ALCB_FULL_DR_STALLS) \ __PMC_EV(MIPS74K, AGCB_FULL_DR_STALLS) \ __PMC_EV(MIPS74K, CLDQ_FULL_DR_STALLS) \ __PMC_EV(MIPS74K, IODQ_FULL_DR_STALLS) \ __PMC_EV(MIPS74K, ALU_EMPTY_CYCLES) \ __PMC_EV(MIPS74K, AGEN_EMPTY_CYCLES) \ __PMC_EV(MIPS74K, ALU_OPERANDS_NOT_READY_CYCLES) \ __PMC_EV(MIPS74K, AGEN_OPERANDS_NOT_READY_CYCLES) \ __PMC_EV(MIPS74K, ALU_NO_ISSUES_CYCLES) \ __PMC_EV(MIPS74K, AGEN_NO_ISSUES_CYCLES) \ __PMC_EV(MIPS74K, ALU_BUBBLE_CYCLES) \ __PMC_EV(MIPS74K, AGEN_BUBBLE_CYCLES) \ __PMC_EV(MIPS74K, SINGLE_ISSUE_CYCLES) \ __PMC_EV(MIPS74K, DUAL_ISSUE_CYCLES) \ __PMC_EV(MIPS74K, OOO_ALU_ISSUE_CYCLES) \ __PMC_EV(MIPS74K, OOO_AGEN_ISSUE_CYCLES) \ __PMC_EV(MIPS74K, JALR_JALR_HB_INSNS) \ __PMC_EV(MIPS74K, DCACHE_LINE_REFILL_REQUESTS) \ __PMC_EV(MIPS74K, DCACHE_LOAD_ACCESSES) \ __PMC_EV(MIPS74K, DCACHE_ACCESSES) \ __PMC_EV(MIPS74K, DCACHE_WRITEBACKS) \ __PMC_EV(MIPS74K, DCACHE_MISSES) \ __PMC_EV(MIPS74K, JTLB_DATA_ACCESSES) \ __PMC_EV(MIPS74K, JTLB_DATA_MISSES) \ __PMC_EV(MIPS74K, LOAD_STORE_REPLAYS) \ __PMC_EV(MIPS74K, VA_TRANSALTION_CORNER_CASES) \ __PMC_EV(MIPS74K, LOAD_STORE_BLOCKED_CYCLES) \ __PMC_EV(MIPS74K, LOAD_STORE_NO_FILL_REQUESTS) \ __PMC_EV(MIPS74K, L2_CACHE_WRITEBACKS) \ __PMC_EV(MIPS74K, L2_CACHE_ACCESSES) \ __PMC_EV(MIPS74K, L2_CACHE_MISSES) \ __PMC_EV(MIPS74K, L2_CACHE_MISS_CYCLES) \ __PMC_EV(MIPS74K, FSB_FULL_STALLS) \ __PMC_EV(MIPS74K, FSB_OVER_50_FULL) \ __PMC_EV(MIPS74K, LDQ_FULL_STALLS) \ __PMC_EV(MIPS74K, LDQ_OVER_50_FULL) \ __PMC_EV(MIPS74K, WBB_FULL_STALLS) \ __PMC_EV(MIPS74K, WBB_OVER_50_FULL) \ __PMC_EV(MIPS74K, LOAD_MISS_CONSUMER_REPLAYS) \ __PMC_EV(MIPS74K, CP1_CP2_LOAD_INSNS) \ __PMC_EV(MIPS74K, JR_NON_31_INSNS) \ __PMC_EV(MIPS74K, MISPREDICTED_JR_31_INSNS) \ __PMC_EV(MIPS74K, BRANCH_INSNS) \ __PMC_EV(MIPS74K, CP1_CP2_COND_BRANCH_INSNS) \ __PMC_EV(MIPS74K, BRANCH_LIKELY_INSNS) \ __PMC_EV(MIPS74K, MISPREDICTED_BRANCH_LIKELY_INSNS) \ __PMC_EV(MIPS74K, COND_BRANCH_INSNS) \ __PMC_EV(MIPS74K, MISPREDICTED_BRANCH_INSNS) \ __PMC_EV(MIPS74K, INTEGER_INSNS) \ __PMC_EV(MIPS74K, FPU_INSNS) \ __PMC_EV(MIPS74K, LOAD_INSNS) \ __PMC_EV(MIPS74K, STORE_INSNS) \ __PMC_EV(MIPS74K, J_JAL_INSNS) \ __PMC_EV(MIPS74K, MIPS16_INSNS) \ __PMC_EV(MIPS74K, NOP_INSNS) \ __PMC_EV(MIPS74K, NT_MUL_DIV_INSNS) \ __PMC_EV(MIPS74K, DSP_INSNS) \ __PMC_EV(MIPS74K, ALU_DSP_SATURATION_INSNS) \ __PMC_EV(MIPS74K, DSP_BRANCH_INSNS) \ __PMC_EV(MIPS74K, MDU_DSP_SATURATION_INSNS) \ __PMC_EV(MIPS74K, UNCACHED_LOAD_INSNS) \ __PMC_EV(MIPS74K, UNCACHED_STORE_INSNS) \ __PMC_EV(MIPS74K, EJTAG_INSN_TRIGGERS) \ __PMC_EV(MIPS74K, CP1_BRANCH_MISPREDICTIONS) \ __PMC_EV(MIPS74K, SC_INSNS) \ __PMC_EV(MIPS74K, FAILED_SC_INSNS) \ __PMC_EV(MIPS74K, PREFETCH_INSNS) \ __PMC_EV(MIPS74K, CACHE_HIT_PREFETCH_INSNS) \ __PMC_EV(MIPS74K, NO_INSN_CYCLES) \ __PMC_EV(MIPS74K, LOAD_MISS_INSNS) \ __PMC_EV(MIPS74K, ONE_INSN_CYCLES) \ __PMC_EV(MIPS74K, TWO_INSNS_CYCLES) \ __PMC_EV(MIPS74K, GFIFO_BLOCKED_CYCLES) \ __PMC_EV(MIPS74K, CP1_CP2_STORE_INSNS) \ __PMC_EV(MIPS74K, MISPREDICTION_STALLS) \ __PMC_EV(MIPS74K, MISPREDICTED_BRANCH_INSNS_CYCLES) \ __PMC_EV(MIPS74K, EXCEPTIONS_TAKEN) \ __PMC_EV(MIPS74K, GRADUATION_REPLAYS) \ __PMC_EV(MIPS74K, COREEXTEND_EVENTS) \ __PMC_EV(MIPS74K, ISPRAM_EVENTS) \ __PMC_EV(MIPS74K, DSPRAM_EVENTS) \ __PMC_EV(MIPS74K, L2_CACHE_SINGLE_BIT_ERRORS) \ __PMC_EV(MIPS74K, SYSTEM_EVENT_0) \ __PMC_EV(MIPS74K, SYSTEM_EVENT_1) \ __PMC_EV(MIPS74K, SYSTEM_EVENT_2) \ __PMC_EV(MIPS74K, SYSTEM_EVENT_3) \ __PMC_EV(MIPS74K, SYSTEM_EVENT_4) \ __PMC_EV(MIPS74K, SYSTEM_EVENT_5) \ __PMC_EV(MIPS74K, SYSTEM_EVENT_6) \ __PMC_EV(MIPS74K, SYSTEM_EVENT_7) \ __PMC_EV(MIPS74K, OCP_ALL_REQUESTS) \ __PMC_EV(MIPS74K, OCP_ALL_CACHEABLE_REQUESTS) \ __PMC_EV(MIPS74K, OCP_READ_REQUESTS) \ __PMC_EV(MIPS74K, OCP_READ_CACHEABLE_REQUESTS) \ __PMC_EV(MIPS74K, OCP_WRITE_REQUESTS) \ __PMC_EV(MIPS74K, OCP_WRITE_CACHEABLE_REQUESTS) \ __PMC_EV(MIPS74K, FSB_LESS_25_FULL) \ __PMC_EV(MIPS74K, FSB_25_50_FULL) \ __PMC_EV(MIPS74K, LDQ_LESS_25_FULL) \ __PMC_EV(MIPS74K, LDQ_25_50_FULL) \ __PMC_EV(MIPS74K, WBB_LESS_25_FULL) \ __PMC_EV(MIPS74K, WBB_25_50_FULL) #define PMC_EV_MIPS74K_FIRST PMC_EV_MIPS74K_CYCLES #define PMC_EV_MIPS74K_LAST PMC_EV_MIPS74K_WBB_25_50_FULL #define __PMC_EV_BERI() \ __PMC_EV(BERI, CYCLE) \ __PMC_EV(BERI, INST) \ __PMC_EV(BERI, INST_USER) \ __PMC_EV(BERI, INST_KERNEL) \ __PMC_EV(BERI, IMPRECISE_SETBOUNDS) \ __PMC_EV(BERI, UNREPRESENTABLE_CAPS) \ __PMC_EV(BERI, ITLB_MISS) \ __PMC_EV(BERI, DTLB_MISS) \ __PMC_EV(BERI, ICACHE_WRITE_HIT) \ __PMC_EV(BERI, ICACHE_WRITE_MISS) \ __PMC_EV(BERI, ICACHE_READ_HIT) \ __PMC_EV(BERI, ICACHE_READ_MISS) \ __PMC_EV(BERI, ICACHE_EVICT) \ __PMC_EV(BERI, DCACHE_WRITE_HIT) \ __PMC_EV(BERI, DCACHE_WRITE_MISS) \ __PMC_EV(BERI, DCACHE_READ_HIT) \ __PMC_EV(BERI, DCACHE_READ_MISS) \ __PMC_EV(BERI, DCACHE_EVICT) \ __PMC_EV(BERI, DCACHE_SET_TAG_WRITE) \ __PMC_EV(BERI, DCACHE_SET_TAG_READ) \ __PMC_EV(BERI, L2CACHE_WRITE_HIT) \ __PMC_EV(BERI, L2CACHE_WRITE_MISS) \ __PMC_EV(BERI, L2CACHE_READ_HIT) \ __PMC_EV(BERI, L2CACHE_READ_MISS) \ __PMC_EV(BERI, L2CACHE_EVICT) \ __PMC_EV(BERI, L2CACHE_SET_TAG_WRITE) \ __PMC_EV(BERI, L2CACHE_SET_TAG_READ) \ __PMC_EV(BERI, MEM_BYTE_READ) \ __PMC_EV(BERI, MEM_BYTE_WRITE) \ __PMC_EV(BERI, MEM_HWORD_READ) \ __PMC_EV(BERI, MEM_HWORD_WRITE) \ __PMC_EV(BERI, MEM_WORD_READ) \ __PMC_EV(BERI, MEM_WORD_WRITE) \ __PMC_EV(BERI, MEM_DWORD_READ) \ __PMC_EV(BERI, MEM_DWORD_WRITE) \ __PMC_EV(BERI, MEM_CAP_READ) \ __PMC_EV(BERI, MEM_CAP_WRITE) \ __PMC_EV(BERI, MEM_CAP_READ_TAG_SET) \ __PMC_EV(BERI, MEM_CAP_WRITE_TAG_SET) \ __PMC_EV(BERI, TAGCACHE_WRITE_HIT) \ __PMC_EV(BERI, TAGCACHE_WRITE_MISS) \ __PMC_EV(BERI, TAGCACHE_READ_HIT) \ __PMC_EV(BERI, TAGCACHE_READ_MISS) \ __PMC_EV(BERI, TAGCACHE_EVICT) \ __PMC_EV(BERI, L2CACHEMASTER_READ_REQ) \ __PMC_EV(BERI, L2CACHEMASTER_WRITE_REQ) \ __PMC_EV(BERI, L2CACHEMASTER_WRITE_REQ_FLIT) \ __PMC_EV(BERI, L2CACHEMASTER_READ_RSP) \ __PMC_EV(BERI, L2CACHEMASTER_READ_RSP_FLIT) \ __PMC_EV(BERI, L2CACHEMASTER_WRITE_RSP) \ __PMC_EV(BERI, TAGCACHEMASTER_READ_REQ) \ __PMC_EV(BERI, TAGCACHEMASTER_WRITE_REQ) \ __PMC_EV(BERI, TAGCACHEMASTER_WRITE_REQ_FLIT) \ __PMC_EV(BERI, TAGCACHEMASTER_READ_RSP) \ __PMC_EV(BERI, TAGCACHEMASTER_READ_RSP_FLIT) \ __PMC_EV(BERI, TAGCACHEMASTER_WRITE_RSP) #define PMC_EV_BERI_FIRST PMC_EV_BERI_CYCLE #define PMC_EV_BERI_LAST PMC_EV_BERI_TAGCACHEMASTER_WRITE_RSP /* * Cavium Octeon counters. Obtained from cvmx-core.h */ #define __PMC_EV_OCTEON() \ __PMC_EV(OCTEON, CLK) \ __PMC_EV(OCTEON, ISSUE) \ __PMC_EV(OCTEON, RET) \ __PMC_EV(OCTEON, NISSUE) \ __PMC_EV(OCTEON, SISSUE) \ __PMC_EV(OCTEON, DISSUE) \ __PMC_EV(OCTEON, IFI) \ __PMC_EV(OCTEON, BR) \ __PMC_EV(OCTEON, BRMIS) \ __PMC_EV(OCTEON, J) \ __PMC_EV(OCTEON, JMIS) \ __PMC_EV(OCTEON, REPLAY) \ __PMC_EV(OCTEON, IUNA) \ __PMC_EV(OCTEON, TRAP) \ __PMC_EV(OCTEON, UULOAD) \ __PMC_EV(OCTEON, UUSTORE) \ __PMC_EV(OCTEON, ULOAD) \ __PMC_EV(OCTEON, USTORE) \ __PMC_EV(OCTEON, EC) \ __PMC_EV(OCTEON, MC) \ __PMC_EV(OCTEON, CC) \ __PMC_EV(OCTEON, CSRC) \ __PMC_EV(OCTEON, CFETCH) \ __PMC_EV(OCTEON, CPREF) \ __PMC_EV(OCTEON, ICA) \ __PMC_EV(OCTEON, II) \ __PMC_EV(OCTEON, IP) \ __PMC_EV(OCTEON, CIMISS) \ __PMC_EV(OCTEON, WBUF) \ __PMC_EV(OCTEON, WDAT) \ __PMC_EV(OCTEON, WBUFLD) \ __PMC_EV(OCTEON, WBUFFL) \ __PMC_EV(OCTEON, WBUFTR) \ __PMC_EV(OCTEON, BADD) \ __PMC_EV(OCTEON, BADDL2) \ __PMC_EV(OCTEON, BFILL) \ __PMC_EV(OCTEON, DDIDS) \ __PMC_EV(OCTEON, IDIDS) \ __PMC_EV(OCTEON, DIDNA) \ __PMC_EV(OCTEON, LDS) \ __PMC_EV(OCTEON, LMLDS) \ __PMC_EV(OCTEON, IOLDS) \ __PMC_EV(OCTEON, DMLDS) \ __PMC_EV(OCTEON, STS) \ __PMC_EV(OCTEON, LMSTS) \ __PMC_EV(OCTEON, IOSTS) \ __PMC_EV(OCTEON, IOBDMA) \ __PMC_EV(OCTEON, DTLB) \ __PMC_EV(OCTEON, DTLBAD) \ __PMC_EV(OCTEON, ITLB) \ __PMC_EV(OCTEON, SYNC) \ __PMC_EV(OCTEON, SYNCIOB) \ __PMC_EV(OCTEON, SYNCW) #define PMC_EV_OCTEON_FIRST PMC_EV_OCTEON_CLK #define PMC_EV_OCTEON_LAST PMC_EV_OCTEON_SYNCW #define __PMC_EV_PPC7450() \ __PMC_EV(PPC7450, CYCLE) \ __PMC_EV(PPC7450, INSTR_COMPLETED) \ __PMC_EV(PPC7450, TLB_BIT_TRANSITIONS) \ __PMC_EV(PPC7450, INSTR_DISPATCHED) \ __PMC_EV(PPC7450, PMON_EXCEPT) \ __PMC_EV(PPC7450, PMON_SIG) \ __PMC_EV(PPC7450, VPU_INSTR_COMPLETED) \ __PMC_EV(PPC7450, VFPU_INSTR_COMPLETED) \ __PMC_EV(PPC7450, VIU1_INSTR_COMPLETED) \ __PMC_EV(PPC7450, VIU2_INSTR_COMPLETED) \ __PMC_EV(PPC7450, MTVSCR_INSTR_COMPLETED) \ __PMC_EV(PPC7450, MTVRSAVE_INSTR_COMPLETED) \ __PMC_EV(PPC7450, VPU_INSTR_WAIT_CYCLES) \ __PMC_EV(PPC7450, VFPU_INSTR_WAIT_CYCLES) \ __PMC_EV(PPC7450, VIU1_INSTR_WAIT_CYCLES) \ __PMC_EV(PPC7450, VIU2_INSTR_WAIT_CYCLES) \ __PMC_EV(PPC7450, MFVSCR_SYNC_CYCLES) \ __PMC_EV(PPC7450, VSCR_SAT_SET) \ __PMC_EV(PPC7450, STORE_INSTR_COMPLETED) \ __PMC_EV(PPC7450, L1_INSTR_CACHE_MISSES) \ __PMC_EV(PPC7450, L1_DATA_SNOOPS) \ __PMC_EV(PPC7450, UNRESOLVED_BRANCHES) \ __PMC_EV(PPC7450, SPEC_BUFFER_CYCLES) \ __PMC_EV(PPC7450, BRANCH_UNIT_STALL_CYCLES) \ __PMC_EV(PPC7450, TRUE_BRANCH_TARGET_HITS) \ __PMC_EV(PPC7450, BRANCH_LINK_STAC_PREDICTED) \ __PMC_EV(PPC7450, GPR_ISSUE_QUEUE_DISPATCHES) \ __PMC_EV(PPC7450, CYCLES_THREE_INSTR_DISPATCHED) \ __PMC_EV(PPC7450, THRESHOLD_INSTR_QUEUE_ENTRIES_CYCLES) \ __PMC_EV(PPC7450, THRESHOLD_VEC_INSTR_QUEUE_ENTRIES_CYCLES) \ __PMC_EV(PPC7450, CYCLES_NO_COMPLETED_INSTRS) \ __PMC_EV(PPC7450, IU2_INSTR_COMPLETED) \ __PMC_EV(PPC7450, BRANCHES_COMPLETED) \ __PMC_EV(PPC7450, EIEIO_INSTR_COMPLETED) \ __PMC_EV(PPC7450, MTSPR_INSTR_COMPLETED) \ __PMC_EV(PPC7450, SC_INSTR_COMPLETED) \ __PMC_EV(PPC7450, LS_LM_COMPLETED) \ __PMC_EV(PPC7450, ITLB_HW_TABLE_SEARCH_CYCLES) \ __PMC_EV(PPC7450, DTLB_HW_SEARCH_CYCLES_OVER_THRESHOLD) \ __PMC_EV(PPC7450, L1_INSTR_CACHE_ACCESSES) \ __PMC_EV(PPC7450, INSTR_BKPT_MATCHES) \ __PMC_EV(PPC7450, L1_DATA_CACHE_LOAD_MISS_CYCLES_OVER_THRESHOLD)\ __PMC_EV(PPC7450, L1_DATA_SNOOP_HIT_ON_MODIFIED) \ __PMC_EV(PPC7450, LOAD_MISS_ALIAS) \ __PMC_EV(PPC7450, LOAD_MISS_ALIAS_ON_TOUCH) \ __PMC_EV(PPC7450, TOUCH_ALIAS) \ __PMC_EV(PPC7450, L1_DATA_SNOOP_HIT_CASTOUT_QUEUE) \ __PMC_EV(PPC7450, L1_DATA_SNOOP_HIT_CASTOUT) \ __PMC_EV(PPC7450, L1_DATA_SNOOP_HITS) \ __PMC_EV(PPC7450, WRITE_THROUGH_STORES) \ __PMC_EV(PPC7450, CACHE_INHIBITED_STORES) \ __PMC_EV(PPC7450, L1_DATA_LOAD_HIT) \ __PMC_EV(PPC7450, L1_DATA_TOUCH_HIT) \ __PMC_EV(PPC7450, L1_DATA_STORE_HIT) \ __PMC_EV(PPC7450, L1_DATA_TOTAL_HITS) \ __PMC_EV(PPC7450, DST_INSTR_DISPATCHED) \ __PMC_EV(PPC7450, REFRESHED_DSTS) \ __PMC_EV(PPC7450, SUCCESSFUL_DST_TABLE_SEARCHES) \ __PMC_EV(PPC7450, DSS_INSTR_COMPLETED) \ __PMC_EV(PPC7450, DST_STREAM_0_CACHE_LINE_FETCHES) \ __PMC_EV(PPC7450, VTQ_SUSPENDS_DUE_TO_CTX_CHANGE) \ __PMC_EV(PPC7450, VTQ_LINE_FETCH_HIT) \ __PMC_EV(PPC7450, VEC_LOAD_INSTR_COMPLETED) \ __PMC_EV(PPC7450, FP_STORE_INSTR_COMPLETED_IN_LSU) \ __PMC_EV(PPC7450, FPU_RENORMALIZATION) \ __PMC_EV(PPC7450, FPU_DENORMALIZATION) \ __PMC_EV(PPC7450, FP_STORE_CAUSES_STALL_IN_LSU) \ __PMC_EV(PPC7450, LD_ST_TRUE_ALIAS_STALL) \ __PMC_EV(PPC7450, LSU_INDEXED_ALIAS_STALL) \ __PMC_EV(PPC7450, LSU_ALIAS_VS_FSQ_WB0_WB1) \ __PMC_EV(PPC7450, LSU_ALIAS_VS_CSQ) \ __PMC_EV(PPC7450, LSU_LOAD_HIT_LINE_ALIAS_VS_CSQ0) \ __PMC_EV(PPC7450, LSU_LOAD_MISS_LINE_ALIAS_VS_CSQ0) \ __PMC_EV(PPC7450, LSU_TOUCH_LINE_ALIAS_VS_FSQ_WB0_WB1) \ __PMC_EV(PPC7450, LSU_TOUCH_ALIAS_VS_CSQ) \ __PMC_EV(PPC7450, LSU_LMQ_FULL_STALL) \ __PMC_EV(PPC7450, FP_LOAD_INSTR_COMPLETED_IN_LSU) \ __PMC_EV(PPC7450, FP_LOAD_SINGLE_INSTR_COMPLETED_IN_LSU) \ __PMC_EV(PPC7450, FP_LOAD_DOUBLE_COMPLETED_IN_LSU) \ __PMC_EV(PPC7450, LSU_RA_LATCH_STALL) \ __PMC_EV(PPC7450, LSU_LOAD_VS_STORE_QUEUE_ALIAS_STALL) \ __PMC_EV(PPC7450, LSU_LMQ_INDEX_ALIAS) \ __PMC_EV(PPC7450, LSU_STORE_QUEUE_INDEX_ALIAS) \ __PMC_EV(PPC7450, LSU_CSQ_FORWARDING) \ __PMC_EV(PPC7450, LSU_MISALIGNED_LOAD_FINISH) \ __PMC_EV(PPC7450, LSU_MISALIGN_STORE_COMPLETED) \ __PMC_EV(PPC7450, LSU_MISALIGN_STALL) \ __PMC_EV(PPC7450, FP_ONE_QUARTER_FPSCR_RENAMES_BUSY) \ __PMC_EV(PPC7450, FP_ONE_HALF_FPSCR_RENAMES_BUSY) \ __PMC_EV(PPC7450, FP_THREE_QUARTERS_FPSCR_RENAMES_BUSY) \ __PMC_EV(PPC7450, FP_ALL_FPSCR_RENAMES_BUSY) \ __PMC_EV(PPC7450, FP_DENORMALIZED_RESULT) \ __PMC_EV(PPC7450, L1_DATA_TOTAL_MISSES) \ __PMC_EV(PPC7450, DISPATCHES_TO_FPR_ISSUE_QUEUE) \ __PMC_EV(PPC7450, LSU_INSTR_COMPLETED) \ __PMC_EV(PPC7450, LOAD_INSTR_COMPLETED) \ __PMC_EV(PPC7450, SS_SM_INSTR_COMPLETED) \ __PMC_EV(PPC7450, TLBIE_INSTR_COMPLETED) \ __PMC_EV(PPC7450, LWARX_INSTR_COMPLETED) \ __PMC_EV(PPC7450, MFSPR_INSTR_COMPLETED) \ __PMC_EV(PPC7450, REFETCH_SERIALIZATION) \ __PMC_EV(PPC7450, COMPLETION_QUEUE_ENTRIES_OVER_THRESHOLD) \ __PMC_EV(PPC7450, CYCLES_ONE_INSTR_DISPATCHED) \ __PMC_EV(PPC7450, CYCLES_TWO_INSTR_COMPLETED) \ __PMC_EV(PPC7450, ITLB_NON_SPECULATIVE_MISSES) \ __PMC_EV(PPC7450, CYCLES_WAITING_FROM_L1_INSTR_CACHE_MISS) \ __PMC_EV(PPC7450, L1_DATA_LOAD_ACCESS_MISS) \ __PMC_EV(PPC7450, L1_DATA_TOUCH_MISS) \ __PMC_EV(PPC7450, L1_DATA_STORE_MISS) \ __PMC_EV(PPC7450, L1_DATA_TOUCH_MISS_CYCLES) \ __PMC_EV(PPC7450, L1_DATA_CYCLES_USED) \ __PMC_EV(PPC7450, DST_STREAM_1_CACHE_LINE_FETCHES) \ __PMC_EV(PPC7450, VTQ_STREAM_CANCELED_PREMATURELY) \ __PMC_EV(PPC7450, VTQ_RESUMES_DUE_TO_CTX_CHANGE) \ __PMC_EV(PPC7450, VTQ_LINE_FETCH_MISS) \ __PMC_EV(PPC7450, VTQ_LINE_FETCH) \ __PMC_EV(PPC7450, TLBIE_SNOOPS) \ __PMC_EV(PPC7450, L1_INSTR_CACHE_RELOADS) \ __PMC_EV(PPC7450, L1_DATA_CACHE_RELOADS) \ __PMC_EV(PPC7450, L1_DATA_CACHE_CASTOUTS_TO_L2) \ __PMC_EV(PPC7450, STORE_MERGE_GATHER) \ __PMC_EV(PPC7450, CACHEABLE_STORE_MERGE_TO_32_BYTES) \ __PMC_EV(PPC7450, DATA_BKPT_MATCHES) \ __PMC_EV(PPC7450, FALL_THROUGH_BRANCHES_PROCESSED) \ __PMC_EV(PPC7450, \ FIRST_SPECULATIVE_BRANCH_BUFFER_RESOLVED_CORRECTLY) \ __PMC_EV(PPC7450, SECOND_SPECULATION_BUFFER_ACTIVE) \ __PMC_EV(PPC7450, BPU_STALL_ON_LR_DEPENDENCY) \ __PMC_EV(PPC7450, BTIC_MISS) \ __PMC_EV(PPC7450, BRANCH_LINK_STACK_CORRECTLY_RESOLVED) \ __PMC_EV(PPC7450, FPR_ISSUE_STALLED) \ __PMC_EV(PPC7450, SWITCHES_BETWEEN_PRIV_USER) \ __PMC_EV(PPC7450, LSU_COMPLETES_FP_STORE_SINGLE) \ __PMC_EV(PPC7450, VR_ISSUE_QUEUE_DISPATCHES) \ __PMC_EV(PPC7450, VR_STALLS) \ __PMC_EV(PPC7450, GPR_RENAME_BUFFER_ENTRIES_OVER_THRESHOLD) \ __PMC_EV(PPC7450, FPR_ISSUE_QUEUE_ENTRIES) \ __PMC_EV(PPC7450, FPU_INSTR_COMPLETED) \ __PMC_EV(PPC7450, STWCX_INSTR_COMPLETED) \ __PMC_EV(PPC7450, LS_LM_INSTR_PIECES) \ __PMC_EV(PPC7450, ITLB_HW_SEARCH_CYCLES_OVER_THRESHOLD) \ __PMC_EV(PPC7450, DTLB_MISSES) \ __PMC_EV(PPC7450, CANCELLED_L1_INSTR_CACHE_MISSES) \ __PMC_EV(PPC7450, L1_DATA_CACHE_OP_HIT) \ __PMC_EV(PPC7450, L1_DATA_LOAD_MISS_CYCLES) \ __PMC_EV(PPC7450, L1_DATA_PUSHES) \ __PMC_EV(PPC7450, L1_DATA_TOTAL_MISS) \ __PMC_EV(PPC7450, VT2_FETCHES) \ __PMC_EV(PPC7450, TAKEN_BRANCHES_PROCESSED) \ __PMC_EV(PPC7450, BRANCH_FLUSHES) \ __PMC_EV(PPC7450, \ SECOND_SPECULATIVE_BRANCH_BUFFER_RESOLVED_CORRECTLY) \ __PMC_EV(PPC7450, THIRD_SPECULATION_BUFFER_ACTIVE) \ __PMC_EV(PPC7450, BRANCH_UNIT_STALL_ON_CTR_DEPENDENCY) \ __PMC_EV(PPC7450, FAST_BTIC_HIT) \ __PMC_EV(PPC7450, BRANCH_LINK_STACK_MISPREDICTED) \ __PMC_EV(PPC7450, CYCLES_THREE_INSTR_COMPLETED) \ __PMC_EV(PPC7450, CYCLES_NO_INSTR_DISPATCHED) \ __PMC_EV(PPC7450, GPR_ISSUE_QUEUE_ENTRIES_OVER_THRESHOLD) \ __PMC_EV(PPC7450, GPR_ISSUE_QUEUE_STALLED) \ __PMC_EV(PPC7450, IU1_INSTR_COMPLETED) \ __PMC_EV(PPC7450, DSSALL_INSTR_COMPLETED) \ __PMC_EV(PPC7450, TLBSYNC_INSTR_COMPLETED) \ __PMC_EV(PPC7450, SYNC_INSTR_COMPLETED) \ __PMC_EV(PPC7450, SS_SM_INSTR_PIECES) \ __PMC_EV(PPC7450, DTLB_HW_SEARCH_CYCLES) \ __PMC_EV(PPC7450, SNOOP_RETRIES) \ __PMC_EV(PPC7450, SUCCESSFUL_STWCX) \ __PMC_EV(PPC7450, DST_STREAM_3_CACHE_LINE_FETCHES) \ __PMC_EV(PPC7450, \ THIRD_SPECULATIVE_BRANCH_BUFFER_RESOLVED_CORRECTLY) \ __PMC_EV(PPC7450, MISPREDICTED_BRANCHES) \ __PMC_EV(PPC7450, FOLDED_BRANCHES) \ __PMC_EV(PPC7450, FP_STORE_DOUBLE_COMPLETES_IN_LSU) \ __PMC_EV(PPC7450, L2_CACHE_HITS) \ __PMC_EV(PPC7450, L3_CACHE_HITS) \ __PMC_EV(PPC7450, L2_INSTR_CACHE_MISSES) \ __PMC_EV(PPC7450, L3_INSTR_CACHE_MISSES) \ __PMC_EV(PPC7450, L2_DATA_CACHE_MISSES) \ __PMC_EV(PPC7450, L3_DATA_CACHE_MISSES) \ __PMC_EV(PPC7450, L2_LOAD_HITS) \ __PMC_EV(PPC7450, L2_STORE_HITS) \ __PMC_EV(PPC7450, L3_LOAD_HITS) \ __PMC_EV(PPC7450, L3_STORE_HITS) \ __PMC_EV(PPC7450, L2_TOUCH_HITS) \ __PMC_EV(PPC7450, L3_TOUCH_HITS) \ __PMC_EV(PPC7450, SNOOP_MODIFIED) \ __PMC_EV(PPC7450, SNOOP_VALID) \ __PMC_EV(PPC7450, INTERVENTION) \ __PMC_EV(PPC7450, L2_CACHE_MISSES) \ __PMC_EV(PPC7450, L3_CACHE_MISSES) \ __PMC_EV(PPC7450, L2_CACHE_CASTOUTS) \ __PMC_EV(PPC7450, L3_CACHE_CASTOUTS) \ __PMC_EV(PPC7450, L2SQ_FULL_CYCLES) \ __PMC_EV(PPC7450, L3SQ_FULL_CYCLES) \ __PMC_EV(PPC7450, RAQ_FULL_CYCLES) \ __PMC_EV(PPC7450, WAQ_FULL_CYCLES) \ __PMC_EV(PPC7450, L1_EXTERNAL_INTERVENTIONS) \ __PMC_EV(PPC7450, L2_EXTERNAL_INTERVENTIONS) \ __PMC_EV(PPC7450, L3_EXTERNAL_INTERVENTIONS) \ __PMC_EV(PPC7450, EXTERNAL_INTERVENTIONS) \ __PMC_EV(PPC7450, EXTERNAL_PUSHES) \ __PMC_EV(PPC7450, EXTERNAL_SNOOP_RETRY) \ __PMC_EV(PPC7450, DTQ_FULL_CYCLES) \ __PMC_EV(PPC7450, BUS_RETRY) \ __PMC_EV(PPC7450, L2_VALID_REQUEST) \ __PMC_EV(PPC7450, BORDQ_FULL) \ __PMC_EV(PPC7450, BUS_TAS_FOR_READS) \ __PMC_EV(PPC7450, BUS_TAS_FOR_WRITES) \ __PMC_EV(PPC7450, BUS_READS_NOT_RETRIED) \ __PMC_EV(PPC7450, BUS_WRITES_NOT_RETRIED) \ __PMC_EV(PPC7450, BUS_READS_WRITES_NOT_RETRIED) \ __PMC_EV(PPC7450, BUS_RETRY_DUE_TO_L1_RETRY) \ __PMC_EV(PPC7450, BUS_RETRY_DUE_TO_PREVIOUS_ADJACENT) \ __PMC_EV(PPC7450, BUS_RETRY_DUE_TO_COLLISION) \ __PMC_EV(PPC7450, BUS_RETRY_DUE_TO_INTERVENTION_ORDERING) \ __PMC_EV(PPC7450, SNOOP_REQUESTS) \ __PMC_EV(PPC7450, PREFETCH_ENGINE_REQUEST) \ __PMC_EV(PPC7450, PREFETCH_ENGINE_COLLISION_VS_LOAD) \ __PMC_EV(PPC7450, PREFETCH_ENGINE_COLLISION_VS_STORE) \ __PMC_EV(PPC7450, PREFETCH_ENGINE_COLLISION_VS_INSTR_FETCH) \ __PMC_EV(PPC7450, \ PREFETCH_ENGINE_COLLISION_VS_LOAD_STORE_INSTR_FETCH) \ __PMC_EV(PPC7450, PREFETCH_ENGINE_FULL) #define PMC_EV_PPC7450_FIRST PMC_EV_PPC7450_CYCLE #define PMC_EV_PPC7450_LAST PMC_EV_PPC7450_PREFETCH_ENGINE_FULL #define __PMC_EV_PPC970() \ __PMC_EV(PPC970, INSTR_COMPLETED) \ __PMC_EV(PPC970, MARKED_GROUP_DISPATCH) \ __PMC_EV(PPC970, MARKED_STORE_COMPLETED) \ __PMC_EV(PPC970, GCT_EMPTY) \ __PMC_EV(PPC970, RUN_CYCLES) \ __PMC_EV(PPC970, OVERFLOW) \ __PMC_EV(PPC970, CYCLES) \ __PMC_EV(PPC970, THRESHOLD_TIMEOUT) \ __PMC_EV(PPC970, GROUP_DISPATCH) \ __PMC_EV(PPC970, BR_MARKED_INSTR_FINISH) \ __PMC_EV(PPC970, GCT_EMPTY_BY_SRQ_FULL) \ __PMC_EV(PPC970, STOP_COMPLETION) \ __PMC_EV(PPC970, LSU_EMPTY) \ __PMC_EV(PPC970, MARKED_STORE_WITH_INTR) \ __PMC_EV(PPC970, CYCLES_IN_SUPER) \ __PMC_EV(PPC970, VPU_MARKED_INSTR_COMPLETED) \ __PMC_EV(PPC970, FXU0_IDLE_FXU1_BUSY) \ __PMC_EV(PPC970, SRQ_EMPTY) \ __PMC_EV(PPC970, MARKED_GROUP_COMPLETED) \ __PMC_EV(PPC970, CR_MARKED_INSTR_FINISH) \ __PMC_EV(PPC970, DISPATCH_SUCCESS) \ __PMC_EV(PPC970, FXU0_IDLE_FXU1_IDLE) \ __PMC_EV(PPC970, ONE_PLUS_INSTR_COMPLETED) \ __PMC_EV(PPC970, GROUP_MARKED_IDU) \ __PMC_EV(PPC970, MARKED_GROUP_COMPLETE_TIMEOUT) \ __PMC_EV(PPC970, FXU0_BUSY_FXU1_BUSY) \ __PMC_EV(PPC970, MARKED_STORE_SENT_TO_STS) \ __PMC_EV(PPC970, FXU_MARKED_INSTR_FINISHED) \ __PMC_EV(PPC970, MARKED_GROUP_ISSUED) \ __PMC_EV(PPC970, FXU0_BUSY_FXU1_IDLE) \ __PMC_EV(PPC970, GROUP_COMPLETED) \ __PMC_EV(PPC970, FPU_MARKED_INSTR_COMPLETED) \ __PMC_EV(PPC970, MARKED_INSTR_FINISH_ANY_UNIT) \ __PMC_EV(PPC970, EXTERNAL_INTERRUPT) \ __PMC_EV(PPC970, GROUP_DISPATCH_REJECT) \ __PMC_EV(PPC970, LSU_MARKED_INSTR_FINISH) \ __PMC_EV(PPC970, TIMEBASE_EVENT) \ __PMC_EV(PPC970, LSU_COMPLETION_STALL) \ __PMC_EV(PPC970, FXU_COMPLETION_STALL) \ __PMC_EV(PPC970, DCACHE_MISS_COMPLETION_STALL) \ __PMC_EV(PPC970, FPU_COMPLETION_STALL) \ __PMC_EV(PPC970, FXU_LONG_INSTR_COMPLETION_STALL) \ __PMC_EV(PPC970, REJECT_COMPLETION_STALL) \ __PMC_EV(PPC970, FPU_LONG_INSTR_COMPLETION_STALL) \ __PMC_EV(PPC970, GCT_EMPTY_BY_ICACHE_MISS) \ __PMC_EV(PPC970, REJECT_COMPLETION_STALL_ERAT_MISS) \ __PMC_EV(PPC970, GCT_EMPTY_BY_BRANCH_MISS_PREDICT) \ __PMC_EV(PPC970, BUS_HIGH) \ __PMC_EV(PPC970, BUS_LOW) \ __PMC_EV(PPC970, ADDER) #define PMC_EV_PPC970_FIRST PMC_EV_PPC970_INSTR_COMPLETED #define PMC_EV_PPC970_LAST PMC_EV_PPC970_ADDER +#define __PMC_EV_POWER8() \ + __PMC_EV(POWER8, CYCLES) \ + __PMC_EV(POWER8, CYCLES_WITH_INSTRS_COMPLETED) \ + __PMC_EV(POWER8, FPU_INSTR_COMPLETED) \ + __PMC_EV(POWER8, ERAT_INSTR_MISS) \ + __PMC_EV(POWER8, CYCLES_IDLE) \ + __PMC_EV(POWER8, CYCLES_WITH_ANY_THREAD_RUNNING) \ + __PMC_EV(POWER8, STORE_COMPLETED) \ + __PMC_EV(POWER8, INSTR_DISPATCHED) \ + __PMC_EV(POWER8, CYCLES_RUNNING) \ + __PMC_EV(POWER8, ERAT_DATA_MISS) \ + __PMC_EV(POWER8, EXTERNAL_INTERRUPT) \ + __PMC_EV(POWER8, BRANCH_TAKEN) \ + __PMC_EV(POWER8, L1_INSTR_MISS) \ + __PMC_EV(POWER8, L2_LOAD_MISS) \ + __PMC_EV(POWER8, STORE_NO_REAL_ADDR) \ + __PMC_EV(POWER8, INSTR_COMPLETED_WITH_ALL_THREADS_RUNNING) \ + __PMC_EV(POWER8, L1_LOAD_MISS) \ + __PMC_EV(POWER8, TIMEBASE_EVENT) \ + __PMC_EV(POWER8, L3_INSTR_MISS) \ + __PMC_EV(POWER8, TLB_DATA_MISS) \ + __PMC_EV(POWER8, L3_LOAD_MISS) \ + __PMC_EV(POWER8, LOAD_NO_REAL_ADDR) \ + __PMC_EV(POWER8, CYCLES_WITH_INSTRS_DISPATCHED) \ + __PMC_EV(POWER8, CYCLES_RUNNING_PURR_INC) \ + __PMC_EV(POWER8, BRANCH_MISPREDICTED) \ + __PMC_EV(POWER8, PREFETCHED_INSTRS_DISCARDED) \ + __PMC_EV(POWER8, INSTR_COMPLETED_RUNNING) \ + __PMC_EV(POWER8, TLB_INSTR_MISS) \ + __PMC_EV(POWER8, CACHE_LOAD_MISS) \ + __PMC_EV(POWER8, INSTR_COMPLETED) + +#define PMC_EV_POWER8_FIRST PMC_EV_POWER8_CYCLES +#define PMC_EV_POWER8_LAST PMC_EV_POWER8_INSTR_COMPLETED + #define __PMC_EV_E500() \ __PMC_EV(E500, CYCLES) \ __PMC_EV(E500, INSTR_COMPLETED) \ __PMC_EV(E500, UOPS_COMPLETED) \ __PMC_EV(E500, INSTR_FETCHED) \ __PMC_EV(E500, UOPS_DECODED) \ __PMC_EV(E500, PM_EVENT_TRANSITIONS) \ __PMC_EV(E500, PM_EVENT_CYCLES) \ __PMC_EV(E500, BRANCH_INSTRS_COMPLETED) \ __PMC_EV(E500, LOAD_UOPS_COMPLETED) \ __PMC_EV(E500, STORE_UOPS_COMPLETED) \ __PMC_EV(E500, CQ_REDIRECTS) \ __PMC_EV(E500, BRANCHES_FINISHED) \ __PMC_EV(E500, TAKEN_BRANCHES_FINISHED) \ __PMC_EV(E500, FINISHED_UNCOND_BRANCHES_MISS_BTB) \ __PMC_EV(E500, BRANCH_MISPRED) \ __PMC_EV(E500, BTB_BRANCH_MISPRED_FROM_DIRECTION) \ __PMC_EV(E500, BTB_HITS_PSEUDO_HITS) \ __PMC_EV(E500, CYCLES_DECODE_STALLED) \ __PMC_EV(E500, CYCLES_ISSUE_STALLED) \ __PMC_EV(E500, CYCLES_BRANCH_ISSUE_STALLED) \ __PMC_EV(E500, CYCLES_SU1_SCHED_STALLED) \ __PMC_EV(E500, CYCLES_SU2_SCHED_STALLED) \ __PMC_EV(E500, CYCLES_MU_SCHED_STALLED) \ __PMC_EV(E500, CYCLES_LRU_SCHED_STALLED) \ __PMC_EV(E500, CYCLES_BU_SCHED_STALLED) \ __PMC_EV(E500, TOTAL_TRANSLATED) \ __PMC_EV(E500, LOADS_TRANSLATED) \ __PMC_EV(E500, STORES_TRANSLATED) \ __PMC_EV(E500, TOUCHES_TRANSLATED) \ __PMC_EV(E500, CACHEOPS_TRANSLATED) \ __PMC_EV(E500, CACHE_INHIBITED_ACCESS_TRANSLATED) \ __PMC_EV(E500, GUARDED_LOADS_TRANSLATED) \ __PMC_EV(E500, WRITE_THROUGH_STORES_TRANSLATED) \ __PMC_EV(E500, MISALIGNED_LOAD_STORE_ACCESS_TRANSLATED) \ __PMC_EV(E500, TOTAL_ALLOCATED_TO_DLFB) \ __PMC_EV(E500, LOADS_TRANSLATED_ALLOCATED_TO_DLFB) \ __PMC_EV(E500, STORES_COMPLETED_ALLOCATED_TO_DLFB) \ __PMC_EV(E500, TOUCHES_TRANSLATED_ALLOCATED_TO_DLFB) \ __PMC_EV(E500, STORES_COMPLETED) \ __PMC_EV(E500, DATA_L1_CACHE_LOCKS) \ __PMC_EV(E500, DATA_L1_CACHE_RELOADS) \ __PMC_EV(E500, DATA_L1_CACHE_CASTOUTS) \ __PMC_EV(E500, LOAD_MISS_DLFB_FULL) \ __PMC_EV(E500, LOAD_MISS_LDQ_FULL) \ __PMC_EV(E500, LOAD_GUARDED_MISS) \ __PMC_EV(E500, STORE_TRANSLATE_WHEN_QUEUE_FULL) \ __PMC_EV(E500, ADDRESS_COLLISION) \ __PMC_EV(E500, DATA_MMU_MISS) \ __PMC_EV(E500, DATA_MMU_BUSY) \ __PMC_EV(E500, PART2_MISALIGNED_CACHE_ACCESS) \ __PMC_EV(E500, LOAD_MISS_DLFB_FULL_CYCLES) \ __PMC_EV(E500, LOAD_MISS_LDQ_FULL_CYCLES) \ __PMC_EV(E500, LOAD_GUARDED_MISS_CYCLES) \ __PMC_EV(E500, STORE_TRANSLATE_WHEN_QUEUE_FULL_CYCLES) \ __PMC_EV(E500, ADDRESS_COLLISION_CYCLES) \ __PMC_EV(E500, DATA_MMU_MISS_CYCLES) \ __PMC_EV(E500, DATA_MMU_BUSY_CYCLES) \ __PMC_EV(E500, PART2_MISALIGNED_CACHE_ACCESS_CYCLES) \ __PMC_EV(E500, INSTR_L1_CACHE_LOCKS) \ __PMC_EV(E500, INSTR_L1_CACHE_RELOADS) \ __PMC_EV(E500, INSTR_L1_CACHE_FETCHES) \ __PMC_EV(E500, INSTR_MMU_TLB4K_RELOADS) \ __PMC_EV(E500, INSTR_MMU_VSP_RELOADS) \ __PMC_EV(E500, DATA_MMU_TLB4K_RELOADS) \ __PMC_EV(E500, DATA_MMU_VSP_RELOADS) \ __PMC_EV(E500, L2MMU_MISSES) \ __PMC_EV(E500, BIU_MASTER_REQUESTS) \ __PMC_EV(E500, BIU_MASTER_INSTR_SIDE_REQUESTS) \ __PMC_EV(E500, BIU_MASTER_DATA_SIDE_REQUESTS) \ __PMC_EV(E500, BIU_MASTER_DATA_SIDE_CASTOUT_REQUESTS) \ __PMC_EV(E500, BIU_MASTER_RETRIES) \ __PMC_EV(E500, SNOOP_REQUESTS) \ __PMC_EV(E500, SNOOP_HITS) \ __PMC_EV(E500, SNOOP_PUSHES) \ __PMC_EV(E500, SNOOP_RETRIES) \ __PMC_EV(E500, DLFB_LOAD_MISS_CYCLES) \ __PMC_EV(E500, ILFB_FETCH_MISS_CYCLES) \ __PMC_EV(E500, EXT_INPU_INTR_LATENCY_CYCLES) \ __PMC_EV(E500, CRIT_INPUT_INTR_LATENCY_CYCLES) \ __PMC_EV(E500, EXT_INPUT_INTR_PENDING_LATENCY_CYCLES) \ __PMC_EV(E500, CRIT_INPUT_INTR_PENDING_LATENCY_CYCLES) \ __PMC_EV(E500, PMC0_OVERFLOW) \ __PMC_EV(E500, PMC1_OVERFLOW) \ __PMC_EV(E500, PMC2_OVERFLOW) \ __PMC_EV(E500, PMC3_OVERFLOW) \ __PMC_EV(E500, INTERRUPTS_TAKEN) \ __PMC_EV(E500, EXT_INPUT_INTR_TAKEN) \ __PMC_EV(E500, CRIT_INPUT_INTR_TAKEN) \ __PMC_EV(E500, SYSCALL_TRAP_INTR) \ __PMC_EV(E500, TLB_BIT_TRANSITIONS) \ __PMC_EV(E500, L2_LINEFILL_BUFFER) \ __PMC_EV(E500, LV2_VS) \ __PMC_EV(E500, CASTOUTS_RELEASED) \ __PMC_EV(E500, INTV_ALLOCATIONS) \ __PMC_EV(E500, DLFB_RETRIES_TO_MBAR) \ __PMC_EV(E500, STORE_RETRIES) \ __PMC_EV(E500, STASH_L1_HITS) \ __PMC_EV(E500, STASH_L2_HITS) \ __PMC_EV(E500, STASH_BUSY_1) \ __PMC_EV(E500, STASH_BUSY_2) \ __PMC_EV(E500, STASH_BUSY_3) \ __PMC_EV(E500, STASH_HITS) \ __PMC_EV(E500, STASH_HIT_DLFB) \ __PMC_EV(E500, STASH_REQUESTS) \ __PMC_EV(E500, STASH_REQUESTS_L1) \ __PMC_EV(E500, STASH_REQUESTS_L2) \ __PMC_EV(E500, STALLS_NO_CAQ_OR_COB) \ __PMC_EV(E500, L2_CACHE_ACCESSES) \ __PMC_EV(E500, L2_HIT_CACHE_ACCESSES) \ __PMC_EV(E500, L2_CACHE_DATA_ACCESSES) \ __PMC_EV(E500, L2_CACHE_DATA_HITS) \ __PMC_EV(E500, L2_CACHE_INSTR_ACCESSES) \ __PMC_EV(E500, L2_CACHE_INSTR_HITS) \ __PMC_EV(E500, L2_CACHE_ALLOCATIONS) \ __PMC_EV(E500, L2_CACHE_DATA_ALLOCATIONS) \ __PMC_EV(E500, L2_CACHE_DIRTY_DATA_ALLOCATIONS) \ __PMC_EV(E500, L2_CACHE_INSTR_ALLOCATIONS) \ __PMC_EV(E500, L2_CACHE_UPDATES) \ __PMC_EV(E500, L2_CACHE_CLEAN_UPDATES) \ __PMC_EV(E500, L2_CACHE_DIRTY_UPDATES) \ __PMC_EV(E500, L2_CACHE_CLEAN_REDUNDANT_UPDATES) \ __PMC_EV(E500, L2_CACHE_DIRTY_REDUNDANT_UPDATES) \ __PMC_EV(E500, L2_CACHE_LOCKS) \ __PMC_EV(E500, L2_CACHE_CASTOUTS) \ __PMC_EV(E500, L2_CACHE_DATA_DIRTY_HITS) \ __PMC_EV(E500, INSTR_LFB_WENT_HIGH_PRIORITY) \ __PMC_EV(E500, SNOOP_THROTTLING_TURNED_ON) \ __PMC_EV(E500, L2_CLEAN_LINE_INVALIDATIONS) \ __PMC_EV(E500, L2_INCOHERENT_LINE_INVALIDATIONS) \ __PMC_EV(E500, L2_COHERENT_LINE_INVALIDATIONS) \ __PMC_EV(E500, COHERENT_LOOKUP_MISS_DUE_TO_VALID_BUT_INCOHERENT_MATCHES) \ __PMC_EV(E500, IAC1S_DETECTED) \ __PMC_EV(E500, IAC2S_DETECTED) \ __PMC_EV(E500, DAC1S_DTECTED) \ __PMC_EV(E500, DAC2S_DTECTED) \ __PMC_EV(E500, DVT0_DETECTED) \ __PMC_EV(E500, DVT1_DETECTED) \ __PMC_EV(E500, DVT2_DETECTED) \ __PMC_EV(E500, DVT3_DETECTED) \ __PMC_EV(E500, DVT4_DETECTED) \ __PMC_EV(E500, DVT5_DETECTED) \ __PMC_EV(E500, DVT6_DETECTED) \ __PMC_EV(E500, DVT7_DETECTED) \ __PMC_EV(E500, CYCLES_COMPLETION_STALLED_NEXUS_FIFO_FULL) \ __PMC_EV(E500, FPU_DOUBLE_PUMP) \ __PMC_EV(E500, FPU_FINISH) \ __PMC_EV(E500, FPU_DIVIDE_CYCLES) \ __PMC_EV(E500, FPU_DENORM_INPUT_CYCLES) \ __PMC_EV(E500, FPU_RESULT_STALL_CYCLES) \ __PMC_EV(E500, FPU_FPSCR_FULL_STALL) \ __PMC_EV(E500, FPU_PIPE_SYNC_STALLS) \ __PMC_EV(E500, FPU_INPUT_DATA_STALLS) \ __PMC_EV(E500, DECORATED_LOADS) \ __PMC_EV(E500, DECORATED_STORES) \ __PMC_EV(E500, LOAD_RETRIES) \ __PMC_EV(E500, STWCX_SUCCESSES) \ __PMC_EV(E500, STWCX_FAILURES) \ #define PMC_EV_E500_FIRST PMC_EV_E500_CYCLES #define PMC_EV_E500_LAST PMC_EV_E500_STWCX_FAILURES /* * All known PMC events. * * PMC event numbers are allocated sparsely to allow new PMC events to * be added to a PMC class without breaking ABI compatibility. The * current allocation scheme is: * * START #EVENTS DESCRIPTION * 0 0x1000 Reserved * 0x1000 0x0001 TSC * 0x2000 0x0080 AMD K7 events * 0x2080 0x0100 AMD K8 events * 0x10000 0x0080 INTEL architectural fixed-function events * 0x10080 0x0F80 INTEL architectural programmable events * 0x11000 0x0080 INTEL Pentium 4 events * 0x11080 0x0080 INTEL Pentium MMX events * 0x11100 0x0100 INTEL Pentium Pro/P-II/P-III/Pentium-M events * 0x11200 0x00FF INTEL XScale events * 0x11300 0x00FF MIPS 24K events * 0x11400 0x00FF Octeon events * 0x11500 0x00FF MIPS 74K events * 0x11600 0x00FF BERI statcounters * 0x13000 0x00FF MPC7450 events * 0x13100 0x00FF IBM PPC970 events + * 0x13200 0x00FF IBM POWER8 events * 0x13300 0x00FF Freescale e500 events * 0x14000 0x0100 ARMv7 events * 0x14100 0x0100 ARMv8 events * 0x20000 0x1000 Software events */ #define __PMC_EVENTS() \ __PMC_EV_BLOCK(TSC, 0x01000) \ __PMC_EV_TSC() \ __PMC_EV_BLOCK(IAF, 0x10000) \ __PMC_EV_IAF() \ __PMC_EV_BLOCK(K7, 0x2000) \ __PMC_EV_K7() \ __PMC_EV_BLOCK(K8, 0x2080) \ __PMC_EV_K8() \ __PMC_EV_BLOCK(XSCALE, 0x11200) \ __PMC_EV_XSCALE() \ __PMC_EV_BLOCK(MIPS24K, 0x11300) \ __PMC_EV_MIPS24K() \ __PMC_EV_BLOCK(OCTEON, 0x11400) \ __PMC_EV_OCTEON() \ __PMC_EV_BLOCK(MIPS74K, 0x11500) \ __PMC_EV_MIPS74K() \ __PMC_EV_BLOCK(BERI, 0x11600) \ __PMC_EV_BERI() \ __PMC_EV_BLOCK(UCP, 0x12080) \ __PMC_EV_UCP() \ __PMC_EV_BLOCK(PPC7450, 0x13000) \ __PMC_EV_PPC7450() \ __PMC_EV_BLOCK(PPC970, 0x13100) \ __PMC_EV_PPC970() \ + __PMC_EV_BLOCK(POWER8, 0x13200) \ + __PMC_EV_POWER8() \ __PMC_EV_BLOCK(E500, 0x13300) \ __PMC_EV_E500() \ __PMC_EV_BLOCK(ARMV7, 0x14000) \ __PMC_EV_ARMV7() \ __PMC_EV_BLOCK(ARMV8, 0x14100) \ __PMC_EV_ARMV8() #define PMC_EVENT_FIRST PMC_EV_TSC_TSC #define PMC_EVENT_LAST PMC_EV_SOFT_LAST #endif /* _DEV_HWPMC_PMC_EVENTS_H_ */ Index: head/sys/modules/hwpmc/Makefile =================================================================== --- head/sys/modules/hwpmc/Makefile (revision 367389) +++ head/sys/modules/hwpmc/Makefile (revision 367390) @@ -1,38 +1,39 @@ # # $FreeBSD$ # .PATH: ${SRCTOP}/sys/dev/hwpmc KMOD= hwpmc SRCS= bus_if.h device_if.h hwpmc_mod.c hwpmc_logging.c hwpmc_soft.c SRCS+= vnode_if.h .if ${MACHINE_CPUARCH} == "aarch64" SRCS+= hwpmc_arm64.c hwpmc_arm64_md.c .endif .if ${MACHINE_CPUARCH} == "amd64" SRCS+= hwpmc_amd.c hwpmc_core.c hwpmc_intel.c hwpmc_tsc.c SRCS+= hwpmc_x86.c hwpmc_uncore.c .endif .if ${MACHINE_CPUARCH} == "arm" SRCS+= hwpmc_arm.c .endif .if ${MACHINE_ARCH} == "armv7" SRCS+= hwpmc_armv7.c .endif .if ${MACHINE_CPUARCH} == "i386" SRCS+= hwpmc_amd.c hwpmc_core.c hwpmc_intel.c SRCS+= hwpmc_tsc.c hwpmc_x86.c hwpmc_uncore.c .endif .if ${MACHINE_CPUARCH} == "powerpc" -SRCS+= hwpmc_powerpc.c hwpmc_e500.c hwpmc_mpc7xxx.c hwpmc_ppc970.c +SRCS+= hwpmc_powerpc.c hwpmc_e500.c hwpmc_mpc7xxx.c hwpmc_ppc970.c \ + hwpmc_power8.c .endif .include Index: head/sys/powerpc/include/pmc_mdep.h =================================================================== --- head/sys/powerpc/include/pmc_mdep.h (revision 367389) +++ head/sys/powerpc/include/pmc_mdep.h (revision 367390) @@ -1,95 +1,96 @@ /*- * This file is in the public domain. * * $FreeBSD$ */ #ifndef _MACHINE_PMC_MDEP_H_ #define _MACHINE_PMC_MDEP_H_ #define PMC_MDEP_CLASS_INDEX_POWERPC 1 union pmc_md_op_pmcallocate { uint64_t __pad[4]; }; /* Logging */ #ifdef __powerpc64__ #define PMCLOG_READADDR PMCLOG_READ64 #define PMCLOG_EMITADDR PMCLOG_EMIT64 #else #define PMCLOG_READADDR PMCLOG_READ32 #define PMCLOG_EMITADDR PMCLOG_EMIT32 #endif #define mtpmr(reg, val) \ __asm __volatile("mtpmr %0,%1" : : "K"(reg), "r"(val)) #define mfpmr(reg) \ ( { register_t val; \ __asm __volatile("mfpmr %0,%1" : "=r"(val) : "K"(reg)); \ val; } ) #define PMR_PMC0 16 #define PMR_PMC1 17 #define PMR_PMC2 18 #define PMR_PMC3 19 #define PMR_PMLCa0 144 #define PMLCax_FC 0x80000000 #define PMLCax_FCS 0x40000000 #define PMLCax_FCU 0x20000000 #define PMLCax_FCM1 0x10000000 #define PMLCax_FCM0 0x08000000 #define PMLCax_CE 0x04000000 #define PMLCax_EVENT(x) ((x) << 16) #define PMLCax_FCGS1 0x00000002 #define PMLCax_FCGS0 0x00000001 #define PMR_PMLCa1 145 #define PMR_PMLCa2 146 #define PMR_PMLCa3 147 #define PMR_PMLCb0 272 #define PMLCbx_TRIGONCTL(x) ((x) << 28) #define PMLCbx_TRIGOFFCTL(x) ((x) << 24) #define PMLCbx_PMCC 0x00800000 #define PMLCbx_PMP(x) ((x) << 13) #define PMLCbx_TREHMUL(x) ((x) << 8) #define PMLCbx_TRESHOLD(x) ((x) << 0) #define PMR_PMLCb1 273 #define PMR_PMLCb2 274 #define PMR_PMLCb3 275 #define PMR_PMGC0 400 #define PMGC_FAC 0x80000000 #define PMGC_PMIE 0x40000000 #define PMGC_FCECE 0x20000000 #define PMGC_TBSEL(x) ((x) << 11) #define PMGC_TBEE 0x00000100 #define PMR_UPMC0 0 #define PMR_UPMC1 1 #define PMR_UPMC2 2 #define PMR_UPMC3 3 #define PMR_UPMLCa0 128 #define PMR_UPMLCa1 129 #define PMR_UPMLCa2 130 #define PMR_UPMLCa3 131 #define PMR_UPMLCb0 256 #define PMR_UPMLCb1 257 #define PMR_UPMLCb2 258 #define PMR_UPMLCb3 259 #define PMR_UPMGC0 384 #if _KERNEL struct pmc_md_powerpc_pmc { + uint64_t pm_powerpc_overflowcnt; uint32_t pm_powerpc_evsel; }; union pmc_md_pmc { struct pmc_md_powerpc_pmc pm_powerpc; }; #define PMC_TRAPFRAME_TO_PC(TF) ((TF)->srr0) #define PMC_TRAPFRAME_TO_FP(TF) ((TF)->fixreg[1]) #define PMC_TRAPFRAME_TO_SP(TF) (0) #endif #endif /* !_MACHINE_PMC_MDEP_H_ */ Index: head/sys/sys/pmc.h =================================================================== --- head/sys/sys/pmc.h (revision 367389) +++ head/sys/sys/pmc.h (revision 367390) @@ -1,1225 +1,1227 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2003-2008, Joseph Koshy * Copyright (c) 2007 The FreeBSD Foundation * All rights reserved. * * Portions of this software were developed by A. Joseph Koshy under * sponsorship from the FreeBSD Foundation and Google, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SYS_PMC_H_ #define _SYS_PMC_H_ #include #include #include #include #include #ifdef _KERNEL #include #include #endif #define PMC_MODULE_NAME "hwpmc" #define PMC_NAME_MAX 64 /* HW counter name size */ #define PMC_CLASS_MAX 8 /* max #classes of PMCs per-system */ /* * Kernel<->userland API version number [MMmmpppp] * * Major numbers are to be incremented when an incompatible change to * the ABI occurs that older clients will not be able to handle. * * Minor numbers are incremented when a backwards compatible change * occurs that allows older correct programs to run unchanged. For * example, when support for a new PMC type is added. * * The patch version is incremented for every bug fix. */ #define PMC_VERSION_MAJOR 0x09 #define PMC_VERSION_MINOR 0x03 #define PMC_VERSION_PATCH 0x0000 #define PMC_VERSION (PMC_VERSION_MAJOR << 24 | \ PMC_VERSION_MINOR << 16 | PMC_VERSION_PATCH) #define PMC_CPUID_LEN 64 /* cpu model name for pmu lookup */ extern char pmc_cpuid[PMC_CPUID_LEN]; /* * Kinds of CPUs known. * * We keep track of CPU variants that need to be distinguished in * some way for PMC operations. CPU names are grouped by manufacturer * and numbered sparsely in order to minimize changes to the ABI involved * when new CPUs are added. */ #define __PMC_CPUS() \ __PMC_CPU(AMD_K7, 0x00, "AMD K7") \ __PMC_CPU(AMD_K8, 0x01, "AMD K8") \ __PMC_CPU(INTEL_P5, 0x80, "Intel Pentium") \ __PMC_CPU(INTEL_P6, 0x81, "Intel Pentium Pro") \ __PMC_CPU(INTEL_CL, 0x82, "Intel Celeron") \ __PMC_CPU(INTEL_PII, 0x83, "Intel Pentium II") \ __PMC_CPU(INTEL_PIII, 0x84, "Intel Pentium III") \ __PMC_CPU(INTEL_PM, 0x85, "Intel Pentium M") \ __PMC_CPU(INTEL_PIV, 0x86, "Intel Pentium IV") \ __PMC_CPU(INTEL_CORE, 0x87, "Intel Core Solo/Duo") \ __PMC_CPU(INTEL_CORE2, 0x88, "Intel Core2") \ __PMC_CPU(INTEL_CORE2EXTREME, 0x89, "Intel Core2 Extreme") \ __PMC_CPU(INTEL_ATOM, 0x8A, "Intel Atom") \ __PMC_CPU(INTEL_COREI7, 0x8B, "Intel Core i7") \ __PMC_CPU(INTEL_WESTMERE, 0x8C, "Intel Westmere") \ __PMC_CPU(INTEL_SANDYBRIDGE, 0x8D, "Intel Sandy Bridge") \ __PMC_CPU(INTEL_IVYBRIDGE, 0x8E, "Intel Ivy Bridge") \ __PMC_CPU(INTEL_SANDYBRIDGE_XEON, 0x8F, "Intel Sandy Bridge Xeon") \ __PMC_CPU(INTEL_IVYBRIDGE_XEON, 0x90, "Intel Ivy Bridge Xeon") \ __PMC_CPU(INTEL_HASWELL, 0x91, "Intel Haswell") \ __PMC_CPU(INTEL_ATOM_SILVERMONT, 0x92, "Intel Atom Silvermont") \ __PMC_CPU(INTEL_NEHALEM_EX, 0x93, "Intel Nehalem Xeon 7500") \ __PMC_CPU(INTEL_WESTMERE_EX, 0x94, "Intel Westmere Xeon E7") \ __PMC_CPU(INTEL_HASWELL_XEON, 0x95, "Intel Haswell Xeon E5 v3") \ __PMC_CPU(INTEL_BROADWELL, 0x96, "Intel Broadwell") \ __PMC_CPU(INTEL_BROADWELL_XEON, 0x97, "Intel Broadwell Xeon") \ __PMC_CPU(INTEL_SKYLAKE, 0x98, "Intel Skylake") \ __PMC_CPU(INTEL_SKYLAKE_XEON, 0x99, "Intel Skylake Xeon") \ __PMC_CPU(INTEL_ATOM_GOLDMONT, 0x9A, "Intel Atom Goldmont") \ __PMC_CPU(INTEL_XSCALE, 0x100, "Intel XScale") \ __PMC_CPU(MIPS_24K, 0x200, "MIPS 24K") \ __PMC_CPU(MIPS_OCTEON, 0x201, "Cavium Octeon") \ __PMC_CPU(MIPS_74K, 0x202, "MIPS 74K") \ __PMC_CPU(MIPS_BERI, 0x203, "BERI") \ __PMC_CPU(PPC_7450, 0x300, "PowerPC MPC7450") \ __PMC_CPU(PPC_E500, 0x340, "PowerPC e500 Core") \ __PMC_CPU(PPC_970, 0x380, "IBM PowerPC 970") \ + __PMC_CPU(PPC_POWER8, 0x390, "IBM POWER8") \ __PMC_CPU(GENERIC, 0x400, "Generic") \ __PMC_CPU(ARMV7_CORTEX_A5, 0x500, "ARMv7 Cortex A5") \ __PMC_CPU(ARMV7_CORTEX_A7, 0x501, "ARMv7 Cortex A7") \ __PMC_CPU(ARMV7_CORTEX_A8, 0x502, "ARMv7 Cortex A8") \ __PMC_CPU(ARMV7_CORTEX_A9, 0x503, "ARMv7 Cortex A9") \ __PMC_CPU(ARMV7_CORTEX_A15, 0x504, "ARMv7 Cortex A15") \ __PMC_CPU(ARMV7_CORTEX_A17, 0x505, "ARMv7 Cortex A17") \ __PMC_CPU(ARMV8_CORTEX_A53, 0x600, "ARMv8 Cortex A53") \ __PMC_CPU(ARMV8_CORTEX_A57, 0x601, "ARMv8 Cortex A57") \ __PMC_CPU(ARMV8_CORTEX_A76, 0x602, "ARMv8 Cortex A76") enum pmc_cputype { #undef __PMC_CPU #define __PMC_CPU(S,V,D) PMC_CPU_##S = V, __PMC_CPUS() }; #define PMC_CPU_FIRST PMC_CPU_AMD_K7 #define PMC_CPU_LAST PMC_CPU_GENERIC /* * Classes of PMCs */ #define __PMC_CLASSES() \ __PMC_CLASS(TSC, 0x00, "CPU Timestamp counter") \ __PMC_CLASS(K7, 0x01, "AMD K7 performance counters") \ __PMC_CLASS(K8, 0x02, "AMD K8 performance counters") \ __PMC_CLASS(P5, 0x03, "Intel Pentium counters") \ __PMC_CLASS(P6, 0x04, "Intel Pentium Pro counters") \ __PMC_CLASS(P4, 0x05, "Intel Pentium-IV counters") \ __PMC_CLASS(IAF, 0x06, "Intel Core2/Atom, fixed function") \ __PMC_CLASS(IAP, 0x07, "Intel Core...Atom, programmable") \ __PMC_CLASS(UCF, 0x08, "Intel Uncore fixed function") \ __PMC_CLASS(UCP, 0x09, "Intel Uncore programmable") \ __PMC_CLASS(XSCALE, 0x0A, "Intel XScale counters") \ __PMC_CLASS(MIPS24K, 0x0B, "MIPS 24K") \ __PMC_CLASS(OCTEON, 0x0C, "Cavium Octeon") \ __PMC_CLASS(PPC7450, 0x0D, "Motorola MPC7450 class") \ __PMC_CLASS(PPC970, 0x0E, "IBM PowerPC 970 class") \ __PMC_CLASS(SOFT, 0x0F, "Software events") \ __PMC_CLASS(ARMV7, 0x10, "ARMv7") \ __PMC_CLASS(ARMV8, 0x11, "ARMv8") \ __PMC_CLASS(MIPS74K, 0x12, "MIPS 74K") \ __PMC_CLASS(E500, 0x13, "Freescale e500 class") \ - __PMC_CLASS(BERI, 0x14, "MIPS BERI") + __PMC_CLASS(BERI, 0x14, "MIPS BERI") \ + __PMC_CLASS(POWER8, 0x15, "IBM POWER8 class") enum pmc_class { #undef __PMC_CLASS #define __PMC_CLASS(S,V,D) PMC_CLASS_##S = V, __PMC_CLASSES() }; #define PMC_CLASS_FIRST PMC_CLASS_TSC -#define PMC_CLASS_LAST PMC_CLASS_E500 +#define PMC_CLASS_LAST PMC_CLASS_POWER8 /* * A PMC can be in the following states: * * Hardware states: * DISABLED -- administratively prohibited from being used. * FREE -- HW available for use * Software states: * ALLOCATED -- allocated * STOPPED -- allocated, but not counting events * RUNNING -- allocated, and in operation; 'pm_runcount' * holds the number of CPUs using this PMC at * a given instant * DELETED -- being destroyed */ #define __PMC_HWSTATES() \ __PMC_STATE(DISABLED) \ __PMC_STATE(FREE) #define __PMC_SWSTATES() \ __PMC_STATE(ALLOCATED) \ __PMC_STATE(STOPPED) \ __PMC_STATE(RUNNING) \ __PMC_STATE(DELETED) #define __PMC_STATES() \ __PMC_HWSTATES() \ __PMC_SWSTATES() enum pmc_state { #undef __PMC_STATE #define __PMC_STATE(S) PMC_STATE_##S, __PMC_STATES() __PMC_STATE(MAX) }; #define PMC_STATE_FIRST PMC_STATE_DISABLED #define PMC_STATE_LAST PMC_STATE_DELETED /* * An allocated PMC may used as a 'global' counter or as a * 'thread-private' one. Each such mode of use can be in either * statistical sampling mode or in counting mode. Thus a PMC in use * * SS i.e., SYSTEM STATISTICAL -- system-wide statistical profiling * SC i.e., SYSTEM COUNTER -- system-wide counting mode * TS i.e., THREAD STATISTICAL -- thread virtual, statistical profiling * TC i.e., THREAD COUNTER -- thread virtual, counting mode * * Statistical profiling modes rely on the PMC periodically delivering * a interrupt to the CPU (when the configured number of events have * been measured), so the PMC must have the ability to generate * interrupts. * * In counting modes, the PMC counts its configured events, with the * value of the PMC being read whenever needed by its owner process. * * The thread specific modes "virtualize" the PMCs -- the PMCs appear * to be thread private and count events only when the profiled thread * actually executes on the CPU. * * The system-wide "global" modes keep the PMCs running all the time * and are used to measure the behaviour of the whole system. */ #define __PMC_MODES() \ __PMC_MODE(SS, 0) \ __PMC_MODE(SC, 1) \ __PMC_MODE(TS, 2) \ __PMC_MODE(TC, 3) enum pmc_mode { #undef __PMC_MODE #define __PMC_MODE(M,N) PMC_MODE_##M = N, __PMC_MODES() }; #define PMC_MODE_FIRST PMC_MODE_SS #define PMC_MODE_LAST PMC_MODE_TC #define PMC_IS_COUNTING_MODE(mode) \ ((mode) == PMC_MODE_SC || (mode) == PMC_MODE_TC) #define PMC_IS_SYSTEM_MODE(mode) \ ((mode) == PMC_MODE_SS || (mode) == PMC_MODE_SC) #define PMC_IS_SAMPLING_MODE(mode) \ ((mode) == PMC_MODE_SS || (mode) == PMC_MODE_TS) #define PMC_IS_VIRTUAL_MODE(mode) \ ((mode) == PMC_MODE_TS || (mode) == PMC_MODE_TC) /* * PMC row disposition */ #define __PMC_DISPOSITIONS(N) \ __PMC_DISP(STANDALONE) /* global/disabled counters */ \ __PMC_DISP(FREE) /* free/available */ \ __PMC_DISP(THREAD) /* thread-virtual PMCs */ \ __PMC_DISP(UNKNOWN) /* sentinel */ enum pmc_disp { #undef __PMC_DISP #define __PMC_DISP(D) PMC_DISP_##D , __PMC_DISPOSITIONS() }; #define PMC_DISP_FIRST PMC_DISP_STANDALONE #define PMC_DISP_LAST PMC_DISP_THREAD /* * Counter capabilities * * __PMC_CAPS(NAME, VALUE, DESCRIPTION) */ #define __PMC_CAPS() \ __PMC_CAP(INTERRUPT, 0, "generate interrupts") \ __PMC_CAP(USER, 1, "count user-mode events") \ __PMC_CAP(SYSTEM, 2, "count system-mode events") \ __PMC_CAP(EDGE, 3, "do edge detection of events") \ __PMC_CAP(THRESHOLD, 4, "ignore events below a threshold") \ __PMC_CAP(READ, 5, "read PMC counter") \ __PMC_CAP(WRITE, 6, "reprogram PMC counter") \ __PMC_CAP(INVERT, 7, "invert comparison sense") \ __PMC_CAP(QUALIFIER, 8, "further qualify monitored events") \ __PMC_CAP(PRECISE, 9, "perform precise sampling") \ __PMC_CAP(TAGGING, 10, "tag upstream events") \ __PMC_CAP(CASCADE, 11, "cascade counters") enum pmc_caps { #undef __PMC_CAP #define __PMC_CAP(NAME, VALUE, DESCR) PMC_CAP_##NAME = (1 << VALUE) , __PMC_CAPS() }; #define PMC_CAP_FIRST PMC_CAP_INTERRUPT #define PMC_CAP_LAST PMC_CAP_CASCADE /* * PMC Event Numbers * * These are generated from the definitions in "dev/hwpmc/pmc_events.h". */ enum pmc_event { #undef __PMC_EV #undef __PMC_EV_BLOCK #define __PMC_EV_BLOCK(C,V) PMC_EV_ ## C ## __BLOCK_START = (V) - 1 , #define __PMC_EV(C,N) PMC_EV_ ## C ## _ ## N , __PMC_EVENTS() }; /* * PMC SYSCALL INTERFACE */ /* * "PMC_OPS" -- these are the commands recognized by the kernel * module, and are used when performing a system call from userland. */ #define __PMC_OPS() \ __PMC_OP(CONFIGURELOG, "Set log file") \ __PMC_OP(FLUSHLOG, "Flush log file") \ __PMC_OP(GETCPUINFO, "Get system CPU information") \ __PMC_OP(GETDRIVERSTATS, "Get driver statistics") \ __PMC_OP(GETMODULEVERSION, "Get module version") \ __PMC_OP(GETPMCINFO, "Get per-cpu PMC information") \ __PMC_OP(PMCADMIN, "Set PMC state") \ __PMC_OP(PMCALLOCATE, "Allocate and configure a PMC") \ __PMC_OP(PMCATTACH, "Attach a PMC to a process") \ __PMC_OP(PMCDETACH, "Detach a PMC from a process") \ __PMC_OP(PMCGETMSR, "Get a PMC's hardware address") \ __PMC_OP(PMCRELEASE, "Release a PMC") \ __PMC_OP(PMCRW, "Read/Set a PMC") \ __PMC_OP(PMCSETCOUNT, "Set initial count/sampling rate") \ __PMC_OP(PMCSTART, "Start a PMC") \ __PMC_OP(PMCSTOP, "Stop a PMC") \ __PMC_OP(WRITELOG, "Write a cookie to the log file") \ __PMC_OP(CLOSELOG, "Close log file") \ __PMC_OP(GETDYNEVENTINFO, "Get dynamic events list") enum pmc_ops { #undef __PMC_OP #define __PMC_OP(N, D) PMC_OP_##N, __PMC_OPS() }; /* * Flags used in operations on PMCs. */ #define PMC_F_UNUSED1 0x00000001 /* unused */ #define PMC_F_DESCENDANTS 0x00000002 /*OP ALLOCATE track descendants */ #define PMC_F_LOG_PROCCSW 0x00000004 /*OP ALLOCATE track ctx switches */ #define PMC_F_LOG_PROCEXIT 0x00000008 /*OP ALLOCATE log proc exits */ #define PMC_F_NEWVALUE 0x00000010 /*OP RW write new value */ #define PMC_F_OLDVALUE 0x00000020 /*OP RW get old value */ /* V2 API */ #define PMC_F_CALLCHAIN 0x00000080 /*OP ALLOCATE capture callchains */ #define PMC_F_USERCALLCHAIN 0x00000100 /*OP ALLOCATE use userspace stack */ /* internal flags */ #define PMC_F_ATTACHED_TO_OWNER 0x00010000 /*attached to owner*/ #define PMC_F_NEEDS_LOGFILE 0x00020000 /*needs log file */ #define PMC_F_ATTACH_DONE 0x00040000 /*attached at least once */ #define PMC_CALLCHAIN_DEPTH_MAX 512 #define PMC_CC_F_USERSPACE 0x01 /*userspace callchain*/ /* * Cookies used to denote allocated PMCs, and the values of PMCs. */ typedef uint32_t pmc_id_t; typedef uint64_t pmc_value_t; #define PMC_ID_INVALID (~ (pmc_id_t) 0) /* * PMC IDs have the following format: * * +-----------------------+-------+-----------+ * | CPU | PMC MODE | CLASS | ROW INDEX | * +-----------------------+-------+-----------+ * * where CPU is 12 bits, MODE 8, CLASS 4, and ROW INDEX 8 Field 'CPU' * is set to the requested CPU for system-wide PMCs or PMC_CPU_ANY for * process-mode PMCs. Field 'PMC MODE' is the allocated PMC mode. * Field 'PMC CLASS' is the class of the PMC. Field 'ROW INDEX' is the * row index for the PMC. * * The 'ROW INDEX' ranges over 0..NWPMCS where NHWPMCS is the total * number of hardware PMCs on this cpu. */ #define PMC_ID_TO_ROWINDEX(ID) ((ID) & 0xFF) #define PMC_ID_TO_CLASS(ID) (((ID) & 0xF00) >> 8) #define PMC_ID_TO_MODE(ID) (((ID) & 0xFF000) >> 12) #define PMC_ID_TO_CPU(ID) (((ID) & 0xFFF00000) >> 20) #define PMC_ID_MAKE_ID(CPU,MODE,CLASS,ROWINDEX) \ ((((CPU) & 0xFFF) << 20) | (((MODE) & 0xFF) << 12) | \ (((CLASS) & 0xF) << 8) | ((ROWINDEX) & 0xFF)) /* * Data structures for system calls supported by the pmc driver. */ /* * OP PMCALLOCATE * * Allocate a PMC on the named CPU. */ #define PMC_CPU_ANY ~0 struct pmc_op_pmcallocate { uint32_t pm_caps; /* PMC_CAP_* */ uint32_t pm_cpu; /* CPU number or PMC_CPU_ANY */ enum pmc_class pm_class; /* class of PMC desired */ enum pmc_event pm_ev; /* [enum pmc_event] desired */ uint32_t pm_flags; /* additional modifiers PMC_F_* */ enum pmc_mode pm_mode; /* desired mode */ pmc_id_t pm_pmcid; /* [return] process pmc id */ pmc_value_t pm_count; /* initial/sample count */ union pmc_md_op_pmcallocate pm_md; /* MD layer extensions */ }; /* * OP PMCADMIN * * Set the administrative state (i.e., whether enabled or disabled) of * a PMC 'pm_pmc' on CPU 'pm_cpu'. Note that 'pm_pmc' specifies an * absolute PMC number and need not have been first allocated by the * calling process. */ struct pmc_op_pmcadmin { int pm_cpu; /* CPU# */ uint32_t pm_flags; /* flags */ int pm_pmc; /* PMC# */ enum pmc_state pm_state; /* desired state */ }; /* * OP PMCATTACH / OP PMCDETACH * * Attach/detach a PMC and a process. */ struct pmc_op_pmcattach { pmc_id_t pm_pmc; /* PMC to attach to */ pid_t pm_pid; /* target process */ }; /* * OP PMCSETCOUNT * * Set the sampling rate (i.e., the reload count) for statistical counters. * 'pm_pmcid' need to have been previously allocated using PMCALLOCATE. */ struct pmc_op_pmcsetcount { pmc_value_t pm_count; /* initial/sample count */ pmc_id_t pm_pmcid; /* PMC id to set */ }; /* * OP PMCRW * * Read the value of a PMC named by 'pm_pmcid'. 'pm_pmcid' needs * to have been previously allocated using PMCALLOCATE. */ struct pmc_op_pmcrw { uint32_t pm_flags; /* PMC_F_{OLD,NEW}VALUE*/ pmc_id_t pm_pmcid; /* pmc id */ pmc_value_t pm_value; /* new&returned value */ }; /* * OP GETPMCINFO * * retrieve PMC state for a named CPU. The caller is expected to * allocate 'npmc' * 'struct pmc_info' bytes of space for the return * values. */ struct pmc_info { char pm_name[PMC_NAME_MAX]; /* pmc name */ enum pmc_class pm_class; /* enum pmc_class */ int pm_enabled; /* whether enabled */ enum pmc_disp pm_rowdisp; /* FREE, THREAD or STANDLONE */ pid_t pm_ownerpid; /* owner, or -1 */ enum pmc_mode pm_mode; /* current mode [enum pmc_mode] */ enum pmc_event pm_event; /* current event */ uint32_t pm_flags; /* current flags */ pmc_value_t pm_reloadcount; /* sampling counters only */ }; struct pmc_op_getpmcinfo { int32_t pm_cpu; /* 0 <= cpu < mp_maxid */ struct pmc_info pm_pmcs[]; /* space for 'npmc' structures */ }; /* * OP GETCPUINFO * * Retrieve system CPU information. */ struct pmc_classinfo { enum pmc_class pm_class; /* class id */ uint32_t pm_caps; /* counter capabilities */ uint32_t pm_width; /* width of the PMC */ uint32_t pm_num; /* number of PMCs in class */ }; struct pmc_op_getcpuinfo { enum pmc_cputype pm_cputype; /* what kind of CPU */ uint32_t pm_ncpu; /* max CPU number */ uint32_t pm_npmc; /* #PMCs per CPU */ uint32_t pm_nclass; /* #classes of PMCs */ struct pmc_classinfo pm_classes[PMC_CLASS_MAX]; }; /* * OP CONFIGURELOG * * Configure a log file for writing system-wide statistics to. */ struct pmc_op_configurelog { int pm_flags; int pm_logfd; /* logfile fd (or -1) */ }; /* * OP GETDRIVERSTATS * * Retrieve pmc(4) driver-wide statistics. */ #ifdef _KERNEL struct pmc_driverstats { counter_u64_t pm_intr_ignored; /* #interrupts ignored */ counter_u64_t pm_intr_processed; /* #interrupts processed */ counter_u64_t pm_intr_bufferfull; /* #interrupts with ENOSPC */ counter_u64_t pm_syscalls; /* #syscalls */ counter_u64_t pm_syscall_errors; /* #syscalls with errors */ counter_u64_t pm_buffer_requests; /* #buffer requests */ counter_u64_t pm_buffer_requests_failed; /* #failed buffer requests */ counter_u64_t pm_log_sweeps; /* #sample buffer processing passes */ counter_u64_t pm_merges; /* merged k+u */ counter_u64_t pm_overwrites; /* UR overwrites */ }; #endif struct pmc_op_getdriverstats { unsigned int pm_intr_ignored; /* #interrupts ignored */ unsigned int pm_intr_processed; /* #interrupts processed */ unsigned int pm_intr_bufferfull; /* #interrupts with ENOSPC */ unsigned int pm_syscalls; /* #syscalls */ unsigned int pm_syscall_errors; /* #syscalls with errors */ unsigned int pm_buffer_requests; /* #buffer requests */ unsigned int pm_buffer_requests_failed; /* #failed buffer requests */ unsigned int pm_log_sweeps; /* #sample buffer processing passes */ }; /* * OP RELEASE / OP START / OP STOP * * Simple operations on a PMC id. */ struct pmc_op_simple { pmc_id_t pm_pmcid; }; /* * OP WRITELOG * * Flush the current log buffer and write 4 bytes of user data to it. */ struct pmc_op_writelog { uint32_t pm_userdata; }; /* * OP GETMSR * * Retrieve the machine specific address associated with the allocated * PMC. This number can be used subsequently with a read-performance-counter * instruction. */ struct pmc_op_getmsr { uint32_t pm_msr; /* machine specific address */ pmc_id_t pm_pmcid; /* allocated pmc id */ }; /* * OP GETDYNEVENTINFO * * Retrieve a PMC dynamic class events list. */ struct pmc_dyn_event_descr { char pm_ev_name[PMC_NAME_MAX]; enum pmc_event pm_ev_code; }; struct pmc_op_getdyneventinfo { enum pmc_class pm_class; unsigned int pm_nevent; struct pmc_dyn_event_descr pm_events[PMC_EV_DYN_COUNT]; }; #ifdef _KERNEL #include #include #include #include #define PMC_HASH_SIZE 1024 #define PMC_MTXPOOL_SIZE 2048 #define PMC_LOG_BUFFER_SIZE 256 #define PMC_NLOGBUFFERS_PCPU 32 #define PMC_NSAMPLES 256 #define PMC_CALLCHAIN_DEPTH 128 #define PMC_THREADLIST_MAX 128 #define PMC_SYSCTL_NAME_PREFIX "kern." PMC_MODULE_NAME "." /* * Locking keys * * (b) - pmc_bufferlist_mtx (spin lock) * (k) - pmc_kthread_mtx (sleep lock) * (o) - po->po_mtx (spin lock) * (g) - global_epoch_preempt (epoch) * (p) - pmc_sx (sx) */ /* * PMC commands */ struct pmc_syscall_args { register_t pmop_code; /* one of PMC_OP_* */ void *pmop_data; /* syscall parameter */ }; /* * Interface to processor specific s1tuff */ /* * struct pmc_descr * * Machine independent (i.e., the common parts) of a human readable * PMC description. */ struct pmc_descr { char pd_name[PMC_NAME_MAX]; /* name */ uint32_t pd_caps; /* capabilities */ enum pmc_class pd_class; /* class of the PMC */ uint32_t pd_width; /* width in bits */ }; /* * struct pmc_target * * This structure records all the target processes associated with a * PMC. */ struct pmc_target { LIST_ENTRY(pmc_target) pt_next; struct pmc_process *pt_process; /* target descriptor */ }; /* * struct pmc * * Describes each allocated PMC. * * Each PMC has precisely one owner, namely the process that allocated * the PMC. * * A PMC may be attached to multiple target processes. The * 'pm_targets' field links all the target processes being monitored * by this PMC. * * The 'pm_savedvalue' field is protected by a mutex. * * On a multi-cpu machine, multiple target threads associated with a * process-virtual PMC could be concurrently executing on different * CPUs. The 'pm_runcount' field is atomically incremented every time * the PMC gets scheduled on a CPU and atomically decremented when it * get descheduled. Deletion of a PMC is only permitted when this * field is '0'. * */ struct pmc_pcpu_state { uint8_t pps_stalled; uint8_t pps_cpustate; } __aligned(CACHE_LINE_SIZE); struct pmc { LIST_HEAD(,pmc_target) pm_targets; /* list of target processes */ LIST_ENTRY(pmc) pm_next; /* owner's list */ /* * System-wide PMCs are allocated on a CPU and are not moved * around. For system-wide PMCs we record the CPU the PMC was * allocated on in the 'CPU' field of the pmc ID. * * Virtual PMCs run on whichever CPU is currently executing * their targets' threads. For these PMCs we need to save * their current PMC counter values when they are taken off * CPU. */ union { pmc_value_t pm_savedvalue; /* Virtual PMCS */ } pm_gv; /* * For sampling mode PMCs, we keep track of the PMC's "reload * count", which is the counter value to be loaded in when * arming the PMC for the next counting session. For counting * modes on PMCs that are read-only (e.g., the x86 TSC), we * keep track of the initial value at the start of * counting-mode operation. */ union { pmc_value_t pm_reloadcount; /* sampling PMC modes */ pmc_value_t pm_initial; /* counting PMC modes */ } pm_sc; struct pmc_pcpu_state *pm_pcpu_state; volatile cpuset_t pm_cpustate; /* CPUs where PMC should be active */ uint32_t pm_caps; /* PMC capabilities */ enum pmc_event pm_event; /* event being measured */ uint32_t pm_flags; /* additional flags PMC_F_... */ struct pmc_owner *pm_owner; /* owner thread state */ counter_u64_t pm_runcount; /* #cpus currently on */ enum pmc_state pm_state; /* current PMC state */ uint32_t pm_overflowcnt; /* count overflow interrupts */ /* * The PMC ID field encodes the row-index for the PMC, its * mode, class and the CPU# associated with the PMC. */ pmc_id_t pm_id; /* allocated PMC id */ enum pmc_class pm_class; /* md extensions */ union pmc_md_pmc pm_md; }; /* * Accessor macros for 'struct pmc' */ #define PMC_TO_MODE(P) PMC_ID_TO_MODE((P)->pm_id) #define PMC_TO_CLASS(P) PMC_ID_TO_CLASS((P)->pm_id) #define PMC_TO_ROWINDEX(P) PMC_ID_TO_ROWINDEX((P)->pm_id) #define PMC_TO_CPU(P) PMC_ID_TO_CPU((P)->pm_id) /* * struct pmc_threadpmcstate * * Record per-PMC, per-thread state. */ struct pmc_threadpmcstate { pmc_value_t pt_pmcval; /* per-thread reload count */ }; /* * struct pmc_thread * * Record a 'target' thread being profiled. */ struct pmc_thread { LIST_ENTRY(pmc_thread) pt_next; /* linked list */ struct thread *pt_td; /* target thread */ struct pmc_threadpmcstate pt_pmcs[]; /* per-PMC state */ }; /* * struct pmc_process * * Record a 'target' process being profiled. * * The target process being profiled could be different from the owner * process which allocated the PMCs. Each target process descriptor * is associated with NHWPMC 'struct pmc *' pointers. Each PMC at a * given hardware row-index 'n' will use slot 'n' of the 'pp_pmcs[]' * array. The size of this structure is thus PMC architecture * dependent. * */ struct pmc_targetstate { struct pmc *pp_pmc; /* target PMC */ pmc_value_t pp_pmcval; /* per-process value */ }; struct pmc_process { LIST_ENTRY(pmc_process) pp_next; /* hash chain */ LIST_HEAD(,pmc_thread) pp_tds; /* list of threads */ struct mtx *pp_tdslock; /* lock on pp_tds thread list */ int pp_refcnt; /* reference count */ uint32_t pp_flags; /* flags PMC_PP_* */ struct proc *pp_proc; /* target process */ struct pmc_targetstate pp_pmcs[]; /* NHWPMCs */ }; #define PMC_PP_ENABLE_MSR_ACCESS 0x00000001 /* * struct pmc_owner * * We associate a PMC with an 'owner' process. * * A process can be associated with 0..NCPUS*NHWPMC PMCs during its * lifetime, where NCPUS is the numbers of CPUS in the system and * NHWPMC is the number of hardware PMCs per CPU. These are * maintained in the list headed by the 'po_pmcs' to save on space. * */ struct pmc_owner { LIST_ENTRY(pmc_owner) po_next; /* hash chain */ CK_LIST_ENTRY(pmc_owner) po_ssnext; /* (g/p) list of SS PMC owners */ LIST_HEAD(, pmc) po_pmcs; /* owned PMC list */ TAILQ_HEAD(, pmclog_buffer) po_logbuffers; /* (o) logbuffer list */ struct mtx po_mtx; /* spin lock for (o) */ struct proc *po_owner; /* owner proc */ uint32_t po_flags; /* (k) flags PMC_PO_* */ struct proc *po_kthread; /* (k) helper kthread */ struct file *po_file; /* file reference */ int po_error; /* recorded error */ short po_sscount; /* # SS PMCs owned */ short po_logprocmaps; /* global mappings done */ struct pmclog_buffer *po_curbuf[MAXCPU]; /* current log buffer */ }; #define PMC_PO_OWNS_LOGFILE 0x00000001 /* has a log file */ #define PMC_PO_SHUTDOWN 0x00000010 /* in the process of shutdown */ #define PMC_PO_INITIAL_MAPPINGS_DONE 0x00000020 /* * struct pmc_hw -- describe the state of the PMC hardware * * When in use, a HW PMC is associated with one allocated 'struct pmc' * pointed to by field 'phw_pmc'. When inactive, this field is NULL. * * On an SMP box, one or more HW PMC's in process virtual mode with * the same 'phw_pmc' could be executing on different CPUs. In order * to handle this case correctly, we need to ensure that only * incremental counts get added to the saved value in the associated * 'struct pmc'. The 'phw_save' field is used to keep the saved PMC * value at the time the hardware is started during this context * switch (i.e., the difference between the new (hardware) count and * the saved count is atomically added to the count field in 'struct * pmc' at context switch time). * */ struct pmc_hw { uint32_t phw_state; /* see PHW_* macros below */ struct pmc *phw_pmc; /* current thread PMC */ }; #define PMC_PHW_RI_MASK 0x000000FF #define PMC_PHW_CPU_SHIFT 8 #define PMC_PHW_CPU_MASK 0x0000FF00 #define PMC_PHW_FLAGS_SHIFT 16 #define PMC_PHW_FLAGS_MASK 0xFFFF0000 #define PMC_PHW_INDEX_TO_STATE(ri) ((ri) & PMC_PHW_RI_MASK) #define PMC_PHW_STATE_TO_INDEX(state) ((state) & PMC_PHW_RI_MASK) #define PMC_PHW_CPU_TO_STATE(cpu) (((cpu) << PMC_PHW_CPU_SHIFT) & \ PMC_PHW_CPU_MASK) #define PMC_PHW_STATE_TO_CPU(state) (((state) & PMC_PHW_CPU_MASK) >> \ PMC_PHW_CPU_SHIFT) #define PMC_PHW_FLAGS_TO_STATE(flags) (((flags) << PMC_PHW_FLAGS_SHIFT) & \ PMC_PHW_FLAGS_MASK) #define PMC_PHW_STATE_TO_FLAGS(state) (((state) & PMC_PHW_FLAGS_MASK) >> \ PMC_PHW_FLAGS_SHIFT) #define PMC_PHW_FLAG_IS_ENABLED (PMC_PHW_FLAGS_TO_STATE(0x01)) #define PMC_PHW_FLAG_IS_SHAREABLE (PMC_PHW_FLAGS_TO_STATE(0x02)) /* * struct pmc_sample * * Space for N (tunable) PC samples and associated control data. */ struct pmc_sample { uint16_t ps_nsamples; /* callchain depth */ uint16_t ps_nsamples_actual; uint16_t ps_cpu; /* cpu number */ uint16_t ps_flags; /* other flags */ lwpid_t ps_tid; /* thread id */ pid_t ps_pid; /* process PID or -1 */ int ps_ticks; /* ticks at sample time */ /* pad */ struct thread *ps_td; /* which thread */ struct pmc *ps_pmc; /* interrupting PMC */ uintptr_t *ps_pc; /* (const) callchain start */ uint64_t ps_tsc; /* tsc value */ }; #define PMC_SAMPLE_FREE ((uint16_t) 0) #define PMC_USER_CALLCHAIN_PENDING ((uint16_t) 0xFFFF) struct pmc_samplebuffer { volatile uint64_t ps_prodidx; /* producer index */ volatile uint64_t ps_considx; /* consumer index */ uintptr_t *ps_callchains; /* all saved call chains */ struct pmc_sample ps_samples[]; /* array of sample entries */ }; #define PMC_CONS_SAMPLE(psb) \ (&(psb)->ps_samples[(psb)->ps_considx & pmc_sample_mask]) #define PMC_CONS_SAMPLE_OFF(psb, off) \ (&(psb)->ps_samples[(off) & pmc_sample_mask]) #define PMC_PROD_SAMPLE(psb) \ (&(psb)->ps_samples[(psb)->ps_prodidx & pmc_sample_mask]) /* * struct pmc_cpustate * * A CPU is modelled as a collection of HW PMCs with space for additional * flags. */ struct pmc_cpu { uint32_t pc_state; /* physical cpu number + flags */ struct pmc_samplebuffer *pc_sb[3]; /* space for samples */ struct pmc_hw *pc_hwpmcs[]; /* 'npmc' pointers */ }; #define PMC_PCPU_CPU_MASK 0x000000FF #define PMC_PCPU_FLAGS_MASK 0xFFFFFF00 #define PMC_PCPU_FLAGS_SHIFT 8 #define PMC_PCPU_STATE_TO_CPU(S) ((S) & PMC_PCPU_CPU_MASK) #define PMC_PCPU_STATE_TO_FLAGS(S) (((S) & PMC_PCPU_FLAGS_MASK) >> PMC_PCPU_FLAGS_SHIFT) #define PMC_PCPU_FLAGS_TO_STATE(F) (((F) << PMC_PCPU_FLAGS_SHIFT) & PMC_PCPU_FLAGS_MASK) #define PMC_PCPU_CPU_TO_STATE(C) ((C) & PMC_PCPU_CPU_MASK) #define PMC_PCPU_FLAG_HTT (PMC_PCPU_FLAGS_TO_STATE(0x1)) /* * struct pmc_binding * * CPU binding information. */ struct pmc_binding { int pb_bound; /* is bound? */ int pb_cpu; /* if so, to which CPU */ }; struct pmc_mdep; /* * struct pmc_classdep * * PMC class-dependent operations. */ struct pmc_classdep { uint32_t pcd_caps; /* class capabilities */ enum pmc_class pcd_class; /* class id */ int pcd_num; /* number of PMCs */ int pcd_ri; /* row index of the first PMC in class */ int pcd_width; /* width of the PMC */ /* configuring/reading/writing the hardware PMCs */ int (*pcd_config_pmc)(int _cpu, int _ri, struct pmc *_pm); int (*pcd_get_config)(int _cpu, int _ri, struct pmc **_ppm); int (*pcd_read_pmc)(int _cpu, int _ri, pmc_value_t *_value); int (*pcd_write_pmc)(int _cpu, int _ri, pmc_value_t _value); /* pmc allocation/release */ int (*pcd_allocate_pmc)(int _cpu, int _ri, struct pmc *_t, const struct pmc_op_pmcallocate *_a); int (*pcd_release_pmc)(int _cpu, int _ri, struct pmc *_pm); /* starting and stopping PMCs */ int (*pcd_start_pmc)(int _cpu, int _ri); int (*pcd_stop_pmc)(int _cpu, int _ri); /* description */ int (*pcd_describe)(int _cpu, int _ri, struct pmc_info *_pi, struct pmc **_ppmc); /* class-dependent initialization & finalization */ int (*pcd_pcpu_init)(struct pmc_mdep *_md, int _cpu); int (*pcd_pcpu_fini)(struct pmc_mdep *_md, int _cpu); /* machine-specific interface */ int (*pcd_get_msr)(int _ri, uint32_t *_msr); }; /* * struct pmc_mdep * * Machine dependent bits needed per CPU type. */ struct pmc_mdep { uint32_t pmd_cputype; /* from enum pmc_cputype */ uint32_t pmd_npmc; /* number of PMCs per CPU */ uint32_t pmd_nclass; /* number of PMC classes present */ /* * Machine dependent methods. */ /* per-cpu initialization and finalization */ int (*pmd_pcpu_init)(struct pmc_mdep *_md, int _cpu); int (*pmd_pcpu_fini)(struct pmc_mdep *_md, int _cpu); /* thread context switch in/out */ int (*pmd_switch_in)(struct pmc_cpu *_p, struct pmc_process *_pp); int (*pmd_switch_out)(struct pmc_cpu *_p, struct pmc_process *_pp); /* handle a PMC interrupt */ int (*pmd_intr)(struct trapframe *_tf); /* * PMC class dependent information. */ struct pmc_classdep pmd_classdep[]; }; /* * Per-CPU state. This is an array of 'mp_ncpu' pointers * to struct pmc_cpu descriptors. */ extern struct pmc_cpu **pmc_pcpu; /* driver statistics */ extern struct pmc_driverstats pmc_stats; #if defined(HWPMC_DEBUG) #include /* debug flags, major flag groups */ struct pmc_debugflags { int pdb_CPU; int pdb_CSW; int pdb_LOG; int pdb_MDP; int pdb_MOD; int pdb_OWN; int pdb_PMC; int pdb_PRC; int pdb_SAM; }; extern struct pmc_debugflags pmc_debugflags; #define KTR_PMC KTR_SUBSYS #define PMC_DEBUG_STRSIZE 128 #define PMC_DEBUG_DEFAULT_FLAGS { 0, 0, 0, 0, 0, 0, 0, 0, 0 } #define PMCDBG0(M, N, L, F) do { \ if (pmc_debugflags.pdb_ ## M & (1 << PMC_DEBUG_MIN_ ## N)) \ CTR0(KTR_PMC, #M ":" #N ":" #L ": " F); \ } while (0) #define PMCDBG1(M, N, L, F, p1) do { \ if (pmc_debugflags.pdb_ ## M & (1 << PMC_DEBUG_MIN_ ## N)) \ CTR1(KTR_PMC, #M ":" #N ":" #L ": " F, p1); \ } while (0) #define PMCDBG2(M, N, L, F, p1, p2) do { \ if (pmc_debugflags.pdb_ ## M & (1 << PMC_DEBUG_MIN_ ## N)) \ CTR2(KTR_PMC, #M ":" #N ":" #L ": " F, p1, p2); \ } while (0) #define PMCDBG3(M, N, L, F, p1, p2, p3) do { \ if (pmc_debugflags.pdb_ ## M & (1 << PMC_DEBUG_MIN_ ## N)) \ CTR3(KTR_PMC, #M ":" #N ":" #L ": " F, p1, p2, p3); \ } while (0) #define PMCDBG4(M, N, L, F, p1, p2, p3, p4) do { \ if (pmc_debugflags.pdb_ ## M & (1 << PMC_DEBUG_MIN_ ## N)) \ CTR4(KTR_PMC, #M ":" #N ":" #L ": " F, p1, p2, p3, p4);\ } while (0) #define PMCDBG5(M, N, L, F, p1, p2, p3, p4, p5) do { \ if (pmc_debugflags.pdb_ ## M & (1 << PMC_DEBUG_MIN_ ## N)) \ CTR5(KTR_PMC, #M ":" #N ":" #L ": " F, p1, p2, p3, p4, \ p5); \ } while (0) #define PMCDBG6(M, N, L, F, p1, p2, p3, p4, p5, p6) do { \ if (pmc_debugflags.pdb_ ## M & (1 << PMC_DEBUG_MIN_ ## N)) \ CTR6(KTR_PMC, #M ":" #N ":" #L ": " F, p1, p2, p3, p4, \ p5, p6); \ } while (0) /* Major numbers */ #define PMC_DEBUG_MAJ_CPU 0 /* cpu switches */ #define PMC_DEBUG_MAJ_CSW 1 /* context switches */ #define PMC_DEBUG_MAJ_LOG 2 /* logging */ #define PMC_DEBUG_MAJ_MDP 3 /* machine dependent */ #define PMC_DEBUG_MAJ_MOD 4 /* misc module infrastructure */ #define PMC_DEBUG_MAJ_OWN 5 /* owner */ #define PMC_DEBUG_MAJ_PMC 6 /* pmc management */ #define PMC_DEBUG_MAJ_PRC 7 /* processes */ #define PMC_DEBUG_MAJ_SAM 8 /* sampling */ /* Minor numbers */ /* Common (8 bits) */ #define PMC_DEBUG_MIN_ALL 0 /* allocation */ #define PMC_DEBUG_MIN_REL 1 /* release */ #define PMC_DEBUG_MIN_OPS 2 /* ops: start, stop, ... */ #define PMC_DEBUG_MIN_INI 3 /* init */ #define PMC_DEBUG_MIN_FND 4 /* find */ /* MODULE */ #define PMC_DEBUG_MIN_PMH 14 /* pmc_hook */ #define PMC_DEBUG_MIN_PMS 15 /* pmc_syscall */ /* OWN */ #define PMC_DEBUG_MIN_ORM 8 /* owner remove */ #define PMC_DEBUG_MIN_OMR 9 /* owner maybe remove */ /* PROCESSES */ #define PMC_DEBUG_MIN_TLK 8 /* link target */ #define PMC_DEBUG_MIN_TUL 9 /* unlink target */ #define PMC_DEBUG_MIN_EXT 10 /* process exit */ #define PMC_DEBUG_MIN_EXC 11 /* process exec */ #define PMC_DEBUG_MIN_FRK 12 /* process fork */ #define PMC_DEBUG_MIN_ATT 13 /* attach/detach */ #define PMC_DEBUG_MIN_SIG 14 /* signalling */ /* CONTEXT SWITCHES */ #define PMC_DEBUG_MIN_SWI 8 /* switch in */ #define PMC_DEBUG_MIN_SWO 9 /* switch out */ /* PMC */ #define PMC_DEBUG_MIN_REG 8 /* pmc register */ #define PMC_DEBUG_MIN_ALR 9 /* allocate row */ /* MACHINE DEPENDENT LAYER */ #define PMC_DEBUG_MIN_REA 8 /* read */ #define PMC_DEBUG_MIN_WRI 9 /* write */ #define PMC_DEBUG_MIN_CFG 10 /* config */ #define PMC_DEBUG_MIN_STA 11 /* start */ #define PMC_DEBUG_MIN_STO 12 /* stop */ #define PMC_DEBUG_MIN_INT 13 /* interrupts */ /* CPU */ #define PMC_DEBUG_MIN_BND 8 /* bind */ #define PMC_DEBUG_MIN_SEL 9 /* select */ /* LOG */ #define PMC_DEBUG_MIN_GTB 8 /* get buf */ #define PMC_DEBUG_MIN_SIO 9 /* schedule i/o */ #define PMC_DEBUG_MIN_FLS 10 /* flush */ #define PMC_DEBUG_MIN_SAM 11 /* sample */ #define PMC_DEBUG_MIN_CLO 12 /* close */ #else #define PMCDBG0(M, N, L, F) /* nothing */ #define PMCDBG1(M, N, L, F, p1) #define PMCDBG2(M, N, L, F, p1, p2) #define PMCDBG3(M, N, L, F, p1, p2, p3) #define PMCDBG4(M, N, L, F, p1, p2, p3, p4) #define PMCDBG5(M, N, L, F, p1, p2, p3, p4, p5) #define PMCDBG6(M, N, L, F, p1, p2, p3, p4, p5, p6) #endif /* declare a dedicated memory pool */ MALLOC_DECLARE(M_PMC); /* * Functions */ struct pmc_mdep *pmc_md_initialize(void); /* MD init function */ void pmc_md_finalize(struct pmc_mdep *_md); /* MD fini function */ int pmc_getrowdisp(int _ri); int pmc_process_interrupt(int _ring, struct pmc *_pm, struct trapframe *_tf); int pmc_save_kernel_callchain(uintptr_t *_cc, int _maxsamples, struct trapframe *_tf); int pmc_save_user_callchain(uintptr_t *_cc, int _maxsamples, struct trapframe *_tf); struct pmc_mdep *pmc_mdep_alloc(int nclasses); void pmc_mdep_free(struct pmc_mdep *md); uint64_t pmc_rdtsc(void); #endif /* _KERNEL */ #endif /* _SYS_PMC_H_ */