hwpmc_mips74k.c revision 298431
1/*- 2 * Copyright (c) 2010 George V. Neville-Neil <gnn@freebsd.org> 3 * Copyright (c) 2015 Adrian Chadd <adrian@freebsd.org> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 */ 28 29#include <sys/cdefs.h> 30__FBSDID("$FreeBSD: head/sys/dev/hwpmc/hwpmc_mips74k.c 298431 2016-04-21 19:40:10Z pfg $"); 31 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/pmc.h> 35#include <sys/pmckern.h> 36 37#include <machine/cpu.h> 38#include <machine/cpufunc.h> 39#include <machine/pmc_mdep.h> 40 41#define MIPS74K_PMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_USER | \ 42 PMC_CAP_SYSTEM | PMC_CAP_EDGE | \ 43 PMC_CAP_THRESHOLD | PMC_CAP_READ | \ 44 PMC_CAP_WRITE | PMC_CAP_INVERT | \ 45 PMC_CAP_QUALIFIER) 46 47/* 0x1 - Exception_enable */ 48#define MIPS74K_PMC_INTERRUPT_ENABLE 0x10 /* Enable interrupts */ 49#define MIPS74K_PMC_USER_ENABLE 0x08 /* Count in USER mode */ 50#define MIPS74K_PMC_SUPER_ENABLE 0x04 /* Count in SUPERVISOR mode */ 51#define MIPS74K_PMC_KERNEL_ENABLE 0x02 /* Count in KERNEL mode */ 52#define MIPS74K_PMC_ENABLE (MIPS74K_PMC_USER_ENABLE | \ 53 MIPS74K_PMC_SUPER_ENABLE | \ 54 MIPS74K_PMC_KERNEL_ENABLE) 55 56#define MIPS74K_PMC_SELECT 5 /* Which bit position the event starts at. */ 57 58const struct mips_event_code_map mips_event_codes[] = { 59 { PMC_EV_MIPS74K_CYCLES, MIPS_CTR_ALL, 0 }, 60 { PMC_EV_MIPS74K_INSTR_EXECUTED, MIPS_CTR_ALL, 1 }, 61 { PMC_EV_MIPS74K_PREDICTED_JR_31, MIPS_CTR_0, 2 }, 62 { PMC_EV_MIPS74K_JR_31_MISPREDICTIONS, MIPS_CTR_1, 2 }, 63 { PMC_EV_MIPS74K_REDIRECT_STALLS, MIPS_CTR_0, 3 }, 64 { PMC_EV_MIPS74K_JR_31_NO_PREDICTIONS, MIPS_CTR_1, 3 }, 65 { PMC_EV_MIPS74K_ITLB_ACCESSES, MIPS_CTR_0, 4 }, 66 { PMC_EV_MIPS74K_ITLB_MISSES, MIPS_CTR_1, 4 }, 67 { PMC_EV_MIPS74K_JTLB_INSN_MISSES, MIPS_CTR_1, 5 }, 68 { PMC_EV_MIPS74K_ICACHE_ACCESSES, MIPS_CTR_0, 6 }, 69 { PMC_EV_MIPS74K_ICACHE_MISSES, MIPS_CTR_1, 6 }, 70 { PMC_EV_MIPS74K_ICACHE_MISS_STALLS, MIPS_CTR_0, 7 }, 71 { PMC_EV_MIPS74K_UNCACHED_IFETCH_STALLS, MIPS_CTR_0, 8 }, 72 { PMC_EV_MIPS74K_PDTRACE_BACK_STALLS, MIPS_CTR_1, 8 }, 73 { PMC_EV_MIPS74K_IFU_REPLAYS, MIPS_CTR_0, 9 }, 74 { PMC_EV_MIPS74K_KILLED_FETCH_SLOTS, MIPS_CTR_1, 9 }, 75 { PMC_EV_MIPS74K_IFU_IDU_MISS_PRED_UPSTREAM_CYCLES, MIPS_CTR_0, 11 }, 76 { PMC_EV_MIPS74K_IFU_IDU_NO_FETCH_CYCLES, MIPS_CTR_1, 11 }, 77 { PMC_EV_MIPS74K_IFU_IDU_CLOGED_DOWNSTREAM_CYCLES, MIPS_CTR_0, 12 }, 78 { PMC_EV_MIPS74K_DDQ0_FULL_DR_STALLS, MIPS_CTR_0, 13 }, 79 { PMC_EV_MIPS74K_DDQ1_FULL_DR_STALLS, MIPS_CTR_1, 13 }, 80 { PMC_EV_MIPS74K_ALCB_FULL_DR_STALLS, MIPS_CTR_0, 14 }, 81 { PMC_EV_MIPS74K_AGCB_FULL_DR_STALLS, MIPS_CTR_1, 14 }, 82 { PMC_EV_MIPS74K_CLDQ_FULL_DR_STALLS, MIPS_CTR_0, 15 }, 83 { PMC_EV_MIPS74K_IODQ_FULL_DR_STALLS, MIPS_CTR_1, 15 }, 84 { PMC_EV_MIPS74K_ALU_EMPTY_CYCLES, MIPS_CTR_0, 16 }, 85 { PMC_EV_MIPS74K_AGEN_EMPTY_CYCLES, MIPS_CTR_1, 16 }, 86 { PMC_EV_MIPS74K_ALU_OPERANDS_NOT_READY_CYCLES, MIPS_CTR_0, 17 }, 87 { PMC_EV_MIPS74K_AGEN_OPERANDS_NOT_READY_CYCLES, MIPS_CTR_1, 17 }, 88 { PMC_EV_MIPS74K_ALU_NO_ISSUES_CYCLES, MIPS_CTR_0, 18 }, 89 { PMC_EV_MIPS74K_AGEN_NO_ISSUES_CYCLES, MIPS_CTR_1, 18 }, 90 { PMC_EV_MIPS74K_ALU_BUBBLE_CYCLES, MIPS_CTR_0, 19 }, 91 { PMC_EV_MIPS74K_AGEN_BUBBLE_CYCLES, MIPS_CTR_1, 19 }, 92 { PMC_EV_MIPS74K_SINGLE_ISSUE_CYCLES, MIPS_CTR_0, 20 }, 93 { PMC_EV_MIPS74K_DUAL_ISSUE_CYCLES, MIPS_CTR_1, 20 }, 94 { PMC_EV_MIPS74K_OOO_ALU_ISSUE_CYCLES, MIPS_CTR_0, 21 }, 95 { PMC_EV_MIPS74K_OOO_AGEN_ISSUE_CYCLES, MIPS_CTR_1, 21 }, 96 { PMC_EV_MIPS74K_JALR_JALR_HB_INSNS, MIPS_CTR_0, 22 }, 97 { PMC_EV_MIPS74K_DCACHE_LINE_REFILL_REQUESTS, MIPS_CTR_1, 22 }, 98 { PMC_EV_MIPS74K_DCACHE_LOAD_ACCESSES, MIPS_CTR_0, 23 }, 99 { PMC_EV_MIPS74K_DCACHE_ACCESSES, MIPS_CTR_1, 23 }, 100 { PMC_EV_MIPS74K_DCACHE_WRITEBACKS, MIPS_CTR_0, 24 }, 101 { PMC_EV_MIPS74K_DCACHE_MISSES, MIPS_CTR_1, 24 }, 102 { PMC_EV_MIPS74K_JTLB_DATA_ACCESSES, MIPS_CTR_0, 25 }, 103 { PMC_EV_MIPS74K_JTLB_DATA_MISSES, MIPS_CTR_1, 25 }, 104 { PMC_EV_MIPS74K_LOAD_STORE_REPLAYS, MIPS_CTR_0, 26 }, 105 { PMC_EV_MIPS74K_VA_TRANSALTION_CORNER_CASES, MIPS_CTR_1, 26 }, 106 { PMC_EV_MIPS74K_LOAD_STORE_BLOCKED_CYCLES, MIPS_CTR_0, 27 }, 107 { PMC_EV_MIPS74K_LOAD_STORE_NO_FILL_REQUESTS, MIPS_CTR_1, 27 }, 108 { PMC_EV_MIPS74K_L2_CACHE_WRITEBACKS, MIPS_CTR_0, 28 }, 109 { PMC_EV_MIPS74K_L2_CACHE_ACCESSES, MIPS_CTR_1, 28 }, 110 { PMC_EV_MIPS74K_L2_CACHE_MISSES, MIPS_CTR_0, 29 }, 111 { PMC_EV_MIPS74K_L2_CACHE_MISS_CYCLES, MIPS_CTR_1, 29 }, 112 { PMC_EV_MIPS74K_FSB_FULL_STALLS, MIPS_CTR_0, 30 }, 113 { PMC_EV_MIPS74K_FSB_OVER_50_FULL, MIPS_CTR_1, 30 }, 114 { PMC_EV_MIPS74K_LDQ_FULL_STALLS, MIPS_CTR_0, 31 }, 115 { PMC_EV_MIPS74K_LDQ_OVER_50_FULL, MIPS_CTR_1, 31 }, 116 { PMC_EV_MIPS74K_WBB_FULL_STALLS, MIPS_CTR_0, 32 }, 117 { PMC_EV_MIPS74K_WBB_OVER_50_FULL, MIPS_CTR_1, 32 }, 118 { PMC_EV_MIPS74K_LOAD_MISS_CONSUMER_REPLAYS, MIPS_CTR_0, 35 }, 119 { PMC_EV_MIPS74K_CP1_CP2_LOAD_INSNS, MIPS_CTR_1, 35 }, 120 { PMC_EV_MIPS74K_JR_NON_31_INSNS, MIPS_CTR_0, 36 }, 121 { PMC_EV_MIPS74K_MISPREDICTED_JR_31_INSNS, MIPS_CTR_1, 36 }, 122 { PMC_EV_MIPS74K_BRANCH_INSNS, MIPS_CTR_0, 37 }, 123 { PMC_EV_MIPS74K_CP1_CP2_COND_BRANCH_INSNS, MIPS_CTR_1, 37 }, 124 { PMC_EV_MIPS74K_BRANCH_LIKELY_INSNS, MIPS_CTR_0, 38 }, 125 { PMC_EV_MIPS74K_MISPREDICTED_BRANCH_LIKELY_INSNS, MIPS_CTR_1, 38 }, 126 { PMC_EV_MIPS74K_COND_BRANCH_INSNS, MIPS_CTR_0, 39 }, 127 { PMC_EV_MIPS74K_MISPREDICTED_BRANCH_INSNS, MIPS_CTR_1, 39 }, 128 { PMC_EV_MIPS74K_INTEGER_INSNS, MIPS_CTR_0, 40 }, 129 { PMC_EV_MIPS74K_FPU_INSNS, MIPS_CTR_1, 40 }, 130 { PMC_EV_MIPS74K_LOAD_INSNS, MIPS_CTR_0, 41 }, 131 { PMC_EV_MIPS74K_STORE_INSNS, MIPS_CTR_1, 41 }, 132 { PMC_EV_MIPS74K_J_JAL_INSNS, MIPS_CTR_0, 42 }, 133 { PMC_EV_MIPS74K_MIPS16_INSNS, MIPS_CTR_1, 42 }, 134 { PMC_EV_MIPS74K_NOP_INSNS, MIPS_CTR_0, 43 }, 135 { PMC_EV_MIPS74K_NT_MUL_DIV_INSNS, MIPS_CTR_1, 43 }, 136 { PMC_EV_MIPS74K_DSP_INSNS, MIPS_CTR_0, 44 }, 137 { PMC_EV_MIPS74K_ALU_DSP_SATURATION_INSNS, MIPS_CTR_1, 44 }, 138 { PMC_EV_MIPS74K_DSP_BRANCH_INSNS, MIPS_CTR_0, 45 }, 139 { PMC_EV_MIPS74K_MDU_DSP_SATURATION_INSNS, MIPS_CTR_1, 45 }, 140 { PMC_EV_MIPS74K_UNCACHED_LOAD_INSNS, MIPS_CTR_0, 46 }, 141 { PMC_EV_MIPS74K_UNCACHED_STORE_INSNS, MIPS_CTR_1, 46 }, 142 { PMC_EV_MIPS74K_EJTAG_INSN_TRIGGERS, MIPS_CTR_0, 49 }, 143 { PMC_EV_MIPS74K_CP1_BRANCH_MISPREDICTIONS, MIPS_CTR_0, 50 }, 144 { PMC_EV_MIPS74K_SC_INSNS, MIPS_CTR_0, 51 }, 145 { PMC_EV_MIPS74K_FAILED_SC_INSNS, MIPS_CTR_1, 51 }, 146 { PMC_EV_MIPS74K_PREFETCH_INSNS, MIPS_CTR_0, 52 }, 147 { PMC_EV_MIPS74K_CACHE_HIT_PREFETCH_INSNS, MIPS_CTR_1, 52 }, 148 { PMC_EV_MIPS74K_NO_INSN_CYCLES, MIPS_CTR_0, 53 }, 149 { PMC_EV_MIPS74K_LOAD_MISS_INSNS, MIPS_CTR_1, 53 }, 150 { PMC_EV_MIPS74K_ONE_INSN_CYCLES, MIPS_CTR_0, 54 }, 151 { PMC_EV_MIPS74K_TWO_INSNS_CYCLES, MIPS_CTR_1, 54 }, 152 { PMC_EV_MIPS74K_GFIFO_BLOCKED_CYCLES, MIPS_CTR_0, 55 }, 153 { PMC_EV_MIPS74K_CP1_CP2_STORE_INSNS, MIPS_CTR_1, 55 }, 154 { PMC_EV_MIPS74K_MISPREDICTION_STALLS, MIPS_CTR_0, 56 }, 155 { PMC_EV_MIPS74K_MISPREDICTED_BRANCH_INSNS_CYCLES, MIPS_CTR_0, 57 }, 156 { PMC_EV_MIPS74K_EXCEPTIONS_TAKEN, MIPS_CTR_0, 58 }, 157 { PMC_EV_MIPS74K_GRADUATION_REPLAYS, MIPS_CTR_1, 58 }, 158 { PMC_EV_MIPS74K_COREEXTEND_EVENTS, MIPS_CTR_0, 59 }, 159 { PMC_EV_MIPS74K_ISPRAM_EVENTS, MIPS_CTR_0, 62 }, 160 { PMC_EV_MIPS74K_DSPRAM_EVENTS, MIPS_CTR_1, 62 }, 161 { PMC_EV_MIPS74K_L2_CACHE_SINGLE_BIT_ERRORS, MIPS_CTR_0, 63 }, 162 { PMC_EV_MIPS74K_SYSTEM_EVENT_0, MIPS_CTR_0, 64 }, 163 { PMC_EV_MIPS74K_SYSTEM_EVENT_1, MIPS_CTR_1, 64 }, 164 { PMC_EV_MIPS74K_SYSTEM_EVENT_2, MIPS_CTR_0, 65 }, 165 { PMC_EV_MIPS74K_SYSTEM_EVENT_3, MIPS_CTR_1, 65 }, 166 { PMC_EV_MIPS74K_SYSTEM_EVENT_4, MIPS_CTR_0, 66 }, 167 { PMC_EV_MIPS74K_SYSTEM_EVENT_5, MIPS_CTR_1, 66 }, 168 { PMC_EV_MIPS74K_SYSTEM_EVENT_6, MIPS_CTR_0, 67 }, 169 { PMC_EV_MIPS74K_SYSTEM_EVENT_7, MIPS_CTR_1, 67 }, 170 { PMC_EV_MIPS74K_OCP_ALL_REQUESTS, MIPS_CTR_0, 68 }, 171 { PMC_EV_MIPS74K_OCP_ALL_CACHEABLE_REQUESTS, MIPS_CTR_1, 68 }, 172 { PMC_EV_MIPS74K_OCP_READ_REQUESTS, MIPS_CTR_0, 69 }, 173 { PMC_EV_MIPS74K_OCP_READ_CACHEABLE_REQUESTS, MIPS_CTR_1, 69 }, 174 { PMC_EV_MIPS74K_OCP_WRITE_REQUESTS, MIPS_CTR_0, 70 }, 175 { PMC_EV_MIPS74K_OCP_WRITE_CACHEABLE_REQUESTS, MIPS_CTR_1, 70 }, 176 { PMC_EV_MIPS74K_FSB_LESS_25_FULL, MIPS_CTR_0, 74 }, 177 { PMC_EV_MIPS74K_FSB_25_50_FULL, MIPS_CTR_1, 74 }, 178 { PMC_EV_MIPS74K_LDQ_LESS_25_FULL, MIPS_CTR_0, 75 }, 179 { PMC_EV_MIPS74K_LDQ_25_50_FULL, MIPS_CTR_1, 75 }, 180 { PMC_EV_MIPS74K_WBB_LESS_25_FULL, MIPS_CTR_0, 76 }, 181 { PMC_EV_MIPS74K_WBB_25_50_FULL, MIPS_CTR_1, 76 }, 182}; 183 184const int mips_event_codes_size = nitems(mips_event_codes); 185 186struct mips_pmc_spec mips_pmc_spec = { 187 .ps_cpuclass = PMC_CLASS_MIPS74K, 188 .ps_cputype = PMC_CPU_MIPS_74K, 189 .ps_capabilities = MIPS74K_PMC_CAPS, 190 .ps_counter_width = 32 191}; 192 193/* 194 * Performance Count Register N 195 */ 196uint64_t 197mips_pmcn_read(unsigned int pmc) 198{ 199 uint32_t reg = 0; 200 201 KASSERT(pmc < mips_npmcs, ("[mips74k,%d] illegal PMC number %d", 202 __LINE__, pmc)); 203 204 /* The counter value is the next value after the control register. */ 205 switch (pmc) { 206 case 0: 207 reg = mips_rd_perfcnt1(); 208 break; 209 case 1: 210 reg = mips_rd_perfcnt3(); 211 break; 212 default: 213 return 0; 214 } 215 return (reg); 216} 217 218uint64_t 219mips_pmcn_write(unsigned int pmc, uint64_t reg) 220{ 221 222 KASSERT(pmc < mips_npmcs, ("[mips74k,%d] illegal PMC number %d", 223 __LINE__, pmc)); 224 225 switch (pmc) { 226 case 0: 227 mips_wr_perfcnt1(reg); 228 break; 229 case 1: 230 mips_wr_perfcnt3(reg); 231 break; 232 default: 233 return 0; 234 } 235 return (reg); 236} 237 238uint32_t 239mips_get_perfctl(int cpu, int ri, uint32_t event, uint32_t caps) 240{ 241 uint32_t config; 242 243 config = event; 244 245 config <<= MIPS74K_PMC_SELECT; 246 247 if (caps & PMC_CAP_SYSTEM) 248 config |= (MIPS74K_PMC_SUPER_ENABLE | 249 MIPS74K_PMC_KERNEL_ENABLE); 250 if (caps & PMC_CAP_USER) 251 config |= MIPS74K_PMC_USER_ENABLE; 252 if ((caps & (PMC_CAP_USER | PMC_CAP_SYSTEM)) == 0) 253 config |= MIPS74K_PMC_ENABLE; 254 if (caps & PMC_CAP_INTERRUPT) 255 config |= MIPS74K_PMC_INTERRUPT_ENABLE; 256 257 PMCDBG2(MDP,ALL,2,"mips74k-get_perfctl ri=%d -> config=0x%x", ri, config); 258 259 return (config); 260} 261