1ebccf1e3SJoseph Koshy /*- 2484202faSJoseph Koshy * Copyright (c) 2003-2008 Joseph Koshy 3ebccf1e3SJoseph Koshy * All rights reserved. 4ebccf1e3SJoseph Koshy * 5ebccf1e3SJoseph Koshy * Redistribution and use in source and binary forms, with or without 6ebccf1e3SJoseph Koshy * modification, are permitted provided that the following conditions 7ebccf1e3SJoseph Koshy * are met: 8ebccf1e3SJoseph Koshy * 1. Redistributions of source code must retain the above copyright 9ebccf1e3SJoseph Koshy * notice, this list of conditions and the following disclaimer. 10ebccf1e3SJoseph Koshy * 2. Redistributions in binary form must reproduce the above copyright 11ebccf1e3SJoseph Koshy * notice, this list of conditions and the following disclaimer in the 12ebccf1e3SJoseph Koshy * documentation and/or other materials provided with the distribution. 13ebccf1e3SJoseph Koshy * 14ebccf1e3SJoseph Koshy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15ebccf1e3SJoseph Koshy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16ebccf1e3SJoseph Koshy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17ebccf1e3SJoseph Koshy * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18ebccf1e3SJoseph Koshy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19ebccf1e3SJoseph Koshy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20ebccf1e3SJoseph Koshy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21ebccf1e3SJoseph Koshy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22ebccf1e3SJoseph Koshy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23ebccf1e3SJoseph Koshy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24ebccf1e3SJoseph Koshy * SUCH DAMAGE. 25ebccf1e3SJoseph Koshy */ 26ebccf1e3SJoseph Koshy 27ebccf1e3SJoseph Koshy #include <sys/cdefs.h> 28ebccf1e3SJoseph Koshy __FBSDID("$FreeBSD$"); 29ebccf1e3SJoseph Koshy 30ebccf1e3SJoseph Koshy #include <sys/types.h> 31169dd953SJustin Hibbits #include <sys/param.h> 32ebccf1e3SJoseph Koshy #include <sys/module.h> 33ebccf1e3SJoseph Koshy #include <sys/pmc.h> 34ebccf1e3SJoseph Koshy #include <sys/syscall.h> 35ebccf1e3SJoseph Koshy 36ebccf1e3SJoseph Koshy #include <ctype.h> 37ebccf1e3SJoseph Koshy #include <errno.h> 38ebccf1e3SJoseph Koshy #include <fcntl.h> 39ebccf1e3SJoseph Koshy #include <pmc.h> 40ebccf1e3SJoseph Koshy #include <stdio.h> 41ebccf1e3SJoseph Koshy #include <stdlib.h> 42ebccf1e3SJoseph Koshy #include <string.h> 43ebccf1e3SJoseph Koshy #include <strings.h> 44ebccf1e3SJoseph Koshy #include <unistd.h> 45ebccf1e3SJoseph Koshy 460cfab8ddSJoseph Koshy #include "libpmcinternal.h" 470cfab8ddSJoseph Koshy 48ebccf1e3SJoseph Koshy /* Function prototypes */ 4904e9feb0SMarcel Moolenaar #if defined(__i386__) 50ebccf1e3SJoseph Koshy static int k7_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 51ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 52f263522aSJoseph Koshy #endif 5386a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 540cfab8ddSJoseph Koshy static int iaf_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 550cfab8ddSJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 560cfab8ddSJoseph Koshy static int iap_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 570cfab8ddSJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 581fa7f10bSFabien Thomas static int ucf_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 591fa7f10bSFabien Thomas struct pmc_op_pmcallocate *_pmc_config); 601fa7f10bSFabien Thomas static int ucp_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 611fa7f10bSFabien Thomas struct pmc_op_pmcallocate *_pmc_config); 62f263522aSJoseph Koshy static int k8_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 63ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 6486a65549SJoseph Koshy static int p4_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 6586a65549SJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 66f263522aSJoseph Koshy #endif 67f263522aSJoseph Koshy #if defined(__i386__) 68ebccf1e3SJoseph Koshy static int p5_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 69ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 70f263522aSJoseph Koshy static int p6_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 71ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 72ebccf1e3SJoseph Koshy #endif 73789140c0SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 74789140c0SJoseph Koshy static int tsc_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 75789140c0SJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 76789140c0SJoseph Koshy #endif 776411d14dSRuslan Bukin #if defined(__arm__) 780ce207d2SRui Paulo #if defined(__XSCALE__) 790ce207d2SRui Paulo static int xscale_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 800ce207d2SRui Paulo struct pmc_op_pmcallocate *_pmc_config); 810ce207d2SRui Paulo #endif 826411d14dSRuslan Bukin static int armv7_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 836411d14dSRuslan Bukin struct pmc_op_pmcallocate *_pmc_config); 846411d14dSRuslan Bukin #endif 85*bc88bb2bSRuslan Bukin #if defined(__aarch64__) 86*bc88bb2bSRuslan Bukin static int arm64_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 87*bc88bb2bSRuslan Bukin struct pmc_op_pmcallocate *_pmc_config); 88*bc88bb2bSRuslan Bukin #endif 89660df75eSGeorge V. Neville-Neil #if defined(__mips__) 902827d3e1SOleksandr Tymoshenko static int mips_allocate_pmc(enum pmc_event _pe, char* ctrspec, 91660df75eSGeorge V. Neville-Neil struct pmc_op_pmcallocate *_pmc_config); 92660df75eSGeorge V. Neville-Neil #endif /* __mips__ */ 93f5f9340bSFabien Thomas static int soft_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 94f5f9340bSFabien Thomas struct pmc_op_pmcallocate *_pmc_config); 95660df75eSGeorge V. Neville-Neil 967b25dccaSJustin Hibbits #if defined(__powerpc__) 97169dd953SJustin Hibbits static int powerpc_allocate_pmc(enum pmc_event _pe, char* ctrspec, 987b25dccaSJustin Hibbits struct pmc_op_pmcallocate *_pmc_config); 997b25dccaSJustin Hibbits #endif /* __powerpc__ */ 100660df75eSGeorge V. Neville-Neil 101ebccf1e3SJoseph Koshy #define PMC_CALL(cmd, params) \ 102ebccf1e3SJoseph Koshy syscall(pmc_syscall, PMC_OP_##cmd, (params)) 103ebccf1e3SJoseph Koshy 104ebccf1e3SJoseph Koshy /* 105ebccf1e3SJoseph Koshy * Event aliases provide a way for the user to ask for generic events 106ebccf1e3SJoseph Koshy * like "cache-misses", or "instructions-retired". These aliases are 107ebccf1e3SJoseph Koshy * mapped to the appropriate canonical event descriptions using a 108ebccf1e3SJoseph Koshy * lookup table. 109ebccf1e3SJoseph Koshy */ 110ebccf1e3SJoseph Koshy struct pmc_event_alias { 111ebccf1e3SJoseph Koshy const char *pm_alias; 112ebccf1e3SJoseph Koshy const char *pm_spec; 113ebccf1e3SJoseph Koshy }; 114ebccf1e3SJoseph Koshy 115ebccf1e3SJoseph Koshy static const struct pmc_event_alias *pmc_mdep_event_aliases; 116ebccf1e3SJoseph Koshy 117ebccf1e3SJoseph Koshy /* 118789140c0SJoseph Koshy * The pmc_event_descr structure maps symbolic names known to the user 119ebccf1e3SJoseph Koshy * to integer codes used by the PMC KLD. 120ebccf1e3SJoseph Koshy */ 121ebccf1e3SJoseph Koshy struct pmc_event_descr { 122ebccf1e3SJoseph Koshy const char *pm_ev_name; 123ebccf1e3SJoseph Koshy enum pmc_event pm_ev_code; 124ebccf1e3SJoseph Koshy }; 125ebccf1e3SJoseph Koshy 126789140c0SJoseph Koshy /* 127789140c0SJoseph Koshy * The pmc_class_descr structure maps class name prefixes for 128789140c0SJoseph Koshy * event names to event tables and other PMC class data. 129789140c0SJoseph Koshy */ 130789140c0SJoseph Koshy struct pmc_class_descr { 131789140c0SJoseph Koshy const char *pm_evc_name; 132789140c0SJoseph Koshy size_t pm_evc_name_size; 133789140c0SJoseph Koshy enum pmc_class pm_evc_class; 134789140c0SJoseph Koshy const struct pmc_event_descr *pm_evc_event_table; 135789140c0SJoseph Koshy size_t pm_evc_event_table_size; 136789140c0SJoseph Koshy int (*pm_evc_allocate_pmc)(enum pmc_event _pe, 137789140c0SJoseph Koshy char *_ctrspec, struct pmc_op_pmcallocate *_pa); 138ebccf1e3SJoseph Koshy }; 139ebccf1e3SJoseph Koshy 140789140c0SJoseph Koshy #define PMC_TABLE_SIZE(N) (sizeof(N)/sizeof(N[0])) 141789140c0SJoseph Koshy #define PMC_EVENT_TABLE_SIZE(N) PMC_TABLE_SIZE(N##_event_table) 142789140c0SJoseph Koshy 143789140c0SJoseph Koshy #undef __PMC_EV 144789140c0SJoseph Koshy #define __PMC_EV(C,N) { #N, PMC_EV_ ## C ## _ ## N }, 145789140c0SJoseph Koshy 146789140c0SJoseph Koshy /* 1470cfab8ddSJoseph Koshy * PMC_CLASSDEP_TABLE(NAME, CLASS) 148789140c0SJoseph Koshy * 1490cfab8ddSJoseph Koshy * Define a table mapping event names and aliases to HWPMC event IDs. 150789140c0SJoseph Koshy */ 1510cfab8ddSJoseph Koshy #define PMC_CLASSDEP_TABLE(N, C) \ 152789140c0SJoseph Koshy static const struct pmc_event_descr N##_event_table[] = \ 153789140c0SJoseph Koshy { \ 154789140c0SJoseph Koshy __PMC_EV_##C() \ 1550cfab8ddSJoseph Koshy } 1560cfab8ddSJoseph Koshy 1570cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(iaf, IAF); 1580cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(k7, K7); 1590cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(k8, K8); 1600cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(p4, P4); 1610cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(p5, P5); 1620cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(p6, P6); 1630ce207d2SRui Paulo PMC_CLASSDEP_TABLE(xscale, XSCALE); 1646411d14dSRuslan Bukin PMC_CLASSDEP_TABLE(armv7, ARMV7); 165*bc88bb2bSRuslan Bukin PMC_CLASSDEP_TABLE(armv8, ARMV8); 166660df75eSGeorge V. Neville-Neil PMC_CLASSDEP_TABLE(mips24k, MIPS24K); 167f6e6460dSAdrian Chadd PMC_CLASSDEP_TABLE(mips74k, MIPS74K); 168c2657f80SOleksandr Tymoshenko PMC_CLASSDEP_TABLE(octeon, OCTEON); 1691fa7f10bSFabien Thomas PMC_CLASSDEP_TABLE(ucf, UCF); 1707b25dccaSJustin Hibbits PMC_CLASSDEP_TABLE(ppc7450, PPC7450); 171169dd953SJustin Hibbits PMC_CLASSDEP_TABLE(ppc970, PPC970); 172a7452468SJustin Hibbits PMC_CLASSDEP_TABLE(e500, E500); 1730cfab8ddSJoseph Koshy 174f5f9340bSFabien Thomas static struct pmc_event_descr soft_event_table[PMC_EV_DYN_COUNT]; 175f5f9340bSFabien Thomas 1760cfab8ddSJoseph Koshy #undef __PMC_EV_ALIAS 1770cfab8ddSJoseph Koshy #define __PMC_EV_ALIAS(N,CODE) { N, PMC_EV_##CODE }, 1780cfab8ddSJoseph Koshy 1790cfab8ddSJoseph Koshy static const struct pmc_event_descr atom_event_table[] = 1800cfab8ddSJoseph Koshy { 1810cfab8ddSJoseph Koshy __PMC_EV_ALIAS_ATOM() 1820cfab8ddSJoseph Koshy }; 1830cfab8ddSJoseph Koshy 184e8f021a3SHiren Panchasara static const struct pmc_event_descr atom_silvermont_event_table[] = 185e8f021a3SHiren Panchasara { 186e8f021a3SHiren Panchasara __PMC_EV_ALIAS_ATOM_SILVERMONT() 187e8f021a3SHiren Panchasara }; 188e8f021a3SHiren Panchasara 1890cfab8ddSJoseph Koshy static const struct pmc_event_descr core_event_table[] = 1900cfab8ddSJoseph Koshy { 1910cfab8ddSJoseph Koshy __PMC_EV_ALIAS_CORE() 1920cfab8ddSJoseph Koshy }; 1930cfab8ddSJoseph Koshy 1940cfab8ddSJoseph Koshy 1950cfab8ddSJoseph Koshy static const struct pmc_event_descr core2_event_table[] = 1960cfab8ddSJoseph Koshy { 1970cfab8ddSJoseph Koshy __PMC_EV_ALIAS_CORE2() 1980cfab8ddSJoseph Koshy }; 1990cfab8ddSJoseph Koshy 200597979c4SJeff Roberson static const struct pmc_event_descr corei7_event_table[] = 201597979c4SJeff Roberson { 202597979c4SJeff Roberson __PMC_EV_ALIAS_COREI7() 203597979c4SJeff Roberson }; 204597979c4SJeff Roberson 20549fe48abSKonstantin Belousov static const struct pmc_event_descr nehalem_ex_event_table[] = 20649fe48abSKonstantin Belousov { 20749fe48abSKonstantin Belousov __PMC_EV_ALIAS_COREI7() 20849fe48abSKonstantin Belousov }; 20949fe48abSKonstantin Belousov 210cc0c1555SSean Bruno static const struct pmc_event_descr haswell_event_table[] = 211cc0c1555SSean Bruno { 212cc0c1555SSean Bruno __PMC_EV_ALIAS_HASWELL() 213cc0c1555SSean Bruno }; 214cc0c1555SSean Bruno 215d95b3509SRandall Stewart static const struct pmc_event_descr haswell_xeon_event_table[] = 216d95b3509SRandall Stewart { 217d95b3509SRandall Stewart __PMC_EV_ALIAS_HASWELL_XEON() 218d95b3509SRandall Stewart }; 219d95b3509SRandall Stewart 220d95b3509SRandall Stewart 2211e862e5aSFabien Thomas static const struct pmc_event_descr ivybridge_event_table[] = 2221e862e5aSFabien Thomas { 2231e862e5aSFabien Thomas __PMC_EV_ALIAS_IVYBRIDGE() 2241e862e5aSFabien Thomas }; 2251e862e5aSFabien Thomas 2263f929d8cSSean Bruno static const struct pmc_event_descr ivybridge_xeon_event_table[] = 2273f929d8cSSean Bruno { 2283f929d8cSSean Bruno __PMC_EV_ALIAS_IVYBRIDGE_XEON() 2293f929d8cSSean Bruno }; 2303f929d8cSSean Bruno 23178d763a2SDavide Italiano static const struct pmc_event_descr sandybridge_event_table[] = 23278d763a2SDavide Italiano { 23378d763a2SDavide Italiano __PMC_EV_ALIAS_SANDYBRIDGE() 23478d763a2SDavide Italiano }; 23578d763a2SDavide Italiano 236fabe02f5SSean Bruno static const struct pmc_event_descr sandybridge_xeon_event_table[] = 237fabe02f5SSean Bruno { 238fabe02f5SSean Bruno __PMC_EV_ALIAS_SANDYBRIDGE_XEON() 239fabe02f5SSean Bruno }; 240fabe02f5SSean Bruno 2411fa7f10bSFabien Thomas static const struct pmc_event_descr westmere_event_table[] = 2421fa7f10bSFabien Thomas { 2431fa7f10bSFabien Thomas __PMC_EV_ALIAS_WESTMERE() 2441fa7f10bSFabien Thomas }; 2451fa7f10bSFabien Thomas 24649fe48abSKonstantin Belousov static const struct pmc_event_descr westmere_ex_event_table[] = 24749fe48abSKonstantin Belousov { 24849fe48abSKonstantin Belousov __PMC_EV_ALIAS_WESTMERE() 24949fe48abSKonstantin Belousov }; 25049fe48abSKonstantin Belousov 2511fa7f10bSFabien Thomas static const struct pmc_event_descr corei7uc_event_table[] = 2521fa7f10bSFabien Thomas { 2531fa7f10bSFabien Thomas __PMC_EV_ALIAS_COREI7UC() 2541fa7f10bSFabien Thomas }; 2551fa7f10bSFabien Thomas 256cc0c1555SSean Bruno static const struct pmc_event_descr haswelluc_event_table[] = 257cc0c1555SSean Bruno { 258cc0c1555SSean Bruno __PMC_EV_ALIAS_HASWELLUC() 259cc0c1555SSean Bruno }; 260cc0c1555SSean Bruno 26178d763a2SDavide Italiano static const struct pmc_event_descr sandybridgeuc_event_table[] = 26278d763a2SDavide Italiano { 26378d763a2SDavide Italiano __PMC_EV_ALIAS_SANDYBRIDGEUC() 26478d763a2SDavide Italiano }; 26578d763a2SDavide Italiano 2661fa7f10bSFabien Thomas static const struct pmc_event_descr westmereuc_event_table[] = 2671fa7f10bSFabien Thomas { 2681fa7f10bSFabien Thomas __PMC_EV_ALIAS_WESTMEREUC() 2691fa7f10bSFabien Thomas }; 2701fa7f10bSFabien Thomas 271*bc88bb2bSRuslan Bukin static const struct pmc_event_descr cortex_a53_event_table[] = 272*bc88bb2bSRuslan Bukin { 273*bc88bb2bSRuslan Bukin __PMC_EV_ALIAS_ARMV8_CORTEX_A53() 274*bc88bb2bSRuslan Bukin }; 275*bc88bb2bSRuslan Bukin 276*bc88bb2bSRuslan Bukin static const struct pmc_event_descr cortex_a57_event_table[] = 277*bc88bb2bSRuslan Bukin { 278*bc88bb2bSRuslan Bukin __PMC_EV_ALIAS_ARMV8_CORTEX_A57() 279*bc88bb2bSRuslan Bukin }; 280*bc88bb2bSRuslan Bukin 2810cfab8ddSJoseph Koshy /* 2820cfab8ddSJoseph Koshy * PMC_MDEP_TABLE(NAME, PRIMARYCLASS, ADDITIONAL_CLASSES...) 2830cfab8ddSJoseph Koshy * 2840cfab8ddSJoseph Koshy * Map a CPU to the PMC classes it supports. 2850cfab8ddSJoseph Koshy */ 2860cfab8ddSJoseph Koshy #define PMC_MDEP_TABLE(N,C,...) \ 287789140c0SJoseph Koshy static const enum pmc_class N##_pmc_classes[] = { \ 288789140c0SJoseph Koshy PMC_CLASS_##C, __VA_ARGS__ \ 289789140c0SJoseph Koshy } 290789140c0SJoseph Koshy 291f5f9340bSFabien Thomas PMC_MDEP_TABLE(atom, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 292e8f021a3SHiren Panchasara PMC_MDEP_TABLE(atom_silvermont, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 293f5f9340bSFabien Thomas PMC_MDEP_TABLE(core, IAP, PMC_CLASS_SOFT, PMC_CLASS_TSC); 294f5f9340bSFabien Thomas PMC_MDEP_TABLE(core2, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 295f5f9340bSFabien Thomas PMC_MDEP_TABLE(corei7, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 29649fe48abSKonstantin Belousov PMC_MDEP_TABLE(nehalem_ex, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 297cc0c1555SSean Bruno PMC_MDEP_TABLE(haswell, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 298d95b3509SRandall Stewart PMC_MDEP_TABLE(haswell_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 2991e862e5aSFabien Thomas PMC_MDEP_TABLE(ivybridge, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 3003f929d8cSSean Bruno PMC_MDEP_TABLE(ivybridge_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 301f5f9340bSFabien Thomas PMC_MDEP_TABLE(sandybridge, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 302fabe02f5SSean Bruno PMC_MDEP_TABLE(sandybridge_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 303f5f9340bSFabien Thomas PMC_MDEP_TABLE(westmere, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 30449fe48abSKonstantin Belousov PMC_MDEP_TABLE(westmere_ex, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 305f5f9340bSFabien Thomas PMC_MDEP_TABLE(k7, K7, PMC_CLASS_SOFT, PMC_CLASS_TSC); 306f5f9340bSFabien Thomas PMC_MDEP_TABLE(k8, K8, PMC_CLASS_SOFT, PMC_CLASS_TSC); 307f5f9340bSFabien Thomas PMC_MDEP_TABLE(p4, P4, PMC_CLASS_SOFT, PMC_CLASS_TSC); 308f5f9340bSFabien Thomas PMC_MDEP_TABLE(p5, P5, PMC_CLASS_SOFT, PMC_CLASS_TSC); 309f5f9340bSFabien Thomas PMC_MDEP_TABLE(p6, P6, PMC_CLASS_SOFT, PMC_CLASS_TSC); 310f5f9340bSFabien Thomas PMC_MDEP_TABLE(xscale, XSCALE, PMC_CLASS_SOFT, PMC_CLASS_XSCALE); 3116411d14dSRuslan Bukin PMC_MDEP_TABLE(armv7, ARMV7, PMC_CLASS_SOFT, PMC_CLASS_ARMV7); 312*bc88bb2bSRuslan Bukin PMC_MDEP_TABLE(cortex_a53, ARMV8, PMC_CLASS_SOFT, PMC_CLASS_ARMV8); 313*bc88bb2bSRuslan Bukin PMC_MDEP_TABLE(cortex_a57, ARMV8, PMC_CLASS_SOFT, PMC_CLASS_ARMV8); 314f5f9340bSFabien Thomas PMC_MDEP_TABLE(mips24k, MIPS24K, PMC_CLASS_SOFT, PMC_CLASS_MIPS24K); 315f6e6460dSAdrian Chadd PMC_MDEP_TABLE(mips74k, MIPS74K, PMC_CLASS_SOFT, PMC_CLASS_MIPS74K); 316f5f9340bSFabien Thomas PMC_MDEP_TABLE(octeon, OCTEON, PMC_CLASS_SOFT, PMC_CLASS_OCTEON); 317a7452468SJustin Hibbits PMC_MDEP_TABLE(ppc7450, PPC7450, PMC_CLASS_SOFT, PMC_CLASS_PPC7450, PMC_CLASS_TSC); 318a7452468SJustin Hibbits PMC_MDEP_TABLE(ppc970, PPC970, PMC_CLASS_SOFT, PMC_CLASS_PPC970, PMC_CLASS_TSC); 319a7452468SJustin Hibbits PMC_MDEP_TABLE(e500, E500, PMC_CLASS_SOFT, PMC_CLASS_E500, PMC_CLASS_TSC); 320f5f9340bSFabien Thomas PMC_MDEP_TABLE(generic, SOFT, PMC_CLASS_SOFT); 321789140c0SJoseph Koshy 322789140c0SJoseph Koshy static const struct pmc_event_descr tsc_event_table[] = 323789140c0SJoseph Koshy { 324789140c0SJoseph Koshy __PMC_EV_TSC() 325789140c0SJoseph Koshy }; 326789140c0SJoseph Koshy 327789140c0SJoseph Koshy #undef PMC_CLASS_TABLE_DESC 3280cfab8ddSJoseph Koshy #define PMC_CLASS_TABLE_DESC(NAME, CLASS, EVENTS, ALLOCATOR) \ 3290cfab8ddSJoseph Koshy static const struct pmc_class_descr NAME##_class_table_descr = \ 3300cfab8ddSJoseph Koshy { \ 3310cfab8ddSJoseph Koshy .pm_evc_name = #CLASS "-", \ 3320cfab8ddSJoseph Koshy .pm_evc_name_size = sizeof(#CLASS "-") - 1, \ 3330cfab8ddSJoseph Koshy .pm_evc_class = PMC_CLASS_##CLASS , \ 3340cfab8ddSJoseph Koshy .pm_evc_event_table = EVENTS##_event_table , \ 335789140c0SJoseph Koshy .pm_evc_event_table_size = \ 3360cfab8ddSJoseph Koshy PMC_EVENT_TABLE_SIZE(EVENTS), \ 3370cfab8ddSJoseph Koshy .pm_evc_allocate_pmc = ALLOCATOR##_allocate_pmc \ 338789140c0SJoseph Koshy } 339789140c0SJoseph Koshy 340789140c0SJoseph Koshy #if defined(__i386__) || defined(__amd64__) 3410cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(iaf, IAF, iaf, iaf); 3420cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(atom, IAP, atom, iap); 343e8f021a3SHiren Panchasara PMC_CLASS_TABLE_DESC(atom_silvermont, IAP, atom_silvermont, iap); 3440cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(core, IAP, core, iap); 3450cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(core2, IAP, core2, iap); 346597979c4SJeff Roberson PMC_CLASS_TABLE_DESC(corei7, IAP, corei7, iap); 34749fe48abSKonstantin Belousov PMC_CLASS_TABLE_DESC(nehalem_ex, IAP, nehalem_ex, iap); 348cc0c1555SSean Bruno PMC_CLASS_TABLE_DESC(haswell, IAP, haswell, iap); 349ae9975dbSRyan Stone PMC_CLASS_TABLE_DESC(haswell_xeon, IAP, haswell_xeon, iap); 3501e862e5aSFabien Thomas PMC_CLASS_TABLE_DESC(ivybridge, IAP, ivybridge, iap); 3513f929d8cSSean Bruno PMC_CLASS_TABLE_DESC(ivybridge_xeon, IAP, ivybridge_xeon, iap); 35278d763a2SDavide Italiano PMC_CLASS_TABLE_DESC(sandybridge, IAP, sandybridge, iap); 353fabe02f5SSean Bruno PMC_CLASS_TABLE_DESC(sandybridge_xeon, IAP, sandybridge_xeon, iap); 3541fa7f10bSFabien Thomas PMC_CLASS_TABLE_DESC(westmere, IAP, westmere, iap); 35549fe48abSKonstantin Belousov PMC_CLASS_TABLE_DESC(westmere_ex, IAP, westmere_ex, iap); 3561fa7f10bSFabien Thomas PMC_CLASS_TABLE_DESC(ucf, UCF, ucf, ucf); 3571fa7f10bSFabien Thomas PMC_CLASS_TABLE_DESC(corei7uc, UCP, corei7uc, ucp); 358cc0c1555SSean Bruno PMC_CLASS_TABLE_DESC(haswelluc, UCP, haswelluc, ucp); 35978d763a2SDavide Italiano PMC_CLASS_TABLE_DESC(sandybridgeuc, UCP, sandybridgeuc, ucp); 3601fa7f10bSFabien Thomas PMC_CLASS_TABLE_DESC(westmereuc, UCP, westmereuc, ucp); 361789140c0SJoseph Koshy #endif 362789140c0SJoseph Koshy #if defined(__i386__) 3630cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(k7, K7, k7, k7); 364789140c0SJoseph Koshy #endif 365789140c0SJoseph Koshy #if defined(__i386__) || defined(__amd64__) 3660cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(k8, K8, k8, k8); 3670cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(p4, P4, p4, p4); 368789140c0SJoseph Koshy #endif 3690cfab8ddSJoseph Koshy #if defined(__i386__) 3700cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(p5, P5, p5, p5); 3710cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(p6, P6, p6, p6); 3720cfab8ddSJoseph Koshy #endif 3730cfab8ddSJoseph Koshy #if defined(__i386__) || defined(__amd64__) 3740cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(tsc, TSC, tsc, tsc); 3750cfab8ddSJoseph Koshy #endif 3766411d14dSRuslan Bukin #if defined(__arm__) 3770ce207d2SRui Paulo #if defined(__XSCALE__) 3780ce207d2SRui Paulo PMC_CLASS_TABLE_DESC(xscale, XSCALE, xscale, xscale); 3790ce207d2SRui Paulo #endif 3806411d14dSRuslan Bukin PMC_CLASS_TABLE_DESC(armv7, ARMV7, armv7, armv7); 3816411d14dSRuslan Bukin #endif 382*bc88bb2bSRuslan Bukin #if defined(__aarch64__) 383*bc88bb2bSRuslan Bukin PMC_CLASS_TABLE_DESC(cortex_a53, ARMV8, cortex_a53, arm64); 384*bc88bb2bSRuslan Bukin PMC_CLASS_TABLE_DESC(cortex_a57, ARMV8, cortex_a57, arm64); 385*bc88bb2bSRuslan Bukin #endif 386660df75eSGeorge V. Neville-Neil #if defined(__mips__) 3872827d3e1SOleksandr Tymoshenko PMC_CLASS_TABLE_DESC(mips24k, MIPS24K, mips24k, mips); 388f6e6460dSAdrian Chadd PMC_CLASS_TABLE_DESC(mips74k, MIPS74K, mips74k, mips); 389c2657f80SOleksandr Tymoshenko PMC_CLASS_TABLE_DESC(octeon, OCTEON, octeon, mips); 390660df75eSGeorge V. Neville-Neil #endif /* __mips__ */ 3917b25dccaSJustin Hibbits #if defined(__powerpc__) 392169dd953SJustin Hibbits PMC_CLASS_TABLE_DESC(ppc7450, PPC7450, ppc7450, powerpc); 393169dd953SJustin Hibbits PMC_CLASS_TABLE_DESC(ppc970, PPC970, ppc970, powerpc); 394a7452468SJustin Hibbits PMC_CLASS_TABLE_DESC(e500, E500, e500, powerpc); 3957b25dccaSJustin Hibbits #endif 3967b25dccaSJustin Hibbits 397f5f9340bSFabien Thomas static struct pmc_class_descr soft_class_table_descr = 398f5f9340bSFabien Thomas { 399f5f9340bSFabien Thomas .pm_evc_name = "SOFT-", 400f5f9340bSFabien Thomas .pm_evc_name_size = sizeof("SOFT-") - 1, 401f5f9340bSFabien Thomas .pm_evc_class = PMC_CLASS_SOFT, 402f5f9340bSFabien Thomas .pm_evc_event_table = NULL, 403f5f9340bSFabien Thomas .pm_evc_event_table_size = 0, 404f5f9340bSFabien Thomas .pm_evc_allocate_pmc = soft_allocate_pmc 405f5f9340bSFabien Thomas }; 406f5f9340bSFabien Thomas 407789140c0SJoseph Koshy #undef PMC_CLASS_TABLE_DESC 408789140c0SJoseph Koshy 4090cfab8ddSJoseph Koshy static const struct pmc_class_descr **pmc_class_table; 4100cfab8ddSJoseph Koshy #define PMC_CLASS_TABLE_SIZE cpu_info.pm_nclass 4110cfab8ddSJoseph Koshy 412789140c0SJoseph Koshy static const enum pmc_class *pmc_mdep_class_list; 413789140c0SJoseph Koshy static size_t pmc_mdep_class_list_size; 414789140c0SJoseph Koshy 415ebccf1e3SJoseph Koshy /* 416ebccf1e3SJoseph Koshy * Mapping tables, mapping enumeration values to human readable 417ebccf1e3SJoseph Koshy * strings. 418ebccf1e3SJoseph Koshy */ 419ebccf1e3SJoseph Koshy 420ebccf1e3SJoseph Koshy static const char * pmc_capability_names[] = { 421ebccf1e3SJoseph Koshy #undef __PMC_CAP 422ebccf1e3SJoseph Koshy #define __PMC_CAP(N,V,D) #N , 423ebccf1e3SJoseph Koshy __PMC_CAPS() 424ebccf1e3SJoseph Koshy }; 425ebccf1e3SJoseph Koshy 426ebccf1e3SJoseph Koshy static const char * pmc_class_names[] = { 427ebccf1e3SJoseph Koshy #undef __PMC_CLASS 428ebccf1e3SJoseph Koshy #define __PMC_CLASS(C) #C , 429ebccf1e3SJoseph Koshy __PMC_CLASSES() 430ebccf1e3SJoseph Koshy }; 431ebccf1e3SJoseph Koshy 432789140c0SJoseph Koshy struct pmc_cputype_map { 433562fc14bSDimitry Andric enum pmc_cputype pm_cputype; 434789140c0SJoseph Koshy const char *pm_name; 435789140c0SJoseph Koshy }; 436789140c0SJoseph Koshy 437789140c0SJoseph Koshy static const struct pmc_cputype_map pmc_cputype_names[] = { 438ebccf1e3SJoseph Koshy #undef __PMC_CPU 439789140c0SJoseph Koshy #define __PMC_CPU(S, V, D) { .pm_cputype = PMC_CPU_##S, .pm_name = #S } , 440ebccf1e3SJoseph Koshy __PMC_CPUS() 441ebccf1e3SJoseph Koshy }; 442ebccf1e3SJoseph Koshy 443ebccf1e3SJoseph Koshy static const char * pmc_disposition_names[] = { 444ebccf1e3SJoseph Koshy #undef __PMC_DISP 445ebccf1e3SJoseph Koshy #define __PMC_DISP(D) #D , 446ebccf1e3SJoseph Koshy __PMC_DISPOSITIONS() 447ebccf1e3SJoseph Koshy }; 448ebccf1e3SJoseph Koshy 449ebccf1e3SJoseph Koshy static const char * pmc_mode_names[] = { 450ebccf1e3SJoseph Koshy #undef __PMC_MODE 451ebccf1e3SJoseph Koshy #define __PMC_MODE(M,N) #M , 452ebccf1e3SJoseph Koshy __PMC_MODES() 453ebccf1e3SJoseph Koshy }; 454ebccf1e3SJoseph Koshy 455ebccf1e3SJoseph Koshy static const char * pmc_state_names[] = { 456ebccf1e3SJoseph Koshy #undef __PMC_STATE 457ebccf1e3SJoseph Koshy #define __PMC_STATE(S) #S , 458ebccf1e3SJoseph Koshy __PMC_STATES() 459ebccf1e3SJoseph Koshy }; 460ebccf1e3SJoseph Koshy 461f5f9340bSFabien Thomas /* 462f5f9340bSFabien Thomas * Filled in by pmc_init(). 463f5f9340bSFabien Thomas */ 464f5f9340bSFabien Thomas static int pmc_syscall = -1; 465f5f9340bSFabien Thomas static struct pmc_cpuinfo cpu_info; 466f5f9340bSFabien Thomas static struct pmc_op_getdyneventinfo soft_event_info; 4671455fcd3SJoseph Koshy 468ebccf1e3SJoseph Koshy /* Event masks for events */ 469ebccf1e3SJoseph Koshy struct pmc_masks { 470ebccf1e3SJoseph Koshy const char *pm_name; 4711e862e5aSFabien Thomas const uint64_t pm_value; 472ebccf1e3SJoseph Koshy }; 473ebccf1e3SJoseph Koshy #define PMCMASK(N,V) { .pm_name = #N, .pm_value = (V) } 4741fa7f10bSFabien Thomas #define NULLMASK { .pm_name = NULL } 475ebccf1e3SJoseph Koshy 47686a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 477ebccf1e3SJoseph Koshy static int 4781e862e5aSFabien Thomas pmc_parse_mask(const struct pmc_masks *pmask, char *p, uint64_t *evmask) 479ebccf1e3SJoseph Koshy { 480ebccf1e3SJoseph Koshy const struct pmc_masks *pm; 481ebccf1e3SJoseph Koshy char *q, *r; 482ebccf1e3SJoseph Koshy int c; 483ebccf1e3SJoseph Koshy 484ebccf1e3SJoseph Koshy if (pmask == NULL) /* no mask keywords */ 485aa342b1fSJoseph Koshy return (-1); 486ebccf1e3SJoseph Koshy q = strchr(p, '='); /* skip '=' */ 487ebccf1e3SJoseph Koshy if (*++q == '\0') /* no more data */ 488aa342b1fSJoseph Koshy return (-1); 489ebccf1e3SJoseph Koshy c = 0; /* count of mask keywords seen */ 490ebccf1e3SJoseph Koshy while ((r = strsep(&q, "+")) != NULL) { 491789140c0SJoseph Koshy for (pm = pmask; pm->pm_name && strcasecmp(r, pm->pm_name); 492789140c0SJoseph Koshy pm++) 493ebccf1e3SJoseph Koshy ; 494ebccf1e3SJoseph Koshy if (pm->pm_name == NULL) /* not found */ 495aa342b1fSJoseph Koshy return (-1); 496ebccf1e3SJoseph Koshy *evmask |= pm->pm_value; 497ebccf1e3SJoseph Koshy c++; 498ebccf1e3SJoseph Koshy } 499aa342b1fSJoseph Koshy return (c); 500ebccf1e3SJoseph Koshy } 50104e9feb0SMarcel Moolenaar #endif 502ebccf1e3SJoseph Koshy 503ebccf1e3SJoseph Koshy #define KWMATCH(p,kw) (strcasecmp((p), (kw)) == 0) 504ebccf1e3SJoseph Koshy #define KWPREFIXMATCH(p,kw) (strncasecmp((p), (kw), sizeof((kw)) - 1) == 0) 505ebccf1e3SJoseph Koshy #define EV_ALIAS(N,S) { .pm_alias = N, .pm_spec = S } 506ebccf1e3SJoseph Koshy 50704e9feb0SMarcel Moolenaar #if defined(__i386__) 508ebccf1e3SJoseph Koshy 509ebccf1e3SJoseph Koshy /* 510ebccf1e3SJoseph Koshy * AMD K7 (Athlon) CPUs. 511ebccf1e3SJoseph Koshy */ 512ebccf1e3SJoseph Koshy 513ebccf1e3SJoseph Koshy static struct pmc_event_alias k7_aliases[] = { 514ebccf1e3SJoseph Koshy EV_ALIAS("branches", "k7-retired-branches"), 515ebccf1e3SJoseph Koshy EV_ALIAS("branch-mispredicts", "k7-retired-branches-mispredicted"), 516ebccf1e3SJoseph Koshy EV_ALIAS("cycles", "tsc"), 5176aa5a193SJoseph Koshy EV_ALIAS("dc-misses", "k7-dc-misses"), 518ebccf1e3SJoseph Koshy EV_ALIAS("ic-misses", "k7-ic-misses"), 519ebccf1e3SJoseph Koshy EV_ALIAS("instructions", "k7-retired-instructions"), 520ebccf1e3SJoseph Koshy EV_ALIAS("interrupts", "k7-hardware-interrupts"), 521ebccf1e3SJoseph Koshy EV_ALIAS(NULL, NULL) 522ebccf1e3SJoseph Koshy }; 523ebccf1e3SJoseph Koshy 524ebccf1e3SJoseph Koshy #define K7_KW_COUNT "count" 525ebccf1e3SJoseph Koshy #define K7_KW_EDGE "edge" 526ebccf1e3SJoseph Koshy #define K7_KW_INV "inv" 527ebccf1e3SJoseph Koshy #define K7_KW_OS "os" 528ebccf1e3SJoseph Koshy #define K7_KW_UNITMASK "unitmask" 529ebccf1e3SJoseph Koshy #define K7_KW_USR "usr" 530ebccf1e3SJoseph Koshy 531ebccf1e3SJoseph Koshy static int 532ebccf1e3SJoseph Koshy k7_allocate_pmc(enum pmc_event pe, char *ctrspec, 533ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 534ebccf1e3SJoseph Koshy { 535ebccf1e3SJoseph Koshy char *e, *p, *q; 536ebccf1e3SJoseph Koshy int c, has_unitmask; 537ebccf1e3SJoseph Koshy uint32_t count, unitmask; 538ebccf1e3SJoseph Koshy 539f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 540789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 541ebccf1e3SJoseph Koshy 542ebccf1e3SJoseph Koshy if (pe == PMC_EV_K7_DC_REFILLS_FROM_L2 || 543ebccf1e3SJoseph Koshy pe == PMC_EV_K7_DC_REFILLS_FROM_SYSTEM || 544ebccf1e3SJoseph Koshy pe == PMC_EV_K7_DC_WRITEBACKS) { 545ebccf1e3SJoseph Koshy has_unitmask = 1; 546f263522aSJoseph Koshy unitmask = AMD_PMC_UNITMASK_MOESI; 547ebccf1e3SJoseph Koshy } else 548ebccf1e3SJoseph Koshy unitmask = has_unitmask = 0; 549ebccf1e3SJoseph Koshy 550ebccf1e3SJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 551ebccf1e3SJoseph Koshy if (KWPREFIXMATCH(p, K7_KW_COUNT "=")) { 552ebccf1e3SJoseph Koshy q = strchr(p, '='); 553ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 554aa342b1fSJoseph Koshy return (-1); 555ebccf1e3SJoseph Koshy 556ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 557ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 558aa342b1fSJoseph Koshy return (-1); 559ebccf1e3SJoseph Koshy 560ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 561f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config |= 562f263522aSJoseph Koshy AMD_PMC_TO_COUNTER(count); 563ebccf1e3SJoseph Koshy 564ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_EDGE)) { 565ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 566ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_INV)) { 567ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 568ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_OS)) { 569ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 570ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, K7_KW_UNITMASK "=")) { 571ebccf1e3SJoseph Koshy if (has_unitmask == 0) 572aa342b1fSJoseph Koshy return (-1); 573ebccf1e3SJoseph Koshy unitmask = 0; 574ebccf1e3SJoseph Koshy q = strchr(p, '='); 575ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 576aa342b1fSJoseph Koshy return (-1); 577ebccf1e3SJoseph Koshy 578ebccf1e3SJoseph Koshy while ((c = tolower(*q++)) != 0) 579ebccf1e3SJoseph Koshy if (c == 'm') 580f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_M; 581ebccf1e3SJoseph Koshy else if (c == 'o') 582f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_O; 583ebccf1e3SJoseph Koshy else if (c == 'e') 584f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_E; 585ebccf1e3SJoseph Koshy else if (c == 's') 586f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_S; 587ebccf1e3SJoseph Koshy else if (c == 'i') 588f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_I; 589ebccf1e3SJoseph Koshy else if (c == '+') 590ebccf1e3SJoseph Koshy continue; 591ebccf1e3SJoseph Koshy else 592aa342b1fSJoseph Koshy return (-1); 593ebccf1e3SJoseph Koshy 594ebccf1e3SJoseph Koshy if (unitmask == 0) 595aa342b1fSJoseph Koshy return (-1); 596ebccf1e3SJoseph Koshy 597ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_USR)) { 598ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 599ebccf1e3SJoseph Koshy } else 600aa342b1fSJoseph Koshy return (-1); 601ebccf1e3SJoseph Koshy } 602ebccf1e3SJoseph Koshy 603ebccf1e3SJoseph Koshy if (has_unitmask) { 604ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 605f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config |= 606f263522aSJoseph Koshy AMD_PMC_TO_UNITMASK(unitmask); 607ebccf1e3SJoseph Koshy } 608ebccf1e3SJoseph Koshy 609aa342b1fSJoseph Koshy return (0); 610ebccf1e3SJoseph Koshy 611ebccf1e3SJoseph Koshy } 612ebccf1e3SJoseph Koshy 613f263522aSJoseph Koshy #endif 614f263522aSJoseph Koshy 61586a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 616f263522aSJoseph Koshy 617f263522aSJoseph Koshy /* 6180cfab8ddSJoseph Koshy * Intel Core (Family 6, Model E) PMCs. 6190cfab8ddSJoseph Koshy */ 6200cfab8ddSJoseph Koshy 6210cfab8ddSJoseph Koshy static struct pmc_event_alias core_aliases[] = { 6220cfab8ddSJoseph Koshy EV_ALIAS("branches", "iap-br-instr-ret"), 6230cfab8ddSJoseph Koshy EV_ALIAS("branch-mispredicts", "iap-br-mispred-ret"), 6240cfab8ddSJoseph Koshy EV_ALIAS("cycles", "tsc-tsc"), 6250cfab8ddSJoseph Koshy EV_ALIAS("ic-misses", "iap-icache-misses"), 6260cfab8ddSJoseph Koshy EV_ALIAS("instructions", "iap-instr-ret"), 6270cfab8ddSJoseph Koshy EV_ALIAS("interrupts", "iap-core-hw-int-rx"), 6280cfab8ddSJoseph Koshy EV_ALIAS("unhalted-cycles", "iap-unhalted-core-cycles"), 6290cfab8ddSJoseph Koshy EV_ALIAS(NULL, NULL) 6300cfab8ddSJoseph Koshy }; 6310cfab8ddSJoseph Koshy 6320cfab8ddSJoseph Koshy /* 6330cfab8ddSJoseph Koshy * Intel Core2 (Family 6, Model F), Core2Extreme (Family 6, Model 17H) 6340cfab8ddSJoseph Koshy * and Atom (Family 6, model 1CH) PMCs. 635791f5d5bSJoseph Koshy * 636791f5d5bSJoseph Koshy * We map aliases to events on the fixed-function counters if these 637791f5d5bSJoseph Koshy * are present. Note that not all CPUs in this family contain fixed-function 638791f5d5bSJoseph Koshy * counters. 6390cfab8ddSJoseph Koshy */ 6400cfab8ddSJoseph Koshy 6410cfab8ddSJoseph Koshy static struct pmc_event_alias core2_aliases[] = { 6420cfab8ddSJoseph Koshy EV_ALIAS("branches", "iap-br-inst-retired.any"), 6430cfab8ddSJoseph Koshy EV_ALIAS("branch-mispredicts", "iap-br-inst-retired.mispred"), 6440cfab8ddSJoseph Koshy EV_ALIAS("cycles", "tsc-tsc"), 6450cfab8ddSJoseph Koshy EV_ALIAS("ic-misses", "iap-l1i-misses"), 6460cfab8ddSJoseph Koshy EV_ALIAS("instructions", "iaf-instr-retired.any"), 6470cfab8ddSJoseph Koshy EV_ALIAS("interrupts", "iap-hw-int-rcv"), 6480cfab8ddSJoseph Koshy EV_ALIAS("unhalted-cycles", "iaf-cpu-clk-unhalted.core"), 6490cfab8ddSJoseph Koshy EV_ALIAS(NULL, NULL) 6500cfab8ddSJoseph Koshy }; 651791f5d5bSJoseph Koshy 652791f5d5bSJoseph Koshy static struct pmc_event_alias core2_aliases_without_iaf[] = { 653791f5d5bSJoseph Koshy EV_ALIAS("branches", "iap-br-inst-retired.any"), 654791f5d5bSJoseph Koshy EV_ALIAS("branch-mispredicts", "iap-br-inst-retired.mispred"), 655791f5d5bSJoseph Koshy EV_ALIAS("cycles", "tsc-tsc"), 656791f5d5bSJoseph Koshy EV_ALIAS("ic-misses", "iap-l1i-misses"), 657791f5d5bSJoseph Koshy EV_ALIAS("instructions", "iap-inst-retired.any_p"), 658791f5d5bSJoseph Koshy EV_ALIAS("interrupts", "iap-hw-int-rcv"), 659791f5d5bSJoseph Koshy EV_ALIAS("unhalted-cycles", "iap-cpu-clk-unhalted.core_p"), 660791f5d5bSJoseph Koshy EV_ALIAS(NULL, NULL) 661791f5d5bSJoseph Koshy }; 662791f5d5bSJoseph Koshy 6630cfab8ddSJoseph Koshy #define atom_aliases core2_aliases 664791f5d5bSJoseph Koshy #define atom_aliases_without_iaf core2_aliases_without_iaf 665e8f021a3SHiren Panchasara #define atom_silvermont_aliases core2_aliases 666e8f021a3SHiren Panchasara #define atom_silvermont_aliases_without_iaf core2_aliases_without_iaf 667597979c4SJeff Roberson #define corei7_aliases core2_aliases 668791f5d5bSJoseph Koshy #define corei7_aliases_without_iaf core2_aliases_without_iaf 66949fe48abSKonstantin Belousov #define nehalem_ex_aliases core2_aliases 67049fe48abSKonstantin Belousov #define nehalem_ex_aliases_without_iaf core2_aliases_without_iaf 671cc0c1555SSean Bruno #define haswell_aliases core2_aliases 672cc0c1555SSean Bruno #define haswell_aliases_without_iaf core2_aliases_without_iaf 673d95b3509SRandall Stewart #define haswell_xeon_aliases core2_aliases 674d95b3509SRandall Stewart #define haswell_xeon_aliases_without_iaf core2_aliases_without_iaf 6751e862e5aSFabien Thomas #define ivybridge_aliases core2_aliases 6761e862e5aSFabien Thomas #define ivybridge_aliases_without_iaf core2_aliases_without_iaf 6773f929d8cSSean Bruno #define ivybridge_xeon_aliases core2_aliases 6783f929d8cSSean Bruno #define ivybridge_xeon_aliases_without_iaf core2_aliases_without_iaf 67978d763a2SDavide Italiano #define sandybridge_aliases core2_aliases 68078d763a2SDavide Italiano #define sandybridge_aliases_without_iaf core2_aliases_without_iaf 681fabe02f5SSean Bruno #define sandybridge_xeon_aliases core2_aliases 682fabe02f5SSean Bruno #define sandybridge_xeon_aliases_without_iaf core2_aliases_without_iaf 6831fa7f10bSFabien Thomas #define westmere_aliases core2_aliases 6841fa7f10bSFabien Thomas #define westmere_aliases_without_iaf core2_aliases_without_iaf 68549fe48abSKonstantin Belousov #define westmere_ex_aliases core2_aliases 68649fe48abSKonstantin Belousov #define westmere_ex_aliases_without_iaf core2_aliases_without_iaf 6870cfab8ddSJoseph Koshy 6880cfab8ddSJoseph Koshy #define IAF_KW_OS "os" 6890cfab8ddSJoseph Koshy #define IAF_KW_USR "usr" 6900cfab8ddSJoseph Koshy #define IAF_KW_ANYTHREAD "anythread" 6910cfab8ddSJoseph Koshy 6920cfab8ddSJoseph Koshy /* 6930cfab8ddSJoseph Koshy * Parse an event specifier for Intel fixed function counters. 6940cfab8ddSJoseph Koshy */ 6950cfab8ddSJoseph Koshy static int 6960cfab8ddSJoseph Koshy iaf_allocate_pmc(enum pmc_event pe, char *ctrspec, 6970cfab8ddSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 6980cfab8ddSJoseph Koshy { 6990cfab8ddSJoseph Koshy char *p; 7000cfab8ddSJoseph Koshy 7010cfab8ddSJoseph Koshy (void) pe; 7020cfab8ddSJoseph Koshy 7030cfab8ddSJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 7040cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iaf.pm_iaf_flags = 0; 7050cfab8ddSJoseph Koshy 7060cfab8ddSJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 7070cfab8ddSJoseph Koshy if (KWMATCH(p, IAF_KW_OS)) 7080cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 7090cfab8ddSJoseph Koshy else if (KWMATCH(p, IAF_KW_USR)) 7100cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 7110cfab8ddSJoseph Koshy else if (KWMATCH(p, IAF_KW_ANYTHREAD)) 7120cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iaf.pm_iaf_flags |= IAF_ANY; 7130cfab8ddSJoseph Koshy else 7140cfab8ddSJoseph Koshy return (-1); 7150cfab8ddSJoseph Koshy } 7160cfab8ddSJoseph Koshy 7170cfab8ddSJoseph Koshy return (0); 7180cfab8ddSJoseph Koshy } 7190cfab8ddSJoseph Koshy 7200cfab8ddSJoseph Koshy /* 7210cfab8ddSJoseph Koshy * Core/Core2 support. 7220cfab8ddSJoseph Koshy */ 7230cfab8ddSJoseph Koshy 7240cfab8ddSJoseph Koshy #define IAP_KW_AGENT "agent" 7250cfab8ddSJoseph Koshy #define IAP_KW_ANYTHREAD "anythread" 7260cfab8ddSJoseph Koshy #define IAP_KW_CACHESTATE "cachestate" 7270cfab8ddSJoseph Koshy #define IAP_KW_CMASK "cmask" 7280cfab8ddSJoseph Koshy #define IAP_KW_CORE "core" 7290cfab8ddSJoseph Koshy #define IAP_KW_EDGE "edge" 7300cfab8ddSJoseph Koshy #define IAP_KW_INV "inv" 7310cfab8ddSJoseph Koshy #define IAP_KW_OS "os" 7320cfab8ddSJoseph Koshy #define IAP_KW_PREFETCH "prefetch" 7330cfab8ddSJoseph Koshy #define IAP_KW_SNOOPRESPONSE "snoopresponse" 7340cfab8ddSJoseph Koshy #define IAP_KW_SNOOPTYPE "snooptype" 7350cfab8ddSJoseph Koshy #define IAP_KW_TRANSITION "trans" 7360cfab8ddSJoseph Koshy #define IAP_KW_USR "usr" 7371fa7f10bSFabien Thomas #define IAP_KW_RSP "rsp" 7380cfab8ddSJoseph Koshy 7390cfab8ddSJoseph Koshy static struct pmc_masks iap_core_mask[] = { 7400cfab8ddSJoseph Koshy PMCMASK(all, (0x3 << 14)), 7410cfab8ddSJoseph Koshy PMCMASK(this, (0x1 << 14)), 7420cfab8ddSJoseph Koshy NULLMASK 7430cfab8ddSJoseph Koshy }; 7440cfab8ddSJoseph Koshy 7450cfab8ddSJoseph Koshy static struct pmc_masks iap_agent_mask[] = { 7460cfab8ddSJoseph Koshy PMCMASK(this, 0), 7470cfab8ddSJoseph Koshy PMCMASK(any, (0x1 << 13)), 7480cfab8ddSJoseph Koshy NULLMASK 7490cfab8ddSJoseph Koshy }; 7500cfab8ddSJoseph Koshy 7510cfab8ddSJoseph Koshy static struct pmc_masks iap_prefetch_mask[] = { 7520cfab8ddSJoseph Koshy PMCMASK(both, (0x3 << 12)), 7530cfab8ddSJoseph Koshy PMCMASK(only, (0x1 << 12)), 7540cfab8ddSJoseph Koshy PMCMASK(exclude, 0), 7550cfab8ddSJoseph Koshy NULLMASK 7560cfab8ddSJoseph Koshy }; 7570cfab8ddSJoseph Koshy 7580cfab8ddSJoseph Koshy static struct pmc_masks iap_cachestate_mask[] = { 7590cfab8ddSJoseph Koshy PMCMASK(i, (1 << 8)), 7600cfab8ddSJoseph Koshy PMCMASK(s, (1 << 9)), 7610cfab8ddSJoseph Koshy PMCMASK(e, (1 << 10)), 7620cfab8ddSJoseph Koshy PMCMASK(m, (1 << 11)), 7630cfab8ddSJoseph Koshy NULLMASK 7640cfab8ddSJoseph Koshy }; 7650cfab8ddSJoseph Koshy 7660cfab8ddSJoseph Koshy static struct pmc_masks iap_snoopresponse_mask[] = { 7670cfab8ddSJoseph Koshy PMCMASK(clean, (1 << 8)), 7680cfab8ddSJoseph Koshy PMCMASK(hit, (1 << 9)), 7690cfab8ddSJoseph Koshy PMCMASK(hitm, (1 << 11)), 7700cfab8ddSJoseph Koshy NULLMASK 7710cfab8ddSJoseph Koshy }; 7720cfab8ddSJoseph Koshy 7730cfab8ddSJoseph Koshy static struct pmc_masks iap_snooptype_mask[] = { 7740cfab8ddSJoseph Koshy PMCMASK(cmp2s, (1 << 8)), 7750cfab8ddSJoseph Koshy PMCMASK(cmp2i, (1 << 9)), 7760cfab8ddSJoseph Koshy NULLMASK 7770cfab8ddSJoseph Koshy }; 7780cfab8ddSJoseph Koshy 7790cfab8ddSJoseph Koshy static struct pmc_masks iap_transition_mask[] = { 7800cfab8ddSJoseph Koshy PMCMASK(any, 0x00), 7810cfab8ddSJoseph Koshy PMCMASK(frequency, 0x10), 7820cfab8ddSJoseph Koshy NULLMASK 7830cfab8ddSJoseph Koshy }; 7840cfab8ddSJoseph Koshy 7851e862e5aSFabien Thomas static struct pmc_masks iap_rsp_mask_i7_wm[] = { 7861fa7f10bSFabien Thomas PMCMASK(DMND_DATA_RD, (1 << 0)), 7871fa7f10bSFabien Thomas PMCMASK(DMND_RFO, (1 << 1)), 7881fa7f10bSFabien Thomas PMCMASK(DMND_IFETCH, (1 << 2)), 7891fa7f10bSFabien Thomas PMCMASK(WB, (1 << 3)), 7901fa7f10bSFabien Thomas PMCMASK(PF_DATA_RD, (1 << 4)), 7911fa7f10bSFabien Thomas PMCMASK(PF_RFO, (1 << 5)), 7921fa7f10bSFabien Thomas PMCMASK(PF_IFETCH, (1 << 6)), 7931fa7f10bSFabien Thomas PMCMASK(OTHER, (1 << 7)), 7941fa7f10bSFabien Thomas PMCMASK(UNCORE_HIT, (1 << 8)), 7951fa7f10bSFabien Thomas PMCMASK(OTHER_CORE_HIT_SNP, (1 << 9)), 7961fa7f10bSFabien Thomas PMCMASK(OTHER_CORE_HITM, (1 << 10)), 7971fa7f10bSFabien Thomas PMCMASK(REMOTE_CACHE_FWD, (1 << 12)), 7981fa7f10bSFabien Thomas PMCMASK(REMOTE_DRAM, (1 << 13)), 7991fa7f10bSFabien Thomas PMCMASK(LOCAL_DRAM, (1 << 14)), 8001fa7f10bSFabien Thomas PMCMASK(NON_DRAM, (1 << 15)), 8011fa7f10bSFabien Thomas NULLMASK 8021fa7f10bSFabien Thomas }; 8031fa7f10bSFabien Thomas 804fabe02f5SSean Bruno static struct pmc_masks iap_rsp_mask_sb_sbx_ib[] = { 8051e862e5aSFabien Thomas PMCMASK(REQ_DMND_DATA_RD, (1ULL << 0)), 8061e862e5aSFabien Thomas PMCMASK(REQ_DMND_RFO, (1ULL << 1)), 8071e862e5aSFabien Thomas PMCMASK(REQ_DMND_IFETCH, (1ULL << 2)), 8081e862e5aSFabien Thomas PMCMASK(REQ_WB, (1ULL << 3)), 8091e862e5aSFabien Thomas PMCMASK(REQ_PF_DATA_RD, (1ULL << 4)), 8101e862e5aSFabien Thomas PMCMASK(REQ_PF_RFO, (1ULL << 5)), 8111e862e5aSFabien Thomas PMCMASK(REQ_PF_IFETCH, (1ULL << 6)), 8121e862e5aSFabien Thomas PMCMASK(REQ_PF_LLC_DATA_RD, (1ULL << 7)), 8131e862e5aSFabien Thomas PMCMASK(REQ_PF_LLC_RFO, (1ULL << 8)), 8141e862e5aSFabien Thomas PMCMASK(REQ_PF_LLC_IFETCH, (1ULL << 9)), 8151e862e5aSFabien Thomas PMCMASK(REQ_BUS_LOCKS, (1ULL << 10)), 8161e862e5aSFabien Thomas PMCMASK(REQ_STRM_ST, (1ULL << 11)), 8171e862e5aSFabien Thomas PMCMASK(REQ_OTHER, (1ULL << 15)), 8181e862e5aSFabien Thomas PMCMASK(RES_ANY, (1ULL << 16)), 8191e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_SUPP, (1ULL << 17)), 8201e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_LLC_HITM, (1ULL << 18)), 8211e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_LLC_HITE, (1ULL << 19)), 8221e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_LLC_HITS, (1ULL << 20)), 8231e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_LLC_HITF, (1ULL << 21)), 8241e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_LOCAL, (1ULL << 22)), 825cdfd0cc8SSean Bruno PMCMASK(RES_SNOOP_SNP_NONE, (1ULL << 31)), 8261e862e5aSFabien Thomas PMCMASK(RES_SNOOP_SNP_NO_NEEDED,(1ULL << 32)), 8271e862e5aSFabien Thomas PMCMASK(RES_SNOOP_SNP_MISS, (1ULL << 33)), 8281e862e5aSFabien Thomas PMCMASK(RES_SNOOP_HIT_NO_FWD, (1ULL << 34)), 8291e862e5aSFabien Thomas PMCMASK(RES_SNOOP_HIT_FWD, (1ULL << 35)), 8301e862e5aSFabien Thomas PMCMASK(RES_SNOOP_HITM, (1ULL << 36)), 8311e862e5aSFabien Thomas PMCMASK(RES_NON_DRAM, (1ULL << 37)), 8321e862e5aSFabien Thomas NULLMASK 8331e862e5aSFabien Thomas }; 8341e862e5aSFabien Thomas 835cc0c1555SSean Bruno static struct pmc_masks iap_rsp_mask_haswell[] = { 836cc0c1555SSean Bruno PMCMASK(REQ_DMND_DATA_RD, (1ULL << 0)), 837cc0c1555SSean Bruno PMCMASK(REQ_DMND_RFO, (1ULL << 1)), 838cc0c1555SSean Bruno PMCMASK(REQ_DMND_IFETCH, (1ULL << 2)), 839cc0c1555SSean Bruno PMCMASK(REQ_PF_DATA_RD, (1ULL << 4)), 840cc0c1555SSean Bruno PMCMASK(REQ_PF_RFO, (1ULL << 5)), 841cc0c1555SSean Bruno PMCMASK(REQ_PF_IFETCH, (1ULL << 6)), 842cc0c1555SSean Bruno PMCMASK(REQ_OTHER, (1ULL << 15)), 843cc0c1555SSean Bruno PMCMASK(RES_ANY, (1ULL << 16)), 844cc0c1555SSean Bruno PMCMASK(RES_SUPPLIER_SUPP, (1ULL << 17)), 845cc0c1555SSean Bruno PMCMASK(RES_SUPPLIER_LLC_HITM, (1ULL << 18)), 846cc0c1555SSean Bruno PMCMASK(RES_SUPPLIER_LLC_HITE, (1ULL << 19)), 847cc0c1555SSean Bruno PMCMASK(RES_SUPPLIER_LLC_HITS, (1ULL << 20)), 848cc0c1555SSean Bruno PMCMASK(RES_SUPPLIER_LLC_HITF, (1ULL << 21)), 849cc0c1555SSean Bruno PMCMASK(RES_SUPPLIER_LOCAL, (1ULL << 22)), 850cc0c1555SSean Bruno PMCMASK(RES_SNOOP_SNP_NONE, (1ULL << 31)), 851cc0c1555SSean Bruno PMCMASK(RES_SNOOP_SNP_NO_NEEDED,(1ULL << 32)), 852cc0c1555SSean Bruno PMCMASK(RES_SNOOP_SNP_MISS, (1ULL << 33)), 853cc0c1555SSean Bruno PMCMASK(RES_SNOOP_HIT_NO_FWD, (1ULL << 34)), 854cc0c1555SSean Bruno PMCMASK(RES_SNOOP_HIT_FWD, (1ULL << 35)), 855cc0c1555SSean Bruno PMCMASK(RES_SNOOP_HITM, (1ULL << 36)), 856cc0c1555SSean Bruno PMCMASK(RES_NON_DRAM, (1ULL << 37)), 857cc0c1555SSean Bruno NULLMASK 858cc0c1555SSean Bruno }; 859cc0c1555SSean Bruno 8600cfab8ddSJoseph Koshy static int 8610cfab8ddSJoseph Koshy iap_allocate_pmc(enum pmc_event pe, char *ctrspec, 8620cfab8ddSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 8630cfab8ddSJoseph Koshy { 8640cfab8ddSJoseph Koshy char *e, *p, *q; 8651e862e5aSFabien Thomas uint64_t cachestate, evmask, rsp; 8660cfab8ddSJoseph Koshy int count, n; 8670cfab8ddSJoseph Koshy 8680cfab8ddSJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE | 8690cfab8ddSJoseph Koshy PMC_CAP_QUALIFIER); 8700cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config = 0; 8710cfab8ddSJoseph Koshy 8721fa7f10bSFabien Thomas cachestate = evmask = rsp = 0; 8730cfab8ddSJoseph Koshy 8740cfab8ddSJoseph Koshy /* Parse additional modifiers if present */ 8750cfab8ddSJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 8760cfab8ddSJoseph Koshy 8770cfab8ddSJoseph Koshy n = 0; 8780cfab8ddSJoseph Koshy if (KWPREFIXMATCH(p, IAP_KW_CMASK "=")) { 8790cfab8ddSJoseph Koshy q = strchr(p, '='); 8800cfab8ddSJoseph Koshy if (*++q == '\0') /* skip '=' */ 8810cfab8ddSJoseph Koshy return (-1); 8820cfab8ddSJoseph Koshy count = strtol(q, &e, 0); 8830cfab8ddSJoseph Koshy if (e == q || *e != '\0') 8840cfab8ddSJoseph Koshy return (-1); 8850cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 8860cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= 8870cfab8ddSJoseph Koshy IAP_CMASK(count); 8880cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_EDGE)) { 8890cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 8900cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_INV)) { 8910cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 8920cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_OS)) { 8930cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 8940cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_USR)) { 8950cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 8960cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_ANYTHREAD)) { 8970cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= IAP_ANY; 898b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_CORE "=")) { 8990cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_core_mask, p, &evmask); 9000cfab8ddSJoseph Koshy if (n != 1) 9010cfab8ddSJoseph Koshy return (-1); 902b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_AGENT "=")) { 9030cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_agent_mask, p, &evmask); 9040cfab8ddSJoseph Koshy if (n != 1) 9050cfab8ddSJoseph Koshy return (-1); 906b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_PREFETCH "=")) { 9070cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_prefetch_mask, p, &evmask); 9080cfab8ddSJoseph Koshy if (n != 1) 9090cfab8ddSJoseph Koshy return (-1); 910b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_CACHESTATE "=")) { 9110cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_cachestate_mask, p, &cachestate); 9120cfab8ddSJoseph Koshy } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_CORE && 913b47ea38eSJoseph Koshy KWPREFIXMATCH(p, IAP_KW_TRANSITION "=")) { 9140cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_transition_mask, p, &evmask); 9150cfab8ddSJoseph Koshy if (n != 1) 9160cfab8ddSJoseph Koshy return (-1); 9170cfab8ddSJoseph Koshy } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM || 918e8f021a3SHiren Panchasara cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM_SILVERMONT || 919b4d091f3SJoseph Koshy cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2 || 9201fa7f10bSFabien Thomas cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2EXTREME) { 921b47ea38eSJoseph Koshy if (KWPREFIXMATCH(p, IAP_KW_SNOOPRESPONSE "=")) { 9220cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_snoopresponse_mask, p, 9230cfab8ddSJoseph Koshy &evmask); 924b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_SNOOPTYPE "=")) { 9250cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_snooptype_mask, p, 9260cfab8ddSJoseph Koshy &evmask); 9270cfab8ddSJoseph Koshy } else 9280cfab8ddSJoseph Koshy return (-1); 9291fa7f10bSFabien Thomas } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_COREI7 || 93049fe48abSKonstantin Belousov cpu_info.pm_cputype == PMC_CPU_INTEL_WESTMERE || 93149fe48abSKonstantin Belousov cpu_info.pm_cputype == PMC_CPU_INTEL_NEHALEM_EX || 93249fe48abSKonstantin Belousov cpu_info.pm_cputype == PMC_CPU_INTEL_WESTMERE_EX) { 9331fa7f10bSFabien Thomas if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 9341e862e5aSFabien Thomas n = pmc_parse_mask(iap_rsp_mask_i7_wm, p, &rsp); 9351e862e5aSFabien Thomas } else 9361e862e5aSFabien Thomas return (-1); 9371e862e5aSFabien Thomas } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_SANDYBRIDGE || 938fabe02f5SSean Bruno cpu_info.pm_cputype == PMC_CPU_INTEL_SANDYBRIDGE_XEON || 9393f929d8cSSean Bruno cpu_info.pm_cputype == PMC_CPU_INTEL_IVYBRIDGE || 9403f929d8cSSean Bruno cpu_info.pm_cputype == PMC_CPU_INTEL_IVYBRIDGE_XEON ) { 9411e862e5aSFabien Thomas if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 942fabe02f5SSean Bruno n = pmc_parse_mask(iap_rsp_mask_sb_sbx_ib, p, &rsp); 9431fa7f10bSFabien Thomas } else 9441fa7f10bSFabien Thomas return (-1); 945d95b3509SRandall Stewart } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_HASWELL || 946d95b3509SRandall Stewart cpu_info.pm_cputype == PMC_CPU_INTEL_HASWELL_XEON) { 947cc0c1555SSean Bruno if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 948cc0c1555SSean Bruno n = pmc_parse_mask(iap_rsp_mask_haswell, p, &rsp); 949cc0c1555SSean Bruno } else 950cc0c1555SSean Bruno return (-1); 9510cfab8ddSJoseph Koshy } else 9520cfab8ddSJoseph Koshy return (-1); 9530cfab8ddSJoseph Koshy 9540cfab8ddSJoseph Koshy if (n < 0) /* Parsing failed. */ 9550cfab8ddSJoseph Koshy return (-1); 9560cfab8ddSJoseph Koshy } 9570cfab8ddSJoseph Koshy 9580cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= evmask; 9590cfab8ddSJoseph Koshy 9600cfab8ddSJoseph Koshy /* 9610cfab8ddSJoseph Koshy * If the event requires a 'cachestate' qualifier but was not 9620cfab8ddSJoseph Koshy * specified by the user, use a sensible default. 9630cfab8ddSJoseph Koshy */ 9640cfab8ddSJoseph Koshy switch (pe) { 9650cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_28H: /* Core, Core2, Atom */ 9660cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_29H: /* Core, Core2, Atom */ 9670cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_2AH: /* Core, Core2, Atom */ 9680cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_2BH: /* Atom, Core2 */ 9690cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_2EH: /* Core, Core2, Atom */ 9700cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_30H: /* Core, Core2, Atom */ 9710cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_32H: /* Core */ 9720cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_40H: /* Core */ 9730cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_41H: /* Core */ 9740cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_42H: /* Core, Core2, Atom */ 9750cfab8ddSJoseph Koshy if (cachestate == 0) 9760cfab8ddSJoseph Koshy cachestate = (0xF << 8); 977aa1b887bSRyan Stone break; 978aa1b887bSRyan Stone case PMC_EV_IAP_EVENT_77H: /* Atom */ 979aa1b887bSRyan Stone /* IAP_EVENT_77H only accepts a cachestate qualifier on the 980aa1b887bSRyan Stone * Atom processor 981aa1b887bSRyan Stone */ 982aa1b887bSRyan Stone if(cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM && cachestate == 0) 983aa1b887bSRyan Stone cachestate = (0xF << 8); 984aa1b887bSRyan Stone break; 9850cfab8ddSJoseph Koshy default: 9860cfab8ddSJoseph Koshy break; 9870cfab8ddSJoseph Koshy } 9880cfab8ddSJoseph Koshy 9890cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= cachestate; 9901fa7f10bSFabien Thomas pmc_config->pm_md.pm_iap.pm_iap_rsp = rsp; 9911fa7f10bSFabien Thomas 9921fa7f10bSFabien Thomas return (0); 9931fa7f10bSFabien Thomas } 9941fa7f10bSFabien Thomas 9951fa7f10bSFabien Thomas /* 9961fa7f10bSFabien Thomas * Intel Uncore. 9971fa7f10bSFabien Thomas */ 9981fa7f10bSFabien Thomas 9991fa7f10bSFabien Thomas static int 10001fa7f10bSFabien Thomas ucf_allocate_pmc(enum pmc_event pe, char *ctrspec, 10011fa7f10bSFabien Thomas struct pmc_op_pmcallocate *pmc_config) 10021fa7f10bSFabien Thomas { 10031fa7f10bSFabien Thomas (void) pe; 10041fa7f10bSFabien Thomas (void) ctrspec; 10051fa7f10bSFabien Thomas 10061fa7f10bSFabien Thomas pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 10071fa7f10bSFabien Thomas pmc_config->pm_md.pm_ucf.pm_ucf_flags = 0; 10081fa7f10bSFabien Thomas 10091fa7f10bSFabien Thomas return (0); 10101fa7f10bSFabien Thomas } 10111fa7f10bSFabien Thomas 10121fa7f10bSFabien Thomas #define UCP_KW_CMASK "cmask" 10131fa7f10bSFabien Thomas #define UCP_KW_EDGE "edge" 10141fa7f10bSFabien Thomas #define UCP_KW_INV "inv" 10151fa7f10bSFabien Thomas 10161fa7f10bSFabien Thomas static int 10171fa7f10bSFabien Thomas ucp_allocate_pmc(enum pmc_event pe, char *ctrspec, 10181fa7f10bSFabien Thomas struct pmc_op_pmcallocate *pmc_config) 10191fa7f10bSFabien Thomas { 10201fa7f10bSFabien Thomas char *e, *p, *q; 10211fa7f10bSFabien Thomas int count, n; 10221fa7f10bSFabien Thomas 10231fa7f10bSFabien Thomas (void) pe; 10241fa7f10bSFabien Thomas 10251fa7f10bSFabien Thomas pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE | 10261fa7f10bSFabien Thomas PMC_CAP_QUALIFIER); 10271fa7f10bSFabien Thomas pmc_config->pm_md.pm_ucp.pm_ucp_config = 0; 10281fa7f10bSFabien Thomas 10291fa7f10bSFabien Thomas /* Parse additional modifiers if present */ 10301fa7f10bSFabien Thomas while ((p = strsep(&ctrspec, ",")) != NULL) { 10311fa7f10bSFabien Thomas 10321fa7f10bSFabien Thomas n = 0; 10331fa7f10bSFabien Thomas if (KWPREFIXMATCH(p, UCP_KW_CMASK "=")) { 10341fa7f10bSFabien Thomas q = strchr(p, '='); 10351fa7f10bSFabien Thomas if (*++q == '\0') /* skip '=' */ 10361fa7f10bSFabien Thomas return (-1); 10371fa7f10bSFabien Thomas count = strtol(q, &e, 0); 10381fa7f10bSFabien Thomas if (e == q || *e != '\0') 10391fa7f10bSFabien Thomas return (-1); 10401fa7f10bSFabien Thomas pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 10411fa7f10bSFabien Thomas pmc_config->pm_md.pm_ucp.pm_ucp_config |= 10421fa7f10bSFabien Thomas UCP_CMASK(count); 10431fa7f10bSFabien Thomas } else if (KWMATCH(p, UCP_KW_EDGE)) { 10441fa7f10bSFabien Thomas pmc_config->pm_caps |= PMC_CAP_EDGE; 10451fa7f10bSFabien Thomas } else if (KWMATCH(p, UCP_KW_INV)) { 10461fa7f10bSFabien Thomas pmc_config->pm_caps |= PMC_CAP_INVERT; 10471fa7f10bSFabien Thomas } else 10481fa7f10bSFabien Thomas return (-1); 10491fa7f10bSFabien Thomas 10501fa7f10bSFabien Thomas if (n < 0) /* Parsing failed. */ 10511fa7f10bSFabien Thomas return (-1); 10521fa7f10bSFabien Thomas } 10530cfab8ddSJoseph Koshy 10540cfab8ddSJoseph Koshy return (0); 10550cfab8ddSJoseph Koshy } 10560cfab8ddSJoseph Koshy 10570cfab8ddSJoseph Koshy /* 1058f263522aSJoseph Koshy * AMD K8 PMCs. 1059f263522aSJoseph Koshy * 1060f263522aSJoseph Koshy * These are very similar to AMD K7 PMCs, but support more kinds of 1061f263522aSJoseph Koshy * events. 1062f263522aSJoseph Koshy */ 1063f263522aSJoseph Koshy 1064f263522aSJoseph Koshy static struct pmc_event_alias k8_aliases[] = { 1065f263522aSJoseph Koshy EV_ALIAS("branches", "k8-fr-retired-taken-branches"), 1066f263522aSJoseph Koshy EV_ALIAS("branch-mispredicts", 1067f263522aSJoseph Koshy "k8-fr-retired-taken-branches-mispredicted"), 1068f263522aSJoseph Koshy EV_ALIAS("cycles", "tsc"), 1069f263522aSJoseph Koshy EV_ALIAS("dc-misses", "k8-dc-miss"), 1070f263522aSJoseph Koshy EV_ALIAS("ic-misses", "k8-ic-miss"), 1071f263522aSJoseph Koshy EV_ALIAS("instructions", "k8-fr-retired-x86-instructions"), 1072f263522aSJoseph Koshy EV_ALIAS("interrupts", "k8-fr-taken-hardware-interrupts"), 1073177a2f22SJoseph Koshy EV_ALIAS("unhalted-cycles", "k8-bu-cpu-clk-unhalted"), 1074f263522aSJoseph Koshy EV_ALIAS(NULL, NULL) 1075f263522aSJoseph Koshy }; 1076f263522aSJoseph Koshy 1077f263522aSJoseph Koshy #define __K8MASK(N,V) PMCMASK(N,(1 << (V))) 1078f263522aSJoseph Koshy 1079f263522aSJoseph Koshy /* 1080f263522aSJoseph Koshy * Parsing tables 1081f263522aSJoseph Koshy */ 1082f263522aSJoseph Koshy 1083f263522aSJoseph Koshy /* fp dispatched fpu ops */ 1084f263522aSJoseph Koshy static const struct pmc_masks k8_mask_fdfo[] = { 1085f263522aSJoseph Koshy __K8MASK(add-pipe-excluding-junk-ops, 0), 1086f263522aSJoseph Koshy __K8MASK(multiply-pipe-excluding-junk-ops, 1), 1087f263522aSJoseph Koshy __K8MASK(store-pipe-excluding-junk-ops, 2), 1088f263522aSJoseph Koshy __K8MASK(add-pipe-junk-ops, 3), 1089f263522aSJoseph Koshy __K8MASK(multiply-pipe-junk-ops, 4), 1090f263522aSJoseph Koshy __K8MASK(store-pipe-junk-ops, 5), 1091f263522aSJoseph Koshy NULLMASK 1092f263522aSJoseph Koshy }; 1093f263522aSJoseph Koshy 1094f263522aSJoseph Koshy /* ls segment register loads */ 1095f263522aSJoseph Koshy static const struct pmc_masks k8_mask_lsrl[] = { 1096f263522aSJoseph Koshy __K8MASK(es, 0), 1097f263522aSJoseph Koshy __K8MASK(cs, 1), 1098f263522aSJoseph Koshy __K8MASK(ss, 2), 1099f263522aSJoseph Koshy __K8MASK(ds, 3), 1100f263522aSJoseph Koshy __K8MASK(fs, 4), 1101f263522aSJoseph Koshy __K8MASK(gs, 5), 1102f263522aSJoseph Koshy __K8MASK(hs, 6), 1103f263522aSJoseph Koshy NULLMASK 1104f263522aSJoseph Koshy }; 1105f263522aSJoseph Koshy 1106f263522aSJoseph Koshy /* ls locked operation */ 1107f263522aSJoseph Koshy static const struct pmc_masks k8_mask_llo[] = { 1108f263522aSJoseph Koshy __K8MASK(locked-instructions, 0), 1109f263522aSJoseph Koshy __K8MASK(cycles-in-request, 1), 1110f263522aSJoseph Koshy __K8MASK(cycles-to-complete, 2), 1111f263522aSJoseph Koshy NULLMASK 1112f263522aSJoseph Koshy }; 1113f263522aSJoseph Koshy 1114f263522aSJoseph Koshy /* dc refill from {l2,system} and dc copyback */ 1115f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dc[] = { 1116f263522aSJoseph Koshy __K8MASK(invalid, 0), 1117f263522aSJoseph Koshy __K8MASK(shared, 1), 1118f263522aSJoseph Koshy __K8MASK(exclusive, 2), 1119f263522aSJoseph Koshy __K8MASK(owner, 3), 1120f263522aSJoseph Koshy __K8MASK(modified, 4), 1121f263522aSJoseph Koshy NULLMASK 1122f263522aSJoseph Koshy }; 1123f263522aSJoseph Koshy 1124f263522aSJoseph Koshy /* dc one bit ecc error */ 1125f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dobee[] = { 1126f263522aSJoseph Koshy __K8MASK(scrubber, 0), 1127f263522aSJoseph Koshy __K8MASK(piggyback, 1), 1128f263522aSJoseph Koshy NULLMASK 1129f263522aSJoseph Koshy }; 1130f263522aSJoseph Koshy 1131f263522aSJoseph Koshy /* dc dispatched prefetch instructions */ 1132f263522aSJoseph Koshy static const struct pmc_masks k8_mask_ddpi[] = { 1133f263522aSJoseph Koshy __K8MASK(load, 0), 1134f263522aSJoseph Koshy __K8MASK(store, 1), 1135f263522aSJoseph Koshy __K8MASK(nta, 2), 1136f263522aSJoseph Koshy NULLMASK 1137f263522aSJoseph Koshy }; 1138f263522aSJoseph Koshy 1139f263522aSJoseph Koshy /* dc dcache accesses by locks */ 1140f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dabl[] = { 1141f263522aSJoseph Koshy __K8MASK(accesses, 0), 1142f263522aSJoseph Koshy __K8MASK(misses, 1), 1143f263522aSJoseph Koshy NULLMASK 1144f263522aSJoseph Koshy }; 1145f263522aSJoseph Koshy 1146f263522aSJoseph Koshy /* bu internal l2 request */ 1147f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bilr[] = { 1148f263522aSJoseph Koshy __K8MASK(ic-fill, 0), 1149f263522aSJoseph Koshy __K8MASK(dc-fill, 1), 1150f263522aSJoseph Koshy __K8MASK(tlb-reload, 2), 1151f263522aSJoseph Koshy __K8MASK(tag-snoop, 3), 1152f263522aSJoseph Koshy __K8MASK(cancelled, 4), 1153f263522aSJoseph Koshy NULLMASK 1154f263522aSJoseph Koshy }; 1155f263522aSJoseph Koshy 1156f263522aSJoseph Koshy /* bu fill request l2 miss */ 1157f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bfrlm[] = { 1158f263522aSJoseph Koshy __K8MASK(ic-fill, 0), 1159f263522aSJoseph Koshy __K8MASK(dc-fill, 1), 1160f263522aSJoseph Koshy __K8MASK(tlb-reload, 2), 1161f263522aSJoseph Koshy NULLMASK 1162f263522aSJoseph Koshy }; 1163f263522aSJoseph Koshy 1164f263522aSJoseph Koshy /* bu fill into l2 */ 1165f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bfil[] = { 1166f263522aSJoseph Koshy __K8MASK(dirty-l2-victim, 0), 1167f263522aSJoseph Koshy __K8MASK(victim-from-l2, 1), 1168f263522aSJoseph Koshy NULLMASK 1169f263522aSJoseph Koshy }; 1170f263522aSJoseph Koshy 1171f263522aSJoseph Koshy /* fr retired fpu instructions */ 1172f263522aSJoseph Koshy static const struct pmc_masks k8_mask_frfi[] = { 1173f263522aSJoseph Koshy __K8MASK(x87, 0), 1174f263522aSJoseph Koshy __K8MASK(mmx-3dnow, 1), 1175f263522aSJoseph Koshy __K8MASK(packed-sse-sse2, 2), 1176f263522aSJoseph Koshy __K8MASK(scalar-sse-sse2, 3), 1177f263522aSJoseph Koshy NULLMASK 1178f263522aSJoseph Koshy }; 1179f263522aSJoseph Koshy 1180f263522aSJoseph Koshy /* fr retired fastpath double op instructions */ 1181f263522aSJoseph Koshy static const struct pmc_masks k8_mask_frfdoi[] = { 1182f263522aSJoseph Koshy __K8MASK(low-op-pos-0, 0), 1183f263522aSJoseph Koshy __K8MASK(low-op-pos-1, 1), 1184f263522aSJoseph Koshy __K8MASK(low-op-pos-2, 2), 1185f263522aSJoseph Koshy NULLMASK 1186f263522aSJoseph Koshy }; 1187f263522aSJoseph Koshy 1188f263522aSJoseph Koshy /* fr fpu exceptions */ 1189f263522aSJoseph Koshy static const struct pmc_masks k8_mask_ffe[] = { 1190f263522aSJoseph Koshy __K8MASK(x87-reclass-microfaults, 0), 1191f263522aSJoseph Koshy __K8MASK(sse-retype-microfaults, 1), 1192f263522aSJoseph Koshy __K8MASK(sse-reclass-microfaults, 2), 1193f263522aSJoseph Koshy __K8MASK(sse-and-x87-microtraps, 3), 1194f263522aSJoseph Koshy NULLMASK 1195f263522aSJoseph Koshy }; 1196f263522aSJoseph Koshy 1197f263522aSJoseph Koshy /* nb memory controller page access event */ 1198f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmcpae[] = { 1199f263522aSJoseph Koshy __K8MASK(page-hit, 0), 1200f263522aSJoseph Koshy __K8MASK(page-miss, 1), 1201f263522aSJoseph Koshy __K8MASK(page-conflict, 2), 1202f263522aSJoseph Koshy NULLMASK 1203f263522aSJoseph Koshy }; 1204f263522aSJoseph Koshy 1205f263522aSJoseph Koshy /* nb memory controller turnaround */ 1206f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmct[] = { 1207f263522aSJoseph Koshy __K8MASK(dimm-turnaround, 0), 1208f263522aSJoseph Koshy __K8MASK(read-to-write-turnaround, 1), 1209f263522aSJoseph Koshy __K8MASK(write-to-read-turnaround, 2), 1210f263522aSJoseph Koshy NULLMASK 1211f263522aSJoseph Koshy }; 1212f263522aSJoseph Koshy 1213f263522aSJoseph Koshy /* nb memory controller bypass saturation */ 1214f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmcbs[] = { 1215f263522aSJoseph Koshy __K8MASK(memory-controller-hi-pri-bypass, 0), 1216f263522aSJoseph Koshy __K8MASK(memory-controller-lo-pri-bypass, 1), 1217f263522aSJoseph Koshy __K8MASK(dram-controller-interface-bypass, 2), 1218f263522aSJoseph Koshy __K8MASK(dram-controller-queue-bypass, 3), 1219f263522aSJoseph Koshy NULLMASK 1220f263522aSJoseph Koshy }; 1221f263522aSJoseph Koshy 1222f263522aSJoseph Koshy /* nb sized commands */ 1223f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nsc[] = { 1224f263522aSJoseph Koshy __K8MASK(nonpostwrszbyte, 0), 1225f263522aSJoseph Koshy __K8MASK(nonpostwrszdword, 1), 1226f263522aSJoseph Koshy __K8MASK(postwrszbyte, 2), 1227f263522aSJoseph Koshy __K8MASK(postwrszdword, 3), 1228f263522aSJoseph Koshy __K8MASK(rdszbyte, 4), 1229f263522aSJoseph Koshy __K8MASK(rdszdword, 5), 1230f263522aSJoseph Koshy __K8MASK(rdmodwr, 6), 1231f263522aSJoseph Koshy NULLMASK 1232f263522aSJoseph Koshy }; 1233f263522aSJoseph Koshy 1234f263522aSJoseph Koshy /* nb probe result */ 1235f263522aSJoseph Koshy static const struct pmc_masks k8_mask_npr[] = { 1236f263522aSJoseph Koshy __K8MASK(probe-miss, 0), 1237f263522aSJoseph Koshy __K8MASK(probe-hit, 1), 1238f263522aSJoseph Koshy __K8MASK(probe-hit-dirty-no-memory-cancel, 2), 1239f263522aSJoseph Koshy __K8MASK(probe-hit-dirty-with-memory-cancel, 3), 1240f263522aSJoseph Koshy NULLMASK 1241f263522aSJoseph Koshy }; 1242f263522aSJoseph Koshy 1243f263522aSJoseph Koshy /* nb hypertransport bus bandwidth */ 1244f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nhbb[] = { /* HT bus bandwidth */ 1245f263522aSJoseph Koshy __K8MASK(command, 0), 1246f263522aSJoseph Koshy __K8MASK(data, 1), 1247f263522aSJoseph Koshy __K8MASK(buffer-release, 2), 1248f263522aSJoseph Koshy __K8MASK(nop, 3), 1249f263522aSJoseph Koshy NULLMASK 1250f263522aSJoseph Koshy }; 1251f263522aSJoseph Koshy 1252f263522aSJoseph Koshy #undef __K8MASK 1253f263522aSJoseph Koshy 1254f263522aSJoseph Koshy #define K8_KW_COUNT "count" 1255f263522aSJoseph Koshy #define K8_KW_EDGE "edge" 1256f263522aSJoseph Koshy #define K8_KW_INV "inv" 1257f263522aSJoseph Koshy #define K8_KW_MASK "mask" 1258f263522aSJoseph Koshy #define K8_KW_OS "os" 1259f263522aSJoseph Koshy #define K8_KW_USR "usr" 1260f263522aSJoseph Koshy 1261f263522aSJoseph Koshy static int 1262f263522aSJoseph Koshy k8_allocate_pmc(enum pmc_event pe, char *ctrspec, 1263f263522aSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 1264f263522aSJoseph Koshy { 1265f263522aSJoseph Koshy char *e, *p, *q; 1266f263522aSJoseph Koshy int n; 12671e862e5aSFabien Thomas uint32_t count; 12681e862e5aSFabien Thomas uint64_t evmask; 1269f263522aSJoseph Koshy const struct pmc_masks *pm, *pmask; 1270f263522aSJoseph Koshy 1271789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1272f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 1273f263522aSJoseph Koshy 1274f263522aSJoseph Koshy pmask = NULL; 1275f263522aSJoseph Koshy evmask = 0; 1276f263522aSJoseph Koshy 1277f263522aSJoseph Koshy #define __K8SETMASK(M) pmask = k8_mask_##M 1278f263522aSJoseph Koshy 1279f263522aSJoseph Koshy /* setup parsing tables */ 1280f263522aSJoseph Koshy switch (pe) { 1281f263522aSJoseph Koshy case PMC_EV_K8_FP_DISPATCHED_FPU_OPS: 1282f263522aSJoseph Koshy __K8SETMASK(fdfo); 1283f263522aSJoseph Koshy break; 1284f263522aSJoseph Koshy case PMC_EV_K8_LS_SEGMENT_REGISTER_LOAD: 1285f263522aSJoseph Koshy __K8SETMASK(lsrl); 1286f263522aSJoseph Koshy break; 1287f263522aSJoseph Koshy case PMC_EV_K8_LS_LOCKED_OPERATION: 1288f263522aSJoseph Koshy __K8SETMASK(llo); 1289f263522aSJoseph Koshy break; 1290f263522aSJoseph Koshy case PMC_EV_K8_DC_REFILL_FROM_L2: 1291f263522aSJoseph Koshy case PMC_EV_K8_DC_REFILL_FROM_SYSTEM: 1292f263522aSJoseph Koshy case PMC_EV_K8_DC_COPYBACK: 1293f263522aSJoseph Koshy __K8SETMASK(dc); 1294f263522aSJoseph Koshy break; 1295f263522aSJoseph Koshy case PMC_EV_K8_DC_ONE_BIT_ECC_ERROR: 1296f263522aSJoseph Koshy __K8SETMASK(dobee); 1297f263522aSJoseph Koshy break; 1298f263522aSJoseph Koshy case PMC_EV_K8_DC_DISPATCHED_PREFETCH_INSTRUCTIONS: 1299f263522aSJoseph Koshy __K8SETMASK(ddpi); 1300f263522aSJoseph Koshy break; 1301f263522aSJoseph Koshy case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS: 1302f263522aSJoseph Koshy __K8SETMASK(dabl); 1303f263522aSJoseph Koshy break; 1304f263522aSJoseph Koshy case PMC_EV_K8_BU_INTERNAL_L2_REQUEST: 1305f263522aSJoseph Koshy __K8SETMASK(bilr); 1306f263522aSJoseph Koshy break; 1307f263522aSJoseph Koshy case PMC_EV_K8_BU_FILL_REQUEST_L2_MISS: 1308f263522aSJoseph Koshy __K8SETMASK(bfrlm); 1309f263522aSJoseph Koshy break; 1310f263522aSJoseph Koshy case PMC_EV_K8_BU_FILL_INTO_L2: 1311f263522aSJoseph Koshy __K8SETMASK(bfil); 1312f263522aSJoseph Koshy break; 1313f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS: 1314f263522aSJoseph Koshy __K8SETMASK(frfi); 1315f263522aSJoseph Koshy break; 1316f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS: 1317f263522aSJoseph Koshy __K8SETMASK(frfdoi); 1318f263522aSJoseph Koshy break; 1319f263522aSJoseph Koshy case PMC_EV_K8_FR_FPU_EXCEPTIONS: 1320f263522aSJoseph Koshy __K8SETMASK(ffe); 1321f263522aSJoseph Koshy break; 1322f263522aSJoseph Koshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_PAGE_ACCESS_EVENT: 1323f263522aSJoseph Koshy __K8SETMASK(nmcpae); 1324f263522aSJoseph Koshy break; 1325f263522aSJoseph Koshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_TURNAROUND: 1326f263522aSJoseph Koshy __K8SETMASK(nmct); 1327f263522aSJoseph Koshy break; 1328f263522aSJoseph Koshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_BYPASS_SATURATION: 1329f263522aSJoseph Koshy __K8SETMASK(nmcbs); 1330f263522aSJoseph Koshy break; 1331f263522aSJoseph Koshy case PMC_EV_K8_NB_SIZED_COMMANDS: 1332f263522aSJoseph Koshy __K8SETMASK(nsc); 1333f263522aSJoseph Koshy break; 1334f263522aSJoseph Koshy case PMC_EV_K8_NB_PROBE_RESULT: 1335f263522aSJoseph Koshy __K8SETMASK(npr); 1336f263522aSJoseph Koshy break; 1337f263522aSJoseph Koshy case PMC_EV_K8_NB_HT_BUS0_BANDWIDTH: 1338f263522aSJoseph Koshy case PMC_EV_K8_NB_HT_BUS1_BANDWIDTH: 1339f263522aSJoseph Koshy case PMC_EV_K8_NB_HT_BUS2_BANDWIDTH: 1340f263522aSJoseph Koshy __K8SETMASK(nhbb); 1341f263522aSJoseph Koshy break; 1342f263522aSJoseph Koshy 1343f263522aSJoseph Koshy default: 1344f263522aSJoseph Koshy break; /* no options defined */ 1345f263522aSJoseph Koshy } 1346f263522aSJoseph Koshy 1347f263522aSJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 1348f263522aSJoseph Koshy if (KWPREFIXMATCH(p, K8_KW_COUNT "=")) { 1349f263522aSJoseph Koshy q = strchr(p, '='); 1350f263522aSJoseph Koshy if (*++q == '\0') /* skip '=' */ 1351aa342b1fSJoseph Koshy return (-1); 1352f263522aSJoseph Koshy 1353f263522aSJoseph Koshy count = strtol(q, &e, 0); 1354f263522aSJoseph Koshy if (e == q || *e != '\0') 1355aa342b1fSJoseph Koshy return (-1); 1356f263522aSJoseph Koshy 1357f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 1358f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config |= 1359f263522aSJoseph Koshy AMD_PMC_TO_COUNTER(count); 1360f263522aSJoseph Koshy 1361f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_EDGE)) { 1362f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1363f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_INV)) { 1364f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 1365f263522aSJoseph Koshy } else if (KWPREFIXMATCH(p, K8_KW_MASK "=")) { 1366f263522aSJoseph Koshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 1367aa342b1fSJoseph Koshy return (-1); 1368f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1369f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_OS)) { 1370f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 1371f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_USR)) { 1372f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 1373f263522aSJoseph Koshy } else 1374aa342b1fSJoseph Koshy return (-1); 1375f263522aSJoseph Koshy } 1376f263522aSJoseph Koshy 1377f263522aSJoseph Koshy /* other post processing */ 1378f263522aSJoseph Koshy switch (pe) { 1379f263522aSJoseph Koshy case PMC_EV_K8_FP_DISPATCHED_FPU_OPS: 1380f263522aSJoseph Koshy case PMC_EV_K8_FP_CYCLES_WITH_NO_FPU_OPS_RETIRED: 1381f263522aSJoseph Koshy case PMC_EV_K8_FP_DISPATCHED_FPU_FAST_FLAG_OPS: 1382f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS: 1383f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS: 1384f263522aSJoseph Koshy case PMC_EV_K8_FR_FPU_EXCEPTIONS: 1385f263522aSJoseph Koshy /* XXX only available in rev B and later */ 1386f263522aSJoseph Koshy break; 1387f263522aSJoseph Koshy case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS: 1388f263522aSJoseph Koshy /* XXX only available in rev C and later */ 1389f263522aSJoseph Koshy break; 1390f263522aSJoseph Koshy case PMC_EV_K8_LS_LOCKED_OPERATION: 1391f263522aSJoseph Koshy /* XXX CPU Rev A,B evmask is to be zero */ 1392f263522aSJoseph Koshy if (evmask & (evmask - 1)) /* > 1 bit set */ 1393aa342b1fSJoseph Koshy return (-1); 1394f263522aSJoseph Koshy if (evmask == 0) { 1395f263522aSJoseph Koshy evmask = 0x01; /* Rev C and later: #instrs */ 1396f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1397f263522aSJoseph Koshy } 1398f263522aSJoseph Koshy break; 1399f263522aSJoseph Koshy default: 1400f263522aSJoseph Koshy if (evmask == 0 && pmask != NULL) { 1401f263522aSJoseph Koshy for (pm = pmask; pm->pm_name; pm++) 1402f263522aSJoseph Koshy evmask |= pm->pm_value; 1403f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1404f263522aSJoseph Koshy } 1405f263522aSJoseph Koshy } 1406f263522aSJoseph Koshy 1407f263522aSJoseph Koshy if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) 1408f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 1409f263522aSJoseph Koshy AMD_PMC_TO_UNITMASK(evmask); 1410f263522aSJoseph Koshy 1411aa342b1fSJoseph Koshy return (0); 1412f263522aSJoseph Koshy } 1413f263522aSJoseph Koshy 1414f263522aSJoseph Koshy #endif 1415f263522aSJoseph Koshy 141686a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 1417f263522aSJoseph Koshy 1418ebccf1e3SJoseph Koshy /* 1419ebccf1e3SJoseph Koshy * Intel P4 PMCs 1420ebccf1e3SJoseph Koshy */ 1421ebccf1e3SJoseph Koshy 1422ebccf1e3SJoseph Koshy static struct pmc_event_alias p4_aliases[] = { 1423d56c5d4bSJoseph Koshy EV_ALIAS("branches", "p4-branch-retired,mask=mmtp+mmtm"), 1424d56c5d4bSJoseph Koshy EV_ALIAS("branch-mispredicts", "p4-mispred-branch-retired"), 1425ebccf1e3SJoseph Koshy EV_ALIAS("cycles", "tsc"), 1426d56c5d4bSJoseph Koshy EV_ALIAS("instructions", 1427d56c5d4bSJoseph Koshy "p4-instr-retired,mask=nbogusntag+nbogustag"), 1428177a2f22SJoseph Koshy EV_ALIAS("unhalted-cycles", "p4-global-power-events"), 1429ebccf1e3SJoseph Koshy EV_ALIAS(NULL, NULL) 1430ebccf1e3SJoseph Koshy }; 1431ebccf1e3SJoseph Koshy 1432ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE "active" 1433ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_ANY "any" 1434ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_BOTH "both" 1435ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_NONE "none" 1436ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_SINGLE "single" 1437ebccf1e3SJoseph Koshy #define P4_KW_BUSREQTYPE "busreqtype" 1438ebccf1e3SJoseph Koshy #define P4_KW_CASCADE "cascade" 1439ebccf1e3SJoseph Koshy #define P4_KW_EDGE "edge" 1440ebccf1e3SJoseph Koshy #define P4_KW_INV "complement" 1441ebccf1e3SJoseph Koshy #define P4_KW_OS "os" 1442ebccf1e3SJoseph Koshy #define P4_KW_MASK "mask" 1443ebccf1e3SJoseph Koshy #define P4_KW_PRECISE "precise" 1444ebccf1e3SJoseph Koshy #define P4_KW_TAG "tag" 1445ebccf1e3SJoseph Koshy #define P4_KW_THRESHOLD "threshold" 1446ebccf1e3SJoseph Koshy #define P4_KW_USR "usr" 1447ebccf1e3SJoseph Koshy 1448ebccf1e3SJoseph Koshy #define __P4MASK(N,V) PMCMASK(N, (1 << (V))) 1449ebccf1e3SJoseph Koshy 1450ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_tcdm[] = { /* tc deliver mode */ 1451ebccf1e3SJoseph Koshy __P4MASK(dd, 0), 1452ebccf1e3SJoseph Koshy __P4MASK(db, 1), 1453ebccf1e3SJoseph Koshy __P4MASK(di, 2), 1454ebccf1e3SJoseph Koshy __P4MASK(bd, 3), 1455ebccf1e3SJoseph Koshy __P4MASK(bb, 4), 1456ebccf1e3SJoseph Koshy __P4MASK(bi, 5), 1457ebccf1e3SJoseph Koshy __P4MASK(id, 6), 1458ebccf1e3SJoseph Koshy __P4MASK(ib, 7), 1459ebccf1e3SJoseph Koshy NULLMASK 1460ebccf1e3SJoseph Koshy }; 1461ebccf1e3SJoseph Koshy 1462ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_bfr[] = { /* bpu fetch request */ 1463ebccf1e3SJoseph Koshy __P4MASK(tcmiss, 0), 1464ebccf1e3SJoseph Koshy NULLMASK, 1465ebccf1e3SJoseph Koshy }; 1466ebccf1e3SJoseph Koshy 1467ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ir[] = { /* itlb reference */ 1468ebccf1e3SJoseph Koshy __P4MASK(hit, 0), 1469ebccf1e3SJoseph Koshy __P4MASK(miss, 1), 1470ebccf1e3SJoseph Koshy __P4MASK(hit-uc, 2), 1471ebccf1e3SJoseph Koshy NULLMASK 1472ebccf1e3SJoseph Koshy }; 1473ebccf1e3SJoseph Koshy 1474ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_memcan[] = { /* memory cancel */ 1475ebccf1e3SJoseph Koshy __P4MASK(st-rb-full, 2), 1476ebccf1e3SJoseph Koshy __P4MASK(64k-conf, 3), 1477ebccf1e3SJoseph Koshy NULLMASK 1478ebccf1e3SJoseph Koshy }; 1479ebccf1e3SJoseph Koshy 1480ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_memcomp[] = { /* memory complete */ 1481ebccf1e3SJoseph Koshy __P4MASK(lsc, 0), 1482ebccf1e3SJoseph Koshy __P4MASK(ssc, 1), 1483ebccf1e3SJoseph Koshy NULLMASK 1484ebccf1e3SJoseph Koshy }; 1485ebccf1e3SJoseph Koshy 1486ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_lpr[] = { /* load port replay */ 1487ebccf1e3SJoseph Koshy __P4MASK(split-ld, 1), 1488ebccf1e3SJoseph Koshy NULLMASK 1489ebccf1e3SJoseph Koshy }; 1490ebccf1e3SJoseph Koshy 1491ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_spr[] = { /* store port replay */ 1492ebccf1e3SJoseph Koshy __P4MASK(split-st, 1), 1493ebccf1e3SJoseph Koshy NULLMASK 1494ebccf1e3SJoseph Koshy }; 1495ebccf1e3SJoseph Koshy 1496ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_mlr[] = { /* mob load replay */ 1497ebccf1e3SJoseph Koshy __P4MASK(no-sta, 1), 1498ebccf1e3SJoseph Koshy __P4MASK(no-std, 3), 1499ebccf1e3SJoseph Koshy __P4MASK(partial-data, 4), 1500ebccf1e3SJoseph Koshy __P4MASK(unalgn-addr, 5), 1501ebccf1e3SJoseph Koshy NULLMASK 1502ebccf1e3SJoseph Koshy }; 1503ebccf1e3SJoseph Koshy 1504ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_pwt[] = { /* page walk type */ 1505ebccf1e3SJoseph Koshy __P4MASK(dtmiss, 0), 1506ebccf1e3SJoseph Koshy __P4MASK(itmiss, 1), 1507ebccf1e3SJoseph Koshy NULLMASK 1508ebccf1e3SJoseph Koshy }; 1509ebccf1e3SJoseph Koshy 1510ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_bcr[] = { /* bsq cache reference */ 1511ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-hits, 0), 1512ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-hite, 1), 1513ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-hitm, 2), 1514ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-hits, 3), 1515ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-hite, 4), 1516ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-hitm, 5), 1517ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-miss, 8), 1518ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-miss, 9), 1519ebccf1e3SJoseph Koshy __P4MASK(wr-2ndl-miss, 10), 1520ebccf1e3SJoseph Koshy NULLMASK 1521ebccf1e3SJoseph Koshy }; 1522ebccf1e3SJoseph Koshy 1523ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ia[] = { /* ioq allocation */ 1524ebccf1e3SJoseph Koshy __P4MASK(all-read, 5), 1525ebccf1e3SJoseph Koshy __P4MASK(all-write, 6), 1526ebccf1e3SJoseph Koshy __P4MASK(mem-uc, 7), 1527ebccf1e3SJoseph Koshy __P4MASK(mem-wc, 8), 1528ebccf1e3SJoseph Koshy __P4MASK(mem-wt, 9), 1529ebccf1e3SJoseph Koshy __P4MASK(mem-wp, 10), 1530ebccf1e3SJoseph Koshy __P4MASK(mem-wb, 11), 1531ebccf1e3SJoseph Koshy __P4MASK(own, 13), 1532ebccf1e3SJoseph Koshy __P4MASK(other, 14), 1533ebccf1e3SJoseph Koshy __P4MASK(prefetch, 15), 1534ebccf1e3SJoseph Koshy NULLMASK 1535ebccf1e3SJoseph Koshy }; 1536ebccf1e3SJoseph Koshy 1537ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_iae[] = { /* ioq active entries */ 1538ebccf1e3SJoseph Koshy __P4MASK(all-read, 5), 1539ebccf1e3SJoseph Koshy __P4MASK(all-write, 6), 1540ebccf1e3SJoseph Koshy __P4MASK(mem-uc, 7), 1541ebccf1e3SJoseph Koshy __P4MASK(mem-wc, 8), 1542ebccf1e3SJoseph Koshy __P4MASK(mem-wt, 9), 1543ebccf1e3SJoseph Koshy __P4MASK(mem-wp, 10), 1544ebccf1e3SJoseph Koshy __P4MASK(mem-wb, 11), 1545ebccf1e3SJoseph Koshy __P4MASK(own, 13), 1546ebccf1e3SJoseph Koshy __P4MASK(other, 14), 1547ebccf1e3SJoseph Koshy __P4MASK(prefetch, 15), 1548ebccf1e3SJoseph Koshy NULLMASK 1549ebccf1e3SJoseph Koshy }; 1550ebccf1e3SJoseph Koshy 1551ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_fda[] = { /* fsb data activity */ 1552ebccf1e3SJoseph Koshy __P4MASK(drdy-drv, 0), 1553ebccf1e3SJoseph Koshy __P4MASK(drdy-own, 1), 1554ebccf1e3SJoseph Koshy __P4MASK(drdy-other, 2), 1555ebccf1e3SJoseph Koshy __P4MASK(dbsy-drv, 3), 1556ebccf1e3SJoseph Koshy __P4MASK(dbsy-own, 4), 1557ebccf1e3SJoseph Koshy __P4MASK(dbsy-other, 5), 1558ebccf1e3SJoseph Koshy NULLMASK 1559ebccf1e3SJoseph Koshy }; 1560ebccf1e3SJoseph Koshy 1561ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ba[] = { /* bsq allocation */ 1562ebccf1e3SJoseph Koshy __P4MASK(req-type0, 0), 1563ebccf1e3SJoseph Koshy __P4MASK(req-type1, 1), 1564ebccf1e3SJoseph Koshy __P4MASK(req-len0, 2), 1565ebccf1e3SJoseph Koshy __P4MASK(req-len1, 3), 1566ebccf1e3SJoseph Koshy __P4MASK(req-io-type, 5), 1567ebccf1e3SJoseph Koshy __P4MASK(req-lock-type, 6), 1568ebccf1e3SJoseph Koshy __P4MASK(req-cache-type, 7), 1569ebccf1e3SJoseph Koshy __P4MASK(req-split-type, 8), 1570ebccf1e3SJoseph Koshy __P4MASK(req-dem-type, 9), 1571ebccf1e3SJoseph Koshy __P4MASK(req-ord-type, 10), 1572ebccf1e3SJoseph Koshy __P4MASK(mem-type0, 11), 1573ebccf1e3SJoseph Koshy __P4MASK(mem-type1, 12), 1574ebccf1e3SJoseph Koshy __P4MASK(mem-type2, 13), 1575ebccf1e3SJoseph Koshy NULLMASK 1576ebccf1e3SJoseph Koshy }; 1577ebccf1e3SJoseph Koshy 1578ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_sia[] = { /* sse input assist */ 1579ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1580ebccf1e3SJoseph Koshy NULLMASK 1581ebccf1e3SJoseph Koshy }; 1582ebccf1e3SJoseph Koshy 1583ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_psu[] = { /* packed sp uop */ 1584ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1585ebccf1e3SJoseph Koshy NULLMASK 1586ebccf1e3SJoseph Koshy }; 1587ebccf1e3SJoseph Koshy 1588ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_pdu[] = { /* packed dp uop */ 1589ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1590ebccf1e3SJoseph Koshy NULLMASK 1591ebccf1e3SJoseph Koshy }; 1592ebccf1e3SJoseph Koshy 1593ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ssu[] = { /* scalar sp uop */ 1594ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1595ebccf1e3SJoseph Koshy NULLMASK 1596ebccf1e3SJoseph Koshy }; 1597ebccf1e3SJoseph Koshy 1598ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_sdu[] = { /* scalar dp uop */ 1599ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1600ebccf1e3SJoseph Koshy NULLMASK 1601ebccf1e3SJoseph Koshy }; 1602ebccf1e3SJoseph Koshy 1603ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_64bmu[] = { /* 64 bit mmx uop */ 1604ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1605ebccf1e3SJoseph Koshy NULLMASK 1606ebccf1e3SJoseph Koshy }; 1607ebccf1e3SJoseph Koshy 1608ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_128bmu[] = { /* 128 bit mmx uop */ 1609ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1610ebccf1e3SJoseph Koshy NULLMASK 1611ebccf1e3SJoseph Koshy }; 1612ebccf1e3SJoseph Koshy 1613ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xfu[] = { /* X87 fp uop */ 1614ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1615ebccf1e3SJoseph Koshy NULLMASK 1616ebccf1e3SJoseph Koshy }; 1617ebccf1e3SJoseph Koshy 1618ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xsmu[] = { /* x87 simd moves uop */ 1619ebccf1e3SJoseph Koshy __P4MASK(allp0, 3), 1620ebccf1e3SJoseph Koshy __P4MASK(allp2, 4), 1621ebccf1e3SJoseph Koshy NULLMASK 1622ebccf1e3SJoseph Koshy }; 1623ebccf1e3SJoseph Koshy 1624ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_gpe[] = { /* global power events */ 1625ebccf1e3SJoseph Koshy __P4MASK(running, 0), 1626ebccf1e3SJoseph Koshy NULLMASK 1627ebccf1e3SJoseph Koshy }; 1628ebccf1e3SJoseph Koshy 1629ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_tmx[] = { /* TC ms xfer */ 1630ebccf1e3SJoseph Koshy __P4MASK(cisc, 0), 1631ebccf1e3SJoseph Koshy NULLMASK 1632ebccf1e3SJoseph Koshy }; 1633ebccf1e3SJoseph Koshy 1634ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_uqw[] = { /* uop queue writes */ 1635ebccf1e3SJoseph Koshy __P4MASK(from-tc-build, 0), 1636ebccf1e3SJoseph Koshy __P4MASK(from-tc-deliver, 1), 1637ebccf1e3SJoseph Koshy __P4MASK(from-rom, 2), 1638ebccf1e3SJoseph Koshy NULLMASK 1639ebccf1e3SJoseph Koshy }; 1640ebccf1e3SJoseph Koshy 1641d56c5d4bSJoseph Koshy static const struct pmc_masks p4_mask_rmbt[] = { 1642d56c5d4bSJoseph Koshy /* retired mispred branch type */ 1643ebccf1e3SJoseph Koshy __P4MASK(conditional, 1), 1644ebccf1e3SJoseph Koshy __P4MASK(call, 2), 1645ebccf1e3SJoseph Koshy __P4MASK(return, 3), 1646ebccf1e3SJoseph Koshy __P4MASK(indirect, 4), 1647ebccf1e3SJoseph Koshy NULLMASK 1648ebccf1e3SJoseph Koshy }; 1649ebccf1e3SJoseph Koshy 1650ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_rbt[] = { /* retired branch type */ 1651ebccf1e3SJoseph Koshy __P4MASK(conditional, 1), 1652ebccf1e3SJoseph Koshy __P4MASK(call, 2), 1653ebccf1e3SJoseph Koshy __P4MASK(retired, 3), 1654ebccf1e3SJoseph Koshy __P4MASK(indirect, 4), 1655ebccf1e3SJoseph Koshy NULLMASK 1656ebccf1e3SJoseph Koshy }; 1657ebccf1e3SJoseph Koshy 1658ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_rs[] = { /* resource stall */ 1659ebccf1e3SJoseph Koshy __P4MASK(sbfull, 5), 1660ebccf1e3SJoseph Koshy NULLMASK 1661ebccf1e3SJoseph Koshy }; 1662ebccf1e3SJoseph Koshy 1663ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_wb[] = { /* WC buffer */ 1664ebccf1e3SJoseph Koshy __P4MASK(wcb-evicts, 0), 1665ebccf1e3SJoseph Koshy __P4MASK(wcb-full-evict, 1), 1666ebccf1e3SJoseph Koshy NULLMASK 1667ebccf1e3SJoseph Koshy }; 1668ebccf1e3SJoseph Koshy 1669ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_fee[] = { /* front end event */ 1670ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1671ebccf1e3SJoseph Koshy __P4MASK(bogus, 1), 1672ebccf1e3SJoseph Koshy NULLMASK 1673ebccf1e3SJoseph Koshy }; 1674ebccf1e3SJoseph Koshy 1675ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ee[] = { /* execution event */ 1676ebccf1e3SJoseph Koshy __P4MASK(nbogus0, 0), 1677ebccf1e3SJoseph Koshy __P4MASK(nbogus1, 1), 1678ebccf1e3SJoseph Koshy __P4MASK(nbogus2, 2), 1679ebccf1e3SJoseph Koshy __P4MASK(nbogus3, 3), 1680ebccf1e3SJoseph Koshy __P4MASK(bogus0, 4), 1681ebccf1e3SJoseph Koshy __P4MASK(bogus1, 5), 1682ebccf1e3SJoseph Koshy __P4MASK(bogus2, 6), 1683ebccf1e3SJoseph Koshy __P4MASK(bogus3, 7), 1684ebccf1e3SJoseph Koshy NULLMASK 1685ebccf1e3SJoseph Koshy }; 1686ebccf1e3SJoseph Koshy 1687ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_re[] = { /* replay event */ 1688ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1689ebccf1e3SJoseph Koshy __P4MASK(bogus, 1), 1690ebccf1e3SJoseph Koshy NULLMASK 1691ebccf1e3SJoseph Koshy }; 1692ebccf1e3SJoseph Koshy 1693ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_insret[] = { /* instr retired */ 1694ebccf1e3SJoseph Koshy __P4MASK(nbogusntag, 0), 1695ebccf1e3SJoseph Koshy __P4MASK(nbogustag, 1), 1696ebccf1e3SJoseph Koshy __P4MASK(bogusntag, 2), 1697ebccf1e3SJoseph Koshy __P4MASK(bogustag, 3), 1698ebccf1e3SJoseph Koshy NULLMASK 1699ebccf1e3SJoseph Koshy }; 1700ebccf1e3SJoseph Koshy 1701ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ur[] = { /* uops retired */ 1702ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1703ebccf1e3SJoseph Koshy __P4MASK(bogus, 1), 1704ebccf1e3SJoseph Koshy NULLMASK 1705ebccf1e3SJoseph Koshy }; 1706ebccf1e3SJoseph Koshy 1707ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ut[] = { /* uop type */ 1708ebccf1e3SJoseph Koshy __P4MASK(tagloads, 1), 1709ebccf1e3SJoseph Koshy __P4MASK(tagstores, 2), 1710ebccf1e3SJoseph Koshy NULLMASK 1711ebccf1e3SJoseph Koshy }; 1712ebccf1e3SJoseph Koshy 1713ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_br[] = { /* branch retired */ 1714ebccf1e3SJoseph Koshy __P4MASK(mmnp, 0), 1715ebccf1e3SJoseph Koshy __P4MASK(mmnm, 1), 1716ebccf1e3SJoseph Koshy __P4MASK(mmtp, 2), 1717ebccf1e3SJoseph Koshy __P4MASK(mmtm, 3), 1718ebccf1e3SJoseph Koshy NULLMASK 1719ebccf1e3SJoseph Koshy }; 1720ebccf1e3SJoseph Koshy 1721ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_mbr[] = { /* mispred branch retired */ 1722ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1723ebccf1e3SJoseph Koshy NULLMASK 1724ebccf1e3SJoseph Koshy }; 1725ebccf1e3SJoseph Koshy 1726ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xa[] = { /* x87 assist */ 1727ebccf1e3SJoseph Koshy __P4MASK(fpsu, 0), 1728ebccf1e3SJoseph Koshy __P4MASK(fpso, 1), 1729ebccf1e3SJoseph Koshy __P4MASK(poao, 2), 1730ebccf1e3SJoseph Koshy __P4MASK(poau, 3), 1731ebccf1e3SJoseph Koshy __P4MASK(prea, 4), 1732ebccf1e3SJoseph Koshy NULLMASK 1733ebccf1e3SJoseph Koshy }; 1734ebccf1e3SJoseph Koshy 1735ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_machclr[] = { /* machine clear */ 1736ebccf1e3SJoseph Koshy __P4MASK(clear, 0), 1737ebccf1e3SJoseph Koshy __P4MASK(moclear, 2), 1738ebccf1e3SJoseph Koshy __P4MASK(smclear, 3), 1739ebccf1e3SJoseph Koshy NULLMASK 1740ebccf1e3SJoseph Koshy }; 1741ebccf1e3SJoseph Koshy 1742ebccf1e3SJoseph Koshy /* P4 event parser */ 1743ebccf1e3SJoseph Koshy static int 1744ebccf1e3SJoseph Koshy p4_allocate_pmc(enum pmc_event pe, char *ctrspec, 1745ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 1746ebccf1e3SJoseph Koshy { 1747ebccf1e3SJoseph Koshy 1748ebccf1e3SJoseph Koshy char *e, *p, *q; 1749ebccf1e3SJoseph Koshy int count, has_tag, has_busreqtype, n; 17501e862e5aSFabien Thomas uint32_t cccractivemask; 17511e862e5aSFabien Thomas uint64_t evmask; 1752ebccf1e3SJoseph Koshy const struct pmc_masks *pm, *pmask; 1753ebccf1e3SJoseph Koshy 1754789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1755f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig = 1756f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 0; 1757ebccf1e3SJoseph Koshy 1758ebccf1e3SJoseph Koshy pmask = NULL; 1759ebccf1e3SJoseph Koshy evmask = 0; 1760ebccf1e3SJoseph Koshy cccractivemask = 0x3; 1761ebccf1e3SJoseph Koshy has_tag = has_busreqtype = 0; 1762ebccf1e3SJoseph Koshy 1763ebccf1e3SJoseph Koshy #define __P4SETMASK(M) do { \ 1764ebccf1e3SJoseph Koshy pmask = p4_mask_##M; \ 1765ebccf1e3SJoseph Koshy } while (0) 1766ebccf1e3SJoseph Koshy 1767ebccf1e3SJoseph Koshy switch (pe) { 1768ebccf1e3SJoseph Koshy case PMC_EV_P4_TC_DELIVER_MODE: 1769ebccf1e3SJoseph Koshy __P4SETMASK(tcdm); 1770ebccf1e3SJoseph Koshy break; 1771ebccf1e3SJoseph Koshy case PMC_EV_P4_BPU_FETCH_REQUEST: 1772ebccf1e3SJoseph Koshy __P4SETMASK(bfr); 1773ebccf1e3SJoseph Koshy break; 1774ebccf1e3SJoseph Koshy case PMC_EV_P4_ITLB_REFERENCE: 1775ebccf1e3SJoseph Koshy __P4SETMASK(ir); 1776ebccf1e3SJoseph Koshy break; 1777ebccf1e3SJoseph Koshy case PMC_EV_P4_MEMORY_CANCEL: 1778ebccf1e3SJoseph Koshy __P4SETMASK(memcan); 1779ebccf1e3SJoseph Koshy break; 1780ebccf1e3SJoseph Koshy case PMC_EV_P4_MEMORY_COMPLETE: 1781ebccf1e3SJoseph Koshy __P4SETMASK(memcomp); 1782ebccf1e3SJoseph Koshy break; 1783ebccf1e3SJoseph Koshy case PMC_EV_P4_LOAD_PORT_REPLAY: 1784ebccf1e3SJoseph Koshy __P4SETMASK(lpr); 1785ebccf1e3SJoseph Koshy break; 1786ebccf1e3SJoseph Koshy case PMC_EV_P4_STORE_PORT_REPLAY: 1787ebccf1e3SJoseph Koshy __P4SETMASK(spr); 1788ebccf1e3SJoseph Koshy break; 1789ebccf1e3SJoseph Koshy case PMC_EV_P4_MOB_LOAD_REPLAY: 1790ebccf1e3SJoseph Koshy __P4SETMASK(mlr); 1791ebccf1e3SJoseph Koshy break; 1792ebccf1e3SJoseph Koshy case PMC_EV_P4_PAGE_WALK_TYPE: 1793ebccf1e3SJoseph Koshy __P4SETMASK(pwt); 1794ebccf1e3SJoseph Koshy break; 1795ebccf1e3SJoseph Koshy case PMC_EV_P4_BSQ_CACHE_REFERENCE: 1796ebccf1e3SJoseph Koshy __P4SETMASK(bcr); 1797ebccf1e3SJoseph Koshy break; 1798ebccf1e3SJoseph Koshy case PMC_EV_P4_IOQ_ALLOCATION: 1799ebccf1e3SJoseph Koshy __P4SETMASK(ia); 1800ebccf1e3SJoseph Koshy has_busreqtype = 1; 1801ebccf1e3SJoseph Koshy break; 1802ebccf1e3SJoseph Koshy case PMC_EV_P4_IOQ_ACTIVE_ENTRIES: 1803ebccf1e3SJoseph Koshy __P4SETMASK(iae); 1804ebccf1e3SJoseph Koshy has_busreqtype = 1; 1805ebccf1e3SJoseph Koshy break; 1806ebccf1e3SJoseph Koshy case PMC_EV_P4_FSB_DATA_ACTIVITY: 1807ebccf1e3SJoseph Koshy __P4SETMASK(fda); 1808ebccf1e3SJoseph Koshy break; 1809ebccf1e3SJoseph Koshy case PMC_EV_P4_BSQ_ALLOCATION: 1810ebccf1e3SJoseph Koshy __P4SETMASK(ba); 1811ebccf1e3SJoseph Koshy break; 1812ebccf1e3SJoseph Koshy case PMC_EV_P4_SSE_INPUT_ASSIST: 1813ebccf1e3SJoseph Koshy __P4SETMASK(sia); 1814ebccf1e3SJoseph Koshy break; 1815ebccf1e3SJoseph Koshy case PMC_EV_P4_PACKED_SP_UOP: 1816ebccf1e3SJoseph Koshy __P4SETMASK(psu); 1817ebccf1e3SJoseph Koshy break; 1818ebccf1e3SJoseph Koshy case PMC_EV_P4_PACKED_DP_UOP: 1819ebccf1e3SJoseph Koshy __P4SETMASK(pdu); 1820ebccf1e3SJoseph Koshy break; 1821ebccf1e3SJoseph Koshy case PMC_EV_P4_SCALAR_SP_UOP: 1822ebccf1e3SJoseph Koshy __P4SETMASK(ssu); 1823ebccf1e3SJoseph Koshy break; 1824ebccf1e3SJoseph Koshy case PMC_EV_P4_SCALAR_DP_UOP: 1825ebccf1e3SJoseph Koshy __P4SETMASK(sdu); 1826ebccf1e3SJoseph Koshy break; 1827ebccf1e3SJoseph Koshy case PMC_EV_P4_64BIT_MMX_UOP: 1828ebccf1e3SJoseph Koshy __P4SETMASK(64bmu); 1829ebccf1e3SJoseph Koshy break; 1830ebccf1e3SJoseph Koshy case PMC_EV_P4_128BIT_MMX_UOP: 1831ebccf1e3SJoseph Koshy __P4SETMASK(128bmu); 1832ebccf1e3SJoseph Koshy break; 1833ebccf1e3SJoseph Koshy case PMC_EV_P4_X87_FP_UOP: 1834ebccf1e3SJoseph Koshy __P4SETMASK(xfu); 1835ebccf1e3SJoseph Koshy break; 1836ebccf1e3SJoseph Koshy case PMC_EV_P4_X87_SIMD_MOVES_UOP: 1837ebccf1e3SJoseph Koshy __P4SETMASK(xsmu); 1838ebccf1e3SJoseph Koshy break; 1839ebccf1e3SJoseph Koshy case PMC_EV_P4_GLOBAL_POWER_EVENTS: 1840ebccf1e3SJoseph Koshy __P4SETMASK(gpe); 1841ebccf1e3SJoseph Koshy break; 1842ebccf1e3SJoseph Koshy case PMC_EV_P4_TC_MS_XFER: 1843ebccf1e3SJoseph Koshy __P4SETMASK(tmx); 1844ebccf1e3SJoseph Koshy break; 1845ebccf1e3SJoseph Koshy case PMC_EV_P4_UOP_QUEUE_WRITES: 1846ebccf1e3SJoseph Koshy __P4SETMASK(uqw); 1847ebccf1e3SJoseph Koshy break; 1848ebccf1e3SJoseph Koshy case PMC_EV_P4_RETIRED_MISPRED_BRANCH_TYPE: 1849ebccf1e3SJoseph Koshy __P4SETMASK(rmbt); 1850ebccf1e3SJoseph Koshy break; 1851ebccf1e3SJoseph Koshy case PMC_EV_P4_RETIRED_BRANCH_TYPE: 1852ebccf1e3SJoseph Koshy __P4SETMASK(rbt); 1853ebccf1e3SJoseph Koshy break; 1854ebccf1e3SJoseph Koshy case PMC_EV_P4_RESOURCE_STALL: 1855ebccf1e3SJoseph Koshy __P4SETMASK(rs); 1856ebccf1e3SJoseph Koshy break; 1857ebccf1e3SJoseph Koshy case PMC_EV_P4_WC_BUFFER: 1858ebccf1e3SJoseph Koshy __P4SETMASK(wb); 1859ebccf1e3SJoseph Koshy break; 1860ebccf1e3SJoseph Koshy case PMC_EV_P4_BSQ_ACTIVE_ENTRIES: 1861ebccf1e3SJoseph Koshy case PMC_EV_P4_B2B_CYCLES: 1862ebccf1e3SJoseph Koshy case PMC_EV_P4_BNR: 1863ebccf1e3SJoseph Koshy case PMC_EV_P4_SNOOP: 1864ebccf1e3SJoseph Koshy case PMC_EV_P4_RESPONSE: 1865ebccf1e3SJoseph Koshy break; 1866ebccf1e3SJoseph Koshy case PMC_EV_P4_FRONT_END_EVENT: 1867ebccf1e3SJoseph Koshy __P4SETMASK(fee); 1868ebccf1e3SJoseph Koshy break; 1869ebccf1e3SJoseph Koshy case PMC_EV_P4_EXECUTION_EVENT: 1870ebccf1e3SJoseph Koshy __P4SETMASK(ee); 1871ebccf1e3SJoseph Koshy break; 1872ebccf1e3SJoseph Koshy case PMC_EV_P4_REPLAY_EVENT: 1873ebccf1e3SJoseph Koshy __P4SETMASK(re); 1874ebccf1e3SJoseph Koshy break; 1875ebccf1e3SJoseph Koshy case PMC_EV_P4_INSTR_RETIRED: 1876ebccf1e3SJoseph Koshy __P4SETMASK(insret); 1877ebccf1e3SJoseph Koshy break; 1878ebccf1e3SJoseph Koshy case PMC_EV_P4_UOPS_RETIRED: 1879ebccf1e3SJoseph Koshy __P4SETMASK(ur); 1880ebccf1e3SJoseph Koshy break; 1881ebccf1e3SJoseph Koshy case PMC_EV_P4_UOP_TYPE: 1882ebccf1e3SJoseph Koshy __P4SETMASK(ut); 1883ebccf1e3SJoseph Koshy break; 1884ebccf1e3SJoseph Koshy case PMC_EV_P4_BRANCH_RETIRED: 1885ebccf1e3SJoseph Koshy __P4SETMASK(br); 1886ebccf1e3SJoseph Koshy break; 1887ebccf1e3SJoseph Koshy case PMC_EV_P4_MISPRED_BRANCH_RETIRED: 1888ebccf1e3SJoseph Koshy __P4SETMASK(mbr); 1889ebccf1e3SJoseph Koshy break; 1890ebccf1e3SJoseph Koshy case PMC_EV_P4_X87_ASSIST: 1891ebccf1e3SJoseph Koshy __P4SETMASK(xa); 1892ebccf1e3SJoseph Koshy break; 1893ebccf1e3SJoseph Koshy case PMC_EV_P4_MACHINE_CLEAR: 1894ebccf1e3SJoseph Koshy __P4SETMASK(machclr); 1895ebccf1e3SJoseph Koshy break; 1896ebccf1e3SJoseph Koshy default: 1897aa342b1fSJoseph Koshy return (-1); 1898ebccf1e3SJoseph Koshy } 1899ebccf1e3SJoseph Koshy 1900ebccf1e3SJoseph Koshy /* process additional flags */ 1901ebccf1e3SJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 1902ebccf1e3SJoseph Koshy if (KWPREFIXMATCH(p, P4_KW_ACTIVE)) { 1903ebccf1e3SJoseph Koshy q = strchr(p, '='); 1904ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1905aa342b1fSJoseph Koshy return (-1); 1906ebccf1e3SJoseph Koshy 1907789140c0SJoseph Koshy if (strcasecmp(q, P4_KW_ACTIVE_NONE) == 0) 1908ebccf1e3SJoseph Koshy cccractivemask = 0x0; 1909789140c0SJoseph Koshy else if (strcasecmp(q, P4_KW_ACTIVE_SINGLE) == 0) 1910ebccf1e3SJoseph Koshy cccractivemask = 0x1; 1911789140c0SJoseph Koshy else if (strcasecmp(q, P4_KW_ACTIVE_BOTH) == 0) 1912ebccf1e3SJoseph Koshy cccractivemask = 0x2; 1913789140c0SJoseph Koshy else if (strcasecmp(q, P4_KW_ACTIVE_ANY) == 0) 1914ebccf1e3SJoseph Koshy cccractivemask = 0x3; 1915ebccf1e3SJoseph Koshy else 1916aa342b1fSJoseph Koshy return (-1); 1917ebccf1e3SJoseph Koshy 1918ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, P4_KW_BUSREQTYPE)) { 1919ebccf1e3SJoseph Koshy if (has_busreqtype == 0) 1920aa342b1fSJoseph Koshy return (-1); 1921ebccf1e3SJoseph Koshy 1922ebccf1e3SJoseph Koshy q = strchr(p, '='); 1923ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1924aa342b1fSJoseph Koshy return (-1); 1925ebccf1e3SJoseph Koshy 1926ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 1927ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 1928aa342b1fSJoseph Koshy return (-1); 1929ebccf1e3SJoseph Koshy evmask = (evmask & ~0x1F) | (count & 0x1F); 1930ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P4_KW_CASCADE)) 1931ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_CASCADE; 1932ebccf1e3SJoseph Koshy else if (KWMATCH(p, P4_KW_EDGE)) 1933ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1934ebccf1e3SJoseph Koshy else if (KWMATCH(p, P4_KW_INV)) 1935ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 1936ebccf1e3SJoseph Koshy else if (KWPREFIXMATCH(p, P4_KW_MASK "=")) { 1937ebccf1e3SJoseph Koshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 1938aa342b1fSJoseph Koshy return (-1); 1939ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1940ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P4_KW_OS)) 1941ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 1942ebccf1e3SJoseph Koshy else if (KWMATCH(p, P4_KW_PRECISE)) 1943ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_PRECISE; 1944ebccf1e3SJoseph Koshy else if (KWPREFIXMATCH(p, P4_KW_TAG "=")) { 1945ebccf1e3SJoseph Koshy if (has_tag == 0) 1946aa342b1fSJoseph Koshy return (-1); 1947ebccf1e3SJoseph Koshy 1948ebccf1e3SJoseph Koshy q = strchr(p, '='); 1949ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1950aa342b1fSJoseph Koshy return (-1); 1951ebccf1e3SJoseph Koshy 1952ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 1953ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 1954aa342b1fSJoseph Koshy return (-1); 1955ebccf1e3SJoseph Koshy 1956ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_TAGGING; 1957f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig |= 1958ebccf1e3SJoseph Koshy P4_ESCR_TO_TAG_VALUE(count); 1959ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, P4_KW_THRESHOLD "=")) { 1960ebccf1e3SJoseph Koshy q = strchr(p, '='); 1961ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1962aa342b1fSJoseph Koshy return (-1); 1963ebccf1e3SJoseph Koshy 1964ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 1965ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 1966aa342b1fSJoseph Koshy return (-1); 1967ebccf1e3SJoseph Koshy 1968ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 1969f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig &= 1970f263522aSJoseph Koshy ~P4_CCCR_THRESHOLD_MASK; 1971f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |= 1972f263522aSJoseph Koshy P4_CCCR_TO_THRESHOLD(count); 1973ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P4_KW_USR)) 1974ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 1975ebccf1e3SJoseph Koshy else 1976aa342b1fSJoseph Koshy return (-1); 1977ebccf1e3SJoseph Koshy } 1978ebccf1e3SJoseph Koshy 1979ebccf1e3SJoseph Koshy /* other post processing */ 1980ebccf1e3SJoseph Koshy if (pe == PMC_EV_P4_IOQ_ALLOCATION || 1981ebccf1e3SJoseph Koshy pe == PMC_EV_P4_FSB_DATA_ACTIVITY || 1982ebccf1e3SJoseph Koshy pe == PMC_EV_P4_BSQ_ALLOCATION) 1983ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1984ebccf1e3SJoseph Koshy 1985ebccf1e3SJoseph Koshy /* fill in thread activity mask */ 1986f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |= 1987ebccf1e3SJoseph Koshy P4_CCCR_TO_ACTIVE_THREAD(cccractivemask); 1988ebccf1e3SJoseph Koshy 1989ebccf1e3SJoseph Koshy if (evmask) 1990ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1991ebccf1e3SJoseph Koshy 1992ebccf1e3SJoseph Koshy switch (pe) { 1993ebccf1e3SJoseph Koshy case PMC_EV_P4_FSB_DATA_ACTIVITY: 1994ebccf1e3SJoseph Koshy if ((evmask & 0x06) == 0x06 || 1995ebccf1e3SJoseph Koshy (evmask & 0x18) == 0x18) 1996aa342b1fSJoseph Koshy return (-1); /* can't have own+other bits together */ 1997ebccf1e3SJoseph Koshy if (evmask == 0) /* default:drdy-{drv,own}+dbsy{drv,own} */ 1998ebccf1e3SJoseph Koshy evmask = 0x1D; 1999ebccf1e3SJoseph Koshy break; 2000ebccf1e3SJoseph Koshy case PMC_EV_P4_MACHINE_CLEAR: 2001ebccf1e3SJoseph Koshy /* only one bit is allowed to be set */ 2002ebccf1e3SJoseph Koshy if ((evmask & (evmask - 1)) != 0) 2003aa342b1fSJoseph Koshy return (-1); 2004ebccf1e3SJoseph Koshy if (evmask == 0) { 2005ebccf1e3SJoseph Koshy evmask = 0x1; /* 'CLEAR' */ 2006ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2007ebccf1e3SJoseph Koshy } 2008ebccf1e3SJoseph Koshy break; 2009ebccf1e3SJoseph Koshy default: 2010ebccf1e3SJoseph Koshy if (evmask == 0 && pmask) { 2011ebccf1e3SJoseph Koshy for (pm = pmask; pm->pm_name; pm++) 2012ebccf1e3SJoseph Koshy evmask |= pm->pm_value; 2013ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2014ebccf1e3SJoseph Koshy } 2015ebccf1e3SJoseph Koshy } 2016ebccf1e3SJoseph Koshy 2017f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 2018f263522aSJoseph Koshy P4_ESCR_TO_EVENT_MASK(evmask); 2019ebccf1e3SJoseph Koshy 2020aa342b1fSJoseph Koshy return (0); 2021ebccf1e3SJoseph Koshy } 2022ebccf1e3SJoseph Koshy 202386a65549SJoseph Koshy #endif 202486a65549SJoseph Koshy 202586a65549SJoseph Koshy #if defined(__i386__) 202686a65549SJoseph Koshy 2027ebccf1e3SJoseph Koshy /* 2028f263522aSJoseph Koshy * Pentium style PMCs 2029f263522aSJoseph Koshy */ 2030f263522aSJoseph Koshy 2031f263522aSJoseph Koshy static struct pmc_event_alias p5_aliases[] = { 20320b9b757dSJoseph Koshy EV_ALIAS("branches", "p5-taken-branches"), 2033f263522aSJoseph Koshy EV_ALIAS("cycles", "tsc"), 20340b9b757dSJoseph Koshy EV_ALIAS("dc-misses", "p5-data-read-miss-or-write-miss"), 20350b9b757dSJoseph Koshy EV_ALIAS("ic-misses", "p5-code-cache-miss"), 20360b9b757dSJoseph Koshy EV_ALIAS("instructions", "p5-instructions-executed"), 20370b9b757dSJoseph Koshy EV_ALIAS("interrupts", "p5-hardware-interrupts"), 20380b9b757dSJoseph Koshy EV_ALIAS("unhalted-cycles", 20390b9b757dSJoseph Koshy "p5-number-of-cycles-not-in-halt-state"), 2040f263522aSJoseph Koshy EV_ALIAS(NULL, NULL) 2041f263522aSJoseph Koshy }; 2042f263522aSJoseph Koshy 2043f263522aSJoseph Koshy static int 2044f263522aSJoseph Koshy p5_allocate_pmc(enum pmc_event pe, char *ctrspec, 2045f263522aSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 2046f263522aSJoseph Koshy { 2047aa342b1fSJoseph Koshy return (-1 || pe || ctrspec || pmc_config); /* shut up gcc */ 2048f263522aSJoseph Koshy } 2049f263522aSJoseph Koshy 2050f263522aSJoseph Koshy /* 2051ebccf1e3SJoseph Koshy * Pentium Pro style PMCs. These PMCs are found in Pentium II, Pentium III, 2052ebccf1e3SJoseph Koshy * and Pentium M CPUs. 2053ebccf1e3SJoseph Koshy */ 2054ebccf1e3SJoseph Koshy 2055ebccf1e3SJoseph Koshy static struct pmc_event_alias p6_aliases[] = { 2056ebccf1e3SJoseph Koshy EV_ALIAS("branches", "p6-br-inst-retired"), 2057ebccf1e3SJoseph Koshy EV_ALIAS("branch-mispredicts", "p6-br-miss-pred-retired"), 2058ebccf1e3SJoseph Koshy EV_ALIAS("cycles", "tsc"), 2059d56c5d4bSJoseph Koshy EV_ALIAS("dc-misses", "p6-dcu-lines-in"), 206073e2d811SJoseph Koshy EV_ALIAS("ic-misses", "p6-ifu-fetch-miss"), 2061ebccf1e3SJoseph Koshy EV_ALIAS("instructions", "p6-inst-retired"), 2062ebccf1e3SJoseph Koshy EV_ALIAS("interrupts", "p6-hw-int-rx"), 2063177a2f22SJoseph Koshy EV_ALIAS("unhalted-cycles", "p6-cpu-clk-unhalted"), 2064ebccf1e3SJoseph Koshy EV_ALIAS(NULL, NULL) 2065ebccf1e3SJoseph Koshy }; 2066ebccf1e3SJoseph Koshy 2067ebccf1e3SJoseph Koshy #define P6_KW_CMASK "cmask" 2068ebccf1e3SJoseph Koshy #define P6_KW_EDGE "edge" 2069ebccf1e3SJoseph Koshy #define P6_KW_INV "inv" 2070ebccf1e3SJoseph Koshy #define P6_KW_OS "os" 2071ebccf1e3SJoseph Koshy #define P6_KW_UMASK "umask" 2072ebccf1e3SJoseph Koshy #define P6_KW_USR "usr" 2073ebccf1e3SJoseph Koshy 2074ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mesi[] = { 2075ebccf1e3SJoseph Koshy PMCMASK(m, 0x01), 2076ebccf1e3SJoseph Koshy PMCMASK(e, 0x02), 2077ebccf1e3SJoseph Koshy PMCMASK(s, 0x04), 2078ebccf1e3SJoseph Koshy PMCMASK(i, 0x08), 2079ebccf1e3SJoseph Koshy NULLMASK 2080ebccf1e3SJoseph Koshy }; 2081ebccf1e3SJoseph Koshy 2082ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mesihw[] = { 2083ebccf1e3SJoseph Koshy PMCMASK(m, 0x01), 2084ebccf1e3SJoseph Koshy PMCMASK(e, 0x02), 2085ebccf1e3SJoseph Koshy PMCMASK(s, 0x04), 2086ebccf1e3SJoseph Koshy PMCMASK(i, 0x08), 2087ebccf1e3SJoseph Koshy PMCMASK(nonhw, 0x00), 2088ebccf1e3SJoseph Koshy PMCMASK(hw, 0x10), 2089ebccf1e3SJoseph Koshy PMCMASK(both, 0x30), 2090ebccf1e3SJoseph Koshy NULLMASK 2091ebccf1e3SJoseph Koshy }; 2092ebccf1e3SJoseph Koshy 2093ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_hw[] = { 2094ebccf1e3SJoseph Koshy PMCMASK(nonhw, 0x00), 2095ebccf1e3SJoseph Koshy PMCMASK(hw, 0x10), 2096ebccf1e3SJoseph Koshy PMCMASK(both, 0x30), 2097ebccf1e3SJoseph Koshy NULLMASK 2098ebccf1e3SJoseph Koshy }; 2099ebccf1e3SJoseph Koshy 2100ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_any[] = { 2101ebccf1e3SJoseph Koshy PMCMASK(self, 0x00), 2102ebccf1e3SJoseph Koshy PMCMASK(any, 0x20), 2103ebccf1e3SJoseph Koshy NULLMASK 2104ebccf1e3SJoseph Koshy }; 2105ebccf1e3SJoseph Koshy 2106ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_ekp[] = { 2107ebccf1e3SJoseph Koshy PMCMASK(nta, 0x00), 2108ebccf1e3SJoseph Koshy PMCMASK(t1, 0x01), 2109ebccf1e3SJoseph Koshy PMCMASK(t2, 0x02), 2110ebccf1e3SJoseph Koshy PMCMASK(wos, 0x03), 2111ebccf1e3SJoseph Koshy NULLMASK 2112ebccf1e3SJoseph Koshy }; 2113ebccf1e3SJoseph Koshy 2114ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_pps[] = { 2115ebccf1e3SJoseph Koshy PMCMASK(packed-and-scalar, 0x00), 2116ebccf1e3SJoseph Koshy PMCMASK(scalar, 0x01), 2117ebccf1e3SJoseph Koshy NULLMASK 2118ebccf1e3SJoseph Koshy }; 2119ebccf1e3SJoseph Koshy 2120ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mite[] = { 2121ebccf1e3SJoseph Koshy PMCMASK(packed-multiply, 0x01), 2122ebccf1e3SJoseph Koshy PMCMASK(packed-shift, 0x02), 2123ebccf1e3SJoseph Koshy PMCMASK(pack, 0x04), 2124ebccf1e3SJoseph Koshy PMCMASK(unpack, 0x08), 2125ebccf1e3SJoseph Koshy PMCMASK(packed-logical, 0x10), 2126ebccf1e3SJoseph Koshy PMCMASK(packed-arithmetic, 0x20), 2127ebccf1e3SJoseph Koshy NULLMASK 2128ebccf1e3SJoseph Koshy }; 2129ebccf1e3SJoseph Koshy 2130ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_fmt[] = { 2131ebccf1e3SJoseph Koshy PMCMASK(mmxtofp, 0x00), 2132ebccf1e3SJoseph Koshy PMCMASK(fptommx, 0x01), 2133ebccf1e3SJoseph Koshy NULLMASK 2134ebccf1e3SJoseph Koshy }; 2135ebccf1e3SJoseph Koshy 2136ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_sr[] = { 2137ebccf1e3SJoseph Koshy PMCMASK(es, 0x01), 2138ebccf1e3SJoseph Koshy PMCMASK(ds, 0x02), 2139ebccf1e3SJoseph Koshy PMCMASK(fs, 0x04), 2140ebccf1e3SJoseph Koshy PMCMASK(gs, 0x08), 2141ebccf1e3SJoseph Koshy NULLMASK 2142ebccf1e3SJoseph Koshy }; 2143ebccf1e3SJoseph Koshy 2144ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_eet[] = { 2145ebccf1e3SJoseph Koshy PMCMASK(all, 0x00), 2146ebccf1e3SJoseph Koshy PMCMASK(freq, 0x02), 2147ebccf1e3SJoseph Koshy NULLMASK 2148ebccf1e3SJoseph Koshy }; 2149ebccf1e3SJoseph Koshy 2150ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_efur[] = { 2151ebccf1e3SJoseph Koshy PMCMASK(all, 0x00), 2152ebccf1e3SJoseph Koshy PMCMASK(loadop, 0x01), 2153ebccf1e3SJoseph Koshy PMCMASK(stdsta, 0x02), 2154ebccf1e3SJoseph Koshy NULLMASK 2155ebccf1e3SJoseph Koshy }; 2156ebccf1e3SJoseph Koshy 2157ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_essir[] = { 2158ebccf1e3SJoseph Koshy PMCMASK(sse-packed-single, 0x00), 2159ebccf1e3SJoseph Koshy PMCMASK(sse-packed-single-scalar-single, 0x01), 2160ebccf1e3SJoseph Koshy PMCMASK(sse2-packed-double, 0x02), 2161ebccf1e3SJoseph Koshy PMCMASK(sse2-scalar-double, 0x03), 2162ebccf1e3SJoseph Koshy NULLMASK 2163ebccf1e3SJoseph Koshy }; 2164ebccf1e3SJoseph Koshy 2165ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_esscir[] = { 2166ebccf1e3SJoseph Koshy PMCMASK(sse-packed-single, 0x00), 2167ebccf1e3SJoseph Koshy PMCMASK(sse-scalar-single, 0x01), 2168ebccf1e3SJoseph Koshy PMCMASK(sse2-packed-double, 0x02), 2169ebccf1e3SJoseph Koshy PMCMASK(sse2-scalar-double, 0x03), 2170ebccf1e3SJoseph Koshy NULLMASK 2171ebccf1e3SJoseph Koshy }; 2172ebccf1e3SJoseph Koshy 2173ebccf1e3SJoseph Koshy /* P6 event parser */ 2174ebccf1e3SJoseph Koshy static int 2175ebccf1e3SJoseph Koshy p6_allocate_pmc(enum pmc_event pe, char *ctrspec, 2176ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 2177ebccf1e3SJoseph Koshy { 2178ebccf1e3SJoseph Koshy char *e, *p, *q; 21791e862e5aSFabien Thomas uint64_t evmask; 2180ebccf1e3SJoseph Koshy int count, n; 2181ebccf1e3SJoseph Koshy const struct pmc_masks *pm, *pmask; 2182ebccf1e3SJoseph Koshy 2183789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2184f263522aSJoseph Koshy pmc_config->pm_md.pm_ppro.pm_ppro_config = 0; 2185ebccf1e3SJoseph Koshy 2186ebccf1e3SJoseph Koshy evmask = 0; 2187ebccf1e3SJoseph Koshy 2188ebccf1e3SJoseph Koshy #define P6MASKSET(M) pmask = p6_mask_ ## M 2189ebccf1e3SJoseph Koshy 2190ebccf1e3SJoseph Koshy switch(pe) { 2191ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_IFETCH: P6MASKSET(mesi); break; 2192ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_LD: P6MASKSET(mesi); break; 2193ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_ST: P6MASKSET(mesi); break; 2194ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_RQSTS: P6MASKSET(mesi); break; 2195ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_DRDY_CLOCKS: 2196ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_LOCK_CLOCKS: 2197ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BRD: 2198ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_RFO: 2199ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_WB: 2200ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_IFETCH: 2201ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_INVAL: 2202ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_PWR: 2203ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_P: 2204ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_IO: 2205ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_DEF: 2206ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BURST: 2207ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_ANY: 2208ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_MEM: 2209ebccf1e3SJoseph Koshy P6MASKSET(any); break; 2210ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED: 2211ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_MISS: 2212ebccf1e3SJoseph Koshy P6MASKSET(ekp); break; 2213ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_INST_RETIRED: 2214ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_COMP_INST_RET: 2215ebccf1e3SJoseph Koshy P6MASKSET(pps); break; 2216ebccf1e3SJoseph Koshy case PMC_EV_P6_MMX_INSTR_TYPE_EXEC: 2217ebccf1e3SJoseph Koshy P6MASKSET(mite); break; 2218ebccf1e3SJoseph Koshy case PMC_EV_P6_FP_MMX_TRANS: 2219ebccf1e3SJoseph Koshy P6MASKSET(fmt); break; 2220ebccf1e3SJoseph Koshy case PMC_EV_P6_SEG_RENAME_STALLS: 2221ebccf1e3SJoseph Koshy case PMC_EV_P6_SEG_REG_RENAMES: 2222ebccf1e3SJoseph Koshy P6MASKSET(sr); break; 2223ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_EST_TRANS: 2224ebccf1e3SJoseph Koshy P6MASKSET(eet); break; 2225ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_FUSED_UOPS_RET: 2226ebccf1e3SJoseph Koshy P6MASKSET(efur); break; 2227ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED: 2228ebccf1e3SJoseph Koshy P6MASKSET(essir); break; 2229ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED: 2230ebccf1e3SJoseph Koshy P6MASKSET(esscir); break; 2231ebccf1e3SJoseph Koshy default: 2232ebccf1e3SJoseph Koshy pmask = NULL; 2233ebccf1e3SJoseph Koshy break; 2234ebccf1e3SJoseph Koshy } 2235ebccf1e3SJoseph Koshy 2236ebccf1e3SJoseph Koshy /* Pentium M PMCs have a few events with different semantics */ 2237ebccf1e3SJoseph Koshy if (cpu_info.pm_cputype == PMC_CPU_INTEL_PM) { 2238ebccf1e3SJoseph Koshy if (pe == PMC_EV_P6_L2_LD || 2239ebccf1e3SJoseph Koshy pe == PMC_EV_P6_L2_LINES_IN || 2240ebccf1e3SJoseph Koshy pe == PMC_EV_P6_L2_LINES_OUT) 2241ebccf1e3SJoseph Koshy P6MASKSET(mesihw); 2242ebccf1e3SJoseph Koshy else if (pe == PMC_EV_P6_L2_M_LINES_OUTM) 2243ebccf1e3SJoseph Koshy P6MASKSET(hw); 2244ebccf1e3SJoseph Koshy } 2245ebccf1e3SJoseph Koshy 2246ebccf1e3SJoseph Koshy /* Parse additional modifiers if present */ 2247ebccf1e3SJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 2248ebccf1e3SJoseph Koshy if (KWPREFIXMATCH(p, P6_KW_CMASK "=")) { 2249ebccf1e3SJoseph Koshy q = strchr(p, '='); 2250ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 2251aa342b1fSJoseph Koshy return (-1); 2252ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 2253ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 2254aa342b1fSJoseph Koshy return (-1); 2255ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 2256f263522aSJoseph Koshy pmc_config->pm_md.pm_ppro.pm_ppro_config |= 2257f263522aSJoseph Koshy P6_EVSEL_TO_CMASK(count); 2258ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_EDGE)) { 2259ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 2260ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_INV)) { 2261ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 2262ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_OS)) { 2263ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2264ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, P6_KW_UMASK "=")) { 2265ebccf1e3SJoseph Koshy evmask = 0; 2266ebccf1e3SJoseph Koshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 2267aa342b1fSJoseph Koshy return (-1); 2268ebccf1e3SJoseph Koshy if ((pe == PMC_EV_P6_BUS_DRDY_CLOCKS || 2269ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_LOCK_CLOCKS || 2270ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_BRD || 2271ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_RFO || 2272ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_IFETCH || 2273ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_INVAL || 2274ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_PWR || 2275ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_DEF || 2276ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_BURST || 2277ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_ANY || 2278ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_MEM || 2279ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRANS_IO || 2280ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRANS_P || 2281ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRANS_WB || 2282ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_EST_TRANS || 2283ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_FUSED_UOPS_RET || 2284ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_COMP_INST_RET || 2285ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_INST_RETIRED || 2286ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_PREF_DISPATCHED || 2287ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_PREF_MISS || 2288ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED || 2289ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED || 2290ebccf1e3SJoseph Koshy pe == PMC_EV_P6_FP_MMX_TRANS) 2291aa342b1fSJoseph Koshy && (n > 1)) /* Only one mask keyword is allowed. */ 2292aa342b1fSJoseph Koshy return (-1); 2293ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2294ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_USR)) { 2295ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 2296ebccf1e3SJoseph Koshy } else 2297aa342b1fSJoseph Koshy return (-1); 2298ebccf1e3SJoseph Koshy } 2299ebccf1e3SJoseph Koshy 2300ebccf1e3SJoseph Koshy /* post processing */ 2301ebccf1e3SJoseph Koshy switch (pe) { 2302ebccf1e3SJoseph Koshy 2303ebccf1e3SJoseph Koshy /* 2304ebccf1e3SJoseph Koshy * The following events default to an evmask of 0 2305ebccf1e3SJoseph Koshy */ 2306ebccf1e3SJoseph Koshy 2307ebccf1e3SJoseph Koshy /* default => 'self' */ 2308ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_DRDY_CLOCKS: 2309ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_LOCK_CLOCKS: 2310ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BRD: 2311ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_RFO: 2312ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_WB: 2313ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_IFETCH: 2314ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_INVAL: 2315ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_PWR: 2316ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_P: 2317ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_IO: 2318ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_DEF: 2319ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BURST: 2320ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_ANY: 2321ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_MEM: 2322ebccf1e3SJoseph Koshy 2323ebccf1e3SJoseph Koshy /* default => 'nta' */ 2324ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED: 2325ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_MISS: 2326ebccf1e3SJoseph Koshy 2327ebccf1e3SJoseph Koshy /* default => 'packed and scalar' */ 2328ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_INST_RETIRED: 2329ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_COMP_INST_RET: 2330ebccf1e3SJoseph Koshy 2331ebccf1e3SJoseph Koshy /* default => 'mmx to fp transitions' */ 2332ebccf1e3SJoseph Koshy case PMC_EV_P6_FP_MMX_TRANS: 2333ebccf1e3SJoseph Koshy 2334ebccf1e3SJoseph Koshy /* default => 'SSE Packed Single' */ 2335ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED: 2336ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED: 2337ebccf1e3SJoseph Koshy 2338ebccf1e3SJoseph Koshy /* default => 'all fused micro-ops' */ 2339ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_FUSED_UOPS_RET: 2340ebccf1e3SJoseph Koshy 2341ebccf1e3SJoseph Koshy /* default => 'all transitions' */ 2342ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_EST_TRANS: 2343ebccf1e3SJoseph Koshy break; 2344ebccf1e3SJoseph Koshy 2345ebccf1e3SJoseph Koshy case PMC_EV_P6_MMX_UOPS_EXEC: 2346ebccf1e3SJoseph Koshy evmask = 0x0F; /* only value allowed */ 2347ebccf1e3SJoseph Koshy break; 2348ebccf1e3SJoseph Koshy 2349ebccf1e3SJoseph Koshy default: 2350ebccf1e3SJoseph Koshy /* 2351ebccf1e3SJoseph Koshy * For all other events, set the default event mask 2352ebccf1e3SJoseph Koshy * to a logical OR of all the allowed event mask bits. 2353ebccf1e3SJoseph Koshy */ 2354ebccf1e3SJoseph Koshy if (evmask == 0 && pmask) { 2355ebccf1e3SJoseph Koshy for (pm = pmask; pm->pm_name; pm++) 2356ebccf1e3SJoseph Koshy evmask |= pm->pm_value; 2357ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2358ebccf1e3SJoseph Koshy } 2359ebccf1e3SJoseph Koshy 2360ebccf1e3SJoseph Koshy break; 2361ebccf1e3SJoseph Koshy } 2362ebccf1e3SJoseph Koshy 2363ebccf1e3SJoseph Koshy if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) 2364f263522aSJoseph Koshy pmc_config->pm_md.pm_ppro.pm_ppro_config |= 2365f263522aSJoseph Koshy P6_EVSEL_TO_UMASK(evmask); 2366ebccf1e3SJoseph Koshy 2367aa342b1fSJoseph Koshy return (0); 2368ebccf1e3SJoseph Koshy } 2369ebccf1e3SJoseph Koshy 2370ebccf1e3SJoseph Koshy #endif 2371ebccf1e3SJoseph Koshy 2372789140c0SJoseph Koshy #if defined(__i386__) || defined(__amd64__) 2373789140c0SJoseph Koshy static int 2374789140c0SJoseph Koshy tsc_allocate_pmc(enum pmc_event pe, char *ctrspec, 2375789140c0SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 2376789140c0SJoseph Koshy { 2377789140c0SJoseph Koshy if (pe != PMC_EV_TSC_TSC) 2378789140c0SJoseph Koshy return (-1); 2379789140c0SJoseph Koshy 2380789140c0SJoseph Koshy /* TSC events must be unqualified. */ 2381789140c0SJoseph Koshy if (ctrspec && *ctrspec != '\0') 2382789140c0SJoseph Koshy return (-1); 2383789140c0SJoseph Koshy 2384789140c0SJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 2385789140c0SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_READ; 2386789140c0SJoseph Koshy 2387789140c0SJoseph Koshy return (0); 2388789140c0SJoseph Koshy } 2389789140c0SJoseph Koshy #endif 2390789140c0SJoseph Koshy 2391f5f9340bSFabien Thomas static struct pmc_event_alias generic_aliases[] = { 2392f5f9340bSFabien Thomas EV_ALIAS("instructions", "SOFT-CLOCK.HARD"), 2393f5f9340bSFabien Thomas EV_ALIAS(NULL, NULL) 2394f5f9340bSFabien Thomas }; 2395f5f9340bSFabien Thomas 2396f5f9340bSFabien Thomas static int 2397f5f9340bSFabien Thomas soft_allocate_pmc(enum pmc_event pe, char *ctrspec, 2398f5f9340bSFabien Thomas struct pmc_op_pmcallocate *pmc_config) 2399f5f9340bSFabien Thomas { 2400f5f9340bSFabien Thomas (void)ctrspec; 2401f5f9340bSFabien Thomas (void)pmc_config; 2402f5f9340bSFabien Thomas 2403f0bbe9aaSDimitry Andric if ((int)pe < PMC_EV_SOFT_FIRST || (int)pe > PMC_EV_SOFT_LAST) 2404f5f9340bSFabien Thomas return (-1); 2405f5f9340bSFabien Thomas 2406f5f9340bSFabien Thomas pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2407f5f9340bSFabien Thomas return (0); 2408f5f9340bSFabien Thomas } 2409f5f9340bSFabien Thomas 24106411d14dSRuslan Bukin #if defined(__arm__) 24110ce207d2SRui Paulo #if defined(__XSCALE__) 24120ce207d2SRui Paulo 24130ce207d2SRui Paulo static struct pmc_event_alias xscale_aliases[] = { 24140ce207d2SRui Paulo EV_ALIAS("branches", "BRANCH_RETIRED"), 24150ce207d2SRui Paulo EV_ALIAS("branch-mispredicts", "BRANCH_MISPRED"), 24160ce207d2SRui Paulo EV_ALIAS("dc-misses", "DC_MISS"), 24170ce207d2SRui Paulo EV_ALIAS("ic-misses", "IC_MISS"), 24180ce207d2SRui Paulo EV_ALIAS("instructions", "INSTR_RETIRED"), 24190ce207d2SRui Paulo EV_ALIAS(NULL, NULL) 24200ce207d2SRui Paulo }; 24210ce207d2SRui Paulo static int 24220ce207d2SRui Paulo xscale_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 24230ce207d2SRui Paulo struct pmc_op_pmcallocate *pmc_config __unused) 24240ce207d2SRui Paulo { 24250ce207d2SRui Paulo switch (pe) { 24260ce207d2SRui Paulo default: 24270ce207d2SRui Paulo break; 24280ce207d2SRui Paulo } 24290ce207d2SRui Paulo 24300ce207d2SRui Paulo return (0); 24310ce207d2SRui Paulo } 24320ce207d2SRui Paulo #endif 24330ce207d2SRui Paulo 24346411d14dSRuslan Bukin static struct pmc_event_alias armv7_aliases[] = { 24356411d14dSRuslan Bukin EV_ALIAS("dc-misses", "L1_DCACHE_REFILL"), 24366411d14dSRuslan Bukin EV_ALIAS("ic-misses", "L1_ICACHE_REFILL"), 24376411d14dSRuslan Bukin EV_ALIAS("instructions", "INSTR_EXECUTED"), 24386411d14dSRuslan Bukin EV_ALIAS(NULL, NULL) 24396411d14dSRuslan Bukin }; 24406411d14dSRuslan Bukin static int 24416411d14dSRuslan Bukin armv7_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 24426411d14dSRuslan Bukin struct pmc_op_pmcallocate *pmc_config __unused) 24436411d14dSRuslan Bukin { 24446411d14dSRuslan Bukin switch (pe) { 24456411d14dSRuslan Bukin default: 24466411d14dSRuslan Bukin break; 24476411d14dSRuslan Bukin } 24486411d14dSRuslan Bukin 24496411d14dSRuslan Bukin return (0); 24506411d14dSRuslan Bukin } 24516411d14dSRuslan Bukin #endif 24526411d14dSRuslan Bukin 2453*bc88bb2bSRuslan Bukin #if defined(__aarch64__) 2454*bc88bb2bSRuslan Bukin static struct pmc_event_alias cortex_a53_aliases[] = { 2455*bc88bb2bSRuslan Bukin EV_ALIAS(NULL, NULL) 2456*bc88bb2bSRuslan Bukin }; 2457*bc88bb2bSRuslan Bukin static struct pmc_event_alias cortex_a57_aliases[] = { 2458*bc88bb2bSRuslan Bukin EV_ALIAS(NULL, NULL) 2459*bc88bb2bSRuslan Bukin }; 2460*bc88bb2bSRuslan Bukin static int 2461*bc88bb2bSRuslan Bukin arm64_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 2462*bc88bb2bSRuslan Bukin struct pmc_op_pmcallocate *pmc_config __unused) 2463*bc88bb2bSRuslan Bukin { 2464*bc88bb2bSRuslan Bukin switch (pe) { 2465*bc88bb2bSRuslan Bukin default: 2466*bc88bb2bSRuslan Bukin break; 2467*bc88bb2bSRuslan Bukin } 2468*bc88bb2bSRuslan Bukin 2469*bc88bb2bSRuslan Bukin return (0); 2470*bc88bb2bSRuslan Bukin } 2471*bc88bb2bSRuslan Bukin #endif 2472*bc88bb2bSRuslan Bukin 2473660df75eSGeorge V. Neville-Neil #if defined(__mips__) 2474660df75eSGeorge V. Neville-Neil 2475660df75eSGeorge V. Neville-Neil static struct pmc_event_alias mips24k_aliases[] = { 2476660df75eSGeorge V. Neville-Neil EV_ALIAS("instructions", "INSTR_EXECUTED"), 2477660df75eSGeorge V. Neville-Neil EV_ALIAS("branches", "BRANCH_COMPLETED"), 2478660df75eSGeorge V. Neville-Neil EV_ALIAS("branch-mispredicts", "BRANCH_MISPRED"), 2479660df75eSGeorge V. Neville-Neil EV_ALIAS(NULL, NULL) 2480660df75eSGeorge V. Neville-Neil }; 2481660df75eSGeorge V. Neville-Neil 2482f6e6460dSAdrian Chadd static struct pmc_event_alias mips74k_aliases[] = { 2483f6e6460dSAdrian Chadd EV_ALIAS("instructions", "INSTR_EXECUTED"), 2484f6e6460dSAdrian Chadd EV_ALIAS("branches", "BRANCH_INSNS"), 2485f6e6460dSAdrian Chadd EV_ALIAS("branch-mispredicts", "MISPREDICTED_BRANCH_INSNS"), 2486f6e6460dSAdrian Chadd EV_ALIAS(NULL, NULL) 2487f6e6460dSAdrian Chadd }; 2488f6e6460dSAdrian Chadd 2489c2657f80SOleksandr Tymoshenko static struct pmc_event_alias octeon_aliases[] = { 2490c2657f80SOleksandr Tymoshenko EV_ALIAS("instructions", "RET"), 2491c2657f80SOleksandr Tymoshenko EV_ALIAS("branches", "BR"), 2492c2657f80SOleksandr Tymoshenko EV_ALIAS("branch-mispredicts", "BRMIS"), 2493c2657f80SOleksandr Tymoshenko EV_ALIAS(NULL, NULL) 2494c2657f80SOleksandr Tymoshenko }; 2495c2657f80SOleksandr Tymoshenko 24962827d3e1SOleksandr Tymoshenko #define MIPS_KW_OS "os" 24972827d3e1SOleksandr Tymoshenko #define MIPS_KW_USR "usr" 24982827d3e1SOleksandr Tymoshenko #define MIPS_KW_ANYTHREAD "anythread" 2499660df75eSGeorge V. Neville-Neil 2500660df75eSGeorge V. Neville-Neil static int 25012827d3e1SOleksandr Tymoshenko mips_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 2502660df75eSGeorge V. Neville-Neil struct pmc_op_pmcallocate *pmc_config __unused) 2503660df75eSGeorge V. Neville-Neil { 2504660df75eSGeorge V. Neville-Neil char *p; 2505660df75eSGeorge V. Neville-Neil 2506660df75eSGeorge V. Neville-Neil (void) pe; 2507660df75eSGeorge V. Neville-Neil 2508660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2509660df75eSGeorge V. Neville-Neil 2510660df75eSGeorge V. Neville-Neil while ((p = strsep(&ctrspec, ",")) != NULL) { 25112827d3e1SOleksandr Tymoshenko if (KWMATCH(p, MIPS_KW_OS)) 2512660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= PMC_CAP_SYSTEM; 25132827d3e1SOleksandr Tymoshenko else if (KWMATCH(p, MIPS_KW_USR)) 2514660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= PMC_CAP_USER; 25152827d3e1SOleksandr Tymoshenko else if (KWMATCH(p, MIPS_KW_ANYTHREAD)) 2516660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= (PMC_CAP_USER | PMC_CAP_SYSTEM); 2517660df75eSGeorge V. Neville-Neil else 2518660df75eSGeorge V. Neville-Neil return (-1); 2519660df75eSGeorge V. Neville-Neil } 2520660df75eSGeorge V. Neville-Neil 2521660df75eSGeorge V. Neville-Neil return (0); 2522660df75eSGeorge V. Neville-Neil } 25232827d3e1SOleksandr Tymoshenko 2524660df75eSGeorge V. Neville-Neil #endif /* __mips__ */ 2525660df75eSGeorge V. Neville-Neil 25267b25dccaSJustin Hibbits #if defined(__powerpc__) 25277b25dccaSJustin Hibbits 25287b25dccaSJustin Hibbits static struct pmc_event_alias ppc7450_aliases[] = { 25297b25dccaSJustin Hibbits EV_ALIAS("instructions", "INSTR_COMPLETED"), 25307b25dccaSJustin Hibbits EV_ALIAS("branches", "BRANCHES_COMPLETED"), 25317b25dccaSJustin Hibbits EV_ALIAS("branch-mispredicts", "MISPREDICTED_BRANCHES"), 25327b25dccaSJustin Hibbits EV_ALIAS(NULL, NULL) 25337b25dccaSJustin Hibbits }; 25347b25dccaSJustin Hibbits 2535169dd953SJustin Hibbits static struct pmc_event_alias ppc970_aliases[] = { 2536169dd953SJustin Hibbits EV_ALIAS("instructions", "INSTR_COMPLETED"), 2537169dd953SJustin Hibbits EV_ALIAS("cycles", "CYCLES"), 2538169dd953SJustin Hibbits EV_ALIAS(NULL, NULL) 2539169dd953SJustin Hibbits }; 2540169dd953SJustin Hibbits 2541a7452468SJustin Hibbits static struct pmc_event_alias e500_aliases[] = { 2542a7452468SJustin Hibbits EV_ALIAS("instructions", "INSTR_COMPLETED"), 2543a7452468SJustin Hibbits EV_ALIAS("cycles", "CYCLES"), 2544a7452468SJustin Hibbits EV_ALIAS(NULL, NULL) 2545a7452468SJustin Hibbits }; 2546a7452468SJustin Hibbits 2547169dd953SJustin Hibbits #define POWERPC_KW_OS "os" 2548169dd953SJustin Hibbits #define POWERPC_KW_USR "usr" 2549169dd953SJustin Hibbits #define POWERPC_KW_ANYTHREAD "anythread" 25507b25dccaSJustin Hibbits 25517b25dccaSJustin Hibbits static int 2552169dd953SJustin Hibbits powerpc_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 25537b25dccaSJustin Hibbits struct pmc_op_pmcallocate *pmc_config __unused) 25547b25dccaSJustin Hibbits { 25557b25dccaSJustin Hibbits char *p; 25567b25dccaSJustin Hibbits 25577b25dccaSJustin Hibbits (void) pe; 25587b25dccaSJustin Hibbits 25597b25dccaSJustin Hibbits pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 25607b25dccaSJustin Hibbits 25617b25dccaSJustin Hibbits while ((p = strsep(&ctrspec, ",")) != NULL) { 2562169dd953SJustin Hibbits if (KWMATCH(p, POWERPC_KW_OS)) 25637b25dccaSJustin Hibbits pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2564169dd953SJustin Hibbits else if (KWMATCH(p, POWERPC_KW_USR)) 25657b25dccaSJustin Hibbits pmc_config->pm_caps |= PMC_CAP_USER; 2566169dd953SJustin Hibbits else if (KWMATCH(p, POWERPC_KW_ANYTHREAD)) 25677b25dccaSJustin Hibbits pmc_config->pm_caps |= (PMC_CAP_USER | PMC_CAP_SYSTEM); 25687b25dccaSJustin Hibbits else 25697b25dccaSJustin Hibbits return (-1); 25707b25dccaSJustin Hibbits } 25717b25dccaSJustin Hibbits 25727b25dccaSJustin Hibbits return (0); 25737b25dccaSJustin Hibbits } 2574169dd953SJustin Hibbits 25757b25dccaSJustin Hibbits #endif /* __powerpc__ */ 25767b25dccaSJustin Hibbits 2577660df75eSGeorge V. Neville-Neil 2578789140c0SJoseph Koshy /* 2579789140c0SJoseph Koshy * Match an event name `name' with its canonical form. 2580789140c0SJoseph Koshy * 25810cfab8ddSJoseph Koshy * Matches are case insensitive and spaces, periods, underscores and 25820cfab8ddSJoseph Koshy * hyphen characters are considered to match each other. 2583789140c0SJoseph Koshy * 2584789140c0SJoseph Koshy * Returns 1 for a match, 0 otherwise. 2585789140c0SJoseph Koshy */ 2586789140c0SJoseph Koshy 2587789140c0SJoseph Koshy static int 2588789140c0SJoseph Koshy pmc_match_event_name(const char *name, const char *canonicalname) 2589789140c0SJoseph Koshy { 2590789140c0SJoseph Koshy int cc, nc; 2591789140c0SJoseph Koshy const unsigned char *c, *n; 2592789140c0SJoseph Koshy 2593789140c0SJoseph Koshy c = (const unsigned char *) canonicalname; 2594789140c0SJoseph Koshy n = (const unsigned char *) name; 2595789140c0SJoseph Koshy 2596789140c0SJoseph Koshy for (; (nc = *n) && (cc = *c); n++, c++) { 2597789140c0SJoseph Koshy 25980cfab8ddSJoseph Koshy if ((nc == ' ' || nc == '_' || nc == '-' || nc == '.') && 25990cfab8ddSJoseph Koshy (cc == ' ' || cc == '_' || cc == '-' || cc == '.')) 2600789140c0SJoseph Koshy continue; 2601789140c0SJoseph Koshy 26020cfab8ddSJoseph Koshy if (toupper(nc) == toupper(cc)) 2603789140c0SJoseph Koshy continue; 2604789140c0SJoseph Koshy 26050cfab8ddSJoseph Koshy 2606789140c0SJoseph Koshy return (0); 2607789140c0SJoseph Koshy } 2608789140c0SJoseph Koshy 2609789140c0SJoseph Koshy if (*n == '\0' && *c == '\0') 2610789140c0SJoseph Koshy return (1); 2611789140c0SJoseph Koshy 2612789140c0SJoseph Koshy return (0); 2613789140c0SJoseph Koshy } 2614789140c0SJoseph Koshy 2615789140c0SJoseph Koshy /* 2616789140c0SJoseph Koshy * Match an event name against all the event named supported by a 2617789140c0SJoseph Koshy * PMC class. 2618789140c0SJoseph Koshy * 2619789140c0SJoseph Koshy * Returns an event descriptor pointer on match or NULL otherwise. 2620789140c0SJoseph Koshy */ 2621789140c0SJoseph Koshy static const struct pmc_event_descr * 2622789140c0SJoseph Koshy pmc_match_event_class(const char *name, 2623789140c0SJoseph Koshy const struct pmc_class_descr *pcd) 2624789140c0SJoseph Koshy { 2625789140c0SJoseph Koshy size_t n; 2626789140c0SJoseph Koshy const struct pmc_event_descr *ev; 2627789140c0SJoseph Koshy 2628789140c0SJoseph Koshy ev = pcd->pm_evc_event_table; 2629789140c0SJoseph Koshy for (n = 0; n < pcd->pm_evc_event_table_size; n++, ev++) 2630789140c0SJoseph Koshy if (pmc_match_event_name(name, ev->pm_ev_name)) 2631789140c0SJoseph Koshy return (ev); 2632789140c0SJoseph Koshy 2633789140c0SJoseph Koshy return (NULL); 2634789140c0SJoseph Koshy } 2635789140c0SJoseph Koshy 2636789140c0SJoseph Koshy static int 2637789140c0SJoseph Koshy pmc_mdep_is_compatible_class(enum pmc_class pc) 2638789140c0SJoseph Koshy { 2639789140c0SJoseph Koshy size_t n; 2640789140c0SJoseph Koshy 2641789140c0SJoseph Koshy for (n = 0; n < pmc_mdep_class_list_size; n++) 2642789140c0SJoseph Koshy if (pmc_mdep_class_list[n] == pc) 2643789140c0SJoseph Koshy return (1); 2644789140c0SJoseph Koshy return (0); 2645789140c0SJoseph Koshy } 2646789140c0SJoseph Koshy 2647ebccf1e3SJoseph Koshy /* 2648ebccf1e3SJoseph Koshy * API entry points 2649ebccf1e3SJoseph Koshy */ 2650ebccf1e3SJoseph Koshy 2651ebccf1e3SJoseph Koshy int 2652ebccf1e3SJoseph Koshy pmc_allocate(const char *ctrspec, enum pmc_mode mode, 2653ebccf1e3SJoseph Koshy uint32_t flags, int cpu, pmc_id_t *pmcid) 2654ebccf1e3SJoseph Koshy { 2655789140c0SJoseph Koshy size_t n; 2656ebccf1e3SJoseph Koshy int retval; 2657ebccf1e3SJoseph Koshy char *r, *spec_copy; 2658ebccf1e3SJoseph Koshy const char *ctrname; 2659789140c0SJoseph Koshy const struct pmc_event_descr *ev; 2660789140c0SJoseph Koshy const struct pmc_event_alias *alias; 2661ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate pmc_config; 2662789140c0SJoseph Koshy const struct pmc_class_descr *pcd; 2663ebccf1e3SJoseph Koshy 2664ebccf1e3SJoseph Koshy spec_copy = NULL; 2665ebccf1e3SJoseph Koshy retval = -1; 2666ebccf1e3SJoseph Koshy 2667ebccf1e3SJoseph Koshy if (mode != PMC_MODE_SS && mode != PMC_MODE_TS && 2668ebccf1e3SJoseph Koshy mode != PMC_MODE_SC && mode != PMC_MODE_TC) { 2669ebccf1e3SJoseph Koshy errno = EINVAL; 2670ebccf1e3SJoseph Koshy goto out; 2671ebccf1e3SJoseph Koshy } 2672ebccf1e3SJoseph Koshy 2673ebccf1e3SJoseph Koshy /* replace an event alias with the canonical event specifier */ 2674ebccf1e3SJoseph Koshy if (pmc_mdep_event_aliases) 2675789140c0SJoseph Koshy for (alias = pmc_mdep_event_aliases; alias->pm_alias; alias++) 2676789140c0SJoseph Koshy if (!strcasecmp(ctrspec, alias->pm_alias)) { 2677789140c0SJoseph Koshy spec_copy = strdup(alias->pm_spec); 2678ebccf1e3SJoseph Koshy break; 2679ebccf1e3SJoseph Koshy } 2680ebccf1e3SJoseph Koshy 2681ebccf1e3SJoseph Koshy if (spec_copy == NULL) 2682ebccf1e3SJoseph Koshy spec_copy = strdup(ctrspec); 2683ebccf1e3SJoseph Koshy 2684ebccf1e3SJoseph Koshy r = spec_copy; 2685ebccf1e3SJoseph Koshy ctrname = strsep(&r, ","); 2686ebccf1e3SJoseph Koshy 2687789140c0SJoseph Koshy /* 2688789140c0SJoseph Koshy * If a explicit class prefix was given by the user, restrict the 2689789140c0SJoseph Koshy * search for the event to the specified PMC class. 2690789140c0SJoseph Koshy */ 2691789140c0SJoseph Koshy ev = NULL; 26920cfab8ddSJoseph Koshy for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) { 26930cfab8ddSJoseph Koshy pcd = pmc_class_table[n]; 2694789140c0SJoseph Koshy if (pmc_mdep_is_compatible_class(pcd->pm_evc_class) && 2695789140c0SJoseph Koshy strncasecmp(ctrname, pcd->pm_evc_name, 2696789140c0SJoseph Koshy pcd->pm_evc_name_size) == 0) { 2697789140c0SJoseph Koshy if ((ev = pmc_match_event_class(ctrname + 2698789140c0SJoseph Koshy pcd->pm_evc_name_size, pcd)) == NULL) { 2699789140c0SJoseph Koshy errno = EINVAL; 2700789140c0SJoseph Koshy goto out; 2701789140c0SJoseph Koshy } 2702ebccf1e3SJoseph Koshy break; 2703789140c0SJoseph Koshy } 2704789140c0SJoseph Koshy } 2705ebccf1e3SJoseph Koshy 2706789140c0SJoseph Koshy /* 2707789140c0SJoseph Koshy * Otherwise, search for this event in all compatible PMC 2708789140c0SJoseph Koshy * classes. 2709789140c0SJoseph Koshy */ 27100cfab8ddSJoseph Koshy for (n = 0; ev == NULL && n < PMC_CLASS_TABLE_SIZE; n++) { 27110cfab8ddSJoseph Koshy pcd = pmc_class_table[n]; 2712789140c0SJoseph Koshy if (pmc_mdep_is_compatible_class(pcd->pm_evc_class)) 2713789140c0SJoseph Koshy ev = pmc_match_event_class(ctrname, pcd); 2714789140c0SJoseph Koshy } 2715789140c0SJoseph Koshy 2716789140c0SJoseph Koshy if (ev == NULL) { 2717ebccf1e3SJoseph Koshy errno = EINVAL; 2718ebccf1e3SJoseph Koshy goto out; 2719ebccf1e3SJoseph Koshy } 2720ebccf1e3SJoseph Koshy 2721ebccf1e3SJoseph Koshy bzero(&pmc_config, sizeof(pmc_config)); 2722789140c0SJoseph Koshy pmc_config.pm_ev = ev->pm_ev_code; 2723789140c0SJoseph Koshy pmc_config.pm_class = pcd->pm_evc_class; 2724ebccf1e3SJoseph Koshy pmc_config.pm_cpu = cpu; 2725ebccf1e3SJoseph Koshy pmc_config.pm_mode = mode; 2726ebccf1e3SJoseph Koshy pmc_config.pm_flags = flags; 2727ebccf1e3SJoseph Koshy 2728ebccf1e3SJoseph Koshy if (PMC_IS_SAMPLING_MODE(mode)) 2729ebccf1e3SJoseph Koshy pmc_config.pm_caps |= PMC_CAP_INTERRUPT; 2730ebccf1e3SJoseph Koshy 2731789140c0SJoseph Koshy if (pcd->pm_evc_allocate_pmc(ev->pm_ev_code, r, &pmc_config) < 0) { 2732ebccf1e3SJoseph Koshy errno = EINVAL; 2733ebccf1e3SJoseph Koshy goto out; 2734ebccf1e3SJoseph Koshy } 2735ebccf1e3SJoseph Koshy 2736ebccf1e3SJoseph Koshy if (PMC_CALL(PMCALLOCATE, &pmc_config) < 0) 2737ebccf1e3SJoseph Koshy goto out; 2738ebccf1e3SJoseph Koshy 2739ebccf1e3SJoseph Koshy *pmcid = pmc_config.pm_pmcid; 2740ebccf1e3SJoseph Koshy 2741ebccf1e3SJoseph Koshy retval = 0; 2742ebccf1e3SJoseph Koshy 2743ebccf1e3SJoseph Koshy out: 2744ebccf1e3SJoseph Koshy if (spec_copy) 2745ebccf1e3SJoseph Koshy free(spec_copy); 2746ebccf1e3SJoseph Koshy 2747aa342b1fSJoseph Koshy return (retval); 2748ebccf1e3SJoseph Koshy } 2749ebccf1e3SJoseph Koshy 2750ebccf1e3SJoseph Koshy int 2751ebccf1e3SJoseph Koshy pmc_attach(pmc_id_t pmc, pid_t pid) 2752ebccf1e3SJoseph Koshy { 2753ebccf1e3SJoseph Koshy struct pmc_op_pmcattach pmc_attach_args; 2754ebccf1e3SJoseph Koshy 2755ebccf1e3SJoseph Koshy pmc_attach_args.pm_pmc = pmc; 2756ebccf1e3SJoseph Koshy pmc_attach_args.pm_pid = pid; 2757ebccf1e3SJoseph Koshy 2758aa342b1fSJoseph Koshy return (PMC_CALL(PMCATTACH, &pmc_attach_args)); 2759ebccf1e3SJoseph Koshy } 2760ebccf1e3SJoseph Koshy 2761ebccf1e3SJoseph Koshy int 2762c5153e19SJoseph Koshy pmc_capabilities(pmc_id_t pmcid, uint32_t *caps) 2763c5153e19SJoseph Koshy { 2764c5153e19SJoseph Koshy unsigned int i; 2765c5153e19SJoseph Koshy enum pmc_class cl; 2766c5153e19SJoseph Koshy 2767c5153e19SJoseph Koshy cl = PMC_ID_TO_CLASS(pmcid); 2768c5153e19SJoseph Koshy for (i = 0; i < cpu_info.pm_nclass; i++) 2769c5153e19SJoseph Koshy if (cpu_info.pm_classes[i].pm_class == cl) { 2770c5153e19SJoseph Koshy *caps = cpu_info.pm_classes[i].pm_caps; 2771aa342b1fSJoseph Koshy return (0); 2772c5153e19SJoseph Koshy } 2773484202faSJoseph Koshy errno = EINVAL; 2774484202faSJoseph Koshy return (-1); 2775c5153e19SJoseph Koshy } 2776c5153e19SJoseph Koshy 2777f263522aSJoseph Koshy int 2778f263522aSJoseph Koshy pmc_configure_logfile(int fd) 2779ebccf1e3SJoseph Koshy { 2780f263522aSJoseph Koshy struct pmc_op_configurelog cla; 2781f263522aSJoseph Koshy 2782f263522aSJoseph Koshy cla.pm_logfd = fd; 2783f263522aSJoseph Koshy if (PMC_CALL(CONFIGURELOG, &cla) < 0) 2784aa342b1fSJoseph Koshy return (-1); 2785aa342b1fSJoseph Koshy return (0); 2786ebccf1e3SJoseph Koshy } 2787ebccf1e3SJoseph Koshy 2788f263522aSJoseph Koshy int 2789f263522aSJoseph Koshy pmc_cpuinfo(const struct pmc_cpuinfo **pci) 2790ebccf1e3SJoseph Koshy { 2791f263522aSJoseph Koshy if (pmc_syscall == -1) { 2792f263522aSJoseph Koshy errno = ENXIO; 2793aa342b1fSJoseph Koshy return (-1); 2794ebccf1e3SJoseph Koshy } 2795ebccf1e3SJoseph Koshy 27961455fcd3SJoseph Koshy *pci = &cpu_info; 2797aa342b1fSJoseph Koshy return (0); 2798ebccf1e3SJoseph Koshy } 2799ebccf1e3SJoseph Koshy 2800f263522aSJoseph Koshy int 2801f263522aSJoseph Koshy pmc_detach(pmc_id_t pmc, pid_t pid) 2802ebccf1e3SJoseph Koshy { 2803f263522aSJoseph Koshy struct pmc_op_pmcattach pmc_detach_args; 2804ebccf1e3SJoseph Koshy 2805f263522aSJoseph Koshy pmc_detach_args.pm_pmc = pmc; 2806f263522aSJoseph Koshy pmc_detach_args.pm_pid = pid; 2807aa342b1fSJoseph Koshy return (PMC_CALL(PMCDETACH, &pmc_detach_args)); 2808ebccf1e3SJoseph Koshy } 2809ebccf1e3SJoseph Koshy 2810f263522aSJoseph Koshy int 2811f263522aSJoseph Koshy pmc_disable(int cpu, int pmc) 2812ebccf1e3SJoseph Koshy { 2813f263522aSJoseph Koshy struct pmc_op_pmcadmin ssa; 2814ebccf1e3SJoseph Koshy 2815f263522aSJoseph Koshy ssa.pm_cpu = cpu; 2816f263522aSJoseph Koshy ssa.pm_pmc = pmc; 2817f263522aSJoseph Koshy ssa.pm_state = PMC_STATE_DISABLED; 2818aa342b1fSJoseph Koshy return (PMC_CALL(PMCADMIN, &ssa)); 2819ebccf1e3SJoseph Koshy } 2820ebccf1e3SJoseph Koshy 2821f263522aSJoseph Koshy int 2822f263522aSJoseph Koshy pmc_enable(int cpu, int pmc) 2823ebccf1e3SJoseph Koshy { 2824f263522aSJoseph Koshy struct pmc_op_pmcadmin ssa; 2825ebccf1e3SJoseph Koshy 2826f263522aSJoseph Koshy ssa.pm_cpu = cpu; 2827f263522aSJoseph Koshy ssa.pm_pmc = pmc; 2828f263522aSJoseph Koshy ssa.pm_state = PMC_STATE_FREE; 2829aa342b1fSJoseph Koshy return (PMC_CALL(PMCADMIN, &ssa)); 2830ebccf1e3SJoseph Koshy } 2831ebccf1e3SJoseph Koshy 2832ebccf1e3SJoseph Koshy /* 2833ebccf1e3SJoseph Koshy * Return a list of events known to a given PMC class. 'cl' is the 2834ebccf1e3SJoseph Koshy * PMC class identifier, 'eventnames' is the returned list of 'const 2835ebccf1e3SJoseph Koshy * char *' pointers pointing to the names of the events. 'nevents' is 2836ebccf1e3SJoseph Koshy * the number of event name pointers returned. 2837ebccf1e3SJoseph Koshy * 2838ebccf1e3SJoseph Koshy * The space for 'eventnames' is allocated using malloc(3). The caller 2839ebccf1e3SJoseph Koshy * is responsible for freeing this space when done. 2840ebccf1e3SJoseph Koshy */ 2841ebccf1e3SJoseph Koshy int 2842ebccf1e3SJoseph Koshy pmc_event_names_of_class(enum pmc_class cl, const char ***eventnames, 2843ebccf1e3SJoseph Koshy int *nevents) 2844ebccf1e3SJoseph Koshy { 2845ebccf1e3SJoseph Koshy int count; 2846ebccf1e3SJoseph Koshy const char **names; 2847ebccf1e3SJoseph Koshy const struct pmc_event_descr *ev; 2848ebccf1e3SJoseph Koshy 2849ebccf1e3SJoseph Koshy switch (cl) 2850ebccf1e3SJoseph Koshy { 28510cfab8ddSJoseph Koshy case PMC_CLASS_IAF: 28520cfab8ddSJoseph Koshy ev = iaf_event_table; 28530cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(iaf); 28540cfab8ddSJoseph Koshy break; 28550cfab8ddSJoseph Koshy case PMC_CLASS_IAP: 28560cfab8ddSJoseph Koshy /* 28570cfab8ddSJoseph Koshy * Return the most appropriate set of event name 28580cfab8ddSJoseph Koshy * spellings for the current CPU. 28590cfab8ddSJoseph Koshy */ 28600cfab8ddSJoseph Koshy switch (cpu_info.pm_cputype) { 28610cfab8ddSJoseph Koshy default: 28620cfab8ddSJoseph Koshy case PMC_CPU_INTEL_ATOM: 28630cfab8ddSJoseph Koshy ev = atom_event_table; 28640cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(atom); 28650cfab8ddSJoseph Koshy break; 2866e8f021a3SHiren Panchasara case PMC_CPU_INTEL_ATOM_SILVERMONT: 2867e8f021a3SHiren Panchasara ev = atom_silvermont_event_table; 2868e8f021a3SHiren Panchasara count = PMC_EVENT_TABLE_SIZE(atom_silvermont); 2869e8f021a3SHiren Panchasara break; 28700cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE: 28710cfab8ddSJoseph Koshy ev = core_event_table; 28720cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(core); 28730cfab8ddSJoseph Koshy break; 28740cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE2: 2875b4d091f3SJoseph Koshy case PMC_CPU_INTEL_CORE2EXTREME: 28760cfab8ddSJoseph Koshy ev = core2_event_table; 28770cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(core2); 28780cfab8ddSJoseph Koshy break; 2879597979c4SJeff Roberson case PMC_CPU_INTEL_COREI7: 2880597979c4SJeff Roberson ev = corei7_event_table; 2881597979c4SJeff Roberson count = PMC_EVENT_TABLE_SIZE(corei7); 2882597979c4SJeff Roberson break; 288349fe48abSKonstantin Belousov case PMC_CPU_INTEL_NEHALEM_EX: 288449fe48abSKonstantin Belousov ev = nehalem_ex_event_table; 288549fe48abSKonstantin Belousov count = PMC_EVENT_TABLE_SIZE(nehalem_ex); 288649fe48abSKonstantin Belousov break; 2887cc0c1555SSean Bruno case PMC_CPU_INTEL_HASWELL: 2888cc0c1555SSean Bruno ev = haswell_event_table; 2889cc0c1555SSean Bruno count = PMC_EVENT_TABLE_SIZE(haswell); 2890cc0c1555SSean Bruno break; 2891d95b3509SRandall Stewart case PMC_CPU_INTEL_HASWELL_XEON: 2892d95b3509SRandall Stewart ev = haswell_xeon_event_table; 2893d95b3509SRandall Stewart count = PMC_EVENT_TABLE_SIZE(haswell_xeon); 2894d95b3509SRandall Stewart break; 28951e862e5aSFabien Thomas case PMC_CPU_INTEL_IVYBRIDGE: 28961e862e5aSFabien Thomas ev = ivybridge_event_table; 28971e862e5aSFabien Thomas count = PMC_EVENT_TABLE_SIZE(ivybridge); 28981e862e5aSFabien Thomas break; 28993f929d8cSSean Bruno case PMC_CPU_INTEL_IVYBRIDGE_XEON: 29003f929d8cSSean Bruno ev = ivybridge_xeon_event_table; 29013f929d8cSSean Bruno count = PMC_EVENT_TABLE_SIZE(ivybridge_xeon); 29023f929d8cSSean Bruno break; 290378d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 290478d763a2SDavide Italiano ev = sandybridge_event_table; 290578d763a2SDavide Italiano count = PMC_EVENT_TABLE_SIZE(sandybridge); 290678d763a2SDavide Italiano break; 2907fabe02f5SSean Bruno case PMC_CPU_INTEL_SANDYBRIDGE_XEON: 2908fabe02f5SSean Bruno ev = sandybridge_xeon_event_table; 2909fabe02f5SSean Bruno count = PMC_EVENT_TABLE_SIZE(sandybridge_xeon); 2910fabe02f5SSean Bruno break; 29111fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 29121fa7f10bSFabien Thomas ev = westmere_event_table; 29131fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(westmere); 29141fa7f10bSFabien Thomas break; 291549fe48abSKonstantin Belousov case PMC_CPU_INTEL_WESTMERE_EX: 291649fe48abSKonstantin Belousov ev = westmere_ex_event_table; 291749fe48abSKonstantin Belousov count = PMC_EVENT_TABLE_SIZE(westmere_ex); 291849fe48abSKonstantin Belousov break; 29191fa7f10bSFabien Thomas } 29201fa7f10bSFabien Thomas break; 29211fa7f10bSFabien Thomas case PMC_CLASS_UCF: 29221fa7f10bSFabien Thomas ev = ucf_event_table; 29231fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(ucf); 29241fa7f10bSFabien Thomas break; 29251fa7f10bSFabien Thomas case PMC_CLASS_UCP: 29261fa7f10bSFabien Thomas /* 29271fa7f10bSFabien Thomas * Return the most appropriate set of event name 29281fa7f10bSFabien Thomas * spellings for the current CPU. 29291fa7f10bSFabien Thomas */ 29301fa7f10bSFabien Thomas switch (cpu_info.pm_cputype) { 29311fa7f10bSFabien Thomas default: 29321fa7f10bSFabien Thomas case PMC_CPU_INTEL_COREI7: 29331fa7f10bSFabien Thomas ev = corei7uc_event_table; 29341fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(corei7uc); 29351fa7f10bSFabien Thomas break; 2936cc0c1555SSean Bruno case PMC_CPU_INTEL_HASWELL: 2937cc0c1555SSean Bruno ev = haswelluc_event_table; 2938cc0c1555SSean Bruno count = PMC_EVENT_TABLE_SIZE(haswelluc); 2939cc0c1555SSean Bruno break; 294078d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 294178d763a2SDavide Italiano ev = sandybridgeuc_event_table; 294278d763a2SDavide Italiano count = PMC_EVENT_TABLE_SIZE(sandybridgeuc); 294378d763a2SDavide Italiano break; 29441fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 29451fa7f10bSFabien Thomas ev = westmereuc_event_table; 29461fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(westmereuc); 29471fa7f10bSFabien Thomas break; 29480cfab8ddSJoseph Koshy } 29490cfab8ddSJoseph Koshy break; 2950ebccf1e3SJoseph Koshy case PMC_CLASS_TSC: 2951789140c0SJoseph Koshy ev = tsc_event_table; 2952789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(tsc); 2953ebccf1e3SJoseph Koshy break; 2954ebccf1e3SJoseph Koshy case PMC_CLASS_K7: 2955789140c0SJoseph Koshy ev = k7_event_table; 2956789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(k7); 2957ebccf1e3SJoseph Koshy break; 2958ebccf1e3SJoseph Koshy case PMC_CLASS_K8: 2959789140c0SJoseph Koshy ev = k8_event_table; 2960789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(k8); 2961ebccf1e3SJoseph Koshy break; 2962ebccf1e3SJoseph Koshy case PMC_CLASS_P4: 2963789140c0SJoseph Koshy ev = p4_event_table; 2964789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p4); 2965789140c0SJoseph Koshy break; 2966789140c0SJoseph Koshy case PMC_CLASS_P5: 2967789140c0SJoseph Koshy ev = p5_event_table; 2968789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p5); 2969789140c0SJoseph Koshy break; 2970789140c0SJoseph Koshy case PMC_CLASS_P6: 2971789140c0SJoseph Koshy ev = p6_event_table; 2972789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p6); 2973ebccf1e3SJoseph Koshy break; 29740ce207d2SRui Paulo case PMC_CLASS_XSCALE: 29750ce207d2SRui Paulo ev = xscale_event_table; 29760ce207d2SRui Paulo count = PMC_EVENT_TABLE_SIZE(xscale); 29770ce207d2SRui Paulo break; 29786411d14dSRuslan Bukin case PMC_CLASS_ARMV7: 29796411d14dSRuslan Bukin ev = armv7_event_table; 29806411d14dSRuslan Bukin count = PMC_EVENT_TABLE_SIZE(armv7); 29816411d14dSRuslan Bukin break; 2982*bc88bb2bSRuslan Bukin case PMC_CLASS_ARMV8: 2983*bc88bb2bSRuslan Bukin switch (cpu_info.pm_cputype) { 2984*bc88bb2bSRuslan Bukin default: 2985*bc88bb2bSRuslan Bukin case PMC_CPU_ARMV8_CORTEX_A53: 2986*bc88bb2bSRuslan Bukin ev = cortex_a53_event_table; 2987*bc88bb2bSRuslan Bukin count = PMC_EVENT_TABLE_SIZE(cortex_a53); 2988*bc88bb2bSRuslan Bukin break; 2989*bc88bb2bSRuslan Bukin case PMC_CPU_ARMV8_CORTEX_A57: 2990*bc88bb2bSRuslan Bukin ev = cortex_a57_event_table; 2991*bc88bb2bSRuslan Bukin count = PMC_EVENT_TABLE_SIZE(cortex_a57); 2992*bc88bb2bSRuslan Bukin break; 2993*bc88bb2bSRuslan Bukin } 2994*bc88bb2bSRuslan Bukin break; 2995660df75eSGeorge V. Neville-Neil case PMC_CLASS_MIPS24K: 2996660df75eSGeorge V. Neville-Neil ev = mips24k_event_table; 2997660df75eSGeorge V. Neville-Neil count = PMC_EVENT_TABLE_SIZE(mips24k); 2998660df75eSGeorge V. Neville-Neil break; 2999f6e6460dSAdrian Chadd case PMC_CLASS_MIPS74K: 3000f6e6460dSAdrian Chadd ev = mips74k_event_table; 3001f6e6460dSAdrian Chadd count = PMC_EVENT_TABLE_SIZE(mips74k); 3002f6e6460dSAdrian Chadd break; 3003c2657f80SOleksandr Tymoshenko case PMC_CLASS_OCTEON: 3004c2657f80SOleksandr Tymoshenko ev = octeon_event_table; 3005c2657f80SOleksandr Tymoshenko count = PMC_EVENT_TABLE_SIZE(octeon); 3006c2657f80SOleksandr Tymoshenko break; 30077b25dccaSJustin Hibbits case PMC_CLASS_PPC7450: 30087b25dccaSJustin Hibbits ev = ppc7450_event_table; 30097b25dccaSJustin Hibbits count = PMC_EVENT_TABLE_SIZE(ppc7450); 30107b25dccaSJustin Hibbits break; 3011169dd953SJustin Hibbits case PMC_CLASS_PPC970: 3012169dd953SJustin Hibbits ev = ppc970_event_table; 3013169dd953SJustin Hibbits count = PMC_EVENT_TABLE_SIZE(ppc970); 3014169dd953SJustin Hibbits break; 3015a7452468SJustin Hibbits case PMC_CLASS_E500: 3016a7452468SJustin Hibbits ev = e500_event_table; 3017a7452468SJustin Hibbits count = PMC_EVENT_TABLE_SIZE(e500); 3018a7452468SJustin Hibbits break; 3019f5f9340bSFabien Thomas case PMC_CLASS_SOFT: 3020f5f9340bSFabien Thomas ev = soft_event_table; 3021f5f9340bSFabien Thomas count = soft_event_info.pm_nevent; 3022f5f9340bSFabien Thomas break; 3023ebccf1e3SJoseph Koshy default: 3024ebccf1e3SJoseph Koshy errno = EINVAL; 3025aa342b1fSJoseph Koshy return (-1); 3026ebccf1e3SJoseph Koshy } 3027ebccf1e3SJoseph Koshy 3028ebccf1e3SJoseph Koshy if ((names = malloc(count * sizeof(const char *))) == NULL) 3029aa342b1fSJoseph Koshy return (-1); 3030ebccf1e3SJoseph Koshy 3031ebccf1e3SJoseph Koshy *eventnames = names; 3032ebccf1e3SJoseph Koshy *nevents = count; 3033ebccf1e3SJoseph Koshy 3034ebccf1e3SJoseph Koshy for (;count--; ev++, names++) 3035ebccf1e3SJoseph Koshy *names = ev->pm_ev_name; 3036f5f9340bSFabien Thomas 3037aa342b1fSJoseph Koshy return (0); 3038ebccf1e3SJoseph Koshy } 3039ebccf1e3SJoseph Koshy 3040f263522aSJoseph Koshy int 3041f263522aSJoseph Koshy pmc_flush_logfile(void) 3042f263522aSJoseph Koshy { 3043aa342b1fSJoseph Koshy return (PMC_CALL(FLUSHLOG,0)); 3044f263522aSJoseph Koshy } 3045ebccf1e3SJoseph Koshy 3046ebccf1e3SJoseph Koshy int 3047dceed24aSFabien Thomas pmc_close_logfile(void) 3048dceed24aSFabien Thomas { 3049dceed24aSFabien Thomas return (PMC_CALL(CLOSELOG,0)); 3050dceed24aSFabien Thomas } 3051dceed24aSFabien Thomas 3052dceed24aSFabien Thomas int 3053f263522aSJoseph Koshy pmc_get_driver_stats(struct pmc_driverstats *ds) 3054ebccf1e3SJoseph Koshy { 3055f263522aSJoseph Koshy struct pmc_op_getdriverstats gms; 3056f263522aSJoseph Koshy 3057f263522aSJoseph Koshy if (PMC_CALL(GETDRIVERSTATS, &gms) < 0) 3058aa342b1fSJoseph Koshy return (-1); 3059f263522aSJoseph Koshy 3060f263522aSJoseph Koshy /* copy out fields in the current userland<->library interface */ 3061f263522aSJoseph Koshy ds->pm_intr_ignored = gms.pm_intr_ignored; 3062f263522aSJoseph Koshy ds->pm_intr_processed = gms.pm_intr_processed; 3063f263522aSJoseph Koshy ds->pm_intr_bufferfull = gms.pm_intr_bufferfull; 3064f263522aSJoseph Koshy ds->pm_syscalls = gms.pm_syscalls; 3065f263522aSJoseph Koshy ds->pm_syscall_errors = gms.pm_syscall_errors; 3066f263522aSJoseph Koshy ds->pm_buffer_requests = gms.pm_buffer_requests; 3067f263522aSJoseph Koshy ds->pm_buffer_requests_failed = gms.pm_buffer_requests_failed; 3068f263522aSJoseph Koshy ds->pm_log_sweeps = gms.pm_log_sweeps; 3069aa342b1fSJoseph Koshy return (0); 3070f263522aSJoseph Koshy } 3071f263522aSJoseph Koshy 3072f263522aSJoseph Koshy int 3073f263522aSJoseph Koshy pmc_get_msr(pmc_id_t pmc, uint32_t *msr) 3074f263522aSJoseph Koshy { 3075f263522aSJoseph Koshy struct pmc_op_getmsr gm; 3076ebccf1e3SJoseph Koshy 3077ebccf1e3SJoseph Koshy gm.pm_pmcid = pmc; 3078f263522aSJoseph Koshy if (PMC_CALL(PMCGETMSR, &gm) < 0) 3079aa342b1fSJoseph Koshy return (-1); 3080ebccf1e3SJoseph Koshy *msr = gm.pm_msr; 3081aa342b1fSJoseph Koshy return (0); 3082ebccf1e3SJoseph Koshy } 3083ebccf1e3SJoseph Koshy 3084f263522aSJoseph Koshy int 3085f263522aSJoseph Koshy pmc_init(void) 3086f263522aSJoseph Koshy { 3087f263522aSJoseph Koshy int error, pmc_mod_id; 30881455fcd3SJoseph Koshy unsigned int n; 3089f263522aSJoseph Koshy uint32_t abi_version; 3090f263522aSJoseph Koshy struct module_stat pmc_modstat; 30911455fcd3SJoseph Koshy struct pmc_op_getcpuinfo op_cpu_info; 3092791f5d5bSJoseph Koshy #if defined(__amd64__) || defined(__i386__) 3093791f5d5bSJoseph Koshy int cpu_has_iaf_counters; 3094791f5d5bSJoseph Koshy unsigned int t; 3095791f5d5bSJoseph Koshy #endif 3096f263522aSJoseph Koshy 3097f263522aSJoseph Koshy if (pmc_syscall != -1) /* already inited */ 3098aa342b1fSJoseph Koshy return (0); 3099f263522aSJoseph Koshy 3100f263522aSJoseph Koshy /* retrieve the system call number from the KLD */ 3101f263522aSJoseph Koshy if ((pmc_mod_id = modfind(PMC_MODULE_NAME)) < 0) 3102aa342b1fSJoseph Koshy return (-1); 3103f263522aSJoseph Koshy 3104f263522aSJoseph Koshy pmc_modstat.version = sizeof(struct module_stat); 3105f263522aSJoseph Koshy if ((error = modstat(pmc_mod_id, &pmc_modstat)) < 0) 3106aa342b1fSJoseph Koshy return (-1); 3107f263522aSJoseph Koshy 3108f263522aSJoseph Koshy pmc_syscall = pmc_modstat.data.intval; 3109f263522aSJoseph Koshy 3110f263522aSJoseph Koshy /* check the kernel module's ABI against our compiled-in version */ 3111f263522aSJoseph Koshy abi_version = PMC_VERSION; 3112f263522aSJoseph Koshy if (PMC_CALL(GETMODULEVERSION, &abi_version) < 0) 3113f263522aSJoseph Koshy return (pmc_syscall = -1); 3114f263522aSJoseph Koshy 3115f263522aSJoseph Koshy /* ignore patch & minor numbers for the comparision */ 3116f263522aSJoseph Koshy if ((abi_version & 0xFF000000) != (PMC_VERSION & 0xFF000000)) { 3117f263522aSJoseph Koshy errno = EPROGMISMATCH; 3118f263522aSJoseph Koshy return (pmc_syscall = -1); 3119f263522aSJoseph Koshy } 3120f263522aSJoseph Koshy 31211455fcd3SJoseph Koshy if (PMC_CALL(GETCPUINFO, &op_cpu_info) < 0) 3122f263522aSJoseph Koshy return (pmc_syscall = -1); 3123f263522aSJoseph Koshy 31241455fcd3SJoseph Koshy cpu_info.pm_cputype = op_cpu_info.pm_cputype; 31251455fcd3SJoseph Koshy cpu_info.pm_ncpu = op_cpu_info.pm_ncpu; 31261455fcd3SJoseph Koshy cpu_info.pm_npmc = op_cpu_info.pm_npmc; 31271455fcd3SJoseph Koshy cpu_info.pm_nclass = op_cpu_info.pm_nclass; 31281455fcd3SJoseph Koshy for (n = 0; n < cpu_info.pm_nclass; n++) 31291455fcd3SJoseph Koshy cpu_info.pm_classes[n] = op_cpu_info.pm_classes[n]; 31301455fcd3SJoseph Koshy 31310cfab8ddSJoseph Koshy pmc_class_table = malloc(PMC_CLASS_TABLE_SIZE * 31320cfab8ddSJoseph Koshy sizeof(struct pmc_class_descr *)); 31330cfab8ddSJoseph Koshy 31340cfab8ddSJoseph Koshy if (pmc_class_table == NULL) 31350cfab8ddSJoseph Koshy return (-1); 31360cfab8ddSJoseph Koshy 3137791f5d5bSJoseph Koshy for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) 3138791f5d5bSJoseph Koshy pmc_class_table[n] = NULL; 31390cfab8ddSJoseph Koshy 31400cfab8ddSJoseph Koshy /* 3141f5f9340bSFabien Thomas * Get soft events list. 3142f5f9340bSFabien Thomas */ 3143f5f9340bSFabien Thomas soft_event_info.pm_class = PMC_CLASS_SOFT; 3144f5f9340bSFabien Thomas if (PMC_CALL(GETDYNEVENTINFO, &soft_event_info) < 0) 3145f5f9340bSFabien Thomas return (pmc_syscall = -1); 3146f5f9340bSFabien Thomas 3147f5f9340bSFabien Thomas /* Map soft events to static list. */ 3148f5f9340bSFabien Thomas for (n = 0; n < soft_event_info.pm_nevent; n++) { 3149f5f9340bSFabien Thomas soft_event_table[n].pm_ev_name = 3150f5f9340bSFabien Thomas soft_event_info.pm_events[n].pm_ev_name; 3151f5f9340bSFabien Thomas soft_event_table[n].pm_ev_code = 3152f5f9340bSFabien Thomas soft_event_info.pm_events[n].pm_ev_code; 3153f5f9340bSFabien Thomas } 3154f5f9340bSFabien Thomas soft_class_table_descr.pm_evc_event_table_size = \ 3155f5f9340bSFabien Thomas soft_event_info.pm_nevent; 3156f5f9340bSFabien Thomas soft_class_table_descr.pm_evc_event_table = \ 3157f5f9340bSFabien Thomas soft_event_table; 3158f5f9340bSFabien Thomas 3159f5f9340bSFabien Thomas /* 31600cfab8ddSJoseph Koshy * Fill in the class table. 31610cfab8ddSJoseph Koshy */ 31620cfab8ddSJoseph Koshy n = 0; 3163f5f9340bSFabien Thomas 3164f5f9340bSFabien Thomas /* Fill soft events information. */ 3165f5f9340bSFabien Thomas pmc_class_table[n++] = &soft_class_table_descr; 31660cfab8ddSJoseph Koshy #if defined(__amd64__) || defined(__i386__) 3167f5f9340bSFabien Thomas if (cpu_info.pm_cputype != PMC_CPU_GENERIC) 31680cfab8ddSJoseph Koshy pmc_class_table[n++] = &tsc_class_table_descr; 3169791f5d5bSJoseph Koshy 3170791f5d5bSJoseph Koshy /* 3171791f5d5bSJoseph Koshy * Check if this CPU has fixed function counters. 3172791f5d5bSJoseph Koshy */ 3173791f5d5bSJoseph Koshy cpu_has_iaf_counters = 0; 3174791f5d5bSJoseph Koshy for (t = 0; t < cpu_info.pm_nclass; t++) 31752aef9dd6SFabien Thomas if (cpu_info.pm_classes[t].pm_class == PMC_CLASS_IAF && 31762aef9dd6SFabien Thomas cpu_info.pm_classes[t].pm_num > 0) 3177791f5d5bSJoseph Koshy cpu_has_iaf_counters = 1; 31780cfab8ddSJoseph Koshy #endif 31790cfab8ddSJoseph Koshy 3180789140c0SJoseph Koshy #define PMC_MDEP_INIT(C) do { \ 3181789140c0SJoseph Koshy pmc_mdep_event_aliases = C##_aliases; \ 3182789140c0SJoseph Koshy pmc_mdep_class_list = C##_pmc_classes; \ 3183789140c0SJoseph Koshy pmc_mdep_class_list_size = \ 3184789140c0SJoseph Koshy PMC_TABLE_SIZE(C##_pmc_classes); \ 3185789140c0SJoseph Koshy } while (0) 3186789140c0SJoseph Koshy 3187791f5d5bSJoseph Koshy #define PMC_MDEP_INIT_INTEL_V2(C) do { \ 3188791f5d5bSJoseph Koshy PMC_MDEP_INIT(C); \ 3189791f5d5bSJoseph Koshy pmc_class_table[n++] = &iaf_class_table_descr; \ 31902aef9dd6SFabien Thomas if (!cpu_has_iaf_counters) \ 3191791f5d5bSJoseph Koshy pmc_mdep_event_aliases = \ 3192791f5d5bSJoseph Koshy C##_aliases_without_iaf; \ 3193791f5d5bSJoseph Koshy pmc_class_table[n] = &C##_class_table_descr; \ 3194791f5d5bSJoseph Koshy } while (0) 3195791f5d5bSJoseph Koshy 3196789140c0SJoseph Koshy /* Configure the event name parser. */ 3197f263522aSJoseph Koshy switch (cpu_info.pm_cputype) { 3198f263522aSJoseph Koshy #if defined(__i386__) 3199f263522aSJoseph Koshy case PMC_CPU_AMD_K7: 3200789140c0SJoseph Koshy PMC_MDEP_INIT(k7); 32010cfab8ddSJoseph Koshy pmc_class_table[n] = &k7_class_table_descr; 3202f263522aSJoseph Koshy break; 3203f263522aSJoseph Koshy case PMC_CPU_INTEL_P5: 3204789140c0SJoseph Koshy PMC_MDEP_INIT(p5); 32050cfab8ddSJoseph Koshy pmc_class_table[n] = &p5_class_table_descr; 3206f263522aSJoseph Koshy break; 3207f263522aSJoseph Koshy case PMC_CPU_INTEL_P6: /* P6 ... Pentium M CPUs have */ 3208f263522aSJoseph Koshy case PMC_CPU_INTEL_PII: /* similar PMCs. */ 3209f263522aSJoseph Koshy case PMC_CPU_INTEL_PIII: 3210f263522aSJoseph Koshy case PMC_CPU_INTEL_PM: 3211789140c0SJoseph Koshy PMC_MDEP_INIT(p6); 32120cfab8ddSJoseph Koshy pmc_class_table[n] = &p6_class_table_descr; 3213f263522aSJoseph Koshy break; 321486a65549SJoseph Koshy #endif 321586a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 3216f263522aSJoseph Koshy case PMC_CPU_AMD_K8: 3217789140c0SJoseph Koshy PMC_MDEP_INIT(k8); 32180cfab8ddSJoseph Koshy pmc_class_table[n] = &k8_class_table_descr; 32190cfab8ddSJoseph Koshy break; 32200cfab8ddSJoseph Koshy case PMC_CPU_INTEL_ATOM: 3221791f5d5bSJoseph Koshy PMC_MDEP_INIT_INTEL_V2(atom); 32220cfab8ddSJoseph Koshy break; 3223e8f021a3SHiren Panchasara case PMC_CPU_INTEL_ATOM_SILVERMONT: 3224e8f021a3SHiren Panchasara PMC_MDEP_INIT_INTEL_V2(atom_silvermont); 3225e8f021a3SHiren Panchasara break; 32260cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE: 32270cfab8ddSJoseph Koshy PMC_MDEP_INIT(core); 3228bc315bbdSJoseph Koshy pmc_class_table[n] = &core_class_table_descr; 32290cfab8ddSJoseph Koshy break; 32300cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE2: 3231b4d091f3SJoseph Koshy case PMC_CPU_INTEL_CORE2EXTREME: 3232791f5d5bSJoseph Koshy PMC_MDEP_INIT_INTEL_V2(core2); 3233789140c0SJoseph Koshy break; 3234597979c4SJeff Roberson case PMC_CPU_INTEL_COREI7: 32351fa7f10bSFabien Thomas pmc_class_table[n++] = &ucf_class_table_descr; 32361fa7f10bSFabien Thomas pmc_class_table[n++] = &corei7uc_class_table_descr; 3237791f5d5bSJoseph Koshy PMC_MDEP_INIT_INTEL_V2(corei7); 3238597979c4SJeff Roberson break; 323949fe48abSKonstantin Belousov case PMC_CPU_INTEL_NEHALEM_EX: 324049fe48abSKonstantin Belousov PMC_MDEP_INIT_INTEL_V2(nehalem_ex); 324149fe48abSKonstantin Belousov break; 3242cc0c1555SSean Bruno case PMC_CPU_INTEL_HASWELL: 3243cc0c1555SSean Bruno pmc_class_table[n++] = &ucf_class_table_descr; 3244cc0c1555SSean Bruno pmc_class_table[n++] = &haswelluc_class_table_descr; 3245cc0c1555SSean Bruno PMC_MDEP_INIT_INTEL_V2(haswell); 3246cc0c1555SSean Bruno break; 3247d95b3509SRandall Stewart case PMC_CPU_INTEL_HASWELL_XEON: 3248d95b3509SRandall Stewart PMC_MDEP_INIT_INTEL_V2(haswell_xeon); 3249d95b3509SRandall Stewart break; 32501e862e5aSFabien Thomas case PMC_CPU_INTEL_IVYBRIDGE: 32511e862e5aSFabien Thomas PMC_MDEP_INIT_INTEL_V2(ivybridge); 32521e862e5aSFabien Thomas break; 32533f929d8cSSean Bruno case PMC_CPU_INTEL_IVYBRIDGE_XEON: 32543f929d8cSSean Bruno PMC_MDEP_INIT_INTEL_V2(ivybridge_xeon); 32553f929d8cSSean Bruno break; 325678d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 325778d763a2SDavide Italiano pmc_class_table[n++] = &ucf_class_table_descr; 325878d763a2SDavide Italiano pmc_class_table[n++] = &sandybridgeuc_class_table_descr; 325978d763a2SDavide Italiano PMC_MDEP_INIT_INTEL_V2(sandybridge); 326078d763a2SDavide Italiano break; 3261fabe02f5SSean Bruno case PMC_CPU_INTEL_SANDYBRIDGE_XEON: 3262fabe02f5SSean Bruno PMC_MDEP_INIT_INTEL_V2(sandybridge_xeon); 3263fabe02f5SSean Bruno break; 32641fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 32651fa7f10bSFabien Thomas pmc_class_table[n++] = &ucf_class_table_descr; 32661fa7f10bSFabien Thomas pmc_class_table[n++] = &westmereuc_class_table_descr; 32671fa7f10bSFabien Thomas PMC_MDEP_INIT_INTEL_V2(westmere); 32681fa7f10bSFabien Thomas break; 326949fe48abSKonstantin Belousov case PMC_CPU_INTEL_WESTMERE_EX: 327049fe48abSKonstantin Belousov PMC_MDEP_INIT_INTEL_V2(westmere_ex); 327149fe48abSKonstantin Belousov break; 3272789140c0SJoseph Koshy case PMC_CPU_INTEL_PIV: 3273789140c0SJoseph Koshy PMC_MDEP_INIT(p4); 32740cfab8ddSJoseph Koshy pmc_class_table[n] = &p4_class_table_descr; 3275f263522aSJoseph Koshy break; 3276ebccf1e3SJoseph Koshy #endif 3277f5f9340bSFabien Thomas case PMC_CPU_GENERIC: 3278f5f9340bSFabien Thomas PMC_MDEP_INIT(generic); 3279f5f9340bSFabien Thomas break; 32806411d14dSRuslan Bukin #if defined(__arm__) 32810ce207d2SRui Paulo #if defined(__XSCALE__) 32820ce207d2SRui Paulo case PMC_CPU_INTEL_XSCALE: 32830ce207d2SRui Paulo PMC_MDEP_INIT(xscale); 32840ce207d2SRui Paulo pmc_class_table[n] = &xscale_class_table_descr; 32850ce207d2SRui Paulo break; 32860ce207d2SRui Paulo #endif 32876411d14dSRuslan Bukin case PMC_CPU_ARMV7: 32886411d14dSRuslan Bukin PMC_MDEP_INIT(armv7); 32896411d14dSRuslan Bukin pmc_class_table[n] = &armv7_class_table_descr; 32906411d14dSRuslan Bukin break; 32916411d14dSRuslan Bukin #endif 3292*bc88bb2bSRuslan Bukin #if defined(__aarch64__) 3293*bc88bb2bSRuslan Bukin case PMC_CPU_ARMV8_CORTEX_A53: 3294*bc88bb2bSRuslan Bukin PMC_MDEP_INIT(cortex_a53); 3295*bc88bb2bSRuslan Bukin pmc_class_table[n] = &cortex_a53_class_table_descr; 3296*bc88bb2bSRuslan Bukin break; 3297*bc88bb2bSRuslan Bukin case PMC_CPU_ARMV8_CORTEX_A57: 3298*bc88bb2bSRuslan Bukin PMC_MDEP_INIT(cortex_a57); 3299*bc88bb2bSRuslan Bukin pmc_class_table[n] = &cortex_a57_class_table_descr; 3300*bc88bb2bSRuslan Bukin break; 3301*bc88bb2bSRuslan Bukin #endif 3302660df75eSGeorge V. Neville-Neil #if defined(__mips__) 3303660df75eSGeorge V. Neville-Neil case PMC_CPU_MIPS_24K: 3304660df75eSGeorge V. Neville-Neil PMC_MDEP_INIT(mips24k); 3305660df75eSGeorge V. Neville-Neil pmc_class_table[n] = &mips24k_class_table_descr; 3306660df75eSGeorge V. Neville-Neil break; 3307f6e6460dSAdrian Chadd case PMC_CPU_MIPS_74K: 3308f6e6460dSAdrian Chadd PMC_MDEP_INIT(mips74k); 3309f6e6460dSAdrian Chadd pmc_class_table[n] = &mips74k_class_table_descr; 3310f6e6460dSAdrian Chadd break; 3311c2657f80SOleksandr Tymoshenko case PMC_CPU_MIPS_OCTEON: 3312c2657f80SOleksandr Tymoshenko PMC_MDEP_INIT(octeon); 3313c2657f80SOleksandr Tymoshenko pmc_class_table[n] = &octeon_class_table_descr; 3314c2657f80SOleksandr Tymoshenko break; 3315660df75eSGeorge V. Neville-Neil #endif /* __mips__ */ 33167b25dccaSJustin Hibbits #if defined(__powerpc__) 33177b25dccaSJustin Hibbits case PMC_CPU_PPC_7450: 33187b25dccaSJustin Hibbits PMC_MDEP_INIT(ppc7450); 33197b25dccaSJustin Hibbits pmc_class_table[n] = &ppc7450_class_table_descr; 33207b25dccaSJustin Hibbits break; 3321169dd953SJustin Hibbits case PMC_CPU_PPC_970: 3322169dd953SJustin Hibbits PMC_MDEP_INIT(ppc970); 3323169dd953SJustin Hibbits pmc_class_table[n] = &ppc970_class_table_descr; 3324169dd953SJustin Hibbits break; 3325a7452468SJustin Hibbits case PMC_CPU_PPC_E500: 3326a7452468SJustin Hibbits PMC_MDEP_INIT(e500); 3327a7452468SJustin Hibbits pmc_class_table[n] = &e500_class_table_descr; 3328a7452468SJustin Hibbits break; 33297b25dccaSJustin Hibbits #endif 3330f263522aSJoseph Koshy default: 3331f263522aSJoseph Koshy /* 3332f263522aSJoseph Koshy * Some kind of CPU this version of the library knows nothing 3333f263522aSJoseph Koshy * about. This shouldn't happen since the abi version check 3334f263522aSJoseph Koshy * should have caught this. 3335f263522aSJoseph Koshy */ 3336f263522aSJoseph Koshy errno = ENXIO; 3337f263522aSJoseph Koshy return (pmc_syscall = -1); 3338f263522aSJoseph Koshy } 3339f263522aSJoseph Koshy 3340aa342b1fSJoseph Koshy return (0); 3341f263522aSJoseph Koshy } 3342f263522aSJoseph Koshy 3343f263522aSJoseph Koshy const char * 3344f263522aSJoseph Koshy pmc_name_of_capability(enum pmc_caps cap) 3345f263522aSJoseph Koshy { 3346f263522aSJoseph Koshy int i; 3347f263522aSJoseph Koshy 3348f263522aSJoseph Koshy /* 3349f263522aSJoseph Koshy * 'cap' should have a single bit set and should be in 3350f263522aSJoseph Koshy * range. 3351f263522aSJoseph Koshy */ 3352f263522aSJoseph Koshy if ((cap & (cap - 1)) || cap < PMC_CAP_FIRST || 3353f263522aSJoseph Koshy cap > PMC_CAP_LAST) { 3354f263522aSJoseph Koshy errno = EINVAL; 3355aa342b1fSJoseph Koshy return (NULL); 3356f263522aSJoseph Koshy } 3357f263522aSJoseph Koshy 3358f263522aSJoseph Koshy i = ffs(cap); 3359aa342b1fSJoseph Koshy return (pmc_capability_names[i - 1]); 3360f263522aSJoseph Koshy } 3361f263522aSJoseph Koshy 3362f263522aSJoseph Koshy const char * 3363f263522aSJoseph Koshy pmc_name_of_class(enum pmc_class pc) 3364f263522aSJoseph Koshy { 3365f263522aSJoseph Koshy if ((int) pc >= PMC_CLASS_FIRST && 3366f263522aSJoseph Koshy pc <= PMC_CLASS_LAST) 3367aa342b1fSJoseph Koshy return (pmc_class_names[pc]); 3368f263522aSJoseph Koshy 3369f263522aSJoseph Koshy errno = EINVAL; 3370aa342b1fSJoseph Koshy return (NULL); 3371f263522aSJoseph Koshy } 3372f263522aSJoseph Koshy 3373f263522aSJoseph Koshy const char * 3374f263522aSJoseph Koshy pmc_name_of_cputype(enum pmc_cputype cp) 3375f263522aSJoseph Koshy { 3376789140c0SJoseph Koshy size_t n; 3377789140c0SJoseph Koshy 3378789140c0SJoseph Koshy for (n = 0; n < PMC_TABLE_SIZE(pmc_cputype_names); n++) 3379789140c0SJoseph Koshy if (cp == pmc_cputype_names[n].pm_cputype) 3380789140c0SJoseph Koshy return (pmc_cputype_names[n].pm_name); 3381789140c0SJoseph Koshy 3382f263522aSJoseph Koshy errno = EINVAL; 3383aa342b1fSJoseph Koshy return (NULL); 3384f263522aSJoseph Koshy } 3385f263522aSJoseph Koshy 3386f263522aSJoseph Koshy const char * 3387f263522aSJoseph Koshy pmc_name_of_disposition(enum pmc_disp pd) 3388f263522aSJoseph Koshy { 3389f263522aSJoseph Koshy if ((int) pd >= PMC_DISP_FIRST && 3390f263522aSJoseph Koshy pd <= PMC_DISP_LAST) 3391aa342b1fSJoseph Koshy return (pmc_disposition_names[pd]); 3392f263522aSJoseph Koshy 3393f263522aSJoseph Koshy errno = EINVAL; 3394aa342b1fSJoseph Koshy return (NULL); 3395f263522aSJoseph Koshy } 3396f263522aSJoseph Koshy 3397f263522aSJoseph Koshy const char * 33980cfab8ddSJoseph Koshy _pmc_name_of_event(enum pmc_event pe, enum pmc_cputype cpu) 3399f263522aSJoseph Koshy { 3400789140c0SJoseph Koshy const struct pmc_event_descr *ev, *evfence; 3401789140c0SJoseph Koshy 3402789140c0SJoseph Koshy ev = evfence = NULL; 34030cfab8ddSJoseph Koshy if (pe >= PMC_EV_IAF_FIRST && pe <= PMC_EV_IAF_LAST) { 34040cfab8ddSJoseph Koshy ev = iaf_event_table; 34050cfab8ddSJoseph Koshy evfence = iaf_event_table + PMC_EVENT_TABLE_SIZE(iaf); 34060cfab8ddSJoseph Koshy } else if (pe >= PMC_EV_IAP_FIRST && pe <= PMC_EV_IAP_LAST) { 34070cfab8ddSJoseph Koshy switch (cpu) { 34080cfab8ddSJoseph Koshy case PMC_CPU_INTEL_ATOM: 34090cfab8ddSJoseph Koshy ev = atom_event_table; 34100cfab8ddSJoseph Koshy evfence = atom_event_table + PMC_EVENT_TABLE_SIZE(atom); 34110cfab8ddSJoseph Koshy break; 3412e8f021a3SHiren Panchasara case PMC_CPU_INTEL_ATOM_SILVERMONT: 3413e8f021a3SHiren Panchasara ev = atom_silvermont_event_table; 3414e8f021a3SHiren Panchasara evfence = atom_silvermont_event_table + 3415e8f021a3SHiren Panchasara PMC_EVENT_TABLE_SIZE(atom_silvermont); 3416e8f021a3SHiren Panchasara break; 34170cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE: 34180cfab8ddSJoseph Koshy ev = core_event_table; 34190cfab8ddSJoseph Koshy evfence = core_event_table + PMC_EVENT_TABLE_SIZE(core); 34200cfab8ddSJoseph Koshy break; 34210cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE2: 3422b4d091f3SJoseph Koshy case PMC_CPU_INTEL_CORE2EXTREME: 34230cfab8ddSJoseph Koshy ev = core2_event_table; 34240cfab8ddSJoseph Koshy evfence = core2_event_table + PMC_EVENT_TABLE_SIZE(core2); 34250cfab8ddSJoseph Koshy break; 3426597979c4SJeff Roberson case PMC_CPU_INTEL_COREI7: 3427597979c4SJeff Roberson ev = corei7_event_table; 3428597979c4SJeff Roberson evfence = corei7_event_table + PMC_EVENT_TABLE_SIZE(corei7); 3429597979c4SJeff Roberson break; 343049fe48abSKonstantin Belousov case PMC_CPU_INTEL_NEHALEM_EX: 343149fe48abSKonstantin Belousov ev = nehalem_ex_event_table; 343249fe48abSKonstantin Belousov evfence = nehalem_ex_event_table + 343349fe48abSKonstantin Belousov PMC_EVENT_TABLE_SIZE(nehalem_ex); 343449fe48abSKonstantin Belousov break; 3435cc0c1555SSean Bruno case PMC_CPU_INTEL_HASWELL: 3436cc0c1555SSean Bruno ev = haswell_event_table; 3437cc0c1555SSean Bruno evfence = haswell_event_table + PMC_EVENT_TABLE_SIZE(haswell); 3438cc0c1555SSean Bruno break; 3439d95b3509SRandall Stewart case PMC_CPU_INTEL_HASWELL_XEON: 3440d95b3509SRandall Stewart ev = haswell_xeon_event_table; 3441d95b3509SRandall Stewart evfence = haswell_xeon_event_table + PMC_EVENT_TABLE_SIZE(haswell_xeon); 3442d95b3509SRandall Stewart break; 3443d95b3509SRandall Stewart 34441e862e5aSFabien Thomas case PMC_CPU_INTEL_IVYBRIDGE: 34451e862e5aSFabien Thomas ev = ivybridge_event_table; 34461e862e5aSFabien Thomas evfence = ivybridge_event_table + PMC_EVENT_TABLE_SIZE(ivybridge); 34471e862e5aSFabien Thomas break; 34483f929d8cSSean Bruno case PMC_CPU_INTEL_IVYBRIDGE_XEON: 34493f929d8cSSean Bruno ev = ivybridge_xeon_event_table; 34503f929d8cSSean Bruno evfence = ivybridge_xeon_event_table + PMC_EVENT_TABLE_SIZE(ivybridge_xeon); 34513f929d8cSSean Bruno break; 345278d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 345378d763a2SDavide Italiano ev = sandybridge_event_table; 345478d763a2SDavide Italiano evfence = sandybridge_event_table + PMC_EVENT_TABLE_SIZE(sandybridge); 345578d763a2SDavide Italiano break; 3456fabe02f5SSean Bruno case PMC_CPU_INTEL_SANDYBRIDGE_XEON: 3457fabe02f5SSean Bruno ev = sandybridge_xeon_event_table; 3458fabe02f5SSean Bruno evfence = sandybridge_xeon_event_table + PMC_EVENT_TABLE_SIZE(sandybridge_xeon); 3459fabe02f5SSean Bruno break; 34601fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 34611fa7f10bSFabien Thomas ev = westmere_event_table; 34621fa7f10bSFabien Thomas evfence = westmere_event_table + PMC_EVENT_TABLE_SIZE(westmere); 34631fa7f10bSFabien Thomas break; 346449fe48abSKonstantin Belousov case PMC_CPU_INTEL_WESTMERE_EX: 346549fe48abSKonstantin Belousov ev = westmere_ex_event_table; 346649fe48abSKonstantin Belousov evfence = westmere_ex_event_table + 346749fe48abSKonstantin Belousov PMC_EVENT_TABLE_SIZE(westmere_ex); 346849fe48abSKonstantin Belousov break; 34690cfab8ddSJoseph Koshy default: /* Unknown CPU type. */ 34700cfab8ddSJoseph Koshy break; 34710cfab8ddSJoseph Koshy } 34721fa7f10bSFabien Thomas } else if (pe >= PMC_EV_UCF_FIRST && pe <= PMC_EV_UCF_LAST) { 34731fa7f10bSFabien Thomas ev = ucf_event_table; 34741fa7f10bSFabien Thomas evfence = ucf_event_table + PMC_EVENT_TABLE_SIZE(ucf); 34751fa7f10bSFabien Thomas } else if (pe >= PMC_EV_UCP_FIRST && pe <= PMC_EV_UCP_LAST) { 34761fa7f10bSFabien Thomas switch (cpu) { 34771fa7f10bSFabien Thomas case PMC_CPU_INTEL_COREI7: 34781fa7f10bSFabien Thomas ev = corei7uc_event_table; 34791fa7f10bSFabien Thomas evfence = corei7uc_event_table + PMC_EVENT_TABLE_SIZE(corei7uc); 34801fa7f10bSFabien Thomas break; 348178d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 348278d763a2SDavide Italiano ev = sandybridgeuc_event_table; 348378d763a2SDavide Italiano evfence = sandybridgeuc_event_table + PMC_EVENT_TABLE_SIZE(sandybridgeuc); 348478d763a2SDavide Italiano break; 34851fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 34861fa7f10bSFabien Thomas ev = westmereuc_event_table; 34871fa7f10bSFabien Thomas evfence = westmereuc_event_table + PMC_EVENT_TABLE_SIZE(westmereuc); 34881fa7f10bSFabien Thomas break; 34891fa7f10bSFabien Thomas default: /* Unknown CPU type. */ 34901fa7f10bSFabien Thomas break; 34911fa7f10bSFabien Thomas } 34921fa7f10bSFabien Thomas } else if (pe >= PMC_EV_K7_FIRST && pe <= PMC_EV_K7_LAST) { 3493789140c0SJoseph Koshy ev = k7_event_table; 3494789140c0SJoseph Koshy evfence = k7_event_table + PMC_EVENT_TABLE_SIZE(k7); 3495789140c0SJoseph Koshy } else if (pe >= PMC_EV_K8_FIRST && pe <= PMC_EV_K8_LAST) { 3496789140c0SJoseph Koshy ev = k8_event_table; 3497789140c0SJoseph Koshy evfence = k8_event_table + PMC_EVENT_TABLE_SIZE(k8); 3498789140c0SJoseph Koshy } else if (pe >= PMC_EV_P4_FIRST && pe <= PMC_EV_P4_LAST) { 3499789140c0SJoseph Koshy ev = p4_event_table; 3500789140c0SJoseph Koshy evfence = p4_event_table + PMC_EVENT_TABLE_SIZE(p4); 3501789140c0SJoseph Koshy } else if (pe >= PMC_EV_P5_FIRST && pe <= PMC_EV_P5_LAST) { 3502789140c0SJoseph Koshy ev = p5_event_table; 3503789140c0SJoseph Koshy evfence = p5_event_table + PMC_EVENT_TABLE_SIZE(p5); 3504789140c0SJoseph Koshy } else if (pe >= PMC_EV_P6_FIRST && pe <= PMC_EV_P6_LAST) { 3505789140c0SJoseph Koshy ev = p6_event_table; 3506789140c0SJoseph Koshy evfence = p6_event_table + PMC_EVENT_TABLE_SIZE(p6); 35070ce207d2SRui Paulo } else if (pe >= PMC_EV_XSCALE_FIRST && pe <= PMC_EV_XSCALE_LAST) { 35080ce207d2SRui Paulo ev = xscale_event_table; 35090ce207d2SRui Paulo evfence = xscale_event_table + PMC_EVENT_TABLE_SIZE(xscale); 35106411d14dSRuslan Bukin } else if (pe >= PMC_EV_ARMV7_FIRST && pe <= PMC_EV_ARMV7_LAST) { 35116411d14dSRuslan Bukin ev = armv7_event_table; 35126411d14dSRuslan Bukin evfence = armv7_event_table + PMC_EVENT_TABLE_SIZE(armv7); 3513*bc88bb2bSRuslan Bukin } else if (pe >= PMC_EV_ARMV8_FIRST && pe <= PMC_EV_ARMV8_LAST) { 3514*bc88bb2bSRuslan Bukin switch (cpu) { 3515*bc88bb2bSRuslan Bukin case PMC_CPU_ARMV8_CORTEX_A53: 3516*bc88bb2bSRuslan Bukin ev = cortex_a53_event_table; 3517*bc88bb2bSRuslan Bukin evfence = cortex_a53_event_table + PMC_EVENT_TABLE_SIZE(cortex_a53); 3518*bc88bb2bSRuslan Bukin break; 3519*bc88bb2bSRuslan Bukin case PMC_CPU_ARMV8_CORTEX_A57: 3520*bc88bb2bSRuslan Bukin ev = cortex_a57_event_table; 3521*bc88bb2bSRuslan Bukin evfence = cortex_a57_event_table + PMC_EVENT_TABLE_SIZE(cortex_a57); 3522*bc88bb2bSRuslan Bukin break; 3523*bc88bb2bSRuslan Bukin default: /* Unknown CPU type. */ 3524*bc88bb2bSRuslan Bukin break; 3525*bc88bb2bSRuslan Bukin } 3526660df75eSGeorge V. Neville-Neil } else if (pe >= PMC_EV_MIPS24K_FIRST && pe <= PMC_EV_MIPS24K_LAST) { 3527660df75eSGeorge V. Neville-Neil ev = mips24k_event_table; 3528f5f9340bSFabien Thomas evfence = mips24k_event_table + PMC_EVENT_TABLE_SIZE(mips24k); 3529f6e6460dSAdrian Chadd } else if (pe >= PMC_EV_MIPS74K_FIRST && pe <= PMC_EV_MIPS74K_LAST) { 3530f6e6460dSAdrian Chadd ev = mips74k_event_table; 3531f6e6460dSAdrian Chadd evfence = mips74k_event_table + PMC_EVENT_TABLE_SIZE(mips74k); 3532c2657f80SOleksandr Tymoshenko } else if (pe >= PMC_EV_OCTEON_FIRST && pe <= PMC_EV_OCTEON_LAST) { 3533c2657f80SOleksandr Tymoshenko ev = octeon_event_table; 3534c2657f80SOleksandr Tymoshenko evfence = octeon_event_table + PMC_EVENT_TABLE_SIZE(octeon); 35357b25dccaSJustin Hibbits } else if (pe >= PMC_EV_PPC7450_FIRST && pe <= PMC_EV_PPC7450_LAST) { 35367b25dccaSJustin Hibbits ev = ppc7450_event_table; 3537f5f9340bSFabien Thomas evfence = ppc7450_event_table + PMC_EVENT_TABLE_SIZE(ppc7450); 3538169dd953SJustin Hibbits } else if (pe >= PMC_EV_PPC970_FIRST && pe <= PMC_EV_PPC970_LAST) { 3539169dd953SJustin Hibbits ev = ppc970_event_table; 3540169dd953SJustin Hibbits evfence = ppc970_event_table + PMC_EVENT_TABLE_SIZE(ppc970); 3541a7452468SJustin Hibbits } else if (pe >= PMC_EV_E500_FIRST && pe <= PMC_EV_E500_LAST) { 3542a7452468SJustin Hibbits ev = e500_event_table; 3543a7452468SJustin Hibbits evfence = e500_event_table + PMC_EVENT_TABLE_SIZE(e500); 3544789140c0SJoseph Koshy } else if (pe == PMC_EV_TSC_TSC) { 3545789140c0SJoseph Koshy ev = tsc_event_table; 3546789140c0SJoseph Koshy evfence = tsc_event_table + PMC_EVENT_TABLE_SIZE(tsc); 3547f0bbe9aaSDimitry Andric } else if ((int)pe >= PMC_EV_SOFT_FIRST && (int)pe <= PMC_EV_SOFT_LAST) { 3548f5f9340bSFabien Thomas ev = soft_event_table; 3549f5f9340bSFabien Thomas evfence = soft_event_table + soft_event_info.pm_nevent; 3550789140c0SJoseph Koshy } 3551789140c0SJoseph Koshy 3552789140c0SJoseph Koshy for (; ev != evfence; ev++) 3553789140c0SJoseph Koshy if (pe == ev->pm_ev_code) 3554789140c0SJoseph Koshy return (ev->pm_ev_name); 3555f263522aSJoseph Koshy 35560cfab8ddSJoseph Koshy return (NULL); 35570cfab8ddSJoseph Koshy } 35580cfab8ddSJoseph Koshy 35590cfab8ddSJoseph Koshy const char * 35600cfab8ddSJoseph Koshy pmc_name_of_event(enum pmc_event pe) 35610cfab8ddSJoseph Koshy { 35620cfab8ddSJoseph Koshy const char *n; 35630cfab8ddSJoseph Koshy 35640cfab8ddSJoseph Koshy if ((n = _pmc_name_of_event(pe, cpu_info.pm_cputype)) != NULL) 35650cfab8ddSJoseph Koshy return (n); 35660cfab8ddSJoseph Koshy 3567f263522aSJoseph Koshy errno = EINVAL; 3568aa342b1fSJoseph Koshy return (NULL); 3569f263522aSJoseph Koshy } 3570f263522aSJoseph Koshy 3571f263522aSJoseph Koshy const char * 3572f263522aSJoseph Koshy pmc_name_of_mode(enum pmc_mode pm) 3573f263522aSJoseph Koshy { 3574f263522aSJoseph Koshy if ((int) pm >= PMC_MODE_FIRST && 3575f263522aSJoseph Koshy pm <= PMC_MODE_LAST) 3576aa342b1fSJoseph Koshy return (pmc_mode_names[pm]); 3577f263522aSJoseph Koshy 3578f263522aSJoseph Koshy errno = EINVAL; 3579aa342b1fSJoseph Koshy return (NULL); 3580f263522aSJoseph Koshy } 3581f263522aSJoseph Koshy 3582f263522aSJoseph Koshy const char * 3583f263522aSJoseph Koshy pmc_name_of_state(enum pmc_state ps) 3584f263522aSJoseph Koshy { 3585f263522aSJoseph Koshy if ((int) ps >= PMC_STATE_FIRST && 3586f263522aSJoseph Koshy ps <= PMC_STATE_LAST) 3587aa342b1fSJoseph Koshy return (pmc_state_names[ps]); 3588f263522aSJoseph Koshy 3589f263522aSJoseph Koshy errno = EINVAL; 3590aa342b1fSJoseph Koshy return (NULL); 3591f263522aSJoseph Koshy } 3592f263522aSJoseph Koshy 3593f263522aSJoseph Koshy int 3594f263522aSJoseph Koshy pmc_ncpu(void) 3595f263522aSJoseph Koshy { 3596f263522aSJoseph Koshy if (pmc_syscall == -1) { 3597f263522aSJoseph Koshy errno = ENXIO; 3598aa342b1fSJoseph Koshy return (-1); 3599f263522aSJoseph Koshy } 3600f263522aSJoseph Koshy 3601aa342b1fSJoseph Koshy return (cpu_info.pm_ncpu); 3602f263522aSJoseph Koshy } 3603f263522aSJoseph Koshy 3604f263522aSJoseph Koshy int 3605f263522aSJoseph Koshy pmc_npmc(int cpu) 3606f263522aSJoseph Koshy { 3607f263522aSJoseph Koshy if (pmc_syscall == -1) { 3608f263522aSJoseph Koshy errno = ENXIO; 3609aa342b1fSJoseph Koshy return (-1); 3610f263522aSJoseph Koshy } 3611f263522aSJoseph Koshy 3612f263522aSJoseph Koshy if (cpu < 0 || cpu >= (int) cpu_info.pm_ncpu) { 3613f263522aSJoseph Koshy errno = EINVAL; 3614aa342b1fSJoseph Koshy return (-1); 3615f263522aSJoseph Koshy } 3616f263522aSJoseph Koshy 3617aa342b1fSJoseph Koshy return (cpu_info.pm_npmc); 3618f263522aSJoseph Koshy } 3619f263522aSJoseph Koshy 3620f263522aSJoseph Koshy int 3621f263522aSJoseph Koshy pmc_pmcinfo(int cpu, struct pmc_pmcinfo **ppmci) 3622f263522aSJoseph Koshy { 3623f263522aSJoseph Koshy int nbytes, npmc; 3624f263522aSJoseph Koshy struct pmc_op_getpmcinfo *pmci; 3625f263522aSJoseph Koshy 3626f263522aSJoseph Koshy if ((npmc = pmc_npmc(cpu)) < 0) 3627aa342b1fSJoseph Koshy return (-1); 3628f263522aSJoseph Koshy 3629f263522aSJoseph Koshy nbytes = sizeof(struct pmc_op_getpmcinfo) + 3630f263522aSJoseph Koshy npmc * sizeof(struct pmc_info); 3631f263522aSJoseph Koshy 3632f263522aSJoseph Koshy if ((pmci = calloc(1, nbytes)) == NULL) 3633aa342b1fSJoseph Koshy return (-1); 3634f263522aSJoseph Koshy 3635f263522aSJoseph Koshy pmci->pm_cpu = cpu; 3636f263522aSJoseph Koshy 3637f263522aSJoseph Koshy if (PMC_CALL(GETPMCINFO, pmci) < 0) { 3638f263522aSJoseph Koshy free(pmci); 3639aa342b1fSJoseph Koshy return (-1); 3640f263522aSJoseph Koshy } 3641f263522aSJoseph Koshy 3642f263522aSJoseph Koshy /* kernel<->library, library<->userland interfaces are identical */ 3643f263522aSJoseph Koshy *ppmci = (struct pmc_pmcinfo *) pmci; 3644aa342b1fSJoseph Koshy return (0); 3645f263522aSJoseph Koshy } 3646f263522aSJoseph Koshy 3647f263522aSJoseph Koshy int 3648f263522aSJoseph Koshy pmc_read(pmc_id_t pmc, pmc_value_t *value) 3649f263522aSJoseph Koshy { 3650f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_read_op; 3651f263522aSJoseph Koshy 3652f263522aSJoseph Koshy pmc_read_op.pm_pmcid = pmc; 3653f263522aSJoseph Koshy pmc_read_op.pm_flags = PMC_F_OLDVALUE; 3654f263522aSJoseph Koshy pmc_read_op.pm_value = -1; 3655f263522aSJoseph Koshy 3656f263522aSJoseph Koshy if (PMC_CALL(PMCRW, &pmc_read_op) < 0) 3657aa342b1fSJoseph Koshy return (-1); 3658f263522aSJoseph Koshy 3659f263522aSJoseph Koshy *value = pmc_read_op.pm_value; 3660aa342b1fSJoseph Koshy return (0); 3661f263522aSJoseph Koshy } 3662f263522aSJoseph Koshy 3663f263522aSJoseph Koshy int 3664f263522aSJoseph Koshy pmc_release(pmc_id_t pmc) 3665f263522aSJoseph Koshy { 3666f263522aSJoseph Koshy struct pmc_op_simple pmc_release_args; 3667f263522aSJoseph Koshy 3668f263522aSJoseph Koshy pmc_release_args.pm_pmcid = pmc; 3669aa342b1fSJoseph Koshy return (PMC_CALL(PMCRELEASE, &pmc_release_args)); 3670f263522aSJoseph Koshy } 3671f263522aSJoseph Koshy 3672f263522aSJoseph Koshy int 3673f263522aSJoseph Koshy pmc_rw(pmc_id_t pmc, pmc_value_t newvalue, pmc_value_t *oldvaluep) 3674f263522aSJoseph Koshy { 3675f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_rw_op; 3676f263522aSJoseph Koshy 3677f263522aSJoseph Koshy pmc_rw_op.pm_pmcid = pmc; 3678f263522aSJoseph Koshy pmc_rw_op.pm_flags = PMC_F_NEWVALUE | PMC_F_OLDVALUE; 3679f263522aSJoseph Koshy pmc_rw_op.pm_value = newvalue; 3680f263522aSJoseph Koshy 3681f263522aSJoseph Koshy if (PMC_CALL(PMCRW, &pmc_rw_op) < 0) 3682aa342b1fSJoseph Koshy return (-1); 3683f263522aSJoseph Koshy 3684f263522aSJoseph Koshy *oldvaluep = pmc_rw_op.pm_value; 3685aa342b1fSJoseph Koshy return (0); 3686f263522aSJoseph Koshy } 3687f263522aSJoseph Koshy 3688f263522aSJoseph Koshy int 3689f263522aSJoseph Koshy pmc_set(pmc_id_t pmc, pmc_value_t value) 3690f263522aSJoseph Koshy { 3691f263522aSJoseph Koshy struct pmc_op_pmcsetcount sc; 3692f263522aSJoseph Koshy 3693f263522aSJoseph Koshy sc.pm_pmcid = pmc; 3694f263522aSJoseph Koshy sc.pm_count = value; 3695f263522aSJoseph Koshy 3696f263522aSJoseph Koshy if (PMC_CALL(PMCSETCOUNT, &sc) < 0) 3697aa342b1fSJoseph Koshy return (-1); 3698aa342b1fSJoseph Koshy return (0); 3699f263522aSJoseph Koshy } 3700f263522aSJoseph Koshy 3701f263522aSJoseph Koshy int 3702f263522aSJoseph Koshy pmc_start(pmc_id_t pmc) 3703f263522aSJoseph Koshy { 3704f263522aSJoseph Koshy struct pmc_op_simple pmc_start_args; 3705f263522aSJoseph Koshy 3706f263522aSJoseph Koshy pmc_start_args.pm_pmcid = pmc; 3707aa342b1fSJoseph Koshy return (PMC_CALL(PMCSTART, &pmc_start_args)); 3708f263522aSJoseph Koshy } 3709f263522aSJoseph Koshy 3710f263522aSJoseph Koshy int 3711f263522aSJoseph Koshy pmc_stop(pmc_id_t pmc) 3712f263522aSJoseph Koshy { 3713f263522aSJoseph Koshy struct pmc_op_simple pmc_stop_args; 3714f263522aSJoseph Koshy 3715f263522aSJoseph Koshy pmc_stop_args.pm_pmcid = pmc; 3716aa342b1fSJoseph Koshy return (PMC_CALL(PMCSTOP, &pmc_stop_args)); 3717f263522aSJoseph Koshy } 3718f263522aSJoseph Koshy 3719f263522aSJoseph Koshy int 3720f263522aSJoseph Koshy pmc_width(pmc_id_t pmcid, uint32_t *width) 3721f263522aSJoseph Koshy { 3722f263522aSJoseph Koshy unsigned int i; 3723f263522aSJoseph Koshy enum pmc_class cl; 3724f263522aSJoseph Koshy 3725f263522aSJoseph Koshy cl = PMC_ID_TO_CLASS(pmcid); 3726f263522aSJoseph Koshy for (i = 0; i < cpu_info.pm_nclass; i++) 3727f263522aSJoseph Koshy if (cpu_info.pm_classes[i].pm_class == cl) { 3728f263522aSJoseph Koshy *width = cpu_info.pm_classes[i].pm_width; 3729aa342b1fSJoseph Koshy return (0); 3730f263522aSJoseph Koshy } 3731484202faSJoseph Koshy errno = EINVAL; 3732484202faSJoseph Koshy return (-1); 3733f263522aSJoseph Koshy } 3734f263522aSJoseph Koshy 3735f263522aSJoseph Koshy int 3736f263522aSJoseph Koshy pmc_write(pmc_id_t pmc, pmc_value_t value) 3737f263522aSJoseph Koshy { 3738f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_write_op; 3739f263522aSJoseph Koshy 3740f263522aSJoseph Koshy pmc_write_op.pm_pmcid = pmc; 3741f263522aSJoseph Koshy pmc_write_op.pm_flags = PMC_F_NEWVALUE; 3742f263522aSJoseph Koshy pmc_write_op.pm_value = value; 3743aa342b1fSJoseph Koshy return (PMC_CALL(PMCRW, &pmc_write_op)); 3744f263522aSJoseph Koshy } 3745f263522aSJoseph Koshy 3746f263522aSJoseph Koshy int 3747f263522aSJoseph Koshy pmc_writelog(uint32_t userdata) 3748f263522aSJoseph Koshy { 3749f263522aSJoseph Koshy struct pmc_op_writelog wl; 3750f263522aSJoseph Koshy 3751f263522aSJoseph Koshy wl.pm_userdata = userdata; 3752aa342b1fSJoseph Koshy return (PMC_CALL(WRITELOG, &wl)); 3753f263522aSJoseph Koshy } 3754