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 85660df75eSGeorge V. Neville-Neil #if defined(__mips__) 862827d3e1SOleksandr Tymoshenko static int mips_allocate_pmc(enum pmc_event _pe, char* ctrspec, 87660df75eSGeorge V. Neville-Neil struct pmc_op_pmcallocate *_pmc_config); 88660df75eSGeorge V. Neville-Neil #endif /* __mips__ */ 89f5f9340bSFabien Thomas static int soft_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 90f5f9340bSFabien Thomas struct pmc_op_pmcallocate *_pmc_config); 91660df75eSGeorge V. Neville-Neil 927b25dccaSJustin Hibbits #if defined(__powerpc__) 93169dd953SJustin Hibbits static int powerpc_allocate_pmc(enum pmc_event _pe, char* ctrspec, 947b25dccaSJustin Hibbits struct pmc_op_pmcallocate *_pmc_config); 957b25dccaSJustin Hibbits #endif /* __powerpc__ */ 96660df75eSGeorge V. Neville-Neil 97ebccf1e3SJoseph Koshy #define PMC_CALL(cmd, params) \ 98ebccf1e3SJoseph Koshy syscall(pmc_syscall, PMC_OP_##cmd, (params)) 99ebccf1e3SJoseph Koshy 100ebccf1e3SJoseph Koshy /* 101ebccf1e3SJoseph Koshy * Event aliases provide a way for the user to ask for generic events 102ebccf1e3SJoseph Koshy * like "cache-misses", or "instructions-retired". These aliases are 103ebccf1e3SJoseph Koshy * mapped to the appropriate canonical event descriptions using a 104ebccf1e3SJoseph Koshy * lookup table. 105ebccf1e3SJoseph Koshy */ 106ebccf1e3SJoseph Koshy struct pmc_event_alias { 107ebccf1e3SJoseph Koshy const char *pm_alias; 108ebccf1e3SJoseph Koshy const char *pm_spec; 109ebccf1e3SJoseph Koshy }; 110ebccf1e3SJoseph Koshy 111ebccf1e3SJoseph Koshy static const struct pmc_event_alias *pmc_mdep_event_aliases; 112ebccf1e3SJoseph Koshy 113ebccf1e3SJoseph Koshy /* 114789140c0SJoseph Koshy * The pmc_event_descr structure maps symbolic names known to the user 115ebccf1e3SJoseph Koshy * to integer codes used by the PMC KLD. 116ebccf1e3SJoseph Koshy */ 117ebccf1e3SJoseph Koshy struct pmc_event_descr { 118ebccf1e3SJoseph Koshy const char *pm_ev_name; 119ebccf1e3SJoseph Koshy enum pmc_event pm_ev_code; 120ebccf1e3SJoseph Koshy }; 121ebccf1e3SJoseph Koshy 122789140c0SJoseph Koshy /* 123789140c0SJoseph Koshy * The pmc_class_descr structure maps class name prefixes for 124789140c0SJoseph Koshy * event names to event tables and other PMC class data. 125789140c0SJoseph Koshy */ 126789140c0SJoseph Koshy struct pmc_class_descr { 127789140c0SJoseph Koshy const char *pm_evc_name; 128789140c0SJoseph Koshy size_t pm_evc_name_size; 129789140c0SJoseph Koshy enum pmc_class pm_evc_class; 130789140c0SJoseph Koshy const struct pmc_event_descr *pm_evc_event_table; 131789140c0SJoseph Koshy size_t pm_evc_event_table_size; 132789140c0SJoseph Koshy int (*pm_evc_allocate_pmc)(enum pmc_event _pe, 133789140c0SJoseph Koshy char *_ctrspec, struct pmc_op_pmcallocate *_pa); 134ebccf1e3SJoseph Koshy }; 135ebccf1e3SJoseph Koshy 136789140c0SJoseph Koshy #define PMC_TABLE_SIZE(N) (sizeof(N)/sizeof(N[0])) 137789140c0SJoseph Koshy #define PMC_EVENT_TABLE_SIZE(N) PMC_TABLE_SIZE(N##_event_table) 138789140c0SJoseph Koshy 139789140c0SJoseph Koshy #undef __PMC_EV 140789140c0SJoseph Koshy #define __PMC_EV(C,N) { #N, PMC_EV_ ## C ## _ ## N }, 141789140c0SJoseph Koshy 142789140c0SJoseph Koshy /* 1430cfab8ddSJoseph Koshy * PMC_CLASSDEP_TABLE(NAME, CLASS) 144789140c0SJoseph Koshy * 1450cfab8ddSJoseph Koshy * Define a table mapping event names and aliases to HWPMC event IDs. 146789140c0SJoseph Koshy */ 1470cfab8ddSJoseph Koshy #define PMC_CLASSDEP_TABLE(N, C) \ 148789140c0SJoseph Koshy static const struct pmc_event_descr N##_event_table[] = \ 149789140c0SJoseph Koshy { \ 150789140c0SJoseph Koshy __PMC_EV_##C() \ 1510cfab8ddSJoseph Koshy } 1520cfab8ddSJoseph Koshy 1530cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(iaf, IAF); 1540cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(k7, K7); 1550cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(k8, K8); 1560cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(p4, P4); 1570cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(p5, P5); 1580cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(p6, P6); 1590ce207d2SRui Paulo PMC_CLASSDEP_TABLE(xscale, XSCALE); 1606411d14dSRuslan Bukin PMC_CLASSDEP_TABLE(armv7, ARMV7); 161660df75eSGeorge V. Neville-Neil PMC_CLASSDEP_TABLE(mips24k, MIPS24K); 162f6e6460dSAdrian Chadd PMC_CLASSDEP_TABLE(mips74k, MIPS74K); 163c2657f80SOleksandr Tymoshenko PMC_CLASSDEP_TABLE(octeon, OCTEON); 1641fa7f10bSFabien Thomas PMC_CLASSDEP_TABLE(ucf, UCF); 1657b25dccaSJustin Hibbits PMC_CLASSDEP_TABLE(ppc7450, PPC7450); 166169dd953SJustin Hibbits PMC_CLASSDEP_TABLE(ppc970, PPC970); 167*a7452468SJustin Hibbits PMC_CLASSDEP_TABLE(e500, E500); 1680cfab8ddSJoseph Koshy 169f5f9340bSFabien Thomas static struct pmc_event_descr soft_event_table[PMC_EV_DYN_COUNT]; 170f5f9340bSFabien Thomas 1710cfab8ddSJoseph Koshy #undef __PMC_EV_ALIAS 1720cfab8ddSJoseph Koshy #define __PMC_EV_ALIAS(N,CODE) { N, PMC_EV_##CODE }, 1730cfab8ddSJoseph Koshy 1740cfab8ddSJoseph Koshy static const struct pmc_event_descr atom_event_table[] = 1750cfab8ddSJoseph Koshy { 1760cfab8ddSJoseph Koshy __PMC_EV_ALIAS_ATOM() 1770cfab8ddSJoseph Koshy }; 1780cfab8ddSJoseph Koshy 179e8f021a3SHiren Panchasara static const struct pmc_event_descr atom_silvermont_event_table[] = 180e8f021a3SHiren Panchasara { 181e8f021a3SHiren Panchasara __PMC_EV_ALIAS_ATOM_SILVERMONT() 182e8f021a3SHiren Panchasara }; 183e8f021a3SHiren Panchasara 1840cfab8ddSJoseph Koshy static const struct pmc_event_descr core_event_table[] = 1850cfab8ddSJoseph Koshy { 1860cfab8ddSJoseph Koshy __PMC_EV_ALIAS_CORE() 1870cfab8ddSJoseph Koshy }; 1880cfab8ddSJoseph Koshy 1890cfab8ddSJoseph Koshy 1900cfab8ddSJoseph Koshy static const struct pmc_event_descr core2_event_table[] = 1910cfab8ddSJoseph Koshy { 1920cfab8ddSJoseph Koshy __PMC_EV_ALIAS_CORE2() 1930cfab8ddSJoseph Koshy }; 1940cfab8ddSJoseph Koshy 195597979c4SJeff Roberson static const struct pmc_event_descr corei7_event_table[] = 196597979c4SJeff Roberson { 197597979c4SJeff Roberson __PMC_EV_ALIAS_COREI7() 198597979c4SJeff Roberson }; 199597979c4SJeff Roberson 20049fe48abSKonstantin Belousov static const struct pmc_event_descr nehalem_ex_event_table[] = 20149fe48abSKonstantin Belousov { 20249fe48abSKonstantin Belousov __PMC_EV_ALIAS_COREI7() 20349fe48abSKonstantin Belousov }; 20449fe48abSKonstantin Belousov 205cc0c1555SSean Bruno static const struct pmc_event_descr haswell_event_table[] = 206cc0c1555SSean Bruno { 207cc0c1555SSean Bruno __PMC_EV_ALIAS_HASWELL() 208cc0c1555SSean Bruno }; 209cc0c1555SSean Bruno 210d95b3509SRandall Stewart static const struct pmc_event_descr haswell_xeon_event_table[] = 211d95b3509SRandall Stewart { 212d95b3509SRandall Stewart __PMC_EV_ALIAS_HASWELL_XEON() 213d95b3509SRandall Stewart }; 214d95b3509SRandall Stewart 215d95b3509SRandall Stewart 2161e862e5aSFabien Thomas static const struct pmc_event_descr ivybridge_event_table[] = 2171e862e5aSFabien Thomas { 2181e862e5aSFabien Thomas __PMC_EV_ALIAS_IVYBRIDGE() 2191e862e5aSFabien Thomas }; 2201e862e5aSFabien Thomas 2213f929d8cSSean Bruno static const struct pmc_event_descr ivybridge_xeon_event_table[] = 2223f929d8cSSean Bruno { 2233f929d8cSSean Bruno __PMC_EV_ALIAS_IVYBRIDGE_XEON() 2243f929d8cSSean Bruno }; 2253f929d8cSSean Bruno 22678d763a2SDavide Italiano static const struct pmc_event_descr sandybridge_event_table[] = 22778d763a2SDavide Italiano { 22878d763a2SDavide Italiano __PMC_EV_ALIAS_SANDYBRIDGE() 22978d763a2SDavide Italiano }; 23078d763a2SDavide Italiano 231fabe02f5SSean Bruno static const struct pmc_event_descr sandybridge_xeon_event_table[] = 232fabe02f5SSean Bruno { 233fabe02f5SSean Bruno __PMC_EV_ALIAS_SANDYBRIDGE_XEON() 234fabe02f5SSean Bruno }; 235fabe02f5SSean Bruno 2361fa7f10bSFabien Thomas static const struct pmc_event_descr westmere_event_table[] = 2371fa7f10bSFabien Thomas { 2381fa7f10bSFabien Thomas __PMC_EV_ALIAS_WESTMERE() 2391fa7f10bSFabien Thomas }; 2401fa7f10bSFabien Thomas 24149fe48abSKonstantin Belousov static const struct pmc_event_descr westmere_ex_event_table[] = 24249fe48abSKonstantin Belousov { 24349fe48abSKonstantin Belousov __PMC_EV_ALIAS_WESTMERE() 24449fe48abSKonstantin Belousov }; 24549fe48abSKonstantin Belousov 2461fa7f10bSFabien Thomas static const struct pmc_event_descr corei7uc_event_table[] = 2471fa7f10bSFabien Thomas { 2481fa7f10bSFabien Thomas __PMC_EV_ALIAS_COREI7UC() 2491fa7f10bSFabien Thomas }; 2501fa7f10bSFabien Thomas 251cc0c1555SSean Bruno static const struct pmc_event_descr haswelluc_event_table[] = 252cc0c1555SSean Bruno { 253cc0c1555SSean Bruno __PMC_EV_ALIAS_HASWELLUC() 254cc0c1555SSean Bruno }; 255cc0c1555SSean Bruno 25678d763a2SDavide Italiano static const struct pmc_event_descr sandybridgeuc_event_table[] = 25778d763a2SDavide Italiano { 25878d763a2SDavide Italiano __PMC_EV_ALIAS_SANDYBRIDGEUC() 25978d763a2SDavide Italiano }; 26078d763a2SDavide Italiano 2611fa7f10bSFabien Thomas static const struct pmc_event_descr westmereuc_event_table[] = 2621fa7f10bSFabien Thomas { 2631fa7f10bSFabien Thomas __PMC_EV_ALIAS_WESTMEREUC() 2641fa7f10bSFabien Thomas }; 2651fa7f10bSFabien Thomas 2660cfab8ddSJoseph Koshy /* 2670cfab8ddSJoseph Koshy * PMC_MDEP_TABLE(NAME, PRIMARYCLASS, ADDITIONAL_CLASSES...) 2680cfab8ddSJoseph Koshy * 2690cfab8ddSJoseph Koshy * Map a CPU to the PMC classes it supports. 2700cfab8ddSJoseph Koshy */ 2710cfab8ddSJoseph Koshy #define PMC_MDEP_TABLE(N,C,...) \ 272789140c0SJoseph Koshy static const enum pmc_class N##_pmc_classes[] = { \ 273789140c0SJoseph Koshy PMC_CLASS_##C, __VA_ARGS__ \ 274789140c0SJoseph Koshy } 275789140c0SJoseph Koshy 276f5f9340bSFabien Thomas PMC_MDEP_TABLE(atom, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 277e8f021a3SHiren Panchasara PMC_MDEP_TABLE(atom_silvermont, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 278f5f9340bSFabien Thomas PMC_MDEP_TABLE(core, IAP, PMC_CLASS_SOFT, PMC_CLASS_TSC); 279f5f9340bSFabien Thomas PMC_MDEP_TABLE(core2, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 280f5f9340bSFabien Thomas PMC_MDEP_TABLE(corei7, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 28149fe48abSKonstantin Belousov PMC_MDEP_TABLE(nehalem_ex, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 282cc0c1555SSean Bruno PMC_MDEP_TABLE(haswell, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 283d95b3509SRandall Stewart PMC_MDEP_TABLE(haswell_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 2841e862e5aSFabien Thomas PMC_MDEP_TABLE(ivybridge, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 2853f929d8cSSean Bruno PMC_MDEP_TABLE(ivybridge_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 286f5f9340bSFabien Thomas PMC_MDEP_TABLE(sandybridge, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 287fabe02f5SSean Bruno PMC_MDEP_TABLE(sandybridge_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 288f5f9340bSFabien Thomas PMC_MDEP_TABLE(westmere, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 28949fe48abSKonstantin Belousov PMC_MDEP_TABLE(westmere_ex, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 290f5f9340bSFabien Thomas PMC_MDEP_TABLE(k7, K7, PMC_CLASS_SOFT, PMC_CLASS_TSC); 291f5f9340bSFabien Thomas PMC_MDEP_TABLE(k8, K8, PMC_CLASS_SOFT, PMC_CLASS_TSC); 292f5f9340bSFabien Thomas PMC_MDEP_TABLE(p4, P4, PMC_CLASS_SOFT, PMC_CLASS_TSC); 293f5f9340bSFabien Thomas PMC_MDEP_TABLE(p5, P5, PMC_CLASS_SOFT, PMC_CLASS_TSC); 294f5f9340bSFabien Thomas PMC_MDEP_TABLE(p6, P6, PMC_CLASS_SOFT, PMC_CLASS_TSC); 295f5f9340bSFabien Thomas PMC_MDEP_TABLE(xscale, XSCALE, PMC_CLASS_SOFT, PMC_CLASS_XSCALE); 2966411d14dSRuslan Bukin PMC_MDEP_TABLE(armv7, ARMV7, PMC_CLASS_SOFT, PMC_CLASS_ARMV7); 297f5f9340bSFabien Thomas PMC_MDEP_TABLE(mips24k, MIPS24K, PMC_CLASS_SOFT, PMC_CLASS_MIPS24K); 298f6e6460dSAdrian Chadd PMC_MDEP_TABLE(mips74k, MIPS74K, PMC_CLASS_SOFT, PMC_CLASS_MIPS74K); 299f5f9340bSFabien Thomas PMC_MDEP_TABLE(octeon, OCTEON, PMC_CLASS_SOFT, PMC_CLASS_OCTEON); 300*a7452468SJustin Hibbits PMC_MDEP_TABLE(ppc7450, PPC7450, PMC_CLASS_SOFT, PMC_CLASS_PPC7450, PMC_CLASS_TSC); 301*a7452468SJustin Hibbits PMC_MDEP_TABLE(ppc970, PPC970, PMC_CLASS_SOFT, PMC_CLASS_PPC970, PMC_CLASS_TSC); 302*a7452468SJustin Hibbits PMC_MDEP_TABLE(e500, E500, PMC_CLASS_SOFT, PMC_CLASS_E500, PMC_CLASS_TSC); 303f5f9340bSFabien Thomas PMC_MDEP_TABLE(generic, SOFT, PMC_CLASS_SOFT); 304789140c0SJoseph Koshy 305789140c0SJoseph Koshy static const struct pmc_event_descr tsc_event_table[] = 306789140c0SJoseph Koshy { 307789140c0SJoseph Koshy __PMC_EV_TSC() 308789140c0SJoseph Koshy }; 309789140c0SJoseph Koshy 310789140c0SJoseph Koshy #undef PMC_CLASS_TABLE_DESC 3110cfab8ddSJoseph Koshy #define PMC_CLASS_TABLE_DESC(NAME, CLASS, EVENTS, ALLOCATOR) \ 3120cfab8ddSJoseph Koshy static const struct pmc_class_descr NAME##_class_table_descr = \ 3130cfab8ddSJoseph Koshy { \ 3140cfab8ddSJoseph Koshy .pm_evc_name = #CLASS "-", \ 3150cfab8ddSJoseph Koshy .pm_evc_name_size = sizeof(#CLASS "-") - 1, \ 3160cfab8ddSJoseph Koshy .pm_evc_class = PMC_CLASS_##CLASS , \ 3170cfab8ddSJoseph Koshy .pm_evc_event_table = EVENTS##_event_table , \ 318789140c0SJoseph Koshy .pm_evc_event_table_size = \ 3190cfab8ddSJoseph Koshy PMC_EVENT_TABLE_SIZE(EVENTS), \ 3200cfab8ddSJoseph Koshy .pm_evc_allocate_pmc = ALLOCATOR##_allocate_pmc \ 321789140c0SJoseph Koshy } 322789140c0SJoseph Koshy 323789140c0SJoseph Koshy #if defined(__i386__) || defined(__amd64__) 3240cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(iaf, IAF, iaf, iaf); 3250cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(atom, IAP, atom, iap); 326e8f021a3SHiren Panchasara PMC_CLASS_TABLE_DESC(atom_silvermont, IAP, atom_silvermont, iap); 3270cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(core, IAP, core, iap); 3280cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(core2, IAP, core2, iap); 329597979c4SJeff Roberson PMC_CLASS_TABLE_DESC(corei7, IAP, corei7, iap); 33049fe48abSKonstantin Belousov PMC_CLASS_TABLE_DESC(nehalem_ex, IAP, nehalem_ex, iap); 331cc0c1555SSean Bruno PMC_CLASS_TABLE_DESC(haswell, IAP, haswell, iap); 332ae9975dbSRyan Stone PMC_CLASS_TABLE_DESC(haswell_xeon, IAP, haswell_xeon, iap); 3331e862e5aSFabien Thomas PMC_CLASS_TABLE_DESC(ivybridge, IAP, ivybridge, iap); 3343f929d8cSSean Bruno PMC_CLASS_TABLE_DESC(ivybridge_xeon, IAP, ivybridge_xeon, iap); 33578d763a2SDavide Italiano PMC_CLASS_TABLE_DESC(sandybridge, IAP, sandybridge, iap); 336fabe02f5SSean Bruno PMC_CLASS_TABLE_DESC(sandybridge_xeon, IAP, sandybridge_xeon, iap); 3371fa7f10bSFabien Thomas PMC_CLASS_TABLE_DESC(westmere, IAP, westmere, iap); 33849fe48abSKonstantin Belousov PMC_CLASS_TABLE_DESC(westmere_ex, IAP, westmere_ex, iap); 3391fa7f10bSFabien Thomas PMC_CLASS_TABLE_DESC(ucf, UCF, ucf, ucf); 3401fa7f10bSFabien Thomas PMC_CLASS_TABLE_DESC(corei7uc, UCP, corei7uc, ucp); 341cc0c1555SSean Bruno PMC_CLASS_TABLE_DESC(haswelluc, UCP, haswelluc, ucp); 34278d763a2SDavide Italiano PMC_CLASS_TABLE_DESC(sandybridgeuc, UCP, sandybridgeuc, ucp); 3431fa7f10bSFabien Thomas PMC_CLASS_TABLE_DESC(westmereuc, UCP, westmereuc, ucp); 344789140c0SJoseph Koshy #endif 345789140c0SJoseph Koshy #if defined(__i386__) 3460cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(k7, K7, k7, k7); 347789140c0SJoseph Koshy #endif 348789140c0SJoseph Koshy #if defined(__i386__) || defined(__amd64__) 3490cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(k8, K8, k8, k8); 3500cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(p4, P4, p4, p4); 351789140c0SJoseph Koshy #endif 3520cfab8ddSJoseph Koshy #if defined(__i386__) 3530cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(p5, P5, p5, p5); 3540cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(p6, P6, p6, p6); 3550cfab8ddSJoseph Koshy #endif 3560cfab8ddSJoseph Koshy #if defined(__i386__) || defined(__amd64__) 3570cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(tsc, TSC, tsc, tsc); 3580cfab8ddSJoseph Koshy #endif 3596411d14dSRuslan Bukin #if defined(__arm__) 3600ce207d2SRui Paulo #if defined(__XSCALE__) 3610ce207d2SRui Paulo PMC_CLASS_TABLE_DESC(xscale, XSCALE, xscale, xscale); 3620ce207d2SRui Paulo #endif 3636411d14dSRuslan Bukin PMC_CLASS_TABLE_DESC(armv7, ARMV7, armv7, armv7); 3646411d14dSRuslan Bukin #endif 365660df75eSGeorge V. Neville-Neil #if defined(__mips__) 3662827d3e1SOleksandr Tymoshenko PMC_CLASS_TABLE_DESC(mips24k, MIPS24K, mips24k, mips); 367f6e6460dSAdrian Chadd PMC_CLASS_TABLE_DESC(mips74k, MIPS74K, mips74k, mips); 368c2657f80SOleksandr Tymoshenko PMC_CLASS_TABLE_DESC(octeon, OCTEON, octeon, mips); 369660df75eSGeorge V. Neville-Neil #endif /* __mips__ */ 3707b25dccaSJustin Hibbits #if defined(__powerpc__) 371169dd953SJustin Hibbits PMC_CLASS_TABLE_DESC(ppc7450, PPC7450, ppc7450, powerpc); 372169dd953SJustin Hibbits PMC_CLASS_TABLE_DESC(ppc970, PPC970, ppc970, powerpc); 373*a7452468SJustin Hibbits PMC_CLASS_TABLE_DESC(e500, E500, e500, powerpc); 3747b25dccaSJustin Hibbits #endif 3757b25dccaSJustin Hibbits 376f5f9340bSFabien Thomas static struct pmc_class_descr soft_class_table_descr = 377f5f9340bSFabien Thomas { 378f5f9340bSFabien Thomas .pm_evc_name = "SOFT-", 379f5f9340bSFabien Thomas .pm_evc_name_size = sizeof("SOFT-") - 1, 380f5f9340bSFabien Thomas .pm_evc_class = PMC_CLASS_SOFT, 381f5f9340bSFabien Thomas .pm_evc_event_table = NULL, 382f5f9340bSFabien Thomas .pm_evc_event_table_size = 0, 383f5f9340bSFabien Thomas .pm_evc_allocate_pmc = soft_allocate_pmc 384f5f9340bSFabien Thomas }; 385f5f9340bSFabien Thomas 386789140c0SJoseph Koshy #undef PMC_CLASS_TABLE_DESC 387789140c0SJoseph Koshy 3880cfab8ddSJoseph Koshy static const struct pmc_class_descr **pmc_class_table; 3890cfab8ddSJoseph Koshy #define PMC_CLASS_TABLE_SIZE cpu_info.pm_nclass 3900cfab8ddSJoseph Koshy 391789140c0SJoseph Koshy static const enum pmc_class *pmc_mdep_class_list; 392789140c0SJoseph Koshy static size_t pmc_mdep_class_list_size; 393789140c0SJoseph Koshy 394ebccf1e3SJoseph Koshy /* 395ebccf1e3SJoseph Koshy * Mapping tables, mapping enumeration values to human readable 396ebccf1e3SJoseph Koshy * strings. 397ebccf1e3SJoseph Koshy */ 398ebccf1e3SJoseph Koshy 399ebccf1e3SJoseph Koshy static const char * pmc_capability_names[] = { 400ebccf1e3SJoseph Koshy #undef __PMC_CAP 401ebccf1e3SJoseph Koshy #define __PMC_CAP(N,V,D) #N , 402ebccf1e3SJoseph Koshy __PMC_CAPS() 403ebccf1e3SJoseph Koshy }; 404ebccf1e3SJoseph Koshy 405ebccf1e3SJoseph Koshy static const char * pmc_class_names[] = { 406ebccf1e3SJoseph Koshy #undef __PMC_CLASS 407ebccf1e3SJoseph Koshy #define __PMC_CLASS(C) #C , 408ebccf1e3SJoseph Koshy __PMC_CLASSES() 409ebccf1e3SJoseph Koshy }; 410ebccf1e3SJoseph Koshy 411789140c0SJoseph Koshy struct pmc_cputype_map { 412562fc14bSDimitry Andric enum pmc_cputype pm_cputype; 413789140c0SJoseph Koshy const char *pm_name; 414789140c0SJoseph Koshy }; 415789140c0SJoseph Koshy 416789140c0SJoseph Koshy static const struct pmc_cputype_map pmc_cputype_names[] = { 417ebccf1e3SJoseph Koshy #undef __PMC_CPU 418789140c0SJoseph Koshy #define __PMC_CPU(S, V, D) { .pm_cputype = PMC_CPU_##S, .pm_name = #S } , 419ebccf1e3SJoseph Koshy __PMC_CPUS() 420ebccf1e3SJoseph Koshy }; 421ebccf1e3SJoseph Koshy 422ebccf1e3SJoseph Koshy static const char * pmc_disposition_names[] = { 423ebccf1e3SJoseph Koshy #undef __PMC_DISP 424ebccf1e3SJoseph Koshy #define __PMC_DISP(D) #D , 425ebccf1e3SJoseph Koshy __PMC_DISPOSITIONS() 426ebccf1e3SJoseph Koshy }; 427ebccf1e3SJoseph Koshy 428ebccf1e3SJoseph Koshy static const char * pmc_mode_names[] = { 429ebccf1e3SJoseph Koshy #undef __PMC_MODE 430ebccf1e3SJoseph Koshy #define __PMC_MODE(M,N) #M , 431ebccf1e3SJoseph Koshy __PMC_MODES() 432ebccf1e3SJoseph Koshy }; 433ebccf1e3SJoseph Koshy 434ebccf1e3SJoseph Koshy static const char * pmc_state_names[] = { 435ebccf1e3SJoseph Koshy #undef __PMC_STATE 436ebccf1e3SJoseph Koshy #define __PMC_STATE(S) #S , 437ebccf1e3SJoseph Koshy __PMC_STATES() 438ebccf1e3SJoseph Koshy }; 439ebccf1e3SJoseph Koshy 440f5f9340bSFabien Thomas /* 441f5f9340bSFabien Thomas * Filled in by pmc_init(). 442f5f9340bSFabien Thomas */ 443f5f9340bSFabien Thomas static int pmc_syscall = -1; 444f5f9340bSFabien Thomas static struct pmc_cpuinfo cpu_info; 445f5f9340bSFabien Thomas static struct pmc_op_getdyneventinfo soft_event_info; 4461455fcd3SJoseph Koshy 447ebccf1e3SJoseph Koshy /* Event masks for events */ 448ebccf1e3SJoseph Koshy struct pmc_masks { 449ebccf1e3SJoseph Koshy const char *pm_name; 4501e862e5aSFabien Thomas const uint64_t pm_value; 451ebccf1e3SJoseph Koshy }; 452ebccf1e3SJoseph Koshy #define PMCMASK(N,V) { .pm_name = #N, .pm_value = (V) } 4531fa7f10bSFabien Thomas #define NULLMASK { .pm_name = NULL } 454ebccf1e3SJoseph Koshy 45586a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 456ebccf1e3SJoseph Koshy static int 4571e862e5aSFabien Thomas pmc_parse_mask(const struct pmc_masks *pmask, char *p, uint64_t *evmask) 458ebccf1e3SJoseph Koshy { 459ebccf1e3SJoseph Koshy const struct pmc_masks *pm; 460ebccf1e3SJoseph Koshy char *q, *r; 461ebccf1e3SJoseph Koshy int c; 462ebccf1e3SJoseph Koshy 463ebccf1e3SJoseph Koshy if (pmask == NULL) /* no mask keywords */ 464aa342b1fSJoseph Koshy return (-1); 465ebccf1e3SJoseph Koshy q = strchr(p, '='); /* skip '=' */ 466ebccf1e3SJoseph Koshy if (*++q == '\0') /* no more data */ 467aa342b1fSJoseph Koshy return (-1); 468ebccf1e3SJoseph Koshy c = 0; /* count of mask keywords seen */ 469ebccf1e3SJoseph Koshy while ((r = strsep(&q, "+")) != NULL) { 470789140c0SJoseph Koshy for (pm = pmask; pm->pm_name && strcasecmp(r, pm->pm_name); 471789140c0SJoseph Koshy pm++) 472ebccf1e3SJoseph Koshy ; 473ebccf1e3SJoseph Koshy if (pm->pm_name == NULL) /* not found */ 474aa342b1fSJoseph Koshy return (-1); 475ebccf1e3SJoseph Koshy *evmask |= pm->pm_value; 476ebccf1e3SJoseph Koshy c++; 477ebccf1e3SJoseph Koshy } 478aa342b1fSJoseph Koshy return (c); 479ebccf1e3SJoseph Koshy } 48004e9feb0SMarcel Moolenaar #endif 481ebccf1e3SJoseph Koshy 482ebccf1e3SJoseph Koshy #define KWMATCH(p,kw) (strcasecmp((p), (kw)) == 0) 483ebccf1e3SJoseph Koshy #define KWPREFIXMATCH(p,kw) (strncasecmp((p), (kw), sizeof((kw)) - 1) == 0) 484ebccf1e3SJoseph Koshy #define EV_ALIAS(N,S) { .pm_alias = N, .pm_spec = S } 485ebccf1e3SJoseph Koshy 48604e9feb0SMarcel Moolenaar #if defined(__i386__) 487ebccf1e3SJoseph Koshy 488ebccf1e3SJoseph Koshy /* 489ebccf1e3SJoseph Koshy * AMD K7 (Athlon) CPUs. 490ebccf1e3SJoseph Koshy */ 491ebccf1e3SJoseph Koshy 492ebccf1e3SJoseph Koshy static struct pmc_event_alias k7_aliases[] = { 493ebccf1e3SJoseph Koshy EV_ALIAS("branches", "k7-retired-branches"), 494ebccf1e3SJoseph Koshy EV_ALIAS("branch-mispredicts", "k7-retired-branches-mispredicted"), 495ebccf1e3SJoseph Koshy EV_ALIAS("cycles", "tsc"), 4966aa5a193SJoseph Koshy EV_ALIAS("dc-misses", "k7-dc-misses"), 497ebccf1e3SJoseph Koshy EV_ALIAS("ic-misses", "k7-ic-misses"), 498ebccf1e3SJoseph Koshy EV_ALIAS("instructions", "k7-retired-instructions"), 499ebccf1e3SJoseph Koshy EV_ALIAS("interrupts", "k7-hardware-interrupts"), 500ebccf1e3SJoseph Koshy EV_ALIAS(NULL, NULL) 501ebccf1e3SJoseph Koshy }; 502ebccf1e3SJoseph Koshy 503ebccf1e3SJoseph Koshy #define K7_KW_COUNT "count" 504ebccf1e3SJoseph Koshy #define K7_KW_EDGE "edge" 505ebccf1e3SJoseph Koshy #define K7_KW_INV "inv" 506ebccf1e3SJoseph Koshy #define K7_KW_OS "os" 507ebccf1e3SJoseph Koshy #define K7_KW_UNITMASK "unitmask" 508ebccf1e3SJoseph Koshy #define K7_KW_USR "usr" 509ebccf1e3SJoseph Koshy 510ebccf1e3SJoseph Koshy static int 511ebccf1e3SJoseph Koshy k7_allocate_pmc(enum pmc_event pe, char *ctrspec, 512ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 513ebccf1e3SJoseph Koshy { 514ebccf1e3SJoseph Koshy char *e, *p, *q; 515ebccf1e3SJoseph Koshy int c, has_unitmask; 516ebccf1e3SJoseph Koshy uint32_t count, unitmask; 517ebccf1e3SJoseph Koshy 518f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 519789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 520ebccf1e3SJoseph Koshy 521ebccf1e3SJoseph Koshy if (pe == PMC_EV_K7_DC_REFILLS_FROM_L2 || 522ebccf1e3SJoseph Koshy pe == PMC_EV_K7_DC_REFILLS_FROM_SYSTEM || 523ebccf1e3SJoseph Koshy pe == PMC_EV_K7_DC_WRITEBACKS) { 524ebccf1e3SJoseph Koshy has_unitmask = 1; 525f263522aSJoseph Koshy unitmask = AMD_PMC_UNITMASK_MOESI; 526ebccf1e3SJoseph Koshy } else 527ebccf1e3SJoseph Koshy unitmask = has_unitmask = 0; 528ebccf1e3SJoseph Koshy 529ebccf1e3SJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 530ebccf1e3SJoseph Koshy if (KWPREFIXMATCH(p, K7_KW_COUNT "=")) { 531ebccf1e3SJoseph Koshy q = strchr(p, '='); 532ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 533aa342b1fSJoseph Koshy return (-1); 534ebccf1e3SJoseph Koshy 535ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 536ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 537aa342b1fSJoseph Koshy return (-1); 538ebccf1e3SJoseph Koshy 539ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 540f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config |= 541f263522aSJoseph Koshy AMD_PMC_TO_COUNTER(count); 542ebccf1e3SJoseph Koshy 543ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_EDGE)) { 544ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 545ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_INV)) { 546ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 547ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_OS)) { 548ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 549ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, K7_KW_UNITMASK "=")) { 550ebccf1e3SJoseph Koshy if (has_unitmask == 0) 551aa342b1fSJoseph Koshy return (-1); 552ebccf1e3SJoseph Koshy unitmask = 0; 553ebccf1e3SJoseph Koshy q = strchr(p, '='); 554ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 555aa342b1fSJoseph Koshy return (-1); 556ebccf1e3SJoseph Koshy 557ebccf1e3SJoseph Koshy while ((c = tolower(*q++)) != 0) 558ebccf1e3SJoseph Koshy if (c == 'm') 559f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_M; 560ebccf1e3SJoseph Koshy else if (c == 'o') 561f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_O; 562ebccf1e3SJoseph Koshy else if (c == 'e') 563f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_E; 564ebccf1e3SJoseph Koshy else if (c == 's') 565f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_S; 566ebccf1e3SJoseph Koshy else if (c == 'i') 567f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_I; 568ebccf1e3SJoseph Koshy else if (c == '+') 569ebccf1e3SJoseph Koshy continue; 570ebccf1e3SJoseph Koshy else 571aa342b1fSJoseph Koshy return (-1); 572ebccf1e3SJoseph Koshy 573ebccf1e3SJoseph Koshy if (unitmask == 0) 574aa342b1fSJoseph Koshy return (-1); 575ebccf1e3SJoseph Koshy 576ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_USR)) { 577ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 578ebccf1e3SJoseph Koshy } else 579aa342b1fSJoseph Koshy return (-1); 580ebccf1e3SJoseph Koshy } 581ebccf1e3SJoseph Koshy 582ebccf1e3SJoseph Koshy if (has_unitmask) { 583ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 584f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config |= 585f263522aSJoseph Koshy AMD_PMC_TO_UNITMASK(unitmask); 586ebccf1e3SJoseph Koshy } 587ebccf1e3SJoseph Koshy 588aa342b1fSJoseph Koshy return (0); 589ebccf1e3SJoseph Koshy 590ebccf1e3SJoseph Koshy } 591ebccf1e3SJoseph Koshy 592f263522aSJoseph Koshy #endif 593f263522aSJoseph Koshy 59486a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 595f263522aSJoseph Koshy 596f263522aSJoseph Koshy /* 5970cfab8ddSJoseph Koshy * Intel Core (Family 6, Model E) PMCs. 5980cfab8ddSJoseph Koshy */ 5990cfab8ddSJoseph Koshy 6000cfab8ddSJoseph Koshy static struct pmc_event_alias core_aliases[] = { 6010cfab8ddSJoseph Koshy EV_ALIAS("branches", "iap-br-instr-ret"), 6020cfab8ddSJoseph Koshy EV_ALIAS("branch-mispredicts", "iap-br-mispred-ret"), 6030cfab8ddSJoseph Koshy EV_ALIAS("cycles", "tsc-tsc"), 6040cfab8ddSJoseph Koshy EV_ALIAS("ic-misses", "iap-icache-misses"), 6050cfab8ddSJoseph Koshy EV_ALIAS("instructions", "iap-instr-ret"), 6060cfab8ddSJoseph Koshy EV_ALIAS("interrupts", "iap-core-hw-int-rx"), 6070cfab8ddSJoseph Koshy EV_ALIAS("unhalted-cycles", "iap-unhalted-core-cycles"), 6080cfab8ddSJoseph Koshy EV_ALIAS(NULL, NULL) 6090cfab8ddSJoseph Koshy }; 6100cfab8ddSJoseph Koshy 6110cfab8ddSJoseph Koshy /* 6120cfab8ddSJoseph Koshy * Intel Core2 (Family 6, Model F), Core2Extreme (Family 6, Model 17H) 6130cfab8ddSJoseph Koshy * and Atom (Family 6, model 1CH) PMCs. 614791f5d5bSJoseph Koshy * 615791f5d5bSJoseph Koshy * We map aliases to events on the fixed-function counters if these 616791f5d5bSJoseph Koshy * are present. Note that not all CPUs in this family contain fixed-function 617791f5d5bSJoseph Koshy * counters. 6180cfab8ddSJoseph Koshy */ 6190cfab8ddSJoseph Koshy 6200cfab8ddSJoseph Koshy static struct pmc_event_alias core2_aliases[] = { 6210cfab8ddSJoseph Koshy EV_ALIAS("branches", "iap-br-inst-retired.any"), 6220cfab8ddSJoseph Koshy EV_ALIAS("branch-mispredicts", "iap-br-inst-retired.mispred"), 6230cfab8ddSJoseph Koshy EV_ALIAS("cycles", "tsc-tsc"), 6240cfab8ddSJoseph Koshy EV_ALIAS("ic-misses", "iap-l1i-misses"), 6250cfab8ddSJoseph Koshy EV_ALIAS("instructions", "iaf-instr-retired.any"), 6260cfab8ddSJoseph Koshy EV_ALIAS("interrupts", "iap-hw-int-rcv"), 6270cfab8ddSJoseph Koshy EV_ALIAS("unhalted-cycles", "iaf-cpu-clk-unhalted.core"), 6280cfab8ddSJoseph Koshy EV_ALIAS(NULL, NULL) 6290cfab8ddSJoseph Koshy }; 630791f5d5bSJoseph Koshy 631791f5d5bSJoseph Koshy static struct pmc_event_alias core2_aliases_without_iaf[] = { 632791f5d5bSJoseph Koshy EV_ALIAS("branches", "iap-br-inst-retired.any"), 633791f5d5bSJoseph Koshy EV_ALIAS("branch-mispredicts", "iap-br-inst-retired.mispred"), 634791f5d5bSJoseph Koshy EV_ALIAS("cycles", "tsc-tsc"), 635791f5d5bSJoseph Koshy EV_ALIAS("ic-misses", "iap-l1i-misses"), 636791f5d5bSJoseph Koshy EV_ALIAS("instructions", "iap-inst-retired.any_p"), 637791f5d5bSJoseph Koshy EV_ALIAS("interrupts", "iap-hw-int-rcv"), 638791f5d5bSJoseph Koshy EV_ALIAS("unhalted-cycles", "iap-cpu-clk-unhalted.core_p"), 639791f5d5bSJoseph Koshy EV_ALIAS(NULL, NULL) 640791f5d5bSJoseph Koshy }; 641791f5d5bSJoseph Koshy 6420cfab8ddSJoseph Koshy #define atom_aliases core2_aliases 643791f5d5bSJoseph Koshy #define atom_aliases_without_iaf core2_aliases_without_iaf 644e8f021a3SHiren Panchasara #define atom_silvermont_aliases core2_aliases 645e8f021a3SHiren Panchasara #define atom_silvermont_aliases_without_iaf core2_aliases_without_iaf 646597979c4SJeff Roberson #define corei7_aliases core2_aliases 647791f5d5bSJoseph Koshy #define corei7_aliases_without_iaf core2_aliases_without_iaf 64849fe48abSKonstantin Belousov #define nehalem_ex_aliases core2_aliases 64949fe48abSKonstantin Belousov #define nehalem_ex_aliases_without_iaf core2_aliases_without_iaf 650cc0c1555SSean Bruno #define haswell_aliases core2_aliases 651cc0c1555SSean Bruno #define haswell_aliases_without_iaf core2_aliases_without_iaf 652d95b3509SRandall Stewart #define haswell_xeon_aliases core2_aliases 653d95b3509SRandall Stewart #define haswell_xeon_aliases_without_iaf core2_aliases_without_iaf 6541e862e5aSFabien Thomas #define ivybridge_aliases core2_aliases 6551e862e5aSFabien Thomas #define ivybridge_aliases_without_iaf core2_aliases_without_iaf 6563f929d8cSSean Bruno #define ivybridge_xeon_aliases core2_aliases 6573f929d8cSSean Bruno #define ivybridge_xeon_aliases_without_iaf core2_aliases_without_iaf 65878d763a2SDavide Italiano #define sandybridge_aliases core2_aliases 65978d763a2SDavide Italiano #define sandybridge_aliases_without_iaf core2_aliases_without_iaf 660fabe02f5SSean Bruno #define sandybridge_xeon_aliases core2_aliases 661fabe02f5SSean Bruno #define sandybridge_xeon_aliases_without_iaf core2_aliases_without_iaf 6621fa7f10bSFabien Thomas #define westmere_aliases core2_aliases 6631fa7f10bSFabien Thomas #define westmere_aliases_without_iaf core2_aliases_without_iaf 66449fe48abSKonstantin Belousov #define westmere_ex_aliases core2_aliases 66549fe48abSKonstantin Belousov #define westmere_ex_aliases_without_iaf core2_aliases_without_iaf 6660cfab8ddSJoseph Koshy 6670cfab8ddSJoseph Koshy #define IAF_KW_OS "os" 6680cfab8ddSJoseph Koshy #define IAF_KW_USR "usr" 6690cfab8ddSJoseph Koshy #define IAF_KW_ANYTHREAD "anythread" 6700cfab8ddSJoseph Koshy 6710cfab8ddSJoseph Koshy /* 6720cfab8ddSJoseph Koshy * Parse an event specifier for Intel fixed function counters. 6730cfab8ddSJoseph Koshy */ 6740cfab8ddSJoseph Koshy static int 6750cfab8ddSJoseph Koshy iaf_allocate_pmc(enum pmc_event pe, char *ctrspec, 6760cfab8ddSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 6770cfab8ddSJoseph Koshy { 6780cfab8ddSJoseph Koshy char *p; 6790cfab8ddSJoseph Koshy 6800cfab8ddSJoseph Koshy (void) pe; 6810cfab8ddSJoseph Koshy 6820cfab8ddSJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 6830cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iaf.pm_iaf_flags = 0; 6840cfab8ddSJoseph Koshy 6850cfab8ddSJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 6860cfab8ddSJoseph Koshy if (KWMATCH(p, IAF_KW_OS)) 6870cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 6880cfab8ddSJoseph Koshy else if (KWMATCH(p, IAF_KW_USR)) 6890cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 6900cfab8ddSJoseph Koshy else if (KWMATCH(p, IAF_KW_ANYTHREAD)) 6910cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iaf.pm_iaf_flags |= IAF_ANY; 6920cfab8ddSJoseph Koshy else 6930cfab8ddSJoseph Koshy return (-1); 6940cfab8ddSJoseph Koshy } 6950cfab8ddSJoseph Koshy 6960cfab8ddSJoseph Koshy return (0); 6970cfab8ddSJoseph Koshy } 6980cfab8ddSJoseph Koshy 6990cfab8ddSJoseph Koshy /* 7000cfab8ddSJoseph Koshy * Core/Core2 support. 7010cfab8ddSJoseph Koshy */ 7020cfab8ddSJoseph Koshy 7030cfab8ddSJoseph Koshy #define IAP_KW_AGENT "agent" 7040cfab8ddSJoseph Koshy #define IAP_KW_ANYTHREAD "anythread" 7050cfab8ddSJoseph Koshy #define IAP_KW_CACHESTATE "cachestate" 7060cfab8ddSJoseph Koshy #define IAP_KW_CMASK "cmask" 7070cfab8ddSJoseph Koshy #define IAP_KW_CORE "core" 7080cfab8ddSJoseph Koshy #define IAP_KW_EDGE "edge" 7090cfab8ddSJoseph Koshy #define IAP_KW_INV "inv" 7100cfab8ddSJoseph Koshy #define IAP_KW_OS "os" 7110cfab8ddSJoseph Koshy #define IAP_KW_PREFETCH "prefetch" 7120cfab8ddSJoseph Koshy #define IAP_KW_SNOOPRESPONSE "snoopresponse" 7130cfab8ddSJoseph Koshy #define IAP_KW_SNOOPTYPE "snooptype" 7140cfab8ddSJoseph Koshy #define IAP_KW_TRANSITION "trans" 7150cfab8ddSJoseph Koshy #define IAP_KW_USR "usr" 7161fa7f10bSFabien Thomas #define IAP_KW_RSP "rsp" 7170cfab8ddSJoseph Koshy 7180cfab8ddSJoseph Koshy static struct pmc_masks iap_core_mask[] = { 7190cfab8ddSJoseph Koshy PMCMASK(all, (0x3 << 14)), 7200cfab8ddSJoseph Koshy PMCMASK(this, (0x1 << 14)), 7210cfab8ddSJoseph Koshy NULLMASK 7220cfab8ddSJoseph Koshy }; 7230cfab8ddSJoseph Koshy 7240cfab8ddSJoseph Koshy static struct pmc_masks iap_agent_mask[] = { 7250cfab8ddSJoseph Koshy PMCMASK(this, 0), 7260cfab8ddSJoseph Koshy PMCMASK(any, (0x1 << 13)), 7270cfab8ddSJoseph Koshy NULLMASK 7280cfab8ddSJoseph Koshy }; 7290cfab8ddSJoseph Koshy 7300cfab8ddSJoseph Koshy static struct pmc_masks iap_prefetch_mask[] = { 7310cfab8ddSJoseph Koshy PMCMASK(both, (0x3 << 12)), 7320cfab8ddSJoseph Koshy PMCMASK(only, (0x1 << 12)), 7330cfab8ddSJoseph Koshy PMCMASK(exclude, 0), 7340cfab8ddSJoseph Koshy NULLMASK 7350cfab8ddSJoseph Koshy }; 7360cfab8ddSJoseph Koshy 7370cfab8ddSJoseph Koshy static struct pmc_masks iap_cachestate_mask[] = { 7380cfab8ddSJoseph Koshy PMCMASK(i, (1 << 8)), 7390cfab8ddSJoseph Koshy PMCMASK(s, (1 << 9)), 7400cfab8ddSJoseph Koshy PMCMASK(e, (1 << 10)), 7410cfab8ddSJoseph Koshy PMCMASK(m, (1 << 11)), 7420cfab8ddSJoseph Koshy NULLMASK 7430cfab8ddSJoseph Koshy }; 7440cfab8ddSJoseph Koshy 7450cfab8ddSJoseph Koshy static struct pmc_masks iap_snoopresponse_mask[] = { 7460cfab8ddSJoseph Koshy PMCMASK(clean, (1 << 8)), 7470cfab8ddSJoseph Koshy PMCMASK(hit, (1 << 9)), 7480cfab8ddSJoseph Koshy PMCMASK(hitm, (1 << 11)), 7490cfab8ddSJoseph Koshy NULLMASK 7500cfab8ddSJoseph Koshy }; 7510cfab8ddSJoseph Koshy 7520cfab8ddSJoseph Koshy static struct pmc_masks iap_snooptype_mask[] = { 7530cfab8ddSJoseph Koshy PMCMASK(cmp2s, (1 << 8)), 7540cfab8ddSJoseph Koshy PMCMASK(cmp2i, (1 << 9)), 7550cfab8ddSJoseph Koshy NULLMASK 7560cfab8ddSJoseph Koshy }; 7570cfab8ddSJoseph Koshy 7580cfab8ddSJoseph Koshy static struct pmc_masks iap_transition_mask[] = { 7590cfab8ddSJoseph Koshy PMCMASK(any, 0x00), 7600cfab8ddSJoseph Koshy PMCMASK(frequency, 0x10), 7610cfab8ddSJoseph Koshy NULLMASK 7620cfab8ddSJoseph Koshy }; 7630cfab8ddSJoseph Koshy 7641e862e5aSFabien Thomas static struct pmc_masks iap_rsp_mask_i7_wm[] = { 7651fa7f10bSFabien Thomas PMCMASK(DMND_DATA_RD, (1 << 0)), 7661fa7f10bSFabien Thomas PMCMASK(DMND_RFO, (1 << 1)), 7671fa7f10bSFabien Thomas PMCMASK(DMND_IFETCH, (1 << 2)), 7681fa7f10bSFabien Thomas PMCMASK(WB, (1 << 3)), 7691fa7f10bSFabien Thomas PMCMASK(PF_DATA_RD, (1 << 4)), 7701fa7f10bSFabien Thomas PMCMASK(PF_RFO, (1 << 5)), 7711fa7f10bSFabien Thomas PMCMASK(PF_IFETCH, (1 << 6)), 7721fa7f10bSFabien Thomas PMCMASK(OTHER, (1 << 7)), 7731fa7f10bSFabien Thomas PMCMASK(UNCORE_HIT, (1 << 8)), 7741fa7f10bSFabien Thomas PMCMASK(OTHER_CORE_HIT_SNP, (1 << 9)), 7751fa7f10bSFabien Thomas PMCMASK(OTHER_CORE_HITM, (1 << 10)), 7761fa7f10bSFabien Thomas PMCMASK(REMOTE_CACHE_FWD, (1 << 12)), 7771fa7f10bSFabien Thomas PMCMASK(REMOTE_DRAM, (1 << 13)), 7781fa7f10bSFabien Thomas PMCMASK(LOCAL_DRAM, (1 << 14)), 7791fa7f10bSFabien Thomas PMCMASK(NON_DRAM, (1 << 15)), 7801fa7f10bSFabien Thomas NULLMASK 7811fa7f10bSFabien Thomas }; 7821fa7f10bSFabien Thomas 783fabe02f5SSean Bruno static struct pmc_masks iap_rsp_mask_sb_sbx_ib[] = { 7841e862e5aSFabien Thomas PMCMASK(REQ_DMND_DATA_RD, (1ULL << 0)), 7851e862e5aSFabien Thomas PMCMASK(REQ_DMND_RFO, (1ULL << 1)), 7861e862e5aSFabien Thomas PMCMASK(REQ_DMND_IFETCH, (1ULL << 2)), 7871e862e5aSFabien Thomas PMCMASK(REQ_WB, (1ULL << 3)), 7881e862e5aSFabien Thomas PMCMASK(REQ_PF_DATA_RD, (1ULL << 4)), 7891e862e5aSFabien Thomas PMCMASK(REQ_PF_RFO, (1ULL << 5)), 7901e862e5aSFabien Thomas PMCMASK(REQ_PF_IFETCH, (1ULL << 6)), 7911e862e5aSFabien Thomas PMCMASK(REQ_PF_LLC_DATA_RD, (1ULL << 7)), 7921e862e5aSFabien Thomas PMCMASK(REQ_PF_LLC_RFO, (1ULL << 8)), 7931e862e5aSFabien Thomas PMCMASK(REQ_PF_LLC_IFETCH, (1ULL << 9)), 7941e862e5aSFabien Thomas PMCMASK(REQ_BUS_LOCKS, (1ULL << 10)), 7951e862e5aSFabien Thomas PMCMASK(REQ_STRM_ST, (1ULL << 11)), 7961e862e5aSFabien Thomas PMCMASK(REQ_OTHER, (1ULL << 15)), 7971e862e5aSFabien Thomas PMCMASK(RES_ANY, (1ULL << 16)), 7981e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_SUPP, (1ULL << 17)), 7991e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_LLC_HITM, (1ULL << 18)), 8001e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_LLC_HITE, (1ULL << 19)), 8011e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_LLC_HITS, (1ULL << 20)), 8021e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_LLC_HITF, (1ULL << 21)), 8031e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_LOCAL, (1ULL << 22)), 804cdfd0cc8SSean Bruno PMCMASK(RES_SNOOP_SNP_NONE, (1ULL << 31)), 8051e862e5aSFabien Thomas PMCMASK(RES_SNOOP_SNP_NO_NEEDED,(1ULL << 32)), 8061e862e5aSFabien Thomas PMCMASK(RES_SNOOP_SNP_MISS, (1ULL << 33)), 8071e862e5aSFabien Thomas PMCMASK(RES_SNOOP_HIT_NO_FWD, (1ULL << 34)), 8081e862e5aSFabien Thomas PMCMASK(RES_SNOOP_HIT_FWD, (1ULL << 35)), 8091e862e5aSFabien Thomas PMCMASK(RES_SNOOP_HITM, (1ULL << 36)), 8101e862e5aSFabien Thomas PMCMASK(RES_NON_DRAM, (1ULL << 37)), 8111e862e5aSFabien Thomas NULLMASK 8121e862e5aSFabien Thomas }; 8131e862e5aSFabien Thomas 814cc0c1555SSean Bruno static struct pmc_masks iap_rsp_mask_haswell[] = { 815cc0c1555SSean Bruno PMCMASK(REQ_DMND_DATA_RD, (1ULL << 0)), 816cc0c1555SSean Bruno PMCMASK(REQ_DMND_RFO, (1ULL << 1)), 817cc0c1555SSean Bruno PMCMASK(REQ_DMND_IFETCH, (1ULL << 2)), 818cc0c1555SSean Bruno PMCMASK(REQ_PF_DATA_RD, (1ULL << 4)), 819cc0c1555SSean Bruno PMCMASK(REQ_PF_RFO, (1ULL << 5)), 820cc0c1555SSean Bruno PMCMASK(REQ_PF_IFETCH, (1ULL << 6)), 821cc0c1555SSean Bruno PMCMASK(REQ_OTHER, (1ULL << 15)), 822cc0c1555SSean Bruno PMCMASK(RES_ANY, (1ULL << 16)), 823cc0c1555SSean Bruno PMCMASK(RES_SUPPLIER_SUPP, (1ULL << 17)), 824cc0c1555SSean Bruno PMCMASK(RES_SUPPLIER_LLC_HITM, (1ULL << 18)), 825cc0c1555SSean Bruno PMCMASK(RES_SUPPLIER_LLC_HITE, (1ULL << 19)), 826cc0c1555SSean Bruno PMCMASK(RES_SUPPLIER_LLC_HITS, (1ULL << 20)), 827cc0c1555SSean Bruno PMCMASK(RES_SUPPLIER_LLC_HITF, (1ULL << 21)), 828cc0c1555SSean Bruno PMCMASK(RES_SUPPLIER_LOCAL, (1ULL << 22)), 829cc0c1555SSean Bruno PMCMASK(RES_SNOOP_SNP_NONE, (1ULL << 31)), 830cc0c1555SSean Bruno PMCMASK(RES_SNOOP_SNP_NO_NEEDED,(1ULL << 32)), 831cc0c1555SSean Bruno PMCMASK(RES_SNOOP_SNP_MISS, (1ULL << 33)), 832cc0c1555SSean Bruno PMCMASK(RES_SNOOP_HIT_NO_FWD, (1ULL << 34)), 833cc0c1555SSean Bruno PMCMASK(RES_SNOOP_HIT_FWD, (1ULL << 35)), 834cc0c1555SSean Bruno PMCMASK(RES_SNOOP_HITM, (1ULL << 36)), 835cc0c1555SSean Bruno PMCMASK(RES_NON_DRAM, (1ULL << 37)), 836cc0c1555SSean Bruno NULLMASK 837cc0c1555SSean Bruno }; 838cc0c1555SSean Bruno 8390cfab8ddSJoseph Koshy static int 8400cfab8ddSJoseph Koshy iap_allocate_pmc(enum pmc_event pe, char *ctrspec, 8410cfab8ddSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 8420cfab8ddSJoseph Koshy { 8430cfab8ddSJoseph Koshy char *e, *p, *q; 8441e862e5aSFabien Thomas uint64_t cachestate, evmask, rsp; 8450cfab8ddSJoseph Koshy int count, n; 8460cfab8ddSJoseph Koshy 8470cfab8ddSJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE | 8480cfab8ddSJoseph Koshy PMC_CAP_QUALIFIER); 8490cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config = 0; 8500cfab8ddSJoseph Koshy 8511fa7f10bSFabien Thomas cachestate = evmask = rsp = 0; 8520cfab8ddSJoseph Koshy 8530cfab8ddSJoseph Koshy /* Parse additional modifiers if present */ 8540cfab8ddSJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 8550cfab8ddSJoseph Koshy 8560cfab8ddSJoseph Koshy n = 0; 8570cfab8ddSJoseph Koshy if (KWPREFIXMATCH(p, IAP_KW_CMASK "=")) { 8580cfab8ddSJoseph Koshy q = strchr(p, '='); 8590cfab8ddSJoseph Koshy if (*++q == '\0') /* skip '=' */ 8600cfab8ddSJoseph Koshy return (-1); 8610cfab8ddSJoseph Koshy count = strtol(q, &e, 0); 8620cfab8ddSJoseph Koshy if (e == q || *e != '\0') 8630cfab8ddSJoseph Koshy return (-1); 8640cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 8650cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= 8660cfab8ddSJoseph Koshy IAP_CMASK(count); 8670cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_EDGE)) { 8680cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 8690cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_INV)) { 8700cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 8710cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_OS)) { 8720cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 8730cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_USR)) { 8740cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 8750cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_ANYTHREAD)) { 8760cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= IAP_ANY; 877b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_CORE "=")) { 8780cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_core_mask, p, &evmask); 8790cfab8ddSJoseph Koshy if (n != 1) 8800cfab8ddSJoseph Koshy return (-1); 881b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_AGENT "=")) { 8820cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_agent_mask, p, &evmask); 8830cfab8ddSJoseph Koshy if (n != 1) 8840cfab8ddSJoseph Koshy return (-1); 885b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_PREFETCH "=")) { 8860cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_prefetch_mask, p, &evmask); 8870cfab8ddSJoseph Koshy if (n != 1) 8880cfab8ddSJoseph Koshy return (-1); 889b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_CACHESTATE "=")) { 8900cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_cachestate_mask, p, &cachestate); 8910cfab8ddSJoseph Koshy } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_CORE && 892b47ea38eSJoseph Koshy KWPREFIXMATCH(p, IAP_KW_TRANSITION "=")) { 8930cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_transition_mask, p, &evmask); 8940cfab8ddSJoseph Koshy if (n != 1) 8950cfab8ddSJoseph Koshy return (-1); 8960cfab8ddSJoseph Koshy } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM || 897e8f021a3SHiren Panchasara cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM_SILVERMONT || 898b4d091f3SJoseph Koshy cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2 || 8991fa7f10bSFabien Thomas cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2EXTREME) { 900b47ea38eSJoseph Koshy if (KWPREFIXMATCH(p, IAP_KW_SNOOPRESPONSE "=")) { 9010cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_snoopresponse_mask, p, 9020cfab8ddSJoseph Koshy &evmask); 903b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_SNOOPTYPE "=")) { 9040cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_snooptype_mask, p, 9050cfab8ddSJoseph Koshy &evmask); 9060cfab8ddSJoseph Koshy } else 9070cfab8ddSJoseph Koshy return (-1); 9081fa7f10bSFabien Thomas } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_COREI7 || 90949fe48abSKonstantin Belousov cpu_info.pm_cputype == PMC_CPU_INTEL_WESTMERE || 91049fe48abSKonstantin Belousov cpu_info.pm_cputype == PMC_CPU_INTEL_NEHALEM_EX || 91149fe48abSKonstantin Belousov cpu_info.pm_cputype == PMC_CPU_INTEL_WESTMERE_EX) { 9121fa7f10bSFabien Thomas if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 9131e862e5aSFabien Thomas n = pmc_parse_mask(iap_rsp_mask_i7_wm, p, &rsp); 9141e862e5aSFabien Thomas } else 9151e862e5aSFabien Thomas return (-1); 9161e862e5aSFabien Thomas } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_SANDYBRIDGE || 917fabe02f5SSean Bruno cpu_info.pm_cputype == PMC_CPU_INTEL_SANDYBRIDGE_XEON || 9183f929d8cSSean Bruno cpu_info.pm_cputype == PMC_CPU_INTEL_IVYBRIDGE || 9193f929d8cSSean Bruno cpu_info.pm_cputype == PMC_CPU_INTEL_IVYBRIDGE_XEON ) { 9201e862e5aSFabien Thomas if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 921fabe02f5SSean Bruno n = pmc_parse_mask(iap_rsp_mask_sb_sbx_ib, p, &rsp); 9221fa7f10bSFabien Thomas } else 9231fa7f10bSFabien Thomas return (-1); 924d95b3509SRandall Stewart } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_HASWELL || 925d95b3509SRandall Stewart cpu_info.pm_cputype == PMC_CPU_INTEL_HASWELL_XEON) { 926cc0c1555SSean Bruno if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 927cc0c1555SSean Bruno n = pmc_parse_mask(iap_rsp_mask_haswell, p, &rsp); 928cc0c1555SSean Bruno } else 929cc0c1555SSean Bruno return (-1); 9300cfab8ddSJoseph Koshy } else 9310cfab8ddSJoseph Koshy return (-1); 9320cfab8ddSJoseph Koshy 9330cfab8ddSJoseph Koshy if (n < 0) /* Parsing failed. */ 9340cfab8ddSJoseph Koshy return (-1); 9350cfab8ddSJoseph Koshy } 9360cfab8ddSJoseph Koshy 9370cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= evmask; 9380cfab8ddSJoseph Koshy 9390cfab8ddSJoseph Koshy /* 9400cfab8ddSJoseph Koshy * If the event requires a 'cachestate' qualifier but was not 9410cfab8ddSJoseph Koshy * specified by the user, use a sensible default. 9420cfab8ddSJoseph Koshy */ 9430cfab8ddSJoseph Koshy switch (pe) { 9440cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_28H: /* Core, Core2, Atom */ 9450cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_29H: /* Core, Core2, Atom */ 9460cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_2AH: /* Core, Core2, Atom */ 9470cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_2BH: /* Atom, Core2 */ 9480cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_2EH: /* Core, Core2, Atom */ 9490cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_30H: /* Core, Core2, Atom */ 9500cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_32H: /* Core */ 9510cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_40H: /* Core */ 9520cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_41H: /* Core */ 9530cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_42H: /* Core, Core2, Atom */ 9540cfab8ddSJoseph Koshy if (cachestate == 0) 9550cfab8ddSJoseph Koshy cachestate = (0xF << 8); 956aa1b887bSRyan Stone break; 957aa1b887bSRyan Stone case PMC_EV_IAP_EVENT_77H: /* Atom */ 958aa1b887bSRyan Stone /* IAP_EVENT_77H only accepts a cachestate qualifier on the 959aa1b887bSRyan Stone * Atom processor 960aa1b887bSRyan Stone */ 961aa1b887bSRyan Stone if(cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM && cachestate == 0) 962aa1b887bSRyan Stone cachestate = (0xF << 8); 963aa1b887bSRyan Stone break; 9640cfab8ddSJoseph Koshy default: 9650cfab8ddSJoseph Koshy break; 9660cfab8ddSJoseph Koshy } 9670cfab8ddSJoseph Koshy 9680cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= cachestate; 9691fa7f10bSFabien Thomas pmc_config->pm_md.pm_iap.pm_iap_rsp = rsp; 9701fa7f10bSFabien Thomas 9711fa7f10bSFabien Thomas return (0); 9721fa7f10bSFabien Thomas } 9731fa7f10bSFabien Thomas 9741fa7f10bSFabien Thomas /* 9751fa7f10bSFabien Thomas * Intel Uncore. 9761fa7f10bSFabien Thomas */ 9771fa7f10bSFabien Thomas 9781fa7f10bSFabien Thomas static int 9791fa7f10bSFabien Thomas ucf_allocate_pmc(enum pmc_event pe, char *ctrspec, 9801fa7f10bSFabien Thomas struct pmc_op_pmcallocate *pmc_config) 9811fa7f10bSFabien Thomas { 9821fa7f10bSFabien Thomas (void) pe; 9831fa7f10bSFabien Thomas (void) ctrspec; 9841fa7f10bSFabien Thomas 9851fa7f10bSFabien Thomas pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 9861fa7f10bSFabien Thomas pmc_config->pm_md.pm_ucf.pm_ucf_flags = 0; 9871fa7f10bSFabien Thomas 9881fa7f10bSFabien Thomas return (0); 9891fa7f10bSFabien Thomas } 9901fa7f10bSFabien Thomas 9911fa7f10bSFabien Thomas #define UCP_KW_CMASK "cmask" 9921fa7f10bSFabien Thomas #define UCP_KW_EDGE "edge" 9931fa7f10bSFabien Thomas #define UCP_KW_INV "inv" 9941fa7f10bSFabien Thomas 9951fa7f10bSFabien Thomas static int 9961fa7f10bSFabien Thomas ucp_allocate_pmc(enum pmc_event pe, char *ctrspec, 9971fa7f10bSFabien Thomas struct pmc_op_pmcallocate *pmc_config) 9981fa7f10bSFabien Thomas { 9991fa7f10bSFabien Thomas char *e, *p, *q; 10001fa7f10bSFabien Thomas int count, n; 10011fa7f10bSFabien Thomas 10021fa7f10bSFabien Thomas (void) pe; 10031fa7f10bSFabien Thomas 10041fa7f10bSFabien Thomas pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE | 10051fa7f10bSFabien Thomas PMC_CAP_QUALIFIER); 10061fa7f10bSFabien Thomas pmc_config->pm_md.pm_ucp.pm_ucp_config = 0; 10071fa7f10bSFabien Thomas 10081fa7f10bSFabien Thomas /* Parse additional modifiers if present */ 10091fa7f10bSFabien Thomas while ((p = strsep(&ctrspec, ",")) != NULL) { 10101fa7f10bSFabien Thomas 10111fa7f10bSFabien Thomas n = 0; 10121fa7f10bSFabien Thomas if (KWPREFIXMATCH(p, UCP_KW_CMASK "=")) { 10131fa7f10bSFabien Thomas q = strchr(p, '='); 10141fa7f10bSFabien Thomas if (*++q == '\0') /* skip '=' */ 10151fa7f10bSFabien Thomas return (-1); 10161fa7f10bSFabien Thomas count = strtol(q, &e, 0); 10171fa7f10bSFabien Thomas if (e == q || *e != '\0') 10181fa7f10bSFabien Thomas return (-1); 10191fa7f10bSFabien Thomas pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 10201fa7f10bSFabien Thomas pmc_config->pm_md.pm_ucp.pm_ucp_config |= 10211fa7f10bSFabien Thomas UCP_CMASK(count); 10221fa7f10bSFabien Thomas } else if (KWMATCH(p, UCP_KW_EDGE)) { 10231fa7f10bSFabien Thomas pmc_config->pm_caps |= PMC_CAP_EDGE; 10241fa7f10bSFabien Thomas } else if (KWMATCH(p, UCP_KW_INV)) { 10251fa7f10bSFabien Thomas pmc_config->pm_caps |= PMC_CAP_INVERT; 10261fa7f10bSFabien Thomas } else 10271fa7f10bSFabien Thomas return (-1); 10281fa7f10bSFabien Thomas 10291fa7f10bSFabien Thomas if (n < 0) /* Parsing failed. */ 10301fa7f10bSFabien Thomas return (-1); 10311fa7f10bSFabien Thomas } 10320cfab8ddSJoseph Koshy 10330cfab8ddSJoseph Koshy return (0); 10340cfab8ddSJoseph Koshy } 10350cfab8ddSJoseph Koshy 10360cfab8ddSJoseph Koshy /* 1037f263522aSJoseph Koshy * AMD K8 PMCs. 1038f263522aSJoseph Koshy * 1039f263522aSJoseph Koshy * These are very similar to AMD K7 PMCs, but support more kinds of 1040f263522aSJoseph Koshy * events. 1041f263522aSJoseph Koshy */ 1042f263522aSJoseph Koshy 1043f263522aSJoseph Koshy static struct pmc_event_alias k8_aliases[] = { 1044f263522aSJoseph Koshy EV_ALIAS("branches", "k8-fr-retired-taken-branches"), 1045f263522aSJoseph Koshy EV_ALIAS("branch-mispredicts", 1046f263522aSJoseph Koshy "k8-fr-retired-taken-branches-mispredicted"), 1047f263522aSJoseph Koshy EV_ALIAS("cycles", "tsc"), 1048f263522aSJoseph Koshy EV_ALIAS("dc-misses", "k8-dc-miss"), 1049f263522aSJoseph Koshy EV_ALIAS("ic-misses", "k8-ic-miss"), 1050f263522aSJoseph Koshy EV_ALIAS("instructions", "k8-fr-retired-x86-instructions"), 1051f263522aSJoseph Koshy EV_ALIAS("interrupts", "k8-fr-taken-hardware-interrupts"), 1052177a2f22SJoseph Koshy EV_ALIAS("unhalted-cycles", "k8-bu-cpu-clk-unhalted"), 1053f263522aSJoseph Koshy EV_ALIAS(NULL, NULL) 1054f263522aSJoseph Koshy }; 1055f263522aSJoseph Koshy 1056f263522aSJoseph Koshy #define __K8MASK(N,V) PMCMASK(N,(1 << (V))) 1057f263522aSJoseph Koshy 1058f263522aSJoseph Koshy /* 1059f263522aSJoseph Koshy * Parsing tables 1060f263522aSJoseph Koshy */ 1061f263522aSJoseph Koshy 1062f263522aSJoseph Koshy /* fp dispatched fpu ops */ 1063f263522aSJoseph Koshy static const struct pmc_masks k8_mask_fdfo[] = { 1064f263522aSJoseph Koshy __K8MASK(add-pipe-excluding-junk-ops, 0), 1065f263522aSJoseph Koshy __K8MASK(multiply-pipe-excluding-junk-ops, 1), 1066f263522aSJoseph Koshy __K8MASK(store-pipe-excluding-junk-ops, 2), 1067f263522aSJoseph Koshy __K8MASK(add-pipe-junk-ops, 3), 1068f263522aSJoseph Koshy __K8MASK(multiply-pipe-junk-ops, 4), 1069f263522aSJoseph Koshy __K8MASK(store-pipe-junk-ops, 5), 1070f263522aSJoseph Koshy NULLMASK 1071f263522aSJoseph Koshy }; 1072f263522aSJoseph Koshy 1073f263522aSJoseph Koshy /* ls segment register loads */ 1074f263522aSJoseph Koshy static const struct pmc_masks k8_mask_lsrl[] = { 1075f263522aSJoseph Koshy __K8MASK(es, 0), 1076f263522aSJoseph Koshy __K8MASK(cs, 1), 1077f263522aSJoseph Koshy __K8MASK(ss, 2), 1078f263522aSJoseph Koshy __K8MASK(ds, 3), 1079f263522aSJoseph Koshy __K8MASK(fs, 4), 1080f263522aSJoseph Koshy __K8MASK(gs, 5), 1081f263522aSJoseph Koshy __K8MASK(hs, 6), 1082f263522aSJoseph Koshy NULLMASK 1083f263522aSJoseph Koshy }; 1084f263522aSJoseph Koshy 1085f263522aSJoseph Koshy /* ls locked operation */ 1086f263522aSJoseph Koshy static const struct pmc_masks k8_mask_llo[] = { 1087f263522aSJoseph Koshy __K8MASK(locked-instructions, 0), 1088f263522aSJoseph Koshy __K8MASK(cycles-in-request, 1), 1089f263522aSJoseph Koshy __K8MASK(cycles-to-complete, 2), 1090f263522aSJoseph Koshy NULLMASK 1091f263522aSJoseph Koshy }; 1092f263522aSJoseph Koshy 1093f263522aSJoseph Koshy /* dc refill from {l2,system} and dc copyback */ 1094f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dc[] = { 1095f263522aSJoseph Koshy __K8MASK(invalid, 0), 1096f263522aSJoseph Koshy __K8MASK(shared, 1), 1097f263522aSJoseph Koshy __K8MASK(exclusive, 2), 1098f263522aSJoseph Koshy __K8MASK(owner, 3), 1099f263522aSJoseph Koshy __K8MASK(modified, 4), 1100f263522aSJoseph Koshy NULLMASK 1101f263522aSJoseph Koshy }; 1102f263522aSJoseph Koshy 1103f263522aSJoseph Koshy /* dc one bit ecc error */ 1104f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dobee[] = { 1105f263522aSJoseph Koshy __K8MASK(scrubber, 0), 1106f263522aSJoseph Koshy __K8MASK(piggyback, 1), 1107f263522aSJoseph Koshy NULLMASK 1108f263522aSJoseph Koshy }; 1109f263522aSJoseph Koshy 1110f263522aSJoseph Koshy /* dc dispatched prefetch instructions */ 1111f263522aSJoseph Koshy static const struct pmc_masks k8_mask_ddpi[] = { 1112f263522aSJoseph Koshy __K8MASK(load, 0), 1113f263522aSJoseph Koshy __K8MASK(store, 1), 1114f263522aSJoseph Koshy __K8MASK(nta, 2), 1115f263522aSJoseph Koshy NULLMASK 1116f263522aSJoseph Koshy }; 1117f263522aSJoseph Koshy 1118f263522aSJoseph Koshy /* dc dcache accesses by locks */ 1119f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dabl[] = { 1120f263522aSJoseph Koshy __K8MASK(accesses, 0), 1121f263522aSJoseph Koshy __K8MASK(misses, 1), 1122f263522aSJoseph Koshy NULLMASK 1123f263522aSJoseph Koshy }; 1124f263522aSJoseph Koshy 1125f263522aSJoseph Koshy /* bu internal l2 request */ 1126f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bilr[] = { 1127f263522aSJoseph Koshy __K8MASK(ic-fill, 0), 1128f263522aSJoseph Koshy __K8MASK(dc-fill, 1), 1129f263522aSJoseph Koshy __K8MASK(tlb-reload, 2), 1130f263522aSJoseph Koshy __K8MASK(tag-snoop, 3), 1131f263522aSJoseph Koshy __K8MASK(cancelled, 4), 1132f263522aSJoseph Koshy NULLMASK 1133f263522aSJoseph Koshy }; 1134f263522aSJoseph Koshy 1135f263522aSJoseph Koshy /* bu fill request l2 miss */ 1136f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bfrlm[] = { 1137f263522aSJoseph Koshy __K8MASK(ic-fill, 0), 1138f263522aSJoseph Koshy __K8MASK(dc-fill, 1), 1139f263522aSJoseph Koshy __K8MASK(tlb-reload, 2), 1140f263522aSJoseph Koshy NULLMASK 1141f263522aSJoseph Koshy }; 1142f263522aSJoseph Koshy 1143f263522aSJoseph Koshy /* bu fill into l2 */ 1144f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bfil[] = { 1145f263522aSJoseph Koshy __K8MASK(dirty-l2-victim, 0), 1146f263522aSJoseph Koshy __K8MASK(victim-from-l2, 1), 1147f263522aSJoseph Koshy NULLMASK 1148f263522aSJoseph Koshy }; 1149f263522aSJoseph Koshy 1150f263522aSJoseph Koshy /* fr retired fpu instructions */ 1151f263522aSJoseph Koshy static const struct pmc_masks k8_mask_frfi[] = { 1152f263522aSJoseph Koshy __K8MASK(x87, 0), 1153f263522aSJoseph Koshy __K8MASK(mmx-3dnow, 1), 1154f263522aSJoseph Koshy __K8MASK(packed-sse-sse2, 2), 1155f263522aSJoseph Koshy __K8MASK(scalar-sse-sse2, 3), 1156f263522aSJoseph Koshy NULLMASK 1157f263522aSJoseph Koshy }; 1158f263522aSJoseph Koshy 1159f263522aSJoseph Koshy /* fr retired fastpath double op instructions */ 1160f263522aSJoseph Koshy static const struct pmc_masks k8_mask_frfdoi[] = { 1161f263522aSJoseph Koshy __K8MASK(low-op-pos-0, 0), 1162f263522aSJoseph Koshy __K8MASK(low-op-pos-1, 1), 1163f263522aSJoseph Koshy __K8MASK(low-op-pos-2, 2), 1164f263522aSJoseph Koshy NULLMASK 1165f263522aSJoseph Koshy }; 1166f263522aSJoseph Koshy 1167f263522aSJoseph Koshy /* fr fpu exceptions */ 1168f263522aSJoseph Koshy static const struct pmc_masks k8_mask_ffe[] = { 1169f263522aSJoseph Koshy __K8MASK(x87-reclass-microfaults, 0), 1170f263522aSJoseph Koshy __K8MASK(sse-retype-microfaults, 1), 1171f263522aSJoseph Koshy __K8MASK(sse-reclass-microfaults, 2), 1172f263522aSJoseph Koshy __K8MASK(sse-and-x87-microtraps, 3), 1173f263522aSJoseph Koshy NULLMASK 1174f263522aSJoseph Koshy }; 1175f263522aSJoseph Koshy 1176f263522aSJoseph Koshy /* nb memory controller page access event */ 1177f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmcpae[] = { 1178f263522aSJoseph Koshy __K8MASK(page-hit, 0), 1179f263522aSJoseph Koshy __K8MASK(page-miss, 1), 1180f263522aSJoseph Koshy __K8MASK(page-conflict, 2), 1181f263522aSJoseph Koshy NULLMASK 1182f263522aSJoseph Koshy }; 1183f263522aSJoseph Koshy 1184f263522aSJoseph Koshy /* nb memory controller turnaround */ 1185f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmct[] = { 1186f263522aSJoseph Koshy __K8MASK(dimm-turnaround, 0), 1187f263522aSJoseph Koshy __K8MASK(read-to-write-turnaround, 1), 1188f263522aSJoseph Koshy __K8MASK(write-to-read-turnaround, 2), 1189f263522aSJoseph Koshy NULLMASK 1190f263522aSJoseph Koshy }; 1191f263522aSJoseph Koshy 1192f263522aSJoseph Koshy /* nb memory controller bypass saturation */ 1193f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmcbs[] = { 1194f263522aSJoseph Koshy __K8MASK(memory-controller-hi-pri-bypass, 0), 1195f263522aSJoseph Koshy __K8MASK(memory-controller-lo-pri-bypass, 1), 1196f263522aSJoseph Koshy __K8MASK(dram-controller-interface-bypass, 2), 1197f263522aSJoseph Koshy __K8MASK(dram-controller-queue-bypass, 3), 1198f263522aSJoseph Koshy NULLMASK 1199f263522aSJoseph Koshy }; 1200f263522aSJoseph Koshy 1201f263522aSJoseph Koshy /* nb sized commands */ 1202f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nsc[] = { 1203f263522aSJoseph Koshy __K8MASK(nonpostwrszbyte, 0), 1204f263522aSJoseph Koshy __K8MASK(nonpostwrszdword, 1), 1205f263522aSJoseph Koshy __K8MASK(postwrszbyte, 2), 1206f263522aSJoseph Koshy __K8MASK(postwrszdword, 3), 1207f263522aSJoseph Koshy __K8MASK(rdszbyte, 4), 1208f263522aSJoseph Koshy __K8MASK(rdszdword, 5), 1209f263522aSJoseph Koshy __K8MASK(rdmodwr, 6), 1210f263522aSJoseph Koshy NULLMASK 1211f263522aSJoseph Koshy }; 1212f263522aSJoseph Koshy 1213f263522aSJoseph Koshy /* nb probe result */ 1214f263522aSJoseph Koshy static const struct pmc_masks k8_mask_npr[] = { 1215f263522aSJoseph Koshy __K8MASK(probe-miss, 0), 1216f263522aSJoseph Koshy __K8MASK(probe-hit, 1), 1217f263522aSJoseph Koshy __K8MASK(probe-hit-dirty-no-memory-cancel, 2), 1218f263522aSJoseph Koshy __K8MASK(probe-hit-dirty-with-memory-cancel, 3), 1219f263522aSJoseph Koshy NULLMASK 1220f263522aSJoseph Koshy }; 1221f263522aSJoseph Koshy 1222f263522aSJoseph Koshy /* nb hypertransport bus bandwidth */ 1223f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nhbb[] = { /* HT bus bandwidth */ 1224f263522aSJoseph Koshy __K8MASK(command, 0), 1225f263522aSJoseph Koshy __K8MASK(data, 1), 1226f263522aSJoseph Koshy __K8MASK(buffer-release, 2), 1227f263522aSJoseph Koshy __K8MASK(nop, 3), 1228f263522aSJoseph Koshy NULLMASK 1229f263522aSJoseph Koshy }; 1230f263522aSJoseph Koshy 1231f263522aSJoseph Koshy #undef __K8MASK 1232f263522aSJoseph Koshy 1233f263522aSJoseph Koshy #define K8_KW_COUNT "count" 1234f263522aSJoseph Koshy #define K8_KW_EDGE "edge" 1235f263522aSJoseph Koshy #define K8_KW_INV "inv" 1236f263522aSJoseph Koshy #define K8_KW_MASK "mask" 1237f263522aSJoseph Koshy #define K8_KW_OS "os" 1238f263522aSJoseph Koshy #define K8_KW_USR "usr" 1239f263522aSJoseph Koshy 1240f263522aSJoseph Koshy static int 1241f263522aSJoseph Koshy k8_allocate_pmc(enum pmc_event pe, char *ctrspec, 1242f263522aSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 1243f263522aSJoseph Koshy { 1244f263522aSJoseph Koshy char *e, *p, *q; 1245f263522aSJoseph Koshy int n; 12461e862e5aSFabien Thomas uint32_t count; 12471e862e5aSFabien Thomas uint64_t evmask; 1248f263522aSJoseph Koshy const struct pmc_masks *pm, *pmask; 1249f263522aSJoseph Koshy 1250789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1251f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 1252f263522aSJoseph Koshy 1253f263522aSJoseph Koshy pmask = NULL; 1254f263522aSJoseph Koshy evmask = 0; 1255f263522aSJoseph Koshy 1256f263522aSJoseph Koshy #define __K8SETMASK(M) pmask = k8_mask_##M 1257f263522aSJoseph Koshy 1258f263522aSJoseph Koshy /* setup parsing tables */ 1259f263522aSJoseph Koshy switch (pe) { 1260f263522aSJoseph Koshy case PMC_EV_K8_FP_DISPATCHED_FPU_OPS: 1261f263522aSJoseph Koshy __K8SETMASK(fdfo); 1262f263522aSJoseph Koshy break; 1263f263522aSJoseph Koshy case PMC_EV_K8_LS_SEGMENT_REGISTER_LOAD: 1264f263522aSJoseph Koshy __K8SETMASK(lsrl); 1265f263522aSJoseph Koshy break; 1266f263522aSJoseph Koshy case PMC_EV_K8_LS_LOCKED_OPERATION: 1267f263522aSJoseph Koshy __K8SETMASK(llo); 1268f263522aSJoseph Koshy break; 1269f263522aSJoseph Koshy case PMC_EV_K8_DC_REFILL_FROM_L2: 1270f263522aSJoseph Koshy case PMC_EV_K8_DC_REFILL_FROM_SYSTEM: 1271f263522aSJoseph Koshy case PMC_EV_K8_DC_COPYBACK: 1272f263522aSJoseph Koshy __K8SETMASK(dc); 1273f263522aSJoseph Koshy break; 1274f263522aSJoseph Koshy case PMC_EV_K8_DC_ONE_BIT_ECC_ERROR: 1275f263522aSJoseph Koshy __K8SETMASK(dobee); 1276f263522aSJoseph Koshy break; 1277f263522aSJoseph Koshy case PMC_EV_K8_DC_DISPATCHED_PREFETCH_INSTRUCTIONS: 1278f263522aSJoseph Koshy __K8SETMASK(ddpi); 1279f263522aSJoseph Koshy break; 1280f263522aSJoseph Koshy case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS: 1281f263522aSJoseph Koshy __K8SETMASK(dabl); 1282f263522aSJoseph Koshy break; 1283f263522aSJoseph Koshy case PMC_EV_K8_BU_INTERNAL_L2_REQUEST: 1284f263522aSJoseph Koshy __K8SETMASK(bilr); 1285f263522aSJoseph Koshy break; 1286f263522aSJoseph Koshy case PMC_EV_K8_BU_FILL_REQUEST_L2_MISS: 1287f263522aSJoseph Koshy __K8SETMASK(bfrlm); 1288f263522aSJoseph Koshy break; 1289f263522aSJoseph Koshy case PMC_EV_K8_BU_FILL_INTO_L2: 1290f263522aSJoseph Koshy __K8SETMASK(bfil); 1291f263522aSJoseph Koshy break; 1292f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS: 1293f263522aSJoseph Koshy __K8SETMASK(frfi); 1294f263522aSJoseph Koshy break; 1295f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS: 1296f263522aSJoseph Koshy __K8SETMASK(frfdoi); 1297f263522aSJoseph Koshy break; 1298f263522aSJoseph Koshy case PMC_EV_K8_FR_FPU_EXCEPTIONS: 1299f263522aSJoseph Koshy __K8SETMASK(ffe); 1300f263522aSJoseph Koshy break; 1301f263522aSJoseph Koshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_PAGE_ACCESS_EVENT: 1302f263522aSJoseph Koshy __K8SETMASK(nmcpae); 1303f263522aSJoseph Koshy break; 1304f263522aSJoseph Koshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_TURNAROUND: 1305f263522aSJoseph Koshy __K8SETMASK(nmct); 1306f263522aSJoseph Koshy break; 1307f263522aSJoseph Koshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_BYPASS_SATURATION: 1308f263522aSJoseph Koshy __K8SETMASK(nmcbs); 1309f263522aSJoseph Koshy break; 1310f263522aSJoseph Koshy case PMC_EV_K8_NB_SIZED_COMMANDS: 1311f263522aSJoseph Koshy __K8SETMASK(nsc); 1312f263522aSJoseph Koshy break; 1313f263522aSJoseph Koshy case PMC_EV_K8_NB_PROBE_RESULT: 1314f263522aSJoseph Koshy __K8SETMASK(npr); 1315f263522aSJoseph Koshy break; 1316f263522aSJoseph Koshy case PMC_EV_K8_NB_HT_BUS0_BANDWIDTH: 1317f263522aSJoseph Koshy case PMC_EV_K8_NB_HT_BUS1_BANDWIDTH: 1318f263522aSJoseph Koshy case PMC_EV_K8_NB_HT_BUS2_BANDWIDTH: 1319f263522aSJoseph Koshy __K8SETMASK(nhbb); 1320f263522aSJoseph Koshy break; 1321f263522aSJoseph Koshy 1322f263522aSJoseph Koshy default: 1323f263522aSJoseph Koshy break; /* no options defined */ 1324f263522aSJoseph Koshy } 1325f263522aSJoseph Koshy 1326f263522aSJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 1327f263522aSJoseph Koshy if (KWPREFIXMATCH(p, K8_KW_COUNT "=")) { 1328f263522aSJoseph Koshy q = strchr(p, '='); 1329f263522aSJoseph Koshy if (*++q == '\0') /* skip '=' */ 1330aa342b1fSJoseph Koshy return (-1); 1331f263522aSJoseph Koshy 1332f263522aSJoseph Koshy count = strtol(q, &e, 0); 1333f263522aSJoseph Koshy if (e == q || *e != '\0') 1334aa342b1fSJoseph Koshy return (-1); 1335f263522aSJoseph Koshy 1336f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 1337f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config |= 1338f263522aSJoseph Koshy AMD_PMC_TO_COUNTER(count); 1339f263522aSJoseph Koshy 1340f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_EDGE)) { 1341f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1342f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_INV)) { 1343f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 1344f263522aSJoseph Koshy } else if (KWPREFIXMATCH(p, K8_KW_MASK "=")) { 1345f263522aSJoseph Koshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 1346aa342b1fSJoseph Koshy return (-1); 1347f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1348f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_OS)) { 1349f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 1350f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_USR)) { 1351f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 1352f263522aSJoseph Koshy } else 1353aa342b1fSJoseph Koshy return (-1); 1354f263522aSJoseph Koshy } 1355f263522aSJoseph Koshy 1356f263522aSJoseph Koshy /* other post processing */ 1357f263522aSJoseph Koshy switch (pe) { 1358f263522aSJoseph Koshy case PMC_EV_K8_FP_DISPATCHED_FPU_OPS: 1359f263522aSJoseph Koshy case PMC_EV_K8_FP_CYCLES_WITH_NO_FPU_OPS_RETIRED: 1360f263522aSJoseph Koshy case PMC_EV_K8_FP_DISPATCHED_FPU_FAST_FLAG_OPS: 1361f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS: 1362f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS: 1363f263522aSJoseph Koshy case PMC_EV_K8_FR_FPU_EXCEPTIONS: 1364f263522aSJoseph Koshy /* XXX only available in rev B and later */ 1365f263522aSJoseph Koshy break; 1366f263522aSJoseph Koshy case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS: 1367f263522aSJoseph Koshy /* XXX only available in rev C and later */ 1368f263522aSJoseph Koshy break; 1369f263522aSJoseph Koshy case PMC_EV_K8_LS_LOCKED_OPERATION: 1370f263522aSJoseph Koshy /* XXX CPU Rev A,B evmask is to be zero */ 1371f263522aSJoseph Koshy if (evmask & (evmask - 1)) /* > 1 bit set */ 1372aa342b1fSJoseph Koshy return (-1); 1373f263522aSJoseph Koshy if (evmask == 0) { 1374f263522aSJoseph Koshy evmask = 0x01; /* Rev C and later: #instrs */ 1375f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1376f263522aSJoseph Koshy } 1377f263522aSJoseph Koshy break; 1378f263522aSJoseph Koshy default: 1379f263522aSJoseph Koshy if (evmask == 0 && pmask != NULL) { 1380f263522aSJoseph Koshy for (pm = pmask; pm->pm_name; pm++) 1381f263522aSJoseph Koshy evmask |= pm->pm_value; 1382f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1383f263522aSJoseph Koshy } 1384f263522aSJoseph Koshy } 1385f263522aSJoseph Koshy 1386f263522aSJoseph Koshy if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) 1387f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 1388f263522aSJoseph Koshy AMD_PMC_TO_UNITMASK(evmask); 1389f263522aSJoseph Koshy 1390aa342b1fSJoseph Koshy return (0); 1391f263522aSJoseph Koshy } 1392f263522aSJoseph Koshy 1393f263522aSJoseph Koshy #endif 1394f263522aSJoseph Koshy 139586a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 1396f263522aSJoseph Koshy 1397ebccf1e3SJoseph Koshy /* 1398ebccf1e3SJoseph Koshy * Intel P4 PMCs 1399ebccf1e3SJoseph Koshy */ 1400ebccf1e3SJoseph Koshy 1401ebccf1e3SJoseph Koshy static struct pmc_event_alias p4_aliases[] = { 1402d56c5d4bSJoseph Koshy EV_ALIAS("branches", "p4-branch-retired,mask=mmtp+mmtm"), 1403d56c5d4bSJoseph Koshy EV_ALIAS("branch-mispredicts", "p4-mispred-branch-retired"), 1404ebccf1e3SJoseph Koshy EV_ALIAS("cycles", "tsc"), 1405d56c5d4bSJoseph Koshy EV_ALIAS("instructions", 1406d56c5d4bSJoseph Koshy "p4-instr-retired,mask=nbogusntag+nbogustag"), 1407177a2f22SJoseph Koshy EV_ALIAS("unhalted-cycles", "p4-global-power-events"), 1408ebccf1e3SJoseph Koshy EV_ALIAS(NULL, NULL) 1409ebccf1e3SJoseph Koshy }; 1410ebccf1e3SJoseph Koshy 1411ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE "active" 1412ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_ANY "any" 1413ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_BOTH "both" 1414ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_NONE "none" 1415ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_SINGLE "single" 1416ebccf1e3SJoseph Koshy #define P4_KW_BUSREQTYPE "busreqtype" 1417ebccf1e3SJoseph Koshy #define P4_KW_CASCADE "cascade" 1418ebccf1e3SJoseph Koshy #define P4_KW_EDGE "edge" 1419ebccf1e3SJoseph Koshy #define P4_KW_INV "complement" 1420ebccf1e3SJoseph Koshy #define P4_KW_OS "os" 1421ebccf1e3SJoseph Koshy #define P4_KW_MASK "mask" 1422ebccf1e3SJoseph Koshy #define P4_KW_PRECISE "precise" 1423ebccf1e3SJoseph Koshy #define P4_KW_TAG "tag" 1424ebccf1e3SJoseph Koshy #define P4_KW_THRESHOLD "threshold" 1425ebccf1e3SJoseph Koshy #define P4_KW_USR "usr" 1426ebccf1e3SJoseph Koshy 1427ebccf1e3SJoseph Koshy #define __P4MASK(N,V) PMCMASK(N, (1 << (V))) 1428ebccf1e3SJoseph Koshy 1429ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_tcdm[] = { /* tc deliver mode */ 1430ebccf1e3SJoseph Koshy __P4MASK(dd, 0), 1431ebccf1e3SJoseph Koshy __P4MASK(db, 1), 1432ebccf1e3SJoseph Koshy __P4MASK(di, 2), 1433ebccf1e3SJoseph Koshy __P4MASK(bd, 3), 1434ebccf1e3SJoseph Koshy __P4MASK(bb, 4), 1435ebccf1e3SJoseph Koshy __P4MASK(bi, 5), 1436ebccf1e3SJoseph Koshy __P4MASK(id, 6), 1437ebccf1e3SJoseph Koshy __P4MASK(ib, 7), 1438ebccf1e3SJoseph Koshy NULLMASK 1439ebccf1e3SJoseph Koshy }; 1440ebccf1e3SJoseph Koshy 1441ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_bfr[] = { /* bpu fetch request */ 1442ebccf1e3SJoseph Koshy __P4MASK(tcmiss, 0), 1443ebccf1e3SJoseph Koshy NULLMASK, 1444ebccf1e3SJoseph Koshy }; 1445ebccf1e3SJoseph Koshy 1446ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ir[] = { /* itlb reference */ 1447ebccf1e3SJoseph Koshy __P4MASK(hit, 0), 1448ebccf1e3SJoseph Koshy __P4MASK(miss, 1), 1449ebccf1e3SJoseph Koshy __P4MASK(hit-uc, 2), 1450ebccf1e3SJoseph Koshy NULLMASK 1451ebccf1e3SJoseph Koshy }; 1452ebccf1e3SJoseph Koshy 1453ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_memcan[] = { /* memory cancel */ 1454ebccf1e3SJoseph Koshy __P4MASK(st-rb-full, 2), 1455ebccf1e3SJoseph Koshy __P4MASK(64k-conf, 3), 1456ebccf1e3SJoseph Koshy NULLMASK 1457ebccf1e3SJoseph Koshy }; 1458ebccf1e3SJoseph Koshy 1459ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_memcomp[] = { /* memory complete */ 1460ebccf1e3SJoseph Koshy __P4MASK(lsc, 0), 1461ebccf1e3SJoseph Koshy __P4MASK(ssc, 1), 1462ebccf1e3SJoseph Koshy NULLMASK 1463ebccf1e3SJoseph Koshy }; 1464ebccf1e3SJoseph Koshy 1465ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_lpr[] = { /* load port replay */ 1466ebccf1e3SJoseph Koshy __P4MASK(split-ld, 1), 1467ebccf1e3SJoseph Koshy NULLMASK 1468ebccf1e3SJoseph Koshy }; 1469ebccf1e3SJoseph Koshy 1470ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_spr[] = { /* store port replay */ 1471ebccf1e3SJoseph Koshy __P4MASK(split-st, 1), 1472ebccf1e3SJoseph Koshy NULLMASK 1473ebccf1e3SJoseph Koshy }; 1474ebccf1e3SJoseph Koshy 1475ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_mlr[] = { /* mob load replay */ 1476ebccf1e3SJoseph Koshy __P4MASK(no-sta, 1), 1477ebccf1e3SJoseph Koshy __P4MASK(no-std, 3), 1478ebccf1e3SJoseph Koshy __P4MASK(partial-data, 4), 1479ebccf1e3SJoseph Koshy __P4MASK(unalgn-addr, 5), 1480ebccf1e3SJoseph Koshy NULLMASK 1481ebccf1e3SJoseph Koshy }; 1482ebccf1e3SJoseph Koshy 1483ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_pwt[] = { /* page walk type */ 1484ebccf1e3SJoseph Koshy __P4MASK(dtmiss, 0), 1485ebccf1e3SJoseph Koshy __P4MASK(itmiss, 1), 1486ebccf1e3SJoseph Koshy NULLMASK 1487ebccf1e3SJoseph Koshy }; 1488ebccf1e3SJoseph Koshy 1489ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_bcr[] = { /* bsq cache reference */ 1490ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-hits, 0), 1491ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-hite, 1), 1492ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-hitm, 2), 1493ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-hits, 3), 1494ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-hite, 4), 1495ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-hitm, 5), 1496ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-miss, 8), 1497ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-miss, 9), 1498ebccf1e3SJoseph Koshy __P4MASK(wr-2ndl-miss, 10), 1499ebccf1e3SJoseph Koshy NULLMASK 1500ebccf1e3SJoseph Koshy }; 1501ebccf1e3SJoseph Koshy 1502ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ia[] = { /* ioq allocation */ 1503ebccf1e3SJoseph Koshy __P4MASK(all-read, 5), 1504ebccf1e3SJoseph Koshy __P4MASK(all-write, 6), 1505ebccf1e3SJoseph Koshy __P4MASK(mem-uc, 7), 1506ebccf1e3SJoseph Koshy __P4MASK(mem-wc, 8), 1507ebccf1e3SJoseph Koshy __P4MASK(mem-wt, 9), 1508ebccf1e3SJoseph Koshy __P4MASK(mem-wp, 10), 1509ebccf1e3SJoseph Koshy __P4MASK(mem-wb, 11), 1510ebccf1e3SJoseph Koshy __P4MASK(own, 13), 1511ebccf1e3SJoseph Koshy __P4MASK(other, 14), 1512ebccf1e3SJoseph Koshy __P4MASK(prefetch, 15), 1513ebccf1e3SJoseph Koshy NULLMASK 1514ebccf1e3SJoseph Koshy }; 1515ebccf1e3SJoseph Koshy 1516ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_iae[] = { /* ioq active entries */ 1517ebccf1e3SJoseph Koshy __P4MASK(all-read, 5), 1518ebccf1e3SJoseph Koshy __P4MASK(all-write, 6), 1519ebccf1e3SJoseph Koshy __P4MASK(mem-uc, 7), 1520ebccf1e3SJoseph Koshy __P4MASK(mem-wc, 8), 1521ebccf1e3SJoseph Koshy __P4MASK(mem-wt, 9), 1522ebccf1e3SJoseph Koshy __P4MASK(mem-wp, 10), 1523ebccf1e3SJoseph Koshy __P4MASK(mem-wb, 11), 1524ebccf1e3SJoseph Koshy __P4MASK(own, 13), 1525ebccf1e3SJoseph Koshy __P4MASK(other, 14), 1526ebccf1e3SJoseph Koshy __P4MASK(prefetch, 15), 1527ebccf1e3SJoseph Koshy NULLMASK 1528ebccf1e3SJoseph Koshy }; 1529ebccf1e3SJoseph Koshy 1530ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_fda[] = { /* fsb data activity */ 1531ebccf1e3SJoseph Koshy __P4MASK(drdy-drv, 0), 1532ebccf1e3SJoseph Koshy __P4MASK(drdy-own, 1), 1533ebccf1e3SJoseph Koshy __P4MASK(drdy-other, 2), 1534ebccf1e3SJoseph Koshy __P4MASK(dbsy-drv, 3), 1535ebccf1e3SJoseph Koshy __P4MASK(dbsy-own, 4), 1536ebccf1e3SJoseph Koshy __P4MASK(dbsy-other, 5), 1537ebccf1e3SJoseph Koshy NULLMASK 1538ebccf1e3SJoseph Koshy }; 1539ebccf1e3SJoseph Koshy 1540ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ba[] = { /* bsq allocation */ 1541ebccf1e3SJoseph Koshy __P4MASK(req-type0, 0), 1542ebccf1e3SJoseph Koshy __P4MASK(req-type1, 1), 1543ebccf1e3SJoseph Koshy __P4MASK(req-len0, 2), 1544ebccf1e3SJoseph Koshy __P4MASK(req-len1, 3), 1545ebccf1e3SJoseph Koshy __P4MASK(req-io-type, 5), 1546ebccf1e3SJoseph Koshy __P4MASK(req-lock-type, 6), 1547ebccf1e3SJoseph Koshy __P4MASK(req-cache-type, 7), 1548ebccf1e3SJoseph Koshy __P4MASK(req-split-type, 8), 1549ebccf1e3SJoseph Koshy __P4MASK(req-dem-type, 9), 1550ebccf1e3SJoseph Koshy __P4MASK(req-ord-type, 10), 1551ebccf1e3SJoseph Koshy __P4MASK(mem-type0, 11), 1552ebccf1e3SJoseph Koshy __P4MASK(mem-type1, 12), 1553ebccf1e3SJoseph Koshy __P4MASK(mem-type2, 13), 1554ebccf1e3SJoseph Koshy NULLMASK 1555ebccf1e3SJoseph Koshy }; 1556ebccf1e3SJoseph Koshy 1557ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_sia[] = { /* sse input assist */ 1558ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1559ebccf1e3SJoseph Koshy NULLMASK 1560ebccf1e3SJoseph Koshy }; 1561ebccf1e3SJoseph Koshy 1562ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_psu[] = { /* packed sp uop */ 1563ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1564ebccf1e3SJoseph Koshy NULLMASK 1565ebccf1e3SJoseph Koshy }; 1566ebccf1e3SJoseph Koshy 1567ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_pdu[] = { /* packed dp uop */ 1568ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1569ebccf1e3SJoseph Koshy NULLMASK 1570ebccf1e3SJoseph Koshy }; 1571ebccf1e3SJoseph Koshy 1572ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ssu[] = { /* scalar sp uop */ 1573ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1574ebccf1e3SJoseph Koshy NULLMASK 1575ebccf1e3SJoseph Koshy }; 1576ebccf1e3SJoseph Koshy 1577ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_sdu[] = { /* scalar dp uop */ 1578ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1579ebccf1e3SJoseph Koshy NULLMASK 1580ebccf1e3SJoseph Koshy }; 1581ebccf1e3SJoseph Koshy 1582ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_64bmu[] = { /* 64 bit mmx uop */ 1583ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1584ebccf1e3SJoseph Koshy NULLMASK 1585ebccf1e3SJoseph Koshy }; 1586ebccf1e3SJoseph Koshy 1587ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_128bmu[] = { /* 128 bit mmx uop */ 1588ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1589ebccf1e3SJoseph Koshy NULLMASK 1590ebccf1e3SJoseph Koshy }; 1591ebccf1e3SJoseph Koshy 1592ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xfu[] = { /* X87 fp uop */ 1593ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1594ebccf1e3SJoseph Koshy NULLMASK 1595ebccf1e3SJoseph Koshy }; 1596ebccf1e3SJoseph Koshy 1597ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xsmu[] = { /* x87 simd moves uop */ 1598ebccf1e3SJoseph Koshy __P4MASK(allp0, 3), 1599ebccf1e3SJoseph Koshy __P4MASK(allp2, 4), 1600ebccf1e3SJoseph Koshy NULLMASK 1601ebccf1e3SJoseph Koshy }; 1602ebccf1e3SJoseph Koshy 1603ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_gpe[] = { /* global power events */ 1604ebccf1e3SJoseph Koshy __P4MASK(running, 0), 1605ebccf1e3SJoseph Koshy NULLMASK 1606ebccf1e3SJoseph Koshy }; 1607ebccf1e3SJoseph Koshy 1608ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_tmx[] = { /* TC ms xfer */ 1609ebccf1e3SJoseph Koshy __P4MASK(cisc, 0), 1610ebccf1e3SJoseph Koshy NULLMASK 1611ebccf1e3SJoseph Koshy }; 1612ebccf1e3SJoseph Koshy 1613ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_uqw[] = { /* uop queue writes */ 1614ebccf1e3SJoseph Koshy __P4MASK(from-tc-build, 0), 1615ebccf1e3SJoseph Koshy __P4MASK(from-tc-deliver, 1), 1616ebccf1e3SJoseph Koshy __P4MASK(from-rom, 2), 1617ebccf1e3SJoseph Koshy NULLMASK 1618ebccf1e3SJoseph Koshy }; 1619ebccf1e3SJoseph Koshy 1620d56c5d4bSJoseph Koshy static const struct pmc_masks p4_mask_rmbt[] = { 1621d56c5d4bSJoseph Koshy /* retired mispred branch type */ 1622ebccf1e3SJoseph Koshy __P4MASK(conditional, 1), 1623ebccf1e3SJoseph Koshy __P4MASK(call, 2), 1624ebccf1e3SJoseph Koshy __P4MASK(return, 3), 1625ebccf1e3SJoseph Koshy __P4MASK(indirect, 4), 1626ebccf1e3SJoseph Koshy NULLMASK 1627ebccf1e3SJoseph Koshy }; 1628ebccf1e3SJoseph Koshy 1629ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_rbt[] = { /* retired branch type */ 1630ebccf1e3SJoseph Koshy __P4MASK(conditional, 1), 1631ebccf1e3SJoseph Koshy __P4MASK(call, 2), 1632ebccf1e3SJoseph Koshy __P4MASK(retired, 3), 1633ebccf1e3SJoseph Koshy __P4MASK(indirect, 4), 1634ebccf1e3SJoseph Koshy NULLMASK 1635ebccf1e3SJoseph Koshy }; 1636ebccf1e3SJoseph Koshy 1637ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_rs[] = { /* resource stall */ 1638ebccf1e3SJoseph Koshy __P4MASK(sbfull, 5), 1639ebccf1e3SJoseph Koshy NULLMASK 1640ebccf1e3SJoseph Koshy }; 1641ebccf1e3SJoseph Koshy 1642ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_wb[] = { /* WC buffer */ 1643ebccf1e3SJoseph Koshy __P4MASK(wcb-evicts, 0), 1644ebccf1e3SJoseph Koshy __P4MASK(wcb-full-evict, 1), 1645ebccf1e3SJoseph Koshy NULLMASK 1646ebccf1e3SJoseph Koshy }; 1647ebccf1e3SJoseph Koshy 1648ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_fee[] = { /* front end event */ 1649ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1650ebccf1e3SJoseph Koshy __P4MASK(bogus, 1), 1651ebccf1e3SJoseph Koshy NULLMASK 1652ebccf1e3SJoseph Koshy }; 1653ebccf1e3SJoseph Koshy 1654ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ee[] = { /* execution event */ 1655ebccf1e3SJoseph Koshy __P4MASK(nbogus0, 0), 1656ebccf1e3SJoseph Koshy __P4MASK(nbogus1, 1), 1657ebccf1e3SJoseph Koshy __P4MASK(nbogus2, 2), 1658ebccf1e3SJoseph Koshy __P4MASK(nbogus3, 3), 1659ebccf1e3SJoseph Koshy __P4MASK(bogus0, 4), 1660ebccf1e3SJoseph Koshy __P4MASK(bogus1, 5), 1661ebccf1e3SJoseph Koshy __P4MASK(bogus2, 6), 1662ebccf1e3SJoseph Koshy __P4MASK(bogus3, 7), 1663ebccf1e3SJoseph Koshy NULLMASK 1664ebccf1e3SJoseph Koshy }; 1665ebccf1e3SJoseph Koshy 1666ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_re[] = { /* replay event */ 1667ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1668ebccf1e3SJoseph Koshy __P4MASK(bogus, 1), 1669ebccf1e3SJoseph Koshy NULLMASK 1670ebccf1e3SJoseph Koshy }; 1671ebccf1e3SJoseph Koshy 1672ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_insret[] = { /* instr retired */ 1673ebccf1e3SJoseph Koshy __P4MASK(nbogusntag, 0), 1674ebccf1e3SJoseph Koshy __P4MASK(nbogustag, 1), 1675ebccf1e3SJoseph Koshy __P4MASK(bogusntag, 2), 1676ebccf1e3SJoseph Koshy __P4MASK(bogustag, 3), 1677ebccf1e3SJoseph Koshy NULLMASK 1678ebccf1e3SJoseph Koshy }; 1679ebccf1e3SJoseph Koshy 1680ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ur[] = { /* uops retired */ 1681ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1682ebccf1e3SJoseph Koshy __P4MASK(bogus, 1), 1683ebccf1e3SJoseph Koshy NULLMASK 1684ebccf1e3SJoseph Koshy }; 1685ebccf1e3SJoseph Koshy 1686ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ut[] = { /* uop type */ 1687ebccf1e3SJoseph Koshy __P4MASK(tagloads, 1), 1688ebccf1e3SJoseph Koshy __P4MASK(tagstores, 2), 1689ebccf1e3SJoseph Koshy NULLMASK 1690ebccf1e3SJoseph Koshy }; 1691ebccf1e3SJoseph Koshy 1692ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_br[] = { /* branch retired */ 1693ebccf1e3SJoseph Koshy __P4MASK(mmnp, 0), 1694ebccf1e3SJoseph Koshy __P4MASK(mmnm, 1), 1695ebccf1e3SJoseph Koshy __P4MASK(mmtp, 2), 1696ebccf1e3SJoseph Koshy __P4MASK(mmtm, 3), 1697ebccf1e3SJoseph Koshy NULLMASK 1698ebccf1e3SJoseph Koshy }; 1699ebccf1e3SJoseph Koshy 1700ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_mbr[] = { /* mispred branch retired */ 1701ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1702ebccf1e3SJoseph Koshy NULLMASK 1703ebccf1e3SJoseph Koshy }; 1704ebccf1e3SJoseph Koshy 1705ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xa[] = { /* x87 assist */ 1706ebccf1e3SJoseph Koshy __P4MASK(fpsu, 0), 1707ebccf1e3SJoseph Koshy __P4MASK(fpso, 1), 1708ebccf1e3SJoseph Koshy __P4MASK(poao, 2), 1709ebccf1e3SJoseph Koshy __P4MASK(poau, 3), 1710ebccf1e3SJoseph Koshy __P4MASK(prea, 4), 1711ebccf1e3SJoseph Koshy NULLMASK 1712ebccf1e3SJoseph Koshy }; 1713ebccf1e3SJoseph Koshy 1714ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_machclr[] = { /* machine clear */ 1715ebccf1e3SJoseph Koshy __P4MASK(clear, 0), 1716ebccf1e3SJoseph Koshy __P4MASK(moclear, 2), 1717ebccf1e3SJoseph Koshy __P4MASK(smclear, 3), 1718ebccf1e3SJoseph Koshy NULLMASK 1719ebccf1e3SJoseph Koshy }; 1720ebccf1e3SJoseph Koshy 1721ebccf1e3SJoseph Koshy /* P4 event parser */ 1722ebccf1e3SJoseph Koshy static int 1723ebccf1e3SJoseph Koshy p4_allocate_pmc(enum pmc_event pe, char *ctrspec, 1724ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 1725ebccf1e3SJoseph Koshy { 1726ebccf1e3SJoseph Koshy 1727ebccf1e3SJoseph Koshy char *e, *p, *q; 1728ebccf1e3SJoseph Koshy int count, has_tag, has_busreqtype, n; 17291e862e5aSFabien Thomas uint32_t cccractivemask; 17301e862e5aSFabien Thomas uint64_t evmask; 1731ebccf1e3SJoseph Koshy const struct pmc_masks *pm, *pmask; 1732ebccf1e3SJoseph Koshy 1733789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1734f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig = 1735f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 0; 1736ebccf1e3SJoseph Koshy 1737ebccf1e3SJoseph Koshy pmask = NULL; 1738ebccf1e3SJoseph Koshy evmask = 0; 1739ebccf1e3SJoseph Koshy cccractivemask = 0x3; 1740ebccf1e3SJoseph Koshy has_tag = has_busreqtype = 0; 1741ebccf1e3SJoseph Koshy 1742ebccf1e3SJoseph Koshy #define __P4SETMASK(M) do { \ 1743ebccf1e3SJoseph Koshy pmask = p4_mask_##M; \ 1744ebccf1e3SJoseph Koshy } while (0) 1745ebccf1e3SJoseph Koshy 1746ebccf1e3SJoseph Koshy switch (pe) { 1747ebccf1e3SJoseph Koshy case PMC_EV_P4_TC_DELIVER_MODE: 1748ebccf1e3SJoseph Koshy __P4SETMASK(tcdm); 1749ebccf1e3SJoseph Koshy break; 1750ebccf1e3SJoseph Koshy case PMC_EV_P4_BPU_FETCH_REQUEST: 1751ebccf1e3SJoseph Koshy __P4SETMASK(bfr); 1752ebccf1e3SJoseph Koshy break; 1753ebccf1e3SJoseph Koshy case PMC_EV_P4_ITLB_REFERENCE: 1754ebccf1e3SJoseph Koshy __P4SETMASK(ir); 1755ebccf1e3SJoseph Koshy break; 1756ebccf1e3SJoseph Koshy case PMC_EV_P4_MEMORY_CANCEL: 1757ebccf1e3SJoseph Koshy __P4SETMASK(memcan); 1758ebccf1e3SJoseph Koshy break; 1759ebccf1e3SJoseph Koshy case PMC_EV_P4_MEMORY_COMPLETE: 1760ebccf1e3SJoseph Koshy __P4SETMASK(memcomp); 1761ebccf1e3SJoseph Koshy break; 1762ebccf1e3SJoseph Koshy case PMC_EV_P4_LOAD_PORT_REPLAY: 1763ebccf1e3SJoseph Koshy __P4SETMASK(lpr); 1764ebccf1e3SJoseph Koshy break; 1765ebccf1e3SJoseph Koshy case PMC_EV_P4_STORE_PORT_REPLAY: 1766ebccf1e3SJoseph Koshy __P4SETMASK(spr); 1767ebccf1e3SJoseph Koshy break; 1768ebccf1e3SJoseph Koshy case PMC_EV_P4_MOB_LOAD_REPLAY: 1769ebccf1e3SJoseph Koshy __P4SETMASK(mlr); 1770ebccf1e3SJoseph Koshy break; 1771ebccf1e3SJoseph Koshy case PMC_EV_P4_PAGE_WALK_TYPE: 1772ebccf1e3SJoseph Koshy __P4SETMASK(pwt); 1773ebccf1e3SJoseph Koshy break; 1774ebccf1e3SJoseph Koshy case PMC_EV_P4_BSQ_CACHE_REFERENCE: 1775ebccf1e3SJoseph Koshy __P4SETMASK(bcr); 1776ebccf1e3SJoseph Koshy break; 1777ebccf1e3SJoseph Koshy case PMC_EV_P4_IOQ_ALLOCATION: 1778ebccf1e3SJoseph Koshy __P4SETMASK(ia); 1779ebccf1e3SJoseph Koshy has_busreqtype = 1; 1780ebccf1e3SJoseph Koshy break; 1781ebccf1e3SJoseph Koshy case PMC_EV_P4_IOQ_ACTIVE_ENTRIES: 1782ebccf1e3SJoseph Koshy __P4SETMASK(iae); 1783ebccf1e3SJoseph Koshy has_busreqtype = 1; 1784ebccf1e3SJoseph Koshy break; 1785ebccf1e3SJoseph Koshy case PMC_EV_P4_FSB_DATA_ACTIVITY: 1786ebccf1e3SJoseph Koshy __P4SETMASK(fda); 1787ebccf1e3SJoseph Koshy break; 1788ebccf1e3SJoseph Koshy case PMC_EV_P4_BSQ_ALLOCATION: 1789ebccf1e3SJoseph Koshy __P4SETMASK(ba); 1790ebccf1e3SJoseph Koshy break; 1791ebccf1e3SJoseph Koshy case PMC_EV_P4_SSE_INPUT_ASSIST: 1792ebccf1e3SJoseph Koshy __P4SETMASK(sia); 1793ebccf1e3SJoseph Koshy break; 1794ebccf1e3SJoseph Koshy case PMC_EV_P4_PACKED_SP_UOP: 1795ebccf1e3SJoseph Koshy __P4SETMASK(psu); 1796ebccf1e3SJoseph Koshy break; 1797ebccf1e3SJoseph Koshy case PMC_EV_P4_PACKED_DP_UOP: 1798ebccf1e3SJoseph Koshy __P4SETMASK(pdu); 1799ebccf1e3SJoseph Koshy break; 1800ebccf1e3SJoseph Koshy case PMC_EV_P4_SCALAR_SP_UOP: 1801ebccf1e3SJoseph Koshy __P4SETMASK(ssu); 1802ebccf1e3SJoseph Koshy break; 1803ebccf1e3SJoseph Koshy case PMC_EV_P4_SCALAR_DP_UOP: 1804ebccf1e3SJoseph Koshy __P4SETMASK(sdu); 1805ebccf1e3SJoseph Koshy break; 1806ebccf1e3SJoseph Koshy case PMC_EV_P4_64BIT_MMX_UOP: 1807ebccf1e3SJoseph Koshy __P4SETMASK(64bmu); 1808ebccf1e3SJoseph Koshy break; 1809ebccf1e3SJoseph Koshy case PMC_EV_P4_128BIT_MMX_UOP: 1810ebccf1e3SJoseph Koshy __P4SETMASK(128bmu); 1811ebccf1e3SJoseph Koshy break; 1812ebccf1e3SJoseph Koshy case PMC_EV_P4_X87_FP_UOP: 1813ebccf1e3SJoseph Koshy __P4SETMASK(xfu); 1814ebccf1e3SJoseph Koshy break; 1815ebccf1e3SJoseph Koshy case PMC_EV_P4_X87_SIMD_MOVES_UOP: 1816ebccf1e3SJoseph Koshy __P4SETMASK(xsmu); 1817ebccf1e3SJoseph Koshy break; 1818ebccf1e3SJoseph Koshy case PMC_EV_P4_GLOBAL_POWER_EVENTS: 1819ebccf1e3SJoseph Koshy __P4SETMASK(gpe); 1820ebccf1e3SJoseph Koshy break; 1821ebccf1e3SJoseph Koshy case PMC_EV_P4_TC_MS_XFER: 1822ebccf1e3SJoseph Koshy __P4SETMASK(tmx); 1823ebccf1e3SJoseph Koshy break; 1824ebccf1e3SJoseph Koshy case PMC_EV_P4_UOP_QUEUE_WRITES: 1825ebccf1e3SJoseph Koshy __P4SETMASK(uqw); 1826ebccf1e3SJoseph Koshy break; 1827ebccf1e3SJoseph Koshy case PMC_EV_P4_RETIRED_MISPRED_BRANCH_TYPE: 1828ebccf1e3SJoseph Koshy __P4SETMASK(rmbt); 1829ebccf1e3SJoseph Koshy break; 1830ebccf1e3SJoseph Koshy case PMC_EV_P4_RETIRED_BRANCH_TYPE: 1831ebccf1e3SJoseph Koshy __P4SETMASK(rbt); 1832ebccf1e3SJoseph Koshy break; 1833ebccf1e3SJoseph Koshy case PMC_EV_P4_RESOURCE_STALL: 1834ebccf1e3SJoseph Koshy __P4SETMASK(rs); 1835ebccf1e3SJoseph Koshy break; 1836ebccf1e3SJoseph Koshy case PMC_EV_P4_WC_BUFFER: 1837ebccf1e3SJoseph Koshy __P4SETMASK(wb); 1838ebccf1e3SJoseph Koshy break; 1839ebccf1e3SJoseph Koshy case PMC_EV_P4_BSQ_ACTIVE_ENTRIES: 1840ebccf1e3SJoseph Koshy case PMC_EV_P4_B2B_CYCLES: 1841ebccf1e3SJoseph Koshy case PMC_EV_P4_BNR: 1842ebccf1e3SJoseph Koshy case PMC_EV_P4_SNOOP: 1843ebccf1e3SJoseph Koshy case PMC_EV_P4_RESPONSE: 1844ebccf1e3SJoseph Koshy break; 1845ebccf1e3SJoseph Koshy case PMC_EV_P4_FRONT_END_EVENT: 1846ebccf1e3SJoseph Koshy __P4SETMASK(fee); 1847ebccf1e3SJoseph Koshy break; 1848ebccf1e3SJoseph Koshy case PMC_EV_P4_EXECUTION_EVENT: 1849ebccf1e3SJoseph Koshy __P4SETMASK(ee); 1850ebccf1e3SJoseph Koshy break; 1851ebccf1e3SJoseph Koshy case PMC_EV_P4_REPLAY_EVENT: 1852ebccf1e3SJoseph Koshy __P4SETMASK(re); 1853ebccf1e3SJoseph Koshy break; 1854ebccf1e3SJoseph Koshy case PMC_EV_P4_INSTR_RETIRED: 1855ebccf1e3SJoseph Koshy __P4SETMASK(insret); 1856ebccf1e3SJoseph Koshy break; 1857ebccf1e3SJoseph Koshy case PMC_EV_P4_UOPS_RETIRED: 1858ebccf1e3SJoseph Koshy __P4SETMASK(ur); 1859ebccf1e3SJoseph Koshy break; 1860ebccf1e3SJoseph Koshy case PMC_EV_P4_UOP_TYPE: 1861ebccf1e3SJoseph Koshy __P4SETMASK(ut); 1862ebccf1e3SJoseph Koshy break; 1863ebccf1e3SJoseph Koshy case PMC_EV_P4_BRANCH_RETIRED: 1864ebccf1e3SJoseph Koshy __P4SETMASK(br); 1865ebccf1e3SJoseph Koshy break; 1866ebccf1e3SJoseph Koshy case PMC_EV_P4_MISPRED_BRANCH_RETIRED: 1867ebccf1e3SJoseph Koshy __P4SETMASK(mbr); 1868ebccf1e3SJoseph Koshy break; 1869ebccf1e3SJoseph Koshy case PMC_EV_P4_X87_ASSIST: 1870ebccf1e3SJoseph Koshy __P4SETMASK(xa); 1871ebccf1e3SJoseph Koshy break; 1872ebccf1e3SJoseph Koshy case PMC_EV_P4_MACHINE_CLEAR: 1873ebccf1e3SJoseph Koshy __P4SETMASK(machclr); 1874ebccf1e3SJoseph Koshy break; 1875ebccf1e3SJoseph Koshy default: 1876aa342b1fSJoseph Koshy return (-1); 1877ebccf1e3SJoseph Koshy } 1878ebccf1e3SJoseph Koshy 1879ebccf1e3SJoseph Koshy /* process additional flags */ 1880ebccf1e3SJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 1881ebccf1e3SJoseph Koshy if (KWPREFIXMATCH(p, P4_KW_ACTIVE)) { 1882ebccf1e3SJoseph Koshy q = strchr(p, '='); 1883ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1884aa342b1fSJoseph Koshy return (-1); 1885ebccf1e3SJoseph Koshy 1886789140c0SJoseph Koshy if (strcasecmp(q, P4_KW_ACTIVE_NONE) == 0) 1887ebccf1e3SJoseph Koshy cccractivemask = 0x0; 1888789140c0SJoseph Koshy else if (strcasecmp(q, P4_KW_ACTIVE_SINGLE) == 0) 1889ebccf1e3SJoseph Koshy cccractivemask = 0x1; 1890789140c0SJoseph Koshy else if (strcasecmp(q, P4_KW_ACTIVE_BOTH) == 0) 1891ebccf1e3SJoseph Koshy cccractivemask = 0x2; 1892789140c0SJoseph Koshy else if (strcasecmp(q, P4_KW_ACTIVE_ANY) == 0) 1893ebccf1e3SJoseph Koshy cccractivemask = 0x3; 1894ebccf1e3SJoseph Koshy else 1895aa342b1fSJoseph Koshy return (-1); 1896ebccf1e3SJoseph Koshy 1897ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, P4_KW_BUSREQTYPE)) { 1898ebccf1e3SJoseph Koshy if (has_busreqtype == 0) 1899aa342b1fSJoseph Koshy return (-1); 1900ebccf1e3SJoseph Koshy 1901ebccf1e3SJoseph Koshy q = strchr(p, '='); 1902ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1903aa342b1fSJoseph Koshy return (-1); 1904ebccf1e3SJoseph Koshy 1905ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 1906ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 1907aa342b1fSJoseph Koshy return (-1); 1908ebccf1e3SJoseph Koshy evmask = (evmask & ~0x1F) | (count & 0x1F); 1909ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P4_KW_CASCADE)) 1910ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_CASCADE; 1911ebccf1e3SJoseph Koshy else if (KWMATCH(p, P4_KW_EDGE)) 1912ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1913ebccf1e3SJoseph Koshy else if (KWMATCH(p, P4_KW_INV)) 1914ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 1915ebccf1e3SJoseph Koshy else if (KWPREFIXMATCH(p, P4_KW_MASK "=")) { 1916ebccf1e3SJoseph Koshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 1917aa342b1fSJoseph Koshy return (-1); 1918ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1919ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P4_KW_OS)) 1920ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 1921ebccf1e3SJoseph Koshy else if (KWMATCH(p, P4_KW_PRECISE)) 1922ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_PRECISE; 1923ebccf1e3SJoseph Koshy else if (KWPREFIXMATCH(p, P4_KW_TAG "=")) { 1924ebccf1e3SJoseph Koshy if (has_tag == 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 1935ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_TAGGING; 1936f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig |= 1937ebccf1e3SJoseph Koshy P4_ESCR_TO_TAG_VALUE(count); 1938ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, P4_KW_THRESHOLD "=")) { 1939ebccf1e3SJoseph Koshy q = strchr(p, '='); 1940ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1941aa342b1fSJoseph Koshy return (-1); 1942ebccf1e3SJoseph Koshy 1943ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 1944ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 1945aa342b1fSJoseph Koshy return (-1); 1946ebccf1e3SJoseph Koshy 1947ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 1948f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig &= 1949f263522aSJoseph Koshy ~P4_CCCR_THRESHOLD_MASK; 1950f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |= 1951f263522aSJoseph Koshy P4_CCCR_TO_THRESHOLD(count); 1952ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P4_KW_USR)) 1953ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 1954ebccf1e3SJoseph Koshy else 1955aa342b1fSJoseph Koshy return (-1); 1956ebccf1e3SJoseph Koshy } 1957ebccf1e3SJoseph Koshy 1958ebccf1e3SJoseph Koshy /* other post processing */ 1959ebccf1e3SJoseph Koshy if (pe == PMC_EV_P4_IOQ_ALLOCATION || 1960ebccf1e3SJoseph Koshy pe == PMC_EV_P4_FSB_DATA_ACTIVITY || 1961ebccf1e3SJoseph Koshy pe == PMC_EV_P4_BSQ_ALLOCATION) 1962ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1963ebccf1e3SJoseph Koshy 1964ebccf1e3SJoseph Koshy /* fill in thread activity mask */ 1965f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |= 1966ebccf1e3SJoseph Koshy P4_CCCR_TO_ACTIVE_THREAD(cccractivemask); 1967ebccf1e3SJoseph Koshy 1968ebccf1e3SJoseph Koshy if (evmask) 1969ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1970ebccf1e3SJoseph Koshy 1971ebccf1e3SJoseph Koshy switch (pe) { 1972ebccf1e3SJoseph Koshy case PMC_EV_P4_FSB_DATA_ACTIVITY: 1973ebccf1e3SJoseph Koshy if ((evmask & 0x06) == 0x06 || 1974ebccf1e3SJoseph Koshy (evmask & 0x18) == 0x18) 1975aa342b1fSJoseph Koshy return (-1); /* can't have own+other bits together */ 1976ebccf1e3SJoseph Koshy if (evmask == 0) /* default:drdy-{drv,own}+dbsy{drv,own} */ 1977ebccf1e3SJoseph Koshy evmask = 0x1D; 1978ebccf1e3SJoseph Koshy break; 1979ebccf1e3SJoseph Koshy case PMC_EV_P4_MACHINE_CLEAR: 1980ebccf1e3SJoseph Koshy /* only one bit is allowed to be set */ 1981ebccf1e3SJoseph Koshy if ((evmask & (evmask - 1)) != 0) 1982aa342b1fSJoseph Koshy return (-1); 1983ebccf1e3SJoseph Koshy if (evmask == 0) { 1984ebccf1e3SJoseph Koshy evmask = 0x1; /* 'CLEAR' */ 1985ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1986ebccf1e3SJoseph Koshy } 1987ebccf1e3SJoseph Koshy break; 1988ebccf1e3SJoseph Koshy default: 1989ebccf1e3SJoseph Koshy if (evmask == 0 && pmask) { 1990ebccf1e3SJoseph Koshy for (pm = pmask; pm->pm_name; pm++) 1991ebccf1e3SJoseph Koshy evmask |= pm->pm_value; 1992ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1993ebccf1e3SJoseph Koshy } 1994ebccf1e3SJoseph Koshy } 1995ebccf1e3SJoseph Koshy 1996f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 1997f263522aSJoseph Koshy P4_ESCR_TO_EVENT_MASK(evmask); 1998ebccf1e3SJoseph Koshy 1999aa342b1fSJoseph Koshy return (0); 2000ebccf1e3SJoseph Koshy } 2001ebccf1e3SJoseph Koshy 200286a65549SJoseph Koshy #endif 200386a65549SJoseph Koshy 200486a65549SJoseph Koshy #if defined(__i386__) 200586a65549SJoseph Koshy 2006ebccf1e3SJoseph Koshy /* 2007f263522aSJoseph Koshy * Pentium style PMCs 2008f263522aSJoseph Koshy */ 2009f263522aSJoseph Koshy 2010f263522aSJoseph Koshy static struct pmc_event_alias p5_aliases[] = { 20110b9b757dSJoseph Koshy EV_ALIAS("branches", "p5-taken-branches"), 2012f263522aSJoseph Koshy EV_ALIAS("cycles", "tsc"), 20130b9b757dSJoseph Koshy EV_ALIAS("dc-misses", "p5-data-read-miss-or-write-miss"), 20140b9b757dSJoseph Koshy EV_ALIAS("ic-misses", "p5-code-cache-miss"), 20150b9b757dSJoseph Koshy EV_ALIAS("instructions", "p5-instructions-executed"), 20160b9b757dSJoseph Koshy EV_ALIAS("interrupts", "p5-hardware-interrupts"), 20170b9b757dSJoseph Koshy EV_ALIAS("unhalted-cycles", 20180b9b757dSJoseph Koshy "p5-number-of-cycles-not-in-halt-state"), 2019f263522aSJoseph Koshy EV_ALIAS(NULL, NULL) 2020f263522aSJoseph Koshy }; 2021f263522aSJoseph Koshy 2022f263522aSJoseph Koshy static int 2023f263522aSJoseph Koshy p5_allocate_pmc(enum pmc_event pe, char *ctrspec, 2024f263522aSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 2025f263522aSJoseph Koshy { 2026aa342b1fSJoseph Koshy return (-1 || pe || ctrspec || pmc_config); /* shut up gcc */ 2027f263522aSJoseph Koshy } 2028f263522aSJoseph Koshy 2029f263522aSJoseph Koshy /* 2030ebccf1e3SJoseph Koshy * Pentium Pro style PMCs. These PMCs are found in Pentium II, Pentium III, 2031ebccf1e3SJoseph Koshy * and Pentium M CPUs. 2032ebccf1e3SJoseph Koshy */ 2033ebccf1e3SJoseph Koshy 2034ebccf1e3SJoseph Koshy static struct pmc_event_alias p6_aliases[] = { 2035ebccf1e3SJoseph Koshy EV_ALIAS("branches", "p6-br-inst-retired"), 2036ebccf1e3SJoseph Koshy EV_ALIAS("branch-mispredicts", "p6-br-miss-pred-retired"), 2037ebccf1e3SJoseph Koshy EV_ALIAS("cycles", "tsc"), 2038d56c5d4bSJoseph Koshy EV_ALIAS("dc-misses", "p6-dcu-lines-in"), 203973e2d811SJoseph Koshy EV_ALIAS("ic-misses", "p6-ifu-fetch-miss"), 2040ebccf1e3SJoseph Koshy EV_ALIAS("instructions", "p6-inst-retired"), 2041ebccf1e3SJoseph Koshy EV_ALIAS("interrupts", "p6-hw-int-rx"), 2042177a2f22SJoseph Koshy EV_ALIAS("unhalted-cycles", "p6-cpu-clk-unhalted"), 2043ebccf1e3SJoseph Koshy EV_ALIAS(NULL, NULL) 2044ebccf1e3SJoseph Koshy }; 2045ebccf1e3SJoseph Koshy 2046ebccf1e3SJoseph Koshy #define P6_KW_CMASK "cmask" 2047ebccf1e3SJoseph Koshy #define P6_KW_EDGE "edge" 2048ebccf1e3SJoseph Koshy #define P6_KW_INV "inv" 2049ebccf1e3SJoseph Koshy #define P6_KW_OS "os" 2050ebccf1e3SJoseph Koshy #define P6_KW_UMASK "umask" 2051ebccf1e3SJoseph Koshy #define P6_KW_USR "usr" 2052ebccf1e3SJoseph Koshy 2053ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mesi[] = { 2054ebccf1e3SJoseph Koshy PMCMASK(m, 0x01), 2055ebccf1e3SJoseph Koshy PMCMASK(e, 0x02), 2056ebccf1e3SJoseph Koshy PMCMASK(s, 0x04), 2057ebccf1e3SJoseph Koshy PMCMASK(i, 0x08), 2058ebccf1e3SJoseph Koshy NULLMASK 2059ebccf1e3SJoseph Koshy }; 2060ebccf1e3SJoseph Koshy 2061ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mesihw[] = { 2062ebccf1e3SJoseph Koshy PMCMASK(m, 0x01), 2063ebccf1e3SJoseph Koshy PMCMASK(e, 0x02), 2064ebccf1e3SJoseph Koshy PMCMASK(s, 0x04), 2065ebccf1e3SJoseph Koshy PMCMASK(i, 0x08), 2066ebccf1e3SJoseph Koshy PMCMASK(nonhw, 0x00), 2067ebccf1e3SJoseph Koshy PMCMASK(hw, 0x10), 2068ebccf1e3SJoseph Koshy PMCMASK(both, 0x30), 2069ebccf1e3SJoseph Koshy NULLMASK 2070ebccf1e3SJoseph Koshy }; 2071ebccf1e3SJoseph Koshy 2072ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_hw[] = { 2073ebccf1e3SJoseph Koshy PMCMASK(nonhw, 0x00), 2074ebccf1e3SJoseph Koshy PMCMASK(hw, 0x10), 2075ebccf1e3SJoseph Koshy PMCMASK(both, 0x30), 2076ebccf1e3SJoseph Koshy NULLMASK 2077ebccf1e3SJoseph Koshy }; 2078ebccf1e3SJoseph Koshy 2079ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_any[] = { 2080ebccf1e3SJoseph Koshy PMCMASK(self, 0x00), 2081ebccf1e3SJoseph Koshy PMCMASK(any, 0x20), 2082ebccf1e3SJoseph Koshy NULLMASK 2083ebccf1e3SJoseph Koshy }; 2084ebccf1e3SJoseph Koshy 2085ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_ekp[] = { 2086ebccf1e3SJoseph Koshy PMCMASK(nta, 0x00), 2087ebccf1e3SJoseph Koshy PMCMASK(t1, 0x01), 2088ebccf1e3SJoseph Koshy PMCMASK(t2, 0x02), 2089ebccf1e3SJoseph Koshy PMCMASK(wos, 0x03), 2090ebccf1e3SJoseph Koshy NULLMASK 2091ebccf1e3SJoseph Koshy }; 2092ebccf1e3SJoseph Koshy 2093ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_pps[] = { 2094ebccf1e3SJoseph Koshy PMCMASK(packed-and-scalar, 0x00), 2095ebccf1e3SJoseph Koshy PMCMASK(scalar, 0x01), 2096ebccf1e3SJoseph Koshy NULLMASK 2097ebccf1e3SJoseph Koshy }; 2098ebccf1e3SJoseph Koshy 2099ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mite[] = { 2100ebccf1e3SJoseph Koshy PMCMASK(packed-multiply, 0x01), 2101ebccf1e3SJoseph Koshy PMCMASK(packed-shift, 0x02), 2102ebccf1e3SJoseph Koshy PMCMASK(pack, 0x04), 2103ebccf1e3SJoseph Koshy PMCMASK(unpack, 0x08), 2104ebccf1e3SJoseph Koshy PMCMASK(packed-logical, 0x10), 2105ebccf1e3SJoseph Koshy PMCMASK(packed-arithmetic, 0x20), 2106ebccf1e3SJoseph Koshy NULLMASK 2107ebccf1e3SJoseph Koshy }; 2108ebccf1e3SJoseph Koshy 2109ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_fmt[] = { 2110ebccf1e3SJoseph Koshy PMCMASK(mmxtofp, 0x00), 2111ebccf1e3SJoseph Koshy PMCMASK(fptommx, 0x01), 2112ebccf1e3SJoseph Koshy NULLMASK 2113ebccf1e3SJoseph Koshy }; 2114ebccf1e3SJoseph Koshy 2115ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_sr[] = { 2116ebccf1e3SJoseph Koshy PMCMASK(es, 0x01), 2117ebccf1e3SJoseph Koshy PMCMASK(ds, 0x02), 2118ebccf1e3SJoseph Koshy PMCMASK(fs, 0x04), 2119ebccf1e3SJoseph Koshy PMCMASK(gs, 0x08), 2120ebccf1e3SJoseph Koshy NULLMASK 2121ebccf1e3SJoseph Koshy }; 2122ebccf1e3SJoseph Koshy 2123ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_eet[] = { 2124ebccf1e3SJoseph Koshy PMCMASK(all, 0x00), 2125ebccf1e3SJoseph Koshy PMCMASK(freq, 0x02), 2126ebccf1e3SJoseph Koshy NULLMASK 2127ebccf1e3SJoseph Koshy }; 2128ebccf1e3SJoseph Koshy 2129ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_efur[] = { 2130ebccf1e3SJoseph Koshy PMCMASK(all, 0x00), 2131ebccf1e3SJoseph Koshy PMCMASK(loadop, 0x01), 2132ebccf1e3SJoseph Koshy PMCMASK(stdsta, 0x02), 2133ebccf1e3SJoseph Koshy NULLMASK 2134ebccf1e3SJoseph Koshy }; 2135ebccf1e3SJoseph Koshy 2136ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_essir[] = { 2137ebccf1e3SJoseph Koshy PMCMASK(sse-packed-single, 0x00), 2138ebccf1e3SJoseph Koshy PMCMASK(sse-packed-single-scalar-single, 0x01), 2139ebccf1e3SJoseph Koshy PMCMASK(sse2-packed-double, 0x02), 2140ebccf1e3SJoseph Koshy PMCMASK(sse2-scalar-double, 0x03), 2141ebccf1e3SJoseph Koshy NULLMASK 2142ebccf1e3SJoseph Koshy }; 2143ebccf1e3SJoseph Koshy 2144ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_esscir[] = { 2145ebccf1e3SJoseph Koshy PMCMASK(sse-packed-single, 0x00), 2146ebccf1e3SJoseph Koshy PMCMASK(sse-scalar-single, 0x01), 2147ebccf1e3SJoseph Koshy PMCMASK(sse2-packed-double, 0x02), 2148ebccf1e3SJoseph Koshy PMCMASK(sse2-scalar-double, 0x03), 2149ebccf1e3SJoseph Koshy NULLMASK 2150ebccf1e3SJoseph Koshy }; 2151ebccf1e3SJoseph Koshy 2152ebccf1e3SJoseph Koshy /* P6 event parser */ 2153ebccf1e3SJoseph Koshy static int 2154ebccf1e3SJoseph Koshy p6_allocate_pmc(enum pmc_event pe, char *ctrspec, 2155ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 2156ebccf1e3SJoseph Koshy { 2157ebccf1e3SJoseph Koshy char *e, *p, *q; 21581e862e5aSFabien Thomas uint64_t evmask; 2159ebccf1e3SJoseph Koshy int count, n; 2160ebccf1e3SJoseph Koshy const struct pmc_masks *pm, *pmask; 2161ebccf1e3SJoseph Koshy 2162789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2163f263522aSJoseph Koshy pmc_config->pm_md.pm_ppro.pm_ppro_config = 0; 2164ebccf1e3SJoseph Koshy 2165ebccf1e3SJoseph Koshy evmask = 0; 2166ebccf1e3SJoseph Koshy 2167ebccf1e3SJoseph Koshy #define P6MASKSET(M) pmask = p6_mask_ ## M 2168ebccf1e3SJoseph Koshy 2169ebccf1e3SJoseph Koshy switch(pe) { 2170ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_IFETCH: P6MASKSET(mesi); break; 2171ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_LD: P6MASKSET(mesi); break; 2172ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_ST: P6MASKSET(mesi); break; 2173ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_RQSTS: P6MASKSET(mesi); break; 2174ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_DRDY_CLOCKS: 2175ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_LOCK_CLOCKS: 2176ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BRD: 2177ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_RFO: 2178ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_WB: 2179ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_IFETCH: 2180ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_INVAL: 2181ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_PWR: 2182ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_P: 2183ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_IO: 2184ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_DEF: 2185ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BURST: 2186ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_ANY: 2187ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_MEM: 2188ebccf1e3SJoseph Koshy P6MASKSET(any); break; 2189ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED: 2190ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_MISS: 2191ebccf1e3SJoseph Koshy P6MASKSET(ekp); break; 2192ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_INST_RETIRED: 2193ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_COMP_INST_RET: 2194ebccf1e3SJoseph Koshy P6MASKSET(pps); break; 2195ebccf1e3SJoseph Koshy case PMC_EV_P6_MMX_INSTR_TYPE_EXEC: 2196ebccf1e3SJoseph Koshy P6MASKSET(mite); break; 2197ebccf1e3SJoseph Koshy case PMC_EV_P6_FP_MMX_TRANS: 2198ebccf1e3SJoseph Koshy P6MASKSET(fmt); break; 2199ebccf1e3SJoseph Koshy case PMC_EV_P6_SEG_RENAME_STALLS: 2200ebccf1e3SJoseph Koshy case PMC_EV_P6_SEG_REG_RENAMES: 2201ebccf1e3SJoseph Koshy P6MASKSET(sr); break; 2202ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_EST_TRANS: 2203ebccf1e3SJoseph Koshy P6MASKSET(eet); break; 2204ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_FUSED_UOPS_RET: 2205ebccf1e3SJoseph Koshy P6MASKSET(efur); break; 2206ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED: 2207ebccf1e3SJoseph Koshy P6MASKSET(essir); break; 2208ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED: 2209ebccf1e3SJoseph Koshy P6MASKSET(esscir); break; 2210ebccf1e3SJoseph Koshy default: 2211ebccf1e3SJoseph Koshy pmask = NULL; 2212ebccf1e3SJoseph Koshy break; 2213ebccf1e3SJoseph Koshy } 2214ebccf1e3SJoseph Koshy 2215ebccf1e3SJoseph Koshy /* Pentium M PMCs have a few events with different semantics */ 2216ebccf1e3SJoseph Koshy if (cpu_info.pm_cputype == PMC_CPU_INTEL_PM) { 2217ebccf1e3SJoseph Koshy if (pe == PMC_EV_P6_L2_LD || 2218ebccf1e3SJoseph Koshy pe == PMC_EV_P6_L2_LINES_IN || 2219ebccf1e3SJoseph Koshy pe == PMC_EV_P6_L2_LINES_OUT) 2220ebccf1e3SJoseph Koshy P6MASKSET(mesihw); 2221ebccf1e3SJoseph Koshy else if (pe == PMC_EV_P6_L2_M_LINES_OUTM) 2222ebccf1e3SJoseph Koshy P6MASKSET(hw); 2223ebccf1e3SJoseph Koshy } 2224ebccf1e3SJoseph Koshy 2225ebccf1e3SJoseph Koshy /* Parse additional modifiers if present */ 2226ebccf1e3SJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 2227ebccf1e3SJoseph Koshy if (KWPREFIXMATCH(p, P6_KW_CMASK "=")) { 2228ebccf1e3SJoseph Koshy q = strchr(p, '='); 2229ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 2230aa342b1fSJoseph Koshy return (-1); 2231ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 2232ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 2233aa342b1fSJoseph Koshy return (-1); 2234ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 2235f263522aSJoseph Koshy pmc_config->pm_md.pm_ppro.pm_ppro_config |= 2236f263522aSJoseph Koshy P6_EVSEL_TO_CMASK(count); 2237ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_EDGE)) { 2238ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 2239ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_INV)) { 2240ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 2241ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_OS)) { 2242ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2243ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, P6_KW_UMASK "=")) { 2244ebccf1e3SJoseph Koshy evmask = 0; 2245ebccf1e3SJoseph Koshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 2246aa342b1fSJoseph Koshy return (-1); 2247ebccf1e3SJoseph Koshy if ((pe == PMC_EV_P6_BUS_DRDY_CLOCKS || 2248ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_LOCK_CLOCKS || 2249ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_BRD || 2250ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_RFO || 2251ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_IFETCH || 2252ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_INVAL || 2253ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_PWR || 2254ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_DEF || 2255ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_BURST || 2256ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_ANY || 2257ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_MEM || 2258ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRANS_IO || 2259ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRANS_P || 2260ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRANS_WB || 2261ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_EST_TRANS || 2262ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_FUSED_UOPS_RET || 2263ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_COMP_INST_RET || 2264ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_INST_RETIRED || 2265ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_PREF_DISPATCHED || 2266ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_PREF_MISS || 2267ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED || 2268ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED || 2269ebccf1e3SJoseph Koshy pe == PMC_EV_P6_FP_MMX_TRANS) 2270aa342b1fSJoseph Koshy && (n > 1)) /* Only one mask keyword is allowed. */ 2271aa342b1fSJoseph Koshy return (-1); 2272ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2273ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_USR)) { 2274ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 2275ebccf1e3SJoseph Koshy } else 2276aa342b1fSJoseph Koshy return (-1); 2277ebccf1e3SJoseph Koshy } 2278ebccf1e3SJoseph Koshy 2279ebccf1e3SJoseph Koshy /* post processing */ 2280ebccf1e3SJoseph Koshy switch (pe) { 2281ebccf1e3SJoseph Koshy 2282ebccf1e3SJoseph Koshy /* 2283ebccf1e3SJoseph Koshy * The following events default to an evmask of 0 2284ebccf1e3SJoseph Koshy */ 2285ebccf1e3SJoseph Koshy 2286ebccf1e3SJoseph Koshy /* default => 'self' */ 2287ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_DRDY_CLOCKS: 2288ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_LOCK_CLOCKS: 2289ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BRD: 2290ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_RFO: 2291ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_WB: 2292ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_IFETCH: 2293ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_INVAL: 2294ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_PWR: 2295ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_P: 2296ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_IO: 2297ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_DEF: 2298ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BURST: 2299ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_ANY: 2300ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_MEM: 2301ebccf1e3SJoseph Koshy 2302ebccf1e3SJoseph Koshy /* default => 'nta' */ 2303ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED: 2304ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_MISS: 2305ebccf1e3SJoseph Koshy 2306ebccf1e3SJoseph Koshy /* default => 'packed and scalar' */ 2307ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_INST_RETIRED: 2308ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_COMP_INST_RET: 2309ebccf1e3SJoseph Koshy 2310ebccf1e3SJoseph Koshy /* default => 'mmx to fp transitions' */ 2311ebccf1e3SJoseph Koshy case PMC_EV_P6_FP_MMX_TRANS: 2312ebccf1e3SJoseph Koshy 2313ebccf1e3SJoseph Koshy /* default => 'SSE Packed Single' */ 2314ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED: 2315ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED: 2316ebccf1e3SJoseph Koshy 2317ebccf1e3SJoseph Koshy /* default => 'all fused micro-ops' */ 2318ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_FUSED_UOPS_RET: 2319ebccf1e3SJoseph Koshy 2320ebccf1e3SJoseph Koshy /* default => 'all transitions' */ 2321ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_EST_TRANS: 2322ebccf1e3SJoseph Koshy break; 2323ebccf1e3SJoseph Koshy 2324ebccf1e3SJoseph Koshy case PMC_EV_P6_MMX_UOPS_EXEC: 2325ebccf1e3SJoseph Koshy evmask = 0x0F; /* only value allowed */ 2326ebccf1e3SJoseph Koshy break; 2327ebccf1e3SJoseph Koshy 2328ebccf1e3SJoseph Koshy default: 2329ebccf1e3SJoseph Koshy /* 2330ebccf1e3SJoseph Koshy * For all other events, set the default event mask 2331ebccf1e3SJoseph Koshy * to a logical OR of all the allowed event mask bits. 2332ebccf1e3SJoseph Koshy */ 2333ebccf1e3SJoseph Koshy if (evmask == 0 && pmask) { 2334ebccf1e3SJoseph Koshy for (pm = pmask; pm->pm_name; pm++) 2335ebccf1e3SJoseph Koshy evmask |= pm->pm_value; 2336ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2337ebccf1e3SJoseph Koshy } 2338ebccf1e3SJoseph Koshy 2339ebccf1e3SJoseph Koshy break; 2340ebccf1e3SJoseph Koshy } 2341ebccf1e3SJoseph Koshy 2342ebccf1e3SJoseph Koshy if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) 2343f263522aSJoseph Koshy pmc_config->pm_md.pm_ppro.pm_ppro_config |= 2344f263522aSJoseph Koshy P6_EVSEL_TO_UMASK(evmask); 2345ebccf1e3SJoseph Koshy 2346aa342b1fSJoseph Koshy return (0); 2347ebccf1e3SJoseph Koshy } 2348ebccf1e3SJoseph Koshy 2349ebccf1e3SJoseph Koshy #endif 2350ebccf1e3SJoseph Koshy 2351789140c0SJoseph Koshy #if defined(__i386__) || defined(__amd64__) 2352789140c0SJoseph Koshy static int 2353789140c0SJoseph Koshy tsc_allocate_pmc(enum pmc_event pe, char *ctrspec, 2354789140c0SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 2355789140c0SJoseph Koshy { 2356789140c0SJoseph Koshy if (pe != PMC_EV_TSC_TSC) 2357789140c0SJoseph Koshy return (-1); 2358789140c0SJoseph Koshy 2359789140c0SJoseph Koshy /* TSC events must be unqualified. */ 2360789140c0SJoseph Koshy if (ctrspec && *ctrspec != '\0') 2361789140c0SJoseph Koshy return (-1); 2362789140c0SJoseph Koshy 2363789140c0SJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 2364789140c0SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_READ; 2365789140c0SJoseph Koshy 2366789140c0SJoseph Koshy return (0); 2367789140c0SJoseph Koshy } 2368789140c0SJoseph Koshy #endif 2369789140c0SJoseph Koshy 2370f5f9340bSFabien Thomas static struct pmc_event_alias generic_aliases[] = { 2371f5f9340bSFabien Thomas EV_ALIAS("instructions", "SOFT-CLOCK.HARD"), 2372f5f9340bSFabien Thomas EV_ALIAS(NULL, NULL) 2373f5f9340bSFabien Thomas }; 2374f5f9340bSFabien Thomas 2375f5f9340bSFabien Thomas static int 2376f5f9340bSFabien Thomas soft_allocate_pmc(enum pmc_event pe, char *ctrspec, 2377f5f9340bSFabien Thomas struct pmc_op_pmcallocate *pmc_config) 2378f5f9340bSFabien Thomas { 2379f5f9340bSFabien Thomas (void)ctrspec; 2380f5f9340bSFabien Thomas (void)pmc_config; 2381f5f9340bSFabien Thomas 2382f0bbe9aaSDimitry Andric if ((int)pe < PMC_EV_SOFT_FIRST || (int)pe > PMC_EV_SOFT_LAST) 2383f5f9340bSFabien Thomas return (-1); 2384f5f9340bSFabien Thomas 2385f5f9340bSFabien Thomas pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2386f5f9340bSFabien Thomas return (0); 2387f5f9340bSFabien Thomas } 2388f5f9340bSFabien Thomas 23896411d14dSRuslan Bukin #if defined(__arm__) 23900ce207d2SRui Paulo #if defined(__XSCALE__) 23910ce207d2SRui Paulo 23920ce207d2SRui Paulo static struct pmc_event_alias xscale_aliases[] = { 23930ce207d2SRui Paulo EV_ALIAS("branches", "BRANCH_RETIRED"), 23940ce207d2SRui Paulo EV_ALIAS("branch-mispredicts", "BRANCH_MISPRED"), 23950ce207d2SRui Paulo EV_ALIAS("dc-misses", "DC_MISS"), 23960ce207d2SRui Paulo EV_ALIAS("ic-misses", "IC_MISS"), 23970ce207d2SRui Paulo EV_ALIAS("instructions", "INSTR_RETIRED"), 23980ce207d2SRui Paulo EV_ALIAS(NULL, NULL) 23990ce207d2SRui Paulo }; 24000ce207d2SRui Paulo static int 24010ce207d2SRui Paulo xscale_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 24020ce207d2SRui Paulo struct pmc_op_pmcallocate *pmc_config __unused) 24030ce207d2SRui Paulo { 24040ce207d2SRui Paulo switch (pe) { 24050ce207d2SRui Paulo default: 24060ce207d2SRui Paulo break; 24070ce207d2SRui Paulo } 24080ce207d2SRui Paulo 24090ce207d2SRui Paulo return (0); 24100ce207d2SRui Paulo } 24110ce207d2SRui Paulo #endif 24120ce207d2SRui Paulo 24136411d14dSRuslan Bukin static struct pmc_event_alias armv7_aliases[] = { 24146411d14dSRuslan Bukin EV_ALIAS("dc-misses", "L1_DCACHE_REFILL"), 24156411d14dSRuslan Bukin EV_ALIAS("ic-misses", "L1_ICACHE_REFILL"), 24166411d14dSRuslan Bukin EV_ALIAS("instructions", "INSTR_EXECUTED"), 24176411d14dSRuslan Bukin EV_ALIAS(NULL, NULL) 24186411d14dSRuslan Bukin }; 24196411d14dSRuslan Bukin static int 24206411d14dSRuslan Bukin armv7_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 24216411d14dSRuslan Bukin struct pmc_op_pmcallocate *pmc_config __unused) 24226411d14dSRuslan Bukin { 24236411d14dSRuslan Bukin switch (pe) { 24246411d14dSRuslan Bukin default: 24256411d14dSRuslan Bukin break; 24266411d14dSRuslan Bukin } 24276411d14dSRuslan Bukin 24286411d14dSRuslan Bukin return (0); 24296411d14dSRuslan Bukin } 24306411d14dSRuslan Bukin #endif 24316411d14dSRuslan Bukin 2432660df75eSGeorge V. Neville-Neil #if defined(__mips__) 2433660df75eSGeorge V. Neville-Neil 2434660df75eSGeorge V. Neville-Neil static struct pmc_event_alias mips24k_aliases[] = { 2435660df75eSGeorge V. Neville-Neil EV_ALIAS("instructions", "INSTR_EXECUTED"), 2436660df75eSGeorge V. Neville-Neil EV_ALIAS("branches", "BRANCH_COMPLETED"), 2437660df75eSGeorge V. Neville-Neil EV_ALIAS("branch-mispredicts", "BRANCH_MISPRED"), 2438660df75eSGeorge V. Neville-Neil EV_ALIAS(NULL, NULL) 2439660df75eSGeorge V. Neville-Neil }; 2440660df75eSGeorge V. Neville-Neil 2441f6e6460dSAdrian Chadd static struct pmc_event_alias mips74k_aliases[] = { 2442f6e6460dSAdrian Chadd EV_ALIAS("instructions", "INSTR_EXECUTED"), 2443f6e6460dSAdrian Chadd EV_ALIAS("branches", "BRANCH_INSNS"), 2444f6e6460dSAdrian Chadd EV_ALIAS("branch-mispredicts", "MISPREDICTED_BRANCH_INSNS"), 2445f6e6460dSAdrian Chadd EV_ALIAS(NULL, NULL) 2446f6e6460dSAdrian Chadd }; 2447f6e6460dSAdrian Chadd 2448c2657f80SOleksandr Tymoshenko static struct pmc_event_alias octeon_aliases[] = { 2449c2657f80SOleksandr Tymoshenko EV_ALIAS("instructions", "RET"), 2450c2657f80SOleksandr Tymoshenko EV_ALIAS("branches", "BR"), 2451c2657f80SOleksandr Tymoshenko EV_ALIAS("branch-mispredicts", "BRMIS"), 2452c2657f80SOleksandr Tymoshenko EV_ALIAS(NULL, NULL) 2453c2657f80SOleksandr Tymoshenko }; 2454c2657f80SOleksandr Tymoshenko 24552827d3e1SOleksandr Tymoshenko #define MIPS_KW_OS "os" 24562827d3e1SOleksandr Tymoshenko #define MIPS_KW_USR "usr" 24572827d3e1SOleksandr Tymoshenko #define MIPS_KW_ANYTHREAD "anythread" 2458660df75eSGeorge V. Neville-Neil 2459660df75eSGeorge V. Neville-Neil static int 24602827d3e1SOleksandr Tymoshenko mips_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 2461660df75eSGeorge V. Neville-Neil struct pmc_op_pmcallocate *pmc_config __unused) 2462660df75eSGeorge V. Neville-Neil { 2463660df75eSGeorge V. Neville-Neil char *p; 2464660df75eSGeorge V. Neville-Neil 2465660df75eSGeorge V. Neville-Neil (void) pe; 2466660df75eSGeorge V. Neville-Neil 2467660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2468660df75eSGeorge V. Neville-Neil 2469660df75eSGeorge V. Neville-Neil while ((p = strsep(&ctrspec, ",")) != NULL) { 24702827d3e1SOleksandr Tymoshenko if (KWMATCH(p, MIPS_KW_OS)) 2471660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= PMC_CAP_SYSTEM; 24722827d3e1SOleksandr Tymoshenko else if (KWMATCH(p, MIPS_KW_USR)) 2473660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= PMC_CAP_USER; 24742827d3e1SOleksandr Tymoshenko else if (KWMATCH(p, MIPS_KW_ANYTHREAD)) 2475660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= (PMC_CAP_USER | PMC_CAP_SYSTEM); 2476660df75eSGeorge V. Neville-Neil else 2477660df75eSGeorge V. Neville-Neil return (-1); 2478660df75eSGeorge V. Neville-Neil } 2479660df75eSGeorge V. Neville-Neil 2480660df75eSGeorge V. Neville-Neil return (0); 2481660df75eSGeorge V. Neville-Neil } 24822827d3e1SOleksandr Tymoshenko 2483660df75eSGeorge V. Neville-Neil #endif /* __mips__ */ 2484660df75eSGeorge V. Neville-Neil 24857b25dccaSJustin Hibbits #if defined(__powerpc__) 24867b25dccaSJustin Hibbits 24877b25dccaSJustin Hibbits static struct pmc_event_alias ppc7450_aliases[] = { 24887b25dccaSJustin Hibbits EV_ALIAS("instructions", "INSTR_COMPLETED"), 24897b25dccaSJustin Hibbits EV_ALIAS("branches", "BRANCHES_COMPLETED"), 24907b25dccaSJustin Hibbits EV_ALIAS("branch-mispredicts", "MISPREDICTED_BRANCHES"), 24917b25dccaSJustin Hibbits EV_ALIAS(NULL, NULL) 24927b25dccaSJustin Hibbits }; 24937b25dccaSJustin Hibbits 2494169dd953SJustin Hibbits static struct pmc_event_alias ppc970_aliases[] = { 2495169dd953SJustin Hibbits EV_ALIAS("instructions", "INSTR_COMPLETED"), 2496169dd953SJustin Hibbits EV_ALIAS("cycles", "CYCLES"), 2497169dd953SJustin Hibbits EV_ALIAS(NULL, NULL) 2498169dd953SJustin Hibbits }; 2499169dd953SJustin Hibbits 2500*a7452468SJustin Hibbits static struct pmc_event_alias e500_aliases[] = { 2501*a7452468SJustin Hibbits EV_ALIAS("instructions", "INSTR_COMPLETED"), 2502*a7452468SJustin Hibbits EV_ALIAS("cycles", "CYCLES"), 2503*a7452468SJustin Hibbits EV_ALIAS(NULL, NULL) 2504*a7452468SJustin Hibbits }; 2505*a7452468SJustin Hibbits 2506169dd953SJustin Hibbits #define POWERPC_KW_OS "os" 2507169dd953SJustin Hibbits #define POWERPC_KW_USR "usr" 2508169dd953SJustin Hibbits #define POWERPC_KW_ANYTHREAD "anythread" 25097b25dccaSJustin Hibbits 25107b25dccaSJustin Hibbits static int 2511169dd953SJustin Hibbits powerpc_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 25127b25dccaSJustin Hibbits struct pmc_op_pmcallocate *pmc_config __unused) 25137b25dccaSJustin Hibbits { 25147b25dccaSJustin Hibbits char *p; 25157b25dccaSJustin Hibbits 25167b25dccaSJustin Hibbits (void) pe; 25177b25dccaSJustin Hibbits 25187b25dccaSJustin Hibbits pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 25197b25dccaSJustin Hibbits 25207b25dccaSJustin Hibbits while ((p = strsep(&ctrspec, ",")) != NULL) { 2521169dd953SJustin Hibbits if (KWMATCH(p, POWERPC_KW_OS)) 25227b25dccaSJustin Hibbits pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2523169dd953SJustin Hibbits else if (KWMATCH(p, POWERPC_KW_USR)) 25247b25dccaSJustin Hibbits pmc_config->pm_caps |= PMC_CAP_USER; 2525169dd953SJustin Hibbits else if (KWMATCH(p, POWERPC_KW_ANYTHREAD)) 25267b25dccaSJustin Hibbits pmc_config->pm_caps |= (PMC_CAP_USER | PMC_CAP_SYSTEM); 25277b25dccaSJustin Hibbits else 25287b25dccaSJustin Hibbits return (-1); 25297b25dccaSJustin Hibbits } 25307b25dccaSJustin Hibbits 25317b25dccaSJustin Hibbits return (0); 25327b25dccaSJustin Hibbits } 2533169dd953SJustin Hibbits 25347b25dccaSJustin Hibbits #endif /* __powerpc__ */ 25357b25dccaSJustin Hibbits 2536660df75eSGeorge V. Neville-Neil 2537789140c0SJoseph Koshy /* 2538789140c0SJoseph Koshy * Match an event name `name' with its canonical form. 2539789140c0SJoseph Koshy * 25400cfab8ddSJoseph Koshy * Matches are case insensitive and spaces, periods, underscores and 25410cfab8ddSJoseph Koshy * hyphen characters are considered to match each other. 2542789140c0SJoseph Koshy * 2543789140c0SJoseph Koshy * Returns 1 for a match, 0 otherwise. 2544789140c0SJoseph Koshy */ 2545789140c0SJoseph Koshy 2546789140c0SJoseph Koshy static int 2547789140c0SJoseph Koshy pmc_match_event_name(const char *name, const char *canonicalname) 2548789140c0SJoseph Koshy { 2549789140c0SJoseph Koshy int cc, nc; 2550789140c0SJoseph Koshy const unsigned char *c, *n; 2551789140c0SJoseph Koshy 2552789140c0SJoseph Koshy c = (const unsigned char *) canonicalname; 2553789140c0SJoseph Koshy n = (const unsigned char *) name; 2554789140c0SJoseph Koshy 2555789140c0SJoseph Koshy for (; (nc = *n) && (cc = *c); n++, c++) { 2556789140c0SJoseph Koshy 25570cfab8ddSJoseph Koshy if ((nc == ' ' || nc == '_' || nc == '-' || nc == '.') && 25580cfab8ddSJoseph Koshy (cc == ' ' || cc == '_' || cc == '-' || cc == '.')) 2559789140c0SJoseph Koshy continue; 2560789140c0SJoseph Koshy 25610cfab8ddSJoseph Koshy if (toupper(nc) == toupper(cc)) 2562789140c0SJoseph Koshy continue; 2563789140c0SJoseph Koshy 25640cfab8ddSJoseph Koshy 2565789140c0SJoseph Koshy return (0); 2566789140c0SJoseph Koshy } 2567789140c0SJoseph Koshy 2568789140c0SJoseph Koshy if (*n == '\0' && *c == '\0') 2569789140c0SJoseph Koshy return (1); 2570789140c0SJoseph Koshy 2571789140c0SJoseph Koshy return (0); 2572789140c0SJoseph Koshy } 2573789140c0SJoseph Koshy 2574789140c0SJoseph Koshy /* 2575789140c0SJoseph Koshy * Match an event name against all the event named supported by a 2576789140c0SJoseph Koshy * PMC class. 2577789140c0SJoseph Koshy * 2578789140c0SJoseph Koshy * Returns an event descriptor pointer on match or NULL otherwise. 2579789140c0SJoseph Koshy */ 2580789140c0SJoseph Koshy static const struct pmc_event_descr * 2581789140c0SJoseph Koshy pmc_match_event_class(const char *name, 2582789140c0SJoseph Koshy const struct pmc_class_descr *pcd) 2583789140c0SJoseph Koshy { 2584789140c0SJoseph Koshy size_t n; 2585789140c0SJoseph Koshy const struct pmc_event_descr *ev; 2586789140c0SJoseph Koshy 2587789140c0SJoseph Koshy ev = pcd->pm_evc_event_table; 2588789140c0SJoseph Koshy for (n = 0; n < pcd->pm_evc_event_table_size; n++, ev++) 2589789140c0SJoseph Koshy if (pmc_match_event_name(name, ev->pm_ev_name)) 2590789140c0SJoseph Koshy return (ev); 2591789140c0SJoseph Koshy 2592789140c0SJoseph Koshy return (NULL); 2593789140c0SJoseph Koshy } 2594789140c0SJoseph Koshy 2595789140c0SJoseph Koshy static int 2596789140c0SJoseph Koshy pmc_mdep_is_compatible_class(enum pmc_class pc) 2597789140c0SJoseph Koshy { 2598789140c0SJoseph Koshy size_t n; 2599789140c0SJoseph Koshy 2600789140c0SJoseph Koshy for (n = 0; n < pmc_mdep_class_list_size; n++) 2601789140c0SJoseph Koshy if (pmc_mdep_class_list[n] == pc) 2602789140c0SJoseph Koshy return (1); 2603789140c0SJoseph Koshy return (0); 2604789140c0SJoseph Koshy } 2605789140c0SJoseph Koshy 2606ebccf1e3SJoseph Koshy /* 2607ebccf1e3SJoseph Koshy * API entry points 2608ebccf1e3SJoseph Koshy */ 2609ebccf1e3SJoseph Koshy 2610ebccf1e3SJoseph Koshy int 2611ebccf1e3SJoseph Koshy pmc_allocate(const char *ctrspec, enum pmc_mode mode, 2612ebccf1e3SJoseph Koshy uint32_t flags, int cpu, pmc_id_t *pmcid) 2613ebccf1e3SJoseph Koshy { 2614789140c0SJoseph Koshy size_t n; 2615ebccf1e3SJoseph Koshy int retval; 2616ebccf1e3SJoseph Koshy char *r, *spec_copy; 2617ebccf1e3SJoseph Koshy const char *ctrname; 2618789140c0SJoseph Koshy const struct pmc_event_descr *ev; 2619789140c0SJoseph Koshy const struct pmc_event_alias *alias; 2620ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate pmc_config; 2621789140c0SJoseph Koshy const struct pmc_class_descr *pcd; 2622ebccf1e3SJoseph Koshy 2623ebccf1e3SJoseph Koshy spec_copy = NULL; 2624ebccf1e3SJoseph Koshy retval = -1; 2625ebccf1e3SJoseph Koshy 2626ebccf1e3SJoseph Koshy if (mode != PMC_MODE_SS && mode != PMC_MODE_TS && 2627ebccf1e3SJoseph Koshy mode != PMC_MODE_SC && mode != PMC_MODE_TC) { 2628ebccf1e3SJoseph Koshy errno = EINVAL; 2629ebccf1e3SJoseph Koshy goto out; 2630ebccf1e3SJoseph Koshy } 2631ebccf1e3SJoseph Koshy 2632ebccf1e3SJoseph Koshy /* replace an event alias with the canonical event specifier */ 2633ebccf1e3SJoseph Koshy if (pmc_mdep_event_aliases) 2634789140c0SJoseph Koshy for (alias = pmc_mdep_event_aliases; alias->pm_alias; alias++) 2635789140c0SJoseph Koshy if (!strcasecmp(ctrspec, alias->pm_alias)) { 2636789140c0SJoseph Koshy spec_copy = strdup(alias->pm_spec); 2637ebccf1e3SJoseph Koshy break; 2638ebccf1e3SJoseph Koshy } 2639ebccf1e3SJoseph Koshy 2640ebccf1e3SJoseph Koshy if (spec_copy == NULL) 2641ebccf1e3SJoseph Koshy spec_copy = strdup(ctrspec); 2642ebccf1e3SJoseph Koshy 2643ebccf1e3SJoseph Koshy r = spec_copy; 2644ebccf1e3SJoseph Koshy ctrname = strsep(&r, ","); 2645ebccf1e3SJoseph Koshy 2646789140c0SJoseph Koshy /* 2647789140c0SJoseph Koshy * If a explicit class prefix was given by the user, restrict the 2648789140c0SJoseph Koshy * search for the event to the specified PMC class. 2649789140c0SJoseph Koshy */ 2650789140c0SJoseph Koshy ev = NULL; 26510cfab8ddSJoseph Koshy for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) { 26520cfab8ddSJoseph Koshy pcd = pmc_class_table[n]; 2653789140c0SJoseph Koshy if (pmc_mdep_is_compatible_class(pcd->pm_evc_class) && 2654789140c0SJoseph Koshy strncasecmp(ctrname, pcd->pm_evc_name, 2655789140c0SJoseph Koshy pcd->pm_evc_name_size) == 0) { 2656789140c0SJoseph Koshy if ((ev = pmc_match_event_class(ctrname + 2657789140c0SJoseph Koshy pcd->pm_evc_name_size, pcd)) == NULL) { 2658789140c0SJoseph Koshy errno = EINVAL; 2659789140c0SJoseph Koshy goto out; 2660789140c0SJoseph Koshy } 2661ebccf1e3SJoseph Koshy break; 2662789140c0SJoseph Koshy } 2663789140c0SJoseph Koshy } 2664ebccf1e3SJoseph Koshy 2665789140c0SJoseph Koshy /* 2666789140c0SJoseph Koshy * Otherwise, search for this event in all compatible PMC 2667789140c0SJoseph Koshy * classes. 2668789140c0SJoseph Koshy */ 26690cfab8ddSJoseph Koshy for (n = 0; ev == NULL && n < PMC_CLASS_TABLE_SIZE; n++) { 26700cfab8ddSJoseph Koshy pcd = pmc_class_table[n]; 2671789140c0SJoseph Koshy if (pmc_mdep_is_compatible_class(pcd->pm_evc_class)) 2672789140c0SJoseph Koshy ev = pmc_match_event_class(ctrname, pcd); 2673789140c0SJoseph Koshy } 2674789140c0SJoseph Koshy 2675789140c0SJoseph Koshy if (ev == NULL) { 2676ebccf1e3SJoseph Koshy errno = EINVAL; 2677ebccf1e3SJoseph Koshy goto out; 2678ebccf1e3SJoseph Koshy } 2679ebccf1e3SJoseph Koshy 2680ebccf1e3SJoseph Koshy bzero(&pmc_config, sizeof(pmc_config)); 2681789140c0SJoseph Koshy pmc_config.pm_ev = ev->pm_ev_code; 2682789140c0SJoseph Koshy pmc_config.pm_class = pcd->pm_evc_class; 2683ebccf1e3SJoseph Koshy pmc_config.pm_cpu = cpu; 2684ebccf1e3SJoseph Koshy pmc_config.pm_mode = mode; 2685ebccf1e3SJoseph Koshy pmc_config.pm_flags = flags; 2686ebccf1e3SJoseph Koshy 2687ebccf1e3SJoseph Koshy if (PMC_IS_SAMPLING_MODE(mode)) 2688ebccf1e3SJoseph Koshy pmc_config.pm_caps |= PMC_CAP_INTERRUPT; 2689ebccf1e3SJoseph Koshy 2690789140c0SJoseph Koshy if (pcd->pm_evc_allocate_pmc(ev->pm_ev_code, r, &pmc_config) < 0) { 2691ebccf1e3SJoseph Koshy errno = EINVAL; 2692ebccf1e3SJoseph Koshy goto out; 2693ebccf1e3SJoseph Koshy } 2694ebccf1e3SJoseph Koshy 2695ebccf1e3SJoseph Koshy if (PMC_CALL(PMCALLOCATE, &pmc_config) < 0) 2696ebccf1e3SJoseph Koshy goto out; 2697ebccf1e3SJoseph Koshy 2698ebccf1e3SJoseph Koshy *pmcid = pmc_config.pm_pmcid; 2699ebccf1e3SJoseph Koshy 2700ebccf1e3SJoseph Koshy retval = 0; 2701ebccf1e3SJoseph Koshy 2702ebccf1e3SJoseph Koshy out: 2703ebccf1e3SJoseph Koshy if (spec_copy) 2704ebccf1e3SJoseph Koshy free(spec_copy); 2705ebccf1e3SJoseph Koshy 2706aa342b1fSJoseph Koshy return (retval); 2707ebccf1e3SJoseph Koshy } 2708ebccf1e3SJoseph Koshy 2709ebccf1e3SJoseph Koshy int 2710ebccf1e3SJoseph Koshy pmc_attach(pmc_id_t pmc, pid_t pid) 2711ebccf1e3SJoseph Koshy { 2712ebccf1e3SJoseph Koshy struct pmc_op_pmcattach pmc_attach_args; 2713ebccf1e3SJoseph Koshy 2714ebccf1e3SJoseph Koshy pmc_attach_args.pm_pmc = pmc; 2715ebccf1e3SJoseph Koshy pmc_attach_args.pm_pid = pid; 2716ebccf1e3SJoseph Koshy 2717aa342b1fSJoseph Koshy return (PMC_CALL(PMCATTACH, &pmc_attach_args)); 2718ebccf1e3SJoseph Koshy } 2719ebccf1e3SJoseph Koshy 2720ebccf1e3SJoseph Koshy int 2721c5153e19SJoseph Koshy pmc_capabilities(pmc_id_t pmcid, uint32_t *caps) 2722c5153e19SJoseph Koshy { 2723c5153e19SJoseph Koshy unsigned int i; 2724c5153e19SJoseph Koshy enum pmc_class cl; 2725c5153e19SJoseph Koshy 2726c5153e19SJoseph Koshy cl = PMC_ID_TO_CLASS(pmcid); 2727c5153e19SJoseph Koshy for (i = 0; i < cpu_info.pm_nclass; i++) 2728c5153e19SJoseph Koshy if (cpu_info.pm_classes[i].pm_class == cl) { 2729c5153e19SJoseph Koshy *caps = cpu_info.pm_classes[i].pm_caps; 2730aa342b1fSJoseph Koshy return (0); 2731c5153e19SJoseph Koshy } 2732484202faSJoseph Koshy errno = EINVAL; 2733484202faSJoseph Koshy return (-1); 2734c5153e19SJoseph Koshy } 2735c5153e19SJoseph Koshy 2736f263522aSJoseph Koshy int 2737f263522aSJoseph Koshy pmc_configure_logfile(int fd) 2738ebccf1e3SJoseph Koshy { 2739f263522aSJoseph Koshy struct pmc_op_configurelog cla; 2740f263522aSJoseph Koshy 2741f263522aSJoseph Koshy cla.pm_logfd = fd; 2742f263522aSJoseph Koshy if (PMC_CALL(CONFIGURELOG, &cla) < 0) 2743aa342b1fSJoseph Koshy return (-1); 2744aa342b1fSJoseph Koshy return (0); 2745ebccf1e3SJoseph Koshy } 2746ebccf1e3SJoseph Koshy 2747f263522aSJoseph Koshy int 2748f263522aSJoseph Koshy pmc_cpuinfo(const struct pmc_cpuinfo **pci) 2749ebccf1e3SJoseph Koshy { 2750f263522aSJoseph Koshy if (pmc_syscall == -1) { 2751f263522aSJoseph Koshy errno = ENXIO; 2752aa342b1fSJoseph Koshy return (-1); 2753ebccf1e3SJoseph Koshy } 2754ebccf1e3SJoseph Koshy 27551455fcd3SJoseph Koshy *pci = &cpu_info; 2756aa342b1fSJoseph Koshy return (0); 2757ebccf1e3SJoseph Koshy } 2758ebccf1e3SJoseph Koshy 2759f263522aSJoseph Koshy int 2760f263522aSJoseph Koshy pmc_detach(pmc_id_t pmc, pid_t pid) 2761ebccf1e3SJoseph Koshy { 2762f263522aSJoseph Koshy struct pmc_op_pmcattach pmc_detach_args; 2763ebccf1e3SJoseph Koshy 2764f263522aSJoseph Koshy pmc_detach_args.pm_pmc = pmc; 2765f263522aSJoseph Koshy pmc_detach_args.pm_pid = pid; 2766aa342b1fSJoseph Koshy return (PMC_CALL(PMCDETACH, &pmc_detach_args)); 2767ebccf1e3SJoseph Koshy } 2768ebccf1e3SJoseph Koshy 2769f263522aSJoseph Koshy int 2770f263522aSJoseph Koshy pmc_disable(int cpu, int pmc) 2771ebccf1e3SJoseph Koshy { 2772f263522aSJoseph Koshy struct pmc_op_pmcadmin ssa; 2773ebccf1e3SJoseph Koshy 2774f263522aSJoseph Koshy ssa.pm_cpu = cpu; 2775f263522aSJoseph Koshy ssa.pm_pmc = pmc; 2776f263522aSJoseph Koshy ssa.pm_state = PMC_STATE_DISABLED; 2777aa342b1fSJoseph Koshy return (PMC_CALL(PMCADMIN, &ssa)); 2778ebccf1e3SJoseph Koshy } 2779ebccf1e3SJoseph Koshy 2780f263522aSJoseph Koshy int 2781f263522aSJoseph Koshy pmc_enable(int cpu, int pmc) 2782ebccf1e3SJoseph Koshy { 2783f263522aSJoseph Koshy struct pmc_op_pmcadmin ssa; 2784ebccf1e3SJoseph Koshy 2785f263522aSJoseph Koshy ssa.pm_cpu = cpu; 2786f263522aSJoseph Koshy ssa.pm_pmc = pmc; 2787f263522aSJoseph Koshy ssa.pm_state = PMC_STATE_FREE; 2788aa342b1fSJoseph Koshy return (PMC_CALL(PMCADMIN, &ssa)); 2789ebccf1e3SJoseph Koshy } 2790ebccf1e3SJoseph Koshy 2791ebccf1e3SJoseph Koshy /* 2792ebccf1e3SJoseph Koshy * Return a list of events known to a given PMC class. 'cl' is the 2793ebccf1e3SJoseph Koshy * PMC class identifier, 'eventnames' is the returned list of 'const 2794ebccf1e3SJoseph Koshy * char *' pointers pointing to the names of the events. 'nevents' is 2795ebccf1e3SJoseph Koshy * the number of event name pointers returned. 2796ebccf1e3SJoseph Koshy * 2797ebccf1e3SJoseph Koshy * The space for 'eventnames' is allocated using malloc(3). The caller 2798ebccf1e3SJoseph Koshy * is responsible for freeing this space when done. 2799ebccf1e3SJoseph Koshy */ 2800ebccf1e3SJoseph Koshy int 2801ebccf1e3SJoseph Koshy pmc_event_names_of_class(enum pmc_class cl, const char ***eventnames, 2802ebccf1e3SJoseph Koshy int *nevents) 2803ebccf1e3SJoseph Koshy { 2804ebccf1e3SJoseph Koshy int count; 2805ebccf1e3SJoseph Koshy const char **names; 2806ebccf1e3SJoseph Koshy const struct pmc_event_descr *ev; 2807ebccf1e3SJoseph Koshy 2808ebccf1e3SJoseph Koshy switch (cl) 2809ebccf1e3SJoseph Koshy { 28100cfab8ddSJoseph Koshy case PMC_CLASS_IAF: 28110cfab8ddSJoseph Koshy ev = iaf_event_table; 28120cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(iaf); 28130cfab8ddSJoseph Koshy break; 28140cfab8ddSJoseph Koshy case PMC_CLASS_IAP: 28150cfab8ddSJoseph Koshy /* 28160cfab8ddSJoseph Koshy * Return the most appropriate set of event name 28170cfab8ddSJoseph Koshy * spellings for the current CPU. 28180cfab8ddSJoseph Koshy */ 28190cfab8ddSJoseph Koshy switch (cpu_info.pm_cputype) { 28200cfab8ddSJoseph Koshy default: 28210cfab8ddSJoseph Koshy case PMC_CPU_INTEL_ATOM: 28220cfab8ddSJoseph Koshy ev = atom_event_table; 28230cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(atom); 28240cfab8ddSJoseph Koshy break; 2825e8f021a3SHiren Panchasara case PMC_CPU_INTEL_ATOM_SILVERMONT: 2826e8f021a3SHiren Panchasara ev = atom_silvermont_event_table; 2827e8f021a3SHiren Panchasara count = PMC_EVENT_TABLE_SIZE(atom_silvermont); 2828e8f021a3SHiren Panchasara break; 28290cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE: 28300cfab8ddSJoseph Koshy ev = core_event_table; 28310cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(core); 28320cfab8ddSJoseph Koshy break; 28330cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE2: 2834b4d091f3SJoseph Koshy case PMC_CPU_INTEL_CORE2EXTREME: 28350cfab8ddSJoseph Koshy ev = core2_event_table; 28360cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(core2); 28370cfab8ddSJoseph Koshy break; 2838597979c4SJeff Roberson case PMC_CPU_INTEL_COREI7: 2839597979c4SJeff Roberson ev = corei7_event_table; 2840597979c4SJeff Roberson count = PMC_EVENT_TABLE_SIZE(corei7); 2841597979c4SJeff Roberson break; 284249fe48abSKonstantin Belousov case PMC_CPU_INTEL_NEHALEM_EX: 284349fe48abSKonstantin Belousov ev = nehalem_ex_event_table; 284449fe48abSKonstantin Belousov count = PMC_EVENT_TABLE_SIZE(nehalem_ex); 284549fe48abSKonstantin Belousov break; 2846cc0c1555SSean Bruno case PMC_CPU_INTEL_HASWELL: 2847cc0c1555SSean Bruno ev = haswell_event_table; 2848cc0c1555SSean Bruno count = PMC_EVENT_TABLE_SIZE(haswell); 2849cc0c1555SSean Bruno break; 2850d95b3509SRandall Stewart case PMC_CPU_INTEL_HASWELL_XEON: 2851d95b3509SRandall Stewart ev = haswell_xeon_event_table; 2852d95b3509SRandall Stewart count = PMC_EVENT_TABLE_SIZE(haswell_xeon); 2853d95b3509SRandall Stewart break; 28541e862e5aSFabien Thomas case PMC_CPU_INTEL_IVYBRIDGE: 28551e862e5aSFabien Thomas ev = ivybridge_event_table; 28561e862e5aSFabien Thomas count = PMC_EVENT_TABLE_SIZE(ivybridge); 28571e862e5aSFabien Thomas break; 28583f929d8cSSean Bruno case PMC_CPU_INTEL_IVYBRIDGE_XEON: 28593f929d8cSSean Bruno ev = ivybridge_xeon_event_table; 28603f929d8cSSean Bruno count = PMC_EVENT_TABLE_SIZE(ivybridge_xeon); 28613f929d8cSSean Bruno break; 286278d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 286378d763a2SDavide Italiano ev = sandybridge_event_table; 286478d763a2SDavide Italiano count = PMC_EVENT_TABLE_SIZE(sandybridge); 286578d763a2SDavide Italiano break; 2866fabe02f5SSean Bruno case PMC_CPU_INTEL_SANDYBRIDGE_XEON: 2867fabe02f5SSean Bruno ev = sandybridge_xeon_event_table; 2868fabe02f5SSean Bruno count = PMC_EVENT_TABLE_SIZE(sandybridge_xeon); 2869fabe02f5SSean Bruno break; 28701fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 28711fa7f10bSFabien Thomas ev = westmere_event_table; 28721fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(westmere); 28731fa7f10bSFabien Thomas break; 287449fe48abSKonstantin Belousov case PMC_CPU_INTEL_WESTMERE_EX: 287549fe48abSKonstantin Belousov ev = westmere_ex_event_table; 287649fe48abSKonstantin Belousov count = PMC_EVENT_TABLE_SIZE(westmere_ex); 287749fe48abSKonstantin Belousov break; 28781fa7f10bSFabien Thomas } 28791fa7f10bSFabien Thomas break; 28801fa7f10bSFabien Thomas case PMC_CLASS_UCF: 28811fa7f10bSFabien Thomas ev = ucf_event_table; 28821fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(ucf); 28831fa7f10bSFabien Thomas break; 28841fa7f10bSFabien Thomas case PMC_CLASS_UCP: 28851fa7f10bSFabien Thomas /* 28861fa7f10bSFabien Thomas * Return the most appropriate set of event name 28871fa7f10bSFabien Thomas * spellings for the current CPU. 28881fa7f10bSFabien Thomas */ 28891fa7f10bSFabien Thomas switch (cpu_info.pm_cputype) { 28901fa7f10bSFabien Thomas default: 28911fa7f10bSFabien Thomas case PMC_CPU_INTEL_COREI7: 28921fa7f10bSFabien Thomas ev = corei7uc_event_table; 28931fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(corei7uc); 28941fa7f10bSFabien Thomas break; 2895cc0c1555SSean Bruno case PMC_CPU_INTEL_HASWELL: 2896cc0c1555SSean Bruno ev = haswelluc_event_table; 2897cc0c1555SSean Bruno count = PMC_EVENT_TABLE_SIZE(haswelluc); 2898cc0c1555SSean Bruno break; 289978d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 290078d763a2SDavide Italiano ev = sandybridgeuc_event_table; 290178d763a2SDavide Italiano count = PMC_EVENT_TABLE_SIZE(sandybridgeuc); 290278d763a2SDavide Italiano break; 29031fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 29041fa7f10bSFabien Thomas ev = westmereuc_event_table; 29051fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(westmereuc); 29061fa7f10bSFabien Thomas break; 29070cfab8ddSJoseph Koshy } 29080cfab8ddSJoseph Koshy break; 2909ebccf1e3SJoseph Koshy case PMC_CLASS_TSC: 2910789140c0SJoseph Koshy ev = tsc_event_table; 2911789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(tsc); 2912ebccf1e3SJoseph Koshy break; 2913ebccf1e3SJoseph Koshy case PMC_CLASS_K7: 2914789140c0SJoseph Koshy ev = k7_event_table; 2915789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(k7); 2916ebccf1e3SJoseph Koshy break; 2917ebccf1e3SJoseph Koshy case PMC_CLASS_K8: 2918789140c0SJoseph Koshy ev = k8_event_table; 2919789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(k8); 2920ebccf1e3SJoseph Koshy break; 2921ebccf1e3SJoseph Koshy case PMC_CLASS_P4: 2922789140c0SJoseph Koshy ev = p4_event_table; 2923789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p4); 2924789140c0SJoseph Koshy break; 2925789140c0SJoseph Koshy case PMC_CLASS_P5: 2926789140c0SJoseph Koshy ev = p5_event_table; 2927789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p5); 2928789140c0SJoseph Koshy break; 2929789140c0SJoseph Koshy case PMC_CLASS_P6: 2930789140c0SJoseph Koshy ev = p6_event_table; 2931789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p6); 2932ebccf1e3SJoseph Koshy break; 29330ce207d2SRui Paulo case PMC_CLASS_XSCALE: 29340ce207d2SRui Paulo ev = xscale_event_table; 29350ce207d2SRui Paulo count = PMC_EVENT_TABLE_SIZE(xscale); 29360ce207d2SRui Paulo break; 29376411d14dSRuslan Bukin case PMC_CLASS_ARMV7: 29386411d14dSRuslan Bukin ev = armv7_event_table; 29396411d14dSRuslan Bukin count = PMC_EVENT_TABLE_SIZE(armv7); 29406411d14dSRuslan Bukin break; 2941660df75eSGeorge V. Neville-Neil case PMC_CLASS_MIPS24K: 2942660df75eSGeorge V. Neville-Neil ev = mips24k_event_table; 2943660df75eSGeorge V. Neville-Neil count = PMC_EVENT_TABLE_SIZE(mips24k); 2944660df75eSGeorge V. Neville-Neil break; 2945f6e6460dSAdrian Chadd case PMC_CLASS_MIPS74K: 2946f6e6460dSAdrian Chadd ev = mips74k_event_table; 2947f6e6460dSAdrian Chadd count = PMC_EVENT_TABLE_SIZE(mips74k); 2948f6e6460dSAdrian Chadd break; 2949c2657f80SOleksandr Tymoshenko case PMC_CLASS_OCTEON: 2950c2657f80SOleksandr Tymoshenko ev = octeon_event_table; 2951c2657f80SOleksandr Tymoshenko count = PMC_EVENT_TABLE_SIZE(octeon); 2952c2657f80SOleksandr Tymoshenko break; 29537b25dccaSJustin Hibbits case PMC_CLASS_PPC7450: 29547b25dccaSJustin Hibbits ev = ppc7450_event_table; 29557b25dccaSJustin Hibbits count = PMC_EVENT_TABLE_SIZE(ppc7450); 29567b25dccaSJustin Hibbits break; 2957169dd953SJustin Hibbits case PMC_CLASS_PPC970: 2958169dd953SJustin Hibbits ev = ppc970_event_table; 2959169dd953SJustin Hibbits count = PMC_EVENT_TABLE_SIZE(ppc970); 2960169dd953SJustin Hibbits break; 2961*a7452468SJustin Hibbits case PMC_CLASS_E500: 2962*a7452468SJustin Hibbits ev = e500_event_table; 2963*a7452468SJustin Hibbits count = PMC_EVENT_TABLE_SIZE(e500); 2964*a7452468SJustin Hibbits break; 2965f5f9340bSFabien Thomas case PMC_CLASS_SOFT: 2966f5f9340bSFabien Thomas ev = soft_event_table; 2967f5f9340bSFabien Thomas count = soft_event_info.pm_nevent; 2968f5f9340bSFabien Thomas break; 2969ebccf1e3SJoseph Koshy default: 2970ebccf1e3SJoseph Koshy errno = EINVAL; 2971aa342b1fSJoseph Koshy return (-1); 2972ebccf1e3SJoseph Koshy } 2973ebccf1e3SJoseph Koshy 2974ebccf1e3SJoseph Koshy if ((names = malloc(count * sizeof(const char *))) == NULL) 2975aa342b1fSJoseph Koshy return (-1); 2976ebccf1e3SJoseph Koshy 2977ebccf1e3SJoseph Koshy *eventnames = names; 2978ebccf1e3SJoseph Koshy *nevents = count; 2979ebccf1e3SJoseph Koshy 2980ebccf1e3SJoseph Koshy for (;count--; ev++, names++) 2981ebccf1e3SJoseph Koshy *names = ev->pm_ev_name; 2982f5f9340bSFabien Thomas 2983aa342b1fSJoseph Koshy return (0); 2984ebccf1e3SJoseph Koshy } 2985ebccf1e3SJoseph Koshy 2986f263522aSJoseph Koshy int 2987f263522aSJoseph Koshy pmc_flush_logfile(void) 2988f263522aSJoseph Koshy { 2989aa342b1fSJoseph Koshy return (PMC_CALL(FLUSHLOG,0)); 2990f263522aSJoseph Koshy } 2991ebccf1e3SJoseph Koshy 2992ebccf1e3SJoseph Koshy int 2993dceed24aSFabien Thomas pmc_close_logfile(void) 2994dceed24aSFabien Thomas { 2995dceed24aSFabien Thomas return (PMC_CALL(CLOSELOG,0)); 2996dceed24aSFabien Thomas } 2997dceed24aSFabien Thomas 2998dceed24aSFabien Thomas int 2999f263522aSJoseph Koshy pmc_get_driver_stats(struct pmc_driverstats *ds) 3000ebccf1e3SJoseph Koshy { 3001f263522aSJoseph Koshy struct pmc_op_getdriverstats gms; 3002f263522aSJoseph Koshy 3003f263522aSJoseph Koshy if (PMC_CALL(GETDRIVERSTATS, &gms) < 0) 3004aa342b1fSJoseph Koshy return (-1); 3005f263522aSJoseph Koshy 3006f263522aSJoseph Koshy /* copy out fields in the current userland<->library interface */ 3007f263522aSJoseph Koshy ds->pm_intr_ignored = gms.pm_intr_ignored; 3008f263522aSJoseph Koshy ds->pm_intr_processed = gms.pm_intr_processed; 3009f263522aSJoseph Koshy ds->pm_intr_bufferfull = gms.pm_intr_bufferfull; 3010f263522aSJoseph Koshy ds->pm_syscalls = gms.pm_syscalls; 3011f263522aSJoseph Koshy ds->pm_syscall_errors = gms.pm_syscall_errors; 3012f263522aSJoseph Koshy ds->pm_buffer_requests = gms.pm_buffer_requests; 3013f263522aSJoseph Koshy ds->pm_buffer_requests_failed = gms.pm_buffer_requests_failed; 3014f263522aSJoseph Koshy ds->pm_log_sweeps = gms.pm_log_sweeps; 3015aa342b1fSJoseph Koshy return (0); 3016f263522aSJoseph Koshy } 3017f263522aSJoseph Koshy 3018f263522aSJoseph Koshy int 3019f263522aSJoseph Koshy pmc_get_msr(pmc_id_t pmc, uint32_t *msr) 3020f263522aSJoseph Koshy { 3021f263522aSJoseph Koshy struct pmc_op_getmsr gm; 3022ebccf1e3SJoseph Koshy 3023ebccf1e3SJoseph Koshy gm.pm_pmcid = pmc; 3024f263522aSJoseph Koshy if (PMC_CALL(PMCGETMSR, &gm) < 0) 3025aa342b1fSJoseph Koshy return (-1); 3026ebccf1e3SJoseph Koshy *msr = gm.pm_msr; 3027aa342b1fSJoseph Koshy return (0); 3028ebccf1e3SJoseph Koshy } 3029ebccf1e3SJoseph Koshy 3030f263522aSJoseph Koshy int 3031f263522aSJoseph Koshy pmc_init(void) 3032f263522aSJoseph Koshy { 3033f263522aSJoseph Koshy int error, pmc_mod_id; 30341455fcd3SJoseph Koshy unsigned int n; 3035f263522aSJoseph Koshy uint32_t abi_version; 3036f263522aSJoseph Koshy struct module_stat pmc_modstat; 30371455fcd3SJoseph Koshy struct pmc_op_getcpuinfo op_cpu_info; 3038791f5d5bSJoseph Koshy #if defined(__amd64__) || defined(__i386__) 3039791f5d5bSJoseph Koshy int cpu_has_iaf_counters; 3040791f5d5bSJoseph Koshy unsigned int t; 3041791f5d5bSJoseph Koshy #endif 3042f263522aSJoseph Koshy 3043f263522aSJoseph Koshy if (pmc_syscall != -1) /* already inited */ 3044aa342b1fSJoseph Koshy return (0); 3045f263522aSJoseph Koshy 3046f263522aSJoseph Koshy /* retrieve the system call number from the KLD */ 3047f263522aSJoseph Koshy if ((pmc_mod_id = modfind(PMC_MODULE_NAME)) < 0) 3048aa342b1fSJoseph Koshy return (-1); 3049f263522aSJoseph Koshy 3050f263522aSJoseph Koshy pmc_modstat.version = sizeof(struct module_stat); 3051f263522aSJoseph Koshy if ((error = modstat(pmc_mod_id, &pmc_modstat)) < 0) 3052aa342b1fSJoseph Koshy return (-1); 3053f263522aSJoseph Koshy 3054f263522aSJoseph Koshy pmc_syscall = pmc_modstat.data.intval; 3055f263522aSJoseph Koshy 3056f263522aSJoseph Koshy /* check the kernel module's ABI against our compiled-in version */ 3057f263522aSJoseph Koshy abi_version = PMC_VERSION; 3058f263522aSJoseph Koshy if (PMC_CALL(GETMODULEVERSION, &abi_version) < 0) 3059f263522aSJoseph Koshy return (pmc_syscall = -1); 3060f263522aSJoseph Koshy 3061f263522aSJoseph Koshy /* ignore patch & minor numbers for the comparision */ 3062f263522aSJoseph Koshy if ((abi_version & 0xFF000000) != (PMC_VERSION & 0xFF000000)) { 3063f263522aSJoseph Koshy errno = EPROGMISMATCH; 3064f263522aSJoseph Koshy return (pmc_syscall = -1); 3065f263522aSJoseph Koshy } 3066f263522aSJoseph Koshy 30671455fcd3SJoseph Koshy if (PMC_CALL(GETCPUINFO, &op_cpu_info) < 0) 3068f263522aSJoseph Koshy return (pmc_syscall = -1); 3069f263522aSJoseph Koshy 30701455fcd3SJoseph Koshy cpu_info.pm_cputype = op_cpu_info.pm_cputype; 30711455fcd3SJoseph Koshy cpu_info.pm_ncpu = op_cpu_info.pm_ncpu; 30721455fcd3SJoseph Koshy cpu_info.pm_npmc = op_cpu_info.pm_npmc; 30731455fcd3SJoseph Koshy cpu_info.pm_nclass = op_cpu_info.pm_nclass; 30741455fcd3SJoseph Koshy for (n = 0; n < cpu_info.pm_nclass; n++) 30751455fcd3SJoseph Koshy cpu_info.pm_classes[n] = op_cpu_info.pm_classes[n]; 30761455fcd3SJoseph Koshy 30770cfab8ddSJoseph Koshy pmc_class_table = malloc(PMC_CLASS_TABLE_SIZE * 30780cfab8ddSJoseph Koshy sizeof(struct pmc_class_descr *)); 30790cfab8ddSJoseph Koshy 30800cfab8ddSJoseph Koshy if (pmc_class_table == NULL) 30810cfab8ddSJoseph Koshy return (-1); 30820cfab8ddSJoseph Koshy 3083791f5d5bSJoseph Koshy for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) 3084791f5d5bSJoseph Koshy pmc_class_table[n] = NULL; 30850cfab8ddSJoseph Koshy 30860cfab8ddSJoseph Koshy /* 3087f5f9340bSFabien Thomas * Get soft events list. 3088f5f9340bSFabien Thomas */ 3089f5f9340bSFabien Thomas soft_event_info.pm_class = PMC_CLASS_SOFT; 3090f5f9340bSFabien Thomas if (PMC_CALL(GETDYNEVENTINFO, &soft_event_info) < 0) 3091f5f9340bSFabien Thomas return (pmc_syscall = -1); 3092f5f9340bSFabien Thomas 3093f5f9340bSFabien Thomas /* Map soft events to static list. */ 3094f5f9340bSFabien Thomas for (n = 0; n < soft_event_info.pm_nevent; n++) { 3095f5f9340bSFabien Thomas soft_event_table[n].pm_ev_name = 3096f5f9340bSFabien Thomas soft_event_info.pm_events[n].pm_ev_name; 3097f5f9340bSFabien Thomas soft_event_table[n].pm_ev_code = 3098f5f9340bSFabien Thomas soft_event_info.pm_events[n].pm_ev_code; 3099f5f9340bSFabien Thomas } 3100f5f9340bSFabien Thomas soft_class_table_descr.pm_evc_event_table_size = \ 3101f5f9340bSFabien Thomas soft_event_info.pm_nevent; 3102f5f9340bSFabien Thomas soft_class_table_descr.pm_evc_event_table = \ 3103f5f9340bSFabien Thomas soft_event_table; 3104f5f9340bSFabien Thomas 3105f5f9340bSFabien Thomas /* 31060cfab8ddSJoseph Koshy * Fill in the class table. 31070cfab8ddSJoseph Koshy */ 31080cfab8ddSJoseph Koshy n = 0; 3109f5f9340bSFabien Thomas 3110f5f9340bSFabien Thomas /* Fill soft events information. */ 3111f5f9340bSFabien Thomas pmc_class_table[n++] = &soft_class_table_descr; 31120cfab8ddSJoseph Koshy #if defined(__amd64__) || defined(__i386__) 3113f5f9340bSFabien Thomas if (cpu_info.pm_cputype != PMC_CPU_GENERIC) 31140cfab8ddSJoseph Koshy pmc_class_table[n++] = &tsc_class_table_descr; 3115791f5d5bSJoseph Koshy 3116791f5d5bSJoseph Koshy /* 3117791f5d5bSJoseph Koshy * Check if this CPU has fixed function counters. 3118791f5d5bSJoseph Koshy */ 3119791f5d5bSJoseph Koshy cpu_has_iaf_counters = 0; 3120791f5d5bSJoseph Koshy for (t = 0; t < cpu_info.pm_nclass; t++) 31212aef9dd6SFabien Thomas if (cpu_info.pm_classes[t].pm_class == PMC_CLASS_IAF && 31222aef9dd6SFabien Thomas cpu_info.pm_classes[t].pm_num > 0) 3123791f5d5bSJoseph Koshy cpu_has_iaf_counters = 1; 31240cfab8ddSJoseph Koshy #endif 31250cfab8ddSJoseph Koshy 3126789140c0SJoseph Koshy #define PMC_MDEP_INIT(C) do { \ 3127789140c0SJoseph Koshy pmc_mdep_event_aliases = C##_aliases; \ 3128789140c0SJoseph Koshy pmc_mdep_class_list = C##_pmc_classes; \ 3129789140c0SJoseph Koshy pmc_mdep_class_list_size = \ 3130789140c0SJoseph Koshy PMC_TABLE_SIZE(C##_pmc_classes); \ 3131789140c0SJoseph Koshy } while (0) 3132789140c0SJoseph Koshy 3133791f5d5bSJoseph Koshy #define PMC_MDEP_INIT_INTEL_V2(C) do { \ 3134791f5d5bSJoseph Koshy PMC_MDEP_INIT(C); \ 3135791f5d5bSJoseph Koshy pmc_class_table[n++] = &iaf_class_table_descr; \ 31362aef9dd6SFabien Thomas if (!cpu_has_iaf_counters) \ 3137791f5d5bSJoseph Koshy pmc_mdep_event_aliases = \ 3138791f5d5bSJoseph Koshy C##_aliases_without_iaf; \ 3139791f5d5bSJoseph Koshy pmc_class_table[n] = &C##_class_table_descr; \ 3140791f5d5bSJoseph Koshy } while (0) 3141791f5d5bSJoseph Koshy 3142789140c0SJoseph Koshy /* Configure the event name parser. */ 3143f263522aSJoseph Koshy switch (cpu_info.pm_cputype) { 3144f263522aSJoseph Koshy #if defined(__i386__) 3145f263522aSJoseph Koshy case PMC_CPU_AMD_K7: 3146789140c0SJoseph Koshy PMC_MDEP_INIT(k7); 31470cfab8ddSJoseph Koshy pmc_class_table[n] = &k7_class_table_descr; 3148f263522aSJoseph Koshy break; 3149f263522aSJoseph Koshy case PMC_CPU_INTEL_P5: 3150789140c0SJoseph Koshy PMC_MDEP_INIT(p5); 31510cfab8ddSJoseph Koshy pmc_class_table[n] = &p5_class_table_descr; 3152f263522aSJoseph Koshy break; 3153f263522aSJoseph Koshy case PMC_CPU_INTEL_P6: /* P6 ... Pentium M CPUs have */ 3154f263522aSJoseph Koshy case PMC_CPU_INTEL_PII: /* similar PMCs. */ 3155f263522aSJoseph Koshy case PMC_CPU_INTEL_PIII: 3156f263522aSJoseph Koshy case PMC_CPU_INTEL_PM: 3157789140c0SJoseph Koshy PMC_MDEP_INIT(p6); 31580cfab8ddSJoseph Koshy pmc_class_table[n] = &p6_class_table_descr; 3159f263522aSJoseph Koshy break; 316086a65549SJoseph Koshy #endif 316186a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 3162f263522aSJoseph Koshy case PMC_CPU_AMD_K8: 3163789140c0SJoseph Koshy PMC_MDEP_INIT(k8); 31640cfab8ddSJoseph Koshy pmc_class_table[n] = &k8_class_table_descr; 31650cfab8ddSJoseph Koshy break; 31660cfab8ddSJoseph Koshy case PMC_CPU_INTEL_ATOM: 3167791f5d5bSJoseph Koshy PMC_MDEP_INIT_INTEL_V2(atom); 31680cfab8ddSJoseph Koshy break; 3169e8f021a3SHiren Panchasara case PMC_CPU_INTEL_ATOM_SILVERMONT: 3170e8f021a3SHiren Panchasara PMC_MDEP_INIT_INTEL_V2(atom_silvermont); 3171e8f021a3SHiren Panchasara break; 31720cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE: 31730cfab8ddSJoseph Koshy PMC_MDEP_INIT(core); 3174bc315bbdSJoseph Koshy pmc_class_table[n] = &core_class_table_descr; 31750cfab8ddSJoseph Koshy break; 31760cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE2: 3177b4d091f3SJoseph Koshy case PMC_CPU_INTEL_CORE2EXTREME: 3178791f5d5bSJoseph Koshy PMC_MDEP_INIT_INTEL_V2(core2); 3179789140c0SJoseph Koshy break; 3180597979c4SJeff Roberson case PMC_CPU_INTEL_COREI7: 31811fa7f10bSFabien Thomas pmc_class_table[n++] = &ucf_class_table_descr; 31821fa7f10bSFabien Thomas pmc_class_table[n++] = &corei7uc_class_table_descr; 3183791f5d5bSJoseph Koshy PMC_MDEP_INIT_INTEL_V2(corei7); 3184597979c4SJeff Roberson break; 318549fe48abSKonstantin Belousov case PMC_CPU_INTEL_NEHALEM_EX: 318649fe48abSKonstantin Belousov PMC_MDEP_INIT_INTEL_V2(nehalem_ex); 318749fe48abSKonstantin Belousov break; 3188cc0c1555SSean Bruno case PMC_CPU_INTEL_HASWELL: 3189cc0c1555SSean Bruno pmc_class_table[n++] = &ucf_class_table_descr; 3190cc0c1555SSean Bruno pmc_class_table[n++] = &haswelluc_class_table_descr; 3191cc0c1555SSean Bruno PMC_MDEP_INIT_INTEL_V2(haswell); 3192cc0c1555SSean Bruno break; 3193d95b3509SRandall Stewart case PMC_CPU_INTEL_HASWELL_XEON: 3194d95b3509SRandall Stewart PMC_MDEP_INIT_INTEL_V2(haswell_xeon); 3195d95b3509SRandall Stewart break; 31961e862e5aSFabien Thomas case PMC_CPU_INTEL_IVYBRIDGE: 31971e862e5aSFabien Thomas PMC_MDEP_INIT_INTEL_V2(ivybridge); 31981e862e5aSFabien Thomas break; 31993f929d8cSSean Bruno case PMC_CPU_INTEL_IVYBRIDGE_XEON: 32003f929d8cSSean Bruno PMC_MDEP_INIT_INTEL_V2(ivybridge_xeon); 32013f929d8cSSean Bruno break; 320278d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 320378d763a2SDavide Italiano pmc_class_table[n++] = &ucf_class_table_descr; 320478d763a2SDavide Italiano pmc_class_table[n++] = &sandybridgeuc_class_table_descr; 320578d763a2SDavide Italiano PMC_MDEP_INIT_INTEL_V2(sandybridge); 320678d763a2SDavide Italiano break; 3207fabe02f5SSean Bruno case PMC_CPU_INTEL_SANDYBRIDGE_XEON: 3208fabe02f5SSean Bruno PMC_MDEP_INIT_INTEL_V2(sandybridge_xeon); 3209fabe02f5SSean Bruno break; 32101fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 32111fa7f10bSFabien Thomas pmc_class_table[n++] = &ucf_class_table_descr; 32121fa7f10bSFabien Thomas pmc_class_table[n++] = &westmereuc_class_table_descr; 32131fa7f10bSFabien Thomas PMC_MDEP_INIT_INTEL_V2(westmere); 32141fa7f10bSFabien Thomas break; 321549fe48abSKonstantin Belousov case PMC_CPU_INTEL_WESTMERE_EX: 321649fe48abSKonstantin Belousov PMC_MDEP_INIT_INTEL_V2(westmere_ex); 321749fe48abSKonstantin Belousov break; 3218789140c0SJoseph Koshy case PMC_CPU_INTEL_PIV: 3219789140c0SJoseph Koshy PMC_MDEP_INIT(p4); 32200cfab8ddSJoseph Koshy pmc_class_table[n] = &p4_class_table_descr; 3221f263522aSJoseph Koshy break; 3222ebccf1e3SJoseph Koshy #endif 3223f5f9340bSFabien Thomas case PMC_CPU_GENERIC: 3224f5f9340bSFabien Thomas PMC_MDEP_INIT(generic); 3225f5f9340bSFabien Thomas break; 32266411d14dSRuslan Bukin #if defined(__arm__) 32270ce207d2SRui Paulo #if defined(__XSCALE__) 32280ce207d2SRui Paulo case PMC_CPU_INTEL_XSCALE: 32290ce207d2SRui Paulo PMC_MDEP_INIT(xscale); 32300ce207d2SRui Paulo pmc_class_table[n] = &xscale_class_table_descr; 32310ce207d2SRui Paulo break; 32320ce207d2SRui Paulo #endif 32336411d14dSRuslan Bukin case PMC_CPU_ARMV7: 32346411d14dSRuslan Bukin PMC_MDEP_INIT(armv7); 32356411d14dSRuslan Bukin pmc_class_table[n] = &armv7_class_table_descr; 32366411d14dSRuslan Bukin break; 32376411d14dSRuslan Bukin #endif 3238660df75eSGeorge V. Neville-Neil #if defined(__mips__) 3239660df75eSGeorge V. Neville-Neil case PMC_CPU_MIPS_24K: 3240660df75eSGeorge V. Neville-Neil PMC_MDEP_INIT(mips24k); 3241660df75eSGeorge V. Neville-Neil pmc_class_table[n] = &mips24k_class_table_descr; 3242660df75eSGeorge V. Neville-Neil break; 3243f6e6460dSAdrian Chadd case PMC_CPU_MIPS_74K: 3244f6e6460dSAdrian Chadd PMC_MDEP_INIT(mips74k); 3245f6e6460dSAdrian Chadd pmc_class_table[n] = &mips74k_class_table_descr; 3246f6e6460dSAdrian Chadd break; 3247c2657f80SOleksandr Tymoshenko case PMC_CPU_MIPS_OCTEON: 3248c2657f80SOleksandr Tymoshenko PMC_MDEP_INIT(octeon); 3249c2657f80SOleksandr Tymoshenko pmc_class_table[n] = &octeon_class_table_descr; 3250c2657f80SOleksandr Tymoshenko break; 3251660df75eSGeorge V. Neville-Neil #endif /* __mips__ */ 32527b25dccaSJustin Hibbits #if defined(__powerpc__) 32537b25dccaSJustin Hibbits case PMC_CPU_PPC_7450: 32547b25dccaSJustin Hibbits PMC_MDEP_INIT(ppc7450); 32557b25dccaSJustin Hibbits pmc_class_table[n] = &ppc7450_class_table_descr; 32567b25dccaSJustin Hibbits break; 3257169dd953SJustin Hibbits case PMC_CPU_PPC_970: 3258169dd953SJustin Hibbits PMC_MDEP_INIT(ppc970); 3259169dd953SJustin Hibbits pmc_class_table[n] = &ppc970_class_table_descr; 3260169dd953SJustin Hibbits break; 3261*a7452468SJustin Hibbits case PMC_CPU_PPC_E500: 3262*a7452468SJustin Hibbits PMC_MDEP_INIT(e500); 3263*a7452468SJustin Hibbits pmc_class_table[n] = &e500_class_table_descr; 3264*a7452468SJustin Hibbits break; 32657b25dccaSJustin Hibbits #endif 3266f263522aSJoseph Koshy default: 3267f263522aSJoseph Koshy /* 3268f263522aSJoseph Koshy * Some kind of CPU this version of the library knows nothing 3269f263522aSJoseph Koshy * about. This shouldn't happen since the abi version check 3270f263522aSJoseph Koshy * should have caught this. 3271f263522aSJoseph Koshy */ 3272f263522aSJoseph Koshy errno = ENXIO; 3273f263522aSJoseph Koshy return (pmc_syscall = -1); 3274f263522aSJoseph Koshy } 3275f263522aSJoseph Koshy 3276aa342b1fSJoseph Koshy return (0); 3277f263522aSJoseph Koshy } 3278f263522aSJoseph Koshy 3279f263522aSJoseph Koshy const char * 3280f263522aSJoseph Koshy pmc_name_of_capability(enum pmc_caps cap) 3281f263522aSJoseph Koshy { 3282f263522aSJoseph Koshy int i; 3283f263522aSJoseph Koshy 3284f263522aSJoseph Koshy /* 3285f263522aSJoseph Koshy * 'cap' should have a single bit set and should be in 3286f263522aSJoseph Koshy * range. 3287f263522aSJoseph Koshy */ 3288f263522aSJoseph Koshy if ((cap & (cap - 1)) || cap < PMC_CAP_FIRST || 3289f263522aSJoseph Koshy cap > PMC_CAP_LAST) { 3290f263522aSJoseph Koshy errno = EINVAL; 3291aa342b1fSJoseph Koshy return (NULL); 3292f263522aSJoseph Koshy } 3293f263522aSJoseph Koshy 3294f263522aSJoseph Koshy i = ffs(cap); 3295aa342b1fSJoseph Koshy return (pmc_capability_names[i - 1]); 3296f263522aSJoseph Koshy } 3297f263522aSJoseph Koshy 3298f263522aSJoseph Koshy const char * 3299f263522aSJoseph Koshy pmc_name_of_class(enum pmc_class pc) 3300f263522aSJoseph Koshy { 3301f263522aSJoseph Koshy if ((int) pc >= PMC_CLASS_FIRST && 3302f263522aSJoseph Koshy pc <= PMC_CLASS_LAST) 3303aa342b1fSJoseph Koshy return (pmc_class_names[pc]); 3304f263522aSJoseph Koshy 3305f263522aSJoseph Koshy errno = EINVAL; 3306aa342b1fSJoseph Koshy return (NULL); 3307f263522aSJoseph Koshy } 3308f263522aSJoseph Koshy 3309f263522aSJoseph Koshy const char * 3310f263522aSJoseph Koshy pmc_name_of_cputype(enum pmc_cputype cp) 3311f263522aSJoseph Koshy { 3312789140c0SJoseph Koshy size_t n; 3313789140c0SJoseph Koshy 3314789140c0SJoseph Koshy for (n = 0; n < PMC_TABLE_SIZE(pmc_cputype_names); n++) 3315789140c0SJoseph Koshy if (cp == pmc_cputype_names[n].pm_cputype) 3316789140c0SJoseph Koshy return (pmc_cputype_names[n].pm_name); 3317789140c0SJoseph Koshy 3318f263522aSJoseph Koshy errno = EINVAL; 3319aa342b1fSJoseph Koshy return (NULL); 3320f263522aSJoseph Koshy } 3321f263522aSJoseph Koshy 3322f263522aSJoseph Koshy const char * 3323f263522aSJoseph Koshy pmc_name_of_disposition(enum pmc_disp pd) 3324f263522aSJoseph Koshy { 3325f263522aSJoseph Koshy if ((int) pd >= PMC_DISP_FIRST && 3326f263522aSJoseph Koshy pd <= PMC_DISP_LAST) 3327aa342b1fSJoseph Koshy return (pmc_disposition_names[pd]); 3328f263522aSJoseph Koshy 3329f263522aSJoseph Koshy errno = EINVAL; 3330aa342b1fSJoseph Koshy return (NULL); 3331f263522aSJoseph Koshy } 3332f263522aSJoseph Koshy 3333f263522aSJoseph Koshy const char * 33340cfab8ddSJoseph Koshy _pmc_name_of_event(enum pmc_event pe, enum pmc_cputype cpu) 3335f263522aSJoseph Koshy { 3336789140c0SJoseph Koshy const struct pmc_event_descr *ev, *evfence; 3337789140c0SJoseph Koshy 3338789140c0SJoseph Koshy ev = evfence = NULL; 33390cfab8ddSJoseph Koshy if (pe >= PMC_EV_IAF_FIRST && pe <= PMC_EV_IAF_LAST) { 33400cfab8ddSJoseph Koshy ev = iaf_event_table; 33410cfab8ddSJoseph Koshy evfence = iaf_event_table + PMC_EVENT_TABLE_SIZE(iaf); 33420cfab8ddSJoseph Koshy } else if (pe >= PMC_EV_IAP_FIRST && pe <= PMC_EV_IAP_LAST) { 33430cfab8ddSJoseph Koshy switch (cpu) { 33440cfab8ddSJoseph Koshy case PMC_CPU_INTEL_ATOM: 33450cfab8ddSJoseph Koshy ev = atom_event_table; 33460cfab8ddSJoseph Koshy evfence = atom_event_table + PMC_EVENT_TABLE_SIZE(atom); 33470cfab8ddSJoseph Koshy break; 3348e8f021a3SHiren Panchasara case PMC_CPU_INTEL_ATOM_SILVERMONT: 3349e8f021a3SHiren Panchasara ev = atom_silvermont_event_table; 3350e8f021a3SHiren Panchasara evfence = atom_silvermont_event_table + 3351e8f021a3SHiren Panchasara PMC_EVENT_TABLE_SIZE(atom_silvermont); 3352e8f021a3SHiren Panchasara break; 33530cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE: 33540cfab8ddSJoseph Koshy ev = core_event_table; 33550cfab8ddSJoseph Koshy evfence = core_event_table + PMC_EVENT_TABLE_SIZE(core); 33560cfab8ddSJoseph Koshy break; 33570cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE2: 3358b4d091f3SJoseph Koshy case PMC_CPU_INTEL_CORE2EXTREME: 33590cfab8ddSJoseph Koshy ev = core2_event_table; 33600cfab8ddSJoseph Koshy evfence = core2_event_table + PMC_EVENT_TABLE_SIZE(core2); 33610cfab8ddSJoseph Koshy break; 3362597979c4SJeff Roberson case PMC_CPU_INTEL_COREI7: 3363597979c4SJeff Roberson ev = corei7_event_table; 3364597979c4SJeff Roberson evfence = corei7_event_table + PMC_EVENT_TABLE_SIZE(corei7); 3365597979c4SJeff Roberson break; 336649fe48abSKonstantin Belousov case PMC_CPU_INTEL_NEHALEM_EX: 336749fe48abSKonstantin Belousov ev = nehalem_ex_event_table; 336849fe48abSKonstantin Belousov evfence = nehalem_ex_event_table + 336949fe48abSKonstantin Belousov PMC_EVENT_TABLE_SIZE(nehalem_ex); 337049fe48abSKonstantin Belousov break; 3371cc0c1555SSean Bruno case PMC_CPU_INTEL_HASWELL: 3372cc0c1555SSean Bruno ev = haswell_event_table; 3373cc0c1555SSean Bruno evfence = haswell_event_table + PMC_EVENT_TABLE_SIZE(haswell); 3374cc0c1555SSean Bruno break; 3375d95b3509SRandall Stewart case PMC_CPU_INTEL_HASWELL_XEON: 3376d95b3509SRandall Stewart ev = haswell_xeon_event_table; 3377d95b3509SRandall Stewart evfence = haswell_xeon_event_table + PMC_EVENT_TABLE_SIZE(haswell_xeon); 3378d95b3509SRandall Stewart break; 3379d95b3509SRandall Stewart 33801e862e5aSFabien Thomas case PMC_CPU_INTEL_IVYBRIDGE: 33811e862e5aSFabien Thomas ev = ivybridge_event_table; 33821e862e5aSFabien Thomas evfence = ivybridge_event_table + PMC_EVENT_TABLE_SIZE(ivybridge); 33831e862e5aSFabien Thomas break; 33843f929d8cSSean Bruno case PMC_CPU_INTEL_IVYBRIDGE_XEON: 33853f929d8cSSean Bruno ev = ivybridge_xeon_event_table; 33863f929d8cSSean Bruno evfence = ivybridge_xeon_event_table + PMC_EVENT_TABLE_SIZE(ivybridge_xeon); 33873f929d8cSSean Bruno break; 338878d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 338978d763a2SDavide Italiano ev = sandybridge_event_table; 339078d763a2SDavide Italiano evfence = sandybridge_event_table + PMC_EVENT_TABLE_SIZE(sandybridge); 339178d763a2SDavide Italiano break; 3392fabe02f5SSean Bruno case PMC_CPU_INTEL_SANDYBRIDGE_XEON: 3393fabe02f5SSean Bruno ev = sandybridge_xeon_event_table; 3394fabe02f5SSean Bruno evfence = sandybridge_xeon_event_table + PMC_EVENT_TABLE_SIZE(sandybridge_xeon); 3395fabe02f5SSean Bruno break; 33961fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 33971fa7f10bSFabien Thomas ev = westmere_event_table; 33981fa7f10bSFabien Thomas evfence = westmere_event_table + PMC_EVENT_TABLE_SIZE(westmere); 33991fa7f10bSFabien Thomas break; 340049fe48abSKonstantin Belousov case PMC_CPU_INTEL_WESTMERE_EX: 340149fe48abSKonstantin Belousov ev = westmere_ex_event_table; 340249fe48abSKonstantin Belousov evfence = westmere_ex_event_table + 340349fe48abSKonstantin Belousov PMC_EVENT_TABLE_SIZE(westmere_ex); 340449fe48abSKonstantin Belousov break; 34050cfab8ddSJoseph Koshy default: /* Unknown CPU type. */ 34060cfab8ddSJoseph Koshy break; 34070cfab8ddSJoseph Koshy } 34081fa7f10bSFabien Thomas } else if (pe >= PMC_EV_UCF_FIRST && pe <= PMC_EV_UCF_LAST) { 34091fa7f10bSFabien Thomas ev = ucf_event_table; 34101fa7f10bSFabien Thomas evfence = ucf_event_table + PMC_EVENT_TABLE_SIZE(ucf); 34111fa7f10bSFabien Thomas } else if (pe >= PMC_EV_UCP_FIRST && pe <= PMC_EV_UCP_LAST) { 34121fa7f10bSFabien Thomas switch (cpu) { 34131fa7f10bSFabien Thomas case PMC_CPU_INTEL_COREI7: 34141fa7f10bSFabien Thomas ev = corei7uc_event_table; 34151fa7f10bSFabien Thomas evfence = corei7uc_event_table + PMC_EVENT_TABLE_SIZE(corei7uc); 34161fa7f10bSFabien Thomas break; 341778d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 341878d763a2SDavide Italiano ev = sandybridgeuc_event_table; 341978d763a2SDavide Italiano evfence = sandybridgeuc_event_table + PMC_EVENT_TABLE_SIZE(sandybridgeuc); 342078d763a2SDavide Italiano break; 34211fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 34221fa7f10bSFabien Thomas ev = westmereuc_event_table; 34231fa7f10bSFabien Thomas evfence = westmereuc_event_table + PMC_EVENT_TABLE_SIZE(westmereuc); 34241fa7f10bSFabien Thomas break; 34251fa7f10bSFabien Thomas default: /* Unknown CPU type. */ 34261fa7f10bSFabien Thomas break; 34271fa7f10bSFabien Thomas } 34281fa7f10bSFabien Thomas } else if (pe >= PMC_EV_K7_FIRST && pe <= PMC_EV_K7_LAST) { 3429789140c0SJoseph Koshy ev = k7_event_table; 3430789140c0SJoseph Koshy evfence = k7_event_table + PMC_EVENT_TABLE_SIZE(k7); 3431789140c0SJoseph Koshy } else if (pe >= PMC_EV_K8_FIRST && pe <= PMC_EV_K8_LAST) { 3432789140c0SJoseph Koshy ev = k8_event_table; 3433789140c0SJoseph Koshy evfence = k8_event_table + PMC_EVENT_TABLE_SIZE(k8); 3434789140c0SJoseph Koshy } else if (pe >= PMC_EV_P4_FIRST && pe <= PMC_EV_P4_LAST) { 3435789140c0SJoseph Koshy ev = p4_event_table; 3436789140c0SJoseph Koshy evfence = p4_event_table + PMC_EVENT_TABLE_SIZE(p4); 3437789140c0SJoseph Koshy } else if (pe >= PMC_EV_P5_FIRST && pe <= PMC_EV_P5_LAST) { 3438789140c0SJoseph Koshy ev = p5_event_table; 3439789140c0SJoseph Koshy evfence = p5_event_table + PMC_EVENT_TABLE_SIZE(p5); 3440789140c0SJoseph Koshy } else if (pe >= PMC_EV_P6_FIRST && pe <= PMC_EV_P6_LAST) { 3441789140c0SJoseph Koshy ev = p6_event_table; 3442789140c0SJoseph Koshy evfence = p6_event_table + PMC_EVENT_TABLE_SIZE(p6); 34430ce207d2SRui Paulo } else if (pe >= PMC_EV_XSCALE_FIRST && pe <= PMC_EV_XSCALE_LAST) { 34440ce207d2SRui Paulo ev = xscale_event_table; 34450ce207d2SRui Paulo evfence = xscale_event_table + PMC_EVENT_TABLE_SIZE(xscale); 34466411d14dSRuslan Bukin } else if (pe >= PMC_EV_ARMV7_FIRST && pe <= PMC_EV_ARMV7_LAST) { 34476411d14dSRuslan Bukin ev = armv7_event_table; 34486411d14dSRuslan Bukin evfence = armv7_event_table + PMC_EVENT_TABLE_SIZE(armv7); 3449660df75eSGeorge V. Neville-Neil } else if (pe >= PMC_EV_MIPS24K_FIRST && pe <= PMC_EV_MIPS24K_LAST) { 3450660df75eSGeorge V. Neville-Neil ev = mips24k_event_table; 3451f5f9340bSFabien Thomas evfence = mips24k_event_table + PMC_EVENT_TABLE_SIZE(mips24k); 3452f6e6460dSAdrian Chadd } else if (pe >= PMC_EV_MIPS74K_FIRST && pe <= PMC_EV_MIPS74K_LAST) { 3453f6e6460dSAdrian Chadd ev = mips74k_event_table; 3454f6e6460dSAdrian Chadd evfence = mips74k_event_table + PMC_EVENT_TABLE_SIZE(mips74k); 3455c2657f80SOleksandr Tymoshenko } else if (pe >= PMC_EV_OCTEON_FIRST && pe <= PMC_EV_OCTEON_LAST) { 3456c2657f80SOleksandr Tymoshenko ev = octeon_event_table; 3457c2657f80SOleksandr Tymoshenko evfence = octeon_event_table + PMC_EVENT_TABLE_SIZE(octeon); 34587b25dccaSJustin Hibbits } else if (pe >= PMC_EV_PPC7450_FIRST && pe <= PMC_EV_PPC7450_LAST) { 34597b25dccaSJustin Hibbits ev = ppc7450_event_table; 3460f5f9340bSFabien Thomas evfence = ppc7450_event_table + PMC_EVENT_TABLE_SIZE(ppc7450); 3461169dd953SJustin Hibbits } else if (pe >= PMC_EV_PPC970_FIRST && pe <= PMC_EV_PPC970_LAST) { 3462169dd953SJustin Hibbits ev = ppc970_event_table; 3463169dd953SJustin Hibbits evfence = ppc970_event_table + PMC_EVENT_TABLE_SIZE(ppc970); 3464*a7452468SJustin Hibbits } else if (pe >= PMC_EV_E500_FIRST && pe <= PMC_EV_E500_LAST) { 3465*a7452468SJustin Hibbits ev = e500_event_table; 3466*a7452468SJustin Hibbits evfence = e500_event_table + PMC_EVENT_TABLE_SIZE(e500); 3467789140c0SJoseph Koshy } else if (pe == PMC_EV_TSC_TSC) { 3468789140c0SJoseph Koshy ev = tsc_event_table; 3469789140c0SJoseph Koshy evfence = tsc_event_table + PMC_EVENT_TABLE_SIZE(tsc); 3470f0bbe9aaSDimitry Andric } else if ((int)pe >= PMC_EV_SOFT_FIRST && (int)pe <= PMC_EV_SOFT_LAST) { 3471f5f9340bSFabien Thomas ev = soft_event_table; 3472f5f9340bSFabien Thomas evfence = soft_event_table + soft_event_info.pm_nevent; 3473789140c0SJoseph Koshy } 3474789140c0SJoseph Koshy 3475789140c0SJoseph Koshy for (; ev != evfence; ev++) 3476789140c0SJoseph Koshy if (pe == ev->pm_ev_code) 3477789140c0SJoseph Koshy return (ev->pm_ev_name); 3478f263522aSJoseph Koshy 34790cfab8ddSJoseph Koshy return (NULL); 34800cfab8ddSJoseph Koshy } 34810cfab8ddSJoseph Koshy 34820cfab8ddSJoseph Koshy const char * 34830cfab8ddSJoseph Koshy pmc_name_of_event(enum pmc_event pe) 34840cfab8ddSJoseph Koshy { 34850cfab8ddSJoseph Koshy const char *n; 34860cfab8ddSJoseph Koshy 34870cfab8ddSJoseph Koshy if ((n = _pmc_name_of_event(pe, cpu_info.pm_cputype)) != NULL) 34880cfab8ddSJoseph Koshy return (n); 34890cfab8ddSJoseph Koshy 3490f263522aSJoseph Koshy errno = EINVAL; 3491aa342b1fSJoseph Koshy return (NULL); 3492f263522aSJoseph Koshy } 3493f263522aSJoseph Koshy 3494f263522aSJoseph Koshy const char * 3495f263522aSJoseph Koshy pmc_name_of_mode(enum pmc_mode pm) 3496f263522aSJoseph Koshy { 3497f263522aSJoseph Koshy if ((int) pm >= PMC_MODE_FIRST && 3498f263522aSJoseph Koshy pm <= PMC_MODE_LAST) 3499aa342b1fSJoseph Koshy return (pmc_mode_names[pm]); 3500f263522aSJoseph Koshy 3501f263522aSJoseph Koshy errno = EINVAL; 3502aa342b1fSJoseph Koshy return (NULL); 3503f263522aSJoseph Koshy } 3504f263522aSJoseph Koshy 3505f263522aSJoseph Koshy const char * 3506f263522aSJoseph Koshy pmc_name_of_state(enum pmc_state ps) 3507f263522aSJoseph Koshy { 3508f263522aSJoseph Koshy if ((int) ps >= PMC_STATE_FIRST && 3509f263522aSJoseph Koshy ps <= PMC_STATE_LAST) 3510aa342b1fSJoseph Koshy return (pmc_state_names[ps]); 3511f263522aSJoseph Koshy 3512f263522aSJoseph Koshy errno = EINVAL; 3513aa342b1fSJoseph Koshy return (NULL); 3514f263522aSJoseph Koshy } 3515f263522aSJoseph Koshy 3516f263522aSJoseph Koshy int 3517f263522aSJoseph Koshy pmc_ncpu(void) 3518f263522aSJoseph Koshy { 3519f263522aSJoseph Koshy if (pmc_syscall == -1) { 3520f263522aSJoseph Koshy errno = ENXIO; 3521aa342b1fSJoseph Koshy return (-1); 3522f263522aSJoseph Koshy } 3523f263522aSJoseph Koshy 3524aa342b1fSJoseph Koshy return (cpu_info.pm_ncpu); 3525f263522aSJoseph Koshy } 3526f263522aSJoseph Koshy 3527f263522aSJoseph Koshy int 3528f263522aSJoseph Koshy pmc_npmc(int cpu) 3529f263522aSJoseph Koshy { 3530f263522aSJoseph Koshy if (pmc_syscall == -1) { 3531f263522aSJoseph Koshy errno = ENXIO; 3532aa342b1fSJoseph Koshy return (-1); 3533f263522aSJoseph Koshy } 3534f263522aSJoseph Koshy 3535f263522aSJoseph Koshy if (cpu < 0 || cpu >= (int) cpu_info.pm_ncpu) { 3536f263522aSJoseph Koshy errno = EINVAL; 3537aa342b1fSJoseph Koshy return (-1); 3538f263522aSJoseph Koshy } 3539f263522aSJoseph Koshy 3540aa342b1fSJoseph Koshy return (cpu_info.pm_npmc); 3541f263522aSJoseph Koshy } 3542f263522aSJoseph Koshy 3543f263522aSJoseph Koshy int 3544f263522aSJoseph Koshy pmc_pmcinfo(int cpu, struct pmc_pmcinfo **ppmci) 3545f263522aSJoseph Koshy { 3546f263522aSJoseph Koshy int nbytes, npmc; 3547f263522aSJoseph Koshy struct pmc_op_getpmcinfo *pmci; 3548f263522aSJoseph Koshy 3549f263522aSJoseph Koshy if ((npmc = pmc_npmc(cpu)) < 0) 3550aa342b1fSJoseph Koshy return (-1); 3551f263522aSJoseph Koshy 3552f263522aSJoseph Koshy nbytes = sizeof(struct pmc_op_getpmcinfo) + 3553f263522aSJoseph Koshy npmc * sizeof(struct pmc_info); 3554f263522aSJoseph Koshy 3555f263522aSJoseph Koshy if ((pmci = calloc(1, nbytes)) == NULL) 3556aa342b1fSJoseph Koshy return (-1); 3557f263522aSJoseph Koshy 3558f263522aSJoseph Koshy pmci->pm_cpu = cpu; 3559f263522aSJoseph Koshy 3560f263522aSJoseph Koshy if (PMC_CALL(GETPMCINFO, pmci) < 0) { 3561f263522aSJoseph Koshy free(pmci); 3562aa342b1fSJoseph Koshy return (-1); 3563f263522aSJoseph Koshy } 3564f263522aSJoseph Koshy 3565f263522aSJoseph Koshy /* kernel<->library, library<->userland interfaces are identical */ 3566f263522aSJoseph Koshy *ppmci = (struct pmc_pmcinfo *) pmci; 3567aa342b1fSJoseph Koshy return (0); 3568f263522aSJoseph Koshy } 3569f263522aSJoseph Koshy 3570f263522aSJoseph Koshy int 3571f263522aSJoseph Koshy pmc_read(pmc_id_t pmc, pmc_value_t *value) 3572f263522aSJoseph Koshy { 3573f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_read_op; 3574f263522aSJoseph Koshy 3575f263522aSJoseph Koshy pmc_read_op.pm_pmcid = pmc; 3576f263522aSJoseph Koshy pmc_read_op.pm_flags = PMC_F_OLDVALUE; 3577f263522aSJoseph Koshy pmc_read_op.pm_value = -1; 3578f263522aSJoseph Koshy 3579f263522aSJoseph Koshy if (PMC_CALL(PMCRW, &pmc_read_op) < 0) 3580aa342b1fSJoseph Koshy return (-1); 3581f263522aSJoseph Koshy 3582f263522aSJoseph Koshy *value = pmc_read_op.pm_value; 3583aa342b1fSJoseph Koshy return (0); 3584f263522aSJoseph Koshy } 3585f263522aSJoseph Koshy 3586f263522aSJoseph Koshy int 3587f263522aSJoseph Koshy pmc_release(pmc_id_t pmc) 3588f263522aSJoseph Koshy { 3589f263522aSJoseph Koshy struct pmc_op_simple pmc_release_args; 3590f263522aSJoseph Koshy 3591f263522aSJoseph Koshy pmc_release_args.pm_pmcid = pmc; 3592aa342b1fSJoseph Koshy return (PMC_CALL(PMCRELEASE, &pmc_release_args)); 3593f263522aSJoseph Koshy } 3594f263522aSJoseph Koshy 3595f263522aSJoseph Koshy int 3596f263522aSJoseph Koshy pmc_rw(pmc_id_t pmc, pmc_value_t newvalue, pmc_value_t *oldvaluep) 3597f263522aSJoseph Koshy { 3598f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_rw_op; 3599f263522aSJoseph Koshy 3600f263522aSJoseph Koshy pmc_rw_op.pm_pmcid = pmc; 3601f263522aSJoseph Koshy pmc_rw_op.pm_flags = PMC_F_NEWVALUE | PMC_F_OLDVALUE; 3602f263522aSJoseph Koshy pmc_rw_op.pm_value = newvalue; 3603f263522aSJoseph Koshy 3604f263522aSJoseph Koshy if (PMC_CALL(PMCRW, &pmc_rw_op) < 0) 3605aa342b1fSJoseph Koshy return (-1); 3606f263522aSJoseph Koshy 3607f263522aSJoseph Koshy *oldvaluep = pmc_rw_op.pm_value; 3608aa342b1fSJoseph Koshy return (0); 3609f263522aSJoseph Koshy } 3610f263522aSJoseph Koshy 3611f263522aSJoseph Koshy int 3612f263522aSJoseph Koshy pmc_set(pmc_id_t pmc, pmc_value_t value) 3613f263522aSJoseph Koshy { 3614f263522aSJoseph Koshy struct pmc_op_pmcsetcount sc; 3615f263522aSJoseph Koshy 3616f263522aSJoseph Koshy sc.pm_pmcid = pmc; 3617f263522aSJoseph Koshy sc.pm_count = value; 3618f263522aSJoseph Koshy 3619f263522aSJoseph Koshy if (PMC_CALL(PMCSETCOUNT, &sc) < 0) 3620aa342b1fSJoseph Koshy return (-1); 3621aa342b1fSJoseph Koshy return (0); 3622f263522aSJoseph Koshy } 3623f263522aSJoseph Koshy 3624f263522aSJoseph Koshy int 3625f263522aSJoseph Koshy pmc_start(pmc_id_t pmc) 3626f263522aSJoseph Koshy { 3627f263522aSJoseph Koshy struct pmc_op_simple pmc_start_args; 3628f263522aSJoseph Koshy 3629f263522aSJoseph Koshy pmc_start_args.pm_pmcid = pmc; 3630aa342b1fSJoseph Koshy return (PMC_CALL(PMCSTART, &pmc_start_args)); 3631f263522aSJoseph Koshy } 3632f263522aSJoseph Koshy 3633f263522aSJoseph Koshy int 3634f263522aSJoseph Koshy pmc_stop(pmc_id_t pmc) 3635f263522aSJoseph Koshy { 3636f263522aSJoseph Koshy struct pmc_op_simple pmc_stop_args; 3637f263522aSJoseph Koshy 3638f263522aSJoseph Koshy pmc_stop_args.pm_pmcid = pmc; 3639aa342b1fSJoseph Koshy return (PMC_CALL(PMCSTOP, &pmc_stop_args)); 3640f263522aSJoseph Koshy } 3641f263522aSJoseph Koshy 3642f263522aSJoseph Koshy int 3643f263522aSJoseph Koshy pmc_width(pmc_id_t pmcid, uint32_t *width) 3644f263522aSJoseph Koshy { 3645f263522aSJoseph Koshy unsigned int i; 3646f263522aSJoseph Koshy enum pmc_class cl; 3647f263522aSJoseph Koshy 3648f263522aSJoseph Koshy cl = PMC_ID_TO_CLASS(pmcid); 3649f263522aSJoseph Koshy for (i = 0; i < cpu_info.pm_nclass; i++) 3650f263522aSJoseph Koshy if (cpu_info.pm_classes[i].pm_class == cl) { 3651f263522aSJoseph Koshy *width = cpu_info.pm_classes[i].pm_width; 3652aa342b1fSJoseph Koshy return (0); 3653f263522aSJoseph Koshy } 3654484202faSJoseph Koshy errno = EINVAL; 3655484202faSJoseph Koshy return (-1); 3656f263522aSJoseph Koshy } 3657f263522aSJoseph Koshy 3658f263522aSJoseph Koshy int 3659f263522aSJoseph Koshy pmc_write(pmc_id_t pmc, pmc_value_t value) 3660f263522aSJoseph Koshy { 3661f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_write_op; 3662f263522aSJoseph Koshy 3663f263522aSJoseph Koshy pmc_write_op.pm_pmcid = pmc; 3664f263522aSJoseph Koshy pmc_write_op.pm_flags = PMC_F_NEWVALUE; 3665f263522aSJoseph Koshy pmc_write_op.pm_value = value; 3666aa342b1fSJoseph Koshy return (PMC_CALL(PMCRW, &pmc_write_op)); 3667f263522aSJoseph Koshy } 3668f263522aSJoseph Koshy 3669f263522aSJoseph Koshy int 3670f263522aSJoseph Koshy pmc_writelog(uint32_t userdata) 3671f263522aSJoseph Koshy { 3672f263522aSJoseph Koshy struct pmc_op_writelog wl; 3673f263522aSJoseph Koshy 3674f263522aSJoseph Koshy wl.pm_userdata = userdata; 3675aa342b1fSJoseph Koshy return (PMC_CALL(WRITELOG, &wl)); 3676f263522aSJoseph Koshy } 3677