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$"); 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 = 153 sizeof(mips_event_codes) / sizeof(mips_event_codes[0]); 154 155struct mips_pmc_spec mips_pmc_spec = { 156 .ps_cpuclass = PMC_CLASS_MIPS24K, 157 .ps_cputype = PMC_CPU_MIPS_24K, 158 .ps_capabilities = MIPS24K_PMC_CAPS, 159 .ps_counter_width = 32 160}; 161 162/* 163 * Performance Count Register N 164 */ 165uint64_t 166mips_pmcn_read(unsigned int pmc) 167{ 168 uint32_t reg = 0; 169 170 KASSERT(pmc < mips_npmcs, ("[mips24k,%d] illegal PMC number %d", 171 __LINE__, pmc)); 172 173 /* The counter value is the next value after the control register. */ 174 switch (pmc) { 175 case 0: 176 reg = mips_rd_perfcnt1(); 177 break; 178 case 1: 179 reg = mips_rd_perfcnt3(); 180 break; 181 default: 182 return 0; 183 } 184 return (reg); 185} 186 187uint64_t 188mips_pmcn_write(unsigned int pmc, uint64_t reg) 189{ 190 191 KASSERT(pmc < mips_npmcs, ("[mips24k,%d] illegal PMC number %d", 192 __LINE__, pmc)); 193 194 switch (pmc) { 195 case 0: 196 mips_wr_perfcnt1(reg); 197 break; 198 case 1: 199 mips_wr_perfcnt3(reg); 200 break; 201 default: 202 return 0; 203 } 204 return (reg); 205} 206 207uint32_t 208mips_get_perfctl(int cpu, int ri, uint32_t event, uint32_t caps) 209{ 210 uint32_t config; 211 212 config = event; 213 214 config <<= MIPS24K_PMC_SELECT; 215 216 if (caps & PMC_CAP_SYSTEM) 217 config |= (MIPS24K_PMC_SUPER_ENABLE | 218 MIPS24K_PMC_KERNEL_ENABLE); 219 if (caps & PMC_CAP_USER) 220 config |= MIPS24K_PMC_USER_ENABLE; 221 if ((caps & (PMC_CAP_USER | PMC_CAP_SYSTEM)) == 0) 222 config |= MIPS24K_PMC_ENABLE; 223 if (caps & PMC_CAP_INTERRUPT) 224 config |= MIPS24K_PMC_INTERRUPT_ENABLE; 225 226 PMCDBG2(MDP,ALL,2,"mips24k-get_perfctl ri=%d -> config=0x%x", ri, config); 227 228 return (config); 229} 230