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 85bc88bb2bSRuslan Bukin #if defined(__aarch64__) 86bc88bb2bSRuslan Bukin static int arm64_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 87bc88bb2bSRuslan Bukin struct pmc_op_pmcallocate *_pmc_config); 88bc88bb2bSRuslan 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); 165bc88bb2bSRuslan 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 271bc88bb2bSRuslan Bukin static const struct pmc_event_descr cortex_a53_event_table[] = 272bc88bb2bSRuslan Bukin { 273bc88bb2bSRuslan Bukin __PMC_EV_ALIAS_ARMV8_CORTEX_A53() 274bc88bb2bSRuslan Bukin }; 275bc88bb2bSRuslan Bukin 276bc88bb2bSRuslan Bukin static const struct pmc_event_descr cortex_a57_event_table[] = 277bc88bb2bSRuslan Bukin { 278bc88bb2bSRuslan Bukin __PMC_EV_ALIAS_ARMV8_CORTEX_A57() 279bc88bb2bSRuslan Bukin }; 280bc88bb2bSRuslan 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); 312bc88bb2bSRuslan Bukin PMC_MDEP_TABLE(cortex_a53, ARMV8, PMC_CLASS_SOFT, PMC_CLASS_ARMV8); 313bc88bb2bSRuslan 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 382bc88bb2bSRuslan Bukin #if defined(__aarch64__) 383bc88bb2bSRuslan Bukin PMC_CLASS_TABLE_DESC(cortex_a53, ARMV8, cortex_a53, arm64); 384bc88bb2bSRuslan Bukin PMC_CLASS_TABLE_DESC(cortex_a57, ARMV8, cortex_a57, arm64); 385bc88bb2bSRuslan 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 426*0ceb54c2SJohn Baldwin struct pmc_class_map { 427*0ceb54c2SJohn Baldwin enum pmc_class pm_class; 428*0ceb54c2SJohn Baldwin const char *pm_name; 429*0ceb54c2SJohn Baldwin }; 430*0ceb54c2SJohn Baldwin 431*0ceb54c2SJohn Baldwin static const struct pmc_class_map pmc_class_names[] = { 432ebccf1e3SJoseph Koshy #undef __PMC_CLASS 433*0ceb54c2SJohn Baldwin #define __PMC_CLASS(S,V,D) { .pm_class = PMC_CLASS_##S, .pm_name = #S } , 434ebccf1e3SJoseph Koshy __PMC_CLASSES() 435ebccf1e3SJoseph Koshy }; 436ebccf1e3SJoseph Koshy 437789140c0SJoseph Koshy struct pmc_cputype_map { 438562fc14bSDimitry Andric enum pmc_cputype pm_cputype; 439789140c0SJoseph Koshy const char *pm_name; 440789140c0SJoseph Koshy }; 441789140c0SJoseph Koshy 442789140c0SJoseph Koshy static const struct pmc_cputype_map pmc_cputype_names[] = { 443ebccf1e3SJoseph Koshy #undef __PMC_CPU 444789140c0SJoseph Koshy #define __PMC_CPU(S, V, D) { .pm_cputype = PMC_CPU_##S, .pm_name = #S } , 445ebccf1e3SJoseph Koshy __PMC_CPUS() 446ebccf1e3SJoseph Koshy }; 447ebccf1e3SJoseph Koshy 448ebccf1e3SJoseph Koshy static const char * pmc_disposition_names[] = { 449ebccf1e3SJoseph Koshy #undef __PMC_DISP 450ebccf1e3SJoseph Koshy #define __PMC_DISP(D) #D , 451ebccf1e3SJoseph Koshy __PMC_DISPOSITIONS() 452ebccf1e3SJoseph Koshy }; 453ebccf1e3SJoseph Koshy 454ebccf1e3SJoseph Koshy static const char * pmc_mode_names[] = { 455ebccf1e3SJoseph Koshy #undef __PMC_MODE 456ebccf1e3SJoseph Koshy #define __PMC_MODE(M,N) #M , 457ebccf1e3SJoseph Koshy __PMC_MODES() 458ebccf1e3SJoseph Koshy }; 459ebccf1e3SJoseph Koshy 460ebccf1e3SJoseph Koshy static const char * pmc_state_names[] = { 461ebccf1e3SJoseph Koshy #undef __PMC_STATE 462ebccf1e3SJoseph Koshy #define __PMC_STATE(S) #S , 463ebccf1e3SJoseph Koshy __PMC_STATES() 464ebccf1e3SJoseph Koshy }; 465ebccf1e3SJoseph Koshy 466f5f9340bSFabien Thomas /* 467f5f9340bSFabien Thomas * Filled in by pmc_init(). 468f5f9340bSFabien Thomas */ 469f5f9340bSFabien Thomas static int pmc_syscall = -1; 470f5f9340bSFabien Thomas static struct pmc_cpuinfo cpu_info; 471f5f9340bSFabien Thomas static struct pmc_op_getdyneventinfo soft_event_info; 4721455fcd3SJoseph Koshy 473ebccf1e3SJoseph Koshy /* Event masks for events */ 474ebccf1e3SJoseph Koshy struct pmc_masks { 475ebccf1e3SJoseph Koshy const char *pm_name; 4761e862e5aSFabien Thomas const uint64_t pm_value; 477ebccf1e3SJoseph Koshy }; 478ebccf1e3SJoseph Koshy #define PMCMASK(N,V) { .pm_name = #N, .pm_value = (V) } 4791fa7f10bSFabien Thomas #define NULLMASK { .pm_name = NULL } 480ebccf1e3SJoseph Koshy 48186a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 482ebccf1e3SJoseph Koshy static int 4831e862e5aSFabien Thomas pmc_parse_mask(const struct pmc_masks *pmask, char *p, uint64_t *evmask) 484ebccf1e3SJoseph Koshy { 485ebccf1e3SJoseph Koshy const struct pmc_masks *pm; 486ebccf1e3SJoseph Koshy char *q, *r; 487ebccf1e3SJoseph Koshy int c; 488ebccf1e3SJoseph Koshy 489ebccf1e3SJoseph Koshy if (pmask == NULL) /* no mask keywords */ 490aa342b1fSJoseph Koshy return (-1); 491ebccf1e3SJoseph Koshy q = strchr(p, '='); /* skip '=' */ 492ebccf1e3SJoseph Koshy if (*++q == '\0') /* no more data */ 493aa342b1fSJoseph Koshy return (-1); 494ebccf1e3SJoseph Koshy c = 0; /* count of mask keywords seen */ 495ebccf1e3SJoseph Koshy while ((r = strsep(&q, "+")) != NULL) { 496789140c0SJoseph Koshy for (pm = pmask; pm->pm_name && strcasecmp(r, pm->pm_name); 497789140c0SJoseph Koshy pm++) 498ebccf1e3SJoseph Koshy ; 499ebccf1e3SJoseph Koshy if (pm->pm_name == NULL) /* not found */ 500aa342b1fSJoseph Koshy return (-1); 501ebccf1e3SJoseph Koshy *evmask |= pm->pm_value; 502ebccf1e3SJoseph Koshy c++; 503ebccf1e3SJoseph Koshy } 504aa342b1fSJoseph Koshy return (c); 505ebccf1e3SJoseph Koshy } 50604e9feb0SMarcel Moolenaar #endif 507ebccf1e3SJoseph Koshy 508ebccf1e3SJoseph Koshy #define KWMATCH(p,kw) (strcasecmp((p), (kw)) == 0) 509ebccf1e3SJoseph Koshy #define KWPREFIXMATCH(p,kw) (strncasecmp((p), (kw), sizeof((kw)) - 1) == 0) 510ebccf1e3SJoseph Koshy #define EV_ALIAS(N,S) { .pm_alias = N, .pm_spec = S } 511ebccf1e3SJoseph Koshy 51204e9feb0SMarcel Moolenaar #if defined(__i386__) 513ebccf1e3SJoseph Koshy 514ebccf1e3SJoseph Koshy /* 515ebccf1e3SJoseph Koshy * AMD K7 (Athlon) CPUs. 516ebccf1e3SJoseph Koshy */ 517ebccf1e3SJoseph Koshy 518ebccf1e3SJoseph Koshy static struct pmc_event_alias k7_aliases[] = { 519ebccf1e3SJoseph Koshy EV_ALIAS("branches", "k7-retired-branches"), 520ebccf1e3SJoseph Koshy EV_ALIAS("branch-mispredicts", "k7-retired-branches-mispredicted"), 521ebccf1e3SJoseph Koshy EV_ALIAS("cycles", "tsc"), 5226aa5a193SJoseph Koshy EV_ALIAS("dc-misses", "k7-dc-misses"), 523ebccf1e3SJoseph Koshy EV_ALIAS("ic-misses", "k7-ic-misses"), 524ebccf1e3SJoseph Koshy EV_ALIAS("instructions", "k7-retired-instructions"), 525ebccf1e3SJoseph Koshy EV_ALIAS("interrupts", "k7-hardware-interrupts"), 526ebccf1e3SJoseph Koshy EV_ALIAS(NULL, NULL) 527ebccf1e3SJoseph Koshy }; 528ebccf1e3SJoseph Koshy 529ebccf1e3SJoseph Koshy #define K7_KW_COUNT "count" 530ebccf1e3SJoseph Koshy #define K7_KW_EDGE "edge" 531ebccf1e3SJoseph Koshy #define K7_KW_INV "inv" 532ebccf1e3SJoseph Koshy #define K7_KW_OS "os" 533ebccf1e3SJoseph Koshy #define K7_KW_UNITMASK "unitmask" 534ebccf1e3SJoseph Koshy #define K7_KW_USR "usr" 535ebccf1e3SJoseph Koshy 536ebccf1e3SJoseph Koshy static int 537ebccf1e3SJoseph Koshy k7_allocate_pmc(enum pmc_event pe, char *ctrspec, 538ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 539ebccf1e3SJoseph Koshy { 540ebccf1e3SJoseph Koshy char *e, *p, *q; 541ebccf1e3SJoseph Koshy int c, has_unitmask; 542ebccf1e3SJoseph Koshy uint32_t count, unitmask; 543ebccf1e3SJoseph Koshy 544f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 545789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 546ebccf1e3SJoseph Koshy 547ebccf1e3SJoseph Koshy if (pe == PMC_EV_K7_DC_REFILLS_FROM_L2 || 548ebccf1e3SJoseph Koshy pe == PMC_EV_K7_DC_REFILLS_FROM_SYSTEM || 549ebccf1e3SJoseph Koshy pe == PMC_EV_K7_DC_WRITEBACKS) { 550ebccf1e3SJoseph Koshy has_unitmask = 1; 551f263522aSJoseph Koshy unitmask = AMD_PMC_UNITMASK_MOESI; 552ebccf1e3SJoseph Koshy } else 553ebccf1e3SJoseph Koshy unitmask = has_unitmask = 0; 554ebccf1e3SJoseph Koshy 555ebccf1e3SJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 556ebccf1e3SJoseph Koshy if (KWPREFIXMATCH(p, K7_KW_COUNT "=")) { 557ebccf1e3SJoseph Koshy q = strchr(p, '='); 558ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 559aa342b1fSJoseph Koshy return (-1); 560ebccf1e3SJoseph Koshy 561ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 562ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 563aa342b1fSJoseph Koshy return (-1); 564ebccf1e3SJoseph Koshy 565ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 566f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config |= 567f263522aSJoseph Koshy AMD_PMC_TO_COUNTER(count); 568ebccf1e3SJoseph Koshy 569ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_EDGE)) { 570ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 571ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_INV)) { 572ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 573ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_OS)) { 574ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 575ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, K7_KW_UNITMASK "=")) { 576ebccf1e3SJoseph Koshy if (has_unitmask == 0) 577aa342b1fSJoseph Koshy return (-1); 578ebccf1e3SJoseph Koshy unitmask = 0; 579ebccf1e3SJoseph Koshy q = strchr(p, '='); 580ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 581aa342b1fSJoseph Koshy return (-1); 582ebccf1e3SJoseph Koshy 583ebccf1e3SJoseph Koshy while ((c = tolower(*q++)) != 0) 584ebccf1e3SJoseph Koshy if (c == 'm') 585f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_M; 586ebccf1e3SJoseph Koshy else if (c == 'o') 587f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_O; 588ebccf1e3SJoseph Koshy else if (c == 'e') 589f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_E; 590ebccf1e3SJoseph Koshy else if (c == 's') 591f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_S; 592ebccf1e3SJoseph Koshy else if (c == 'i') 593f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_I; 594ebccf1e3SJoseph Koshy else if (c == '+') 595ebccf1e3SJoseph Koshy continue; 596ebccf1e3SJoseph Koshy else 597aa342b1fSJoseph Koshy return (-1); 598ebccf1e3SJoseph Koshy 599ebccf1e3SJoseph Koshy if (unitmask == 0) 600aa342b1fSJoseph Koshy return (-1); 601ebccf1e3SJoseph Koshy 602ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_USR)) { 603ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 604ebccf1e3SJoseph Koshy } else 605aa342b1fSJoseph Koshy return (-1); 606ebccf1e3SJoseph Koshy } 607ebccf1e3SJoseph Koshy 608ebccf1e3SJoseph Koshy if (has_unitmask) { 609ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 610f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config |= 611f263522aSJoseph Koshy AMD_PMC_TO_UNITMASK(unitmask); 612ebccf1e3SJoseph Koshy } 613ebccf1e3SJoseph Koshy 614aa342b1fSJoseph Koshy return (0); 615ebccf1e3SJoseph Koshy 616ebccf1e3SJoseph Koshy } 617ebccf1e3SJoseph Koshy 618f263522aSJoseph Koshy #endif 619f263522aSJoseph Koshy 62086a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 621f263522aSJoseph Koshy 622f263522aSJoseph Koshy /* 6230cfab8ddSJoseph Koshy * Intel Core (Family 6, Model E) PMCs. 6240cfab8ddSJoseph Koshy */ 6250cfab8ddSJoseph Koshy 6260cfab8ddSJoseph Koshy static struct pmc_event_alias core_aliases[] = { 6270cfab8ddSJoseph Koshy EV_ALIAS("branches", "iap-br-instr-ret"), 6280cfab8ddSJoseph Koshy EV_ALIAS("branch-mispredicts", "iap-br-mispred-ret"), 6290cfab8ddSJoseph Koshy EV_ALIAS("cycles", "tsc-tsc"), 6300cfab8ddSJoseph Koshy EV_ALIAS("ic-misses", "iap-icache-misses"), 6310cfab8ddSJoseph Koshy EV_ALIAS("instructions", "iap-instr-ret"), 6320cfab8ddSJoseph Koshy EV_ALIAS("interrupts", "iap-core-hw-int-rx"), 6330cfab8ddSJoseph Koshy EV_ALIAS("unhalted-cycles", "iap-unhalted-core-cycles"), 6340cfab8ddSJoseph Koshy EV_ALIAS(NULL, NULL) 6350cfab8ddSJoseph Koshy }; 6360cfab8ddSJoseph Koshy 6370cfab8ddSJoseph Koshy /* 6380cfab8ddSJoseph Koshy * Intel Core2 (Family 6, Model F), Core2Extreme (Family 6, Model 17H) 6390cfab8ddSJoseph Koshy * and Atom (Family 6, model 1CH) PMCs. 640791f5d5bSJoseph Koshy * 641791f5d5bSJoseph Koshy * We map aliases to events on the fixed-function counters if these 642791f5d5bSJoseph Koshy * are present. Note that not all CPUs in this family contain fixed-function 643791f5d5bSJoseph Koshy * counters. 6440cfab8ddSJoseph Koshy */ 6450cfab8ddSJoseph Koshy 6460cfab8ddSJoseph Koshy static struct pmc_event_alias core2_aliases[] = { 6470cfab8ddSJoseph Koshy EV_ALIAS("branches", "iap-br-inst-retired.any"), 6480cfab8ddSJoseph Koshy EV_ALIAS("branch-mispredicts", "iap-br-inst-retired.mispred"), 6490cfab8ddSJoseph Koshy EV_ALIAS("cycles", "tsc-tsc"), 6500cfab8ddSJoseph Koshy EV_ALIAS("ic-misses", "iap-l1i-misses"), 6510cfab8ddSJoseph Koshy EV_ALIAS("instructions", "iaf-instr-retired.any"), 6520cfab8ddSJoseph Koshy EV_ALIAS("interrupts", "iap-hw-int-rcv"), 6530cfab8ddSJoseph Koshy EV_ALIAS("unhalted-cycles", "iaf-cpu-clk-unhalted.core"), 6540cfab8ddSJoseph Koshy EV_ALIAS(NULL, NULL) 6550cfab8ddSJoseph Koshy }; 656791f5d5bSJoseph Koshy 657791f5d5bSJoseph Koshy static struct pmc_event_alias core2_aliases_without_iaf[] = { 658791f5d5bSJoseph Koshy EV_ALIAS("branches", "iap-br-inst-retired.any"), 659791f5d5bSJoseph Koshy EV_ALIAS("branch-mispredicts", "iap-br-inst-retired.mispred"), 660791f5d5bSJoseph Koshy EV_ALIAS("cycles", "tsc-tsc"), 661791f5d5bSJoseph Koshy EV_ALIAS("ic-misses", "iap-l1i-misses"), 662791f5d5bSJoseph Koshy EV_ALIAS("instructions", "iap-inst-retired.any_p"), 663791f5d5bSJoseph Koshy EV_ALIAS("interrupts", "iap-hw-int-rcv"), 664791f5d5bSJoseph Koshy EV_ALIAS("unhalted-cycles", "iap-cpu-clk-unhalted.core_p"), 665791f5d5bSJoseph Koshy EV_ALIAS(NULL, NULL) 666791f5d5bSJoseph Koshy }; 667791f5d5bSJoseph Koshy 6680cfab8ddSJoseph Koshy #define atom_aliases core2_aliases 669791f5d5bSJoseph Koshy #define atom_aliases_without_iaf core2_aliases_without_iaf 670e8f021a3SHiren Panchasara #define atom_silvermont_aliases core2_aliases 671e8f021a3SHiren Panchasara #define atom_silvermont_aliases_without_iaf core2_aliases_without_iaf 672597979c4SJeff Roberson #define corei7_aliases core2_aliases 673791f5d5bSJoseph Koshy #define corei7_aliases_without_iaf core2_aliases_without_iaf 67449fe48abSKonstantin Belousov #define nehalem_ex_aliases core2_aliases 67549fe48abSKonstantin Belousov #define nehalem_ex_aliases_without_iaf core2_aliases_without_iaf 676cc0c1555SSean Bruno #define haswell_aliases core2_aliases 677cc0c1555SSean Bruno #define haswell_aliases_without_iaf core2_aliases_without_iaf 678d95b3509SRandall Stewart #define haswell_xeon_aliases core2_aliases 679d95b3509SRandall Stewart #define haswell_xeon_aliases_without_iaf core2_aliases_without_iaf 6801e862e5aSFabien Thomas #define ivybridge_aliases core2_aliases 6811e862e5aSFabien Thomas #define ivybridge_aliases_without_iaf core2_aliases_without_iaf 6823f929d8cSSean Bruno #define ivybridge_xeon_aliases core2_aliases 6833f929d8cSSean Bruno #define ivybridge_xeon_aliases_without_iaf core2_aliases_without_iaf 68478d763a2SDavide Italiano #define sandybridge_aliases core2_aliases 68578d763a2SDavide Italiano #define sandybridge_aliases_without_iaf core2_aliases_without_iaf 686fabe02f5SSean Bruno #define sandybridge_xeon_aliases core2_aliases 687fabe02f5SSean Bruno #define sandybridge_xeon_aliases_without_iaf core2_aliases_without_iaf 6881fa7f10bSFabien Thomas #define westmere_aliases core2_aliases 6891fa7f10bSFabien Thomas #define westmere_aliases_without_iaf core2_aliases_without_iaf 69049fe48abSKonstantin Belousov #define westmere_ex_aliases core2_aliases 69149fe48abSKonstantin Belousov #define westmere_ex_aliases_without_iaf core2_aliases_without_iaf 6920cfab8ddSJoseph Koshy 6930cfab8ddSJoseph Koshy #define IAF_KW_OS "os" 6940cfab8ddSJoseph Koshy #define IAF_KW_USR "usr" 6950cfab8ddSJoseph Koshy #define IAF_KW_ANYTHREAD "anythread" 6960cfab8ddSJoseph Koshy 6970cfab8ddSJoseph Koshy /* 6980cfab8ddSJoseph Koshy * Parse an event specifier for Intel fixed function counters. 6990cfab8ddSJoseph Koshy */ 7000cfab8ddSJoseph Koshy static int 7010cfab8ddSJoseph Koshy iaf_allocate_pmc(enum pmc_event pe, char *ctrspec, 7020cfab8ddSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 7030cfab8ddSJoseph Koshy { 7040cfab8ddSJoseph Koshy char *p; 7050cfab8ddSJoseph Koshy 7060cfab8ddSJoseph Koshy (void) pe; 7070cfab8ddSJoseph Koshy 7080cfab8ddSJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 7090cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iaf.pm_iaf_flags = 0; 7100cfab8ddSJoseph Koshy 7110cfab8ddSJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 7120cfab8ddSJoseph Koshy if (KWMATCH(p, IAF_KW_OS)) 7130cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 7140cfab8ddSJoseph Koshy else if (KWMATCH(p, IAF_KW_USR)) 7150cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 7160cfab8ddSJoseph Koshy else if (KWMATCH(p, IAF_KW_ANYTHREAD)) 7170cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iaf.pm_iaf_flags |= IAF_ANY; 7180cfab8ddSJoseph Koshy else 7190cfab8ddSJoseph Koshy return (-1); 7200cfab8ddSJoseph Koshy } 7210cfab8ddSJoseph Koshy 7220cfab8ddSJoseph Koshy return (0); 7230cfab8ddSJoseph Koshy } 7240cfab8ddSJoseph Koshy 7250cfab8ddSJoseph Koshy /* 7260cfab8ddSJoseph Koshy * Core/Core2 support. 7270cfab8ddSJoseph Koshy */ 7280cfab8ddSJoseph Koshy 7290cfab8ddSJoseph Koshy #define IAP_KW_AGENT "agent" 7300cfab8ddSJoseph Koshy #define IAP_KW_ANYTHREAD "anythread" 7310cfab8ddSJoseph Koshy #define IAP_KW_CACHESTATE "cachestate" 7320cfab8ddSJoseph Koshy #define IAP_KW_CMASK "cmask" 7330cfab8ddSJoseph Koshy #define IAP_KW_CORE "core" 7340cfab8ddSJoseph Koshy #define IAP_KW_EDGE "edge" 7350cfab8ddSJoseph Koshy #define IAP_KW_INV "inv" 7360cfab8ddSJoseph Koshy #define IAP_KW_OS "os" 7370cfab8ddSJoseph Koshy #define IAP_KW_PREFETCH "prefetch" 7380cfab8ddSJoseph Koshy #define IAP_KW_SNOOPRESPONSE "snoopresponse" 7390cfab8ddSJoseph Koshy #define IAP_KW_SNOOPTYPE "snooptype" 7400cfab8ddSJoseph Koshy #define IAP_KW_TRANSITION "trans" 7410cfab8ddSJoseph Koshy #define IAP_KW_USR "usr" 7421fa7f10bSFabien Thomas #define IAP_KW_RSP "rsp" 7430cfab8ddSJoseph Koshy 7440cfab8ddSJoseph Koshy static struct pmc_masks iap_core_mask[] = { 7450cfab8ddSJoseph Koshy PMCMASK(all, (0x3 << 14)), 7460cfab8ddSJoseph Koshy PMCMASK(this, (0x1 << 14)), 7470cfab8ddSJoseph Koshy NULLMASK 7480cfab8ddSJoseph Koshy }; 7490cfab8ddSJoseph Koshy 7500cfab8ddSJoseph Koshy static struct pmc_masks iap_agent_mask[] = { 7510cfab8ddSJoseph Koshy PMCMASK(this, 0), 7520cfab8ddSJoseph Koshy PMCMASK(any, (0x1 << 13)), 7530cfab8ddSJoseph Koshy NULLMASK 7540cfab8ddSJoseph Koshy }; 7550cfab8ddSJoseph Koshy 7560cfab8ddSJoseph Koshy static struct pmc_masks iap_prefetch_mask[] = { 7570cfab8ddSJoseph Koshy PMCMASK(both, (0x3 << 12)), 7580cfab8ddSJoseph Koshy PMCMASK(only, (0x1 << 12)), 7590cfab8ddSJoseph Koshy PMCMASK(exclude, 0), 7600cfab8ddSJoseph Koshy NULLMASK 7610cfab8ddSJoseph Koshy }; 7620cfab8ddSJoseph Koshy 7630cfab8ddSJoseph Koshy static struct pmc_masks iap_cachestate_mask[] = { 7640cfab8ddSJoseph Koshy PMCMASK(i, (1 << 8)), 7650cfab8ddSJoseph Koshy PMCMASK(s, (1 << 9)), 7660cfab8ddSJoseph Koshy PMCMASK(e, (1 << 10)), 7670cfab8ddSJoseph Koshy PMCMASK(m, (1 << 11)), 7680cfab8ddSJoseph Koshy NULLMASK 7690cfab8ddSJoseph Koshy }; 7700cfab8ddSJoseph Koshy 7710cfab8ddSJoseph Koshy static struct pmc_masks iap_snoopresponse_mask[] = { 7720cfab8ddSJoseph Koshy PMCMASK(clean, (1 << 8)), 7730cfab8ddSJoseph Koshy PMCMASK(hit, (1 << 9)), 7740cfab8ddSJoseph Koshy PMCMASK(hitm, (1 << 11)), 7750cfab8ddSJoseph Koshy NULLMASK 7760cfab8ddSJoseph Koshy }; 7770cfab8ddSJoseph Koshy 7780cfab8ddSJoseph Koshy static struct pmc_masks iap_snooptype_mask[] = { 7790cfab8ddSJoseph Koshy PMCMASK(cmp2s, (1 << 8)), 7800cfab8ddSJoseph Koshy PMCMASK(cmp2i, (1 << 9)), 7810cfab8ddSJoseph Koshy NULLMASK 7820cfab8ddSJoseph Koshy }; 7830cfab8ddSJoseph Koshy 7840cfab8ddSJoseph Koshy static struct pmc_masks iap_transition_mask[] = { 7850cfab8ddSJoseph Koshy PMCMASK(any, 0x00), 7860cfab8ddSJoseph Koshy PMCMASK(frequency, 0x10), 7870cfab8ddSJoseph Koshy NULLMASK 7880cfab8ddSJoseph Koshy }; 7890cfab8ddSJoseph Koshy 7901e862e5aSFabien Thomas static struct pmc_masks iap_rsp_mask_i7_wm[] = { 7911fa7f10bSFabien Thomas PMCMASK(DMND_DATA_RD, (1 << 0)), 7921fa7f10bSFabien Thomas PMCMASK(DMND_RFO, (1 << 1)), 7931fa7f10bSFabien Thomas PMCMASK(DMND_IFETCH, (1 << 2)), 7941fa7f10bSFabien Thomas PMCMASK(WB, (1 << 3)), 7951fa7f10bSFabien Thomas PMCMASK(PF_DATA_RD, (1 << 4)), 7961fa7f10bSFabien Thomas PMCMASK(PF_RFO, (1 << 5)), 7971fa7f10bSFabien Thomas PMCMASK(PF_IFETCH, (1 << 6)), 7981fa7f10bSFabien Thomas PMCMASK(OTHER, (1 << 7)), 7991fa7f10bSFabien Thomas PMCMASK(UNCORE_HIT, (1 << 8)), 8001fa7f10bSFabien Thomas PMCMASK(OTHER_CORE_HIT_SNP, (1 << 9)), 8011fa7f10bSFabien Thomas PMCMASK(OTHER_CORE_HITM, (1 << 10)), 8021fa7f10bSFabien Thomas PMCMASK(REMOTE_CACHE_FWD, (1 << 12)), 8031fa7f10bSFabien Thomas PMCMASK(REMOTE_DRAM, (1 << 13)), 8041fa7f10bSFabien Thomas PMCMASK(LOCAL_DRAM, (1 << 14)), 8051fa7f10bSFabien Thomas PMCMASK(NON_DRAM, (1 << 15)), 8061fa7f10bSFabien Thomas NULLMASK 8071fa7f10bSFabien Thomas }; 8081fa7f10bSFabien Thomas 809fabe02f5SSean Bruno static struct pmc_masks iap_rsp_mask_sb_sbx_ib[] = { 8101e862e5aSFabien Thomas PMCMASK(REQ_DMND_DATA_RD, (1ULL << 0)), 8111e862e5aSFabien Thomas PMCMASK(REQ_DMND_RFO, (1ULL << 1)), 8121e862e5aSFabien Thomas PMCMASK(REQ_DMND_IFETCH, (1ULL << 2)), 8131e862e5aSFabien Thomas PMCMASK(REQ_WB, (1ULL << 3)), 8141e862e5aSFabien Thomas PMCMASK(REQ_PF_DATA_RD, (1ULL << 4)), 8151e862e5aSFabien Thomas PMCMASK(REQ_PF_RFO, (1ULL << 5)), 8161e862e5aSFabien Thomas PMCMASK(REQ_PF_IFETCH, (1ULL << 6)), 8171e862e5aSFabien Thomas PMCMASK(REQ_PF_LLC_DATA_RD, (1ULL << 7)), 8181e862e5aSFabien Thomas PMCMASK(REQ_PF_LLC_RFO, (1ULL << 8)), 8191e862e5aSFabien Thomas PMCMASK(REQ_PF_LLC_IFETCH, (1ULL << 9)), 8201e862e5aSFabien Thomas PMCMASK(REQ_BUS_LOCKS, (1ULL << 10)), 8211e862e5aSFabien Thomas PMCMASK(REQ_STRM_ST, (1ULL << 11)), 8221e862e5aSFabien Thomas PMCMASK(REQ_OTHER, (1ULL << 15)), 8231e862e5aSFabien Thomas PMCMASK(RES_ANY, (1ULL << 16)), 8241e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_SUPP, (1ULL << 17)), 8251e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_LLC_HITM, (1ULL << 18)), 8261e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_LLC_HITE, (1ULL << 19)), 8271e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_LLC_HITS, (1ULL << 20)), 8281e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_LLC_HITF, (1ULL << 21)), 8291e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_LOCAL, (1ULL << 22)), 830cdfd0cc8SSean Bruno PMCMASK(RES_SNOOP_SNP_NONE, (1ULL << 31)), 8311e862e5aSFabien Thomas PMCMASK(RES_SNOOP_SNP_NO_NEEDED,(1ULL << 32)), 8321e862e5aSFabien Thomas PMCMASK(RES_SNOOP_SNP_MISS, (1ULL << 33)), 8331e862e5aSFabien Thomas PMCMASK(RES_SNOOP_HIT_NO_FWD, (1ULL << 34)), 8341e862e5aSFabien Thomas PMCMASK(RES_SNOOP_HIT_FWD, (1ULL << 35)), 8351e862e5aSFabien Thomas PMCMASK(RES_SNOOP_HITM, (1ULL << 36)), 8361e862e5aSFabien Thomas PMCMASK(RES_NON_DRAM, (1ULL << 37)), 8371e862e5aSFabien Thomas NULLMASK 8381e862e5aSFabien Thomas }; 8391e862e5aSFabien Thomas 840cc0c1555SSean Bruno static struct pmc_masks iap_rsp_mask_haswell[] = { 841cc0c1555SSean Bruno PMCMASK(REQ_DMND_DATA_RD, (1ULL << 0)), 842cc0c1555SSean Bruno PMCMASK(REQ_DMND_RFO, (1ULL << 1)), 843cc0c1555SSean Bruno PMCMASK(REQ_DMND_IFETCH, (1ULL << 2)), 844cc0c1555SSean Bruno PMCMASK(REQ_PF_DATA_RD, (1ULL << 4)), 845cc0c1555SSean Bruno PMCMASK(REQ_PF_RFO, (1ULL << 5)), 846cc0c1555SSean Bruno PMCMASK(REQ_PF_IFETCH, (1ULL << 6)), 847cc0c1555SSean Bruno PMCMASK(REQ_OTHER, (1ULL << 15)), 848cc0c1555SSean Bruno PMCMASK(RES_ANY, (1ULL << 16)), 849cc0c1555SSean Bruno PMCMASK(RES_SUPPLIER_SUPP, (1ULL << 17)), 850cc0c1555SSean Bruno PMCMASK(RES_SUPPLIER_LLC_HITM, (1ULL << 18)), 851cc0c1555SSean Bruno PMCMASK(RES_SUPPLIER_LLC_HITE, (1ULL << 19)), 852cc0c1555SSean Bruno PMCMASK(RES_SUPPLIER_LLC_HITS, (1ULL << 20)), 853cc0c1555SSean Bruno PMCMASK(RES_SUPPLIER_LLC_HITF, (1ULL << 21)), 854cc0c1555SSean Bruno PMCMASK(RES_SUPPLIER_LOCAL, (1ULL << 22)), 855cc0c1555SSean Bruno PMCMASK(RES_SNOOP_SNP_NONE, (1ULL << 31)), 856cc0c1555SSean Bruno PMCMASK(RES_SNOOP_SNP_NO_NEEDED,(1ULL << 32)), 857cc0c1555SSean Bruno PMCMASK(RES_SNOOP_SNP_MISS, (1ULL << 33)), 858cc0c1555SSean Bruno PMCMASK(RES_SNOOP_HIT_NO_FWD, (1ULL << 34)), 859cc0c1555SSean Bruno PMCMASK(RES_SNOOP_HIT_FWD, (1ULL << 35)), 860cc0c1555SSean Bruno PMCMASK(RES_SNOOP_HITM, (1ULL << 36)), 861cc0c1555SSean Bruno PMCMASK(RES_NON_DRAM, (1ULL << 37)), 862cc0c1555SSean Bruno NULLMASK 863cc0c1555SSean Bruno }; 864cc0c1555SSean Bruno 8650cfab8ddSJoseph Koshy static int 8660cfab8ddSJoseph Koshy iap_allocate_pmc(enum pmc_event pe, char *ctrspec, 8670cfab8ddSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 8680cfab8ddSJoseph Koshy { 8690cfab8ddSJoseph Koshy char *e, *p, *q; 8701e862e5aSFabien Thomas uint64_t cachestate, evmask, rsp; 8710cfab8ddSJoseph Koshy int count, n; 8720cfab8ddSJoseph Koshy 8730cfab8ddSJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE | 8740cfab8ddSJoseph Koshy PMC_CAP_QUALIFIER); 8750cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config = 0; 8760cfab8ddSJoseph Koshy 8771fa7f10bSFabien Thomas cachestate = evmask = rsp = 0; 8780cfab8ddSJoseph Koshy 8790cfab8ddSJoseph Koshy /* Parse additional modifiers if present */ 8800cfab8ddSJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 8810cfab8ddSJoseph Koshy 8820cfab8ddSJoseph Koshy n = 0; 8830cfab8ddSJoseph Koshy if (KWPREFIXMATCH(p, IAP_KW_CMASK "=")) { 8840cfab8ddSJoseph Koshy q = strchr(p, '='); 8850cfab8ddSJoseph Koshy if (*++q == '\0') /* skip '=' */ 8860cfab8ddSJoseph Koshy return (-1); 8870cfab8ddSJoseph Koshy count = strtol(q, &e, 0); 8880cfab8ddSJoseph Koshy if (e == q || *e != '\0') 8890cfab8ddSJoseph Koshy return (-1); 8900cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 8910cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= 8920cfab8ddSJoseph Koshy IAP_CMASK(count); 8930cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_EDGE)) { 8940cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 8950cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_INV)) { 8960cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 8970cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_OS)) { 8980cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 8990cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_USR)) { 9000cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 9010cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_ANYTHREAD)) { 9020cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= IAP_ANY; 903b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_CORE "=")) { 9040cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_core_mask, p, &evmask); 9050cfab8ddSJoseph Koshy if (n != 1) 9060cfab8ddSJoseph Koshy return (-1); 907b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_AGENT "=")) { 9080cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_agent_mask, p, &evmask); 9090cfab8ddSJoseph Koshy if (n != 1) 9100cfab8ddSJoseph Koshy return (-1); 911b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_PREFETCH "=")) { 9120cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_prefetch_mask, p, &evmask); 9130cfab8ddSJoseph Koshy if (n != 1) 9140cfab8ddSJoseph Koshy return (-1); 915b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_CACHESTATE "=")) { 9160cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_cachestate_mask, p, &cachestate); 9170cfab8ddSJoseph Koshy } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_CORE && 918b47ea38eSJoseph Koshy KWPREFIXMATCH(p, IAP_KW_TRANSITION "=")) { 9190cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_transition_mask, p, &evmask); 9200cfab8ddSJoseph Koshy if (n != 1) 9210cfab8ddSJoseph Koshy return (-1); 9220cfab8ddSJoseph Koshy } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM || 923e8f021a3SHiren Panchasara cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM_SILVERMONT || 924b4d091f3SJoseph Koshy cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2 || 9251fa7f10bSFabien Thomas cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2EXTREME) { 926b47ea38eSJoseph Koshy if (KWPREFIXMATCH(p, IAP_KW_SNOOPRESPONSE "=")) { 9270cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_snoopresponse_mask, p, 9280cfab8ddSJoseph Koshy &evmask); 929b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_SNOOPTYPE "=")) { 9300cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_snooptype_mask, p, 9310cfab8ddSJoseph Koshy &evmask); 9320cfab8ddSJoseph Koshy } else 9330cfab8ddSJoseph Koshy return (-1); 9341fa7f10bSFabien Thomas } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_COREI7 || 93549fe48abSKonstantin Belousov cpu_info.pm_cputype == PMC_CPU_INTEL_WESTMERE || 93649fe48abSKonstantin Belousov cpu_info.pm_cputype == PMC_CPU_INTEL_NEHALEM_EX || 93749fe48abSKonstantin Belousov cpu_info.pm_cputype == PMC_CPU_INTEL_WESTMERE_EX) { 9381fa7f10bSFabien Thomas if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 9391e862e5aSFabien Thomas n = pmc_parse_mask(iap_rsp_mask_i7_wm, p, &rsp); 9401e862e5aSFabien Thomas } else 9411e862e5aSFabien Thomas return (-1); 9421e862e5aSFabien Thomas } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_SANDYBRIDGE || 943fabe02f5SSean Bruno cpu_info.pm_cputype == PMC_CPU_INTEL_SANDYBRIDGE_XEON || 9443f929d8cSSean Bruno cpu_info.pm_cputype == PMC_CPU_INTEL_IVYBRIDGE || 9453f929d8cSSean Bruno cpu_info.pm_cputype == PMC_CPU_INTEL_IVYBRIDGE_XEON ) { 9461e862e5aSFabien Thomas if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 947fabe02f5SSean Bruno n = pmc_parse_mask(iap_rsp_mask_sb_sbx_ib, p, &rsp); 9481fa7f10bSFabien Thomas } else 9491fa7f10bSFabien Thomas return (-1); 950d95b3509SRandall Stewart } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_HASWELL || 951d95b3509SRandall Stewart cpu_info.pm_cputype == PMC_CPU_INTEL_HASWELL_XEON) { 952cc0c1555SSean Bruno if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 953cc0c1555SSean Bruno n = pmc_parse_mask(iap_rsp_mask_haswell, p, &rsp); 954cc0c1555SSean Bruno } else 955cc0c1555SSean Bruno return (-1); 9560cfab8ddSJoseph Koshy } else 9570cfab8ddSJoseph Koshy return (-1); 9580cfab8ddSJoseph Koshy 9590cfab8ddSJoseph Koshy if (n < 0) /* Parsing failed. */ 9600cfab8ddSJoseph Koshy return (-1); 9610cfab8ddSJoseph Koshy } 9620cfab8ddSJoseph Koshy 9630cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= evmask; 9640cfab8ddSJoseph Koshy 9650cfab8ddSJoseph Koshy /* 9660cfab8ddSJoseph Koshy * If the event requires a 'cachestate' qualifier but was not 9670cfab8ddSJoseph Koshy * specified by the user, use a sensible default. 9680cfab8ddSJoseph Koshy */ 9690cfab8ddSJoseph Koshy switch (pe) { 9700cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_28H: /* Core, Core2, Atom */ 9710cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_29H: /* Core, Core2, Atom */ 9720cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_2AH: /* Core, Core2, Atom */ 9730cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_2BH: /* Atom, Core2 */ 9740cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_2EH: /* Core, Core2, Atom */ 9750cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_30H: /* Core, Core2, Atom */ 9760cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_32H: /* Core */ 9770cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_40H: /* Core */ 9780cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_41H: /* Core */ 9790cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_42H: /* Core, Core2, Atom */ 9800cfab8ddSJoseph Koshy if (cachestate == 0) 9810cfab8ddSJoseph Koshy cachestate = (0xF << 8); 982aa1b887bSRyan Stone break; 983aa1b887bSRyan Stone case PMC_EV_IAP_EVENT_77H: /* Atom */ 984aa1b887bSRyan Stone /* IAP_EVENT_77H only accepts a cachestate qualifier on the 985aa1b887bSRyan Stone * Atom processor 986aa1b887bSRyan Stone */ 987aa1b887bSRyan Stone if(cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM && cachestate == 0) 988aa1b887bSRyan Stone cachestate = (0xF << 8); 989aa1b887bSRyan Stone break; 9900cfab8ddSJoseph Koshy default: 9910cfab8ddSJoseph Koshy break; 9920cfab8ddSJoseph Koshy } 9930cfab8ddSJoseph Koshy 9940cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= cachestate; 9951fa7f10bSFabien Thomas pmc_config->pm_md.pm_iap.pm_iap_rsp = rsp; 9961fa7f10bSFabien Thomas 9971fa7f10bSFabien Thomas return (0); 9981fa7f10bSFabien Thomas } 9991fa7f10bSFabien Thomas 10001fa7f10bSFabien Thomas /* 10011fa7f10bSFabien Thomas * Intel Uncore. 10021fa7f10bSFabien Thomas */ 10031fa7f10bSFabien Thomas 10041fa7f10bSFabien Thomas static int 10051fa7f10bSFabien Thomas ucf_allocate_pmc(enum pmc_event pe, char *ctrspec, 10061fa7f10bSFabien Thomas struct pmc_op_pmcallocate *pmc_config) 10071fa7f10bSFabien Thomas { 10081fa7f10bSFabien Thomas (void) pe; 10091fa7f10bSFabien Thomas (void) ctrspec; 10101fa7f10bSFabien Thomas 10111fa7f10bSFabien Thomas pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 10121fa7f10bSFabien Thomas pmc_config->pm_md.pm_ucf.pm_ucf_flags = 0; 10131fa7f10bSFabien Thomas 10141fa7f10bSFabien Thomas return (0); 10151fa7f10bSFabien Thomas } 10161fa7f10bSFabien Thomas 10171fa7f10bSFabien Thomas #define UCP_KW_CMASK "cmask" 10181fa7f10bSFabien Thomas #define UCP_KW_EDGE "edge" 10191fa7f10bSFabien Thomas #define UCP_KW_INV "inv" 10201fa7f10bSFabien Thomas 10211fa7f10bSFabien Thomas static int 10221fa7f10bSFabien Thomas ucp_allocate_pmc(enum pmc_event pe, char *ctrspec, 10231fa7f10bSFabien Thomas struct pmc_op_pmcallocate *pmc_config) 10241fa7f10bSFabien Thomas { 10251fa7f10bSFabien Thomas char *e, *p, *q; 10261fa7f10bSFabien Thomas int count, n; 10271fa7f10bSFabien Thomas 10281fa7f10bSFabien Thomas (void) pe; 10291fa7f10bSFabien Thomas 10301fa7f10bSFabien Thomas pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE | 10311fa7f10bSFabien Thomas PMC_CAP_QUALIFIER); 10321fa7f10bSFabien Thomas pmc_config->pm_md.pm_ucp.pm_ucp_config = 0; 10331fa7f10bSFabien Thomas 10341fa7f10bSFabien Thomas /* Parse additional modifiers if present */ 10351fa7f10bSFabien Thomas while ((p = strsep(&ctrspec, ",")) != NULL) { 10361fa7f10bSFabien Thomas 10371fa7f10bSFabien Thomas n = 0; 10381fa7f10bSFabien Thomas if (KWPREFIXMATCH(p, UCP_KW_CMASK "=")) { 10391fa7f10bSFabien Thomas q = strchr(p, '='); 10401fa7f10bSFabien Thomas if (*++q == '\0') /* skip '=' */ 10411fa7f10bSFabien Thomas return (-1); 10421fa7f10bSFabien Thomas count = strtol(q, &e, 0); 10431fa7f10bSFabien Thomas if (e == q || *e != '\0') 10441fa7f10bSFabien Thomas return (-1); 10451fa7f10bSFabien Thomas pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 10461fa7f10bSFabien Thomas pmc_config->pm_md.pm_ucp.pm_ucp_config |= 10471fa7f10bSFabien Thomas UCP_CMASK(count); 10481fa7f10bSFabien Thomas } else if (KWMATCH(p, UCP_KW_EDGE)) { 10491fa7f10bSFabien Thomas pmc_config->pm_caps |= PMC_CAP_EDGE; 10501fa7f10bSFabien Thomas } else if (KWMATCH(p, UCP_KW_INV)) { 10511fa7f10bSFabien Thomas pmc_config->pm_caps |= PMC_CAP_INVERT; 10521fa7f10bSFabien Thomas } else 10531fa7f10bSFabien Thomas return (-1); 10541fa7f10bSFabien Thomas 10551fa7f10bSFabien Thomas if (n < 0) /* Parsing failed. */ 10561fa7f10bSFabien Thomas return (-1); 10571fa7f10bSFabien Thomas } 10580cfab8ddSJoseph Koshy 10590cfab8ddSJoseph Koshy return (0); 10600cfab8ddSJoseph Koshy } 10610cfab8ddSJoseph Koshy 10620cfab8ddSJoseph Koshy /* 1063f263522aSJoseph Koshy * AMD K8 PMCs. 1064f263522aSJoseph Koshy * 1065f263522aSJoseph Koshy * These are very similar to AMD K7 PMCs, but support more kinds of 1066f263522aSJoseph Koshy * events. 1067f263522aSJoseph Koshy */ 1068f263522aSJoseph Koshy 1069f263522aSJoseph Koshy static struct pmc_event_alias k8_aliases[] = { 1070f263522aSJoseph Koshy EV_ALIAS("branches", "k8-fr-retired-taken-branches"), 1071f263522aSJoseph Koshy EV_ALIAS("branch-mispredicts", 1072f263522aSJoseph Koshy "k8-fr-retired-taken-branches-mispredicted"), 1073f263522aSJoseph Koshy EV_ALIAS("cycles", "tsc"), 1074f263522aSJoseph Koshy EV_ALIAS("dc-misses", "k8-dc-miss"), 1075f263522aSJoseph Koshy EV_ALIAS("ic-misses", "k8-ic-miss"), 1076f263522aSJoseph Koshy EV_ALIAS("instructions", "k8-fr-retired-x86-instructions"), 1077f263522aSJoseph Koshy EV_ALIAS("interrupts", "k8-fr-taken-hardware-interrupts"), 1078177a2f22SJoseph Koshy EV_ALIAS("unhalted-cycles", "k8-bu-cpu-clk-unhalted"), 1079f263522aSJoseph Koshy EV_ALIAS(NULL, NULL) 1080f263522aSJoseph Koshy }; 1081f263522aSJoseph Koshy 1082f263522aSJoseph Koshy #define __K8MASK(N,V) PMCMASK(N,(1 << (V))) 1083f263522aSJoseph Koshy 1084f263522aSJoseph Koshy /* 1085f263522aSJoseph Koshy * Parsing tables 1086f263522aSJoseph Koshy */ 1087f263522aSJoseph Koshy 1088f263522aSJoseph Koshy /* fp dispatched fpu ops */ 1089f263522aSJoseph Koshy static const struct pmc_masks k8_mask_fdfo[] = { 1090f263522aSJoseph Koshy __K8MASK(add-pipe-excluding-junk-ops, 0), 1091f263522aSJoseph Koshy __K8MASK(multiply-pipe-excluding-junk-ops, 1), 1092f263522aSJoseph Koshy __K8MASK(store-pipe-excluding-junk-ops, 2), 1093f263522aSJoseph Koshy __K8MASK(add-pipe-junk-ops, 3), 1094f263522aSJoseph Koshy __K8MASK(multiply-pipe-junk-ops, 4), 1095f263522aSJoseph Koshy __K8MASK(store-pipe-junk-ops, 5), 1096f263522aSJoseph Koshy NULLMASK 1097f263522aSJoseph Koshy }; 1098f263522aSJoseph Koshy 1099f263522aSJoseph Koshy /* ls segment register loads */ 1100f263522aSJoseph Koshy static const struct pmc_masks k8_mask_lsrl[] = { 1101f263522aSJoseph Koshy __K8MASK(es, 0), 1102f263522aSJoseph Koshy __K8MASK(cs, 1), 1103f263522aSJoseph Koshy __K8MASK(ss, 2), 1104f263522aSJoseph Koshy __K8MASK(ds, 3), 1105f263522aSJoseph Koshy __K8MASK(fs, 4), 1106f263522aSJoseph Koshy __K8MASK(gs, 5), 1107f263522aSJoseph Koshy __K8MASK(hs, 6), 1108f263522aSJoseph Koshy NULLMASK 1109f263522aSJoseph Koshy }; 1110f263522aSJoseph Koshy 1111f263522aSJoseph Koshy /* ls locked operation */ 1112f263522aSJoseph Koshy static const struct pmc_masks k8_mask_llo[] = { 1113f263522aSJoseph Koshy __K8MASK(locked-instructions, 0), 1114f263522aSJoseph Koshy __K8MASK(cycles-in-request, 1), 1115f263522aSJoseph Koshy __K8MASK(cycles-to-complete, 2), 1116f263522aSJoseph Koshy NULLMASK 1117f263522aSJoseph Koshy }; 1118f263522aSJoseph Koshy 1119f263522aSJoseph Koshy /* dc refill from {l2,system} and dc copyback */ 1120f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dc[] = { 1121f263522aSJoseph Koshy __K8MASK(invalid, 0), 1122f263522aSJoseph Koshy __K8MASK(shared, 1), 1123f263522aSJoseph Koshy __K8MASK(exclusive, 2), 1124f263522aSJoseph Koshy __K8MASK(owner, 3), 1125f263522aSJoseph Koshy __K8MASK(modified, 4), 1126f263522aSJoseph Koshy NULLMASK 1127f263522aSJoseph Koshy }; 1128f263522aSJoseph Koshy 1129f263522aSJoseph Koshy /* dc one bit ecc error */ 1130f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dobee[] = { 1131f263522aSJoseph Koshy __K8MASK(scrubber, 0), 1132f263522aSJoseph Koshy __K8MASK(piggyback, 1), 1133f263522aSJoseph Koshy NULLMASK 1134f263522aSJoseph Koshy }; 1135f263522aSJoseph Koshy 1136f263522aSJoseph Koshy /* dc dispatched prefetch instructions */ 1137f263522aSJoseph Koshy static const struct pmc_masks k8_mask_ddpi[] = { 1138f263522aSJoseph Koshy __K8MASK(load, 0), 1139f263522aSJoseph Koshy __K8MASK(store, 1), 1140f263522aSJoseph Koshy __K8MASK(nta, 2), 1141f263522aSJoseph Koshy NULLMASK 1142f263522aSJoseph Koshy }; 1143f263522aSJoseph Koshy 1144f263522aSJoseph Koshy /* dc dcache accesses by locks */ 1145f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dabl[] = { 1146f263522aSJoseph Koshy __K8MASK(accesses, 0), 1147f263522aSJoseph Koshy __K8MASK(misses, 1), 1148f263522aSJoseph Koshy NULLMASK 1149f263522aSJoseph Koshy }; 1150f263522aSJoseph Koshy 1151f263522aSJoseph Koshy /* bu internal l2 request */ 1152f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bilr[] = { 1153f263522aSJoseph Koshy __K8MASK(ic-fill, 0), 1154f263522aSJoseph Koshy __K8MASK(dc-fill, 1), 1155f263522aSJoseph Koshy __K8MASK(tlb-reload, 2), 1156f263522aSJoseph Koshy __K8MASK(tag-snoop, 3), 1157f263522aSJoseph Koshy __K8MASK(cancelled, 4), 1158f263522aSJoseph Koshy NULLMASK 1159f263522aSJoseph Koshy }; 1160f263522aSJoseph Koshy 1161f263522aSJoseph Koshy /* bu fill request l2 miss */ 1162f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bfrlm[] = { 1163f263522aSJoseph Koshy __K8MASK(ic-fill, 0), 1164f263522aSJoseph Koshy __K8MASK(dc-fill, 1), 1165f263522aSJoseph Koshy __K8MASK(tlb-reload, 2), 1166f263522aSJoseph Koshy NULLMASK 1167f263522aSJoseph Koshy }; 1168f263522aSJoseph Koshy 1169f263522aSJoseph Koshy /* bu fill into l2 */ 1170f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bfil[] = { 1171f263522aSJoseph Koshy __K8MASK(dirty-l2-victim, 0), 1172f263522aSJoseph Koshy __K8MASK(victim-from-l2, 1), 1173f263522aSJoseph Koshy NULLMASK 1174f263522aSJoseph Koshy }; 1175f263522aSJoseph Koshy 1176f263522aSJoseph Koshy /* fr retired fpu instructions */ 1177f263522aSJoseph Koshy static const struct pmc_masks k8_mask_frfi[] = { 1178f263522aSJoseph Koshy __K8MASK(x87, 0), 1179f263522aSJoseph Koshy __K8MASK(mmx-3dnow, 1), 1180f263522aSJoseph Koshy __K8MASK(packed-sse-sse2, 2), 1181f263522aSJoseph Koshy __K8MASK(scalar-sse-sse2, 3), 1182f263522aSJoseph Koshy NULLMASK 1183f263522aSJoseph Koshy }; 1184f263522aSJoseph Koshy 1185f263522aSJoseph Koshy /* fr retired fastpath double op instructions */ 1186f263522aSJoseph Koshy static const struct pmc_masks k8_mask_frfdoi[] = { 1187f263522aSJoseph Koshy __K8MASK(low-op-pos-0, 0), 1188f263522aSJoseph Koshy __K8MASK(low-op-pos-1, 1), 1189f263522aSJoseph Koshy __K8MASK(low-op-pos-2, 2), 1190f263522aSJoseph Koshy NULLMASK 1191f263522aSJoseph Koshy }; 1192f263522aSJoseph Koshy 1193f263522aSJoseph Koshy /* fr fpu exceptions */ 1194f263522aSJoseph Koshy static const struct pmc_masks k8_mask_ffe[] = { 1195f263522aSJoseph Koshy __K8MASK(x87-reclass-microfaults, 0), 1196f263522aSJoseph Koshy __K8MASK(sse-retype-microfaults, 1), 1197f263522aSJoseph Koshy __K8MASK(sse-reclass-microfaults, 2), 1198f263522aSJoseph Koshy __K8MASK(sse-and-x87-microtraps, 3), 1199f263522aSJoseph Koshy NULLMASK 1200f263522aSJoseph Koshy }; 1201f263522aSJoseph Koshy 1202f263522aSJoseph Koshy /* nb memory controller page access event */ 1203f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmcpae[] = { 1204f263522aSJoseph Koshy __K8MASK(page-hit, 0), 1205f263522aSJoseph Koshy __K8MASK(page-miss, 1), 1206f263522aSJoseph Koshy __K8MASK(page-conflict, 2), 1207f263522aSJoseph Koshy NULLMASK 1208f263522aSJoseph Koshy }; 1209f263522aSJoseph Koshy 1210f263522aSJoseph Koshy /* nb memory controller turnaround */ 1211f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmct[] = { 1212f263522aSJoseph Koshy __K8MASK(dimm-turnaround, 0), 1213f263522aSJoseph Koshy __K8MASK(read-to-write-turnaround, 1), 1214f263522aSJoseph Koshy __K8MASK(write-to-read-turnaround, 2), 1215f263522aSJoseph Koshy NULLMASK 1216f263522aSJoseph Koshy }; 1217f263522aSJoseph Koshy 1218f263522aSJoseph Koshy /* nb memory controller bypass saturation */ 1219f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmcbs[] = { 1220f263522aSJoseph Koshy __K8MASK(memory-controller-hi-pri-bypass, 0), 1221f263522aSJoseph Koshy __K8MASK(memory-controller-lo-pri-bypass, 1), 1222f263522aSJoseph Koshy __K8MASK(dram-controller-interface-bypass, 2), 1223f263522aSJoseph Koshy __K8MASK(dram-controller-queue-bypass, 3), 1224f263522aSJoseph Koshy NULLMASK 1225f263522aSJoseph Koshy }; 1226f263522aSJoseph Koshy 1227f263522aSJoseph Koshy /* nb sized commands */ 1228f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nsc[] = { 1229f263522aSJoseph Koshy __K8MASK(nonpostwrszbyte, 0), 1230f263522aSJoseph Koshy __K8MASK(nonpostwrszdword, 1), 1231f263522aSJoseph Koshy __K8MASK(postwrszbyte, 2), 1232f263522aSJoseph Koshy __K8MASK(postwrszdword, 3), 1233f263522aSJoseph Koshy __K8MASK(rdszbyte, 4), 1234f263522aSJoseph Koshy __K8MASK(rdszdword, 5), 1235f263522aSJoseph Koshy __K8MASK(rdmodwr, 6), 1236f263522aSJoseph Koshy NULLMASK 1237f263522aSJoseph Koshy }; 1238f263522aSJoseph Koshy 1239f263522aSJoseph Koshy /* nb probe result */ 1240f263522aSJoseph Koshy static const struct pmc_masks k8_mask_npr[] = { 1241f263522aSJoseph Koshy __K8MASK(probe-miss, 0), 1242f263522aSJoseph Koshy __K8MASK(probe-hit, 1), 1243f263522aSJoseph Koshy __K8MASK(probe-hit-dirty-no-memory-cancel, 2), 1244f263522aSJoseph Koshy __K8MASK(probe-hit-dirty-with-memory-cancel, 3), 1245f263522aSJoseph Koshy NULLMASK 1246f263522aSJoseph Koshy }; 1247f263522aSJoseph Koshy 1248f263522aSJoseph Koshy /* nb hypertransport bus bandwidth */ 1249f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nhbb[] = { /* HT bus bandwidth */ 1250f263522aSJoseph Koshy __K8MASK(command, 0), 1251f263522aSJoseph Koshy __K8MASK(data, 1), 1252f263522aSJoseph Koshy __K8MASK(buffer-release, 2), 1253f263522aSJoseph Koshy __K8MASK(nop, 3), 1254f263522aSJoseph Koshy NULLMASK 1255f263522aSJoseph Koshy }; 1256f263522aSJoseph Koshy 1257f263522aSJoseph Koshy #undef __K8MASK 1258f263522aSJoseph Koshy 1259f263522aSJoseph Koshy #define K8_KW_COUNT "count" 1260f263522aSJoseph Koshy #define K8_KW_EDGE "edge" 1261f263522aSJoseph Koshy #define K8_KW_INV "inv" 1262f263522aSJoseph Koshy #define K8_KW_MASK "mask" 1263f263522aSJoseph Koshy #define K8_KW_OS "os" 1264f263522aSJoseph Koshy #define K8_KW_USR "usr" 1265f263522aSJoseph Koshy 1266f263522aSJoseph Koshy static int 1267f263522aSJoseph Koshy k8_allocate_pmc(enum pmc_event pe, char *ctrspec, 1268f263522aSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 1269f263522aSJoseph Koshy { 1270f263522aSJoseph Koshy char *e, *p, *q; 1271f263522aSJoseph Koshy int n; 12721e862e5aSFabien Thomas uint32_t count; 12731e862e5aSFabien Thomas uint64_t evmask; 1274f263522aSJoseph Koshy const struct pmc_masks *pm, *pmask; 1275f263522aSJoseph Koshy 1276789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1277f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 1278f263522aSJoseph Koshy 1279f263522aSJoseph Koshy pmask = NULL; 1280f263522aSJoseph Koshy evmask = 0; 1281f263522aSJoseph Koshy 1282f263522aSJoseph Koshy #define __K8SETMASK(M) pmask = k8_mask_##M 1283f263522aSJoseph Koshy 1284f263522aSJoseph Koshy /* setup parsing tables */ 1285f263522aSJoseph Koshy switch (pe) { 1286f263522aSJoseph Koshy case PMC_EV_K8_FP_DISPATCHED_FPU_OPS: 1287f263522aSJoseph Koshy __K8SETMASK(fdfo); 1288f263522aSJoseph Koshy break; 1289f263522aSJoseph Koshy case PMC_EV_K8_LS_SEGMENT_REGISTER_LOAD: 1290f263522aSJoseph Koshy __K8SETMASK(lsrl); 1291f263522aSJoseph Koshy break; 1292f263522aSJoseph Koshy case PMC_EV_K8_LS_LOCKED_OPERATION: 1293f263522aSJoseph Koshy __K8SETMASK(llo); 1294f263522aSJoseph Koshy break; 1295f263522aSJoseph Koshy case PMC_EV_K8_DC_REFILL_FROM_L2: 1296f263522aSJoseph Koshy case PMC_EV_K8_DC_REFILL_FROM_SYSTEM: 1297f263522aSJoseph Koshy case PMC_EV_K8_DC_COPYBACK: 1298f263522aSJoseph Koshy __K8SETMASK(dc); 1299f263522aSJoseph Koshy break; 1300f263522aSJoseph Koshy case PMC_EV_K8_DC_ONE_BIT_ECC_ERROR: 1301f263522aSJoseph Koshy __K8SETMASK(dobee); 1302f263522aSJoseph Koshy break; 1303f263522aSJoseph Koshy case PMC_EV_K8_DC_DISPATCHED_PREFETCH_INSTRUCTIONS: 1304f263522aSJoseph Koshy __K8SETMASK(ddpi); 1305f263522aSJoseph Koshy break; 1306f263522aSJoseph Koshy case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS: 1307f263522aSJoseph Koshy __K8SETMASK(dabl); 1308f263522aSJoseph Koshy break; 1309f263522aSJoseph Koshy case PMC_EV_K8_BU_INTERNAL_L2_REQUEST: 1310f263522aSJoseph Koshy __K8SETMASK(bilr); 1311f263522aSJoseph Koshy break; 1312f263522aSJoseph Koshy case PMC_EV_K8_BU_FILL_REQUEST_L2_MISS: 1313f263522aSJoseph Koshy __K8SETMASK(bfrlm); 1314f263522aSJoseph Koshy break; 1315f263522aSJoseph Koshy case PMC_EV_K8_BU_FILL_INTO_L2: 1316f263522aSJoseph Koshy __K8SETMASK(bfil); 1317f263522aSJoseph Koshy break; 1318f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS: 1319f263522aSJoseph Koshy __K8SETMASK(frfi); 1320f263522aSJoseph Koshy break; 1321f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS: 1322f263522aSJoseph Koshy __K8SETMASK(frfdoi); 1323f263522aSJoseph Koshy break; 1324f263522aSJoseph Koshy case PMC_EV_K8_FR_FPU_EXCEPTIONS: 1325f263522aSJoseph Koshy __K8SETMASK(ffe); 1326f263522aSJoseph Koshy break; 1327f263522aSJoseph Koshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_PAGE_ACCESS_EVENT: 1328f263522aSJoseph Koshy __K8SETMASK(nmcpae); 1329f263522aSJoseph Koshy break; 1330f263522aSJoseph Koshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_TURNAROUND: 1331f263522aSJoseph Koshy __K8SETMASK(nmct); 1332f263522aSJoseph Koshy break; 1333f263522aSJoseph Koshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_BYPASS_SATURATION: 1334f263522aSJoseph Koshy __K8SETMASK(nmcbs); 1335f263522aSJoseph Koshy break; 1336f263522aSJoseph Koshy case PMC_EV_K8_NB_SIZED_COMMANDS: 1337f263522aSJoseph Koshy __K8SETMASK(nsc); 1338f263522aSJoseph Koshy break; 1339f263522aSJoseph Koshy case PMC_EV_K8_NB_PROBE_RESULT: 1340f263522aSJoseph Koshy __K8SETMASK(npr); 1341f263522aSJoseph Koshy break; 1342f263522aSJoseph Koshy case PMC_EV_K8_NB_HT_BUS0_BANDWIDTH: 1343f263522aSJoseph Koshy case PMC_EV_K8_NB_HT_BUS1_BANDWIDTH: 1344f263522aSJoseph Koshy case PMC_EV_K8_NB_HT_BUS2_BANDWIDTH: 1345f263522aSJoseph Koshy __K8SETMASK(nhbb); 1346f263522aSJoseph Koshy break; 1347f263522aSJoseph Koshy 1348f263522aSJoseph Koshy default: 1349f263522aSJoseph Koshy break; /* no options defined */ 1350f263522aSJoseph Koshy } 1351f263522aSJoseph Koshy 1352f263522aSJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 1353f263522aSJoseph Koshy if (KWPREFIXMATCH(p, K8_KW_COUNT "=")) { 1354f263522aSJoseph Koshy q = strchr(p, '='); 1355f263522aSJoseph Koshy if (*++q == '\0') /* skip '=' */ 1356aa342b1fSJoseph Koshy return (-1); 1357f263522aSJoseph Koshy 1358f263522aSJoseph Koshy count = strtol(q, &e, 0); 1359f263522aSJoseph Koshy if (e == q || *e != '\0') 1360aa342b1fSJoseph Koshy return (-1); 1361f263522aSJoseph Koshy 1362f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 1363f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config |= 1364f263522aSJoseph Koshy AMD_PMC_TO_COUNTER(count); 1365f263522aSJoseph Koshy 1366f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_EDGE)) { 1367f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1368f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_INV)) { 1369f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 1370f263522aSJoseph Koshy } else if (KWPREFIXMATCH(p, K8_KW_MASK "=")) { 1371f263522aSJoseph Koshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 1372aa342b1fSJoseph Koshy return (-1); 1373f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1374f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_OS)) { 1375f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 1376f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_USR)) { 1377f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 1378f263522aSJoseph Koshy } else 1379aa342b1fSJoseph Koshy return (-1); 1380f263522aSJoseph Koshy } 1381f263522aSJoseph Koshy 1382f263522aSJoseph Koshy /* other post processing */ 1383f263522aSJoseph Koshy switch (pe) { 1384f263522aSJoseph Koshy case PMC_EV_K8_FP_DISPATCHED_FPU_OPS: 1385f263522aSJoseph Koshy case PMC_EV_K8_FP_CYCLES_WITH_NO_FPU_OPS_RETIRED: 1386f263522aSJoseph Koshy case PMC_EV_K8_FP_DISPATCHED_FPU_FAST_FLAG_OPS: 1387f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS: 1388f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS: 1389f263522aSJoseph Koshy case PMC_EV_K8_FR_FPU_EXCEPTIONS: 1390f263522aSJoseph Koshy /* XXX only available in rev B and later */ 1391f263522aSJoseph Koshy break; 1392f263522aSJoseph Koshy case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS: 1393f263522aSJoseph Koshy /* XXX only available in rev C and later */ 1394f263522aSJoseph Koshy break; 1395f263522aSJoseph Koshy case PMC_EV_K8_LS_LOCKED_OPERATION: 1396f263522aSJoseph Koshy /* XXX CPU Rev A,B evmask is to be zero */ 1397f263522aSJoseph Koshy if (evmask & (evmask - 1)) /* > 1 bit set */ 1398aa342b1fSJoseph Koshy return (-1); 1399f263522aSJoseph Koshy if (evmask == 0) { 1400f263522aSJoseph Koshy evmask = 0x01; /* Rev C and later: #instrs */ 1401f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1402f263522aSJoseph Koshy } 1403f263522aSJoseph Koshy break; 1404f263522aSJoseph Koshy default: 1405f263522aSJoseph Koshy if (evmask == 0 && pmask != NULL) { 1406f263522aSJoseph Koshy for (pm = pmask; pm->pm_name; pm++) 1407f263522aSJoseph Koshy evmask |= pm->pm_value; 1408f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1409f263522aSJoseph Koshy } 1410f263522aSJoseph Koshy } 1411f263522aSJoseph Koshy 1412f263522aSJoseph Koshy if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) 1413f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 1414f263522aSJoseph Koshy AMD_PMC_TO_UNITMASK(evmask); 1415f263522aSJoseph Koshy 1416aa342b1fSJoseph Koshy return (0); 1417f263522aSJoseph Koshy } 1418f263522aSJoseph Koshy 1419f263522aSJoseph Koshy #endif 1420f263522aSJoseph Koshy 142186a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 1422f263522aSJoseph Koshy 1423ebccf1e3SJoseph Koshy /* 1424ebccf1e3SJoseph Koshy * Intel P4 PMCs 1425ebccf1e3SJoseph Koshy */ 1426ebccf1e3SJoseph Koshy 1427ebccf1e3SJoseph Koshy static struct pmc_event_alias p4_aliases[] = { 1428d56c5d4bSJoseph Koshy EV_ALIAS("branches", "p4-branch-retired,mask=mmtp+mmtm"), 1429d56c5d4bSJoseph Koshy EV_ALIAS("branch-mispredicts", "p4-mispred-branch-retired"), 1430ebccf1e3SJoseph Koshy EV_ALIAS("cycles", "tsc"), 1431d56c5d4bSJoseph Koshy EV_ALIAS("instructions", 1432d56c5d4bSJoseph Koshy "p4-instr-retired,mask=nbogusntag+nbogustag"), 1433177a2f22SJoseph Koshy EV_ALIAS("unhalted-cycles", "p4-global-power-events"), 1434ebccf1e3SJoseph Koshy EV_ALIAS(NULL, NULL) 1435ebccf1e3SJoseph Koshy }; 1436ebccf1e3SJoseph Koshy 1437ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE "active" 1438ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_ANY "any" 1439ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_BOTH "both" 1440ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_NONE "none" 1441ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_SINGLE "single" 1442ebccf1e3SJoseph Koshy #define P4_KW_BUSREQTYPE "busreqtype" 1443ebccf1e3SJoseph Koshy #define P4_KW_CASCADE "cascade" 1444ebccf1e3SJoseph Koshy #define P4_KW_EDGE "edge" 1445ebccf1e3SJoseph Koshy #define P4_KW_INV "complement" 1446ebccf1e3SJoseph Koshy #define P4_KW_OS "os" 1447ebccf1e3SJoseph Koshy #define P4_KW_MASK "mask" 1448ebccf1e3SJoseph Koshy #define P4_KW_PRECISE "precise" 1449ebccf1e3SJoseph Koshy #define P4_KW_TAG "tag" 1450ebccf1e3SJoseph Koshy #define P4_KW_THRESHOLD "threshold" 1451ebccf1e3SJoseph Koshy #define P4_KW_USR "usr" 1452ebccf1e3SJoseph Koshy 1453ebccf1e3SJoseph Koshy #define __P4MASK(N,V) PMCMASK(N, (1 << (V))) 1454ebccf1e3SJoseph Koshy 1455ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_tcdm[] = { /* tc deliver mode */ 1456ebccf1e3SJoseph Koshy __P4MASK(dd, 0), 1457ebccf1e3SJoseph Koshy __P4MASK(db, 1), 1458ebccf1e3SJoseph Koshy __P4MASK(di, 2), 1459ebccf1e3SJoseph Koshy __P4MASK(bd, 3), 1460ebccf1e3SJoseph Koshy __P4MASK(bb, 4), 1461ebccf1e3SJoseph Koshy __P4MASK(bi, 5), 1462ebccf1e3SJoseph Koshy __P4MASK(id, 6), 1463ebccf1e3SJoseph Koshy __P4MASK(ib, 7), 1464ebccf1e3SJoseph Koshy NULLMASK 1465ebccf1e3SJoseph Koshy }; 1466ebccf1e3SJoseph Koshy 1467ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_bfr[] = { /* bpu fetch request */ 1468ebccf1e3SJoseph Koshy __P4MASK(tcmiss, 0), 1469ebccf1e3SJoseph Koshy NULLMASK, 1470ebccf1e3SJoseph Koshy }; 1471ebccf1e3SJoseph Koshy 1472ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ir[] = { /* itlb reference */ 1473ebccf1e3SJoseph Koshy __P4MASK(hit, 0), 1474ebccf1e3SJoseph Koshy __P4MASK(miss, 1), 1475ebccf1e3SJoseph Koshy __P4MASK(hit-uc, 2), 1476ebccf1e3SJoseph Koshy NULLMASK 1477ebccf1e3SJoseph Koshy }; 1478ebccf1e3SJoseph Koshy 1479ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_memcan[] = { /* memory cancel */ 1480ebccf1e3SJoseph Koshy __P4MASK(st-rb-full, 2), 1481ebccf1e3SJoseph Koshy __P4MASK(64k-conf, 3), 1482ebccf1e3SJoseph Koshy NULLMASK 1483ebccf1e3SJoseph Koshy }; 1484ebccf1e3SJoseph Koshy 1485ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_memcomp[] = { /* memory complete */ 1486ebccf1e3SJoseph Koshy __P4MASK(lsc, 0), 1487ebccf1e3SJoseph Koshy __P4MASK(ssc, 1), 1488ebccf1e3SJoseph Koshy NULLMASK 1489ebccf1e3SJoseph Koshy }; 1490ebccf1e3SJoseph Koshy 1491ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_lpr[] = { /* load port replay */ 1492ebccf1e3SJoseph Koshy __P4MASK(split-ld, 1), 1493ebccf1e3SJoseph Koshy NULLMASK 1494ebccf1e3SJoseph Koshy }; 1495ebccf1e3SJoseph Koshy 1496ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_spr[] = { /* store port replay */ 1497ebccf1e3SJoseph Koshy __P4MASK(split-st, 1), 1498ebccf1e3SJoseph Koshy NULLMASK 1499ebccf1e3SJoseph Koshy }; 1500ebccf1e3SJoseph Koshy 1501ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_mlr[] = { /* mob load replay */ 1502ebccf1e3SJoseph Koshy __P4MASK(no-sta, 1), 1503ebccf1e3SJoseph Koshy __P4MASK(no-std, 3), 1504ebccf1e3SJoseph Koshy __P4MASK(partial-data, 4), 1505ebccf1e3SJoseph Koshy __P4MASK(unalgn-addr, 5), 1506ebccf1e3SJoseph Koshy NULLMASK 1507ebccf1e3SJoseph Koshy }; 1508ebccf1e3SJoseph Koshy 1509ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_pwt[] = { /* page walk type */ 1510ebccf1e3SJoseph Koshy __P4MASK(dtmiss, 0), 1511ebccf1e3SJoseph Koshy __P4MASK(itmiss, 1), 1512ebccf1e3SJoseph Koshy NULLMASK 1513ebccf1e3SJoseph Koshy }; 1514ebccf1e3SJoseph Koshy 1515ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_bcr[] = { /* bsq cache reference */ 1516ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-hits, 0), 1517ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-hite, 1), 1518ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-hitm, 2), 1519ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-hits, 3), 1520ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-hite, 4), 1521ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-hitm, 5), 1522ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-miss, 8), 1523ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-miss, 9), 1524ebccf1e3SJoseph Koshy __P4MASK(wr-2ndl-miss, 10), 1525ebccf1e3SJoseph Koshy NULLMASK 1526ebccf1e3SJoseph Koshy }; 1527ebccf1e3SJoseph Koshy 1528ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ia[] = { /* ioq allocation */ 1529ebccf1e3SJoseph Koshy __P4MASK(all-read, 5), 1530ebccf1e3SJoseph Koshy __P4MASK(all-write, 6), 1531ebccf1e3SJoseph Koshy __P4MASK(mem-uc, 7), 1532ebccf1e3SJoseph Koshy __P4MASK(mem-wc, 8), 1533ebccf1e3SJoseph Koshy __P4MASK(mem-wt, 9), 1534ebccf1e3SJoseph Koshy __P4MASK(mem-wp, 10), 1535ebccf1e3SJoseph Koshy __P4MASK(mem-wb, 11), 1536ebccf1e3SJoseph Koshy __P4MASK(own, 13), 1537ebccf1e3SJoseph Koshy __P4MASK(other, 14), 1538ebccf1e3SJoseph Koshy __P4MASK(prefetch, 15), 1539ebccf1e3SJoseph Koshy NULLMASK 1540ebccf1e3SJoseph Koshy }; 1541ebccf1e3SJoseph Koshy 1542ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_iae[] = { /* ioq active entries */ 1543ebccf1e3SJoseph Koshy __P4MASK(all-read, 5), 1544ebccf1e3SJoseph Koshy __P4MASK(all-write, 6), 1545ebccf1e3SJoseph Koshy __P4MASK(mem-uc, 7), 1546ebccf1e3SJoseph Koshy __P4MASK(mem-wc, 8), 1547ebccf1e3SJoseph Koshy __P4MASK(mem-wt, 9), 1548ebccf1e3SJoseph Koshy __P4MASK(mem-wp, 10), 1549ebccf1e3SJoseph Koshy __P4MASK(mem-wb, 11), 1550ebccf1e3SJoseph Koshy __P4MASK(own, 13), 1551ebccf1e3SJoseph Koshy __P4MASK(other, 14), 1552ebccf1e3SJoseph Koshy __P4MASK(prefetch, 15), 1553ebccf1e3SJoseph Koshy NULLMASK 1554ebccf1e3SJoseph Koshy }; 1555ebccf1e3SJoseph Koshy 1556ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_fda[] = { /* fsb data activity */ 1557ebccf1e3SJoseph Koshy __P4MASK(drdy-drv, 0), 1558ebccf1e3SJoseph Koshy __P4MASK(drdy-own, 1), 1559ebccf1e3SJoseph Koshy __P4MASK(drdy-other, 2), 1560ebccf1e3SJoseph Koshy __P4MASK(dbsy-drv, 3), 1561ebccf1e3SJoseph Koshy __P4MASK(dbsy-own, 4), 1562ebccf1e3SJoseph Koshy __P4MASK(dbsy-other, 5), 1563ebccf1e3SJoseph Koshy NULLMASK 1564ebccf1e3SJoseph Koshy }; 1565ebccf1e3SJoseph Koshy 1566ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ba[] = { /* bsq allocation */ 1567ebccf1e3SJoseph Koshy __P4MASK(req-type0, 0), 1568ebccf1e3SJoseph Koshy __P4MASK(req-type1, 1), 1569ebccf1e3SJoseph Koshy __P4MASK(req-len0, 2), 1570ebccf1e3SJoseph Koshy __P4MASK(req-len1, 3), 1571ebccf1e3SJoseph Koshy __P4MASK(req-io-type, 5), 1572ebccf1e3SJoseph Koshy __P4MASK(req-lock-type, 6), 1573ebccf1e3SJoseph Koshy __P4MASK(req-cache-type, 7), 1574ebccf1e3SJoseph Koshy __P4MASK(req-split-type, 8), 1575ebccf1e3SJoseph Koshy __P4MASK(req-dem-type, 9), 1576ebccf1e3SJoseph Koshy __P4MASK(req-ord-type, 10), 1577ebccf1e3SJoseph Koshy __P4MASK(mem-type0, 11), 1578ebccf1e3SJoseph Koshy __P4MASK(mem-type1, 12), 1579ebccf1e3SJoseph Koshy __P4MASK(mem-type2, 13), 1580ebccf1e3SJoseph Koshy NULLMASK 1581ebccf1e3SJoseph Koshy }; 1582ebccf1e3SJoseph Koshy 1583ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_sia[] = { /* sse input assist */ 1584ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1585ebccf1e3SJoseph Koshy NULLMASK 1586ebccf1e3SJoseph Koshy }; 1587ebccf1e3SJoseph Koshy 1588ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_psu[] = { /* packed sp uop */ 1589ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1590ebccf1e3SJoseph Koshy NULLMASK 1591ebccf1e3SJoseph Koshy }; 1592ebccf1e3SJoseph Koshy 1593ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_pdu[] = { /* packed dp uop */ 1594ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1595ebccf1e3SJoseph Koshy NULLMASK 1596ebccf1e3SJoseph Koshy }; 1597ebccf1e3SJoseph Koshy 1598ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ssu[] = { /* scalar sp uop */ 1599ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1600ebccf1e3SJoseph Koshy NULLMASK 1601ebccf1e3SJoseph Koshy }; 1602ebccf1e3SJoseph Koshy 1603ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_sdu[] = { /* scalar dp uop */ 1604ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1605ebccf1e3SJoseph Koshy NULLMASK 1606ebccf1e3SJoseph Koshy }; 1607ebccf1e3SJoseph Koshy 1608ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_64bmu[] = { /* 64 bit mmx uop */ 1609ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1610ebccf1e3SJoseph Koshy NULLMASK 1611ebccf1e3SJoseph Koshy }; 1612ebccf1e3SJoseph Koshy 1613ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_128bmu[] = { /* 128 bit mmx uop */ 1614ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1615ebccf1e3SJoseph Koshy NULLMASK 1616ebccf1e3SJoseph Koshy }; 1617ebccf1e3SJoseph Koshy 1618ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xfu[] = { /* X87 fp uop */ 1619ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1620ebccf1e3SJoseph Koshy NULLMASK 1621ebccf1e3SJoseph Koshy }; 1622ebccf1e3SJoseph Koshy 1623ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xsmu[] = { /* x87 simd moves uop */ 1624ebccf1e3SJoseph Koshy __P4MASK(allp0, 3), 1625ebccf1e3SJoseph Koshy __P4MASK(allp2, 4), 1626ebccf1e3SJoseph Koshy NULLMASK 1627ebccf1e3SJoseph Koshy }; 1628ebccf1e3SJoseph Koshy 1629ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_gpe[] = { /* global power events */ 1630ebccf1e3SJoseph Koshy __P4MASK(running, 0), 1631ebccf1e3SJoseph Koshy NULLMASK 1632ebccf1e3SJoseph Koshy }; 1633ebccf1e3SJoseph Koshy 1634ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_tmx[] = { /* TC ms xfer */ 1635ebccf1e3SJoseph Koshy __P4MASK(cisc, 0), 1636ebccf1e3SJoseph Koshy NULLMASK 1637ebccf1e3SJoseph Koshy }; 1638ebccf1e3SJoseph Koshy 1639ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_uqw[] = { /* uop queue writes */ 1640ebccf1e3SJoseph Koshy __P4MASK(from-tc-build, 0), 1641ebccf1e3SJoseph Koshy __P4MASK(from-tc-deliver, 1), 1642ebccf1e3SJoseph Koshy __P4MASK(from-rom, 2), 1643ebccf1e3SJoseph Koshy NULLMASK 1644ebccf1e3SJoseph Koshy }; 1645ebccf1e3SJoseph Koshy 1646d56c5d4bSJoseph Koshy static const struct pmc_masks p4_mask_rmbt[] = { 1647d56c5d4bSJoseph Koshy /* retired mispred branch type */ 1648ebccf1e3SJoseph Koshy __P4MASK(conditional, 1), 1649ebccf1e3SJoseph Koshy __P4MASK(call, 2), 1650ebccf1e3SJoseph Koshy __P4MASK(return, 3), 1651ebccf1e3SJoseph Koshy __P4MASK(indirect, 4), 1652ebccf1e3SJoseph Koshy NULLMASK 1653ebccf1e3SJoseph Koshy }; 1654ebccf1e3SJoseph Koshy 1655ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_rbt[] = { /* retired branch type */ 1656ebccf1e3SJoseph Koshy __P4MASK(conditional, 1), 1657ebccf1e3SJoseph Koshy __P4MASK(call, 2), 1658ebccf1e3SJoseph Koshy __P4MASK(retired, 3), 1659ebccf1e3SJoseph Koshy __P4MASK(indirect, 4), 1660ebccf1e3SJoseph Koshy NULLMASK 1661ebccf1e3SJoseph Koshy }; 1662ebccf1e3SJoseph Koshy 1663ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_rs[] = { /* resource stall */ 1664ebccf1e3SJoseph Koshy __P4MASK(sbfull, 5), 1665ebccf1e3SJoseph Koshy NULLMASK 1666ebccf1e3SJoseph Koshy }; 1667ebccf1e3SJoseph Koshy 1668ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_wb[] = { /* WC buffer */ 1669ebccf1e3SJoseph Koshy __P4MASK(wcb-evicts, 0), 1670ebccf1e3SJoseph Koshy __P4MASK(wcb-full-evict, 1), 1671ebccf1e3SJoseph Koshy NULLMASK 1672ebccf1e3SJoseph Koshy }; 1673ebccf1e3SJoseph Koshy 1674ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_fee[] = { /* front end event */ 1675ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1676ebccf1e3SJoseph Koshy __P4MASK(bogus, 1), 1677ebccf1e3SJoseph Koshy NULLMASK 1678ebccf1e3SJoseph Koshy }; 1679ebccf1e3SJoseph Koshy 1680ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ee[] = { /* execution event */ 1681ebccf1e3SJoseph Koshy __P4MASK(nbogus0, 0), 1682ebccf1e3SJoseph Koshy __P4MASK(nbogus1, 1), 1683ebccf1e3SJoseph Koshy __P4MASK(nbogus2, 2), 1684ebccf1e3SJoseph Koshy __P4MASK(nbogus3, 3), 1685ebccf1e3SJoseph Koshy __P4MASK(bogus0, 4), 1686ebccf1e3SJoseph Koshy __P4MASK(bogus1, 5), 1687ebccf1e3SJoseph Koshy __P4MASK(bogus2, 6), 1688ebccf1e3SJoseph Koshy __P4MASK(bogus3, 7), 1689ebccf1e3SJoseph Koshy NULLMASK 1690ebccf1e3SJoseph Koshy }; 1691ebccf1e3SJoseph Koshy 1692ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_re[] = { /* replay event */ 1693ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1694ebccf1e3SJoseph Koshy __P4MASK(bogus, 1), 1695ebccf1e3SJoseph Koshy NULLMASK 1696ebccf1e3SJoseph Koshy }; 1697ebccf1e3SJoseph Koshy 1698ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_insret[] = { /* instr retired */ 1699ebccf1e3SJoseph Koshy __P4MASK(nbogusntag, 0), 1700ebccf1e3SJoseph Koshy __P4MASK(nbogustag, 1), 1701ebccf1e3SJoseph Koshy __P4MASK(bogusntag, 2), 1702ebccf1e3SJoseph Koshy __P4MASK(bogustag, 3), 1703ebccf1e3SJoseph Koshy NULLMASK 1704ebccf1e3SJoseph Koshy }; 1705ebccf1e3SJoseph Koshy 1706ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ur[] = { /* uops retired */ 1707ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1708ebccf1e3SJoseph Koshy __P4MASK(bogus, 1), 1709ebccf1e3SJoseph Koshy NULLMASK 1710ebccf1e3SJoseph Koshy }; 1711ebccf1e3SJoseph Koshy 1712ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ut[] = { /* uop type */ 1713ebccf1e3SJoseph Koshy __P4MASK(tagloads, 1), 1714ebccf1e3SJoseph Koshy __P4MASK(tagstores, 2), 1715ebccf1e3SJoseph Koshy NULLMASK 1716ebccf1e3SJoseph Koshy }; 1717ebccf1e3SJoseph Koshy 1718ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_br[] = { /* branch retired */ 1719ebccf1e3SJoseph Koshy __P4MASK(mmnp, 0), 1720ebccf1e3SJoseph Koshy __P4MASK(mmnm, 1), 1721ebccf1e3SJoseph Koshy __P4MASK(mmtp, 2), 1722ebccf1e3SJoseph Koshy __P4MASK(mmtm, 3), 1723ebccf1e3SJoseph Koshy NULLMASK 1724ebccf1e3SJoseph Koshy }; 1725ebccf1e3SJoseph Koshy 1726ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_mbr[] = { /* mispred branch retired */ 1727ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1728ebccf1e3SJoseph Koshy NULLMASK 1729ebccf1e3SJoseph Koshy }; 1730ebccf1e3SJoseph Koshy 1731ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xa[] = { /* x87 assist */ 1732ebccf1e3SJoseph Koshy __P4MASK(fpsu, 0), 1733ebccf1e3SJoseph Koshy __P4MASK(fpso, 1), 1734ebccf1e3SJoseph Koshy __P4MASK(poao, 2), 1735ebccf1e3SJoseph Koshy __P4MASK(poau, 3), 1736ebccf1e3SJoseph Koshy __P4MASK(prea, 4), 1737ebccf1e3SJoseph Koshy NULLMASK 1738ebccf1e3SJoseph Koshy }; 1739ebccf1e3SJoseph Koshy 1740ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_machclr[] = { /* machine clear */ 1741ebccf1e3SJoseph Koshy __P4MASK(clear, 0), 1742ebccf1e3SJoseph Koshy __P4MASK(moclear, 2), 1743ebccf1e3SJoseph Koshy __P4MASK(smclear, 3), 1744ebccf1e3SJoseph Koshy NULLMASK 1745ebccf1e3SJoseph Koshy }; 1746ebccf1e3SJoseph Koshy 1747ebccf1e3SJoseph Koshy /* P4 event parser */ 1748ebccf1e3SJoseph Koshy static int 1749ebccf1e3SJoseph Koshy p4_allocate_pmc(enum pmc_event pe, char *ctrspec, 1750ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 1751ebccf1e3SJoseph Koshy { 1752ebccf1e3SJoseph Koshy 1753ebccf1e3SJoseph Koshy char *e, *p, *q; 1754ebccf1e3SJoseph Koshy int count, has_tag, has_busreqtype, n; 17551e862e5aSFabien Thomas uint32_t cccractivemask; 17561e862e5aSFabien Thomas uint64_t evmask; 1757ebccf1e3SJoseph Koshy const struct pmc_masks *pm, *pmask; 1758ebccf1e3SJoseph Koshy 1759789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1760f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig = 1761f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 0; 1762ebccf1e3SJoseph Koshy 1763ebccf1e3SJoseph Koshy pmask = NULL; 1764ebccf1e3SJoseph Koshy evmask = 0; 1765ebccf1e3SJoseph Koshy cccractivemask = 0x3; 1766ebccf1e3SJoseph Koshy has_tag = has_busreqtype = 0; 1767ebccf1e3SJoseph Koshy 1768ebccf1e3SJoseph Koshy #define __P4SETMASK(M) do { \ 1769ebccf1e3SJoseph Koshy pmask = p4_mask_##M; \ 1770ebccf1e3SJoseph Koshy } while (0) 1771ebccf1e3SJoseph Koshy 1772ebccf1e3SJoseph Koshy switch (pe) { 1773ebccf1e3SJoseph Koshy case PMC_EV_P4_TC_DELIVER_MODE: 1774ebccf1e3SJoseph Koshy __P4SETMASK(tcdm); 1775ebccf1e3SJoseph Koshy break; 1776ebccf1e3SJoseph Koshy case PMC_EV_P4_BPU_FETCH_REQUEST: 1777ebccf1e3SJoseph Koshy __P4SETMASK(bfr); 1778ebccf1e3SJoseph Koshy break; 1779ebccf1e3SJoseph Koshy case PMC_EV_P4_ITLB_REFERENCE: 1780ebccf1e3SJoseph Koshy __P4SETMASK(ir); 1781ebccf1e3SJoseph Koshy break; 1782ebccf1e3SJoseph Koshy case PMC_EV_P4_MEMORY_CANCEL: 1783ebccf1e3SJoseph Koshy __P4SETMASK(memcan); 1784ebccf1e3SJoseph Koshy break; 1785ebccf1e3SJoseph Koshy case PMC_EV_P4_MEMORY_COMPLETE: 1786ebccf1e3SJoseph Koshy __P4SETMASK(memcomp); 1787ebccf1e3SJoseph Koshy break; 1788ebccf1e3SJoseph Koshy case PMC_EV_P4_LOAD_PORT_REPLAY: 1789ebccf1e3SJoseph Koshy __P4SETMASK(lpr); 1790ebccf1e3SJoseph Koshy break; 1791ebccf1e3SJoseph Koshy case PMC_EV_P4_STORE_PORT_REPLAY: 1792ebccf1e3SJoseph Koshy __P4SETMASK(spr); 1793ebccf1e3SJoseph Koshy break; 1794ebccf1e3SJoseph Koshy case PMC_EV_P4_MOB_LOAD_REPLAY: 1795ebccf1e3SJoseph Koshy __P4SETMASK(mlr); 1796ebccf1e3SJoseph Koshy break; 1797ebccf1e3SJoseph Koshy case PMC_EV_P4_PAGE_WALK_TYPE: 1798ebccf1e3SJoseph Koshy __P4SETMASK(pwt); 1799ebccf1e3SJoseph Koshy break; 1800ebccf1e3SJoseph Koshy case PMC_EV_P4_BSQ_CACHE_REFERENCE: 1801ebccf1e3SJoseph Koshy __P4SETMASK(bcr); 1802ebccf1e3SJoseph Koshy break; 1803ebccf1e3SJoseph Koshy case PMC_EV_P4_IOQ_ALLOCATION: 1804ebccf1e3SJoseph Koshy __P4SETMASK(ia); 1805ebccf1e3SJoseph Koshy has_busreqtype = 1; 1806ebccf1e3SJoseph Koshy break; 1807ebccf1e3SJoseph Koshy case PMC_EV_P4_IOQ_ACTIVE_ENTRIES: 1808ebccf1e3SJoseph Koshy __P4SETMASK(iae); 1809ebccf1e3SJoseph Koshy has_busreqtype = 1; 1810ebccf1e3SJoseph Koshy break; 1811ebccf1e3SJoseph Koshy case PMC_EV_P4_FSB_DATA_ACTIVITY: 1812ebccf1e3SJoseph Koshy __P4SETMASK(fda); 1813ebccf1e3SJoseph Koshy break; 1814ebccf1e3SJoseph Koshy case PMC_EV_P4_BSQ_ALLOCATION: 1815ebccf1e3SJoseph Koshy __P4SETMASK(ba); 1816ebccf1e3SJoseph Koshy break; 1817ebccf1e3SJoseph Koshy case PMC_EV_P4_SSE_INPUT_ASSIST: 1818ebccf1e3SJoseph Koshy __P4SETMASK(sia); 1819ebccf1e3SJoseph Koshy break; 1820ebccf1e3SJoseph Koshy case PMC_EV_P4_PACKED_SP_UOP: 1821ebccf1e3SJoseph Koshy __P4SETMASK(psu); 1822ebccf1e3SJoseph Koshy break; 1823ebccf1e3SJoseph Koshy case PMC_EV_P4_PACKED_DP_UOP: 1824ebccf1e3SJoseph Koshy __P4SETMASK(pdu); 1825ebccf1e3SJoseph Koshy break; 1826ebccf1e3SJoseph Koshy case PMC_EV_P4_SCALAR_SP_UOP: 1827ebccf1e3SJoseph Koshy __P4SETMASK(ssu); 1828ebccf1e3SJoseph Koshy break; 1829ebccf1e3SJoseph Koshy case PMC_EV_P4_SCALAR_DP_UOP: 1830ebccf1e3SJoseph Koshy __P4SETMASK(sdu); 1831ebccf1e3SJoseph Koshy break; 1832ebccf1e3SJoseph Koshy case PMC_EV_P4_64BIT_MMX_UOP: 1833ebccf1e3SJoseph Koshy __P4SETMASK(64bmu); 1834ebccf1e3SJoseph Koshy break; 1835ebccf1e3SJoseph Koshy case PMC_EV_P4_128BIT_MMX_UOP: 1836ebccf1e3SJoseph Koshy __P4SETMASK(128bmu); 1837ebccf1e3SJoseph Koshy break; 1838ebccf1e3SJoseph Koshy case PMC_EV_P4_X87_FP_UOP: 1839ebccf1e3SJoseph Koshy __P4SETMASK(xfu); 1840ebccf1e3SJoseph Koshy break; 1841ebccf1e3SJoseph Koshy case PMC_EV_P4_X87_SIMD_MOVES_UOP: 1842ebccf1e3SJoseph Koshy __P4SETMASK(xsmu); 1843ebccf1e3SJoseph Koshy break; 1844ebccf1e3SJoseph Koshy case PMC_EV_P4_GLOBAL_POWER_EVENTS: 1845ebccf1e3SJoseph Koshy __P4SETMASK(gpe); 1846ebccf1e3SJoseph Koshy break; 1847ebccf1e3SJoseph Koshy case PMC_EV_P4_TC_MS_XFER: 1848ebccf1e3SJoseph Koshy __P4SETMASK(tmx); 1849ebccf1e3SJoseph Koshy break; 1850ebccf1e3SJoseph Koshy case PMC_EV_P4_UOP_QUEUE_WRITES: 1851ebccf1e3SJoseph Koshy __P4SETMASK(uqw); 1852ebccf1e3SJoseph Koshy break; 1853ebccf1e3SJoseph Koshy case PMC_EV_P4_RETIRED_MISPRED_BRANCH_TYPE: 1854ebccf1e3SJoseph Koshy __P4SETMASK(rmbt); 1855ebccf1e3SJoseph Koshy break; 1856ebccf1e3SJoseph Koshy case PMC_EV_P4_RETIRED_BRANCH_TYPE: 1857ebccf1e3SJoseph Koshy __P4SETMASK(rbt); 1858ebccf1e3SJoseph Koshy break; 1859ebccf1e3SJoseph Koshy case PMC_EV_P4_RESOURCE_STALL: 1860ebccf1e3SJoseph Koshy __P4SETMASK(rs); 1861ebccf1e3SJoseph Koshy break; 1862ebccf1e3SJoseph Koshy case PMC_EV_P4_WC_BUFFER: 1863ebccf1e3SJoseph Koshy __P4SETMASK(wb); 1864ebccf1e3SJoseph Koshy break; 1865ebccf1e3SJoseph Koshy case PMC_EV_P4_BSQ_ACTIVE_ENTRIES: 1866ebccf1e3SJoseph Koshy case PMC_EV_P4_B2B_CYCLES: 1867ebccf1e3SJoseph Koshy case PMC_EV_P4_BNR: 1868ebccf1e3SJoseph Koshy case PMC_EV_P4_SNOOP: 1869ebccf1e3SJoseph Koshy case PMC_EV_P4_RESPONSE: 1870ebccf1e3SJoseph Koshy break; 1871ebccf1e3SJoseph Koshy case PMC_EV_P4_FRONT_END_EVENT: 1872ebccf1e3SJoseph Koshy __P4SETMASK(fee); 1873ebccf1e3SJoseph Koshy break; 1874ebccf1e3SJoseph Koshy case PMC_EV_P4_EXECUTION_EVENT: 1875ebccf1e3SJoseph Koshy __P4SETMASK(ee); 1876ebccf1e3SJoseph Koshy break; 1877ebccf1e3SJoseph Koshy case PMC_EV_P4_REPLAY_EVENT: 1878ebccf1e3SJoseph Koshy __P4SETMASK(re); 1879ebccf1e3SJoseph Koshy break; 1880ebccf1e3SJoseph Koshy case PMC_EV_P4_INSTR_RETIRED: 1881ebccf1e3SJoseph Koshy __P4SETMASK(insret); 1882ebccf1e3SJoseph Koshy break; 1883ebccf1e3SJoseph Koshy case PMC_EV_P4_UOPS_RETIRED: 1884ebccf1e3SJoseph Koshy __P4SETMASK(ur); 1885ebccf1e3SJoseph Koshy break; 1886ebccf1e3SJoseph Koshy case PMC_EV_P4_UOP_TYPE: 1887ebccf1e3SJoseph Koshy __P4SETMASK(ut); 1888ebccf1e3SJoseph Koshy break; 1889ebccf1e3SJoseph Koshy case PMC_EV_P4_BRANCH_RETIRED: 1890ebccf1e3SJoseph Koshy __P4SETMASK(br); 1891ebccf1e3SJoseph Koshy break; 1892ebccf1e3SJoseph Koshy case PMC_EV_P4_MISPRED_BRANCH_RETIRED: 1893ebccf1e3SJoseph Koshy __P4SETMASK(mbr); 1894ebccf1e3SJoseph Koshy break; 1895ebccf1e3SJoseph Koshy case PMC_EV_P4_X87_ASSIST: 1896ebccf1e3SJoseph Koshy __P4SETMASK(xa); 1897ebccf1e3SJoseph Koshy break; 1898ebccf1e3SJoseph Koshy case PMC_EV_P4_MACHINE_CLEAR: 1899ebccf1e3SJoseph Koshy __P4SETMASK(machclr); 1900ebccf1e3SJoseph Koshy break; 1901ebccf1e3SJoseph Koshy default: 1902aa342b1fSJoseph Koshy return (-1); 1903ebccf1e3SJoseph Koshy } 1904ebccf1e3SJoseph Koshy 1905ebccf1e3SJoseph Koshy /* process additional flags */ 1906ebccf1e3SJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 1907ebccf1e3SJoseph Koshy if (KWPREFIXMATCH(p, P4_KW_ACTIVE)) { 1908ebccf1e3SJoseph Koshy q = strchr(p, '='); 1909ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1910aa342b1fSJoseph Koshy return (-1); 1911ebccf1e3SJoseph Koshy 1912789140c0SJoseph Koshy if (strcasecmp(q, P4_KW_ACTIVE_NONE) == 0) 1913ebccf1e3SJoseph Koshy cccractivemask = 0x0; 1914789140c0SJoseph Koshy else if (strcasecmp(q, P4_KW_ACTIVE_SINGLE) == 0) 1915ebccf1e3SJoseph Koshy cccractivemask = 0x1; 1916789140c0SJoseph Koshy else if (strcasecmp(q, P4_KW_ACTIVE_BOTH) == 0) 1917ebccf1e3SJoseph Koshy cccractivemask = 0x2; 1918789140c0SJoseph Koshy else if (strcasecmp(q, P4_KW_ACTIVE_ANY) == 0) 1919ebccf1e3SJoseph Koshy cccractivemask = 0x3; 1920ebccf1e3SJoseph Koshy else 1921aa342b1fSJoseph Koshy return (-1); 1922ebccf1e3SJoseph Koshy 1923ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, P4_KW_BUSREQTYPE)) { 1924ebccf1e3SJoseph Koshy if (has_busreqtype == 0) 1925aa342b1fSJoseph Koshy return (-1); 1926ebccf1e3SJoseph Koshy 1927ebccf1e3SJoseph Koshy q = strchr(p, '='); 1928ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1929aa342b1fSJoseph Koshy return (-1); 1930ebccf1e3SJoseph Koshy 1931ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 1932ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 1933aa342b1fSJoseph Koshy return (-1); 1934ebccf1e3SJoseph Koshy evmask = (evmask & ~0x1F) | (count & 0x1F); 1935ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P4_KW_CASCADE)) 1936ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_CASCADE; 1937ebccf1e3SJoseph Koshy else if (KWMATCH(p, P4_KW_EDGE)) 1938ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1939ebccf1e3SJoseph Koshy else if (KWMATCH(p, P4_KW_INV)) 1940ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 1941ebccf1e3SJoseph Koshy else if (KWPREFIXMATCH(p, P4_KW_MASK "=")) { 1942ebccf1e3SJoseph Koshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 1943aa342b1fSJoseph Koshy return (-1); 1944ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1945ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P4_KW_OS)) 1946ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 1947ebccf1e3SJoseph Koshy else if (KWMATCH(p, P4_KW_PRECISE)) 1948ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_PRECISE; 1949ebccf1e3SJoseph Koshy else if (KWPREFIXMATCH(p, P4_KW_TAG "=")) { 1950ebccf1e3SJoseph Koshy if (has_tag == 0) 1951aa342b1fSJoseph Koshy return (-1); 1952ebccf1e3SJoseph Koshy 1953ebccf1e3SJoseph Koshy q = strchr(p, '='); 1954ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1955aa342b1fSJoseph Koshy return (-1); 1956ebccf1e3SJoseph Koshy 1957ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 1958ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 1959aa342b1fSJoseph Koshy return (-1); 1960ebccf1e3SJoseph Koshy 1961ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_TAGGING; 1962f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig |= 1963ebccf1e3SJoseph Koshy P4_ESCR_TO_TAG_VALUE(count); 1964ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, P4_KW_THRESHOLD "=")) { 1965ebccf1e3SJoseph Koshy q = strchr(p, '='); 1966ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1967aa342b1fSJoseph Koshy return (-1); 1968ebccf1e3SJoseph Koshy 1969ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 1970ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 1971aa342b1fSJoseph Koshy return (-1); 1972ebccf1e3SJoseph Koshy 1973ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 1974f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig &= 1975f263522aSJoseph Koshy ~P4_CCCR_THRESHOLD_MASK; 1976f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |= 1977f263522aSJoseph Koshy P4_CCCR_TO_THRESHOLD(count); 1978ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P4_KW_USR)) 1979ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 1980ebccf1e3SJoseph Koshy else 1981aa342b1fSJoseph Koshy return (-1); 1982ebccf1e3SJoseph Koshy } 1983ebccf1e3SJoseph Koshy 1984ebccf1e3SJoseph Koshy /* other post processing */ 1985ebccf1e3SJoseph Koshy if (pe == PMC_EV_P4_IOQ_ALLOCATION || 1986ebccf1e3SJoseph Koshy pe == PMC_EV_P4_FSB_DATA_ACTIVITY || 1987ebccf1e3SJoseph Koshy pe == PMC_EV_P4_BSQ_ALLOCATION) 1988ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1989ebccf1e3SJoseph Koshy 1990ebccf1e3SJoseph Koshy /* fill in thread activity mask */ 1991f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |= 1992ebccf1e3SJoseph Koshy P4_CCCR_TO_ACTIVE_THREAD(cccractivemask); 1993ebccf1e3SJoseph Koshy 1994ebccf1e3SJoseph Koshy if (evmask) 1995ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1996ebccf1e3SJoseph Koshy 1997ebccf1e3SJoseph Koshy switch (pe) { 1998ebccf1e3SJoseph Koshy case PMC_EV_P4_FSB_DATA_ACTIVITY: 1999ebccf1e3SJoseph Koshy if ((evmask & 0x06) == 0x06 || 2000ebccf1e3SJoseph Koshy (evmask & 0x18) == 0x18) 2001aa342b1fSJoseph Koshy return (-1); /* can't have own+other bits together */ 2002ebccf1e3SJoseph Koshy if (evmask == 0) /* default:drdy-{drv,own}+dbsy{drv,own} */ 2003ebccf1e3SJoseph Koshy evmask = 0x1D; 2004ebccf1e3SJoseph Koshy break; 2005ebccf1e3SJoseph Koshy case PMC_EV_P4_MACHINE_CLEAR: 2006ebccf1e3SJoseph Koshy /* only one bit is allowed to be set */ 2007ebccf1e3SJoseph Koshy if ((evmask & (evmask - 1)) != 0) 2008aa342b1fSJoseph Koshy return (-1); 2009ebccf1e3SJoseph Koshy if (evmask == 0) { 2010ebccf1e3SJoseph Koshy evmask = 0x1; /* 'CLEAR' */ 2011ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2012ebccf1e3SJoseph Koshy } 2013ebccf1e3SJoseph Koshy break; 2014ebccf1e3SJoseph Koshy default: 2015ebccf1e3SJoseph Koshy if (evmask == 0 && pmask) { 2016ebccf1e3SJoseph Koshy for (pm = pmask; pm->pm_name; pm++) 2017ebccf1e3SJoseph Koshy evmask |= pm->pm_value; 2018ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2019ebccf1e3SJoseph Koshy } 2020ebccf1e3SJoseph Koshy } 2021ebccf1e3SJoseph Koshy 2022f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 2023f263522aSJoseph Koshy P4_ESCR_TO_EVENT_MASK(evmask); 2024ebccf1e3SJoseph Koshy 2025aa342b1fSJoseph Koshy return (0); 2026ebccf1e3SJoseph Koshy } 2027ebccf1e3SJoseph Koshy 202886a65549SJoseph Koshy #endif 202986a65549SJoseph Koshy 203086a65549SJoseph Koshy #if defined(__i386__) 203186a65549SJoseph Koshy 2032ebccf1e3SJoseph Koshy /* 2033f263522aSJoseph Koshy * Pentium style PMCs 2034f263522aSJoseph Koshy */ 2035f263522aSJoseph Koshy 2036f263522aSJoseph Koshy static struct pmc_event_alias p5_aliases[] = { 20370b9b757dSJoseph Koshy EV_ALIAS("branches", "p5-taken-branches"), 2038f263522aSJoseph Koshy EV_ALIAS("cycles", "tsc"), 20390b9b757dSJoseph Koshy EV_ALIAS("dc-misses", "p5-data-read-miss-or-write-miss"), 20400b9b757dSJoseph Koshy EV_ALIAS("ic-misses", "p5-code-cache-miss"), 20410b9b757dSJoseph Koshy EV_ALIAS("instructions", "p5-instructions-executed"), 20420b9b757dSJoseph Koshy EV_ALIAS("interrupts", "p5-hardware-interrupts"), 20430b9b757dSJoseph Koshy EV_ALIAS("unhalted-cycles", 20440b9b757dSJoseph Koshy "p5-number-of-cycles-not-in-halt-state"), 2045f263522aSJoseph Koshy EV_ALIAS(NULL, NULL) 2046f263522aSJoseph Koshy }; 2047f263522aSJoseph Koshy 2048f263522aSJoseph Koshy static int 2049f263522aSJoseph Koshy p5_allocate_pmc(enum pmc_event pe, char *ctrspec, 2050f263522aSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 2051f263522aSJoseph Koshy { 2052aa342b1fSJoseph Koshy return (-1 || pe || ctrspec || pmc_config); /* shut up gcc */ 2053f263522aSJoseph Koshy } 2054f263522aSJoseph Koshy 2055f263522aSJoseph Koshy /* 2056ebccf1e3SJoseph Koshy * Pentium Pro style PMCs. These PMCs are found in Pentium II, Pentium III, 2057ebccf1e3SJoseph Koshy * and Pentium M CPUs. 2058ebccf1e3SJoseph Koshy */ 2059ebccf1e3SJoseph Koshy 2060ebccf1e3SJoseph Koshy static struct pmc_event_alias p6_aliases[] = { 2061ebccf1e3SJoseph Koshy EV_ALIAS("branches", "p6-br-inst-retired"), 2062ebccf1e3SJoseph Koshy EV_ALIAS("branch-mispredicts", "p6-br-miss-pred-retired"), 2063ebccf1e3SJoseph Koshy EV_ALIAS("cycles", "tsc"), 2064d56c5d4bSJoseph Koshy EV_ALIAS("dc-misses", "p6-dcu-lines-in"), 206573e2d811SJoseph Koshy EV_ALIAS("ic-misses", "p6-ifu-fetch-miss"), 2066ebccf1e3SJoseph Koshy EV_ALIAS("instructions", "p6-inst-retired"), 2067ebccf1e3SJoseph Koshy EV_ALIAS("interrupts", "p6-hw-int-rx"), 2068177a2f22SJoseph Koshy EV_ALIAS("unhalted-cycles", "p6-cpu-clk-unhalted"), 2069ebccf1e3SJoseph Koshy EV_ALIAS(NULL, NULL) 2070ebccf1e3SJoseph Koshy }; 2071ebccf1e3SJoseph Koshy 2072ebccf1e3SJoseph Koshy #define P6_KW_CMASK "cmask" 2073ebccf1e3SJoseph Koshy #define P6_KW_EDGE "edge" 2074ebccf1e3SJoseph Koshy #define P6_KW_INV "inv" 2075ebccf1e3SJoseph Koshy #define P6_KW_OS "os" 2076ebccf1e3SJoseph Koshy #define P6_KW_UMASK "umask" 2077ebccf1e3SJoseph Koshy #define P6_KW_USR "usr" 2078ebccf1e3SJoseph Koshy 2079ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mesi[] = { 2080ebccf1e3SJoseph Koshy PMCMASK(m, 0x01), 2081ebccf1e3SJoseph Koshy PMCMASK(e, 0x02), 2082ebccf1e3SJoseph Koshy PMCMASK(s, 0x04), 2083ebccf1e3SJoseph Koshy PMCMASK(i, 0x08), 2084ebccf1e3SJoseph Koshy NULLMASK 2085ebccf1e3SJoseph Koshy }; 2086ebccf1e3SJoseph Koshy 2087ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mesihw[] = { 2088ebccf1e3SJoseph Koshy PMCMASK(m, 0x01), 2089ebccf1e3SJoseph Koshy PMCMASK(e, 0x02), 2090ebccf1e3SJoseph Koshy PMCMASK(s, 0x04), 2091ebccf1e3SJoseph Koshy PMCMASK(i, 0x08), 2092ebccf1e3SJoseph Koshy PMCMASK(nonhw, 0x00), 2093ebccf1e3SJoseph Koshy PMCMASK(hw, 0x10), 2094ebccf1e3SJoseph Koshy PMCMASK(both, 0x30), 2095ebccf1e3SJoseph Koshy NULLMASK 2096ebccf1e3SJoseph Koshy }; 2097ebccf1e3SJoseph Koshy 2098ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_hw[] = { 2099ebccf1e3SJoseph Koshy PMCMASK(nonhw, 0x00), 2100ebccf1e3SJoseph Koshy PMCMASK(hw, 0x10), 2101ebccf1e3SJoseph Koshy PMCMASK(both, 0x30), 2102ebccf1e3SJoseph Koshy NULLMASK 2103ebccf1e3SJoseph Koshy }; 2104ebccf1e3SJoseph Koshy 2105ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_any[] = { 2106ebccf1e3SJoseph Koshy PMCMASK(self, 0x00), 2107ebccf1e3SJoseph Koshy PMCMASK(any, 0x20), 2108ebccf1e3SJoseph Koshy NULLMASK 2109ebccf1e3SJoseph Koshy }; 2110ebccf1e3SJoseph Koshy 2111ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_ekp[] = { 2112ebccf1e3SJoseph Koshy PMCMASK(nta, 0x00), 2113ebccf1e3SJoseph Koshy PMCMASK(t1, 0x01), 2114ebccf1e3SJoseph Koshy PMCMASK(t2, 0x02), 2115ebccf1e3SJoseph Koshy PMCMASK(wos, 0x03), 2116ebccf1e3SJoseph Koshy NULLMASK 2117ebccf1e3SJoseph Koshy }; 2118ebccf1e3SJoseph Koshy 2119ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_pps[] = { 2120ebccf1e3SJoseph Koshy PMCMASK(packed-and-scalar, 0x00), 2121ebccf1e3SJoseph Koshy PMCMASK(scalar, 0x01), 2122ebccf1e3SJoseph Koshy NULLMASK 2123ebccf1e3SJoseph Koshy }; 2124ebccf1e3SJoseph Koshy 2125ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mite[] = { 2126ebccf1e3SJoseph Koshy PMCMASK(packed-multiply, 0x01), 2127ebccf1e3SJoseph Koshy PMCMASK(packed-shift, 0x02), 2128ebccf1e3SJoseph Koshy PMCMASK(pack, 0x04), 2129ebccf1e3SJoseph Koshy PMCMASK(unpack, 0x08), 2130ebccf1e3SJoseph Koshy PMCMASK(packed-logical, 0x10), 2131ebccf1e3SJoseph Koshy PMCMASK(packed-arithmetic, 0x20), 2132ebccf1e3SJoseph Koshy NULLMASK 2133ebccf1e3SJoseph Koshy }; 2134ebccf1e3SJoseph Koshy 2135ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_fmt[] = { 2136ebccf1e3SJoseph Koshy PMCMASK(mmxtofp, 0x00), 2137ebccf1e3SJoseph Koshy PMCMASK(fptommx, 0x01), 2138ebccf1e3SJoseph Koshy NULLMASK 2139ebccf1e3SJoseph Koshy }; 2140ebccf1e3SJoseph Koshy 2141ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_sr[] = { 2142ebccf1e3SJoseph Koshy PMCMASK(es, 0x01), 2143ebccf1e3SJoseph Koshy PMCMASK(ds, 0x02), 2144ebccf1e3SJoseph Koshy PMCMASK(fs, 0x04), 2145ebccf1e3SJoseph Koshy PMCMASK(gs, 0x08), 2146ebccf1e3SJoseph Koshy NULLMASK 2147ebccf1e3SJoseph Koshy }; 2148ebccf1e3SJoseph Koshy 2149ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_eet[] = { 2150ebccf1e3SJoseph Koshy PMCMASK(all, 0x00), 2151ebccf1e3SJoseph Koshy PMCMASK(freq, 0x02), 2152ebccf1e3SJoseph Koshy NULLMASK 2153ebccf1e3SJoseph Koshy }; 2154ebccf1e3SJoseph Koshy 2155ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_efur[] = { 2156ebccf1e3SJoseph Koshy PMCMASK(all, 0x00), 2157ebccf1e3SJoseph Koshy PMCMASK(loadop, 0x01), 2158ebccf1e3SJoseph Koshy PMCMASK(stdsta, 0x02), 2159ebccf1e3SJoseph Koshy NULLMASK 2160ebccf1e3SJoseph Koshy }; 2161ebccf1e3SJoseph Koshy 2162ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_essir[] = { 2163ebccf1e3SJoseph Koshy PMCMASK(sse-packed-single, 0x00), 2164ebccf1e3SJoseph Koshy PMCMASK(sse-packed-single-scalar-single, 0x01), 2165ebccf1e3SJoseph Koshy PMCMASK(sse2-packed-double, 0x02), 2166ebccf1e3SJoseph Koshy PMCMASK(sse2-scalar-double, 0x03), 2167ebccf1e3SJoseph Koshy NULLMASK 2168ebccf1e3SJoseph Koshy }; 2169ebccf1e3SJoseph Koshy 2170ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_esscir[] = { 2171ebccf1e3SJoseph Koshy PMCMASK(sse-packed-single, 0x00), 2172ebccf1e3SJoseph Koshy PMCMASK(sse-scalar-single, 0x01), 2173ebccf1e3SJoseph Koshy PMCMASK(sse2-packed-double, 0x02), 2174ebccf1e3SJoseph Koshy PMCMASK(sse2-scalar-double, 0x03), 2175ebccf1e3SJoseph Koshy NULLMASK 2176ebccf1e3SJoseph Koshy }; 2177ebccf1e3SJoseph Koshy 2178ebccf1e3SJoseph Koshy /* P6 event parser */ 2179ebccf1e3SJoseph Koshy static int 2180ebccf1e3SJoseph Koshy p6_allocate_pmc(enum pmc_event pe, char *ctrspec, 2181ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 2182ebccf1e3SJoseph Koshy { 2183ebccf1e3SJoseph Koshy char *e, *p, *q; 21841e862e5aSFabien Thomas uint64_t evmask; 2185ebccf1e3SJoseph Koshy int count, n; 2186ebccf1e3SJoseph Koshy const struct pmc_masks *pm, *pmask; 2187ebccf1e3SJoseph Koshy 2188789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2189f263522aSJoseph Koshy pmc_config->pm_md.pm_ppro.pm_ppro_config = 0; 2190ebccf1e3SJoseph Koshy 2191ebccf1e3SJoseph Koshy evmask = 0; 2192ebccf1e3SJoseph Koshy 2193ebccf1e3SJoseph Koshy #define P6MASKSET(M) pmask = p6_mask_ ## M 2194ebccf1e3SJoseph Koshy 2195ebccf1e3SJoseph Koshy switch(pe) { 2196ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_IFETCH: P6MASKSET(mesi); break; 2197ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_LD: P6MASKSET(mesi); break; 2198ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_ST: P6MASKSET(mesi); break; 2199ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_RQSTS: P6MASKSET(mesi); break; 2200ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_DRDY_CLOCKS: 2201ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_LOCK_CLOCKS: 2202ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BRD: 2203ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_RFO: 2204ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_WB: 2205ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_IFETCH: 2206ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_INVAL: 2207ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_PWR: 2208ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_P: 2209ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_IO: 2210ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_DEF: 2211ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BURST: 2212ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_ANY: 2213ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_MEM: 2214ebccf1e3SJoseph Koshy P6MASKSET(any); break; 2215ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED: 2216ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_MISS: 2217ebccf1e3SJoseph Koshy P6MASKSET(ekp); break; 2218ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_INST_RETIRED: 2219ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_COMP_INST_RET: 2220ebccf1e3SJoseph Koshy P6MASKSET(pps); break; 2221ebccf1e3SJoseph Koshy case PMC_EV_P6_MMX_INSTR_TYPE_EXEC: 2222ebccf1e3SJoseph Koshy P6MASKSET(mite); break; 2223ebccf1e3SJoseph Koshy case PMC_EV_P6_FP_MMX_TRANS: 2224ebccf1e3SJoseph Koshy P6MASKSET(fmt); break; 2225ebccf1e3SJoseph Koshy case PMC_EV_P6_SEG_RENAME_STALLS: 2226ebccf1e3SJoseph Koshy case PMC_EV_P6_SEG_REG_RENAMES: 2227ebccf1e3SJoseph Koshy P6MASKSET(sr); break; 2228ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_EST_TRANS: 2229ebccf1e3SJoseph Koshy P6MASKSET(eet); break; 2230ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_FUSED_UOPS_RET: 2231ebccf1e3SJoseph Koshy P6MASKSET(efur); break; 2232ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED: 2233ebccf1e3SJoseph Koshy P6MASKSET(essir); break; 2234ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED: 2235ebccf1e3SJoseph Koshy P6MASKSET(esscir); break; 2236ebccf1e3SJoseph Koshy default: 2237ebccf1e3SJoseph Koshy pmask = NULL; 2238ebccf1e3SJoseph Koshy break; 2239ebccf1e3SJoseph Koshy } 2240ebccf1e3SJoseph Koshy 2241ebccf1e3SJoseph Koshy /* Pentium M PMCs have a few events with different semantics */ 2242ebccf1e3SJoseph Koshy if (cpu_info.pm_cputype == PMC_CPU_INTEL_PM) { 2243ebccf1e3SJoseph Koshy if (pe == PMC_EV_P6_L2_LD || 2244ebccf1e3SJoseph Koshy pe == PMC_EV_P6_L2_LINES_IN || 2245ebccf1e3SJoseph Koshy pe == PMC_EV_P6_L2_LINES_OUT) 2246ebccf1e3SJoseph Koshy P6MASKSET(mesihw); 2247ebccf1e3SJoseph Koshy else if (pe == PMC_EV_P6_L2_M_LINES_OUTM) 2248ebccf1e3SJoseph Koshy P6MASKSET(hw); 2249ebccf1e3SJoseph Koshy } 2250ebccf1e3SJoseph Koshy 2251ebccf1e3SJoseph Koshy /* Parse additional modifiers if present */ 2252ebccf1e3SJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 2253ebccf1e3SJoseph Koshy if (KWPREFIXMATCH(p, P6_KW_CMASK "=")) { 2254ebccf1e3SJoseph Koshy q = strchr(p, '='); 2255ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 2256aa342b1fSJoseph Koshy return (-1); 2257ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 2258ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 2259aa342b1fSJoseph Koshy return (-1); 2260ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 2261f263522aSJoseph Koshy pmc_config->pm_md.pm_ppro.pm_ppro_config |= 2262f263522aSJoseph Koshy P6_EVSEL_TO_CMASK(count); 2263ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_EDGE)) { 2264ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 2265ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_INV)) { 2266ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 2267ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_OS)) { 2268ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2269ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, P6_KW_UMASK "=")) { 2270ebccf1e3SJoseph Koshy evmask = 0; 2271ebccf1e3SJoseph Koshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 2272aa342b1fSJoseph Koshy return (-1); 2273ebccf1e3SJoseph Koshy if ((pe == PMC_EV_P6_BUS_DRDY_CLOCKS || 2274ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_LOCK_CLOCKS || 2275ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_BRD || 2276ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_RFO || 2277ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_IFETCH || 2278ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_INVAL || 2279ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_PWR || 2280ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_DEF || 2281ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_BURST || 2282ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_ANY || 2283ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_MEM || 2284ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRANS_IO || 2285ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRANS_P || 2286ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRANS_WB || 2287ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_EST_TRANS || 2288ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_FUSED_UOPS_RET || 2289ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_COMP_INST_RET || 2290ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_INST_RETIRED || 2291ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_PREF_DISPATCHED || 2292ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_PREF_MISS || 2293ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED || 2294ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED || 2295ebccf1e3SJoseph Koshy pe == PMC_EV_P6_FP_MMX_TRANS) 2296aa342b1fSJoseph Koshy && (n > 1)) /* Only one mask keyword is allowed. */ 2297aa342b1fSJoseph Koshy return (-1); 2298ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2299ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_USR)) { 2300ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 2301ebccf1e3SJoseph Koshy } else 2302aa342b1fSJoseph Koshy return (-1); 2303ebccf1e3SJoseph Koshy } 2304ebccf1e3SJoseph Koshy 2305ebccf1e3SJoseph Koshy /* post processing */ 2306ebccf1e3SJoseph Koshy switch (pe) { 2307ebccf1e3SJoseph Koshy 2308ebccf1e3SJoseph Koshy /* 2309ebccf1e3SJoseph Koshy * The following events default to an evmask of 0 2310ebccf1e3SJoseph Koshy */ 2311ebccf1e3SJoseph Koshy 2312ebccf1e3SJoseph Koshy /* default => 'self' */ 2313ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_DRDY_CLOCKS: 2314ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_LOCK_CLOCKS: 2315ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BRD: 2316ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_RFO: 2317ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_WB: 2318ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_IFETCH: 2319ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_INVAL: 2320ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_PWR: 2321ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_P: 2322ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_IO: 2323ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_DEF: 2324ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BURST: 2325ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_ANY: 2326ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_MEM: 2327ebccf1e3SJoseph Koshy 2328ebccf1e3SJoseph Koshy /* default => 'nta' */ 2329ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED: 2330ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_MISS: 2331ebccf1e3SJoseph Koshy 2332ebccf1e3SJoseph Koshy /* default => 'packed and scalar' */ 2333ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_INST_RETIRED: 2334ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_COMP_INST_RET: 2335ebccf1e3SJoseph Koshy 2336ebccf1e3SJoseph Koshy /* default => 'mmx to fp transitions' */ 2337ebccf1e3SJoseph Koshy case PMC_EV_P6_FP_MMX_TRANS: 2338ebccf1e3SJoseph Koshy 2339ebccf1e3SJoseph Koshy /* default => 'SSE Packed Single' */ 2340ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED: 2341ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED: 2342ebccf1e3SJoseph Koshy 2343ebccf1e3SJoseph Koshy /* default => 'all fused micro-ops' */ 2344ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_FUSED_UOPS_RET: 2345ebccf1e3SJoseph Koshy 2346ebccf1e3SJoseph Koshy /* default => 'all transitions' */ 2347ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_EST_TRANS: 2348ebccf1e3SJoseph Koshy break; 2349ebccf1e3SJoseph Koshy 2350ebccf1e3SJoseph Koshy case PMC_EV_P6_MMX_UOPS_EXEC: 2351ebccf1e3SJoseph Koshy evmask = 0x0F; /* only value allowed */ 2352ebccf1e3SJoseph Koshy break; 2353ebccf1e3SJoseph Koshy 2354ebccf1e3SJoseph Koshy default: 2355ebccf1e3SJoseph Koshy /* 2356ebccf1e3SJoseph Koshy * For all other events, set the default event mask 2357ebccf1e3SJoseph Koshy * to a logical OR of all the allowed event mask bits. 2358ebccf1e3SJoseph Koshy */ 2359ebccf1e3SJoseph Koshy if (evmask == 0 && pmask) { 2360ebccf1e3SJoseph Koshy for (pm = pmask; pm->pm_name; pm++) 2361ebccf1e3SJoseph Koshy evmask |= pm->pm_value; 2362ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2363ebccf1e3SJoseph Koshy } 2364ebccf1e3SJoseph Koshy 2365ebccf1e3SJoseph Koshy break; 2366ebccf1e3SJoseph Koshy } 2367ebccf1e3SJoseph Koshy 2368ebccf1e3SJoseph Koshy if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) 2369f263522aSJoseph Koshy pmc_config->pm_md.pm_ppro.pm_ppro_config |= 2370f263522aSJoseph Koshy P6_EVSEL_TO_UMASK(evmask); 2371ebccf1e3SJoseph Koshy 2372aa342b1fSJoseph Koshy return (0); 2373ebccf1e3SJoseph Koshy } 2374ebccf1e3SJoseph Koshy 2375ebccf1e3SJoseph Koshy #endif 2376ebccf1e3SJoseph Koshy 2377789140c0SJoseph Koshy #if defined(__i386__) || defined(__amd64__) 2378789140c0SJoseph Koshy static int 2379789140c0SJoseph Koshy tsc_allocate_pmc(enum pmc_event pe, char *ctrspec, 2380789140c0SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 2381789140c0SJoseph Koshy { 2382789140c0SJoseph Koshy if (pe != PMC_EV_TSC_TSC) 2383789140c0SJoseph Koshy return (-1); 2384789140c0SJoseph Koshy 2385789140c0SJoseph Koshy /* TSC events must be unqualified. */ 2386789140c0SJoseph Koshy if (ctrspec && *ctrspec != '\0') 2387789140c0SJoseph Koshy return (-1); 2388789140c0SJoseph Koshy 2389789140c0SJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 2390789140c0SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_READ; 2391789140c0SJoseph Koshy 2392789140c0SJoseph Koshy return (0); 2393789140c0SJoseph Koshy } 2394789140c0SJoseph Koshy #endif 2395789140c0SJoseph Koshy 2396f5f9340bSFabien Thomas static struct pmc_event_alias generic_aliases[] = { 2397f5f9340bSFabien Thomas EV_ALIAS("instructions", "SOFT-CLOCK.HARD"), 2398f5f9340bSFabien Thomas EV_ALIAS(NULL, NULL) 2399f5f9340bSFabien Thomas }; 2400f5f9340bSFabien Thomas 2401f5f9340bSFabien Thomas static int 2402f5f9340bSFabien Thomas soft_allocate_pmc(enum pmc_event pe, char *ctrspec, 2403f5f9340bSFabien Thomas struct pmc_op_pmcallocate *pmc_config) 2404f5f9340bSFabien Thomas { 2405f5f9340bSFabien Thomas (void)ctrspec; 2406f5f9340bSFabien Thomas (void)pmc_config; 2407f5f9340bSFabien Thomas 2408f0bbe9aaSDimitry Andric if ((int)pe < PMC_EV_SOFT_FIRST || (int)pe > PMC_EV_SOFT_LAST) 2409f5f9340bSFabien Thomas return (-1); 2410f5f9340bSFabien Thomas 2411f5f9340bSFabien Thomas pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2412f5f9340bSFabien Thomas return (0); 2413f5f9340bSFabien Thomas } 2414f5f9340bSFabien Thomas 24156411d14dSRuslan Bukin #if defined(__arm__) 24160ce207d2SRui Paulo #if defined(__XSCALE__) 24170ce207d2SRui Paulo 24180ce207d2SRui Paulo static struct pmc_event_alias xscale_aliases[] = { 24190ce207d2SRui Paulo EV_ALIAS("branches", "BRANCH_RETIRED"), 24200ce207d2SRui Paulo EV_ALIAS("branch-mispredicts", "BRANCH_MISPRED"), 24210ce207d2SRui Paulo EV_ALIAS("dc-misses", "DC_MISS"), 24220ce207d2SRui Paulo EV_ALIAS("ic-misses", "IC_MISS"), 24230ce207d2SRui Paulo EV_ALIAS("instructions", "INSTR_RETIRED"), 24240ce207d2SRui Paulo EV_ALIAS(NULL, NULL) 24250ce207d2SRui Paulo }; 24260ce207d2SRui Paulo static int 24270ce207d2SRui Paulo xscale_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 24280ce207d2SRui Paulo struct pmc_op_pmcallocate *pmc_config __unused) 24290ce207d2SRui Paulo { 24300ce207d2SRui Paulo switch (pe) { 24310ce207d2SRui Paulo default: 24320ce207d2SRui Paulo break; 24330ce207d2SRui Paulo } 24340ce207d2SRui Paulo 24350ce207d2SRui Paulo return (0); 24360ce207d2SRui Paulo } 24370ce207d2SRui Paulo #endif 24380ce207d2SRui Paulo 24396411d14dSRuslan Bukin static struct pmc_event_alias armv7_aliases[] = { 24406411d14dSRuslan Bukin EV_ALIAS("dc-misses", "L1_DCACHE_REFILL"), 24416411d14dSRuslan Bukin EV_ALIAS("ic-misses", "L1_ICACHE_REFILL"), 24426411d14dSRuslan Bukin EV_ALIAS("instructions", "INSTR_EXECUTED"), 24436411d14dSRuslan Bukin EV_ALIAS(NULL, NULL) 24446411d14dSRuslan Bukin }; 24456411d14dSRuslan Bukin static int 24466411d14dSRuslan Bukin armv7_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 24476411d14dSRuslan Bukin struct pmc_op_pmcallocate *pmc_config __unused) 24486411d14dSRuslan Bukin { 24496411d14dSRuslan Bukin switch (pe) { 24506411d14dSRuslan Bukin default: 24516411d14dSRuslan Bukin break; 24526411d14dSRuslan Bukin } 24536411d14dSRuslan Bukin 24546411d14dSRuslan Bukin return (0); 24556411d14dSRuslan Bukin } 24566411d14dSRuslan Bukin #endif 24576411d14dSRuslan Bukin 2458bc88bb2bSRuslan Bukin #if defined(__aarch64__) 2459bc88bb2bSRuslan Bukin static struct pmc_event_alias cortex_a53_aliases[] = { 2460bc88bb2bSRuslan Bukin EV_ALIAS(NULL, NULL) 2461bc88bb2bSRuslan Bukin }; 2462bc88bb2bSRuslan Bukin static struct pmc_event_alias cortex_a57_aliases[] = { 2463bc88bb2bSRuslan Bukin EV_ALIAS(NULL, NULL) 2464bc88bb2bSRuslan Bukin }; 2465bc88bb2bSRuslan Bukin static int 2466bc88bb2bSRuslan Bukin arm64_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 2467bc88bb2bSRuslan Bukin struct pmc_op_pmcallocate *pmc_config __unused) 2468bc88bb2bSRuslan Bukin { 2469bc88bb2bSRuslan Bukin switch (pe) { 2470bc88bb2bSRuslan Bukin default: 2471bc88bb2bSRuslan Bukin break; 2472bc88bb2bSRuslan Bukin } 2473bc88bb2bSRuslan Bukin 2474bc88bb2bSRuslan Bukin return (0); 2475bc88bb2bSRuslan Bukin } 2476bc88bb2bSRuslan Bukin #endif 2477bc88bb2bSRuslan Bukin 2478660df75eSGeorge V. Neville-Neil #if defined(__mips__) 2479660df75eSGeorge V. Neville-Neil 2480660df75eSGeorge V. Neville-Neil static struct pmc_event_alias mips24k_aliases[] = { 2481660df75eSGeorge V. Neville-Neil EV_ALIAS("instructions", "INSTR_EXECUTED"), 2482660df75eSGeorge V. Neville-Neil EV_ALIAS("branches", "BRANCH_COMPLETED"), 2483660df75eSGeorge V. Neville-Neil EV_ALIAS("branch-mispredicts", "BRANCH_MISPRED"), 2484660df75eSGeorge V. Neville-Neil EV_ALIAS(NULL, NULL) 2485660df75eSGeorge V. Neville-Neil }; 2486660df75eSGeorge V. Neville-Neil 2487f6e6460dSAdrian Chadd static struct pmc_event_alias mips74k_aliases[] = { 2488f6e6460dSAdrian Chadd EV_ALIAS("instructions", "INSTR_EXECUTED"), 2489f6e6460dSAdrian Chadd EV_ALIAS("branches", "BRANCH_INSNS"), 2490f6e6460dSAdrian Chadd EV_ALIAS("branch-mispredicts", "MISPREDICTED_BRANCH_INSNS"), 2491f6e6460dSAdrian Chadd EV_ALIAS(NULL, NULL) 2492f6e6460dSAdrian Chadd }; 2493f6e6460dSAdrian Chadd 2494c2657f80SOleksandr Tymoshenko static struct pmc_event_alias octeon_aliases[] = { 2495c2657f80SOleksandr Tymoshenko EV_ALIAS("instructions", "RET"), 2496c2657f80SOleksandr Tymoshenko EV_ALIAS("branches", "BR"), 2497c2657f80SOleksandr Tymoshenko EV_ALIAS("branch-mispredicts", "BRMIS"), 2498c2657f80SOleksandr Tymoshenko EV_ALIAS(NULL, NULL) 2499c2657f80SOleksandr Tymoshenko }; 2500c2657f80SOleksandr Tymoshenko 25012827d3e1SOleksandr Tymoshenko #define MIPS_KW_OS "os" 25022827d3e1SOleksandr Tymoshenko #define MIPS_KW_USR "usr" 25032827d3e1SOleksandr Tymoshenko #define MIPS_KW_ANYTHREAD "anythread" 2504660df75eSGeorge V. Neville-Neil 2505660df75eSGeorge V. Neville-Neil static int 25062827d3e1SOleksandr Tymoshenko mips_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 2507660df75eSGeorge V. Neville-Neil struct pmc_op_pmcallocate *pmc_config __unused) 2508660df75eSGeorge V. Neville-Neil { 2509660df75eSGeorge V. Neville-Neil char *p; 2510660df75eSGeorge V. Neville-Neil 2511660df75eSGeorge V. Neville-Neil (void) pe; 2512660df75eSGeorge V. Neville-Neil 2513660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2514660df75eSGeorge V. Neville-Neil 2515660df75eSGeorge V. Neville-Neil while ((p = strsep(&ctrspec, ",")) != NULL) { 25162827d3e1SOleksandr Tymoshenko if (KWMATCH(p, MIPS_KW_OS)) 2517660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= PMC_CAP_SYSTEM; 25182827d3e1SOleksandr Tymoshenko else if (KWMATCH(p, MIPS_KW_USR)) 2519660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= PMC_CAP_USER; 25202827d3e1SOleksandr Tymoshenko else if (KWMATCH(p, MIPS_KW_ANYTHREAD)) 2521660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= (PMC_CAP_USER | PMC_CAP_SYSTEM); 2522660df75eSGeorge V. Neville-Neil else 2523660df75eSGeorge V. Neville-Neil return (-1); 2524660df75eSGeorge V. Neville-Neil } 2525660df75eSGeorge V. Neville-Neil 2526660df75eSGeorge V. Neville-Neil return (0); 2527660df75eSGeorge V. Neville-Neil } 25282827d3e1SOleksandr Tymoshenko 2529660df75eSGeorge V. Neville-Neil #endif /* __mips__ */ 2530660df75eSGeorge V. Neville-Neil 25317b25dccaSJustin Hibbits #if defined(__powerpc__) 25327b25dccaSJustin Hibbits 25337b25dccaSJustin Hibbits static struct pmc_event_alias ppc7450_aliases[] = { 25347b25dccaSJustin Hibbits EV_ALIAS("instructions", "INSTR_COMPLETED"), 25357b25dccaSJustin Hibbits EV_ALIAS("branches", "BRANCHES_COMPLETED"), 25367b25dccaSJustin Hibbits EV_ALIAS("branch-mispredicts", "MISPREDICTED_BRANCHES"), 25377b25dccaSJustin Hibbits EV_ALIAS(NULL, NULL) 25387b25dccaSJustin Hibbits }; 25397b25dccaSJustin Hibbits 2540169dd953SJustin Hibbits static struct pmc_event_alias ppc970_aliases[] = { 2541169dd953SJustin Hibbits EV_ALIAS("instructions", "INSTR_COMPLETED"), 2542169dd953SJustin Hibbits EV_ALIAS("cycles", "CYCLES"), 2543169dd953SJustin Hibbits EV_ALIAS(NULL, NULL) 2544169dd953SJustin Hibbits }; 2545169dd953SJustin Hibbits 2546a7452468SJustin Hibbits static struct pmc_event_alias e500_aliases[] = { 2547a7452468SJustin Hibbits EV_ALIAS("instructions", "INSTR_COMPLETED"), 2548a7452468SJustin Hibbits EV_ALIAS("cycles", "CYCLES"), 2549a7452468SJustin Hibbits EV_ALIAS(NULL, NULL) 2550a7452468SJustin Hibbits }; 2551a7452468SJustin Hibbits 2552169dd953SJustin Hibbits #define POWERPC_KW_OS "os" 2553169dd953SJustin Hibbits #define POWERPC_KW_USR "usr" 2554169dd953SJustin Hibbits #define POWERPC_KW_ANYTHREAD "anythread" 25557b25dccaSJustin Hibbits 25567b25dccaSJustin Hibbits static int 2557169dd953SJustin Hibbits powerpc_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 25587b25dccaSJustin Hibbits struct pmc_op_pmcallocate *pmc_config __unused) 25597b25dccaSJustin Hibbits { 25607b25dccaSJustin Hibbits char *p; 25617b25dccaSJustin Hibbits 25627b25dccaSJustin Hibbits (void) pe; 25637b25dccaSJustin Hibbits 25647b25dccaSJustin Hibbits pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 25657b25dccaSJustin Hibbits 25667b25dccaSJustin Hibbits while ((p = strsep(&ctrspec, ",")) != NULL) { 2567169dd953SJustin Hibbits if (KWMATCH(p, POWERPC_KW_OS)) 25687b25dccaSJustin Hibbits pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2569169dd953SJustin Hibbits else if (KWMATCH(p, POWERPC_KW_USR)) 25707b25dccaSJustin Hibbits pmc_config->pm_caps |= PMC_CAP_USER; 2571169dd953SJustin Hibbits else if (KWMATCH(p, POWERPC_KW_ANYTHREAD)) 25727b25dccaSJustin Hibbits pmc_config->pm_caps |= (PMC_CAP_USER | PMC_CAP_SYSTEM); 25737b25dccaSJustin Hibbits else 25747b25dccaSJustin Hibbits return (-1); 25757b25dccaSJustin Hibbits } 25767b25dccaSJustin Hibbits 25777b25dccaSJustin Hibbits return (0); 25787b25dccaSJustin Hibbits } 2579169dd953SJustin Hibbits 25807b25dccaSJustin Hibbits #endif /* __powerpc__ */ 25817b25dccaSJustin Hibbits 2582660df75eSGeorge V. Neville-Neil 2583789140c0SJoseph Koshy /* 2584789140c0SJoseph Koshy * Match an event name `name' with its canonical form. 2585789140c0SJoseph Koshy * 25860cfab8ddSJoseph Koshy * Matches are case insensitive and spaces, periods, underscores and 25870cfab8ddSJoseph Koshy * hyphen characters are considered to match each other. 2588789140c0SJoseph Koshy * 2589789140c0SJoseph Koshy * Returns 1 for a match, 0 otherwise. 2590789140c0SJoseph Koshy */ 2591789140c0SJoseph Koshy 2592789140c0SJoseph Koshy static int 2593789140c0SJoseph Koshy pmc_match_event_name(const char *name, const char *canonicalname) 2594789140c0SJoseph Koshy { 2595789140c0SJoseph Koshy int cc, nc; 2596789140c0SJoseph Koshy const unsigned char *c, *n; 2597789140c0SJoseph Koshy 2598789140c0SJoseph Koshy c = (const unsigned char *) canonicalname; 2599789140c0SJoseph Koshy n = (const unsigned char *) name; 2600789140c0SJoseph Koshy 2601789140c0SJoseph Koshy for (; (nc = *n) && (cc = *c); n++, c++) { 2602789140c0SJoseph Koshy 26030cfab8ddSJoseph Koshy if ((nc == ' ' || nc == '_' || nc == '-' || nc == '.') && 26040cfab8ddSJoseph Koshy (cc == ' ' || cc == '_' || cc == '-' || cc == '.')) 2605789140c0SJoseph Koshy continue; 2606789140c0SJoseph Koshy 26070cfab8ddSJoseph Koshy if (toupper(nc) == toupper(cc)) 2608789140c0SJoseph Koshy continue; 2609789140c0SJoseph Koshy 26100cfab8ddSJoseph Koshy 2611789140c0SJoseph Koshy return (0); 2612789140c0SJoseph Koshy } 2613789140c0SJoseph Koshy 2614789140c0SJoseph Koshy if (*n == '\0' && *c == '\0') 2615789140c0SJoseph Koshy return (1); 2616789140c0SJoseph Koshy 2617789140c0SJoseph Koshy return (0); 2618789140c0SJoseph Koshy } 2619789140c0SJoseph Koshy 2620789140c0SJoseph Koshy /* 2621789140c0SJoseph Koshy * Match an event name against all the event named supported by a 2622789140c0SJoseph Koshy * PMC class. 2623789140c0SJoseph Koshy * 2624789140c0SJoseph Koshy * Returns an event descriptor pointer on match or NULL otherwise. 2625789140c0SJoseph Koshy */ 2626789140c0SJoseph Koshy static const struct pmc_event_descr * 2627789140c0SJoseph Koshy pmc_match_event_class(const char *name, 2628789140c0SJoseph Koshy const struct pmc_class_descr *pcd) 2629789140c0SJoseph Koshy { 2630789140c0SJoseph Koshy size_t n; 2631789140c0SJoseph Koshy const struct pmc_event_descr *ev; 2632789140c0SJoseph Koshy 2633789140c0SJoseph Koshy ev = pcd->pm_evc_event_table; 2634789140c0SJoseph Koshy for (n = 0; n < pcd->pm_evc_event_table_size; n++, ev++) 2635789140c0SJoseph Koshy if (pmc_match_event_name(name, ev->pm_ev_name)) 2636789140c0SJoseph Koshy return (ev); 2637789140c0SJoseph Koshy 2638789140c0SJoseph Koshy return (NULL); 2639789140c0SJoseph Koshy } 2640789140c0SJoseph Koshy 2641789140c0SJoseph Koshy static int 2642789140c0SJoseph Koshy pmc_mdep_is_compatible_class(enum pmc_class pc) 2643789140c0SJoseph Koshy { 2644789140c0SJoseph Koshy size_t n; 2645789140c0SJoseph Koshy 2646789140c0SJoseph Koshy for (n = 0; n < pmc_mdep_class_list_size; n++) 2647789140c0SJoseph Koshy if (pmc_mdep_class_list[n] == pc) 2648789140c0SJoseph Koshy return (1); 2649789140c0SJoseph Koshy return (0); 2650789140c0SJoseph Koshy } 2651789140c0SJoseph Koshy 2652ebccf1e3SJoseph Koshy /* 2653ebccf1e3SJoseph Koshy * API entry points 2654ebccf1e3SJoseph Koshy */ 2655ebccf1e3SJoseph Koshy 2656ebccf1e3SJoseph Koshy int 2657ebccf1e3SJoseph Koshy pmc_allocate(const char *ctrspec, enum pmc_mode mode, 2658ebccf1e3SJoseph Koshy uint32_t flags, int cpu, pmc_id_t *pmcid) 2659ebccf1e3SJoseph Koshy { 2660789140c0SJoseph Koshy size_t n; 2661ebccf1e3SJoseph Koshy int retval; 2662ebccf1e3SJoseph Koshy char *r, *spec_copy; 2663ebccf1e3SJoseph Koshy const char *ctrname; 2664789140c0SJoseph Koshy const struct pmc_event_descr *ev; 2665789140c0SJoseph Koshy const struct pmc_event_alias *alias; 2666ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate pmc_config; 2667789140c0SJoseph Koshy const struct pmc_class_descr *pcd; 2668ebccf1e3SJoseph Koshy 2669ebccf1e3SJoseph Koshy spec_copy = NULL; 2670ebccf1e3SJoseph Koshy retval = -1; 2671ebccf1e3SJoseph Koshy 2672ebccf1e3SJoseph Koshy if (mode != PMC_MODE_SS && mode != PMC_MODE_TS && 2673ebccf1e3SJoseph Koshy mode != PMC_MODE_SC && mode != PMC_MODE_TC) { 2674ebccf1e3SJoseph Koshy errno = EINVAL; 2675ebccf1e3SJoseph Koshy goto out; 2676ebccf1e3SJoseph Koshy } 2677ebccf1e3SJoseph Koshy 2678ebccf1e3SJoseph Koshy /* replace an event alias with the canonical event specifier */ 2679ebccf1e3SJoseph Koshy if (pmc_mdep_event_aliases) 2680789140c0SJoseph Koshy for (alias = pmc_mdep_event_aliases; alias->pm_alias; alias++) 2681789140c0SJoseph Koshy if (!strcasecmp(ctrspec, alias->pm_alias)) { 2682789140c0SJoseph Koshy spec_copy = strdup(alias->pm_spec); 2683ebccf1e3SJoseph Koshy break; 2684ebccf1e3SJoseph Koshy } 2685ebccf1e3SJoseph Koshy 2686ebccf1e3SJoseph Koshy if (spec_copy == NULL) 2687ebccf1e3SJoseph Koshy spec_copy = strdup(ctrspec); 2688ebccf1e3SJoseph Koshy 2689ebccf1e3SJoseph Koshy r = spec_copy; 2690ebccf1e3SJoseph Koshy ctrname = strsep(&r, ","); 2691ebccf1e3SJoseph Koshy 2692789140c0SJoseph Koshy /* 2693789140c0SJoseph Koshy * If a explicit class prefix was given by the user, restrict the 2694789140c0SJoseph Koshy * search for the event to the specified PMC class. 2695789140c0SJoseph Koshy */ 2696789140c0SJoseph Koshy ev = NULL; 26970cfab8ddSJoseph Koshy for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) { 26980cfab8ddSJoseph Koshy pcd = pmc_class_table[n]; 2699789140c0SJoseph Koshy if (pmc_mdep_is_compatible_class(pcd->pm_evc_class) && 2700789140c0SJoseph Koshy strncasecmp(ctrname, pcd->pm_evc_name, 2701789140c0SJoseph Koshy pcd->pm_evc_name_size) == 0) { 2702789140c0SJoseph Koshy if ((ev = pmc_match_event_class(ctrname + 2703789140c0SJoseph Koshy pcd->pm_evc_name_size, pcd)) == NULL) { 2704789140c0SJoseph Koshy errno = EINVAL; 2705789140c0SJoseph Koshy goto out; 2706789140c0SJoseph Koshy } 2707ebccf1e3SJoseph Koshy break; 2708789140c0SJoseph Koshy } 2709789140c0SJoseph Koshy } 2710ebccf1e3SJoseph Koshy 2711789140c0SJoseph Koshy /* 2712789140c0SJoseph Koshy * Otherwise, search for this event in all compatible PMC 2713789140c0SJoseph Koshy * classes. 2714789140c0SJoseph Koshy */ 27150cfab8ddSJoseph Koshy for (n = 0; ev == NULL && n < PMC_CLASS_TABLE_SIZE; n++) { 27160cfab8ddSJoseph Koshy pcd = pmc_class_table[n]; 2717789140c0SJoseph Koshy if (pmc_mdep_is_compatible_class(pcd->pm_evc_class)) 2718789140c0SJoseph Koshy ev = pmc_match_event_class(ctrname, pcd); 2719789140c0SJoseph Koshy } 2720789140c0SJoseph Koshy 2721789140c0SJoseph Koshy if (ev == NULL) { 2722ebccf1e3SJoseph Koshy errno = EINVAL; 2723ebccf1e3SJoseph Koshy goto out; 2724ebccf1e3SJoseph Koshy } 2725ebccf1e3SJoseph Koshy 2726ebccf1e3SJoseph Koshy bzero(&pmc_config, sizeof(pmc_config)); 2727789140c0SJoseph Koshy pmc_config.pm_ev = ev->pm_ev_code; 2728789140c0SJoseph Koshy pmc_config.pm_class = pcd->pm_evc_class; 2729ebccf1e3SJoseph Koshy pmc_config.pm_cpu = cpu; 2730ebccf1e3SJoseph Koshy pmc_config.pm_mode = mode; 2731ebccf1e3SJoseph Koshy pmc_config.pm_flags = flags; 2732ebccf1e3SJoseph Koshy 2733ebccf1e3SJoseph Koshy if (PMC_IS_SAMPLING_MODE(mode)) 2734ebccf1e3SJoseph Koshy pmc_config.pm_caps |= PMC_CAP_INTERRUPT; 2735ebccf1e3SJoseph Koshy 2736789140c0SJoseph Koshy if (pcd->pm_evc_allocate_pmc(ev->pm_ev_code, r, &pmc_config) < 0) { 2737ebccf1e3SJoseph Koshy errno = EINVAL; 2738ebccf1e3SJoseph Koshy goto out; 2739ebccf1e3SJoseph Koshy } 2740ebccf1e3SJoseph Koshy 2741ebccf1e3SJoseph Koshy if (PMC_CALL(PMCALLOCATE, &pmc_config) < 0) 2742ebccf1e3SJoseph Koshy goto out; 2743ebccf1e3SJoseph Koshy 2744ebccf1e3SJoseph Koshy *pmcid = pmc_config.pm_pmcid; 2745ebccf1e3SJoseph Koshy 2746ebccf1e3SJoseph Koshy retval = 0; 2747ebccf1e3SJoseph Koshy 2748ebccf1e3SJoseph Koshy out: 2749ebccf1e3SJoseph Koshy if (spec_copy) 2750ebccf1e3SJoseph Koshy free(spec_copy); 2751ebccf1e3SJoseph Koshy 2752aa342b1fSJoseph Koshy return (retval); 2753ebccf1e3SJoseph Koshy } 2754ebccf1e3SJoseph Koshy 2755ebccf1e3SJoseph Koshy int 2756ebccf1e3SJoseph Koshy pmc_attach(pmc_id_t pmc, pid_t pid) 2757ebccf1e3SJoseph Koshy { 2758ebccf1e3SJoseph Koshy struct pmc_op_pmcattach pmc_attach_args; 2759ebccf1e3SJoseph Koshy 2760ebccf1e3SJoseph Koshy pmc_attach_args.pm_pmc = pmc; 2761ebccf1e3SJoseph Koshy pmc_attach_args.pm_pid = pid; 2762ebccf1e3SJoseph Koshy 2763aa342b1fSJoseph Koshy return (PMC_CALL(PMCATTACH, &pmc_attach_args)); 2764ebccf1e3SJoseph Koshy } 2765ebccf1e3SJoseph Koshy 2766ebccf1e3SJoseph Koshy int 2767c5153e19SJoseph Koshy pmc_capabilities(pmc_id_t pmcid, uint32_t *caps) 2768c5153e19SJoseph Koshy { 2769c5153e19SJoseph Koshy unsigned int i; 2770c5153e19SJoseph Koshy enum pmc_class cl; 2771c5153e19SJoseph Koshy 2772c5153e19SJoseph Koshy cl = PMC_ID_TO_CLASS(pmcid); 2773c5153e19SJoseph Koshy for (i = 0; i < cpu_info.pm_nclass; i++) 2774c5153e19SJoseph Koshy if (cpu_info.pm_classes[i].pm_class == cl) { 2775c5153e19SJoseph Koshy *caps = cpu_info.pm_classes[i].pm_caps; 2776aa342b1fSJoseph Koshy return (0); 2777c5153e19SJoseph Koshy } 2778484202faSJoseph Koshy errno = EINVAL; 2779484202faSJoseph Koshy return (-1); 2780c5153e19SJoseph Koshy } 2781c5153e19SJoseph Koshy 2782f263522aSJoseph Koshy int 2783f263522aSJoseph Koshy pmc_configure_logfile(int fd) 2784ebccf1e3SJoseph Koshy { 2785f263522aSJoseph Koshy struct pmc_op_configurelog cla; 2786f263522aSJoseph Koshy 2787f263522aSJoseph Koshy cla.pm_logfd = fd; 2788f263522aSJoseph Koshy if (PMC_CALL(CONFIGURELOG, &cla) < 0) 2789aa342b1fSJoseph Koshy return (-1); 2790aa342b1fSJoseph Koshy return (0); 2791ebccf1e3SJoseph Koshy } 2792ebccf1e3SJoseph Koshy 2793f263522aSJoseph Koshy int 2794f263522aSJoseph Koshy pmc_cpuinfo(const struct pmc_cpuinfo **pci) 2795ebccf1e3SJoseph Koshy { 2796f263522aSJoseph Koshy if (pmc_syscall == -1) { 2797f263522aSJoseph Koshy errno = ENXIO; 2798aa342b1fSJoseph Koshy return (-1); 2799ebccf1e3SJoseph Koshy } 2800ebccf1e3SJoseph Koshy 28011455fcd3SJoseph Koshy *pci = &cpu_info; 2802aa342b1fSJoseph Koshy return (0); 2803ebccf1e3SJoseph Koshy } 2804ebccf1e3SJoseph Koshy 2805f263522aSJoseph Koshy int 2806f263522aSJoseph Koshy pmc_detach(pmc_id_t pmc, pid_t pid) 2807ebccf1e3SJoseph Koshy { 2808f263522aSJoseph Koshy struct pmc_op_pmcattach pmc_detach_args; 2809ebccf1e3SJoseph Koshy 2810f263522aSJoseph Koshy pmc_detach_args.pm_pmc = pmc; 2811f263522aSJoseph Koshy pmc_detach_args.pm_pid = pid; 2812aa342b1fSJoseph Koshy return (PMC_CALL(PMCDETACH, &pmc_detach_args)); 2813ebccf1e3SJoseph Koshy } 2814ebccf1e3SJoseph Koshy 2815f263522aSJoseph Koshy int 2816f263522aSJoseph Koshy pmc_disable(int cpu, int pmc) 2817ebccf1e3SJoseph Koshy { 2818f263522aSJoseph Koshy struct pmc_op_pmcadmin ssa; 2819ebccf1e3SJoseph Koshy 2820f263522aSJoseph Koshy ssa.pm_cpu = cpu; 2821f263522aSJoseph Koshy ssa.pm_pmc = pmc; 2822f263522aSJoseph Koshy ssa.pm_state = PMC_STATE_DISABLED; 2823aa342b1fSJoseph Koshy return (PMC_CALL(PMCADMIN, &ssa)); 2824ebccf1e3SJoseph Koshy } 2825ebccf1e3SJoseph Koshy 2826f263522aSJoseph Koshy int 2827f263522aSJoseph Koshy pmc_enable(int cpu, int pmc) 2828ebccf1e3SJoseph Koshy { 2829f263522aSJoseph Koshy struct pmc_op_pmcadmin ssa; 2830ebccf1e3SJoseph Koshy 2831f263522aSJoseph Koshy ssa.pm_cpu = cpu; 2832f263522aSJoseph Koshy ssa.pm_pmc = pmc; 2833f263522aSJoseph Koshy ssa.pm_state = PMC_STATE_FREE; 2834aa342b1fSJoseph Koshy return (PMC_CALL(PMCADMIN, &ssa)); 2835ebccf1e3SJoseph Koshy } 2836ebccf1e3SJoseph Koshy 2837ebccf1e3SJoseph Koshy /* 2838ebccf1e3SJoseph Koshy * Return a list of events known to a given PMC class. 'cl' is the 2839ebccf1e3SJoseph Koshy * PMC class identifier, 'eventnames' is the returned list of 'const 2840ebccf1e3SJoseph Koshy * char *' pointers pointing to the names of the events. 'nevents' is 2841ebccf1e3SJoseph Koshy * the number of event name pointers returned. 2842ebccf1e3SJoseph Koshy * 2843ebccf1e3SJoseph Koshy * The space for 'eventnames' is allocated using malloc(3). The caller 2844ebccf1e3SJoseph Koshy * is responsible for freeing this space when done. 2845ebccf1e3SJoseph Koshy */ 2846ebccf1e3SJoseph Koshy int 2847ebccf1e3SJoseph Koshy pmc_event_names_of_class(enum pmc_class cl, const char ***eventnames, 2848ebccf1e3SJoseph Koshy int *nevents) 2849ebccf1e3SJoseph Koshy { 2850ebccf1e3SJoseph Koshy int count; 2851ebccf1e3SJoseph Koshy const char **names; 2852ebccf1e3SJoseph Koshy const struct pmc_event_descr *ev; 2853ebccf1e3SJoseph Koshy 2854ebccf1e3SJoseph Koshy switch (cl) 2855ebccf1e3SJoseph Koshy { 28560cfab8ddSJoseph Koshy case PMC_CLASS_IAF: 28570cfab8ddSJoseph Koshy ev = iaf_event_table; 28580cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(iaf); 28590cfab8ddSJoseph Koshy break; 28600cfab8ddSJoseph Koshy case PMC_CLASS_IAP: 28610cfab8ddSJoseph Koshy /* 28620cfab8ddSJoseph Koshy * Return the most appropriate set of event name 28630cfab8ddSJoseph Koshy * spellings for the current CPU. 28640cfab8ddSJoseph Koshy */ 28650cfab8ddSJoseph Koshy switch (cpu_info.pm_cputype) { 28660cfab8ddSJoseph Koshy default: 28670cfab8ddSJoseph Koshy case PMC_CPU_INTEL_ATOM: 28680cfab8ddSJoseph Koshy ev = atom_event_table; 28690cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(atom); 28700cfab8ddSJoseph Koshy break; 2871e8f021a3SHiren Panchasara case PMC_CPU_INTEL_ATOM_SILVERMONT: 2872e8f021a3SHiren Panchasara ev = atom_silvermont_event_table; 2873e8f021a3SHiren Panchasara count = PMC_EVENT_TABLE_SIZE(atom_silvermont); 2874e8f021a3SHiren Panchasara break; 28750cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE: 28760cfab8ddSJoseph Koshy ev = core_event_table; 28770cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(core); 28780cfab8ddSJoseph Koshy break; 28790cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE2: 2880b4d091f3SJoseph Koshy case PMC_CPU_INTEL_CORE2EXTREME: 28810cfab8ddSJoseph Koshy ev = core2_event_table; 28820cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(core2); 28830cfab8ddSJoseph Koshy break; 2884597979c4SJeff Roberson case PMC_CPU_INTEL_COREI7: 2885597979c4SJeff Roberson ev = corei7_event_table; 2886597979c4SJeff Roberson count = PMC_EVENT_TABLE_SIZE(corei7); 2887597979c4SJeff Roberson break; 288849fe48abSKonstantin Belousov case PMC_CPU_INTEL_NEHALEM_EX: 288949fe48abSKonstantin Belousov ev = nehalem_ex_event_table; 289049fe48abSKonstantin Belousov count = PMC_EVENT_TABLE_SIZE(nehalem_ex); 289149fe48abSKonstantin Belousov break; 2892cc0c1555SSean Bruno case PMC_CPU_INTEL_HASWELL: 2893cc0c1555SSean Bruno ev = haswell_event_table; 2894cc0c1555SSean Bruno count = PMC_EVENT_TABLE_SIZE(haswell); 2895cc0c1555SSean Bruno break; 2896d95b3509SRandall Stewart case PMC_CPU_INTEL_HASWELL_XEON: 2897d95b3509SRandall Stewart ev = haswell_xeon_event_table; 2898d95b3509SRandall Stewart count = PMC_EVENT_TABLE_SIZE(haswell_xeon); 2899d95b3509SRandall Stewart break; 29001e862e5aSFabien Thomas case PMC_CPU_INTEL_IVYBRIDGE: 29011e862e5aSFabien Thomas ev = ivybridge_event_table; 29021e862e5aSFabien Thomas count = PMC_EVENT_TABLE_SIZE(ivybridge); 29031e862e5aSFabien Thomas break; 29043f929d8cSSean Bruno case PMC_CPU_INTEL_IVYBRIDGE_XEON: 29053f929d8cSSean Bruno ev = ivybridge_xeon_event_table; 29063f929d8cSSean Bruno count = PMC_EVENT_TABLE_SIZE(ivybridge_xeon); 29073f929d8cSSean Bruno break; 290878d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 290978d763a2SDavide Italiano ev = sandybridge_event_table; 291078d763a2SDavide Italiano count = PMC_EVENT_TABLE_SIZE(sandybridge); 291178d763a2SDavide Italiano break; 2912fabe02f5SSean Bruno case PMC_CPU_INTEL_SANDYBRIDGE_XEON: 2913fabe02f5SSean Bruno ev = sandybridge_xeon_event_table; 2914fabe02f5SSean Bruno count = PMC_EVENT_TABLE_SIZE(sandybridge_xeon); 2915fabe02f5SSean Bruno break; 29161fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 29171fa7f10bSFabien Thomas ev = westmere_event_table; 29181fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(westmere); 29191fa7f10bSFabien Thomas break; 292049fe48abSKonstantin Belousov case PMC_CPU_INTEL_WESTMERE_EX: 292149fe48abSKonstantin Belousov ev = westmere_ex_event_table; 292249fe48abSKonstantin Belousov count = PMC_EVENT_TABLE_SIZE(westmere_ex); 292349fe48abSKonstantin Belousov break; 29241fa7f10bSFabien Thomas } 29251fa7f10bSFabien Thomas break; 29261fa7f10bSFabien Thomas case PMC_CLASS_UCF: 29271fa7f10bSFabien Thomas ev = ucf_event_table; 29281fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(ucf); 29291fa7f10bSFabien Thomas break; 29301fa7f10bSFabien Thomas case PMC_CLASS_UCP: 29311fa7f10bSFabien Thomas /* 29321fa7f10bSFabien Thomas * Return the most appropriate set of event name 29331fa7f10bSFabien Thomas * spellings for the current CPU. 29341fa7f10bSFabien Thomas */ 29351fa7f10bSFabien Thomas switch (cpu_info.pm_cputype) { 29361fa7f10bSFabien Thomas default: 29371fa7f10bSFabien Thomas case PMC_CPU_INTEL_COREI7: 29381fa7f10bSFabien Thomas ev = corei7uc_event_table; 29391fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(corei7uc); 29401fa7f10bSFabien Thomas break; 2941cc0c1555SSean Bruno case PMC_CPU_INTEL_HASWELL: 2942cc0c1555SSean Bruno ev = haswelluc_event_table; 2943cc0c1555SSean Bruno count = PMC_EVENT_TABLE_SIZE(haswelluc); 2944cc0c1555SSean Bruno break; 294578d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 294678d763a2SDavide Italiano ev = sandybridgeuc_event_table; 294778d763a2SDavide Italiano count = PMC_EVENT_TABLE_SIZE(sandybridgeuc); 294878d763a2SDavide Italiano break; 29491fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 29501fa7f10bSFabien Thomas ev = westmereuc_event_table; 29511fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(westmereuc); 29521fa7f10bSFabien Thomas break; 29530cfab8ddSJoseph Koshy } 29540cfab8ddSJoseph Koshy break; 2955ebccf1e3SJoseph Koshy case PMC_CLASS_TSC: 2956789140c0SJoseph Koshy ev = tsc_event_table; 2957789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(tsc); 2958ebccf1e3SJoseph Koshy break; 2959ebccf1e3SJoseph Koshy case PMC_CLASS_K7: 2960789140c0SJoseph Koshy ev = k7_event_table; 2961789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(k7); 2962ebccf1e3SJoseph Koshy break; 2963ebccf1e3SJoseph Koshy case PMC_CLASS_K8: 2964789140c0SJoseph Koshy ev = k8_event_table; 2965789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(k8); 2966ebccf1e3SJoseph Koshy break; 2967ebccf1e3SJoseph Koshy case PMC_CLASS_P4: 2968789140c0SJoseph Koshy ev = p4_event_table; 2969789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p4); 2970789140c0SJoseph Koshy break; 2971789140c0SJoseph Koshy case PMC_CLASS_P5: 2972789140c0SJoseph Koshy ev = p5_event_table; 2973789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p5); 2974789140c0SJoseph Koshy break; 2975789140c0SJoseph Koshy case PMC_CLASS_P6: 2976789140c0SJoseph Koshy ev = p6_event_table; 2977789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p6); 2978ebccf1e3SJoseph Koshy break; 29790ce207d2SRui Paulo case PMC_CLASS_XSCALE: 29800ce207d2SRui Paulo ev = xscale_event_table; 29810ce207d2SRui Paulo count = PMC_EVENT_TABLE_SIZE(xscale); 29820ce207d2SRui Paulo break; 29836411d14dSRuslan Bukin case PMC_CLASS_ARMV7: 29846411d14dSRuslan Bukin ev = armv7_event_table; 29856411d14dSRuslan Bukin count = PMC_EVENT_TABLE_SIZE(armv7); 29866411d14dSRuslan Bukin break; 2987bc88bb2bSRuslan Bukin case PMC_CLASS_ARMV8: 2988bc88bb2bSRuslan Bukin switch (cpu_info.pm_cputype) { 2989bc88bb2bSRuslan Bukin default: 2990bc88bb2bSRuslan Bukin case PMC_CPU_ARMV8_CORTEX_A53: 2991bc88bb2bSRuslan Bukin ev = cortex_a53_event_table; 2992bc88bb2bSRuslan Bukin count = PMC_EVENT_TABLE_SIZE(cortex_a53); 2993bc88bb2bSRuslan Bukin break; 2994bc88bb2bSRuslan Bukin case PMC_CPU_ARMV8_CORTEX_A57: 2995bc88bb2bSRuslan Bukin ev = cortex_a57_event_table; 2996bc88bb2bSRuslan Bukin count = PMC_EVENT_TABLE_SIZE(cortex_a57); 2997bc88bb2bSRuslan Bukin break; 2998bc88bb2bSRuslan Bukin } 2999bc88bb2bSRuslan Bukin break; 3000660df75eSGeorge V. Neville-Neil case PMC_CLASS_MIPS24K: 3001660df75eSGeorge V. Neville-Neil ev = mips24k_event_table; 3002660df75eSGeorge V. Neville-Neil count = PMC_EVENT_TABLE_SIZE(mips24k); 3003660df75eSGeorge V. Neville-Neil break; 3004f6e6460dSAdrian Chadd case PMC_CLASS_MIPS74K: 3005f6e6460dSAdrian Chadd ev = mips74k_event_table; 3006f6e6460dSAdrian Chadd count = PMC_EVENT_TABLE_SIZE(mips74k); 3007f6e6460dSAdrian Chadd break; 3008c2657f80SOleksandr Tymoshenko case PMC_CLASS_OCTEON: 3009c2657f80SOleksandr Tymoshenko ev = octeon_event_table; 3010c2657f80SOleksandr Tymoshenko count = PMC_EVENT_TABLE_SIZE(octeon); 3011c2657f80SOleksandr Tymoshenko break; 30127b25dccaSJustin Hibbits case PMC_CLASS_PPC7450: 30137b25dccaSJustin Hibbits ev = ppc7450_event_table; 30147b25dccaSJustin Hibbits count = PMC_EVENT_TABLE_SIZE(ppc7450); 30157b25dccaSJustin Hibbits break; 3016169dd953SJustin Hibbits case PMC_CLASS_PPC970: 3017169dd953SJustin Hibbits ev = ppc970_event_table; 3018169dd953SJustin Hibbits count = PMC_EVENT_TABLE_SIZE(ppc970); 3019169dd953SJustin Hibbits break; 3020a7452468SJustin Hibbits case PMC_CLASS_E500: 3021a7452468SJustin Hibbits ev = e500_event_table; 3022a7452468SJustin Hibbits count = PMC_EVENT_TABLE_SIZE(e500); 3023a7452468SJustin Hibbits break; 3024f5f9340bSFabien Thomas case PMC_CLASS_SOFT: 3025f5f9340bSFabien Thomas ev = soft_event_table; 3026f5f9340bSFabien Thomas count = soft_event_info.pm_nevent; 3027f5f9340bSFabien Thomas break; 3028ebccf1e3SJoseph Koshy default: 3029ebccf1e3SJoseph Koshy errno = EINVAL; 3030aa342b1fSJoseph Koshy return (-1); 3031ebccf1e3SJoseph Koshy } 3032ebccf1e3SJoseph Koshy 3033ebccf1e3SJoseph Koshy if ((names = malloc(count * sizeof(const char *))) == NULL) 3034aa342b1fSJoseph Koshy return (-1); 3035ebccf1e3SJoseph Koshy 3036ebccf1e3SJoseph Koshy *eventnames = names; 3037ebccf1e3SJoseph Koshy *nevents = count; 3038ebccf1e3SJoseph Koshy 3039ebccf1e3SJoseph Koshy for (;count--; ev++, names++) 3040ebccf1e3SJoseph Koshy *names = ev->pm_ev_name; 3041f5f9340bSFabien Thomas 3042aa342b1fSJoseph Koshy return (0); 3043ebccf1e3SJoseph Koshy } 3044ebccf1e3SJoseph Koshy 3045f263522aSJoseph Koshy int 3046f263522aSJoseph Koshy pmc_flush_logfile(void) 3047f263522aSJoseph Koshy { 3048aa342b1fSJoseph Koshy return (PMC_CALL(FLUSHLOG,0)); 3049f263522aSJoseph Koshy } 3050ebccf1e3SJoseph Koshy 3051ebccf1e3SJoseph Koshy int 3052dceed24aSFabien Thomas pmc_close_logfile(void) 3053dceed24aSFabien Thomas { 3054dceed24aSFabien Thomas return (PMC_CALL(CLOSELOG,0)); 3055dceed24aSFabien Thomas } 3056dceed24aSFabien Thomas 3057dceed24aSFabien Thomas int 3058f263522aSJoseph Koshy pmc_get_driver_stats(struct pmc_driverstats *ds) 3059ebccf1e3SJoseph Koshy { 3060f263522aSJoseph Koshy struct pmc_op_getdriverstats gms; 3061f263522aSJoseph Koshy 3062f263522aSJoseph Koshy if (PMC_CALL(GETDRIVERSTATS, &gms) < 0) 3063aa342b1fSJoseph Koshy return (-1); 3064f263522aSJoseph Koshy 3065f263522aSJoseph Koshy /* copy out fields in the current userland<->library interface */ 3066f263522aSJoseph Koshy ds->pm_intr_ignored = gms.pm_intr_ignored; 3067f263522aSJoseph Koshy ds->pm_intr_processed = gms.pm_intr_processed; 3068f263522aSJoseph Koshy ds->pm_intr_bufferfull = gms.pm_intr_bufferfull; 3069f263522aSJoseph Koshy ds->pm_syscalls = gms.pm_syscalls; 3070f263522aSJoseph Koshy ds->pm_syscall_errors = gms.pm_syscall_errors; 3071f263522aSJoseph Koshy ds->pm_buffer_requests = gms.pm_buffer_requests; 3072f263522aSJoseph Koshy ds->pm_buffer_requests_failed = gms.pm_buffer_requests_failed; 3073f263522aSJoseph Koshy ds->pm_log_sweeps = gms.pm_log_sweeps; 3074aa342b1fSJoseph Koshy return (0); 3075f263522aSJoseph Koshy } 3076f263522aSJoseph Koshy 3077f263522aSJoseph Koshy int 3078f263522aSJoseph Koshy pmc_get_msr(pmc_id_t pmc, uint32_t *msr) 3079f263522aSJoseph Koshy { 3080f263522aSJoseph Koshy struct pmc_op_getmsr gm; 3081ebccf1e3SJoseph Koshy 3082ebccf1e3SJoseph Koshy gm.pm_pmcid = pmc; 3083f263522aSJoseph Koshy if (PMC_CALL(PMCGETMSR, &gm) < 0) 3084aa342b1fSJoseph Koshy return (-1); 3085ebccf1e3SJoseph Koshy *msr = gm.pm_msr; 3086aa342b1fSJoseph Koshy return (0); 3087ebccf1e3SJoseph Koshy } 3088ebccf1e3SJoseph Koshy 3089f263522aSJoseph Koshy int 3090f263522aSJoseph Koshy pmc_init(void) 3091f263522aSJoseph Koshy { 3092f263522aSJoseph Koshy int error, pmc_mod_id; 30931455fcd3SJoseph Koshy unsigned int n; 3094f263522aSJoseph Koshy uint32_t abi_version; 3095f263522aSJoseph Koshy struct module_stat pmc_modstat; 30961455fcd3SJoseph Koshy struct pmc_op_getcpuinfo op_cpu_info; 3097791f5d5bSJoseph Koshy #if defined(__amd64__) || defined(__i386__) 3098791f5d5bSJoseph Koshy int cpu_has_iaf_counters; 3099791f5d5bSJoseph Koshy unsigned int t; 3100791f5d5bSJoseph Koshy #endif 3101f263522aSJoseph Koshy 3102f263522aSJoseph Koshy if (pmc_syscall != -1) /* already inited */ 3103aa342b1fSJoseph Koshy return (0); 3104f263522aSJoseph Koshy 3105f263522aSJoseph Koshy /* retrieve the system call number from the KLD */ 3106f263522aSJoseph Koshy if ((pmc_mod_id = modfind(PMC_MODULE_NAME)) < 0) 3107aa342b1fSJoseph Koshy return (-1); 3108f263522aSJoseph Koshy 3109f263522aSJoseph Koshy pmc_modstat.version = sizeof(struct module_stat); 3110f263522aSJoseph Koshy if ((error = modstat(pmc_mod_id, &pmc_modstat)) < 0) 3111aa342b1fSJoseph Koshy return (-1); 3112f263522aSJoseph Koshy 3113f263522aSJoseph Koshy pmc_syscall = pmc_modstat.data.intval; 3114f263522aSJoseph Koshy 3115f263522aSJoseph Koshy /* check the kernel module's ABI against our compiled-in version */ 3116f263522aSJoseph Koshy abi_version = PMC_VERSION; 3117f263522aSJoseph Koshy if (PMC_CALL(GETMODULEVERSION, &abi_version) < 0) 3118f263522aSJoseph Koshy return (pmc_syscall = -1); 3119f263522aSJoseph Koshy 3120f263522aSJoseph Koshy /* ignore patch & minor numbers for the comparision */ 3121f263522aSJoseph Koshy if ((abi_version & 0xFF000000) != (PMC_VERSION & 0xFF000000)) { 3122f263522aSJoseph Koshy errno = EPROGMISMATCH; 3123f263522aSJoseph Koshy return (pmc_syscall = -1); 3124f263522aSJoseph Koshy } 3125f263522aSJoseph Koshy 31261455fcd3SJoseph Koshy if (PMC_CALL(GETCPUINFO, &op_cpu_info) < 0) 3127f263522aSJoseph Koshy return (pmc_syscall = -1); 3128f263522aSJoseph Koshy 31291455fcd3SJoseph Koshy cpu_info.pm_cputype = op_cpu_info.pm_cputype; 31301455fcd3SJoseph Koshy cpu_info.pm_ncpu = op_cpu_info.pm_ncpu; 31311455fcd3SJoseph Koshy cpu_info.pm_npmc = op_cpu_info.pm_npmc; 31321455fcd3SJoseph Koshy cpu_info.pm_nclass = op_cpu_info.pm_nclass; 31331455fcd3SJoseph Koshy for (n = 0; n < cpu_info.pm_nclass; n++) 31341455fcd3SJoseph Koshy cpu_info.pm_classes[n] = op_cpu_info.pm_classes[n]; 31351455fcd3SJoseph Koshy 31360cfab8ddSJoseph Koshy pmc_class_table = malloc(PMC_CLASS_TABLE_SIZE * 31370cfab8ddSJoseph Koshy sizeof(struct pmc_class_descr *)); 31380cfab8ddSJoseph Koshy 31390cfab8ddSJoseph Koshy if (pmc_class_table == NULL) 31400cfab8ddSJoseph Koshy return (-1); 31410cfab8ddSJoseph Koshy 3142791f5d5bSJoseph Koshy for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) 3143791f5d5bSJoseph Koshy pmc_class_table[n] = NULL; 31440cfab8ddSJoseph Koshy 31450cfab8ddSJoseph Koshy /* 3146f5f9340bSFabien Thomas * Get soft events list. 3147f5f9340bSFabien Thomas */ 3148f5f9340bSFabien Thomas soft_event_info.pm_class = PMC_CLASS_SOFT; 3149f5f9340bSFabien Thomas if (PMC_CALL(GETDYNEVENTINFO, &soft_event_info) < 0) 3150f5f9340bSFabien Thomas return (pmc_syscall = -1); 3151f5f9340bSFabien Thomas 3152f5f9340bSFabien Thomas /* Map soft events to static list. */ 3153f5f9340bSFabien Thomas for (n = 0; n < soft_event_info.pm_nevent; n++) { 3154f5f9340bSFabien Thomas soft_event_table[n].pm_ev_name = 3155f5f9340bSFabien Thomas soft_event_info.pm_events[n].pm_ev_name; 3156f5f9340bSFabien Thomas soft_event_table[n].pm_ev_code = 3157f5f9340bSFabien Thomas soft_event_info.pm_events[n].pm_ev_code; 3158f5f9340bSFabien Thomas } 3159f5f9340bSFabien Thomas soft_class_table_descr.pm_evc_event_table_size = \ 3160f5f9340bSFabien Thomas soft_event_info.pm_nevent; 3161f5f9340bSFabien Thomas soft_class_table_descr.pm_evc_event_table = \ 3162f5f9340bSFabien Thomas soft_event_table; 3163f5f9340bSFabien Thomas 3164f5f9340bSFabien Thomas /* 31650cfab8ddSJoseph Koshy * Fill in the class table. 31660cfab8ddSJoseph Koshy */ 31670cfab8ddSJoseph Koshy n = 0; 3168f5f9340bSFabien Thomas 3169f5f9340bSFabien Thomas /* Fill soft events information. */ 3170f5f9340bSFabien Thomas pmc_class_table[n++] = &soft_class_table_descr; 31710cfab8ddSJoseph Koshy #if defined(__amd64__) || defined(__i386__) 3172f5f9340bSFabien Thomas if (cpu_info.pm_cputype != PMC_CPU_GENERIC) 31730cfab8ddSJoseph Koshy pmc_class_table[n++] = &tsc_class_table_descr; 3174791f5d5bSJoseph Koshy 3175791f5d5bSJoseph Koshy /* 3176791f5d5bSJoseph Koshy * Check if this CPU has fixed function counters. 3177791f5d5bSJoseph Koshy */ 3178791f5d5bSJoseph Koshy cpu_has_iaf_counters = 0; 3179791f5d5bSJoseph Koshy for (t = 0; t < cpu_info.pm_nclass; t++) 31802aef9dd6SFabien Thomas if (cpu_info.pm_classes[t].pm_class == PMC_CLASS_IAF && 31812aef9dd6SFabien Thomas cpu_info.pm_classes[t].pm_num > 0) 3182791f5d5bSJoseph Koshy cpu_has_iaf_counters = 1; 31830cfab8ddSJoseph Koshy #endif 31840cfab8ddSJoseph Koshy 3185789140c0SJoseph Koshy #define PMC_MDEP_INIT(C) do { \ 3186789140c0SJoseph Koshy pmc_mdep_event_aliases = C##_aliases; \ 3187789140c0SJoseph Koshy pmc_mdep_class_list = C##_pmc_classes; \ 3188789140c0SJoseph Koshy pmc_mdep_class_list_size = \ 3189789140c0SJoseph Koshy PMC_TABLE_SIZE(C##_pmc_classes); \ 3190789140c0SJoseph Koshy } while (0) 3191789140c0SJoseph Koshy 3192791f5d5bSJoseph Koshy #define PMC_MDEP_INIT_INTEL_V2(C) do { \ 3193791f5d5bSJoseph Koshy PMC_MDEP_INIT(C); \ 3194791f5d5bSJoseph Koshy pmc_class_table[n++] = &iaf_class_table_descr; \ 31952aef9dd6SFabien Thomas if (!cpu_has_iaf_counters) \ 3196791f5d5bSJoseph Koshy pmc_mdep_event_aliases = \ 3197791f5d5bSJoseph Koshy C##_aliases_without_iaf; \ 3198791f5d5bSJoseph Koshy pmc_class_table[n] = &C##_class_table_descr; \ 3199791f5d5bSJoseph Koshy } while (0) 3200791f5d5bSJoseph Koshy 3201789140c0SJoseph Koshy /* Configure the event name parser. */ 3202f263522aSJoseph Koshy switch (cpu_info.pm_cputype) { 3203f263522aSJoseph Koshy #if defined(__i386__) 3204f263522aSJoseph Koshy case PMC_CPU_AMD_K7: 3205789140c0SJoseph Koshy PMC_MDEP_INIT(k7); 32060cfab8ddSJoseph Koshy pmc_class_table[n] = &k7_class_table_descr; 3207f263522aSJoseph Koshy break; 3208f263522aSJoseph Koshy case PMC_CPU_INTEL_P5: 3209789140c0SJoseph Koshy PMC_MDEP_INIT(p5); 32100cfab8ddSJoseph Koshy pmc_class_table[n] = &p5_class_table_descr; 3211f263522aSJoseph Koshy break; 3212f263522aSJoseph Koshy case PMC_CPU_INTEL_P6: /* P6 ... Pentium M CPUs have */ 3213f263522aSJoseph Koshy case PMC_CPU_INTEL_PII: /* similar PMCs. */ 3214f263522aSJoseph Koshy case PMC_CPU_INTEL_PIII: 3215f263522aSJoseph Koshy case PMC_CPU_INTEL_PM: 3216789140c0SJoseph Koshy PMC_MDEP_INIT(p6); 32170cfab8ddSJoseph Koshy pmc_class_table[n] = &p6_class_table_descr; 3218f263522aSJoseph Koshy break; 321986a65549SJoseph Koshy #endif 322086a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 3221f263522aSJoseph Koshy case PMC_CPU_AMD_K8: 3222789140c0SJoseph Koshy PMC_MDEP_INIT(k8); 32230cfab8ddSJoseph Koshy pmc_class_table[n] = &k8_class_table_descr; 32240cfab8ddSJoseph Koshy break; 32250cfab8ddSJoseph Koshy case PMC_CPU_INTEL_ATOM: 3226791f5d5bSJoseph Koshy PMC_MDEP_INIT_INTEL_V2(atom); 32270cfab8ddSJoseph Koshy break; 3228e8f021a3SHiren Panchasara case PMC_CPU_INTEL_ATOM_SILVERMONT: 3229e8f021a3SHiren Panchasara PMC_MDEP_INIT_INTEL_V2(atom_silvermont); 3230e8f021a3SHiren Panchasara break; 32310cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE: 32320cfab8ddSJoseph Koshy PMC_MDEP_INIT(core); 3233bc315bbdSJoseph Koshy pmc_class_table[n] = &core_class_table_descr; 32340cfab8ddSJoseph Koshy break; 32350cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE2: 3236b4d091f3SJoseph Koshy case PMC_CPU_INTEL_CORE2EXTREME: 3237791f5d5bSJoseph Koshy PMC_MDEP_INIT_INTEL_V2(core2); 3238789140c0SJoseph Koshy break; 3239597979c4SJeff Roberson case PMC_CPU_INTEL_COREI7: 32401fa7f10bSFabien Thomas pmc_class_table[n++] = &ucf_class_table_descr; 32411fa7f10bSFabien Thomas pmc_class_table[n++] = &corei7uc_class_table_descr; 3242791f5d5bSJoseph Koshy PMC_MDEP_INIT_INTEL_V2(corei7); 3243597979c4SJeff Roberson break; 324449fe48abSKonstantin Belousov case PMC_CPU_INTEL_NEHALEM_EX: 324549fe48abSKonstantin Belousov PMC_MDEP_INIT_INTEL_V2(nehalem_ex); 324649fe48abSKonstantin Belousov break; 3247cc0c1555SSean Bruno case PMC_CPU_INTEL_HASWELL: 3248cc0c1555SSean Bruno pmc_class_table[n++] = &ucf_class_table_descr; 3249cc0c1555SSean Bruno pmc_class_table[n++] = &haswelluc_class_table_descr; 3250cc0c1555SSean Bruno PMC_MDEP_INIT_INTEL_V2(haswell); 3251cc0c1555SSean Bruno break; 3252d95b3509SRandall Stewart case PMC_CPU_INTEL_HASWELL_XEON: 3253d95b3509SRandall Stewart PMC_MDEP_INIT_INTEL_V2(haswell_xeon); 3254d95b3509SRandall Stewart break; 32551e862e5aSFabien Thomas case PMC_CPU_INTEL_IVYBRIDGE: 32561e862e5aSFabien Thomas PMC_MDEP_INIT_INTEL_V2(ivybridge); 32571e862e5aSFabien Thomas break; 32583f929d8cSSean Bruno case PMC_CPU_INTEL_IVYBRIDGE_XEON: 32593f929d8cSSean Bruno PMC_MDEP_INIT_INTEL_V2(ivybridge_xeon); 32603f929d8cSSean Bruno break; 326178d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 326278d763a2SDavide Italiano pmc_class_table[n++] = &ucf_class_table_descr; 326378d763a2SDavide Italiano pmc_class_table[n++] = &sandybridgeuc_class_table_descr; 326478d763a2SDavide Italiano PMC_MDEP_INIT_INTEL_V2(sandybridge); 326578d763a2SDavide Italiano break; 3266fabe02f5SSean Bruno case PMC_CPU_INTEL_SANDYBRIDGE_XEON: 3267fabe02f5SSean Bruno PMC_MDEP_INIT_INTEL_V2(sandybridge_xeon); 3268fabe02f5SSean Bruno break; 32691fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 32701fa7f10bSFabien Thomas pmc_class_table[n++] = &ucf_class_table_descr; 32711fa7f10bSFabien Thomas pmc_class_table[n++] = &westmereuc_class_table_descr; 32721fa7f10bSFabien Thomas PMC_MDEP_INIT_INTEL_V2(westmere); 32731fa7f10bSFabien Thomas break; 327449fe48abSKonstantin Belousov case PMC_CPU_INTEL_WESTMERE_EX: 327549fe48abSKonstantin Belousov PMC_MDEP_INIT_INTEL_V2(westmere_ex); 327649fe48abSKonstantin Belousov break; 3277789140c0SJoseph Koshy case PMC_CPU_INTEL_PIV: 3278789140c0SJoseph Koshy PMC_MDEP_INIT(p4); 32790cfab8ddSJoseph Koshy pmc_class_table[n] = &p4_class_table_descr; 3280f263522aSJoseph Koshy break; 3281ebccf1e3SJoseph Koshy #endif 3282f5f9340bSFabien Thomas case PMC_CPU_GENERIC: 3283f5f9340bSFabien Thomas PMC_MDEP_INIT(generic); 3284f5f9340bSFabien Thomas break; 32856411d14dSRuslan Bukin #if defined(__arm__) 32860ce207d2SRui Paulo #if defined(__XSCALE__) 32870ce207d2SRui Paulo case PMC_CPU_INTEL_XSCALE: 32880ce207d2SRui Paulo PMC_MDEP_INIT(xscale); 32890ce207d2SRui Paulo pmc_class_table[n] = &xscale_class_table_descr; 32900ce207d2SRui Paulo break; 32910ce207d2SRui Paulo #endif 32926411d14dSRuslan Bukin case PMC_CPU_ARMV7: 32936411d14dSRuslan Bukin PMC_MDEP_INIT(armv7); 32946411d14dSRuslan Bukin pmc_class_table[n] = &armv7_class_table_descr; 32956411d14dSRuslan Bukin break; 32966411d14dSRuslan Bukin #endif 3297bc88bb2bSRuslan Bukin #if defined(__aarch64__) 3298bc88bb2bSRuslan Bukin case PMC_CPU_ARMV8_CORTEX_A53: 3299bc88bb2bSRuslan Bukin PMC_MDEP_INIT(cortex_a53); 3300bc88bb2bSRuslan Bukin pmc_class_table[n] = &cortex_a53_class_table_descr; 3301bc88bb2bSRuslan Bukin break; 3302bc88bb2bSRuslan Bukin case PMC_CPU_ARMV8_CORTEX_A57: 3303bc88bb2bSRuslan Bukin PMC_MDEP_INIT(cortex_a57); 3304bc88bb2bSRuslan Bukin pmc_class_table[n] = &cortex_a57_class_table_descr; 3305bc88bb2bSRuslan Bukin break; 3306bc88bb2bSRuslan Bukin #endif 3307660df75eSGeorge V. Neville-Neil #if defined(__mips__) 3308660df75eSGeorge V. Neville-Neil case PMC_CPU_MIPS_24K: 3309660df75eSGeorge V. Neville-Neil PMC_MDEP_INIT(mips24k); 3310660df75eSGeorge V. Neville-Neil pmc_class_table[n] = &mips24k_class_table_descr; 3311660df75eSGeorge V. Neville-Neil break; 3312f6e6460dSAdrian Chadd case PMC_CPU_MIPS_74K: 3313f6e6460dSAdrian Chadd PMC_MDEP_INIT(mips74k); 3314f6e6460dSAdrian Chadd pmc_class_table[n] = &mips74k_class_table_descr; 3315f6e6460dSAdrian Chadd break; 3316c2657f80SOleksandr Tymoshenko case PMC_CPU_MIPS_OCTEON: 3317c2657f80SOleksandr Tymoshenko PMC_MDEP_INIT(octeon); 3318c2657f80SOleksandr Tymoshenko pmc_class_table[n] = &octeon_class_table_descr; 3319c2657f80SOleksandr Tymoshenko break; 3320660df75eSGeorge V. Neville-Neil #endif /* __mips__ */ 33217b25dccaSJustin Hibbits #if defined(__powerpc__) 33227b25dccaSJustin Hibbits case PMC_CPU_PPC_7450: 33237b25dccaSJustin Hibbits PMC_MDEP_INIT(ppc7450); 33247b25dccaSJustin Hibbits pmc_class_table[n] = &ppc7450_class_table_descr; 33257b25dccaSJustin Hibbits break; 3326169dd953SJustin Hibbits case PMC_CPU_PPC_970: 3327169dd953SJustin Hibbits PMC_MDEP_INIT(ppc970); 3328169dd953SJustin Hibbits pmc_class_table[n] = &ppc970_class_table_descr; 3329169dd953SJustin Hibbits break; 3330a7452468SJustin Hibbits case PMC_CPU_PPC_E500: 3331a7452468SJustin Hibbits PMC_MDEP_INIT(e500); 3332a7452468SJustin Hibbits pmc_class_table[n] = &e500_class_table_descr; 3333a7452468SJustin Hibbits break; 33347b25dccaSJustin Hibbits #endif 3335f263522aSJoseph Koshy default: 3336f263522aSJoseph Koshy /* 3337f263522aSJoseph Koshy * Some kind of CPU this version of the library knows nothing 3338f263522aSJoseph Koshy * about. This shouldn't happen since the abi version check 3339f263522aSJoseph Koshy * should have caught this. 3340f263522aSJoseph Koshy */ 3341f263522aSJoseph Koshy errno = ENXIO; 3342f263522aSJoseph Koshy return (pmc_syscall = -1); 3343f263522aSJoseph Koshy } 3344f263522aSJoseph Koshy 3345aa342b1fSJoseph Koshy return (0); 3346f263522aSJoseph Koshy } 3347f263522aSJoseph Koshy 3348f263522aSJoseph Koshy const char * 3349f263522aSJoseph Koshy pmc_name_of_capability(enum pmc_caps cap) 3350f263522aSJoseph Koshy { 3351f263522aSJoseph Koshy int i; 3352f263522aSJoseph Koshy 3353f263522aSJoseph Koshy /* 3354f263522aSJoseph Koshy * 'cap' should have a single bit set and should be in 3355f263522aSJoseph Koshy * range. 3356f263522aSJoseph Koshy */ 3357f263522aSJoseph Koshy if ((cap & (cap - 1)) || cap < PMC_CAP_FIRST || 3358f263522aSJoseph Koshy cap > PMC_CAP_LAST) { 3359f263522aSJoseph Koshy errno = EINVAL; 3360aa342b1fSJoseph Koshy return (NULL); 3361f263522aSJoseph Koshy } 3362f263522aSJoseph Koshy 3363f263522aSJoseph Koshy i = ffs(cap); 3364aa342b1fSJoseph Koshy return (pmc_capability_names[i - 1]); 3365f263522aSJoseph Koshy } 3366f263522aSJoseph Koshy 3367f263522aSJoseph Koshy const char * 3368f263522aSJoseph Koshy pmc_name_of_class(enum pmc_class pc) 3369f263522aSJoseph Koshy { 3370*0ceb54c2SJohn Baldwin size_t n; 3371*0ceb54c2SJohn Baldwin 3372*0ceb54c2SJohn Baldwin for (n = 0; n < PMC_TABLE_SIZE(pmc_class_names); n++) 3373*0ceb54c2SJohn Baldwin if (pc == pmc_class_names[n].pm_class) 3374*0ceb54c2SJohn Baldwin return (pmc_class_names[n].pm_name); 3375f263522aSJoseph Koshy 3376f263522aSJoseph Koshy errno = EINVAL; 3377aa342b1fSJoseph Koshy return (NULL); 3378f263522aSJoseph Koshy } 3379f263522aSJoseph Koshy 3380f263522aSJoseph Koshy const char * 3381f263522aSJoseph Koshy pmc_name_of_cputype(enum pmc_cputype cp) 3382f263522aSJoseph Koshy { 3383789140c0SJoseph Koshy size_t n; 3384789140c0SJoseph Koshy 3385789140c0SJoseph Koshy for (n = 0; n < PMC_TABLE_SIZE(pmc_cputype_names); n++) 3386789140c0SJoseph Koshy if (cp == pmc_cputype_names[n].pm_cputype) 3387789140c0SJoseph Koshy return (pmc_cputype_names[n].pm_name); 3388789140c0SJoseph Koshy 3389f263522aSJoseph Koshy errno = EINVAL; 3390aa342b1fSJoseph Koshy return (NULL); 3391f263522aSJoseph Koshy } 3392f263522aSJoseph Koshy 3393f263522aSJoseph Koshy const char * 3394f263522aSJoseph Koshy pmc_name_of_disposition(enum pmc_disp pd) 3395f263522aSJoseph Koshy { 3396f263522aSJoseph Koshy if ((int) pd >= PMC_DISP_FIRST && 3397f263522aSJoseph Koshy pd <= PMC_DISP_LAST) 3398aa342b1fSJoseph Koshy return (pmc_disposition_names[pd]); 3399f263522aSJoseph Koshy 3400f263522aSJoseph Koshy errno = EINVAL; 3401aa342b1fSJoseph Koshy return (NULL); 3402f263522aSJoseph Koshy } 3403f263522aSJoseph Koshy 3404f263522aSJoseph Koshy const char * 34050cfab8ddSJoseph Koshy _pmc_name_of_event(enum pmc_event pe, enum pmc_cputype cpu) 3406f263522aSJoseph Koshy { 3407789140c0SJoseph Koshy const struct pmc_event_descr *ev, *evfence; 3408789140c0SJoseph Koshy 3409789140c0SJoseph Koshy ev = evfence = NULL; 34100cfab8ddSJoseph Koshy if (pe >= PMC_EV_IAF_FIRST && pe <= PMC_EV_IAF_LAST) { 34110cfab8ddSJoseph Koshy ev = iaf_event_table; 34120cfab8ddSJoseph Koshy evfence = iaf_event_table + PMC_EVENT_TABLE_SIZE(iaf); 34130cfab8ddSJoseph Koshy } else if (pe >= PMC_EV_IAP_FIRST && pe <= PMC_EV_IAP_LAST) { 34140cfab8ddSJoseph Koshy switch (cpu) { 34150cfab8ddSJoseph Koshy case PMC_CPU_INTEL_ATOM: 34160cfab8ddSJoseph Koshy ev = atom_event_table; 34170cfab8ddSJoseph Koshy evfence = atom_event_table + PMC_EVENT_TABLE_SIZE(atom); 34180cfab8ddSJoseph Koshy break; 3419e8f021a3SHiren Panchasara case PMC_CPU_INTEL_ATOM_SILVERMONT: 3420e8f021a3SHiren Panchasara ev = atom_silvermont_event_table; 3421e8f021a3SHiren Panchasara evfence = atom_silvermont_event_table + 3422e8f021a3SHiren Panchasara PMC_EVENT_TABLE_SIZE(atom_silvermont); 3423e8f021a3SHiren Panchasara break; 34240cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE: 34250cfab8ddSJoseph Koshy ev = core_event_table; 34260cfab8ddSJoseph Koshy evfence = core_event_table + PMC_EVENT_TABLE_SIZE(core); 34270cfab8ddSJoseph Koshy break; 34280cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE2: 3429b4d091f3SJoseph Koshy case PMC_CPU_INTEL_CORE2EXTREME: 34300cfab8ddSJoseph Koshy ev = core2_event_table; 34310cfab8ddSJoseph Koshy evfence = core2_event_table + PMC_EVENT_TABLE_SIZE(core2); 34320cfab8ddSJoseph Koshy break; 3433597979c4SJeff Roberson case PMC_CPU_INTEL_COREI7: 3434597979c4SJeff Roberson ev = corei7_event_table; 3435597979c4SJeff Roberson evfence = corei7_event_table + PMC_EVENT_TABLE_SIZE(corei7); 3436597979c4SJeff Roberson break; 343749fe48abSKonstantin Belousov case PMC_CPU_INTEL_NEHALEM_EX: 343849fe48abSKonstantin Belousov ev = nehalem_ex_event_table; 343949fe48abSKonstantin Belousov evfence = nehalem_ex_event_table + 344049fe48abSKonstantin Belousov PMC_EVENT_TABLE_SIZE(nehalem_ex); 344149fe48abSKonstantin Belousov break; 3442cc0c1555SSean Bruno case PMC_CPU_INTEL_HASWELL: 3443cc0c1555SSean Bruno ev = haswell_event_table; 3444cc0c1555SSean Bruno evfence = haswell_event_table + PMC_EVENT_TABLE_SIZE(haswell); 3445cc0c1555SSean Bruno break; 3446d95b3509SRandall Stewart case PMC_CPU_INTEL_HASWELL_XEON: 3447d95b3509SRandall Stewart ev = haswell_xeon_event_table; 3448d95b3509SRandall Stewart evfence = haswell_xeon_event_table + PMC_EVENT_TABLE_SIZE(haswell_xeon); 3449d95b3509SRandall Stewart break; 3450d95b3509SRandall Stewart 34511e862e5aSFabien Thomas case PMC_CPU_INTEL_IVYBRIDGE: 34521e862e5aSFabien Thomas ev = ivybridge_event_table; 34531e862e5aSFabien Thomas evfence = ivybridge_event_table + PMC_EVENT_TABLE_SIZE(ivybridge); 34541e862e5aSFabien Thomas break; 34553f929d8cSSean Bruno case PMC_CPU_INTEL_IVYBRIDGE_XEON: 34563f929d8cSSean Bruno ev = ivybridge_xeon_event_table; 34573f929d8cSSean Bruno evfence = ivybridge_xeon_event_table + PMC_EVENT_TABLE_SIZE(ivybridge_xeon); 34583f929d8cSSean Bruno break; 345978d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 346078d763a2SDavide Italiano ev = sandybridge_event_table; 346178d763a2SDavide Italiano evfence = sandybridge_event_table + PMC_EVENT_TABLE_SIZE(sandybridge); 346278d763a2SDavide Italiano break; 3463fabe02f5SSean Bruno case PMC_CPU_INTEL_SANDYBRIDGE_XEON: 3464fabe02f5SSean Bruno ev = sandybridge_xeon_event_table; 3465fabe02f5SSean Bruno evfence = sandybridge_xeon_event_table + PMC_EVENT_TABLE_SIZE(sandybridge_xeon); 3466fabe02f5SSean Bruno break; 34671fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 34681fa7f10bSFabien Thomas ev = westmere_event_table; 34691fa7f10bSFabien Thomas evfence = westmere_event_table + PMC_EVENT_TABLE_SIZE(westmere); 34701fa7f10bSFabien Thomas break; 347149fe48abSKonstantin Belousov case PMC_CPU_INTEL_WESTMERE_EX: 347249fe48abSKonstantin Belousov ev = westmere_ex_event_table; 347349fe48abSKonstantin Belousov evfence = westmere_ex_event_table + 347449fe48abSKonstantin Belousov PMC_EVENT_TABLE_SIZE(westmere_ex); 347549fe48abSKonstantin Belousov break; 34760cfab8ddSJoseph Koshy default: /* Unknown CPU type. */ 34770cfab8ddSJoseph Koshy break; 34780cfab8ddSJoseph Koshy } 34791fa7f10bSFabien Thomas } else if (pe >= PMC_EV_UCF_FIRST && pe <= PMC_EV_UCF_LAST) { 34801fa7f10bSFabien Thomas ev = ucf_event_table; 34811fa7f10bSFabien Thomas evfence = ucf_event_table + PMC_EVENT_TABLE_SIZE(ucf); 34821fa7f10bSFabien Thomas } else if (pe >= PMC_EV_UCP_FIRST && pe <= PMC_EV_UCP_LAST) { 34831fa7f10bSFabien Thomas switch (cpu) { 34841fa7f10bSFabien Thomas case PMC_CPU_INTEL_COREI7: 34851fa7f10bSFabien Thomas ev = corei7uc_event_table; 34861fa7f10bSFabien Thomas evfence = corei7uc_event_table + PMC_EVENT_TABLE_SIZE(corei7uc); 34871fa7f10bSFabien Thomas break; 348878d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 348978d763a2SDavide Italiano ev = sandybridgeuc_event_table; 349078d763a2SDavide Italiano evfence = sandybridgeuc_event_table + PMC_EVENT_TABLE_SIZE(sandybridgeuc); 349178d763a2SDavide Italiano break; 34921fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 34931fa7f10bSFabien Thomas ev = westmereuc_event_table; 34941fa7f10bSFabien Thomas evfence = westmereuc_event_table + PMC_EVENT_TABLE_SIZE(westmereuc); 34951fa7f10bSFabien Thomas break; 34961fa7f10bSFabien Thomas default: /* Unknown CPU type. */ 34971fa7f10bSFabien Thomas break; 34981fa7f10bSFabien Thomas } 34991fa7f10bSFabien Thomas } else if (pe >= PMC_EV_K7_FIRST && pe <= PMC_EV_K7_LAST) { 3500789140c0SJoseph Koshy ev = k7_event_table; 3501789140c0SJoseph Koshy evfence = k7_event_table + PMC_EVENT_TABLE_SIZE(k7); 3502789140c0SJoseph Koshy } else if (pe >= PMC_EV_K8_FIRST && pe <= PMC_EV_K8_LAST) { 3503789140c0SJoseph Koshy ev = k8_event_table; 3504789140c0SJoseph Koshy evfence = k8_event_table + PMC_EVENT_TABLE_SIZE(k8); 3505789140c0SJoseph Koshy } else if (pe >= PMC_EV_P4_FIRST && pe <= PMC_EV_P4_LAST) { 3506789140c0SJoseph Koshy ev = p4_event_table; 3507789140c0SJoseph Koshy evfence = p4_event_table + PMC_EVENT_TABLE_SIZE(p4); 3508789140c0SJoseph Koshy } else if (pe >= PMC_EV_P5_FIRST && pe <= PMC_EV_P5_LAST) { 3509789140c0SJoseph Koshy ev = p5_event_table; 3510789140c0SJoseph Koshy evfence = p5_event_table + PMC_EVENT_TABLE_SIZE(p5); 3511789140c0SJoseph Koshy } else if (pe >= PMC_EV_P6_FIRST && pe <= PMC_EV_P6_LAST) { 3512789140c0SJoseph Koshy ev = p6_event_table; 3513789140c0SJoseph Koshy evfence = p6_event_table + PMC_EVENT_TABLE_SIZE(p6); 35140ce207d2SRui Paulo } else if (pe >= PMC_EV_XSCALE_FIRST && pe <= PMC_EV_XSCALE_LAST) { 35150ce207d2SRui Paulo ev = xscale_event_table; 35160ce207d2SRui Paulo evfence = xscale_event_table + PMC_EVENT_TABLE_SIZE(xscale); 35176411d14dSRuslan Bukin } else if (pe >= PMC_EV_ARMV7_FIRST && pe <= PMC_EV_ARMV7_LAST) { 35186411d14dSRuslan Bukin ev = armv7_event_table; 35196411d14dSRuslan Bukin evfence = armv7_event_table + PMC_EVENT_TABLE_SIZE(armv7); 3520bc88bb2bSRuslan Bukin } else if (pe >= PMC_EV_ARMV8_FIRST && pe <= PMC_EV_ARMV8_LAST) { 3521bc88bb2bSRuslan Bukin switch (cpu) { 3522bc88bb2bSRuslan Bukin case PMC_CPU_ARMV8_CORTEX_A53: 3523bc88bb2bSRuslan Bukin ev = cortex_a53_event_table; 3524bc88bb2bSRuslan Bukin evfence = cortex_a53_event_table + PMC_EVENT_TABLE_SIZE(cortex_a53); 3525bc88bb2bSRuslan Bukin break; 3526bc88bb2bSRuslan Bukin case PMC_CPU_ARMV8_CORTEX_A57: 3527bc88bb2bSRuslan Bukin ev = cortex_a57_event_table; 3528bc88bb2bSRuslan Bukin evfence = cortex_a57_event_table + PMC_EVENT_TABLE_SIZE(cortex_a57); 3529bc88bb2bSRuslan Bukin break; 3530bc88bb2bSRuslan Bukin default: /* Unknown CPU type. */ 3531bc88bb2bSRuslan Bukin break; 3532bc88bb2bSRuslan Bukin } 3533660df75eSGeorge V. Neville-Neil } else if (pe >= PMC_EV_MIPS24K_FIRST && pe <= PMC_EV_MIPS24K_LAST) { 3534660df75eSGeorge V. Neville-Neil ev = mips24k_event_table; 3535f5f9340bSFabien Thomas evfence = mips24k_event_table + PMC_EVENT_TABLE_SIZE(mips24k); 3536f6e6460dSAdrian Chadd } else if (pe >= PMC_EV_MIPS74K_FIRST && pe <= PMC_EV_MIPS74K_LAST) { 3537f6e6460dSAdrian Chadd ev = mips74k_event_table; 3538f6e6460dSAdrian Chadd evfence = mips74k_event_table + PMC_EVENT_TABLE_SIZE(mips74k); 3539c2657f80SOleksandr Tymoshenko } else if (pe >= PMC_EV_OCTEON_FIRST && pe <= PMC_EV_OCTEON_LAST) { 3540c2657f80SOleksandr Tymoshenko ev = octeon_event_table; 3541c2657f80SOleksandr Tymoshenko evfence = octeon_event_table + PMC_EVENT_TABLE_SIZE(octeon); 35427b25dccaSJustin Hibbits } else if (pe >= PMC_EV_PPC7450_FIRST && pe <= PMC_EV_PPC7450_LAST) { 35437b25dccaSJustin Hibbits ev = ppc7450_event_table; 3544f5f9340bSFabien Thomas evfence = ppc7450_event_table + PMC_EVENT_TABLE_SIZE(ppc7450); 3545169dd953SJustin Hibbits } else if (pe >= PMC_EV_PPC970_FIRST && pe <= PMC_EV_PPC970_LAST) { 3546169dd953SJustin Hibbits ev = ppc970_event_table; 3547169dd953SJustin Hibbits evfence = ppc970_event_table + PMC_EVENT_TABLE_SIZE(ppc970); 3548a7452468SJustin Hibbits } else if (pe >= PMC_EV_E500_FIRST && pe <= PMC_EV_E500_LAST) { 3549a7452468SJustin Hibbits ev = e500_event_table; 3550a7452468SJustin Hibbits evfence = e500_event_table + PMC_EVENT_TABLE_SIZE(e500); 3551789140c0SJoseph Koshy } else if (pe == PMC_EV_TSC_TSC) { 3552789140c0SJoseph Koshy ev = tsc_event_table; 3553789140c0SJoseph Koshy evfence = tsc_event_table + PMC_EVENT_TABLE_SIZE(tsc); 3554f0bbe9aaSDimitry Andric } else if ((int)pe >= PMC_EV_SOFT_FIRST && (int)pe <= PMC_EV_SOFT_LAST) { 3555f5f9340bSFabien Thomas ev = soft_event_table; 3556f5f9340bSFabien Thomas evfence = soft_event_table + soft_event_info.pm_nevent; 3557789140c0SJoseph Koshy } 3558789140c0SJoseph Koshy 3559789140c0SJoseph Koshy for (; ev != evfence; ev++) 3560789140c0SJoseph Koshy if (pe == ev->pm_ev_code) 3561789140c0SJoseph Koshy return (ev->pm_ev_name); 3562f263522aSJoseph Koshy 35630cfab8ddSJoseph Koshy return (NULL); 35640cfab8ddSJoseph Koshy } 35650cfab8ddSJoseph Koshy 35660cfab8ddSJoseph Koshy const char * 35670cfab8ddSJoseph Koshy pmc_name_of_event(enum pmc_event pe) 35680cfab8ddSJoseph Koshy { 35690cfab8ddSJoseph Koshy const char *n; 35700cfab8ddSJoseph Koshy 35710cfab8ddSJoseph Koshy if ((n = _pmc_name_of_event(pe, cpu_info.pm_cputype)) != NULL) 35720cfab8ddSJoseph Koshy return (n); 35730cfab8ddSJoseph Koshy 3574f263522aSJoseph Koshy errno = EINVAL; 3575aa342b1fSJoseph Koshy return (NULL); 3576f263522aSJoseph Koshy } 3577f263522aSJoseph Koshy 3578f263522aSJoseph Koshy const char * 3579f263522aSJoseph Koshy pmc_name_of_mode(enum pmc_mode pm) 3580f263522aSJoseph Koshy { 3581f263522aSJoseph Koshy if ((int) pm >= PMC_MODE_FIRST && 3582f263522aSJoseph Koshy pm <= PMC_MODE_LAST) 3583aa342b1fSJoseph Koshy return (pmc_mode_names[pm]); 3584f263522aSJoseph Koshy 3585f263522aSJoseph Koshy errno = EINVAL; 3586aa342b1fSJoseph Koshy return (NULL); 3587f263522aSJoseph Koshy } 3588f263522aSJoseph Koshy 3589f263522aSJoseph Koshy const char * 3590f263522aSJoseph Koshy pmc_name_of_state(enum pmc_state ps) 3591f263522aSJoseph Koshy { 3592f263522aSJoseph Koshy if ((int) ps >= PMC_STATE_FIRST && 3593f263522aSJoseph Koshy ps <= PMC_STATE_LAST) 3594aa342b1fSJoseph Koshy return (pmc_state_names[ps]); 3595f263522aSJoseph Koshy 3596f263522aSJoseph Koshy errno = EINVAL; 3597aa342b1fSJoseph Koshy return (NULL); 3598f263522aSJoseph Koshy } 3599f263522aSJoseph Koshy 3600f263522aSJoseph Koshy int 3601f263522aSJoseph Koshy pmc_ncpu(void) 3602f263522aSJoseph Koshy { 3603f263522aSJoseph Koshy if (pmc_syscall == -1) { 3604f263522aSJoseph Koshy errno = ENXIO; 3605aa342b1fSJoseph Koshy return (-1); 3606f263522aSJoseph Koshy } 3607f263522aSJoseph Koshy 3608aa342b1fSJoseph Koshy return (cpu_info.pm_ncpu); 3609f263522aSJoseph Koshy } 3610f263522aSJoseph Koshy 3611f263522aSJoseph Koshy int 3612f263522aSJoseph Koshy pmc_npmc(int cpu) 3613f263522aSJoseph Koshy { 3614f263522aSJoseph Koshy if (pmc_syscall == -1) { 3615f263522aSJoseph Koshy errno = ENXIO; 3616aa342b1fSJoseph Koshy return (-1); 3617f263522aSJoseph Koshy } 3618f263522aSJoseph Koshy 3619f263522aSJoseph Koshy if (cpu < 0 || cpu >= (int) cpu_info.pm_ncpu) { 3620f263522aSJoseph Koshy errno = EINVAL; 3621aa342b1fSJoseph Koshy return (-1); 3622f263522aSJoseph Koshy } 3623f263522aSJoseph Koshy 3624aa342b1fSJoseph Koshy return (cpu_info.pm_npmc); 3625f263522aSJoseph Koshy } 3626f263522aSJoseph Koshy 3627f263522aSJoseph Koshy int 3628f263522aSJoseph Koshy pmc_pmcinfo(int cpu, struct pmc_pmcinfo **ppmci) 3629f263522aSJoseph Koshy { 3630f263522aSJoseph Koshy int nbytes, npmc; 3631f263522aSJoseph Koshy struct pmc_op_getpmcinfo *pmci; 3632f263522aSJoseph Koshy 3633f263522aSJoseph Koshy if ((npmc = pmc_npmc(cpu)) < 0) 3634aa342b1fSJoseph Koshy return (-1); 3635f263522aSJoseph Koshy 3636f263522aSJoseph Koshy nbytes = sizeof(struct pmc_op_getpmcinfo) + 3637f263522aSJoseph Koshy npmc * sizeof(struct pmc_info); 3638f263522aSJoseph Koshy 3639f263522aSJoseph Koshy if ((pmci = calloc(1, nbytes)) == NULL) 3640aa342b1fSJoseph Koshy return (-1); 3641f263522aSJoseph Koshy 3642f263522aSJoseph Koshy pmci->pm_cpu = cpu; 3643f263522aSJoseph Koshy 3644f263522aSJoseph Koshy if (PMC_CALL(GETPMCINFO, pmci) < 0) { 3645f263522aSJoseph Koshy free(pmci); 3646aa342b1fSJoseph Koshy return (-1); 3647f263522aSJoseph Koshy } 3648f263522aSJoseph Koshy 3649f263522aSJoseph Koshy /* kernel<->library, library<->userland interfaces are identical */ 3650f263522aSJoseph Koshy *ppmci = (struct pmc_pmcinfo *) pmci; 3651aa342b1fSJoseph Koshy return (0); 3652f263522aSJoseph Koshy } 3653f263522aSJoseph Koshy 3654f263522aSJoseph Koshy int 3655f263522aSJoseph Koshy pmc_read(pmc_id_t pmc, pmc_value_t *value) 3656f263522aSJoseph Koshy { 3657f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_read_op; 3658f263522aSJoseph Koshy 3659f263522aSJoseph Koshy pmc_read_op.pm_pmcid = pmc; 3660f263522aSJoseph Koshy pmc_read_op.pm_flags = PMC_F_OLDVALUE; 3661f263522aSJoseph Koshy pmc_read_op.pm_value = -1; 3662f263522aSJoseph Koshy 3663f263522aSJoseph Koshy if (PMC_CALL(PMCRW, &pmc_read_op) < 0) 3664aa342b1fSJoseph Koshy return (-1); 3665f263522aSJoseph Koshy 3666f263522aSJoseph Koshy *value = pmc_read_op.pm_value; 3667aa342b1fSJoseph Koshy return (0); 3668f263522aSJoseph Koshy } 3669f263522aSJoseph Koshy 3670f263522aSJoseph Koshy int 3671f263522aSJoseph Koshy pmc_release(pmc_id_t pmc) 3672f263522aSJoseph Koshy { 3673f263522aSJoseph Koshy struct pmc_op_simple pmc_release_args; 3674f263522aSJoseph Koshy 3675f263522aSJoseph Koshy pmc_release_args.pm_pmcid = pmc; 3676aa342b1fSJoseph Koshy return (PMC_CALL(PMCRELEASE, &pmc_release_args)); 3677f263522aSJoseph Koshy } 3678f263522aSJoseph Koshy 3679f263522aSJoseph Koshy int 3680f263522aSJoseph Koshy pmc_rw(pmc_id_t pmc, pmc_value_t newvalue, pmc_value_t *oldvaluep) 3681f263522aSJoseph Koshy { 3682f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_rw_op; 3683f263522aSJoseph Koshy 3684f263522aSJoseph Koshy pmc_rw_op.pm_pmcid = pmc; 3685f263522aSJoseph Koshy pmc_rw_op.pm_flags = PMC_F_NEWVALUE | PMC_F_OLDVALUE; 3686f263522aSJoseph Koshy pmc_rw_op.pm_value = newvalue; 3687f263522aSJoseph Koshy 3688f263522aSJoseph Koshy if (PMC_CALL(PMCRW, &pmc_rw_op) < 0) 3689aa342b1fSJoseph Koshy return (-1); 3690f263522aSJoseph Koshy 3691f263522aSJoseph Koshy *oldvaluep = pmc_rw_op.pm_value; 3692aa342b1fSJoseph Koshy return (0); 3693f263522aSJoseph Koshy } 3694f263522aSJoseph Koshy 3695f263522aSJoseph Koshy int 3696f263522aSJoseph Koshy pmc_set(pmc_id_t pmc, pmc_value_t value) 3697f263522aSJoseph Koshy { 3698f263522aSJoseph Koshy struct pmc_op_pmcsetcount sc; 3699f263522aSJoseph Koshy 3700f263522aSJoseph Koshy sc.pm_pmcid = pmc; 3701f263522aSJoseph Koshy sc.pm_count = value; 3702f263522aSJoseph Koshy 3703f263522aSJoseph Koshy if (PMC_CALL(PMCSETCOUNT, &sc) < 0) 3704aa342b1fSJoseph Koshy return (-1); 3705aa342b1fSJoseph Koshy return (0); 3706f263522aSJoseph Koshy } 3707f263522aSJoseph Koshy 3708f263522aSJoseph Koshy int 3709f263522aSJoseph Koshy pmc_start(pmc_id_t pmc) 3710f263522aSJoseph Koshy { 3711f263522aSJoseph Koshy struct pmc_op_simple pmc_start_args; 3712f263522aSJoseph Koshy 3713f263522aSJoseph Koshy pmc_start_args.pm_pmcid = pmc; 3714aa342b1fSJoseph Koshy return (PMC_CALL(PMCSTART, &pmc_start_args)); 3715f263522aSJoseph Koshy } 3716f263522aSJoseph Koshy 3717f263522aSJoseph Koshy int 3718f263522aSJoseph Koshy pmc_stop(pmc_id_t pmc) 3719f263522aSJoseph Koshy { 3720f263522aSJoseph Koshy struct pmc_op_simple pmc_stop_args; 3721f263522aSJoseph Koshy 3722f263522aSJoseph Koshy pmc_stop_args.pm_pmcid = pmc; 3723aa342b1fSJoseph Koshy return (PMC_CALL(PMCSTOP, &pmc_stop_args)); 3724f263522aSJoseph Koshy } 3725f263522aSJoseph Koshy 3726f263522aSJoseph Koshy int 3727f263522aSJoseph Koshy pmc_width(pmc_id_t pmcid, uint32_t *width) 3728f263522aSJoseph Koshy { 3729f263522aSJoseph Koshy unsigned int i; 3730f263522aSJoseph Koshy enum pmc_class cl; 3731f263522aSJoseph Koshy 3732f263522aSJoseph Koshy cl = PMC_ID_TO_CLASS(pmcid); 3733f263522aSJoseph Koshy for (i = 0; i < cpu_info.pm_nclass; i++) 3734f263522aSJoseph Koshy if (cpu_info.pm_classes[i].pm_class == cl) { 3735f263522aSJoseph Koshy *width = cpu_info.pm_classes[i].pm_width; 3736aa342b1fSJoseph Koshy return (0); 3737f263522aSJoseph Koshy } 3738484202faSJoseph Koshy errno = EINVAL; 3739484202faSJoseph Koshy return (-1); 3740f263522aSJoseph Koshy } 3741f263522aSJoseph Koshy 3742f263522aSJoseph Koshy int 3743f263522aSJoseph Koshy pmc_write(pmc_id_t pmc, pmc_value_t value) 3744f263522aSJoseph Koshy { 3745f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_write_op; 3746f263522aSJoseph Koshy 3747f263522aSJoseph Koshy pmc_write_op.pm_pmcid = pmc; 3748f263522aSJoseph Koshy pmc_write_op.pm_flags = PMC_F_NEWVALUE; 3749f263522aSJoseph Koshy pmc_write_op.pm_value = value; 3750aa342b1fSJoseph Koshy return (PMC_CALL(PMCRW, &pmc_write_op)); 3751f263522aSJoseph Koshy } 3752f263522aSJoseph Koshy 3753f263522aSJoseph Koshy int 3754f263522aSJoseph Koshy pmc_writelog(uint32_t userdata) 3755f263522aSJoseph Koshy { 3756f263522aSJoseph Koshy struct pmc_op_writelog wl; 3757f263522aSJoseph Koshy 3758f263522aSJoseph Koshy wl.pm_userdata = userdata; 3759aa342b1fSJoseph Koshy return (PMC_CALL(WRITELOG, &wl)); 3760f263522aSJoseph Koshy } 3761