1/*- 2 * Copyright (c) 2010 George V. Neville-Neil <gnn@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 */ 27 28#include <sys/cdefs.h> 29__FBSDID("$FreeBSD: releng/11.0/sys/dev/hwpmc/hwpmc_mips24k.c 298431 2016-04-21 19:40:10Z pfg $"); 30 31#include <sys/param.h> 32#include <sys/systm.h> 33#include <sys/pmc.h> 34#include <sys/pmckern.h> 35 36#include <machine/cpu.h> 37#include <machine/cpufunc.h> 38#include <machine/pmc_mdep.h> 39 40#define MIPS24K_PMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_USER | \ 41 PMC_CAP_SYSTEM | PMC_CAP_EDGE | \ 42 PMC_CAP_THRESHOLD | PMC_CAP_READ | \ 43 PMC_CAP_WRITE | PMC_CAP_INVERT | \ 44 PMC_CAP_QUALIFIER) 45 46#define MIPS24K_PMC_INTERRUPT_ENABLE 0x10 /* Enable interrupts */ 47#define MIPS24K_PMC_USER_ENABLE 0x08 /* Count in USER mode */ 48#define MIPS24K_PMC_SUPER_ENABLE 0x04 /* Count in SUPERVISOR mode */ 49#define MIPS24K_PMC_KERNEL_ENABLE 0x02 /* Count in KERNEL mode */ 50#define MIPS24K_PMC_ENABLE (MIPS24K_PMC_USER_ENABLE | \ 51 MIPS24K_PMC_SUPER_ENABLE | \ 52 MIPS24K_PMC_KERNEL_ENABLE) 53 54#define MIPS24K_PMC_SELECT 5 /* Which bit position the event starts at. */ 55 56const struct mips_event_code_map mips_event_codes[] = { 57 { PMC_EV_MIPS24K_CYCLE, MIPS_CTR_ALL, 0}, 58 { PMC_EV_MIPS24K_INSTR_EXECUTED, MIPS_CTR_ALL, 1}, 59 { PMC_EV_MIPS24K_BRANCH_COMPLETED, MIPS_CTR_0, 2}, 60 { PMC_EV_MIPS24K_BRANCH_MISPRED, MIPS_CTR_1, 2}, 61 { PMC_EV_MIPS24K_RETURN, MIPS_CTR_0, 3}, 62 { PMC_EV_MIPS24K_RETURN_MISPRED, MIPS_CTR_1, 3}, 63 { PMC_EV_MIPS24K_RETURN_NOT_31, MIPS_CTR_0, 4}, 64 { PMC_EV_MIPS24K_RETURN_NOTPRED, MIPS_CTR_1, 4}, 65 { PMC_EV_MIPS24K_ITLB_ACCESS, MIPS_CTR_0, 5}, 66 { PMC_EV_MIPS24K_ITLB_MISS, MIPS_CTR_1, 5}, 67 { PMC_EV_MIPS24K_DTLB_ACCESS, MIPS_CTR_0, 6}, 68 { PMC_EV_MIPS24K_DTLB_MISS, MIPS_CTR_1, 6}, 69 { PMC_EV_MIPS24K_JTLB_IACCESS, MIPS_CTR_0, 7}, 70 { PMC_EV_MIPS24K_JTLB_IMISS, MIPS_CTR_1, 7}, 71 { PMC_EV_MIPS24K_JTLB_DACCESS, MIPS_CTR_0, 8}, 72 { PMC_EV_MIPS24K_JTLB_DMISS, MIPS_CTR_1, 8}, 73 { PMC_EV_MIPS24K_IC_FETCH, MIPS_CTR_0, 9}, 74 { PMC_EV_MIPS24K_IC_MISS, MIPS_CTR_1, 9}, 75 { PMC_EV_MIPS24K_DC_LOADSTORE, MIPS_CTR_0, 10}, 76 { PMC_EV_MIPS24K_DC_WRITEBACK, MIPS_CTR_1, 10}, 77 { PMC_EV_MIPS24K_DC_MISS, MIPS_CTR_ALL, 11}, 78 /* 12 reserved */ 79 { PMC_EV_MIPS24K_STORE_MISS, MIPS_CTR_0, 13}, 80 { PMC_EV_MIPS24K_LOAD_MISS, MIPS_CTR_1, 13}, 81 { PMC_EV_MIPS24K_INTEGER_COMPLETED, MIPS_CTR_0, 14}, 82 { PMC_EV_MIPS24K_FP_COMPLETED, MIPS_CTR_1, 14}, 83 { PMC_EV_MIPS24K_LOAD_COMPLETED, MIPS_CTR_0, 15}, 84 { PMC_EV_MIPS24K_STORE_COMPLETED, MIPS_CTR_1, 15}, 85 { PMC_EV_MIPS24K_BARRIER_COMPLETED, MIPS_CTR_0, 16}, 86 { PMC_EV_MIPS24K_MIPS16_COMPLETED, MIPS_CTR_1, 16}, 87 { PMC_EV_MIPS24K_NOP_COMPLETED, MIPS_CTR_0, 17}, 88 { PMC_EV_MIPS24K_INTEGER_MULDIV_COMPLETED, MIPS_CTR_1, 17}, 89 { PMC_EV_MIPS24K_RF_STALL, MIPS_CTR_0, 18}, 90 { PMC_EV_MIPS24K_INSTR_REFETCH, MIPS_CTR_1, 18}, 91 { PMC_EV_MIPS24K_STORE_COND_COMPLETED, MIPS_CTR_0, 19}, 92 { PMC_EV_MIPS24K_STORE_COND_FAILED, MIPS_CTR_1, 19}, 93 { PMC_EV_MIPS24K_ICACHE_REQUESTS, MIPS_CTR_0, 20}, 94 { PMC_EV_MIPS24K_ICACHE_HIT, MIPS_CTR_1, 20}, 95 { PMC_EV_MIPS24K_L2_WRITEBACK, MIPS_CTR_0, 21}, 96 { PMC_EV_MIPS24K_L2_ACCESS, MIPS_CTR_1, 21}, 97 { PMC_EV_MIPS24K_L2_MISS, MIPS_CTR_0, 22}, 98 { PMC_EV_MIPS24K_L2_ERR_CORRECTED, MIPS_CTR_1, 22}, 99 { PMC_EV_MIPS24K_EXCEPTIONS, MIPS_CTR_0, 23}, 100 /* Event 23 on COP0 1/3 is undefined */ 101 { PMC_EV_MIPS24K_RF_CYCLES_STALLED, MIPS_CTR_0, 24}, 102 { PMC_EV_MIPS24K_IFU_CYCLES_STALLED, MIPS_CTR_0, 25}, 103 { PMC_EV_MIPS24K_ALU_CYCLES_STALLED, MIPS_CTR_1, 25}, 104 /* Events 26 through 32 undefined or reserved to customers */ 105 { PMC_EV_MIPS24K_UNCACHED_LOAD, MIPS_CTR_0, 33}, 106 { PMC_EV_MIPS24K_UNCACHED_STORE, MIPS_CTR_1, 33}, 107 { PMC_EV_MIPS24K_CP2_REG_TO_REG_COMPLETED, MIPS_CTR_0, 35}, 108 { PMC_EV_MIPS24K_MFTC_COMPLETED, MIPS_CTR_1, 35}, 109 /* Event 36 reserved */ 110 { PMC_EV_MIPS24K_IC_BLOCKED_CYCLES, MIPS_CTR_0, 37}, 111 { PMC_EV_MIPS24K_DC_BLOCKED_CYCLES, MIPS_CTR_1, 37}, 112 { PMC_EV_MIPS24K_L2_IMISS_STALL_CYCLES, MIPS_CTR_0, 38}, 113 { PMC_EV_MIPS24K_L2_DMISS_STALL_CYCLES, MIPS_CTR_1, 38}, 114 { PMC_EV_MIPS24K_DMISS_CYCLES, MIPS_CTR_0, 39}, 115 { PMC_EV_MIPS24K_L2_MISS_CYCLES, MIPS_CTR_1, 39}, 116 { PMC_EV_MIPS24K_UNCACHED_BLOCK_CYCLES, MIPS_CTR_0, 40}, 117 { PMC_EV_MIPS24K_MDU_STALL_CYCLES, MIPS_CTR_0, 41}, 118 { PMC_EV_MIPS24K_FPU_STALL_CYCLES, MIPS_CTR_1, 41}, 119 { PMC_EV_MIPS24K_CP2_STALL_CYCLES, MIPS_CTR_0, 42}, 120 { PMC_EV_MIPS24K_COREXTEND_STALL_CYCLES, MIPS_CTR_1, 42}, 121 { PMC_EV_MIPS24K_ISPRAM_STALL_CYCLES, MIPS_CTR_0, 43}, 122 { PMC_EV_MIPS24K_DSPRAM_STALL_CYCLES, MIPS_CTR_1, 43}, 123 { PMC_EV_MIPS24K_CACHE_STALL_CYCLES, MIPS_CTR_0, 44}, 124 /* Event 44 undefined on 1/3 */ 125 { PMC_EV_MIPS24K_LOAD_TO_USE_STALLS, MIPS_CTR_0, 45}, 126 { PMC_EV_MIPS24K_BASE_MISPRED_STALLS, MIPS_CTR_1, 45}, 127 { PMC_EV_MIPS24K_CPO_READ_STALLS, MIPS_CTR_0, 46}, 128 { PMC_EV_MIPS24K_BRANCH_MISPRED_CYCLES, MIPS_CTR_1, 46}, 129 /* Event 47 reserved */ 130 { PMC_EV_MIPS24K_IFETCH_BUFFER_FULL, MIPS_CTR_0, 48}, 131 { PMC_EV_MIPS24K_FETCH_BUFFER_ALLOCATED, MIPS_CTR_1, 48}, 132 { PMC_EV_MIPS24K_EJTAG_ITRIGGER, MIPS_CTR_0, 49}, 133 { PMC_EV_MIPS24K_EJTAG_DTRIGGER, MIPS_CTR_1, 49}, 134 { PMC_EV_MIPS24K_FSB_LT_QUARTER, MIPS_CTR_0, 50}, 135 { PMC_EV_MIPS24K_FSB_QUARTER_TO_HALF, MIPS_CTR_1, 50}, 136 { PMC_EV_MIPS24K_FSB_GT_HALF, MIPS_CTR_0, 51}, 137 { PMC_EV_MIPS24K_FSB_FULL_PIPELINE_STALLS, MIPS_CTR_1, 51}, 138 { PMC_EV_MIPS24K_LDQ_LT_QUARTER, MIPS_CTR_0, 52}, 139 { PMC_EV_MIPS24K_LDQ_QUARTER_TO_HALF, MIPS_CTR_1, 52}, 140 { PMC_EV_MIPS24K_LDQ_GT_HALF, MIPS_CTR_0, 53}, 141 { PMC_EV_MIPS24K_LDQ_FULL_PIPELINE_STALLS, MIPS_CTR_1, 53}, 142 { PMC_EV_MIPS24K_WBB_LT_QUARTER, MIPS_CTR_0, 54}, 143 { PMC_EV_MIPS24K_WBB_QUARTER_TO_HALF, MIPS_CTR_1, 54}, 144 { PMC_EV_MIPS24K_WBB_GT_HALF, MIPS_CTR_0, 55}, 145 { PMC_EV_MIPS24K_WBB_FULL_PIPELINE_STALLS, MIPS_CTR_1, 55}, 146 /* Events 56-63 reserved */ 147 { PMC_EV_MIPS24K_REQUEST_LATENCY, MIPS_CTR_0, 61}, 148 { PMC_EV_MIPS24K_REQUEST_COUNT, MIPS_CTR_1, 61} 149 150}; 151 152const int mips_event_codes_size = nitems(mips_event_codes); 153 154struct mips_pmc_spec mips_pmc_spec = { 155 .ps_cpuclass = PMC_CLASS_MIPS24K, 156 .ps_cputype = PMC_CPU_MIPS_24K, 157 .ps_capabilities = MIPS24K_PMC_CAPS, 158 .ps_counter_width = 32 159}; 160 161/* 162 * Performance Count Register N 163 */ 164uint64_t 165mips_pmcn_read(unsigned int pmc) 166{ 167 uint32_t reg = 0; 168 169 KASSERT(pmc < mips_npmcs, ("[mips24k,%d] illegal PMC number %d", 170 __LINE__, pmc)); 171 172 /* The counter value is the next value after the control register. */ 173 switch (pmc) { 174 case 0: 175 reg = mips_rd_perfcnt1(); 176 break; 177 case 1: 178 reg = mips_rd_perfcnt3(); 179 break; 180 default: 181 return 0; 182 } 183 return (reg); 184} 185 186uint64_t 187mips_pmcn_write(unsigned int pmc, uint64_t reg) 188{ 189 190 KASSERT(pmc < mips_npmcs, ("[mips24k,%d] illegal PMC number %d", 191 __LINE__, pmc)); 192 193 switch (pmc) { 194 case 0: 195 mips_wr_perfcnt1(reg); 196 break; 197 case 1: 198 mips_wr_perfcnt3(reg); 199 break; 200 default: 201 return 0; 202 } 203 return (reg); 204} 205 206uint32_t 207mips_get_perfctl(int cpu, int ri, uint32_t event, uint32_t caps) 208{ 209 uint32_t config; 210 211 config = event; 212 213 config <<= MIPS24K_PMC_SELECT; 214 215 if (caps & PMC_CAP_SYSTEM) 216 config |= (MIPS24K_PMC_SUPER_ENABLE | 217 MIPS24K_PMC_KERNEL_ENABLE); 218 if (caps & PMC_CAP_USER) 219 config |= MIPS24K_PMC_USER_ENABLE; 220 if ((caps & (PMC_CAP_USER | PMC_CAP_SYSTEM)) == 0) 221 config |= MIPS24K_PMC_ENABLE; 222 if (caps & PMC_CAP_INTERRUPT) 223 config |= MIPS24K_PMC_INTERRUPT_ENABLE; 224 225 PMCDBG2(MDP,ALL,2,"mips24k-get_perfctl ri=%d -> config=0x%x", ri, config); 226 227 return (config); 228} 229