1204635Sgnn/*- 2204635Sgnn * Copyright (c) 2010 George V. Neville-Neil <gnn@freebsd.org> 3204635Sgnn * All rights reserved. 4204635Sgnn * 5204635Sgnn * Redistribution and use in source and binary forms, with or without 6204635Sgnn * modification, are permitted provided that the following conditions 7204635Sgnn * are met: 8204635Sgnn * 1. Redistributions of source code must retain the above copyright 9204635Sgnn * notice, this list of conditions and the following disclaimer. 10204635Sgnn * 2. Redistributions in binary form must reproduce the above copyright 11204635Sgnn * notice, this list of conditions and the following disclaimer in the 12204635Sgnn * documentation and/or other materials provided with the distribution. 13204635Sgnn * 14204635Sgnn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15204635Sgnn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16204635Sgnn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17204635Sgnn * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18204635Sgnn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19204635Sgnn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20204635Sgnn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21204635Sgnn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22204635Sgnn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23204635Sgnn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24204635Sgnn * SUCH DAMAGE. 25204635Sgnn * 26204635Sgnn */ 27204635Sgnn 28204635Sgnn#include <sys/cdefs.h> 29204635Sgnn__FBSDID("$FreeBSD$"); 30204635Sgnn 31204635Sgnn#include <sys/param.h> 32204635Sgnn#include <sys/systm.h> 33204635Sgnn#include <sys/pmc.h> 34204635Sgnn#include <sys/pmckern.h> 35204635Sgnn 36204635Sgnn#include <machine/cpu.h> 37204635Sgnn#include <machine/cpufunc.h> 38204635Sgnn#include <machine/pmc_mdep.h> 39204635Sgnn 40233319Sgonzo#define MIPS24K_PMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_USER | \ 41233319Sgonzo PMC_CAP_SYSTEM | PMC_CAP_EDGE | \ 42233319Sgonzo PMC_CAP_THRESHOLD | PMC_CAP_READ | \ 43233319Sgonzo PMC_CAP_WRITE | PMC_CAP_INVERT | \ 44233319Sgonzo PMC_CAP_QUALIFIER) 45204635Sgnn 46233319Sgonzo#define MIPS24K_PMC_INTERRUPT_ENABLE 0x10 /* Enable interrupts */ 47233319Sgonzo#define MIPS24K_PMC_USER_ENABLE 0x08 /* Count in USER mode */ 48233319Sgonzo#define MIPS24K_PMC_SUPER_ENABLE 0x04 /* Count in SUPERVISOR mode */ 49233319Sgonzo#define MIPS24K_PMC_KERNEL_ENABLE 0x02 /* Count in KERNEL mode */ 50233319Sgonzo#define MIPS24K_PMC_ENABLE (MIPS24K_PMC_USER_ENABLE | \ 51233319Sgonzo MIPS24K_PMC_SUPER_ENABLE | \ 52233319Sgonzo MIPS24K_PMC_KERNEL_ENABLE) 53204635Sgnn 54233319Sgonzo#define MIPS24K_PMC_SELECT 5 /* Which bit position the event starts at. */ 55204635Sgnn 56233319Sgonzoconst struct mips_event_code_map mips_event_codes[] = { 57233319Sgonzo { PMC_EV_MIPS24K_CYCLE, MIPS_CTR_ALL, 0}, 58233319Sgonzo { PMC_EV_MIPS24K_INSTR_EXECUTED, MIPS_CTR_ALL, 1}, 59233319Sgonzo { PMC_EV_MIPS24K_BRANCH_COMPLETED, MIPS_CTR_0, 2}, 60233319Sgonzo { PMC_EV_MIPS24K_BRANCH_MISPRED, MIPS_CTR_1, 2}, 61233319Sgonzo { PMC_EV_MIPS24K_RETURN, MIPS_CTR_0, 3}, 62233319Sgonzo { PMC_EV_MIPS24K_RETURN_MISPRED, MIPS_CTR_1, 3}, 63233319Sgonzo { PMC_EV_MIPS24K_RETURN_NOT_31, MIPS_CTR_0, 4}, 64233319Sgonzo { PMC_EV_MIPS24K_RETURN_NOTPRED, MIPS_CTR_1, 4}, 65233319Sgonzo { PMC_EV_MIPS24K_ITLB_ACCESS, MIPS_CTR_0, 5}, 66233319Sgonzo { PMC_EV_MIPS24K_ITLB_MISS, MIPS_CTR_1, 5}, 67233319Sgonzo { PMC_EV_MIPS24K_DTLB_ACCESS, MIPS_CTR_0, 6}, 68233319Sgonzo { PMC_EV_MIPS24K_DTLB_MISS, MIPS_CTR_1, 6}, 69233319Sgonzo { PMC_EV_MIPS24K_JTLB_IACCESS, MIPS_CTR_0, 7}, 70233319Sgonzo { PMC_EV_MIPS24K_JTLB_IMISS, MIPS_CTR_1, 7}, 71233319Sgonzo { PMC_EV_MIPS24K_JTLB_DACCESS, MIPS_CTR_0, 8}, 72233319Sgonzo { PMC_EV_MIPS24K_JTLB_DMISS, MIPS_CTR_1, 8}, 73233319Sgonzo { PMC_EV_MIPS24K_IC_FETCH, MIPS_CTR_0, 9}, 74233319Sgonzo { PMC_EV_MIPS24K_IC_MISS, MIPS_CTR_1, 9}, 75233319Sgonzo { PMC_EV_MIPS24K_DC_LOADSTORE, MIPS_CTR_0, 10}, 76233319Sgonzo { PMC_EV_MIPS24K_DC_WRITEBACK, MIPS_CTR_1, 10}, 77233319Sgonzo { PMC_EV_MIPS24K_DC_MISS, MIPS_CTR_ALL, 11}, 78204635Sgnn /* 12 reserved */ 79233319Sgonzo { PMC_EV_MIPS24K_STORE_MISS, MIPS_CTR_0, 13}, 80233319Sgonzo { PMC_EV_MIPS24K_LOAD_MISS, MIPS_CTR_1, 13}, 81233319Sgonzo { PMC_EV_MIPS24K_INTEGER_COMPLETED, MIPS_CTR_0, 14}, 82233319Sgonzo { PMC_EV_MIPS24K_FP_COMPLETED, MIPS_CTR_1, 14}, 83233319Sgonzo { PMC_EV_MIPS24K_LOAD_COMPLETED, MIPS_CTR_0, 15}, 84233319Sgonzo { PMC_EV_MIPS24K_STORE_COMPLETED, MIPS_CTR_1, 15}, 85233319Sgonzo { PMC_EV_MIPS24K_BARRIER_COMPLETED, MIPS_CTR_0, 16}, 86233319Sgonzo { PMC_EV_MIPS24K_MIPS16_COMPLETED, MIPS_CTR_1, 16}, 87233319Sgonzo { PMC_EV_MIPS24K_NOP_COMPLETED, MIPS_CTR_0, 17}, 88233319Sgonzo { PMC_EV_MIPS24K_INTEGER_MULDIV_COMPLETED, MIPS_CTR_1, 17}, 89233319Sgonzo { PMC_EV_MIPS24K_RF_STALL, MIPS_CTR_0, 18}, 90233319Sgonzo { PMC_EV_MIPS24K_INSTR_REFETCH, MIPS_CTR_1, 18}, 91233319Sgonzo { PMC_EV_MIPS24K_STORE_COND_COMPLETED, MIPS_CTR_0, 19}, 92233319Sgonzo { PMC_EV_MIPS24K_STORE_COND_FAILED, MIPS_CTR_1, 19}, 93233319Sgonzo { PMC_EV_MIPS24K_ICACHE_REQUESTS, MIPS_CTR_0, 20}, 94233319Sgonzo { PMC_EV_MIPS24K_ICACHE_HIT, MIPS_CTR_1, 20}, 95233319Sgonzo { PMC_EV_MIPS24K_L2_WRITEBACK, MIPS_CTR_0, 21}, 96233319Sgonzo { PMC_EV_MIPS24K_L2_ACCESS, MIPS_CTR_1, 21}, 97233319Sgonzo { PMC_EV_MIPS24K_L2_MISS, MIPS_CTR_0, 22}, 98233319Sgonzo { PMC_EV_MIPS24K_L2_ERR_CORRECTED, MIPS_CTR_1, 22}, 99233319Sgonzo { PMC_EV_MIPS24K_EXCEPTIONS, MIPS_CTR_0, 23}, 100204635Sgnn /* Event 23 on COP0 1/3 is undefined */ 101233319Sgonzo { PMC_EV_MIPS24K_RF_CYCLES_STALLED, MIPS_CTR_0, 24}, 102233319Sgonzo { PMC_EV_MIPS24K_IFU_CYCLES_STALLED, MIPS_CTR_0, 25}, 103233319Sgonzo { PMC_EV_MIPS24K_ALU_CYCLES_STALLED, MIPS_CTR_1, 25}, 104204635Sgnn /* Events 26 through 32 undefined or reserved to customers */ 105233319Sgonzo { PMC_EV_MIPS24K_UNCACHED_LOAD, MIPS_CTR_0, 33}, 106233319Sgonzo { PMC_EV_MIPS24K_UNCACHED_STORE, MIPS_CTR_1, 33}, 107233319Sgonzo { PMC_EV_MIPS24K_CP2_REG_TO_REG_COMPLETED, MIPS_CTR_0, 35}, 108233319Sgonzo { PMC_EV_MIPS24K_MFTC_COMPLETED, MIPS_CTR_1, 35}, 109204635Sgnn /* Event 36 reserved */ 110233319Sgonzo { PMC_EV_MIPS24K_IC_BLOCKED_CYCLES, MIPS_CTR_0, 37}, 111233319Sgonzo { PMC_EV_MIPS24K_DC_BLOCKED_CYCLES, MIPS_CTR_1, 37}, 112233319Sgonzo { PMC_EV_MIPS24K_L2_IMISS_STALL_CYCLES, MIPS_CTR_0, 38}, 113233319Sgonzo { PMC_EV_MIPS24K_L2_DMISS_STALL_CYCLES, MIPS_CTR_1, 38}, 114233319Sgonzo { PMC_EV_MIPS24K_DMISS_CYCLES, MIPS_CTR_0, 39}, 115233319Sgonzo { PMC_EV_MIPS24K_L2_MISS_CYCLES, MIPS_CTR_1, 39}, 116233319Sgonzo { PMC_EV_MIPS24K_UNCACHED_BLOCK_CYCLES, MIPS_CTR_0, 40}, 117233319Sgonzo { PMC_EV_MIPS24K_MDU_STALL_CYCLES, MIPS_CTR_0, 41}, 118233319Sgonzo { PMC_EV_MIPS24K_FPU_STALL_CYCLES, MIPS_CTR_1, 41}, 119233319Sgonzo { PMC_EV_MIPS24K_CP2_STALL_CYCLES, MIPS_CTR_0, 42}, 120233319Sgonzo { PMC_EV_MIPS24K_COREXTEND_STALL_CYCLES, MIPS_CTR_1, 42}, 121233319Sgonzo { PMC_EV_MIPS24K_ISPRAM_STALL_CYCLES, MIPS_CTR_0, 43}, 122233319Sgonzo { PMC_EV_MIPS24K_DSPRAM_STALL_CYCLES, MIPS_CTR_1, 43}, 123233319Sgonzo { PMC_EV_MIPS24K_CACHE_STALL_CYCLES, MIPS_CTR_0, 44}, 124204635Sgnn /* Event 44 undefined on 1/3 */ 125233319Sgonzo { PMC_EV_MIPS24K_LOAD_TO_USE_STALLS, MIPS_CTR_0, 45}, 126233319Sgonzo { PMC_EV_MIPS24K_BASE_MISPRED_STALLS, MIPS_CTR_1, 45}, 127233319Sgonzo { PMC_EV_MIPS24K_CPO_READ_STALLS, MIPS_CTR_0, 46}, 128233319Sgonzo { PMC_EV_MIPS24K_BRANCH_MISPRED_CYCLES, MIPS_CTR_1, 46}, 129204635Sgnn /* Event 47 reserved */ 130233319Sgonzo { PMC_EV_MIPS24K_IFETCH_BUFFER_FULL, MIPS_CTR_0, 48}, 131233319Sgonzo { PMC_EV_MIPS24K_FETCH_BUFFER_ALLOCATED, MIPS_CTR_1, 48}, 132233319Sgonzo { PMC_EV_MIPS24K_EJTAG_ITRIGGER, MIPS_CTR_0, 49}, 133233319Sgonzo { PMC_EV_MIPS24K_EJTAG_DTRIGGER, MIPS_CTR_1, 49}, 134233319Sgonzo { PMC_EV_MIPS24K_FSB_LT_QUARTER, MIPS_CTR_0, 50}, 135233319Sgonzo { PMC_EV_MIPS24K_FSB_QUARTER_TO_HALF, MIPS_CTR_1, 50}, 136233319Sgonzo { PMC_EV_MIPS24K_FSB_GT_HALF, MIPS_CTR_0, 51}, 137233319Sgonzo { PMC_EV_MIPS24K_FSB_FULL_PIPELINE_STALLS, MIPS_CTR_1, 51}, 138233319Sgonzo { PMC_EV_MIPS24K_LDQ_LT_QUARTER, MIPS_CTR_0, 52}, 139233319Sgonzo { PMC_EV_MIPS24K_LDQ_QUARTER_TO_HALF, MIPS_CTR_1, 52}, 140233319Sgonzo { PMC_EV_MIPS24K_LDQ_GT_HALF, MIPS_CTR_0, 53}, 141233319Sgonzo { PMC_EV_MIPS24K_LDQ_FULL_PIPELINE_STALLS, MIPS_CTR_1, 53}, 142233319Sgonzo { PMC_EV_MIPS24K_WBB_LT_QUARTER, MIPS_CTR_0, 54}, 143233319Sgonzo { PMC_EV_MIPS24K_WBB_QUARTER_TO_HALF, MIPS_CTR_1, 54}, 144233319Sgonzo { PMC_EV_MIPS24K_WBB_GT_HALF, MIPS_CTR_0, 55}, 145233319Sgonzo { PMC_EV_MIPS24K_WBB_FULL_PIPELINE_STALLS, MIPS_CTR_1, 55}, 146204635Sgnn /* Events 56-63 reserved */ 147233319Sgonzo { PMC_EV_MIPS24K_REQUEST_LATENCY, MIPS_CTR_0, 61}, 148233319Sgonzo { PMC_EV_MIPS24K_REQUEST_COUNT, MIPS_CTR_1, 61} 149204635Sgnn 150204635Sgnn}; 151204635Sgnn 152233319Sgonzoconst int mips_event_codes_size = 153233319Sgonzo sizeof(mips_event_codes) / sizeof(mips_event_codes[0]); 154204635Sgnn 155233319Sgonzostruct mips_pmc_spec mips_pmc_spec = { 156233319Sgonzo .ps_cpuclass = PMC_CLASS_MIPS24K, 157233319Sgonzo .ps_cputype = PMC_CPU_MIPS_24K, 158233319Sgonzo .ps_capabilities = MIPS24K_PMC_CAPS, 159233319Sgonzo .ps_counter_width = 32 160204635Sgnn}; 161204635Sgnn 162204635Sgnn/* 163204635Sgnn * Performance Count Register N 164204635Sgnn */ 165233319Sgonzouint64_t 166233319Sgonzomips_pmcn_read(unsigned int pmc) 167204635Sgnn{ 168204635Sgnn uint32_t reg = 0; 169204635Sgnn 170233319Sgonzo KASSERT(pmc < mips_npmcs, ("[mips24k,%d] illegal PMC number %d", 171204635Sgnn __LINE__, pmc)); 172204635Sgnn 173204635Sgnn /* The counter value is the next value after the control register. */ 174204635Sgnn switch (pmc) { 175204635Sgnn case 0: 176204635Sgnn reg = mips_rd_perfcnt1(); 177204635Sgnn break; 178204635Sgnn case 1: 179204635Sgnn reg = mips_rd_perfcnt3(); 180204635Sgnn break; 181204635Sgnn default: 182204635Sgnn return 0; 183204635Sgnn } 184204635Sgnn return (reg); 185204635Sgnn} 186204635Sgnn 187233319Sgonzouint64_t 188233319Sgonzomips_pmcn_write(unsigned int pmc, uint64_t reg) 189204635Sgnn{ 190204635Sgnn 191233319Sgonzo KASSERT(pmc < mips_npmcs, ("[mips24k,%d] illegal PMC number %d", 192204635Sgnn __LINE__, pmc)); 193233319Sgonzo 194204635Sgnn switch (pmc) { 195204635Sgnn case 0: 196204635Sgnn mips_wr_perfcnt1(reg); 197204635Sgnn break; 198204635Sgnn case 1: 199204635Sgnn mips_wr_perfcnt3(reg); 200204635Sgnn break; 201204635Sgnn default: 202204635Sgnn return 0; 203204635Sgnn } 204204635Sgnn return (reg); 205204635Sgnn} 206204635Sgnn 207233319Sgonzouint32_t 208233319Sgonzomips_get_perfctl(int cpu, int ri, uint32_t event, uint32_t caps) 209204635Sgnn{ 210233319Sgonzo uint32_t config; 211204635Sgnn 212233319Sgonzo config = event; 213204635Sgnn 214204635Sgnn config <<= MIPS24K_PMC_SELECT; 215204635Sgnn 216204635Sgnn if (caps & PMC_CAP_SYSTEM) 217233319Sgonzo config |= (MIPS24K_PMC_SUPER_ENABLE | 218204635Sgnn MIPS24K_PMC_KERNEL_ENABLE); 219204635Sgnn if (caps & PMC_CAP_USER) 220204635Sgnn config |= MIPS24K_PMC_USER_ENABLE; 221204635Sgnn if ((caps & (PMC_CAP_USER | PMC_CAP_SYSTEM)) == 0) 222204635Sgnn config |= MIPS24K_PMC_ENABLE; 223227395Sadrian if (caps & PMC_CAP_INTERRUPT) 224227395Sadrian config |= MIPS24K_PMC_INTERRUPT_ENABLE; 225204635Sgnn 226283884Sjhb PMCDBG2(MDP,ALL,2,"mips24k-get_perfctl ri=%d -> config=0x%x", ri, config); 227204635Sgnn 228233319Sgonzo return (config); 229204635Sgnn} 230