1ebccf1e3SJoseph Koshy /*- 25e53a4f9SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 35e53a4f9SPedro F. Giffuni * 4484202faSJoseph Koshy * Copyright (c) 2003-2008 Joseph Koshy 5ebccf1e3SJoseph Koshy * All rights reserved. 6ebccf1e3SJoseph Koshy * 7ebccf1e3SJoseph Koshy * Redistribution and use in source and binary forms, with or without 8ebccf1e3SJoseph Koshy * modification, are permitted provided that the following conditions 9ebccf1e3SJoseph Koshy * are met: 10ebccf1e3SJoseph Koshy * 1. Redistributions of source code must retain the above copyright 11ebccf1e3SJoseph Koshy * notice, this list of conditions and the following disclaimer. 12ebccf1e3SJoseph Koshy * 2. Redistributions in binary form must reproduce the above copyright 13ebccf1e3SJoseph Koshy * notice, this list of conditions and the following disclaimer in the 14ebccf1e3SJoseph Koshy * documentation and/or other materials provided with the distribution. 15ebccf1e3SJoseph Koshy * 16ebccf1e3SJoseph Koshy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17ebccf1e3SJoseph Koshy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18ebccf1e3SJoseph Koshy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19ebccf1e3SJoseph Koshy * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20ebccf1e3SJoseph Koshy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21ebccf1e3SJoseph Koshy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22ebccf1e3SJoseph Koshy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23ebccf1e3SJoseph Koshy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24ebccf1e3SJoseph Koshy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25ebccf1e3SJoseph Koshy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26ebccf1e3SJoseph Koshy * SUCH DAMAGE. 27ebccf1e3SJoseph Koshy */ 28ebccf1e3SJoseph Koshy 29ebccf1e3SJoseph Koshy #include <sys/cdefs.h> 30ebccf1e3SJoseph Koshy __FBSDID("$FreeBSD$"); 31ebccf1e3SJoseph Koshy 32ebccf1e3SJoseph Koshy #include <sys/types.h> 33169dd953SJustin Hibbits #include <sys/param.h> 34ebccf1e3SJoseph Koshy #include <sys/module.h> 35ebccf1e3SJoseph Koshy #include <sys/pmc.h> 36ebccf1e3SJoseph Koshy #include <sys/syscall.h> 37ebccf1e3SJoseph Koshy 38ebccf1e3SJoseph Koshy #include <ctype.h> 39ebccf1e3SJoseph Koshy #include <errno.h> 40ebccf1e3SJoseph Koshy #include <fcntl.h> 41ebccf1e3SJoseph Koshy #include <pmc.h> 42ebccf1e3SJoseph Koshy #include <stdio.h> 43ebccf1e3SJoseph Koshy #include <stdlib.h> 44ebccf1e3SJoseph Koshy #include <string.h> 45ebccf1e3SJoseph Koshy #include <strings.h> 46ebccf1e3SJoseph Koshy #include <unistd.h> 47ebccf1e3SJoseph Koshy 480cfab8ddSJoseph Koshy #include "libpmcinternal.h" 490cfab8ddSJoseph Koshy 50ebccf1e3SJoseph Koshy /* Function prototypes */ 5104e9feb0SMarcel Moolenaar #if defined(__i386__) 52ebccf1e3SJoseph Koshy static int k7_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 53ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 54f263522aSJoseph Koshy #endif 5586a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 560cfab8ddSJoseph Koshy static int iaf_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 570cfab8ddSJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 580cfab8ddSJoseph Koshy static int iap_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 590cfab8ddSJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 601fa7f10bSFabien Thomas static int ucf_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 611fa7f10bSFabien Thomas struct pmc_op_pmcallocate *_pmc_config); 621fa7f10bSFabien Thomas static int ucp_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 631fa7f10bSFabien Thomas struct pmc_op_pmcallocate *_pmc_config); 64f263522aSJoseph Koshy static int k8_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 65ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 6686a65549SJoseph Koshy static int p4_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 6786a65549SJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 68f263522aSJoseph Koshy #endif 69f263522aSJoseph Koshy #if defined(__i386__) 70ebccf1e3SJoseph Koshy static int p5_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 71ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 72f263522aSJoseph Koshy static int p6_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 73ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 74ebccf1e3SJoseph Koshy #endif 75789140c0SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 76789140c0SJoseph Koshy static int tsc_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 77789140c0SJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 78789140c0SJoseph Koshy #endif 796411d14dSRuslan Bukin #if defined(__arm__) 800ce207d2SRui Paulo #if defined(__XSCALE__) 810ce207d2SRui Paulo static int xscale_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 820ce207d2SRui Paulo struct pmc_op_pmcallocate *_pmc_config); 830ce207d2SRui Paulo #endif 846411d14dSRuslan Bukin static int armv7_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 856411d14dSRuslan Bukin struct pmc_op_pmcallocate *_pmc_config); 866411d14dSRuslan Bukin #endif 87bc88bb2bSRuslan Bukin #if defined(__aarch64__) 88bc88bb2bSRuslan Bukin static int arm64_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 89bc88bb2bSRuslan Bukin struct pmc_op_pmcallocate *_pmc_config); 90bc88bb2bSRuslan Bukin #endif 91660df75eSGeorge V. Neville-Neil #if defined(__mips__) 922827d3e1SOleksandr Tymoshenko static int mips_allocate_pmc(enum pmc_event _pe, char* ctrspec, 93660df75eSGeorge V. Neville-Neil struct pmc_op_pmcallocate *_pmc_config); 94660df75eSGeorge V. Neville-Neil #endif /* __mips__ */ 95f5f9340bSFabien Thomas static int soft_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 96f5f9340bSFabien Thomas struct pmc_op_pmcallocate *_pmc_config); 97660df75eSGeorge V. Neville-Neil 987b25dccaSJustin Hibbits #if defined(__powerpc__) 99169dd953SJustin Hibbits static int powerpc_allocate_pmc(enum pmc_event _pe, char* ctrspec, 1007b25dccaSJustin Hibbits struct pmc_op_pmcallocate *_pmc_config); 1017b25dccaSJustin Hibbits #endif /* __powerpc__ */ 102660df75eSGeorge V. Neville-Neil 103ebccf1e3SJoseph Koshy #define PMC_CALL(cmd, params) \ 104ebccf1e3SJoseph Koshy syscall(pmc_syscall, PMC_OP_##cmd, (params)) 105ebccf1e3SJoseph Koshy 106ebccf1e3SJoseph Koshy /* 107ebccf1e3SJoseph Koshy * Event aliases provide a way for the user to ask for generic events 108ebccf1e3SJoseph Koshy * like "cache-misses", or "instructions-retired". These aliases are 109ebccf1e3SJoseph Koshy * mapped to the appropriate canonical event descriptions using a 110ebccf1e3SJoseph Koshy * lookup table. 111ebccf1e3SJoseph Koshy */ 112ebccf1e3SJoseph Koshy struct pmc_event_alias { 113ebccf1e3SJoseph Koshy const char *pm_alias; 114ebccf1e3SJoseph Koshy const char *pm_spec; 115ebccf1e3SJoseph Koshy }; 116ebccf1e3SJoseph Koshy 117ebccf1e3SJoseph Koshy static const struct pmc_event_alias *pmc_mdep_event_aliases; 118ebccf1e3SJoseph Koshy 119ebccf1e3SJoseph Koshy /* 120789140c0SJoseph Koshy * The pmc_event_descr structure maps symbolic names known to the user 121ebccf1e3SJoseph Koshy * to integer codes used by the PMC KLD. 122ebccf1e3SJoseph Koshy */ 123ebccf1e3SJoseph Koshy struct pmc_event_descr { 124ebccf1e3SJoseph Koshy const char *pm_ev_name; 125ebccf1e3SJoseph Koshy enum pmc_event pm_ev_code; 126ebccf1e3SJoseph Koshy }; 127ebccf1e3SJoseph Koshy 128789140c0SJoseph Koshy /* 129789140c0SJoseph Koshy * The pmc_class_descr structure maps class name prefixes for 130789140c0SJoseph Koshy * event names to event tables and other PMC class data. 131789140c0SJoseph Koshy */ 132789140c0SJoseph Koshy struct pmc_class_descr { 133789140c0SJoseph Koshy const char *pm_evc_name; 134789140c0SJoseph Koshy size_t pm_evc_name_size; 135789140c0SJoseph Koshy enum pmc_class pm_evc_class; 136789140c0SJoseph Koshy const struct pmc_event_descr *pm_evc_event_table; 137789140c0SJoseph Koshy size_t pm_evc_event_table_size; 138789140c0SJoseph Koshy int (*pm_evc_allocate_pmc)(enum pmc_event _pe, 139789140c0SJoseph Koshy char *_ctrspec, struct pmc_op_pmcallocate *_pa); 140ebccf1e3SJoseph Koshy }; 141ebccf1e3SJoseph Koshy 142789140c0SJoseph Koshy #define PMC_TABLE_SIZE(N) (sizeof(N)/sizeof(N[0])) 143789140c0SJoseph Koshy #define PMC_EVENT_TABLE_SIZE(N) PMC_TABLE_SIZE(N##_event_table) 144789140c0SJoseph Koshy 145789140c0SJoseph Koshy #undef __PMC_EV 146789140c0SJoseph Koshy #define __PMC_EV(C,N) { #N, PMC_EV_ ## C ## _ ## N }, 147789140c0SJoseph Koshy 148789140c0SJoseph Koshy /* 1490cfab8ddSJoseph Koshy * PMC_CLASSDEP_TABLE(NAME, CLASS) 150789140c0SJoseph Koshy * 1510cfab8ddSJoseph Koshy * Define a table mapping event names and aliases to HWPMC event IDs. 152789140c0SJoseph Koshy */ 1530cfab8ddSJoseph Koshy #define PMC_CLASSDEP_TABLE(N, C) \ 154789140c0SJoseph Koshy static const struct pmc_event_descr N##_event_table[] = \ 155789140c0SJoseph Koshy { \ 156789140c0SJoseph Koshy __PMC_EV_##C() \ 1570cfab8ddSJoseph Koshy } 1580cfab8ddSJoseph Koshy 1590cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(iaf, IAF); 1600cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(k7, K7); 1610cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(k8, K8); 1620cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(p4, P4); 1630cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(p5, P5); 1640cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(p6, P6); 1650ce207d2SRui Paulo PMC_CLASSDEP_TABLE(xscale, XSCALE); 1666411d14dSRuslan Bukin PMC_CLASSDEP_TABLE(armv7, ARMV7); 167bc88bb2bSRuslan Bukin PMC_CLASSDEP_TABLE(armv8, ARMV8); 168660df75eSGeorge V. Neville-Neil PMC_CLASSDEP_TABLE(mips24k, MIPS24K); 169f6e6460dSAdrian Chadd PMC_CLASSDEP_TABLE(mips74k, MIPS74K); 170c2657f80SOleksandr Tymoshenko PMC_CLASSDEP_TABLE(octeon, OCTEON); 1711fa7f10bSFabien Thomas PMC_CLASSDEP_TABLE(ucf, UCF); 1727b25dccaSJustin Hibbits PMC_CLASSDEP_TABLE(ppc7450, PPC7450); 173169dd953SJustin Hibbits PMC_CLASSDEP_TABLE(ppc970, PPC970); 174a7452468SJustin Hibbits PMC_CLASSDEP_TABLE(e500, E500); 1750cfab8ddSJoseph Koshy 176f5f9340bSFabien Thomas static struct pmc_event_descr soft_event_table[PMC_EV_DYN_COUNT]; 177f5f9340bSFabien Thomas 1780cfab8ddSJoseph Koshy #undef __PMC_EV_ALIAS 1790cfab8ddSJoseph Koshy #define __PMC_EV_ALIAS(N,CODE) { N, PMC_EV_##CODE }, 1800cfab8ddSJoseph Koshy 1810cfab8ddSJoseph Koshy static const struct pmc_event_descr atom_event_table[] = 1820cfab8ddSJoseph Koshy { 1830cfab8ddSJoseph Koshy __PMC_EV_ALIAS_ATOM() 1840cfab8ddSJoseph Koshy }; 1850cfab8ddSJoseph Koshy 186e8f021a3SHiren Panchasara static const struct pmc_event_descr atom_silvermont_event_table[] = 187e8f021a3SHiren Panchasara { 188e8f021a3SHiren Panchasara __PMC_EV_ALIAS_ATOM_SILVERMONT() 189e8f021a3SHiren Panchasara }; 190e8f021a3SHiren Panchasara 1910cfab8ddSJoseph Koshy static const struct pmc_event_descr core_event_table[] = 1920cfab8ddSJoseph Koshy { 1930cfab8ddSJoseph Koshy __PMC_EV_ALIAS_CORE() 1940cfab8ddSJoseph Koshy }; 1950cfab8ddSJoseph Koshy 1960cfab8ddSJoseph Koshy 1970cfab8ddSJoseph Koshy static const struct pmc_event_descr core2_event_table[] = 1980cfab8ddSJoseph Koshy { 1990cfab8ddSJoseph Koshy __PMC_EV_ALIAS_CORE2() 2000cfab8ddSJoseph Koshy }; 2010cfab8ddSJoseph Koshy 202597979c4SJeff Roberson static const struct pmc_event_descr corei7_event_table[] = 203597979c4SJeff Roberson { 204597979c4SJeff Roberson __PMC_EV_ALIAS_COREI7() 205597979c4SJeff Roberson }; 206597979c4SJeff Roberson 20749fe48abSKonstantin Belousov static const struct pmc_event_descr nehalem_ex_event_table[] = 20849fe48abSKonstantin Belousov { 20949fe48abSKonstantin Belousov __PMC_EV_ALIAS_COREI7() 21049fe48abSKonstantin Belousov }; 21149fe48abSKonstantin Belousov 212cc0c1555SSean Bruno static const struct pmc_event_descr haswell_event_table[] = 213cc0c1555SSean Bruno { 214cc0c1555SSean Bruno __PMC_EV_ALIAS_HASWELL() 215cc0c1555SSean Bruno }; 216cc0c1555SSean Bruno 217d95b3509SRandall Stewart static const struct pmc_event_descr haswell_xeon_event_table[] = 218d95b3509SRandall Stewart { 219d95b3509SRandall Stewart __PMC_EV_ALIAS_HASWELL_XEON() 220d95b3509SRandall Stewart }; 221d95b3509SRandall Stewart 222f19bae41SRandall Stewart static const struct pmc_event_descr broadwell_event_table[] = 223f19bae41SRandall Stewart { 224f19bae41SRandall Stewart __PMC_EV_ALIAS_BROADWELL() 225f19bae41SRandall Stewart }; 226f19bae41SRandall Stewart 227f19bae41SRandall Stewart static const struct pmc_event_descr broadwell_xeon_event_table[] = 228f19bae41SRandall Stewart { 229f19bae41SRandall Stewart __PMC_EV_ALIAS_BROADWELL_XEON() 230f19bae41SRandall Stewart }; 231f19bae41SRandall Stewart 232f19bae41SRandall Stewart static const struct pmc_event_descr skylake_event_table[] = 233f19bae41SRandall Stewart { 234f19bae41SRandall Stewart __PMC_EV_ALIAS_SKYLAKE() 235f19bae41SRandall Stewart }; 236d95b3509SRandall Stewart 237b99b705dSKonstantin Belousov static const struct pmc_event_descr skylake_xeon_event_table[] = 238b99b705dSKonstantin Belousov { 239b99b705dSKonstantin Belousov __PMC_EV_ALIAS_SKYLAKE_XEON() 240b99b705dSKonstantin Belousov }; 241b99b705dSKonstantin Belousov 2421e862e5aSFabien Thomas static const struct pmc_event_descr ivybridge_event_table[] = 2431e862e5aSFabien Thomas { 2441e862e5aSFabien Thomas __PMC_EV_ALIAS_IVYBRIDGE() 2451e862e5aSFabien Thomas }; 2461e862e5aSFabien Thomas 2473f929d8cSSean Bruno static const struct pmc_event_descr ivybridge_xeon_event_table[] = 2483f929d8cSSean Bruno { 2493f929d8cSSean Bruno __PMC_EV_ALIAS_IVYBRIDGE_XEON() 2503f929d8cSSean Bruno }; 2513f929d8cSSean Bruno 25278d763a2SDavide Italiano static const struct pmc_event_descr sandybridge_event_table[] = 25378d763a2SDavide Italiano { 25478d763a2SDavide Italiano __PMC_EV_ALIAS_SANDYBRIDGE() 25578d763a2SDavide Italiano }; 25678d763a2SDavide Italiano 257fabe02f5SSean Bruno static const struct pmc_event_descr sandybridge_xeon_event_table[] = 258fabe02f5SSean Bruno { 259fabe02f5SSean Bruno __PMC_EV_ALIAS_SANDYBRIDGE_XEON() 260fabe02f5SSean Bruno }; 261fabe02f5SSean Bruno 2621fa7f10bSFabien Thomas static const struct pmc_event_descr westmere_event_table[] = 2631fa7f10bSFabien Thomas { 2641fa7f10bSFabien Thomas __PMC_EV_ALIAS_WESTMERE() 2651fa7f10bSFabien Thomas }; 2661fa7f10bSFabien Thomas 26749fe48abSKonstantin Belousov static const struct pmc_event_descr westmere_ex_event_table[] = 26849fe48abSKonstantin Belousov { 26949fe48abSKonstantin Belousov __PMC_EV_ALIAS_WESTMERE() 27049fe48abSKonstantin Belousov }; 27149fe48abSKonstantin Belousov 2721fa7f10bSFabien Thomas static const struct pmc_event_descr corei7uc_event_table[] = 2731fa7f10bSFabien Thomas { 2741fa7f10bSFabien Thomas __PMC_EV_ALIAS_COREI7UC() 2751fa7f10bSFabien Thomas }; 2761fa7f10bSFabien Thomas 277cc0c1555SSean Bruno static const struct pmc_event_descr haswelluc_event_table[] = 278cc0c1555SSean Bruno { 279cc0c1555SSean Bruno __PMC_EV_ALIAS_HASWELLUC() 280cc0c1555SSean Bruno }; 281cc0c1555SSean Bruno 282f19bae41SRandall Stewart static const struct pmc_event_descr broadwelluc_event_table[] = 283f19bae41SRandall Stewart { 284f19bae41SRandall Stewart __PMC_EV_ALIAS_BROADWELLUC() 285f19bae41SRandall Stewart }; 286f19bae41SRandall Stewart 28778d763a2SDavide Italiano static const struct pmc_event_descr sandybridgeuc_event_table[] = 28878d763a2SDavide Italiano { 28978d763a2SDavide Italiano __PMC_EV_ALIAS_SANDYBRIDGEUC() 29078d763a2SDavide Italiano }; 29178d763a2SDavide Italiano 2921fa7f10bSFabien Thomas static const struct pmc_event_descr westmereuc_event_table[] = 2931fa7f10bSFabien Thomas { 2941fa7f10bSFabien Thomas __PMC_EV_ALIAS_WESTMEREUC() 2951fa7f10bSFabien Thomas }; 2961fa7f10bSFabien Thomas 2973e0bfdd8SRuslan Bukin static const struct pmc_event_descr cortex_a8_event_table[] = 2983e0bfdd8SRuslan Bukin { 2993e0bfdd8SRuslan Bukin __PMC_EV_ALIAS_ARMV7_CORTEX_A8() 3003e0bfdd8SRuslan Bukin }; 3013e0bfdd8SRuslan Bukin 3023e0bfdd8SRuslan Bukin static const struct pmc_event_descr cortex_a9_event_table[] = 3033e0bfdd8SRuslan Bukin { 3043e0bfdd8SRuslan Bukin __PMC_EV_ALIAS_ARMV7_CORTEX_A9() 3053e0bfdd8SRuslan Bukin }; 3063e0bfdd8SRuslan Bukin 307bc88bb2bSRuslan Bukin static const struct pmc_event_descr cortex_a53_event_table[] = 308bc88bb2bSRuslan Bukin { 309bc88bb2bSRuslan Bukin __PMC_EV_ALIAS_ARMV8_CORTEX_A53() 310bc88bb2bSRuslan Bukin }; 311bc88bb2bSRuslan Bukin 312bc88bb2bSRuslan Bukin static const struct pmc_event_descr cortex_a57_event_table[] = 313bc88bb2bSRuslan Bukin { 314bc88bb2bSRuslan Bukin __PMC_EV_ALIAS_ARMV8_CORTEX_A57() 315bc88bb2bSRuslan Bukin }; 316bc88bb2bSRuslan Bukin 3170cfab8ddSJoseph Koshy /* 3180cfab8ddSJoseph Koshy * PMC_MDEP_TABLE(NAME, PRIMARYCLASS, ADDITIONAL_CLASSES...) 3190cfab8ddSJoseph Koshy * 3200cfab8ddSJoseph Koshy * Map a CPU to the PMC classes it supports. 3210cfab8ddSJoseph Koshy */ 3220cfab8ddSJoseph Koshy #define PMC_MDEP_TABLE(N,C,...) \ 323789140c0SJoseph Koshy static const enum pmc_class N##_pmc_classes[] = { \ 324789140c0SJoseph Koshy PMC_CLASS_##C, __VA_ARGS__ \ 325789140c0SJoseph Koshy } 326789140c0SJoseph Koshy 327f5f9340bSFabien Thomas PMC_MDEP_TABLE(atom, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 328e8f021a3SHiren Panchasara PMC_MDEP_TABLE(atom_silvermont, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 329f5f9340bSFabien Thomas PMC_MDEP_TABLE(core, IAP, PMC_CLASS_SOFT, PMC_CLASS_TSC); 330f5f9340bSFabien Thomas PMC_MDEP_TABLE(core2, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 331f5f9340bSFabien Thomas PMC_MDEP_TABLE(corei7, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 33249fe48abSKonstantin Belousov PMC_MDEP_TABLE(nehalem_ex, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 333cc0c1555SSean Bruno PMC_MDEP_TABLE(haswell, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 334d95b3509SRandall Stewart PMC_MDEP_TABLE(haswell_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 335f19bae41SRandall Stewart PMC_MDEP_TABLE(broadwell, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 336f19bae41SRandall Stewart PMC_MDEP_TABLE(broadwell_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 337f19bae41SRandall Stewart PMC_MDEP_TABLE(skylake, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 338b99b705dSKonstantin Belousov PMC_MDEP_TABLE(skylake_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 3391e862e5aSFabien Thomas PMC_MDEP_TABLE(ivybridge, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 3403f929d8cSSean Bruno PMC_MDEP_TABLE(ivybridge_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 341f5f9340bSFabien Thomas PMC_MDEP_TABLE(sandybridge, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 342fabe02f5SSean Bruno PMC_MDEP_TABLE(sandybridge_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 343f5f9340bSFabien Thomas PMC_MDEP_TABLE(westmere, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 34449fe48abSKonstantin Belousov PMC_MDEP_TABLE(westmere_ex, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 345f5f9340bSFabien Thomas PMC_MDEP_TABLE(k7, K7, PMC_CLASS_SOFT, PMC_CLASS_TSC); 346f5f9340bSFabien Thomas PMC_MDEP_TABLE(k8, K8, PMC_CLASS_SOFT, PMC_CLASS_TSC); 347f5f9340bSFabien Thomas PMC_MDEP_TABLE(p4, P4, PMC_CLASS_SOFT, PMC_CLASS_TSC); 348f5f9340bSFabien Thomas PMC_MDEP_TABLE(p5, P5, PMC_CLASS_SOFT, PMC_CLASS_TSC); 349f5f9340bSFabien Thomas PMC_MDEP_TABLE(p6, P6, PMC_CLASS_SOFT, PMC_CLASS_TSC); 350f5f9340bSFabien Thomas PMC_MDEP_TABLE(xscale, XSCALE, PMC_CLASS_SOFT, PMC_CLASS_XSCALE); 3513e0bfdd8SRuslan Bukin PMC_MDEP_TABLE(cortex_a8, ARMV7, PMC_CLASS_SOFT, PMC_CLASS_ARMV7); 3523e0bfdd8SRuslan Bukin PMC_MDEP_TABLE(cortex_a9, ARMV7, PMC_CLASS_SOFT, PMC_CLASS_ARMV7); 353bc88bb2bSRuslan Bukin PMC_MDEP_TABLE(cortex_a53, ARMV8, PMC_CLASS_SOFT, PMC_CLASS_ARMV8); 354bc88bb2bSRuslan Bukin PMC_MDEP_TABLE(cortex_a57, ARMV8, PMC_CLASS_SOFT, PMC_CLASS_ARMV8); 355f5f9340bSFabien Thomas PMC_MDEP_TABLE(mips24k, MIPS24K, PMC_CLASS_SOFT, PMC_CLASS_MIPS24K); 356f6e6460dSAdrian Chadd PMC_MDEP_TABLE(mips74k, MIPS74K, PMC_CLASS_SOFT, PMC_CLASS_MIPS74K); 357f5f9340bSFabien Thomas PMC_MDEP_TABLE(octeon, OCTEON, PMC_CLASS_SOFT, PMC_CLASS_OCTEON); 358a7452468SJustin Hibbits PMC_MDEP_TABLE(ppc7450, PPC7450, PMC_CLASS_SOFT, PMC_CLASS_PPC7450, PMC_CLASS_TSC); 359a7452468SJustin Hibbits PMC_MDEP_TABLE(ppc970, PPC970, PMC_CLASS_SOFT, PMC_CLASS_PPC970, PMC_CLASS_TSC); 360a7452468SJustin Hibbits PMC_MDEP_TABLE(e500, E500, PMC_CLASS_SOFT, PMC_CLASS_E500, PMC_CLASS_TSC); 361f5f9340bSFabien Thomas PMC_MDEP_TABLE(generic, SOFT, PMC_CLASS_SOFT); 362789140c0SJoseph Koshy 363789140c0SJoseph Koshy static const struct pmc_event_descr tsc_event_table[] = 364789140c0SJoseph Koshy { 365789140c0SJoseph Koshy __PMC_EV_TSC() 366789140c0SJoseph Koshy }; 367789140c0SJoseph Koshy 368789140c0SJoseph Koshy #undef PMC_CLASS_TABLE_DESC 3690cfab8ddSJoseph Koshy #define PMC_CLASS_TABLE_DESC(NAME, CLASS, EVENTS, ALLOCATOR) \ 3700cfab8ddSJoseph Koshy static const struct pmc_class_descr NAME##_class_table_descr = \ 3710cfab8ddSJoseph Koshy { \ 3720cfab8ddSJoseph Koshy .pm_evc_name = #CLASS "-", \ 3730cfab8ddSJoseph Koshy .pm_evc_name_size = sizeof(#CLASS "-") - 1, \ 3740cfab8ddSJoseph Koshy .pm_evc_class = PMC_CLASS_##CLASS , \ 3750cfab8ddSJoseph Koshy .pm_evc_event_table = EVENTS##_event_table , \ 376789140c0SJoseph Koshy .pm_evc_event_table_size = \ 3770cfab8ddSJoseph Koshy PMC_EVENT_TABLE_SIZE(EVENTS), \ 3780cfab8ddSJoseph Koshy .pm_evc_allocate_pmc = ALLOCATOR##_allocate_pmc \ 379789140c0SJoseph Koshy } 380789140c0SJoseph Koshy 381789140c0SJoseph Koshy #if defined(__i386__) || defined(__amd64__) 3820cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(iaf, IAF, iaf, iaf); 3830cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(atom, IAP, atom, iap); 384e8f021a3SHiren Panchasara PMC_CLASS_TABLE_DESC(atom_silvermont, IAP, atom_silvermont, iap); 3850cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(core, IAP, core, iap); 3860cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(core2, IAP, core2, iap); 387597979c4SJeff Roberson PMC_CLASS_TABLE_DESC(corei7, IAP, corei7, iap); 38849fe48abSKonstantin Belousov PMC_CLASS_TABLE_DESC(nehalem_ex, IAP, nehalem_ex, iap); 389cc0c1555SSean Bruno PMC_CLASS_TABLE_DESC(haswell, IAP, haswell, iap); 390ae9975dbSRyan Stone PMC_CLASS_TABLE_DESC(haswell_xeon, IAP, haswell_xeon, iap); 391f19bae41SRandall Stewart PMC_CLASS_TABLE_DESC(broadwell, IAP, broadwell, iap); 392f19bae41SRandall Stewart PMC_CLASS_TABLE_DESC(broadwell_xeon, IAP, broadwell_xeon, iap); 393f19bae41SRandall Stewart PMC_CLASS_TABLE_DESC(skylake, IAP, skylake, iap); 394b99b705dSKonstantin Belousov PMC_CLASS_TABLE_DESC(skylake_xeon, IAP, skylake_xeon, iap); 3951e862e5aSFabien Thomas PMC_CLASS_TABLE_DESC(ivybridge, IAP, ivybridge, iap); 3963f929d8cSSean Bruno PMC_CLASS_TABLE_DESC(ivybridge_xeon, IAP, ivybridge_xeon, iap); 39778d763a2SDavide Italiano PMC_CLASS_TABLE_DESC(sandybridge, IAP, sandybridge, iap); 398fabe02f5SSean Bruno PMC_CLASS_TABLE_DESC(sandybridge_xeon, IAP, sandybridge_xeon, iap); 3991fa7f10bSFabien Thomas PMC_CLASS_TABLE_DESC(westmere, IAP, westmere, iap); 40049fe48abSKonstantin Belousov PMC_CLASS_TABLE_DESC(westmere_ex, IAP, westmere_ex, iap); 4011fa7f10bSFabien Thomas PMC_CLASS_TABLE_DESC(ucf, UCF, ucf, ucf); 4021fa7f10bSFabien Thomas PMC_CLASS_TABLE_DESC(corei7uc, UCP, corei7uc, ucp); 403cc0c1555SSean Bruno PMC_CLASS_TABLE_DESC(haswelluc, UCP, haswelluc, ucp); 404f19bae41SRandall Stewart PMC_CLASS_TABLE_DESC(broadwelluc, UCP, broadwelluc, ucp); 40578d763a2SDavide Italiano PMC_CLASS_TABLE_DESC(sandybridgeuc, UCP, sandybridgeuc, ucp); 4061fa7f10bSFabien Thomas PMC_CLASS_TABLE_DESC(westmereuc, UCP, westmereuc, ucp); 407789140c0SJoseph Koshy #endif 408789140c0SJoseph Koshy #if defined(__i386__) 4090cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(k7, K7, k7, k7); 410789140c0SJoseph Koshy #endif 411789140c0SJoseph Koshy #if defined(__i386__) || defined(__amd64__) 4120cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(k8, K8, k8, k8); 4130cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(p4, P4, p4, p4); 414789140c0SJoseph Koshy #endif 4150cfab8ddSJoseph Koshy #if defined(__i386__) 4160cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(p5, P5, p5, p5); 4170cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(p6, P6, p6, p6); 4180cfab8ddSJoseph Koshy #endif 4190cfab8ddSJoseph Koshy #if defined(__i386__) || defined(__amd64__) 4200cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(tsc, TSC, tsc, tsc); 4210cfab8ddSJoseph Koshy #endif 4226411d14dSRuslan Bukin #if defined(__arm__) 4230ce207d2SRui Paulo #if defined(__XSCALE__) 4240ce207d2SRui Paulo PMC_CLASS_TABLE_DESC(xscale, XSCALE, xscale, xscale); 4250ce207d2SRui Paulo #endif 4263ed01392SBjoern A. Zeeb PMC_CLASS_TABLE_DESC(cortex_a8, ARMV7, cortex_a8, armv7); 4273e0bfdd8SRuslan Bukin PMC_CLASS_TABLE_DESC(cortex_a9, ARMV7, cortex_a9, armv7); 4286411d14dSRuslan Bukin #endif 429bc88bb2bSRuslan Bukin #if defined(__aarch64__) 430bc88bb2bSRuslan Bukin PMC_CLASS_TABLE_DESC(cortex_a53, ARMV8, cortex_a53, arm64); 431bc88bb2bSRuslan Bukin PMC_CLASS_TABLE_DESC(cortex_a57, ARMV8, cortex_a57, arm64); 432bc88bb2bSRuslan Bukin #endif 433660df75eSGeorge V. Neville-Neil #if defined(__mips__) 4342827d3e1SOleksandr Tymoshenko PMC_CLASS_TABLE_DESC(mips24k, MIPS24K, mips24k, mips); 435f6e6460dSAdrian Chadd PMC_CLASS_TABLE_DESC(mips74k, MIPS74K, mips74k, mips); 436c2657f80SOleksandr Tymoshenko PMC_CLASS_TABLE_DESC(octeon, OCTEON, octeon, mips); 437660df75eSGeorge V. Neville-Neil #endif /* __mips__ */ 4387b25dccaSJustin Hibbits #if defined(__powerpc__) 439169dd953SJustin Hibbits PMC_CLASS_TABLE_DESC(ppc7450, PPC7450, ppc7450, powerpc); 440169dd953SJustin Hibbits PMC_CLASS_TABLE_DESC(ppc970, PPC970, ppc970, powerpc); 441a7452468SJustin Hibbits PMC_CLASS_TABLE_DESC(e500, E500, e500, powerpc); 4427b25dccaSJustin Hibbits #endif 4437b25dccaSJustin Hibbits 444f5f9340bSFabien Thomas static struct pmc_class_descr soft_class_table_descr = 445f5f9340bSFabien Thomas { 446f5f9340bSFabien Thomas .pm_evc_name = "SOFT-", 447f5f9340bSFabien Thomas .pm_evc_name_size = sizeof("SOFT-") - 1, 448f5f9340bSFabien Thomas .pm_evc_class = PMC_CLASS_SOFT, 449f5f9340bSFabien Thomas .pm_evc_event_table = NULL, 450f5f9340bSFabien Thomas .pm_evc_event_table_size = 0, 451f5f9340bSFabien Thomas .pm_evc_allocate_pmc = soft_allocate_pmc 452f5f9340bSFabien Thomas }; 453f5f9340bSFabien Thomas 454789140c0SJoseph Koshy #undef PMC_CLASS_TABLE_DESC 455789140c0SJoseph Koshy 4560cfab8ddSJoseph Koshy static const struct pmc_class_descr **pmc_class_table; 4570cfab8ddSJoseph Koshy #define PMC_CLASS_TABLE_SIZE cpu_info.pm_nclass 4580cfab8ddSJoseph Koshy 459789140c0SJoseph Koshy static const enum pmc_class *pmc_mdep_class_list; 460789140c0SJoseph Koshy static size_t pmc_mdep_class_list_size; 461789140c0SJoseph Koshy 462ebccf1e3SJoseph Koshy /* 463ebccf1e3SJoseph Koshy * Mapping tables, mapping enumeration values to human readable 464ebccf1e3SJoseph Koshy * strings. 465ebccf1e3SJoseph Koshy */ 466ebccf1e3SJoseph Koshy 467ebccf1e3SJoseph Koshy static const char * pmc_capability_names[] = { 468ebccf1e3SJoseph Koshy #undef __PMC_CAP 469ebccf1e3SJoseph Koshy #define __PMC_CAP(N,V,D) #N , 470ebccf1e3SJoseph Koshy __PMC_CAPS() 471ebccf1e3SJoseph Koshy }; 472ebccf1e3SJoseph Koshy 4730ceb54c2SJohn Baldwin struct pmc_class_map { 4740ceb54c2SJohn Baldwin enum pmc_class pm_class; 4750ceb54c2SJohn Baldwin const char *pm_name; 4760ceb54c2SJohn Baldwin }; 4770ceb54c2SJohn Baldwin 4780ceb54c2SJohn Baldwin static const struct pmc_class_map pmc_class_names[] = { 479ebccf1e3SJoseph Koshy #undef __PMC_CLASS 4800ceb54c2SJohn Baldwin #define __PMC_CLASS(S,V,D) { .pm_class = PMC_CLASS_##S, .pm_name = #S } , 481ebccf1e3SJoseph Koshy __PMC_CLASSES() 482ebccf1e3SJoseph Koshy }; 483ebccf1e3SJoseph Koshy 484789140c0SJoseph Koshy struct pmc_cputype_map { 485562fc14bSDimitry Andric enum pmc_cputype pm_cputype; 486789140c0SJoseph Koshy const char *pm_name; 487789140c0SJoseph Koshy }; 488789140c0SJoseph Koshy 489789140c0SJoseph Koshy static const struct pmc_cputype_map pmc_cputype_names[] = { 490ebccf1e3SJoseph Koshy #undef __PMC_CPU 491789140c0SJoseph Koshy #define __PMC_CPU(S, V, D) { .pm_cputype = PMC_CPU_##S, .pm_name = #S } , 492ebccf1e3SJoseph Koshy __PMC_CPUS() 493ebccf1e3SJoseph Koshy }; 494ebccf1e3SJoseph Koshy 495ebccf1e3SJoseph Koshy static const char * pmc_disposition_names[] = { 496ebccf1e3SJoseph Koshy #undef __PMC_DISP 497ebccf1e3SJoseph Koshy #define __PMC_DISP(D) #D , 498ebccf1e3SJoseph Koshy __PMC_DISPOSITIONS() 499ebccf1e3SJoseph Koshy }; 500ebccf1e3SJoseph Koshy 501ebccf1e3SJoseph Koshy static const char * pmc_mode_names[] = { 502ebccf1e3SJoseph Koshy #undef __PMC_MODE 503ebccf1e3SJoseph Koshy #define __PMC_MODE(M,N) #M , 504ebccf1e3SJoseph Koshy __PMC_MODES() 505ebccf1e3SJoseph Koshy }; 506ebccf1e3SJoseph Koshy 507ebccf1e3SJoseph Koshy static const char * pmc_state_names[] = { 508ebccf1e3SJoseph Koshy #undef __PMC_STATE 509ebccf1e3SJoseph Koshy #define __PMC_STATE(S) #S , 510ebccf1e3SJoseph Koshy __PMC_STATES() 511ebccf1e3SJoseph Koshy }; 512ebccf1e3SJoseph Koshy 513f5f9340bSFabien Thomas /* 514f5f9340bSFabien Thomas * Filled in by pmc_init(). 515f5f9340bSFabien Thomas */ 516f5f9340bSFabien Thomas static int pmc_syscall = -1; 517f5f9340bSFabien Thomas static struct pmc_cpuinfo cpu_info; 518f5f9340bSFabien Thomas static struct pmc_op_getdyneventinfo soft_event_info; 5191455fcd3SJoseph Koshy 520ebccf1e3SJoseph Koshy /* Event masks for events */ 521ebccf1e3SJoseph Koshy struct pmc_masks { 522ebccf1e3SJoseph Koshy const char *pm_name; 5231e862e5aSFabien Thomas const uint64_t pm_value; 524ebccf1e3SJoseph Koshy }; 525ebccf1e3SJoseph Koshy #define PMCMASK(N,V) { .pm_name = #N, .pm_value = (V) } 5261fa7f10bSFabien Thomas #define NULLMASK { .pm_name = NULL } 527ebccf1e3SJoseph Koshy 52886a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 529ebccf1e3SJoseph Koshy static int 5301e862e5aSFabien Thomas pmc_parse_mask(const struct pmc_masks *pmask, char *p, uint64_t *evmask) 531ebccf1e3SJoseph Koshy { 532ebccf1e3SJoseph Koshy const struct pmc_masks *pm; 533ebccf1e3SJoseph Koshy char *q, *r; 534ebccf1e3SJoseph Koshy int c; 535ebccf1e3SJoseph Koshy 536ebccf1e3SJoseph Koshy if (pmask == NULL) /* no mask keywords */ 537aa342b1fSJoseph Koshy return (-1); 538ebccf1e3SJoseph Koshy q = strchr(p, '='); /* skip '=' */ 539ebccf1e3SJoseph Koshy if (*++q == '\0') /* no more data */ 540aa342b1fSJoseph Koshy return (-1); 541ebccf1e3SJoseph Koshy c = 0; /* count of mask keywords seen */ 542ebccf1e3SJoseph Koshy while ((r = strsep(&q, "+")) != NULL) { 543789140c0SJoseph Koshy for (pm = pmask; pm->pm_name && strcasecmp(r, pm->pm_name); 544789140c0SJoseph Koshy pm++) 545ebccf1e3SJoseph Koshy ; 546ebccf1e3SJoseph Koshy if (pm->pm_name == NULL) /* not found */ 547aa342b1fSJoseph Koshy return (-1); 548ebccf1e3SJoseph Koshy *evmask |= pm->pm_value; 549ebccf1e3SJoseph Koshy c++; 550ebccf1e3SJoseph Koshy } 551aa342b1fSJoseph Koshy return (c); 552ebccf1e3SJoseph Koshy } 55304e9feb0SMarcel Moolenaar #endif 554ebccf1e3SJoseph Koshy 555ebccf1e3SJoseph Koshy #define KWMATCH(p,kw) (strcasecmp((p), (kw)) == 0) 556ebccf1e3SJoseph Koshy #define KWPREFIXMATCH(p,kw) (strncasecmp((p), (kw), sizeof((kw)) - 1) == 0) 557ebccf1e3SJoseph Koshy #define EV_ALIAS(N,S) { .pm_alias = N, .pm_spec = S } 558ebccf1e3SJoseph Koshy 55904e9feb0SMarcel Moolenaar #if defined(__i386__) 560ebccf1e3SJoseph Koshy 561ebccf1e3SJoseph Koshy /* 562ebccf1e3SJoseph Koshy * AMD K7 (Athlon) CPUs. 563ebccf1e3SJoseph Koshy */ 564ebccf1e3SJoseph Koshy 565ebccf1e3SJoseph Koshy static struct pmc_event_alias k7_aliases[] = { 566ebccf1e3SJoseph Koshy EV_ALIAS("branches", "k7-retired-branches"), 567ebccf1e3SJoseph Koshy EV_ALIAS("branch-mispredicts", "k7-retired-branches-mispredicted"), 568ebccf1e3SJoseph Koshy EV_ALIAS("cycles", "tsc"), 5696aa5a193SJoseph Koshy EV_ALIAS("dc-misses", "k7-dc-misses"), 570ebccf1e3SJoseph Koshy EV_ALIAS("ic-misses", "k7-ic-misses"), 571ebccf1e3SJoseph Koshy EV_ALIAS("instructions", "k7-retired-instructions"), 572ebccf1e3SJoseph Koshy EV_ALIAS("interrupts", "k7-hardware-interrupts"), 573ebccf1e3SJoseph Koshy EV_ALIAS(NULL, NULL) 574ebccf1e3SJoseph Koshy }; 575ebccf1e3SJoseph Koshy 576ebccf1e3SJoseph Koshy #define K7_KW_COUNT "count" 577ebccf1e3SJoseph Koshy #define K7_KW_EDGE "edge" 578ebccf1e3SJoseph Koshy #define K7_KW_INV "inv" 579ebccf1e3SJoseph Koshy #define K7_KW_OS "os" 580ebccf1e3SJoseph Koshy #define K7_KW_UNITMASK "unitmask" 581ebccf1e3SJoseph Koshy #define K7_KW_USR "usr" 582ebccf1e3SJoseph Koshy 583ebccf1e3SJoseph Koshy static int 584ebccf1e3SJoseph Koshy k7_allocate_pmc(enum pmc_event pe, char *ctrspec, 585ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 586ebccf1e3SJoseph Koshy { 587ebccf1e3SJoseph Koshy char *e, *p, *q; 588ebccf1e3SJoseph Koshy int c, has_unitmask; 589ebccf1e3SJoseph Koshy uint32_t count, unitmask; 590ebccf1e3SJoseph Koshy 591f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 592789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 593ebccf1e3SJoseph Koshy 594ebccf1e3SJoseph Koshy if (pe == PMC_EV_K7_DC_REFILLS_FROM_L2 || 595ebccf1e3SJoseph Koshy pe == PMC_EV_K7_DC_REFILLS_FROM_SYSTEM || 596ebccf1e3SJoseph Koshy pe == PMC_EV_K7_DC_WRITEBACKS) { 597ebccf1e3SJoseph Koshy has_unitmask = 1; 598f263522aSJoseph Koshy unitmask = AMD_PMC_UNITMASK_MOESI; 599ebccf1e3SJoseph Koshy } else 600ebccf1e3SJoseph Koshy unitmask = has_unitmask = 0; 601ebccf1e3SJoseph Koshy 602ebccf1e3SJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 603ebccf1e3SJoseph Koshy if (KWPREFIXMATCH(p, K7_KW_COUNT "=")) { 604ebccf1e3SJoseph Koshy q = strchr(p, '='); 605ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 606aa342b1fSJoseph Koshy return (-1); 607ebccf1e3SJoseph Koshy 608ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 609ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 610aa342b1fSJoseph Koshy return (-1); 611ebccf1e3SJoseph Koshy 612ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 613f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config |= 614f263522aSJoseph Koshy AMD_PMC_TO_COUNTER(count); 615ebccf1e3SJoseph Koshy 616ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_EDGE)) { 617ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 618ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_INV)) { 619ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 620ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_OS)) { 621ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 622ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, K7_KW_UNITMASK "=")) { 623ebccf1e3SJoseph Koshy if (has_unitmask == 0) 624aa342b1fSJoseph Koshy return (-1); 625ebccf1e3SJoseph Koshy unitmask = 0; 626ebccf1e3SJoseph Koshy q = strchr(p, '='); 627ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 628aa342b1fSJoseph Koshy return (-1); 629ebccf1e3SJoseph Koshy 630ebccf1e3SJoseph Koshy while ((c = tolower(*q++)) != 0) 631ebccf1e3SJoseph Koshy if (c == 'm') 632f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_M; 633ebccf1e3SJoseph Koshy else if (c == 'o') 634f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_O; 635ebccf1e3SJoseph Koshy else if (c == 'e') 636f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_E; 637ebccf1e3SJoseph Koshy else if (c == 's') 638f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_S; 639ebccf1e3SJoseph Koshy else if (c == 'i') 640f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_I; 641ebccf1e3SJoseph Koshy else if (c == '+') 642ebccf1e3SJoseph Koshy continue; 643ebccf1e3SJoseph Koshy else 644aa342b1fSJoseph Koshy return (-1); 645ebccf1e3SJoseph Koshy 646ebccf1e3SJoseph Koshy if (unitmask == 0) 647aa342b1fSJoseph Koshy return (-1); 648ebccf1e3SJoseph Koshy 649ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_USR)) { 650ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 651ebccf1e3SJoseph Koshy } else 652aa342b1fSJoseph Koshy return (-1); 653ebccf1e3SJoseph Koshy } 654ebccf1e3SJoseph Koshy 655ebccf1e3SJoseph Koshy if (has_unitmask) { 656ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 657f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config |= 658f263522aSJoseph Koshy AMD_PMC_TO_UNITMASK(unitmask); 659ebccf1e3SJoseph Koshy } 660ebccf1e3SJoseph Koshy 661aa342b1fSJoseph Koshy return (0); 662ebccf1e3SJoseph Koshy 663ebccf1e3SJoseph Koshy } 664ebccf1e3SJoseph Koshy 665f263522aSJoseph Koshy #endif 666f263522aSJoseph Koshy 66786a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 668f263522aSJoseph Koshy 669f263522aSJoseph Koshy /* 6700cfab8ddSJoseph Koshy * Intel Core (Family 6, Model E) PMCs. 6710cfab8ddSJoseph Koshy */ 6720cfab8ddSJoseph Koshy 6730cfab8ddSJoseph Koshy static struct pmc_event_alias core_aliases[] = { 6740cfab8ddSJoseph Koshy EV_ALIAS("branches", "iap-br-instr-ret"), 6750cfab8ddSJoseph Koshy EV_ALIAS("branch-mispredicts", "iap-br-mispred-ret"), 6760cfab8ddSJoseph Koshy EV_ALIAS("cycles", "tsc-tsc"), 6770cfab8ddSJoseph Koshy EV_ALIAS("ic-misses", "iap-icache-misses"), 6780cfab8ddSJoseph Koshy EV_ALIAS("instructions", "iap-instr-ret"), 6790cfab8ddSJoseph Koshy EV_ALIAS("interrupts", "iap-core-hw-int-rx"), 6800cfab8ddSJoseph Koshy EV_ALIAS("unhalted-cycles", "iap-unhalted-core-cycles"), 6810cfab8ddSJoseph Koshy EV_ALIAS(NULL, NULL) 6820cfab8ddSJoseph Koshy }; 6830cfab8ddSJoseph Koshy 6840cfab8ddSJoseph Koshy /* 6850cfab8ddSJoseph Koshy * Intel Core2 (Family 6, Model F), Core2Extreme (Family 6, Model 17H) 6860cfab8ddSJoseph Koshy * and Atom (Family 6, model 1CH) PMCs. 687791f5d5bSJoseph Koshy * 688791f5d5bSJoseph Koshy * We map aliases to events on the fixed-function counters if these 689791f5d5bSJoseph Koshy * are present. Note that not all CPUs in this family contain fixed-function 690791f5d5bSJoseph Koshy * counters. 6910cfab8ddSJoseph Koshy */ 6920cfab8ddSJoseph Koshy 6930cfab8ddSJoseph Koshy static struct pmc_event_alias core2_aliases[] = { 6940cfab8ddSJoseph Koshy EV_ALIAS("branches", "iap-br-inst-retired.any"), 6950cfab8ddSJoseph Koshy EV_ALIAS("branch-mispredicts", "iap-br-inst-retired.mispred"), 6960cfab8ddSJoseph Koshy EV_ALIAS("cycles", "tsc-tsc"), 6970cfab8ddSJoseph Koshy EV_ALIAS("ic-misses", "iap-l1i-misses"), 6980cfab8ddSJoseph Koshy EV_ALIAS("instructions", "iaf-instr-retired.any"), 6990cfab8ddSJoseph Koshy EV_ALIAS("interrupts", "iap-hw-int-rcv"), 7000cfab8ddSJoseph Koshy EV_ALIAS("unhalted-cycles", "iaf-cpu-clk-unhalted.core"), 7010cfab8ddSJoseph Koshy EV_ALIAS(NULL, NULL) 7020cfab8ddSJoseph Koshy }; 703791f5d5bSJoseph Koshy 704791f5d5bSJoseph Koshy static struct pmc_event_alias core2_aliases_without_iaf[] = { 705791f5d5bSJoseph Koshy EV_ALIAS("branches", "iap-br-inst-retired.any"), 706791f5d5bSJoseph Koshy EV_ALIAS("branch-mispredicts", "iap-br-inst-retired.mispred"), 707791f5d5bSJoseph Koshy EV_ALIAS("cycles", "tsc-tsc"), 708791f5d5bSJoseph Koshy EV_ALIAS("ic-misses", "iap-l1i-misses"), 709791f5d5bSJoseph Koshy EV_ALIAS("instructions", "iap-inst-retired.any_p"), 710791f5d5bSJoseph Koshy EV_ALIAS("interrupts", "iap-hw-int-rcv"), 711791f5d5bSJoseph Koshy EV_ALIAS("unhalted-cycles", "iap-cpu-clk-unhalted.core_p"), 712791f5d5bSJoseph Koshy EV_ALIAS(NULL, NULL) 713791f5d5bSJoseph Koshy }; 714791f5d5bSJoseph Koshy 7150cfab8ddSJoseph Koshy #define atom_aliases core2_aliases 716791f5d5bSJoseph Koshy #define atom_aliases_without_iaf core2_aliases_without_iaf 717e8f021a3SHiren Panchasara #define atom_silvermont_aliases core2_aliases 718e8f021a3SHiren Panchasara #define atom_silvermont_aliases_without_iaf core2_aliases_without_iaf 719597979c4SJeff Roberson #define corei7_aliases core2_aliases 720791f5d5bSJoseph Koshy #define corei7_aliases_without_iaf core2_aliases_without_iaf 72149fe48abSKonstantin Belousov #define nehalem_ex_aliases core2_aliases 72249fe48abSKonstantin Belousov #define nehalem_ex_aliases_without_iaf core2_aliases_without_iaf 723cc0c1555SSean Bruno #define haswell_aliases core2_aliases 724cc0c1555SSean Bruno #define haswell_aliases_without_iaf core2_aliases_without_iaf 725d95b3509SRandall Stewart #define haswell_xeon_aliases core2_aliases 726d95b3509SRandall Stewart #define haswell_xeon_aliases_without_iaf core2_aliases_without_iaf 727f19bae41SRandall Stewart #define broadwell_aliases core2_aliases 728f19bae41SRandall Stewart #define broadwell_aliases_without_iaf core2_aliases_without_iaf 729f19bae41SRandall Stewart #define broadwell_xeon_aliases core2_aliases 730f19bae41SRandall Stewart #define broadwell_xeon_aliases_without_iaf core2_aliases_without_iaf 731f19bae41SRandall Stewart #define skylake_aliases core2_aliases 732f19bae41SRandall Stewart #define skylake_aliases_without_iaf core2_aliases_without_iaf 733b99b705dSKonstantin Belousov #define skylake_xeon_aliases core2_aliases 734b99b705dSKonstantin Belousov #define skylake_xeon_aliases_without_iaf core2_aliases_without_iaf 7351e862e5aSFabien Thomas #define ivybridge_aliases core2_aliases 7361e862e5aSFabien Thomas #define ivybridge_aliases_without_iaf core2_aliases_without_iaf 7373f929d8cSSean Bruno #define ivybridge_xeon_aliases core2_aliases 7383f929d8cSSean Bruno #define ivybridge_xeon_aliases_without_iaf core2_aliases_without_iaf 73978d763a2SDavide Italiano #define sandybridge_aliases core2_aliases 74078d763a2SDavide Italiano #define sandybridge_aliases_without_iaf core2_aliases_without_iaf 741fabe02f5SSean Bruno #define sandybridge_xeon_aliases core2_aliases 742fabe02f5SSean Bruno #define sandybridge_xeon_aliases_without_iaf core2_aliases_without_iaf 7431fa7f10bSFabien Thomas #define westmere_aliases core2_aliases 7441fa7f10bSFabien Thomas #define westmere_aliases_without_iaf core2_aliases_without_iaf 74549fe48abSKonstantin Belousov #define westmere_ex_aliases core2_aliases 74649fe48abSKonstantin Belousov #define westmere_ex_aliases_without_iaf core2_aliases_without_iaf 7470cfab8ddSJoseph Koshy 7480cfab8ddSJoseph Koshy #define IAF_KW_OS "os" 7490cfab8ddSJoseph Koshy #define IAF_KW_USR "usr" 7500cfab8ddSJoseph Koshy #define IAF_KW_ANYTHREAD "anythread" 7510cfab8ddSJoseph Koshy 7520cfab8ddSJoseph Koshy /* 7530cfab8ddSJoseph Koshy * Parse an event specifier for Intel fixed function counters. 7540cfab8ddSJoseph Koshy */ 7550cfab8ddSJoseph Koshy static int 7560cfab8ddSJoseph Koshy iaf_allocate_pmc(enum pmc_event pe, char *ctrspec, 7570cfab8ddSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 7580cfab8ddSJoseph Koshy { 7590cfab8ddSJoseph Koshy char *p; 7600cfab8ddSJoseph Koshy 7610cfab8ddSJoseph Koshy (void) pe; 7620cfab8ddSJoseph Koshy 7630cfab8ddSJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 7640cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iaf.pm_iaf_flags = 0; 7650cfab8ddSJoseph Koshy 7660cfab8ddSJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 7670cfab8ddSJoseph Koshy if (KWMATCH(p, IAF_KW_OS)) 7680cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 7690cfab8ddSJoseph Koshy else if (KWMATCH(p, IAF_KW_USR)) 7700cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 7710cfab8ddSJoseph Koshy else if (KWMATCH(p, IAF_KW_ANYTHREAD)) 7720cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iaf.pm_iaf_flags |= IAF_ANY; 7730cfab8ddSJoseph Koshy else 7740cfab8ddSJoseph Koshy return (-1); 7750cfab8ddSJoseph Koshy } 7760cfab8ddSJoseph Koshy 7770cfab8ddSJoseph Koshy return (0); 7780cfab8ddSJoseph Koshy } 7790cfab8ddSJoseph Koshy 7800cfab8ddSJoseph Koshy /* 7810cfab8ddSJoseph Koshy * Core/Core2 support. 7820cfab8ddSJoseph Koshy */ 7830cfab8ddSJoseph Koshy 7840cfab8ddSJoseph Koshy #define IAP_KW_AGENT "agent" 7850cfab8ddSJoseph Koshy #define IAP_KW_ANYTHREAD "anythread" 7860cfab8ddSJoseph Koshy #define IAP_KW_CACHESTATE "cachestate" 7870cfab8ddSJoseph Koshy #define IAP_KW_CMASK "cmask" 7880cfab8ddSJoseph Koshy #define IAP_KW_CORE "core" 7890cfab8ddSJoseph Koshy #define IAP_KW_EDGE "edge" 7900cfab8ddSJoseph Koshy #define IAP_KW_INV "inv" 7910cfab8ddSJoseph Koshy #define IAP_KW_OS "os" 7920cfab8ddSJoseph Koshy #define IAP_KW_PREFETCH "prefetch" 7930cfab8ddSJoseph Koshy #define IAP_KW_SNOOPRESPONSE "snoopresponse" 7940cfab8ddSJoseph Koshy #define IAP_KW_SNOOPTYPE "snooptype" 7950cfab8ddSJoseph Koshy #define IAP_KW_TRANSITION "trans" 7960cfab8ddSJoseph Koshy #define IAP_KW_USR "usr" 7971fa7f10bSFabien Thomas #define IAP_KW_RSP "rsp" 7980cfab8ddSJoseph Koshy 7990cfab8ddSJoseph Koshy static struct pmc_masks iap_core_mask[] = { 8000cfab8ddSJoseph Koshy PMCMASK(all, (0x3 << 14)), 8010cfab8ddSJoseph Koshy PMCMASK(this, (0x1 << 14)), 8020cfab8ddSJoseph Koshy NULLMASK 8030cfab8ddSJoseph Koshy }; 8040cfab8ddSJoseph Koshy 8050cfab8ddSJoseph Koshy static struct pmc_masks iap_agent_mask[] = { 8060cfab8ddSJoseph Koshy PMCMASK(this, 0), 8070cfab8ddSJoseph Koshy PMCMASK(any, (0x1 << 13)), 8080cfab8ddSJoseph Koshy NULLMASK 8090cfab8ddSJoseph Koshy }; 8100cfab8ddSJoseph Koshy 8110cfab8ddSJoseph Koshy static struct pmc_masks iap_prefetch_mask[] = { 8120cfab8ddSJoseph Koshy PMCMASK(both, (0x3 << 12)), 8130cfab8ddSJoseph Koshy PMCMASK(only, (0x1 << 12)), 8140cfab8ddSJoseph Koshy PMCMASK(exclude, 0), 8150cfab8ddSJoseph Koshy NULLMASK 8160cfab8ddSJoseph Koshy }; 8170cfab8ddSJoseph Koshy 8180cfab8ddSJoseph Koshy static struct pmc_masks iap_cachestate_mask[] = { 8190cfab8ddSJoseph Koshy PMCMASK(i, (1 << 8)), 8200cfab8ddSJoseph Koshy PMCMASK(s, (1 << 9)), 8210cfab8ddSJoseph Koshy PMCMASK(e, (1 << 10)), 8220cfab8ddSJoseph Koshy PMCMASK(m, (1 << 11)), 8230cfab8ddSJoseph Koshy NULLMASK 8240cfab8ddSJoseph Koshy }; 8250cfab8ddSJoseph Koshy 8260cfab8ddSJoseph Koshy static struct pmc_masks iap_snoopresponse_mask[] = { 8270cfab8ddSJoseph Koshy PMCMASK(clean, (1 << 8)), 8280cfab8ddSJoseph Koshy PMCMASK(hit, (1 << 9)), 8290cfab8ddSJoseph Koshy PMCMASK(hitm, (1 << 11)), 8300cfab8ddSJoseph Koshy NULLMASK 8310cfab8ddSJoseph Koshy }; 8320cfab8ddSJoseph Koshy 8330cfab8ddSJoseph Koshy static struct pmc_masks iap_snooptype_mask[] = { 8340cfab8ddSJoseph Koshy PMCMASK(cmp2s, (1 << 8)), 8350cfab8ddSJoseph Koshy PMCMASK(cmp2i, (1 << 9)), 8360cfab8ddSJoseph Koshy NULLMASK 8370cfab8ddSJoseph Koshy }; 8380cfab8ddSJoseph Koshy 8390cfab8ddSJoseph Koshy static struct pmc_masks iap_transition_mask[] = { 8400cfab8ddSJoseph Koshy PMCMASK(any, 0x00), 8410cfab8ddSJoseph Koshy PMCMASK(frequency, 0x10), 8420cfab8ddSJoseph Koshy NULLMASK 8430cfab8ddSJoseph Koshy }; 8440cfab8ddSJoseph Koshy 8451e862e5aSFabien Thomas static struct pmc_masks iap_rsp_mask_i7_wm[] = { 8461fa7f10bSFabien Thomas PMCMASK(DMND_DATA_RD, (1 << 0)), 8471fa7f10bSFabien Thomas PMCMASK(DMND_RFO, (1 << 1)), 8481fa7f10bSFabien Thomas PMCMASK(DMND_IFETCH, (1 << 2)), 8491fa7f10bSFabien Thomas PMCMASK(WB, (1 << 3)), 8501fa7f10bSFabien Thomas PMCMASK(PF_DATA_RD, (1 << 4)), 8511fa7f10bSFabien Thomas PMCMASK(PF_RFO, (1 << 5)), 8521fa7f10bSFabien Thomas PMCMASK(PF_IFETCH, (1 << 6)), 8531fa7f10bSFabien Thomas PMCMASK(OTHER, (1 << 7)), 8541fa7f10bSFabien Thomas PMCMASK(UNCORE_HIT, (1 << 8)), 8551fa7f10bSFabien Thomas PMCMASK(OTHER_CORE_HIT_SNP, (1 << 9)), 8561fa7f10bSFabien Thomas PMCMASK(OTHER_CORE_HITM, (1 << 10)), 8571fa7f10bSFabien Thomas PMCMASK(REMOTE_CACHE_FWD, (1 << 12)), 8581fa7f10bSFabien Thomas PMCMASK(REMOTE_DRAM, (1 << 13)), 8591fa7f10bSFabien Thomas PMCMASK(LOCAL_DRAM, (1 << 14)), 8601fa7f10bSFabien Thomas PMCMASK(NON_DRAM, (1 << 15)), 8611fa7f10bSFabien Thomas NULLMASK 8621fa7f10bSFabien Thomas }; 8631fa7f10bSFabien Thomas 864fabe02f5SSean Bruno static struct pmc_masks iap_rsp_mask_sb_sbx_ib[] = { 8651e862e5aSFabien Thomas PMCMASK(REQ_DMND_DATA_RD, (1ULL << 0)), 8661e862e5aSFabien Thomas PMCMASK(REQ_DMND_RFO, (1ULL << 1)), 8671e862e5aSFabien Thomas PMCMASK(REQ_DMND_IFETCH, (1ULL << 2)), 8681e862e5aSFabien Thomas PMCMASK(REQ_WB, (1ULL << 3)), 8691e862e5aSFabien Thomas PMCMASK(REQ_PF_DATA_RD, (1ULL << 4)), 8701e862e5aSFabien Thomas PMCMASK(REQ_PF_RFO, (1ULL << 5)), 8711e862e5aSFabien Thomas PMCMASK(REQ_PF_IFETCH, (1ULL << 6)), 8721e862e5aSFabien Thomas PMCMASK(REQ_PF_LLC_DATA_RD, (1ULL << 7)), 8731e862e5aSFabien Thomas PMCMASK(REQ_PF_LLC_RFO, (1ULL << 8)), 8741e862e5aSFabien Thomas PMCMASK(REQ_PF_LLC_IFETCH, (1ULL << 9)), 8751e862e5aSFabien Thomas PMCMASK(REQ_BUS_LOCKS, (1ULL << 10)), 8761e862e5aSFabien Thomas PMCMASK(REQ_STRM_ST, (1ULL << 11)), 8771e862e5aSFabien Thomas PMCMASK(REQ_OTHER, (1ULL << 15)), 8781e862e5aSFabien Thomas PMCMASK(RES_ANY, (1ULL << 16)), 8791e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_SUPP, (1ULL << 17)), 8801e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_LLC_HITM, (1ULL << 18)), 8811e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_LLC_HITE, (1ULL << 19)), 8821e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_LLC_HITS, (1ULL << 20)), 8831e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_LLC_HITF, (1ULL << 21)), 8841e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_LOCAL, (1ULL << 22)), 885cdfd0cc8SSean Bruno PMCMASK(RES_SNOOP_SNP_NONE, (1ULL << 31)), 8861e862e5aSFabien Thomas PMCMASK(RES_SNOOP_SNP_NO_NEEDED,(1ULL << 32)), 8871e862e5aSFabien Thomas PMCMASK(RES_SNOOP_SNP_MISS, (1ULL << 33)), 8881e862e5aSFabien Thomas PMCMASK(RES_SNOOP_HIT_NO_FWD, (1ULL << 34)), 8891e862e5aSFabien Thomas PMCMASK(RES_SNOOP_HIT_FWD, (1ULL << 35)), 8901e862e5aSFabien Thomas PMCMASK(RES_SNOOP_HITM, (1ULL << 36)), 8911e862e5aSFabien Thomas PMCMASK(RES_NON_DRAM, (1ULL << 37)), 8921e862e5aSFabien Thomas NULLMASK 8931e862e5aSFabien Thomas }; 8941e862e5aSFabien Thomas 895f19bae41SRandall Stewart /* Broadwell is defined to use the same mask as Haswell */ 896cc0c1555SSean Bruno static struct pmc_masks iap_rsp_mask_haswell[] = { 897cc0c1555SSean Bruno PMCMASK(REQ_DMND_DATA_RD, (1ULL << 0)), 898cc0c1555SSean Bruno PMCMASK(REQ_DMND_RFO, (1ULL << 1)), 899cc0c1555SSean Bruno PMCMASK(REQ_DMND_IFETCH, (1ULL << 2)), 900cc0c1555SSean Bruno PMCMASK(REQ_PF_DATA_RD, (1ULL << 4)), 901cc0c1555SSean Bruno PMCMASK(REQ_PF_RFO, (1ULL << 5)), 902cc0c1555SSean Bruno PMCMASK(REQ_PF_IFETCH, (1ULL << 6)), 903cc0c1555SSean Bruno PMCMASK(REQ_OTHER, (1ULL << 15)), 904cc0c1555SSean Bruno PMCMASK(RES_ANY, (1ULL << 16)), 905cc0c1555SSean Bruno PMCMASK(RES_SUPPLIER_SUPP, (1ULL << 17)), 906cc0c1555SSean Bruno PMCMASK(RES_SUPPLIER_LLC_HITM, (1ULL << 18)), 907cc0c1555SSean Bruno PMCMASK(RES_SUPPLIER_LLC_HITE, (1ULL << 19)), 908cc0c1555SSean Bruno PMCMASK(RES_SUPPLIER_LLC_HITS, (1ULL << 20)), 909cc0c1555SSean Bruno PMCMASK(RES_SUPPLIER_LLC_HITF, (1ULL << 21)), 910cc0c1555SSean Bruno PMCMASK(RES_SUPPLIER_LOCAL, (1ULL << 22)), 911f19bae41SRandall Stewart /* 912f19bae41SRandall Stewart * For processor type 06_45H 22 is L4_HIT_LOCAL_L4 913f19bae41SRandall Stewart * and 23, 24 and 25 are also defined. 914f19bae41SRandall Stewart */ 915cc0c1555SSean Bruno PMCMASK(RES_SNOOP_SNP_NONE, (1ULL << 31)), 916cc0c1555SSean Bruno PMCMASK(RES_SNOOP_SNP_NO_NEEDED,(1ULL << 32)), 917cc0c1555SSean Bruno PMCMASK(RES_SNOOP_SNP_MISS, (1ULL << 33)), 918cc0c1555SSean Bruno PMCMASK(RES_SNOOP_HIT_NO_FWD, (1ULL << 34)), 919cc0c1555SSean Bruno PMCMASK(RES_SNOOP_HIT_FWD, (1ULL << 35)), 920cc0c1555SSean Bruno PMCMASK(RES_SNOOP_HITM, (1ULL << 36)), 921cc0c1555SSean Bruno PMCMASK(RES_NON_DRAM, (1ULL << 37)), 922cc0c1555SSean Bruno NULLMASK 923cc0c1555SSean Bruno }; 924cc0c1555SSean Bruno 925f19bae41SRandall Stewart static struct pmc_masks iap_rsp_mask_skylake[] = { 926f19bae41SRandall Stewart PMCMASK(REQ_DMND_DATA_RD, (1ULL << 0)), 927f19bae41SRandall Stewart PMCMASK(REQ_DMND_RFO, (1ULL << 1)), 928f19bae41SRandall Stewart PMCMASK(REQ_DMND_IFETCH, (1ULL << 2)), 929f19bae41SRandall Stewart PMCMASK(REQ_PF_DATA_RD, (1ULL << 7)), 930f19bae41SRandall Stewart PMCMASK(REQ_PF_RFO, (1ULL << 8)), 931f19bae41SRandall Stewart PMCMASK(REQ_STRM_ST, (1ULL << 11)), 932f19bae41SRandall Stewart PMCMASK(REQ_OTHER, (1ULL << 15)), 933f19bae41SRandall Stewart PMCMASK(RES_ANY, (1ULL << 16)), 934f19bae41SRandall Stewart PMCMASK(RES_SUPPLIER_SUPP, (1ULL << 17)), 935f19bae41SRandall Stewart PMCMASK(RES_SUPPLIER_LLC_HITM, (1ULL << 18)), 936f19bae41SRandall Stewart PMCMASK(RES_SUPPLIER_LLC_HITE, (1ULL << 19)), 937f19bae41SRandall Stewart PMCMASK(RES_SUPPLIER_LLC_HITS, (1ULL << 20)), 938f19bae41SRandall Stewart PMCMASK(RES_SUPPLIER_L4_HIT, (1ULL << 22)), 939f19bae41SRandall Stewart PMCMASK(RES_SUPPLIER_DRAM, (1ULL << 26)), 940f19bae41SRandall Stewart PMCMASK(RES_SUPPLIER_SPL_HIT, (1ULL << 30)), 941f19bae41SRandall Stewart PMCMASK(RES_SNOOP_SNP_NONE, (1ULL << 31)), 942f19bae41SRandall Stewart PMCMASK(RES_SNOOP_SNP_NO_NEEDED,(1ULL << 32)), 943f19bae41SRandall Stewart PMCMASK(RES_SNOOP_SNP_MISS, (1ULL << 33)), 944f19bae41SRandall Stewart PMCMASK(RES_SNOOP_HIT_NO_FWD, (1ULL << 34)), 945f19bae41SRandall Stewart PMCMASK(RES_SNOOP_HIT_FWD, (1ULL << 35)), 946f19bae41SRandall Stewart PMCMASK(RES_SNOOP_HITM, (1ULL << 36)), 947f19bae41SRandall Stewart PMCMASK(RES_NON_DRAM, (1ULL << 37)), 948f19bae41SRandall Stewart NULLMASK 949f19bae41SRandall Stewart }; 950f19bae41SRandall Stewart 951f19bae41SRandall Stewart 9520cfab8ddSJoseph Koshy static int 9530cfab8ddSJoseph Koshy iap_allocate_pmc(enum pmc_event pe, char *ctrspec, 9540cfab8ddSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 9550cfab8ddSJoseph Koshy { 9560cfab8ddSJoseph Koshy char *e, *p, *q; 9571e862e5aSFabien Thomas uint64_t cachestate, evmask, rsp; 9580cfab8ddSJoseph Koshy int count, n; 9590cfab8ddSJoseph Koshy 9600cfab8ddSJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE | 9610cfab8ddSJoseph Koshy PMC_CAP_QUALIFIER); 9620cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config = 0; 9630cfab8ddSJoseph Koshy 9641fa7f10bSFabien Thomas cachestate = evmask = rsp = 0; 9650cfab8ddSJoseph Koshy 9660cfab8ddSJoseph Koshy /* Parse additional modifiers if present */ 9670cfab8ddSJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 9680cfab8ddSJoseph Koshy 9690cfab8ddSJoseph Koshy n = 0; 9700cfab8ddSJoseph Koshy if (KWPREFIXMATCH(p, IAP_KW_CMASK "=")) { 9710cfab8ddSJoseph Koshy q = strchr(p, '='); 9720cfab8ddSJoseph Koshy if (*++q == '\0') /* skip '=' */ 9730cfab8ddSJoseph Koshy return (-1); 9740cfab8ddSJoseph Koshy count = strtol(q, &e, 0); 9750cfab8ddSJoseph Koshy if (e == q || *e != '\0') 9760cfab8ddSJoseph Koshy return (-1); 9770cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 9780cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= 9790cfab8ddSJoseph Koshy IAP_CMASK(count); 9800cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_EDGE)) { 9810cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 9820cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_INV)) { 9830cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 9840cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_OS)) { 9850cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 9860cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_USR)) { 9870cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 9880cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_ANYTHREAD)) { 9890cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= IAP_ANY; 990b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_CORE "=")) { 9910cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_core_mask, p, &evmask); 9920cfab8ddSJoseph Koshy if (n != 1) 9930cfab8ddSJoseph Koshy return (-1); 994b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_AGENT "=")) { 9950cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_agent_mask, p, &evmask); 9960cfab8ddSJoseph Koshy if (n != 1) 9970cfab8ddSJoseph Koshy return (-1); 998b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_PREFETCH "=")) { 9990cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_prefetch_mask, p, &evmask); 10000cfab8ddSJoseph Koshy if (n != 1) 10010cfab8ddSJoseph Koshy return (-1); 1002b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_CACHESTATE "=")) { 10030cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_cachestate_mask, p, &cachestate); 10040cfab8ddSJoseph Koshy } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_CORE && 1005b47ea38eSJoseph Koshy KWPREFIXMATCH(p, IAP_KW_TRANSITION "=")) { 10060cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_transition_mask, p, &evmask); 10070cfab8ddSJoseph Koshy if (n != 1) 10080cfab8ddSJoseph Koshy return (-1); 10090cfab8ddSJoseph Koshy } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM || 1010e8f021a3SHiren Panchasara cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM_SILVERMONT || 1011b4d091f3SJoseph Koshy cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2 || 10121fa7f10bSFabien Thomas cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2EXTREME) { 1013b47ea38eSJoseph Koshy if (KWPREFIXMATCH(p, IAP_KW_SNOOPRESPONSE "=")) { 10140cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_snoopresponse_mask, p, 10150cfab8ddSJoseph Koshy &evmask); 1016b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_SNOOPTYPE "=")) { 10170cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_snooptype_mask, p, 10180cfab8ddSJoseph Koshy &evmask); 10190cfab8ddSJoseph Koshy } else 10200cfab8ddSJoseph Koshy return (-1); 10211fa7f10bSFabien Thomas } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_COREI7 || 102249fe48abSKonstantin Belousov cpu_info.pm_cputype == PMC_CPU_INTEL_WESTMERE || 102349fe48abSKonstantin Belousov cpu_info.pm_cputype == PMC_CPU_INTEL_NEHALEM_EX || 102449fe48abSKonstantin Belousov cpu_info.pm_cputype == PMC_CPU_INTEL_WESTMERE_EX) { 10251fa7f10bSFabien Thomas if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 10261e862e5aSFabien Thomas n = pmc_parse_mask(iap_rsp_mask_i7_wm, p, &rsp); 10271e862e5aSFabien Thomas } else 10281e862e5aSFabien Thomas return (-1); 10291e862e5aSFabien Thomas } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_SANDYBRIDGE || 1030fabe02f5SSean Bruno cpu_info.pm_cputype == PMC_CPU_INTEL_SANDYBRIDGE_XEON || 10313f929d8cSSean Bruno cpu_info.pm_cputype == PMC_CPU_INTEL_IVYBRIDGE || 10323f929d8cSSean Bruno cpu_info.pm_cputype == PMC_CPU_INTEL_IVYBRIDGE_XEON ) { 10331e862e5aSFabien Thomas if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 1034fabe02f5SSean Bruno n = pmc_parse_mask(iap_rsp_mask_sb_sbx_ib, p, &rsp); 10351fa7f10bSFabien Thomas } else 10361fa7f10bSFabien Thomas return (-1); 1037d95b3509SRandall Stewart } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_HASWELL || 1038d95b3509SRandall Stewart cpu_info.pm_cputype == PMC_CPU_INTEL_HASWELL_XEON) { 1039cc0c1555SSean Bruno if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 1040cc0c1555SSean Bruno n = pmc_parse_mask(iap_rsp_mask_haswell, p, &rsp); 1041cc0c1555SSean Bruno } else 1042cc0c1555SSean Bruno return (-1); 1043f19bae41SRandall Stewart } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_BROADWELL || 1044f19bae41SRandall Stewart cpu_info.pm_cputype == PMC_CPU_INTEL_BROADWELL_XEON) { 1045f19bae41SRandall Stewart /* Broadwell is defined to use same mask as haswell */ 1046f19bae41SRandall Stewart if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 1047f19bae41SRandall Stewart n = pmc_parse_mask(iap_rsp_mask_haswell, p, &rsp); 1048f19bae41SRandall Stewart } else 1049f19bae41SRandall Stewart return (-1); 1050f19bae41SRandall Stewart 1051b99b705dSKonstantin Belousov } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_SKYLAKE || 1052b99b705dSKonstantin Belousov cpu_info.pm_cputype == PMC_CPU_INTEL_SKYLAKE_XEON) { 1053f19bae41SRandall Stewart if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 1054f19bae41SRandall Stewart n = pmc_parse_mask(iap_rsp_mask_skylake, p, &rsp); 1055f19bae41SRandall Stewart } else 1056f19bae41SRandall Stewart return (-1); 1057f19bae41SRandall Stewart 10580cfab8ddSJoseph Koshy } else 10590cfab8ddSJoseph Koshy return (-1); 10600cfab8ddSJoseph Koshy 10610cfab8ddSJoseph Koshy if (n < 0) /* Parsing failed. */ 10620cfab8ddSJoseph Koshy return (-1); 10630cfab8ddSJoseph Koshy } 10640cfab8ddSJoseph Koshy 10650cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= evmask; 10660cfab8ddSJoseph Koshy 10670cfab8ddSJoseph Koshy /* 10680cfab8ddSJoseph Koshy * If the event requires a 'cachestate' qualifier but was not 10690cfab8ddSJoseph Koshy * specified by the user, use a sensible default. 10700cfab8ddSJoseph Koshy */ 10710cfab8ddSJoseph Koshy switch (pe) { 10720cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_28H: /* Core, Core2, Atom */ 10730cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_29H: /* Core, Core2, Atom */ 10740cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_2AH: /* Core, Core2, Atom */ 10750cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_2BH: /* Atom, Core2 */ 10760cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_2EH: /* Core, Core2, Atom */ 10770cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_30H: /* Core, Core2, Atom */ 10780cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_32H: /* Core */ 10790cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_40H: /* Core */ 10800cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_41H: /* Core */ 10810cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_42H: /* Core, Core2, Atom */ 10820cfab8ddSJoseph Koshy if (cachestate == 0) 10830cfab8ddSJoseph Koshy cachestate = (0xF << 8); 1084aa1b887bSRyan Stone break; 1085aa1b887bSRyan Stone case PMC_EV_IAP_EVENT_77H: /* Atom */ 1086aa1b887bSRyan Stone /* IAP_EVENT_77H only accepts a cachestate qualifier on the 1087aa1b887bSRyan Stone * Atom processor 1088aa1b887bSRyan Stone */ 1089aa1b887bSRyan Stone if(cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM && cachestate == 0) 1090aa1b887bSRyan Stone cachestate = (0xF << 8); 1091aa1b887bSRyan Stone break; 10920cfab8ddSJoseph Koshy default: 10930cfab8ddSJoseph Koshy break; 10940cfab8ddSJoseph Koshy } 10950cfab8ddSJoseph Koshy 10960cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= cachestate; 10971fa7f10bSFabien Thomas pmc_config->pm_md.pm_iap.pm_iap_rsp = rsp; 10981fa7f10bSFabien Thomas 10991fa7f10bSFabien Thomas return (0); 11001fa7f10bSFabien Thomas } 11011fa7f10bSFabien Thomas 11021fa7f10bSFabien Thomas /* 11031fa7f10bSFabien Thomas * Intel Uncore. 11041fa7f10bSFabien Thomas */ 11051fa7f10bSFabien Thomas 11061fa7f10bSFabien Thomas static int 11071fa7f10bSFabien Thomas ucf_allocate_pmc(enum pmc_event pe, char *ctrspec, 11081fa7f10bSFabien Thomas struct pmc_op_pmcallocate *pmc_config) 11091fa7f10bSFabien Thomas { 11101fa7f10bSFabien Thomas (void) pe; 11111fa7f10bSFabien Thomas (void) ctrspec; 11121fa7f10bSFabien Thomas 11131fa7f10bSFabien Thomas pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 11141fa7f10bSFabien Thomas pmc_config->pm_md.pm_ucf.pm_ucf_flags = 0; 11151fa7f10bSFabien Thomas 11161fa7f10bSFabien Thomas return (0); 11171fa7f10bSFabien Thomas } 11181fa7f10bSFabien Thomas 11191fa7f10bSFabien Thomas #define UCP_KW_CMASK "cmask" 11201fa7f10bSFabien Thomas #define UCP_KW_EDGE "edge" 11211fa7f10bSFabien Thomas #define UCP_KW_INV "inv" 11221fa7f10bSFabien Thomas 11231fa7f10bSFabien Thomas static int 11241fa7f10bSFabien Thomas ucp_allocate_pmc(enum pmc_event pe, char *ctrspec, 11251fa7f10bSFabien Thomas struct pmc_op_pmcallocate *pmc_config) 11261fa7f10bSFabien Thomas { 11271fa7f10bSFabien Thomas char *e, *p, *q; 11281fa7f10bSFabien Thomas int count, n; 11291fa7f10bSFabien Thomas 11301fa7f10bSFabien Thomas (void) pe; 11311fa7f10bSFabien Thomas 11321fa7f10bSFabien Thomas pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE | 11331fa7f10bSFabien Thomas PMC_CAP_QUALIFIER); 11341fa7f10bSFabien Thomas pmc_config->pm_md.pm_ucp.pm_ucp_config = 0; 11351fa7f10bSFabien Thomas 11361fa7f10bSFabien Thomas /* Parse additional modifiers if present */ 11371fa7f10bSFabien Thomas while ((p = strsep(&ctrspec, ",")) != NULL) { 11381fa7f10bSFabien Thomas 11391fa7f10bSFabien Thomas n = 0; 11401fa7f10bSFabien Thomas if (KWPREFIXMATCH(p, UCP_KW_CMASK "=")) { 11411fa7f10bSFabien Thomas q = strchr(p, '='); 11421fa7f10bSFabien Thomas if (*++q == '\0') /* skip '=' */ 11431fa7f10bSFabien Thomas return (-1); 11441fa7f10bSFabien Thomas count = strtol(q, &e, 0); 11451fa7f10bSFabien Thomas if (e == q || *e != '\0') 11461fa7f10bSFabien Thomas return (-1); 11471fa7f10bSFabien Thomas pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 11481fa7f10bSFabien Thomas pmc_config->pm_md.pm_ucp.pm_ucp_config |= 11491fa7f10bSFabien Thomas UCP_CMASK(count); 11501fa7f10bSFabien Thomas } else if (KWMATCH(p, UCP_KW_EDGE)) { 11511fa7f10bSFabien Thomas pmc_config->pm_caps |= PMC_CAP_EDGE; 11521fa7f10bSFabien Thomas } else if (KWMATCH(p, UCP_KW_INV)) { 11531fa7f10bSFabien Thomas pmc_config->pm_caps |= PMC_CAP_INVERT; 11541fa7f10bSFabien Thomas } else 11551fa7f10bSFabien Thomas return (-1); 11561fa7f10bSFabien Thomas 11571fa7f10bSFabien Thomas if (n < 0) /* Parsing failed. */ 11581fa7f10bSFabien Thomas return (-1); 11591fa7f10bSFabien Thomas } 11600cfab8ddSJoseph Koshy 11610cfab8ddSJoseph Koshy return (0); 11620cfab8ddSJoseph Koshy } 11630cfab8ddSJoseph Koshy 11640cfab8ddSJoseph Koshy /* 1165f263522aSJoseph Koshy * AMD K8 PMCs. 1166f263522aSJoseph Koshy * 1167f263522aSJoseph Koshy * These are very similar to AMD K7 PMCs, but support more kinds of 1168f263522aSJoseph Koshy * events. 1169f263522aSJoseph Koshy */ 1170f263522aSJoseph Koshy 1171f263522aSJoseph Koshy static struct pmc_event_alias k8_aliases[] = { 1172f263522aSJoseph Koshy EV_ALIAS("branches", "k8-fr-retired-taken-branches"), 1173f263522aSJoseph Koshy EV_ALIAS("branch-mispredicts", 1174f263522aSJoseph Koshy "k8-fr-retired-taken-branches-mispredicted"), 1175f263522aSJoseph Koshy EV_ALIAS("cycles", "tsc"), 1176f263522aSJoseph Koshy EV_ALIAS("dc-misses", "k8-dc-miss"), 1177f263522aSJoseph Koshy EV_ALIAS("ic-misses", "k8-ic-miss"), 1178f263522aSJoseph Koshy EV_ALIAS("instructions", "k8-fr-retired-x86-instructions"), 1179f263522aSJoseph Koshy EV_ALIAS("interrupts", "k8-fr-taken-hardware-interrupts"), 1180177a2f22SJoseph Koshy EV_ALIAS("unhalted-cycles", "k8-bu-cpu-clk-unhalted"), 1181f263522aSJoseph Koshy EV_ALIAS(NULL, NULL) 1182f263522aSJoseph Koshy }; 1183f263522aSJoseph Koshy 1184f263522aSJoseph Koshy #define __K8MASK(N,V) PMCMASK(N,(1 << (V))) 1185f263522aSJoseph Koshy 1186f263522aSJoseph Koshy /* 1187f263522aSJoseph Koshy * Parsing tables 1188f263522aSJoseph Koshy */ 1189f263522aSJoseph Koshy 1190f263522aSJoseph Koshy /* fp dispatched fpu ops */ 1191f263522aSJoseph Koshy static const struct pmc_masks k8_mask_fdfo[] = { 1192f263522aSJoseph Koshy __K8MASK(add-pipe-excluding-junk-ops, 0), 1193f263522aSJoseph Koshy __K8MASK(multiply-pipe-excluding-junk-ops, 1), 1194f263522aSJoseph Koshy __K8MASK(store-pipe-excluding-junk-ops, 2), 1195f263522aSJoseph Koshy __K8MASK(add-pipe-junk-ops, 3), 1196f263522aSJoseph Koshy __K8MASK(multiply-pipe-junk-ops, 4), 1197f263522aSJoseph Koshy __K8MASK(store-pipe-junk-ops, 5), 1198f263522aSJoseph Koshy NULLMASK 1199f263522aSJoseph Koshy }; 1200f263522aSJoseph Koshy 1201f263522aSJoseph Koshy /* ls segment register loads */ 1202f263522aSJoseph Koshy static const struct pmc_masks k8_mask_lsrl[] = { 1203f263522aSJoseph Koshy __K8MASK(es, 0), 1204f263522aSJoseph Koshy __K8MASK(cs, 1), 1205f263522aSJoseph Koshy __K8MASK(ss, 2), 1206f263522aSJoseph Koshy __K8MASK(ds, 3), 1207f263522aSJoseph Koshy __K8MASK(fs, 4), 1208f263522aSJoseph Koshy __K8MASK(gs, 5), 1209f263522aSJoseph Koshy __K8MASK(hs, 6), 1210f263522aSJoseph Koshy NULLMASK 1211f263522aSJoseph Koshy }; 1212f263522aSJoseph Koshy 1213f263522aSJoseph Koshy /* ls locked operation */ 1214f263522aSJoseph Koshy static const struct pmc_masks k8_mask_llo[] = { 1215f263522aSJoseph Koshy __K8MASK(locked-instructions, 0), 1216f263522aSJoseph Koshy __K8MASK(cycles-in-request, 1), 1217f263522aSJoseph Koshy __K8MASK(cycles-to-complete, 2), 1218f263522aSJoseph Koshy NULLMASK 1219f263522aSJoseph Koshy }; 1220f263522aSJoseph Koshy 1221f263522aSJoseph Koshy /* dc refill from {l2,system} and dc copyback */ 1222f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dc[] = { 1223f263522aSJoseph Koshy __K8MASK(invalid, 0), 1224f263522aSJoseph Koshy __K8MASK(shared, 1), 1225f263522aSJoseph Koshy __K8MASK(exclusive, 2), 1226f263522aSJoseph Koshy __K8MASK(owner, 3), 1227f263522aSJoseph Koshy __K8MASK(modified, 4), 1228f263522aSJoseph Koshy NULLMASK 1229f263522aSJoseph Koshy }; 1230f263522aSJoseph Koshy 1231f263522aSJoseph Koshy /* dc one bit ecc error */ 1232f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dobee[] = { 1233f263522aSJoseph Koshy __K8MASK(scrubber, 0), 1234f263522aSJoseph Koshy __K8MASK(piggyback, 1), 1235f263522aSJoseph Koshy NULLMASK 1236f263522aSJoseph Koshy }; 1237f263522aSJoseph Koshy 1238f263522aSJoseph Koshy /* dc dispatched prefetch instructions */ 1239f263522aSJoseph Koshy static const struct pmc_masks k8_mask_ddpi[] = { 1240f263522aSJoseph Koshy __K8MASK(load, 0), 1241f263522aSJoseph Koshy __K8MASK(store, 1), 1242f263522aSJoseph Koshy __K8MASK(nta, 2), 1243f263522aSJoseph Koshy NULLMASK 1244f263522aSJoseph Koshy }; 1245f263522aSJoseph Koshy 1246f263522aSJoseph Koshy /* dc dcache accesses by locks */ 1247f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dabl[] = { 1248f263522aSJoseph Koshy __K8MASK(accesses, 0), 1249f263522aSJoseph Koshy __K8MASK(misses, 1), 1250f263522aSJoseph Koshy NULLMASK 1251f263522aSJoseph Koshy }; 1252f263522aSJoseph Koshy 1253f263522aSJoseph Koshy /* bu internal l2 request */ 1254f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bilr[] = { 1255f263522aSJoseph Koshy __K8MASK(ic-fill, 0), 1256f263522aSJoseph Koshy __K8MASK(dc-fill, 1), 1257f263522aSJoseph Koshy __K8MASK(tlb-reload, 2), 1258f263522aSJoseph Koshy __K8MASK(tag-snoop, 3), 1259f263522aSJoseph Koshy __K8MASK(cancelled, 4), 1260f263522aSJoseph Koshy NULLMASK 1261f263522aSJoseph Koshy }; 1262f263522aSJoseph Koshy 1263f263522aSJoseph Koshy /* bu fill request l2 miss */ 1264f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bfrlm[] = { 1265f263522aSJoseph Koshy __K8MASK(ic-fill, 0), 1266f263522aSJoseph Koshy __K8MASK(dc-fill, 1), 1267f263522aSJoseph Koshy __K8MASK(tlb-reload, 2), 1268f263522aSJoseph Koshy NULLMASK 1269f263522aSJoseph Koshy }; 1270f263522aSJoseph Koshy 1271f263522aSJoseph Koshy /* bu fill into l2 */ 1272f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bfil[] = { 1273f263522aSJoseph Koshy __K8MASK(dirty-l2-victim, 0), 1274f263522aSJoseph Koshy __K8MASK(victim-from-l2, 1), 1275f263522aSJoseph Koshy NULLMASK 1276f263522aSJoseph Koshy }; 1277f263522aSJoseph Koshy 1278f263522aSJoseph Koshy /* fr retired fpu instructions */ 1279f263522aSJoseph Koshy static const struct pmc_masks k8_mask_frfi[] = { 1280f263522aSJoseph Koshy __K8MASK(x87, 0), 1281f263522aSJoseph Koshy __K8MASK(mmx-3dnow, 1), 1282f263522aSJoseph Koshy __K8MASK(packed-sse-sse2, 2), 1283f263522aSJoseph Koshy __K8MASK(scalar-sse-sse2, 3), 1284f263522aSJoseph Koshy NULLMASK 1285f263522aSJoseph Koshy }; 1286f263522aSJoseph Koshy 1287f263522aSJoseph Koshy /* fr retired fastpath double op instructions */ 1288f263522aSJoseph Koshy static const struct pmc_masks k8_mask_frfdoi[] = { 1289f263522aSJoseph Koshy __K8MASK(low-op-pos-0, 0), 1290f263522aSJoseph Koshy __K8MASK(low-op-pos-1, 1), 1291f263522aSJoseph Koshy __K8MASK(low-op-pos-2, 2), 1292f263522aSJoseph Koshy NULLMASK 1293f263522aSJoseph Koshy }; 1294f263522aSJoseph Koshy 1295f263522aSJoseph Koshy /* fr fpu exceptions */ 1296f263522aSJoseph Koshy static const struct pmc_masks k8_mask_ffe[] = { 1297f263522aSJoseph Koshy __K8MASK(x87-reclass-microfaults, 0), 1298f263522aSJoseph Koshy __K8MASK(sse-retype-microfaults, 1), 1299f263522aSJoseph Koshy __K8MASK(sse-reclass-microfaults, 2), 1300f263522aSJoseph Koshy __K8MASK(sse-and-x87-microtraps, 3), 1301f263522aSJoseph Koshy NULLMASK 1302f263522aSJoseph Koshy }; 1303f263522aSJoseph Koshy 1304f263522aSJoseph Koshy /* nb memory controller page access event */ 1305f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmcpae[] = { 1306f263522aSJoseph Koshy __K8MASK(page-hit, 0), 1307f263522aSJoseph Koshy __K8MASK(page-miss, 1), 1308f263522aSJoseph Koshy __K8MASK(page-conflict, 2), 1309f263522aSJoseph Koshy NULLMASK 1310f263522aSJoseph Koshy }; 1311f263522aSJoseph Koshy 1312f263522aSJoseph Koshy /* nb memory controller turnaround */ 1313f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmct[] = { 1314f263522aSJoseph Koshy __K8MASK(dimm-turnaround, 0), 1315f263522aSJoseph Koshy __K8MASK(read-to-write-turnaround, 1), 1316f263522aSJoseph Koshy __K8MASK(write-to-read-turnaround, 2), 1317f263522aSJoseph Koshy NULLMASK 1318f263522aSJoseph Koshy }; 1319f263522aSJoseph Koshy 1320f263522aSJoseph Koshy /* nb memory controller bypass saturation */ 1321f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmcbs[] = { 1322f263522aSJoseph Koshy __K8MASK(memory-controller-hi-pri-bypass, 0), 1323f263522aSJoseph Koshy __K8MASK(memory-controller-lo-pri-bypass, 1), 1324f263522aSJoseph Koshy __K8MASK(dram-controller-interface-bypass, 2), 1325f263522aSJoseph Koshy __K8MASK(dram-controller-queue-bypass, 3), 1326f263522aSJoseph Koshy NULLMASK 1327f263522aSJoseph Koshy }; 1328f263522aSJoseph Koshy 1329f263522aSJoseph Koshy /* nb sized commands */ 1330f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nsc[] = { 1331f263522aSJoseph Koshy __K8MASK(nonpostwrszbyte, 0), 1332f263522aSJoseph Koshy __K8MASK(nonpostwrszdword, 1), 1333f263522aSJoseph Koshy __K8MASK(postwrszbyte, 2), 1334f263522aSJoseph Koshy __K8MASK(postwrszdword, 3), 1335f263522aSJoseph Koshy __K8MASK(rdszbyte, 4), 1336f263522aSJoseph Koshy __K8MASK(rdszdword, 5), 1337f263522aSJoseph Koshy __K8MASK(rdmodwr, 6), 1338f263522aSJoseph Koshy NULLMASK 1339f263522aSJoseph Koshy }; 1340f263522aSJoseph Koshy 1341f263522aSJoseph Koshy /* nb probe result */ 1342f263522aSJoseph Koshy static const struct pmc_masks k8_mask_npr[] = { 1343f263522aSJoseph Koshy __K8MASK(probe-miss, 0), 1344f263522aSJoseph Koshy __K8MASK(probe-hit, 1), 1345f263522aSJoseph Koshy __K8MASK(probe-hit-dirty-no-memory-cancel, 2), 1346f263522aSJoseph Koshy __K8MASK(probe-hit-dirty-with-memory-cancel, 3), 1347f263522aSJoseph Koshy NULLMASK 1348f263522aSJoseph Koshy }; 1349f263522aSJoseph Koshy 1350f263522aSJoseph Koshy /* nb hypertransport bus bandwidth */ 1351f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nhbb[] = { /* HT bus bandwidth */ 1352f263522aSJoseph Koshy __K8MASK(command, 0), 1353f263522aSJoseph Koshy __K8MASK(data, 1), 1354f263522aSJoseph Koshy __K8MASK(buffer-release, 2), 1355f263522aSJoseph Koshy __K8MASK(nop, 3), 1356f263522aSJoseph Koshy NULLMASK 1357f263522aSJoseph Koshy }; 1358f263522aSJoseph Koshy 1359f263522aSJoseph Koshy #undef __K8MASK 1360f263522aSJoseph Koshy 1361f263522aSJoseph Koshy #define K8_KW_COUNT "count" 1362f263522aSJoseph Koshy #define K8_KW_EDGE "edge" 1363f263522aSJoseph Koshy #define K8_KW_INV "inv" 1364f263522aSJoseph Koshy #define K8_KW_MASK "mask" 1365f263522aSJoseph Koshy #define K8_KW_OS "os" 1366f263522aSJoseph Koshy #define K8_KW_USR "usr" 1367f263522aSJoseph Koshy 1368f263522aSJoseph Koshy static int 1369f263522aSJoseph Koshy k8_allocate_pmc(enum pmc_event pe, char *ctrspec, 1370f263522aSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 1371f263522aSJoseph Koshy { 1372f263522aSJoseph Koshy char *e, *p, *q; 1373f263522aSJoseph Koshy int n; 13741e862e5aSFabien Thomas uint32_t count; 13751e862e5aSFabien Thomas uint64_t evmask; 1376f263522aSJoseph Koshy const struct pmc_masks *pm, *pmask; 1377f263522aSJoseph Koshy 1378789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1379f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 1380f263522aSJoseph Koshy 1381f263522aSJoseph Koshy pmask = NULL; 1382f263522aSJoseph Koshy evmask = 0; 1383f263522aSJoseph Koshy 1384f263522aSJoseph Koshy #define __K8SETMASK(M) pmask = k8_mask_##M 1385f263522aSJoseph Koshy 1386f263522aSJoseph Koshy /* setup parsing tables */ 1387f263522aSJoseph Koshy switch (pe) { 1388f263522aSJoseph Koshy case PMC_EV_K8_FP_DISPATCHED_FPU_OPS: 1389f263522aSJoseph Koshy __K8SETMASK(fdfo); 1390f263522aSJoseph Koshy break; 1391f263522aSJoseph Koshy case PMC_EV_K8_LS_SEGMENT_REGISTER_LOAD: 1392f263522aSJoseph Koshy __K8SETMASK(lsrl); 1393f263522aSJoseph Koshy break; 1394f263522aSJoseph Koshy case PMC_EV_K8_LS_LOCKED_OPERATION: 1395f263522aSJoseph Koshy __K8SETMASK(llo); 1396f263522aSJoseph Koshy break; 1397f263522aSJoseph Koshy case PMC_EV_K8_DC_REFILL_FROM_L2: 1398f263522aSJoseph Koshy case PMC_EV_K8_DC_REFILL_FROM_SYSTEM: 1399f263522aSJoseph Koshy case PMC_EV_K8_DC_COPYBACK: 1400f263522aSJoseph Koshy __K8SETMASK(dc); 1401f263522aSJoseph Koshy break; 1402f263522aSJoseph Koshy case PMC_EV_K8_DC_ONE_BIT_ECC_ERROR: 1403f263522aSJoseph Koshy __K8SETMASK(dobee); 1404f263522aSJoseph Koshy break; 1405f263522aSJoseph Koshy case PMC_EV_K8_DC_DISPATCHED_PREFETCH_INSTRUCTIONS: 1406f263522aSJoseph Koshy __K8SETMASK(ddpi); 1407f263522aSJoseph Koshy break; 1408f263522aSJoseph Koshy case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS: 1409f263522aSJoseph Koshy __K8SETMASK(dabl); 1410f263522aSJoseph Koshy break; 1411f263522aSJoseph Koshy case PMC_EV_K8_BU_INTERNAL_L2_REQUEST: 1412f263522aSJoseph Koshy __K8SETMASK(bilr); 1413f263522aSJoseph Koshy break; 1414f263522aSJoseph Koshy case PMC_EV_K8_BU_FILL_REQUEST_L2_MISS: 1415f263522aSJoseph Koshy __K8SETMASK(bfrlm); 1416f263522aSJoseph Koshy break; 1417f263522aSJoseph Koshy case PMC_EV_K8_BU_FILL_INTO_L2: 1418f263522aSJoseph Koshy __K8SETMASK(bfil); 1419f263522aSJoseph Koshy break; 1420f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS: 1421f263522aSJoseph Koshy __K8SETMASK(frfi); 1422f263522aSJoseph Koshy break; 1423f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS: 1424f263522aSJoseph Koshy __K8SETMASK(frfdoi); 1425f263522aSJoseph Koshy break; 1426f263522aSJoseph Koshy case PMC_EV_K8_FR_FPU_EXCEPTIONS: 1427f263522aSJoseph Koshy __K8SETMASK(ffe); 1428f263522aSJoseph Koshy break; 1429f263522aSJoseph Koshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_PAGE_ACCESS_EVENT: 1430f263522aSJoseph Koshy __K8SETMASK(nmcpae); 1431f263522aSJoseph Koshy break; 1432f263522aSJoseph Koshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_TURNAROUND: 1433f263522aSJoseph Koshy __K8SETMASK(nmct); 1434f263522aSJoseph Koshy break; 1435f263522aSJoseph Koshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_BYPASS_SATURATION: 1436f263522aSJoseph Koshy __K8SETMASK(nmcbs); 1437f263522aSJoseph Koshy break; 1438f263522aSJoseph Koshy case PMC_EV_K8_NB_SIZED_COMMANDS: 1439f263522aSJoseph Koshy __K8SETMASK(nsc); 1440f263522aSJoseph Koshy break; 1441f263522aSJoseph Koshy case PMC_EV_K8_NB_PROBE_RESULT: 1442f263522aSJoseph Koshy __K8SETMASK(npr); 1443f263522aSJoseph Koshy break; 1444f263522aSJoseph Koshy case PMC_EV_K8_NB_HT_BUS0_BANDWIDTH: 1445f263522aSJoseph Koshy case PMC_EV_K8_NB_HT_BUS1_BANDWIDTH: 1446f263522aSJoseph Koshy case PMC_EV_K8_NB_HT_BUS2_BANDWIDTH: 1447f263522aSJoseph Koshy __K8SETMASK(nhbb); 1448f263522aSJoseph Koshy break; 1449f263522aSJoseph Koshy 1450f263522aSJoseph Koshy default: 1451f263522aSJoseph Koshy break; /* no options defined */ 1452f263522aSJoseph Koshy } 1453f263522aSJoseph Koshy 1454f263522aSJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 1455f263522aSJoseph Koshy if (KWPREFIXMATCH(p, K8_KW_COUNT "=")) { 1456f263522aSJoseph Koshy q = strchr(p, '='); 1457f263522aSJoseph Koshy if (*++q == '\0') /* skip '=' */ 1458aa342b1fSJoseph Koshy return (-1); 1459f263522aSJoseph Koshy 1460f263522aSJoseph Koshy count = strtol(q, &e, 0); 1461f263522aSJoseph Koshy if (e == q || *e != '\0') 1462aa342b1fSJoseph Koshy return (-1); 1463f263522aSJoseph Koshy 1464f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 1465f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config |= 1466f263522aSJoseph Koshy AMD_PMC_TO_COUNTER(count); 1467f263522aSJoseph Koshy 1468f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_EDGE)) { 1469f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1470f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_INV)) { 1471f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 1472f263522aSJoseph Koshy } else if (KWPREFIXMATCH(p, K8_KW_MASK "=")) { 1473f263522aSJoseph Koshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 1474aa342b1fSJoseph Koshy return (-1); 1475f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1476f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_OS)) { 1477f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 1478f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_USR)) { 1479f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 1480f263522aSJoseph Koshy } else 1481aa342b1fSJoseph Koshy return (-1); 1482f263522aSJoseph Koshy } 1483f263522aSJoseph Koshy 1484f263522aSJoseph Koshy /* other post processing */ 1485f263522aSJoseph Koshy switch (pe) { 1486f263522aSJoseph Koshy case PMC_EV_K8_FP_DISPATCHED_FPU_OPS: 1487f263522aSJoseph Koshy case PMC_EV_K8_FP_CYCLES_WITH_NO_FPU_OPS_RETIRED: 1488f263522aSJoseph Koshy case PMC_EV_K8_FP_DISPATCHED_FPU_FAST_FLAG_OPS: 1489f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS: 1490f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS: 1491f263522aSJoseph Koshy case PMC_EV_K8_FR_FPU_EXCEPTIONS: 1492f263522aSJoseph Koshy /* XXX only available in rev B and later */ 1493f263522aSJoseph Koshy break; 1494f263522aSJoseph Koshy case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS: 1495f263522aSJoseph Koshy /* XXX only available in rev C and later */ 1496f263522aSJoseph Koshy break; 1497f263522aSJoseph Koshy case PMC_EV_K8_LS_LOCKED_OPERATION: 1498f263522aSJoseph Koshy /* XXX CPU Rev A,B evmask is to be zero */ 1499f263522aSJoseph Koshy if (evmask & (evmask - 1)) /* > 1 bit set */ 1500aa342b1fSJoseph Koshy return (-1); 1501f263522aSJoseph Koshy if (evmask == 0) { 1502f263522aSJoseph Koshy evmask = 0x01; /* Rev C and later: #instrs */ 1503f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1504f263522aSJoseph Koshy } 1505f263522aSJoseph Koshy break; 1506f263522aSJoseph Koshy default: 1507f263522aSJoseph Koshy if (evmask == 0 && pmask != NULL) { 1508f263522aSJoseph Koshy for (pm = pmask; pm->pm_name; pm++) 1509f263522aSJoseph Koshy evmask |= pm->pm_value; 1510f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1511f263522aSJoseph Koshy } 1512f263522aSJoseph Koshy } 1513f263522aSJoseph Koshy 1514f263522aSJoseph Koshy if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) 1515f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 1516f263522aSJoseph Koshy AMD_PMC_TO_UNITMASK(evmask); 1517f263522aSJoseph Koshy 1518aa342b1fSJoseph Koshy return (0); 1519f263522aSJoseph Koshy } 1520f263522aSJoseph Koshy 1521f263522aSJoseph Koshy #endif 1522f263522aSJoseph Koshy 152386a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 1524f263522aSJoseph Koshy 1525ebccf1e3SJoseph Koshy /* 1526ebccf1e3SJoseph Koshy * Intel P4 PMCs 1527ebccf1e3SJoseph Koshy */ 1528ebccf1e3SJoseph Koshy 1529ebccf1e3SJoseph Koshy static struct pmc_event_alias p4_aliases[] = { 1530d56c5d4bSJoseph Koshy EV_ALIAS("branches", "p4-branch-retired,mask=mmtp+mmtm"), 1531d56c5d4bSJoseph Koshy EV_ALIAS("branch-mispredicts", "p4-mispred-branch-retired"), 1532ebccf1e3SJoseph Koshy EV_ALIAS("cycles", "tsc"), 1533d56c5d4bSJoseph Koshy EV_ALIAS("instructions", 1534d56c5d4bSJoseph Koshy "p4-instr-retired,mask=nbogusntag+nbogustag"), 1535177a2f22SJoseph Koshy EV_ALIAS("unhalted-cycles", "p4-global-power-events"), 1536ebccf1e3SJoseph Koshy EV_ALIAS(NULL, NULL) 1537ebccf1e3SJoseph Koshy }; 1538ebccf1e3SJoseph Koshy 1539ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE "active" 1540ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_ANY "any" 1541ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_BOTH "both" 1542ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_NONE "none" 1543ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_SINGLE "single" 1544ebccf1e3SJoseph Koshy #define P4_KW_BUSREQTYPE "busreqtype" 1545ebccf1e3SJoseph Koshy #define P4_KW_CASCADE "cascade" 1546ebccf1e3SJoseph Koshy #define P4_KW_EDGE "edge" 1547ebccf1e3SJoseph Koshy #define P4_KW_INV "complement" 1548ebccf1e3SJoseph Koshy #define P4_KW_OS "os" 1549ebccf1e3SJoseph Koshy #define P4_KW_MASK "mask" 1550ebccf1e3SJoseph Koshy #define P4_KW_PRECISE "precise" 1551ebccf1e3SJoseph Koshy #define P4_KW_TAG "tag" 1552ebccf1e3SJoseph Koshy #define P4_KW_THRESHOLD "threshold" 1553ebccf1e3SJoseph Koshy #define P4_KW_USR "usr" 1554ebccf1e3SJoseph Koshy 1555ebccf1e3SJoseph Koshy #define __P4MASK(N,V) PMCMASK(N, (1 << (V))) 1556ebccf1e3SJoseph Koshy 1557ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_tcdm[] = { /* tc deliver mode */ 1558ebccf1e3SJoseph Koshy __P4MASK(dd, 0), 1559ebccf1e3SJoseph Koshy __P4MASK(db, 1), 1560ebccf1e3SJoseph Koshy __P4MASK(di, 2), 1561ebccf1e3SJoseph Koshy __P4MASK(bd, 3), 1562ebccf1e3SJoseph Koshy __P4MASK(bb, 4), 1563ebccf1e3SJoseph Koshy __P4MASK(bi, 5), 1564ebccf1e3SJoseph Koshy __P4MASK(id, 6), 1565ebccf1e3SJoseph Koshy __P4MASK(ib, 7), 1566ebccf1e3SJoseph Koshy NULLMASK 1567ebccf1e3SJoseph Koshy }; 1568ebccf1e3SJoseph Koshy 1569ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_bfr[] = { /* bpu fetch request */ 1570ebccf1e3SJoseph Koshy __P4MASK(tcmiss, 0), 1571ebccf1e3SJoseph Koshy NULLMASK, 1572ebccf1e3SJoseph Koshy }; 1573ebccf1e3SJoseph Koshy 1574ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ir[] = { /* itlb reference */ 1575ebccf1e3SJoseph Koshy __P4MASK(hit, 0), 1576ebccf1e3SJoseph Koshy __P4MASK(miss, 1), 1577ebccf1e3SJoseph Koshy __P4MASK(hit-uc, 2), 1578ebccf1e3SJoseph Koshy NULLMASK 1579ebccf1e3SJoseph Koshy }; 1580ebccf1e3SJoseph Koshy 1581ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_memcan[] = { /* memory cancel */ 1582ebccf1e3SJoseph Koshy __P4MASK(st-rb-full, 2), 1583ebccf1e3SJoseph Koshy __P4MASK(64k-conf, 3), 1584ebccf1e3SJoseph Koshy NULLMASK 1585ebccf1e3SJoseph Koshy }; 1586ebccf1e3SJoseph Koshy 1587ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_memcomp[] = { /* memory complete */ 1588ebccf1e3SJoseph Koshy __P4MASK(lsc, 0), 1589ebccf1e3SJoseph Koshy __P4MASK(ssc, 1), 1590ebccf1e3SJoseph Koshy NULLMASK 1591ebccf1e3SJoseph Koshy }; 1592ebccf1e3SJoseph Koshy 1593ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_lpr[] = { /* load port replay */ 1594ebccf1e3SJoseph Koshy __P4MASK(split-ld, 1), 1595ebccf1e3SJoseph Koshy NULLMASK 1596ebccf1e3SJoseph Koshy }; 1597ebccf1e3SJoseph Koshy 1598ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_spr[] = { /* store port replay */ 1599ebccf1e3SJoseph Koshy __P4MASK(split-st, 1), 1600ebccf1e3SJoseph Koshy NULLMASK 1601ebccf1e3SJoseph Koshy }; 1602ebccf1e3SJoseph Koshy 1603ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_mlr[] = { /* mob load replay */ 1604ebccf1e3SJoseph Koshy __P4MASK(no-sta, 1), 1605ebccf1e3SJoseph Koshy __P4MASK(no-std, 3), 1606ebccf1e3SJoseph Koshy __P4MASK(partial-data, 4), 1607ebccf1e3SJoseph Koshy __P4MASK(unalgn-addr, 5), 1608ebccf1e3SJoseph Koshy NULLMASK 1609ebccf1e3SJoseph Koshy }; 1610ebccf1e3SJoseph Koshy 1611ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_pwt[] = { /* page walk type */ 1612ebccf1e3SJoseph Koshy __P4MASK(dtmiss, 0), 1613ebccf1e3SJoseph Koshy __P4MASK(itmiss, 1), 1614ebccf1e3SJoseph Koshy NULLMASK 1615ebccf1e3SJoseph Koshy }; 1616ebccf1e3SJoseph Koshy 1617ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_bcr[] = { /* bsq cache reference */ 1618ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-hits, 0), 1619ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-hite, 1), 1620ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-hitm, 2), 1621ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-hits, 3), 1622ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-hite, 4), 1623ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-hitm, 5), 1624ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-miss, 8), 1625ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-miss, 9), 1626ebccf1e3SJoseph Koshy __P4MASK(wr-2ndl-miss, 10), 1627ebccf1e3SJoseph Koshy NULLMASK 1628ebccf1e3SJoseph Koshy }; 1629ebccf1e3SJoseph Koshy 1630ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ia[] = { /* ioq allocation */ 1631ebccf1e3SJoseph Koshy __P4MASK(all-read, 5), 1632ebccf1e3SJoseph Koshy __P4MASK(all-write, 6), 1633ebccf1e3SJoseph Koshy __P4MASK(mem-uc, 7), 1634ebccf1e3SJoseph Koshy __P4MASK(mem-wc, 8), 1635ebccf1e3SJoseph Koshy __P4MASK(mem-wt, 9), 1636ebccf1e3SJoseph Koshy __P4MASK(mem-wp, 10), 1637ebccf1e3SJoseph Koshy __P4MASK(mem-wb, 11), 1638ebccf1e3SJoseph Koshy __P4MASK(own, 13), 1639ebccf1e3SJoseph Koshy __P4MASK(other, 14), 1640ebccf1e3SJoseph Koshy __P4MASK(prefetch, 15), 1641ebccf1e3SJoseph Koshy NULLMASK 1642ebccf1e3SJoseph Koshy }; 1643ebccf1e3SJoseph Koshy 1644ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_iae[] = { /* ioq active entries */ 1645ebccf1e3SJoseph Koshy __P4MASK(all-read, 5), 1646ebccf1e3SJoseph Koshy __P4MASK(all-write, 6), 1647ebccf1e3SJoseph Koshy __P4MASK(mem-uc, 7), 1648ebccf1e3SJoseph Koshy __P4MASK(mem-wc, 8), 1649ebccf1e3SJoseph Koshy __P4MASK(mem-wt, 9), 1650ebccf1e3SJoseph Koshy __P4MASK(mem-wp, 10), 1651ebccf1e3SJoseph Koshy __P4MASK(mem-wb, 11), 1652ebccf1e3SJoseph Koshy __P4MASK(own, 13), 1653ebccf1e3SJoseph Koshy __P4MASK(other, 14), 1654ebccf1e3SJoseph Koshy __P4MASK(prefetch, 15), 1655ebccf1e3SJoseph Koshy NULLMASK 1656ebccf1e3SJoseph Koshy }; 1657ebccf1e3SJoseph Koshy 1658ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_fda[] = { /* fsb data activity */ 1659ebccf1e3SJoseph Koshy __P4MASK(drdy-drv, 0), 1660ebccf1e3SJoseph Koshy __P4MASK(drdy-own, 1), 1661ebccf1e3SJoseph Koshy __P4MASK(drdy-other, 2), 1662ebccf1e3SJoseph Koshy __P4MASK(dbsy-drv, 3), 1663ebccf1e3SJoseph Koshy __P4MASK(dbsy-own, 4), 1664ebccf1e3SJoseph Koshy __P4MASK(dbsy-other, 5), 1665ebccf1e3SJoseph Koshy NULLMASK 1666ebccf1e3SJoseph Koshy }; 1667ebccf1e3SJoseph Koshy 1668ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ba[] = { /* bsq allocation */ 1669ebccf1e3SJoseph Koshy __P4MASK(req-type0, 0), 1670ebccf1e3SJoseph Koshy __P4MASK(req-type1, 1), 1671ebccf1e3SJoseph Koshy __P4MASK(req-len0, 2), 1672ebccf1e3SJoseph Koshy __P4MASK(req-len1, 3), 1673ebccf1e3SJoseph Koshy __P4MASK(req-io-type, 5), 1674ebccf1e3SJoseph Koshy __P4MASK(req-lock-type, 6), 1675ebccf1e3SJoseph Koshy __P4MASK(req-cache-type, 7), 1676ebccf1e3SJoseph Koshy __P4MASK(req-split-type, 8), 1677ebccf1e3SJoseph Koshy __P4MASK(req-dem-type, 9), 1678ebccf1e3SJoseph Koshy __P4MASK(req-ord-type, 10), 1679ebccf1e3SJoseph Koshy __P4MASK(mem-type0, 11), 1680ebccf1e3SJoseph Koshy __P4MASK(mem-type1, 12), 1681ebccf1e3SJoseph Koshy __P4MASK(mem-type2, 13), 1682ebccf1e3SJoseph Koshy NULLMASK 1683ebccf1e3SJoseph Koshy }; 1684ebccf1e3SJoseph Koshy 1685ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_sia[] = { /* sse input assist */ 1686ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1687ebccf1e3SJoseph Koshy NULLMASK 1688ebccf1e3SJoseph Koshy }; 1689ebccf1e3SJoseph Koshy 1690ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_psu[] = { /* packed sp uop */ 1691ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1692ebccf1e3SJoseph Koshy NULLMASK 1693ebccf1e3SJoseph Koshy }; 1694ebccf1e3SJoseph Koshy 1695ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_pdu[] = { /* packed dp uop */ 1696ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1697ebccf1e3SJoseph Koshy NULLMASK 1698ebccf1e3SJoseph Koshy }; 1699ebccf1e3SJoseph Koshy 1700ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ssu[] = { /* scalar sp uop */ 1701ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1702ebccf1e3SJoseph Koshy NULLMASK 1703ebccf1e3SJoseph Koshy }; 1704ebccf1e3SJoseph Koshy 1705ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_sdu[] = { /* scalar dp uop */ 1706ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1707ebccf1e3SJoseph Koshy NULLMASK 1708ebccf1e3SJoseph Koshy }; 1709ebccf1e3SJoseph Koshy 1710ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_64bmu[] = { /* 64 bit mmx uop */ 1711ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1712ebccf1e3SJoseph Koshy NULLMASK 1713ebccf1e3SJoseph Koshy }; 1714ebccf1e3SJoseph Koshy 1715ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_128bmu[] = { /* 128 bit mmx uop */ 1716ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1717ebccf1e3SJoseph Koshy NULLMASK 1718ebccf1e3SJoseph Koshy }; 1719ebccf1e3SJoseph Koshy 1720ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xfu[] = { /* X87 fp uop */ 1721ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1722ebccf1e3SJoseph Koshy NULLMASK 1723ebccf1e3SJoseph Koshy }; 1724ebccf1e3SJoseph Koshy 1725ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xsmu[] = { /* x87 simd moves uop */ 1726ebccf1e3SJoseph Koshy __P4MASK(allp0, 3), 1727ebccf1e3SJoseph Koshy __P4MASK(allp2, 4), 1728ebccf1e3SJoseph Koshy NULLMASK 1729ebccf1e3SJoseph Koshy }; 1730ebccf1e3SJoseph Koshy 1731ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_gpe[] = { /* global power events */ 1732ebccf1e3SJoseph Koshy __P4MASK(running, 0), 1733ebccf1e3SJoseph Koshy NULLMASK 1734ebccf1e3SJoseph Koshy }; 1735ebccf1e3SJoseph Koshy 1736ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_tmx[] = { /* TC ms xfer */ 1737ebccf1e3SJoseph Koshy __P4MASK(cisc, 0), 1738ebccf1e3SJoseph Koshy NULLMASK 1739ebccf1e3SJoseph Koshy }; 1740ebccf1e3SJoseph Koshy 1741ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_uqw[] = { /* uop queue writes */ 1742ebccf1e3SJoseph Koshy __P4MASK(from-tc-build, 0), 1743ebccf1e3SJoseph Koshy __P4MASK(from-tc-deliver, 1), 1744ebccf1e3SJoseph Koshy __P4MASK(from-rom, 2), 1745ebccf1e3SJoseph Koshy NULLMASK 1746ebccf1e3SJoseph Koshy }; 1747ebccf1e3SJoseph Koshy 1748d56c5d4bSJoseph Koshy static const struct pmc_masks p4_mask_rmbt[] = { 1749d56c5d4bSJoseph Koshy /* retired mispred branch type */ 1750ebccf1e3SJoseph Koshy __P4MASK(conditional, 1), 1751ebccf1e3SJoseph Koshy __P4MASK(call, 2), 1752ebccf1e3SJoseph Koshy __P4MASK(return, 3), 1753ebccf1e3SJoseph Koshy __P4MASK(indirect, 4), 1754ebccf1e3SJoseph Koshy NULLMASK 1755ebccf1e3SJoseph Koshy }; 1756ebccf1e3SJoseph Koshy 1757ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_rbt[] = { /* retired branch type */ 1758ebccf1e3SJoseph Koshy __P4MASK(conditional, 1), 1759ebccf1e3SJoseph Koshy __P4MASK(call, 2), 1760ebccf1e3SJoseph Koshy __P4MASK(retired, 3), 1761ebccf1e3SJoseph Koshy __P4MASK(indirect, 4), 1762ebccf1e3SJoseph Koshy NULLMASK 1763ebccf1e3SJoseph Koshy }; 1764ebccf1e3SJoseph Koshy 1765ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_rs[] = { /* resource stall */ 1766ebccf1e3SJoseph Koshy __P4MASK(sbfull, 5), 1767ebccf1e3SJoseph Koshy NULLMASK 1768ebccf1e3SJoseph Koshy }; 1769ebccf1e3SJoseph Koshy 1770ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_wb[] = { /* WC buffer */ 1771ebccf1e3SJoseph Koshy __P4MASK(wcb-evicts, 0), 1772ebccf1e3SJoseph Koshy __P4MASK(wcb-full-evict, 1), 1773ebccf1e3SJoseph Koshy NULLMASK 1774ebccf1e3SJoseph Koshy }; 1775ebccf1e3SJoseph Koshy 1776ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_fee[] = { /* front end event */ 1777ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1778ebccf1e3SJoseph Koshy __P4MASK(bogus, 1), 1779ebccf1e3SJoseph Koshy NULLMASK 1780ebccf1e3SJoseph Koshy }; 1781ebccf1e3SJoseph Koshy 1782ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ee[] = { /* execution event */ 1783ebccf1e3SJoseph Koshy __P4MASK(nbogus0, 0), 1784ebccf1e3SJoseph Koshy __P4MASK(nbogus1, 1), 1785ebccf1e3SJoseph Koshy __P4MASK(nbogus2, 2), 1786ebccf1e3SJoseph Koshy __P4MASK(nbogus3, 3), 1787ebccf1e3SJoseph Koshy __P4MASK(bogus0, 4), 1788ebccf1e3SJoseph Koshy __P4MASK(bogus1, 5), 1789ebccf1e3SJoseph Koshy __P4MASK(bogus2, 6), 1790ebccf1e3SJoseph Koshy __P4MASK(bogus3, 7), 1791ebccf1e3SJoseph Koshy NULLMASK 1792ebccf1e3SJoseph Koshy }; 1793ebccf1e3SJoseph Koshy 1794ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_re[] = { /* replay event */ 1795ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1796ebccf1e3SJoseph Koshy __P4MASK(bogus, 1), 1797ebccf1e3SJoseph Koshy NULLMASK 1798ebccf1e3SJoseph Koshy }; 1799ebccf1e3SJoseph Koshy 1800ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_insret[] = { /* instr retired */ 1801ebccf1e3SJoseph Koshy __P4MASK(nbogusntag, 0), 1802ebccf1e3SJoseph Koshy __P4MASK(nbogustag, 1), 1803ebccf1e3SJoseph Koshy __P4MASK(bogusntag, 2), 1804ebccf1e3SJoseph Koshy __P4MASK(bogustag, 3), 1805ebccf1e3SJoseph Koshy NULLMASK 1806ebccf1e3SJoseph Koshy }; 1807ebccf1e3SJoseph Koshy 1808ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ur[] = { /* uops retired */ 1809ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1810ebccf1e3SJoseph Koshy __P4MASK(bogus, 1), 1811ebccf1e3SJoseph Koshy NULLMASK 1812ebccf1e3SJoseph Koshy }; 1813ebccf1e3SJoseph Koshy 1814ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ut[] = { /* uop type */ 1815ebccf1e3SJoseph Koshy __P4MASK(tagloads, 1), 1816ebccf1e3SJoseph Koshy __P4MASK(tagstores, 2), 1817ebccf1e3SJoseph Koshy NULLMASK 1818ebccf1e3SJoseph Koshy }; 1819ebccf1e3SJoseph Koshy 1820ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_br[] = { /* branch retired */ 1821ebccf1e3SJoseph Koshy __P4MASK(mmnp, 0), 1822ebccf1e3SJoseph Koshy __P4MASK(mmnm, 1), 1823ebccf1e3SJoseph Koshy __P4MASK(mmtp, 2), 1824ebccf1e3SJoseph Koshy __P4MASK(mmtm, 3), 1825ebccf1e3SJoseph Koshy NULLMASK 1826ebccf1e3SJoseph Koshy }; 1827ebccf1e3SJoseph Koshy 1828ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_mbr[] = { /* mispred branch retired */ 1829ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1830ebccf1e3SJoseph Koshy NULLMASK 1831ebccf1e3SJoseph Koshy }; 1832ebccf1e3SJoseph Koshy 1833ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xa[] = { /* x87 assist */ 1834ebccf1e3SJoseph Koshy __P4MASK(fpsu, 0), 1835ebccf1e3SJoseph Koshy __P4MASK(fpso, 1), 1836ebccf1e3SJoseph Koshy __P4MASK(poao, 2), 1837ebccf1e3SJoseph Koshy __P4MASK(poau, 3), 1838ebccf1e3SJoseph Koshy __P4MASK(prea, 4), 1839ebccf1e3SJoseph Koshy NULLMASK 1840ebccf1e3SJoseph Koshy }; 1841ebccf1e3SJoseph Koshy 1842ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_machclr[] = { /* machine clear */ 1843ebccf1e3SJoseph Koshy __P4MASK(clear, 0), 1844ebccf1e3SJoseph Koshy __P4MASK(moclear, 2), 1845ebccf1e3SJoseph Koshy __P4MASK(smclear, 3), 1846ebccf1e3SJoseph Koshy NULLMASK 1847ebccf1e3SJoseph Koshy }; 1848ebccf1e3SJoseph Koshy 1849ebccf1e3SJoseph Koshy /* P4 event parser */ 1850ebccf1e3SJoseph Koshy static int 1851ebccf1e3SJoseph Koshy p4_allocate_pmc(enum pmc_event pe, char *ctrspec, 1852ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 1853ebccf1e3SJoseph Koshy { 1854ebccf1e3SJoseph Koshy 1855ebccf1e3SJoseph Koshy char *e, *p, *q; 1856ebccf1e3SJoseph Koshy int count, has_tag, has_busreqtype, n; 18571e862e5aSFabien Thomas uint32_t cccractivemask; 18581e862e5aSFabien Thomas uint64_t evmask; 1859ebccf1e3SJoseph Koshy const struct pmc_masks *pm, *pmask; 1860ebccf1e3SJoseph Koshy 1861789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1862f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig = 1863f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 0; 1864ebccf1e3SJoseph Koshy 1865ebccf1e3SJoseph Koshy pmask = NULL; 1866ebccf1e3SJoseph Koshy evmask = 0; 1867ebccf1e3SJoseph Koshy cccractivemask = 0x3; 1868ebccf1e3SJoseph Koshy has_tag = has_busreqtype = 0; 1869ebccf1e3SJoseph Koshy 1870ebccf1e3SJoseph Koshy #define __P4SETMASK(M) do { \ 1871ebccf1e3SJoseph Koshy pmask = p4_mask_##M; \ 1872ebccf1e3SJoseph Koshy } while (0) 1873ebccf1e3SJoseph Koshy 1874ebccf1e3SJoseph Koshy switch (pe) { 1875ebccf1e3SJoseph Koshy case PMC_EV_P4_TC_DELIVER_MODE: 1876ebccf1e3SJoseph Koshy __P4SETMASK(tcdm); 1877ebccf1e3SJoseph Koshy break; 1878ebccf1e3SJoseph Koshy case PMC_EV_P4_BPU_FETCH_REQUEST: 1879ebccf1e3SJoseph Koshy __P4SETMASK(bfr); 1880ebccf1e3SJoseph Koshy break; 1881ebccf1e3SJoseph Koshy case PMC_EV_P4_ITLB_REFERENCE: 1882ebccf1e3SJoseph Koshy __P4SETMASK(ir); 1883ebccf1e3SJoseph Koshy break; 1884ebccf1e3SJoseph Koshy case PMC_EV_P4_MEMORY_CANCEL: 1885ebccf1e3SJoseph Koshy __P4SETMASK(memcan); 1886ebccf1e3SJoseph Koshy break; 1887ebccf1e3SJoseph Koshy case PMC_EV_P4_MEMORY_COMPLETE: 1888ebccf1e3SJoseph Koshy __P4SETMASK(memcomp); 1889ebccf1e3SJoseph Koshy break; 1890ebccf1e3SJoseph Koshy case PMC_EV_P4_LOAD_PORT_REPLAY: 1891ebccf1e3SJoseph Koshy __P4SETMASK(lpr); 1892ebccf1e3SJoseph Koshy break; 1893ebccf1e3SJoseph Koshy case PMC_EV_P4_STORE_PORT_REPLAY: 1894ebccf1e3SJoseph Koshy __P4SETMASK(spr); 1895ebccf1e3SJoseph Koshy break; 1896ebccf1e3SJoseph Koshy case PMC_EV_P4_MOB_LOAD_REPLAY: 1897ebccf1e3SJoseph Koshy __P4SETMASK(mlr); 1898ebccf1e3SJoseph Koshy break; 1899ebccf1e3SJoseph Koshy case PMC_EV_P4_PAGE_WALK_TYPE: 1900ebccf1e3SJoseph Koshy __P4SETMASK(pwt); 1901ebccf1e3SJoseph Koshy break; 1902ebccf1e3SJoseph Koshy case PMC_EV_P4_BSQ_CACHE_REFERENCE: 1903ebccf1e3SJoseph Koshy __P4SETMASK(bcr); 1904ebccf1e3SJoseph Koshy break; 1905ebccf1e3SJoseph Koshy case PMC_EV_P4_IOQ_ALLOCATION: 1906ebccf1e3SJoseph Koshy __P4SETMASK(ia); 1907ebccf1e3SJoseph Koshy has_busreqtype = 1; 1908ebccf1e3SJoseph Koshy break; 1909ebccf1e3SJoseph Koshy case PMC_EV_P4_IOQ_ACTIVE_ENTRIES: 1910ebccf1e3SJoseph Koshy __P4SETMASK(iae); 1911ebccf1e3SJoseph Koshy has_busreqtype = 1; 1912ebccf1e3SJoseph Koshy break; 1913ebccf1e3SJoseph Koshy case PMC_EV_P4_FSB_DATA_ACTIVITY: 1914ebccf1e3SJoseph Koshy __P4SETMASK(fda); 1915ebccf1e3SJoseph Koshy break; 1916ebccf1e3SJoseph Koshy case PMC_EV_P4_BSQ_ALLOCATION: 1917ebccf1e3SJoseph Koshy __P4SETMASK(ba); 1918ebccf1e3SJoseph Koshy break; 1919ebccf1e3SJoseph Koshy case PMC_EV_P4_SSE_INPUT_ASSIST: 1920ebccf1e3SJoseph Koshy __P4SETMASK(sia); 1921ebccf1e3SJoseph Koshy break; 1922ebccf1e3SJoseph Koshy case PMC_EV_P4_PACKED_SP_UOP: 1923ebccf1e3SJoseph Koshy __P4SETMASK(psu); 1924ebccf1e3SJoseph Koshy break; 1925ebccf1e3SJoseph Koshy case PMC_EV_P4_PACKED_DP_UOP: 1926ebccf1e3SJoseph Koshy __P4SETMASK(pdu); 1927ebccf1e3SJoseph Koshy break; 1928ebccf1e3SJoseph Koshy case PMC_EV_P4_SCALAR_SP_UOP: 1929ebccf1e3SJoseph Koshy __P4SETMASK(ssu); 1930ebccf1e3SJoseph Koshy break; 1931ebccf1e3SJoseph Koshy case PMC_EV_P4_SCALAR_DP_UOP: 1932ebccf1e3SJoseph Koshy __P4SETMASK(sdu); 1933ebccf1e3SJoseph Koshy break; 1934ebccf1e3SJoseph Koshy case PMC_EV_P4_64BIT_MMX_UOP: 1935ebccf1e3SJoseph Koshy __P4SETMASK(64bmu); 1936ebccf1e3SJoseph Koshy break; 1937ebccf1e3SJoseph Koshy case PMC_EV_P4_128BIT_MMX_UOP: 1938ebccf1e3SJoseph Koshy __P4SETMASK(128bmu); 1939ebccf1e3SJoseph Koshy break; 1940ebccf1e3SJoseph Koshy case PMC_EV_P4_X87_FP_UOP: 1941ebccf1e3SJoseph Koshy __P4SETMASK(xfu); 1942ebccf1e3SJoseph Koshy break; 1943ebccf1e3SJoseph Koshy case PMC_EV_P4_X87_SIMD_MOVES_UOP: 1944ebccf1e3SJoseph Koshy __P4SETMASK(xsmu); 1945ebccf1e3SJoseph Koshy break; 1946ebccf1e3SJoseph Koshy case PMC_EV_P4_GLOBAL_POWER_EVENTS: 1947ebccf1e3SJoseph Koshy __P4SETMASK(gpe); 1948ebccf1e3SJoseph Koshy break; 1949ebccf1e3SJoseph Koshy case PMC_EV_P4_TC_MS_XFER: 1950ebccf1e3SJoseph Koshy __P4SETMASK(tmx); 1951ebccf1e3SJoseph Koshy break; 1952ebccf1e3SJoseph Koshy case PMC_EV_P4_UOP_QUEUE_WRITES: 1953ebccf1e3SJoseph Koshy __P4SETMASK(uqw); 1954ebccf1e3SJoseph Koshy break; 1955ebccf1e3SJoseph Koshy case PMC_EV_P4_RETIRED_MISPRED_BRANCH_TYPE: 1956ebccf1e3SJoseph Koshy __P4SETMASK(rmbt); 1957ebccf1e3SJoseph Koshy break; 1958ebccf1e3SJoseph Koshy case PMC_EV_P4_RETIRED_BRANCH_TYPE: 1959ebccf1e3SJoseph Koshy __P4SETMASK(rbt); 1960ebccf1e3SJoseph Koshy break; 1961ebccf1e3SJoseph Koshy case PMC_EV_P4_RESOURCE_STALL: 1962ebccf1e3SJoseph Koshy __P4SETMASK(rs); 1963ebccf1e3SJoseph Koshy break; 1964ebccf1e3SJoseph Koshy case PMC_EV_P4_WC_BUFFER: 1965ebccf1e3SJoseph Koshy __P4SETMASK(wb); 1966ebccf1e3SJoseph Koshy break; 1967ebccf1e3SJoseph Koshy case PMC_EV_P4_BSQ_ACTIVE_ENTRIES: 1968ebccf1e3SJoseph Koshy case PMC_EV_P4_B2B_CYCLES: 1969ebccf1e3SJoseph Koshy case PMC_EV_P4_BNR: 1970ebccf1e3SJoseph Koshy case PMC_EV_P4_SNOOP: 1971ebccf1e3SJoseph Koshy case PMC_EV_P4_RESPONSE: 1972ebccf1e3SJoseph Koshy break; 1973ebccf1e3SJoseph Koshy case PMC_EV_P4_FRONT_END_EVENT: 1974ebccf1e3SJoseph Koshy __P4SETMASK(fee); 1975ebccf1e3SJoseph Koshy break; 1976ebccf1e3SJoseph Koshy case PMC_EV_P4_EXECUTION_EVENT: 1977ebccf1e3SJoseph Koshy __P4SETMASK(ee); 1978ebccf1e3SJoseph Koshy break; 1979ebccf1e3SJoseph Koshy case PMC_EV_P4_REPLAY_EVENT: 1980ebccf1e3SJoseph Koshy __P4SETMASK(re); 1981ebccf1e3SJoseph Koshy break; 1982ebccf1e3SJoseph Koshy case PMC_EV_P4_INSTR_RETIRED: 1983ebccf1e3SJoseph Koshy __P4SETMASK(insret); 1984ebccf1e3SJoseph Koshy break; 1985ebccf1e3SJoseph Koshy case PMC_EV_P4_UOPS_RETIRED: 1986ebccf1e3SJoseph Koshy __P4SETMASK(ur); 1987ebccf1e3SJoseph Koshy break; 1988ebccf1e3SJoseph Koshy case PMC_EV_P4_UOP_TYPE: 1989ebccf1e3SJoseph Koshy __P4SETMASK(ut); 1990ebccf1e3SJoseph Koshy break; 1991ebccf1e3SJoseph Koshy case PMC_EV_P4_BRANCH_RETIRED: 1992ebccf1e3SJoseph Koshy __P4SETMASK(br); 1993ebccf1e3SJoseph Koshy break; 1994ebccf1e3SJoseph Koshy case PMC_EV_P4_MISPRED_BRANCH_RETIRED: 1995ebccf1e3SJoseph Koshy __P4SETMASK(mbr); 1996ebccf1e3SJoseph Koshy break; 1997ebccf1e3SJoseph Koshy case PMC_EV_P4_X87_ASSIST: 1998ebccf1e3SJoseph Koshy __P4SETMASK(xa); 1999ebccf1e3SJoseph Koshy break; 2000ebccf1e3SJoseph Koshy case PMC_EV_P4_MACHINE_CLEAR: 2001ebccf1e3SJoseph Koshy __P4SETMASK(machclr); 2002ebccf1e3SJoseph Koshy break; 2003ebccf1e3SJoseph Koshy default: 2004aa342b1fSJoseph Koshy return (-1); 2005ebccf1e3SJoseph Koshy } 2006ebccf1e3SJoseph Koshy 2007ebccf1e3SJoseph Koshy /* process additional flags */ 2008ebccf1e3SJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 2009ebccf1e3SJoseph Koshy if (KWPREFIXMATCH(p, P4_KW_ACTIVE)) { 2010ebccf1e3SJoseph Koshy q = strchr(p, '='); 2011ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 2012aa342b1fSJoseph Koshy return (-1); 2013ebccf1e3SJoseph Koshy 2014789140c0SJoseph Koshy if (strcasecmp(q, P4_KW_ACTIVE_NONE) == 0) 2015ebccf1e3SJoseph Koshy cccractivemask = 0x0; 2016789140c0SJoseph Koshy else if (strcasecmp(q, P4_KW_ACTIVE_SINGLE) == 0) 2017ebccf1e3SJoseph Koshy cccractivemask = 0x1; 2018789140c0SJoseph Koshy else if (strcasecmp(q, P4_KW_ACTIVE_BOTH) == 0) 2019ebccf1e3SJoseph Koshy cccractivemask = 0x2; 2020789140c0SJoseph Koshy else if (strcasecmp(q, P4_KW_ACTIVE_ANY) == 0) 2021ebccf1e3SJoseph Koshy cccractivemask = 0x3; 2022ebccf1e3SJoseph Koshy else 2023aa342b1fSJoseph Koshy return (-1); 2024ebccf1e3SJoseph Koshy 2025ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, P4_KW_BUSREQTYPE)) { 2026ebccf1e3SJoseph Koshy if (has_busreqtype == 0) 2027aa342b1fSJoseph Koshy return (-1); 2028ebccf1e3SJoseph Koshy 2029ebccf1e3SJoseph Koshy q = strchr(p, '='); 2030ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 2031aa342b1fSJoseph Koshy return (-1); 2032ebccf1e3SJoseph Koshy 2033ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 2034ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 2035aa342b1fSJoseph Koshy return (-1); 2036ebccf1e3SJoseph Koshy evmask = (evmask & ~0x1F) | (count & 0x1F); 2037ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P4_KW_CASCADE)) 2038ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_CASCADE; 2039ebccf1e3SJoseph Koshy else if (KWMATCH(p, P4_KW_EDGE)) 2040ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 2041ebccf1e3SJoseph Koshy else if (KWMATCH(p, P4_KW_INV)) 2042ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 2043ebccf1e3SJoseph Koshy else if (KWPREFIXMATCH(p, P4_KW_MASK "=")) { 2044ebccf1e3SJoseph Koshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 2045aa342b1fSJoseph Koshy return (-1); 2046ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2047ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P4_KW_OS)) 2048ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2049ebccf1e3SJoseph Koshy else if (KWMATCH(p, P4_KW_PRECISE)) 2050ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_PRECISE; 2051ebccf1e3SJoseph Koshy else if (KWPREFIXMATCH(p, P4_KW_TAG "=")) { 2052ebccf1e3SJoseph Koshy if (has_tag == 0) 2053aa342b1fSJoseph Koshy return (-1); 2054ebccf1e3SJoseph Koshy 2055ebccf1e3SJoseph Koshy q = strchr(p, '='); 2056ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 2057aa342b1fSJoseph Koshy return (-1); 2058ebccf1e3SJoseph Koshy 2059ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 2060ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 2061aa342b1fSJoseph Koshy return (-1); 2062ebccf1e3SJoseph Koshy 2063ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_TAGGING; 2064f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig |= 2065ebccf1e3SJoseph Koshy P4_ESCR_TO_TAG_VALUE(count); 2066ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, P4_KW_THRESHOLD "=")) { 2067ebccf1e3SJoseph Koshy q = strchr(p, '='); 2068ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 2069aa342b1fSJoseph Koshy return (-1); 2070ebccf1e3SJoseph Koshy 2071ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 2072ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 2073aa342b1fSJoseph Koshy return (-1); 2074ebccf1e3SJoseph Koshy 2075ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 2076f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig &= 2077f263522aSJoseph Koshy ~P4_CCCR_THRESHOLD_MASK; 2078f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |= 2079f263522aSJoseph Koshy P4_CCCR_TO_THRESHOLD(count); 2080ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P4_KW_USR)) 2081ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 2082ebccf1e3SJoseph Koshy else 2083aa342b1fSJoseph Koshy return (-1); 2084ebccf1e3SJoseph Koshy } 2085ebccf1e3SJoseph Koshy 2086ebccf1e3SJoseph Koshy /* other post processing */ 2087ebccf1e3SJoseph Koshy if (pe == PMC_EV_P4_IOQ_ALLOCATION || 2088ebccf1e3SJoseph Koshy pe == PMC_EV_P4_FSB_DATA_ACTIVITY || 2089ebccf1e3SJoseph Koshy pe == PMC_EV_P4_BSQ_ALLOCATION) 2090ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 2091ebccf1e3SJoseph Koshy 2092ebccf1e3SJoseph Koshy /* fill in thread activity mask */ 2093f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |= 2094ebccf1e3SJoseph Koshy P4_CCCR_TO_ACTIVE_THREAD(cccractivemask); 2095ebccf1e3SJoseph Koshy 2096ebccf1e3SJoseph Koshy if (evmask) 2097ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2098ebccf1e3SJoseph Koshy 2099ebccf1e3SJoseph Koshy switch (pe) { 2100ebccf1e3SJoseph Koshy case PMC_EV_P4_FSB_DATA_ACTIVITY: 2101ebccf1e3SJoseph Koshy if ((evmask & 0x06) == 0x06 || 2102ebccf1e3SJoseph Koshy (evmask & 0x18) == 0x18) 2103aa342b1fSJoseph Koshy return (-1); /* can't have own+other bits together */ 2104ebccf1e3SJoseph Koshy if (evmask == 0) /* default:drdy-{drv,own}+dbsy{drv,own} */ 2105ebccf1e3SJoseph Koshy evmask = 0x1D; 2106ebccf1e3SJoseph Koshy break; 2107ebccf1e3SJoseph Koshy case PMC_EV_P4_MACHINE_CLEAR: 2108ebccf1e3SJoseph Koshy /* only one bit is allowed to be set */ 2109ebccf1e3SJoseph Koshy if ((evmask & (evmask - 1)) != 0) 2110aa342b1fSJoseph Koshy return (-1); 2111ebccf1e3SJoseph Koshy if (evmask == 0) { 2112ebccf1e3SJoseph Koshy evmask = 0x1; /* 'CLEAR' */ 2113ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2114ebccf1e3SJoseph Koshy } 2115ebccf1e3SJoseph Koshy break; 2116ebccf1e3SJoseph Koshy default: 2117ebccf1e3SJoseph Koshy if (evmask == 0 && pmask) { 2118ebccf1e3SJoseph Koshy for (pm = pmask; pm->pm_name; pm++) 2119ebccf1e3SJoseph Koshy evmask |= pm->pm_value; 2120ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2121ebccf1e3SJoseph Koshy } 2122ebccf1e3SJoseph Koshy } 2123ebccf1e3SJoseph Koshy 2124f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 2125f263522aSJoseph Koshy P4_ESCR_TO_EVENT_MASK(evmask); 2126ebccf1e3SJoseph Koshy 2127aa342b1fSJoseph Koshy return (0); 2128ebccf1e3SJoseph Koshy } 2129ebccf1e3SJoseph Koshy 213086a65549SJoseph Koshy #endif 213186a65549SJoseph Koshy 213286a65549SJoseph Koshy #if defined(__i386__) 213386a65549SJoseph Koshy 2134ebccf1e3SJoseph Koshy /* 2135f263522aSJoseph Koshy * Pentium style PMCs 2136f263522aSJoseph Koshy */ 2137f263522aSJoseph Koshy 2138f263522aSJoseph Koshy static struct pmc_event_alias p5_aliases[] = { 21390b9b757dSJoseph Koshy EV_ALIAS("branches", "p5-taken-branches"), 2140f263522aSJoseph Koshy EV_ALIAS("cycles", "tsc"), 21410b9b757dSJoseph Koshy EV_ALIAS("dc-misses", "p5-data-read-miss-or-write-miss"), 21420b9b757dSJoseph Koshy EV_ALIAS("ic-misses", "p5-code-cache-miss"), 21430b9b757dSJoseph Koshy EV_ALIAS("instructions", "p5-instructions-executed"), 21440b9b757dSJoseph Koshy EV_ALIAS("interrupts", "p5-hardware-interrupts"), 21450b9b757dSJoseph Koshy EV_ALIAS("unhalted-cycles", 21460b9b757dSJoseph Koshy "p5-number-of-cycles-not-in-halt-state"), 2147f263522aSJoseph Koshy EV_ALIAS(NULL, NULL) 2148f263522aSJoseph Koshy }; 2149f263522aSJoseph Koshy 2150f263522aSJoseph Koshy static int 2151f263522aSJoseph Koshy p5_allocate_pmc(enum pmc_event pe, char *ctrspec, 2152f263522aSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 2153f263522aSJoseph Koshy { 2154aa342b1fSJoseph Koshy return (-1 || pe || ctrspec || pmc_config); /* shut up gcc */ 2155f263522aSJoseph Koshy } 2156f263522aSJoseph Koshy 2157f263522aSJoseph Koshy /* 2158ebccf1e3SJoseph Koshy * Pentium Pro style PMCs. These PMCs are found in Pentium II, Pentium III, 2159ebccf1e3SJoseph Koshy * and Pentium M CPUs. 2160ebccf1e3SJoseph Koshy */ 2161ebccf1e3SJoseph Koshy 2162ebccf1e3SJoseph Koshy static struct pmc_event_alias p6_aliases[] = { 2163ebccf1e3SJoseph Koshy EV_ALIAS("branches", "p6-br-inst-retired"), 2164ebccf1e3SJoseph Koshy EV_ALIAS("branch-mispredicts", "p6-br-miss-pred-retired"), 2165ebccf1e3SJoseph Koshy EV_ALIAS("cycles", "tsc"), 2166d56c5d4bSJoseph Koshy EV_ALIAS("dc-misses", "p6-dcu-lines-in"), 216773e2d811SJoseph Koshy EV_ALIAS("ic-misses", "p6-ifu-fetch-miss"), 2168ebccf1e3SJoseph Koshy EV_ALIAS("instructions", "p6-inst-retired"), 2169ebccf1e3SJoseph Koshy EV_ALIAS("interrupts", "p6-hw-int-rx"), 2170177a2f22SJoseph Koshy EV_ALIAS("unhalted-cycles", "p6-cpu-clk-unhalted"), 2171ebccf1e3SJoseph Koshy EV_ALIAS(NULL, NULL) 2172ebccf1e3SJoseph Koshy }; 2173ebccf1e3SJoseph Koshy 2174ebccf1e3SJoseph Koshy #define P6_KW_CMASK "cmask" 2175ebccf1e3SJoseph Koshy #define P6_KW_EDGE "edge" 2176ebccf1e3SJoseph Koshy #define P6_KW_INV "inv" 2177ebccf1e3SJoseph Koshy #define P6_KW_OS "os" 2178ebccf1e3SJoseph Koshy #define P6_KW_UMASK "umask" 2179ebccf1e3SJoseph Koshy #define P6_KW_USR "usr" 2180ebccf1e3SJoseph Koshy 2181ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mesi[] = { 2182ebccf1e3SJoseph Koshy PMCMASK(m, 0x01), 2183ebccf1e3SJoseph Koshy PMCMASK(e, 0x02), 2184ebccf1e3SJoseph Koshy PMCMASK(s, 0x04), 2185ebccf1e3SJoseph Koshy PMCMASK(i, 0x08), 2186ebccf1e3SJoseph Koshy NULLMASK 2187ebccf1e3SJoseph Koshy }; 2188ebccf1e3SJoseph Koshy 2189ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mesihw[] = { 2190ebccf1e3SJoseph Koshy PMCMASK(m, 0x01), 2191ebccf1e3SJoseph Koshy PMCMASK(e, 0x02), 2192ebccf1e3SJoseph Koshy PMCMASK(s, 0x04), 2193ebccf1e3SJoseph Koshy PMCMASK(i, 0x08), 2194ebccf1e3SJoseph Koshy PMCMASK(nonhw, 0x00), 2195ebccf1e3SJoseph Koshy PMCMASK(hw, 0x10), 2196ebccf1e3SJoseph Koshy PMCMASK(both, 0x30), 2197ebccf1e3SJoseph Koshy NULLMASK 2198ebccf1e3SJoseph Koshy }; 2199ebccf1e3SJoseph Koshy 2200ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_hw[] = { 2201ebccf1e3SJoseph Koshy PMCMASK(nonhw, 0x00), 2202ebccf1e3SJoseph Koshy PMCMASK(hw, 0x10), 2203ebccf1e3SJoseph Koshy PMCMASK(both, 0x30), 2204ebccf1e3SJoseph Koshy NULLMASK 2205ebccf1e3SJoseph Koshy }; 2206ebccf1e3SJoseph Koshy 2207ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_any[] = { 2208ebccf1e3SJoseph Koshy PMCMASK(self, 0x00), 2209ebccf1e3SJoseph Koshy PMCMASK(any, 0x20), 2210ebccf1e3SJoseph Koshy NULLMASK 2211ebccf1e3SJoseph Koshy }; 2212ebccf1e3SJoseph Koshy 2213ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_ekp[] = { 2214ebccf1e3SJoseph Koshy PMCMASK(nta, 0x00), 2215ebccf1e3SJoseph Koshy PMCMASK(t1, 0x01), 2216ebccf1e3SJoseph Koshy PMCMASK(t2, 0x02), 2217ebccf1e3SJoseph Koshy PMCMASK(wos, 0x03), 2218ebccf1e3SJoseph Koshy NULLMASK 2219ebccf1e3SJoseph Koshy }; 2220ebccf1e3SJoseph Koshy 2221ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_pps[] = { 2222ebccf1e3SJoseph Koshy PMCMASK(packed-and-scalar, 0x00), 2223ebccf1e3SJoseph Koshy PMCMASK(scalar, 0x01), 2224ebccf1e3SJoseph Koshy NULLMASK 2225ebccf1e3SJoseph Koshy }; 2226ebccf1e3SJoseph Koshy 2227ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mite[] = { 2228ebccf1e3SJoseph Koshy PMCMASK(packed-multiply, 0x01), 2229ebccf1e3SJoseph Koshy PMCMASK(packed-shift, 0x02), 2230ebccf1e3SJoseph Koshy PMCMASK(pack, 0x04), 2231ebccf1e3SJoseph Koshy PMCMASK(unpack, 0x08), 2232ebccf1e3SJoseph Koshy PMCMASK(packed-logical, 0x10), 2233ebccf1e3SJoseph Koshy PMCMASK(packed-arithmetic, 0x20), 2234ebccf1e3SJoseph Koshy NULLMASK 2235ebccf1e3SJoseph Koshy }; 2236ebccf1e3SJoseph Koshy 2237ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_fmt[] = { 2238ebccf1e3SJoseph Koshy PMCMASK(mmxtofp, 0x00), 2239ebccf1e3SJoseph Koshy PMCMASK(fptommx, 0x01), 2240ebccf1e3SJoseph Koshy NULLMASK 2241ebccf1e3SJoseph Koshy }; 2242ebccf1e3SJoseph Koshy 2243ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_sr[] = { 2244ebccf1e3SJoseph Koshy PMCMASK(es, 0x01), 2245ebccf1e3SJoseph Koshy PMCMASK(ds, 0x02), 2246ebccf1e3SJoseph Koshy PMCMASK(fs, 0x04), 2247ebccf1e3SJoseph Koshy PMCMASK(gs, 0x08), 2248ebccf1e3SJoseph Koshy NULLMASK 2249ebccf1e3SJoseph Koshy }; 2250ebccf1e3SJoseph Koshy 2251ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_eet[] = { 2252ebccf1e3SJoseph Koshy PMCMASK(all, 0x00), 2253ebccf1e3SJoseph Koshy PMCMASK(freq, 0x02), 2254ebccf1e3SJoseph Koshy NULLMASK 2255ebccf1e3SJoseph Koshy }; 2256ebccf1e3SJoseph Koshy 2257ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_efur[] = { 2258ebccf1e3SJoseph Koshy PMCMASK(all, 0x00), 2259ebccf1e3SJoseph Koshy PMCMASK(loadop, 0x01), 2260ebccf1e3SJoseph Koshy PMCMASK(stdsta, 0x02), 2261ebccf1e3SJoseph Koshy NULLMASK 2262ebccf1e3SJoseph Koshy }; 2263ebccf1e3SJoseph Koshy 2264ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_essir[] = { 2265ebccf1e3SJoseph Koshy PMCMASK(sse-packed-single, 0x00), 2266ebccf1e3SJoseph Koshy PMCMASK(sse-packed-single-scalar-single, 0x01), 2267ebccf1e3SJoseph Koshy PMCMASK(sse2-packed-double, 0x02), 2268ebccf1e3SJoseph Koshy PMCMASK(sse2-scalar-double, 0x03), 2269ebccf1e3SJoseph Koshy NULLMASK 2270ebccf1e3SJoseph Koshy }; 2271ebccf1e3SJoseph Koshy 2272ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_esscir[] = { 2273ebccf1e3SJoseph Koshy PMCMASK(sse-packed-single, 0x00), 2274ebccf1e3SJoseph Koshy PMCMASK(sse-scalar-single, 0x01), 2275ebccf1e3SJoseph Koshy PMCMASK(sse2-packed-double, 0x02), 2276ebccf1e3SJoseph Koshy PMCMASK(sse2-scalar-double, 0x03), 2277ebccf1e3SJoseph Koshy NULLMASK 2278ebccf1e3SJoseph Koshy }; 2279ebccf1e3SJoseph Koshy 2280ebccf1e3SJoseph Koshy /* P6 event parser */ 2281ebccf1e3SJoseph Koshy static int 2282ebccf1e3SJoseph Koshy p6_allocate_pmc(enum pmc_event pe, char *ctrspec, 2283ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 2284ebccf1e3SJoseph Koshy { 2285ebccf1e3SJoseph Koshy char *e, *p, *q; 22861e862e5aSFabien Thomas uint64_t evmask; 2287ebccf1e3SJoseph Koshy int count, n; 2288ebccf1e3SJoseph Koshy const struct pmc_masks *pm, *pmask; 2289ebccf1e3SJoseph Koshy 2290789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2291f263522aSJoseph Koshy pmc_config->pm_md.pm_ppro.pm_ppro_config = 0; 2292ebccf1e3SJoseph Koshy 2293ebccf1e3SJoseph Koshy evmask = 0; 2294ebccf1e3SJoseph Koshy 2295ebccf1e3SJoseph Koshy #define P6MASKSET(M) pmask = p6_mask_ ## M 2296ebccf1e3SJoseph Koshy 2297ebccf1e3SJoseph Koshy switch(pe) { 2298ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_IFETCH: P6MASKSET(mesi); break; 2299ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_LD: P6MASKSET(mesi); break; 2300ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_ST: P6MASKSET(mesi); break; 2301ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_RQSTS: P6MASKSET(mesi); break; 2302ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_DRDY_CLOCKS: 2303ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_LOCK_CLOCKS: 2304ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BRD: 2305ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_RFO: 2306ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_WB: 2307ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_IFETCH: 2308ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_INVAL: 2309ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_PWR: 2310ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_P: 2311ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_IO: 2312ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_DEF: 2313ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BURST: 2314ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_ANY: 2315ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_MEM: 2316ebccf1e3SJoseph Koshy P6MASKSET(any); break; 2317ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED: 2318ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_MISS: 2319ebccf1e3SJoseph Koshy P6MASKSET(ekp); break; 2320ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_INST_RETIRED: 2321ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_COMP_INST_RET: 2322ebccf1e3SJoseph Koshy P6MASKSET(pps); break; 2323ebccf1e3SJoseph Koshy case PMC_EV_P6_MMX_INSTR_TYPE_EXEC: 2324ebccf1e3SJoseph Koshy P6MASKSET(mite); break; 2325ebccf1e3SJoseph Koshy case PMC_EV_P6_FP_MMX_TRANS: 2326ebccf1e3SJoseph Koshy P6MASKSET(fmt); break; 2327ebccf1e3SJoseph Koshy case PMC_EV_P6_SEG_RENAME_STALLS: 2328ebccf1e3SJoseph Koshy case PMC_EV_P6_SEG_REG_RENAMES: 2329ebccf1e3SJoseph Koshy P6MASKSET(sr); break; 2330ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_EST_TRANS: 2331ebccf1e3SJoseph Koshy P6MASKSET(eet); break; 2332ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_FUSED_UOPS_RET: 2333ebccf1e3SJoseph Koshy P6MASKSET(efur); break; 2334ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED: 2335ebccf1e3SJoseph Koshy P6MASKSET(essir); break; 2336ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED: 2337ebccf1e3SJoseph Koshy P6MASKSET(esscir); break; 2338ebccf1e3SJoseph Koshy default: 2339ebccf1e3SJoseph Koshy pmask = NULL; 2340ebccf1e3SJoseph Koshy break; 2341ebccf1e3SJoseph Koshy } 2342ebccf1e3SJoseph Koshy 2343ebccf1e3SJoseph Koshy /* Pentium M PMCs have a few events with different semantics */ 2344ebccf1e3SJoseph Koshy if (cpu_info.pm_cputype == PMC_CPU_INTEL_PM) { 2345ebccf1e3SJoseph Koshy if (pe == PMC_EV_P6_L2_LD || 2346ebccf1e3SJoseph Koshy pe == PMC_EV_P6_L2_LINES_IN || 2347ebccf1e3SJoseph Koshy pe == PMC_EV_P6_L2_LINES_OUT) 2348ebccf1e3SJoseph Koshy P6MASKSET(mesihw); 2349ebccf1e3SJoseph Koshy else if (pe == PMC_EV_P6_L2_M_LINES_OUTM) 2350ebccf1e3SJoseph Koshy P6MASKSET(hw); 2351ebccf1e3SJoseph Koshy } 2352ebccf1e3SJoseph Koshy 2353ebccf1e3SJoseph Koshy /* Parse additional modifiers if present */ 2354ebccf1e3SJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 2355ebccf1e3SJoseph Koshy if (KWPREFIXMATCH(p, P6_KW_CMASK "=")) { 2356ebccf1e3SJoseph Koshy q = strchr(p, '='); 2357ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 2358aa342b1fSJoseph Koshy return (-1); 2359ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 2360ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 2361aa342b1fSJoseph Koshy return (-1); 2362ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 2363f263522aSJoseph Koshy pmc_config->pm_md.pm_ppro.pm_ppro_config |= 2364f263522aSJoseph Koshy P6_EVSEL_TO_CMASK(count); 2365ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_EDGE)) { 2366ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 2367ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_INV)) { 2368ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 2369ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_OS)) { 2370ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2371ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, P6_KW_UMASK "=")) { 2372ebccf1e3SJoseph Koshy evmask = 0; 2373ebccf1e3SJoseph Koshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 2374aa342b1fSJoseph Koshy return (-1); 2375ebccf1e3SJoseph Koshy if ((pe == PMC_EV_P6_BUS_DRDY_CLOCKS || 2376ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_LOCK_CLOCKS || 2377ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_BRD || 2378ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_RFO || 2379ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_IFETCH || 2380ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_INVAL || 2381ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_PWR || 2382ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_DEF || 2383ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_BURST || 2384ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_ANY || 2385ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_MEM || 2386ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRANS_IO || 2387ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRANS_P || 2388ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRANS_WB || 2389ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_EST_TRANS || 2390ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_FUSED_UOPS_RET || 2391ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_COMP_INST_RET || 2392ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_INST_RETIRED || 2393ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_PREF_DISPATCHED || 2394ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_PREF_MISS || 2395ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED || 2396ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED || 2397ebccf1e3SJoseph Koshy pe == PMC_EV_P6_FP_MMX_TRANS) 2398aa342b1fSJoseph Koshy && (n > 1)) /* Only one mask keyword is allowed. */ 2399aa342b1fSJoseph Koshy return (-1); 2400ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2401ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_USR)) { 2402ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 2403ebccf1e3SJoseph Koshy } else 2404aa342b1fSJoseph Koshy return (-1); 2405ebccf1e3SJoseph Koshy } 2406ebccf1e3SJoseph Koshy 2407ebccf1e3SJoseph Koshy /* post processing */ 2408ebccf1e3SJoseph Koshy switch (pe) { 2409ebccf1e3SJoseph Koshy 2410ebccf1e3SJoseph Koshy /* 2411ebccf1e3SJoseph Koshy * The following events default to an evmask of 0 2412ebccf1e3SJoseph Koshy */ 2413ebccf1e3SJoseph Koshy 2414ebccf1e3SJoseph Koshy /* default => 'self' */ 2415ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_DRDY_CLOCKS: 2416ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_LOCK_CLOCKS: 2417ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BRD: 2418ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_RFO: 2419ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_WB: 2420ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_IFETCH: 2421ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_INVAL: 2422ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_PWR: 2423ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_P: 2424ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_IO: 2425ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_DEF: 2426ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BURST: 2427ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_ANY: 2428ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_MEM: 2429ebccf1e3SJoseph Koshy 2430ebccf1e3SJoseph Koshy /* default => 'nta' */ 2431ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED: 2432ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_MISS: 2433ebccf1e3SJoseph Koshy 2434ebccf1e3SJoseph Koshy /* default => 'packed and scalar' */ 2435ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_INST_RETIRED: 2436ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_COMP_INST_RET: 2437ebccf1e3SJoseph Koshy 2438ebccf1e3SJoseph Koshy /* default => 'mmx to fp transitions' */ 2439ebccf1e3SJoseph Koshy case PMC_EV_P6_FP_MMX_TRANS: 2440ebccf1e3SJoseph Koshy 2441ebccf1e3SJoseph Koshy /* default => 'SSE Packed Single' */ 2442ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED: 2443ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED: 2444ebccf1e3SJoseph Koshy 2445ebccf1e3SJoseph Koshy /* default => 'all fused micro-ops' */ 2446ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_FUSED_UOPS_RET: 2447ebccf1e3SJoseph Koshy 2448ebccf1e3SJoseph Koshy /* default => 'all transitions' */ 2449ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_EST_TRANS: 2450ebccf1e3SJoseph Koshy break; 2451ebccf1e3SJoseph Koshy 2452ebccf1e3SJoseph Koshy case PMC_EV_P6_MMX_UOPS_EXEC: 2453ebccf1e3SJoseph Koshy evmask = 0x0F; /* only value allowed */ 2454ebccf1e3SJoseph Koshy break; 2455ebccf1e3SJoseph Koshy 2456ebccf1e3SJoseph Koshy default: 2457ebccf1e3SJoseph Koshy /* 2458ebccf1e3SJoseph Koshy * For all other events, set the default event mask 2459ebccf1e3SJoseph Koshy * to a logical OR of all the allowed event mask bits. 2460ebccf1e3SJoseph Koshy */ 2461ebccf1e3SJoseph Koshy if (evmask == 0 && pmask) { 2462ebccf1e3SJoseph Koshy for (pm = pmask; pm->pm_name; pm++) 2463ebccf1e3SJoseph Koshy evmask |= pm->pm_value; 2464ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2465ebccf1e3SJoseph Koshy } 2466ebccf1e3SJoseph Koshy 2467ebccf1e3SJoseph Koshy break; 2468ebccf1e3SJoseph Koshy } 2469ebccf1e3SJoseph Koshy 2470ebccf1e3SJoseph Koshy if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) 2471f263522aSJoseph Koshy pmc_config->pm_md.pm_ppro.pm_ppro_config |= 2472f263522aSJoseph Koshy P6_EVSEL_TO_UMASK(evmask); 2473ebccf1e3SJoseph Koshy 2474aa342b1fSJoseph Koshy return (0); 2475ebccf1e3SJoseph Koshy } 2476ebccf1e3SJoseph Koshy 2477ebccf1e3SJoseph Koshy #endif 2478ebccf1e3SJoseph Koshy 2479789140c0SJoseph Koshy #if defined(__i386__) || defined(__amd64__) 2480789140c0SJoseph Koshy static int 2481789140c0SJoseph Koshy tsc_allocate_pmc(enum pmc_event pe, char *ctrspec, 2482789140c0SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 2483789140c0SJoseph Koshy { 2484789140c0SJoseph Koshy if (pe != PMC_EV_TSC_TSC) 2485789140c0SJoseph Koshy return (-1); 2486789140c0SJoseph Koshy 2487789140c0SJoseph Koshy /* TSC events must be unqualified. */ 2488789140c0SJoseph Koshy if (ctrspec && *ctrspec != '\0') 2489789140c0SJoseph Koshy return (-1); 2490789140c0SJoseph Koshy 2491789140c0SJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 2492789140c0SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_READ; 2493789140c0SJoseph Koshy 2494789140c0SJoseph Koshy return (0); 2495789140c0SJoseph Koshy } 2496789140c0SJoseph Koshy #endif 2497789140c0SJoseph Koshy 2498f5f9340bSFabien Thomas static struct pmc_event_alias generic_aliases[] = { 2499f5f9340bSFabien Thomas EV_ALIAS("instructions", "SOFT-CLOCK.HARD"), 2500f5f9340bSFabien Thomas EV_ALIAS(NULL, NULL) 2501f5f9340bSFabien Thomas }; 2502f5f9340bSFabien Thomas 2503f5f9340bSFabien Thomas static int 2504f5f9340bSFabien Thomas soft_allocate_pmc(enum pmc_event pe, char *ctrspec, 2505f5f9340bSFabien Thomas struct pmc_op_pmcallocate *pmc_config) 2506f5f9340bSFabien Thomas { 2507f5f9340bSFabien Thomas (void)ctrspec; 2508f5f9340bSFabien Thomas (void)pmc_config; 2509f5f9340bSFabien Thomas 2510f0bbe9aaSDimitry Andric if ((int)pe < PMC_EV_SOFT_FIRST || (int)pe > PMC_EV_SOFT_LAST) 2511f5f9340bSFabien Thomas return (-1); 2512f5f9340bSFabien Thomas 2513f5f9340bSFabien Thomas pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2514f5f9340bSFabien Thomas return (0); 2515f5f9340bSFabien Thomas } 2516f5f9340bSFabien Thomas 25176411d14dSRuslan Bukin #if defined(__arm__) 25180ce207d2SRui Paulo #if defined(__XSCALE__) 25190ce207d2SRui Paulo 25200ce207d2SRui Paulo static struct pmc_event_alias xscale_aliases[] = { 25210ce207d2SRui Paulo EV_ALIAS("branches", "BRANCH_RETIRED"), 25220ce207d2SRui Paulo EV_ALIAS("branch-mispredicts", "BRANCH_MISPRED"), 25230ce207d2SRui Paulo EV_ALIAS("dc-misses", "DC_MISS"), 25240ce207d2SRui Paulo EV_ALIAS("ic-misses", "IC_MISS"), 25250ce207d2SRui Paulo EV_ALIAS("instructions", "INSTR_RETIRED"), 25260ce207d2SRui Paulo EV_ALIAS(NULL, NULL) 25270ce207d2SRui Paulo }; 25280ce207d2SRui Paulo static int 25290ce207d2SRui Paulo xscale_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 25300ce207d2SRui Paulo struct pmc_op_pmcallocate *pmc_config __unused) 25310ce207d2SRui Paulo { 25320ce207d2SRui Paulo switch (pe) { 25330ce207d2SRui Paulo default: 25340ce207d2SRui Paulo break; 25350ce207d2SRui Paulo } 25360ce207d2SRui Paulo 25370ce207d2SRui Paulo return (0); 25380ce207d2SRui Paulo } 25390ce207d2SRui Paulo #endif 25400ce207d2SRui Paulo 25413e0bfdd8SRuslan Bukin static struct pmc_event_alias cortex_a8_aliases[] = { 25426411d14dSRuslan Bukin EV_ALIAS("dc-misses", "L1_DCACHE_REFILL"), 25436411d14dSRuslan Bukin EV_ALIAS("ic-misses", "L1_ICACHE_REFILL"), 25446411d14dSRuslan Bukin EV_ALIAS("instructions", "INSTR_EXECUTED"), 25456411d14dSRuslan Bukin EV_ALIAS(NULL, NULL) 25466411d14dSRuslan Bukin }; 25473e0bfdd8SRuslan Bukin 25483e0bfdd8SRuslan Bukin static struct pmc_event_alias cortex_a9_aliases[] = { 25493e0bfdd8SRuslan Bukin EV_ALIAS("dc-misses", "L1_DCACHE_REFILL"), 25503e0bfdd8SRuslan Bukin EV_ALIAS("ic-misses", "L1_ICACHE_REFILL"), 25513e0bfdd8SRuslan Bukin EV_ALIAS("instructions", "INSTR_EXECUTED"), 25523e0bfdd8SRuslan Bukin EV_ALIAS(NULL, NULL) 25533e0bfdd8SRuslan Bukin }; 25543e0bfdd8SRuslan Bukin 25556411d14dSRuslan Bukin static int 25566411d14dSRuslan Bukin armv7_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 25576411d14dSRuslan Bukin struct pmc_op_pmcallocate *pmc_config __unused) 25586411d14dSRuslan Bukin { 25596411d14dSRuslan Bukin switch (pe) { 25606411d14dSRuslan Bukin default: 25616411d14dSRuslan Bukin break; 25626411d14dSRuslan Bukin } 25636411d14dSRuslan Bukin 25646411d14dSRuslan Bukin return (0); 25656411d14dSRuslan Bukin } 25666411d14dSRuslan Bukin #endif 25676411d14dSRuslan Bukin 2568bc88bb2bSRuslan Bukin #if defined(__aarch64__) 2569bc88bb2bSRuslan Bukin static struct pmc_event_alias cortex_a53_aliases[] = { 2570bc88bb2bSRuslan Bukin EV_ALIAS(NULL, NULL) 2571bc88bb2bSRuslan Bukin }; 2572bc88bb2bSRuslan Bukin static struct pmc_event_alias cortex_a57_aliases[] = { 2573bc88bb2bSRuslan Bukin EV_ALIAS(NULL, NULL) 2574bc88bb2bSRuslan Bukin }; 2575bc88bb2bSRuslan Bukin static int 2576bc88bb2bSRuslan Bukin arm64_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 2577bc88bb2bSRuslan Bukin struct pmc_op_pmcallocate *pmc_config __unused) 2578bc88bb2bSRuslan Bukin { 2579bc88bb2bSRuslan Bukin switch (pe) { 2580bc88bb2bSRuslan Bukin default: 2581bc88bb2bSRuslan Bukin break; 2582bc88bb2bSRuslan Bukin } 2583bc88bb2bSRuslan Bukin 2584bc88bb2bSRuslan Bukin return (0); 2585bc88bb2bSRuslan Bukin } 2586bc88bb2bSRuslan Bukin #endif 2587bc88bb2bSRuslan Bukin 2588660df75eSGeorge V. Neville-Neil #if defined(__mips__) 2589660df75eSGeorge V. Neville-Neil 2590660df75eSGeorge V. Neville-Neil static struct pmc_event_alias mips24k_aliases[] = { 2591660df75eSGeorge V. Neville-Neil EV_ALIAS("instructions", "INSTR_EXECUTED"), 2592660df75eSGeorge V. Neville-Neil EV_ALIAS("branches", "BRANCH_COMPLETED"), 2593660df75eSGeorge V. Neville-Neil EV_ALIAS("branch-mispredicts", "BRANCH_MISPRED"), 2594660df75eSGeorge V. Neville-Neil EV_ALIAS(NULL, NULL) 2595660df75eSGeorge V. Neville-Neil }; 2596660df75eSGeorge V. Neville-Neil 2597f6e6460dSAdrian Chadd static struct pmc_event_alias mips74k_aliases[] = { 2598f6e6460dSAdrian Chadd EV_ALIAS("instructions", "INSTR_EXECUTED"), 2599f6e6460dSAdrian Chadd EV_ALIAS("branches", "BRANCH_INSNS"), 2600f6e6460dSAdrian Chadd EV_ALIAS("branch-mispredicts", "MISPREDICTED_BRANCH_INSNS"), 2601f6e6460dSAdrian Chadd EV_ALIAS(NULL, NULL) 2602f6e6460dSAdrian Chadd }; 2603f6e6460dSAdrian Chadd 2604c2657f80SOleksandr Tymoshenko static struct pmc_event_alias octeon_aliases[] = { 2605c2657f80SOleksandr Tymoshenko EV_ALIAS("instructions", "RET"), 2606c2657f80SOleksandr Tymoshenko EV_ALIAS("branches", "BR"), 2607c2657f80SOleksandr Tymoshenko EV_ALIAS("branch-mispredicts", "BRMIS"), 2608c2657f80SOleksandr Tymoshenko EV_ALIAS(NULL, NULL) 2609c2657f80SOleksandr Tymoshenko }; 2610c2657f80SOleksandr Tymoshenko 26112827d3e1SOleksandr Tymoshenko #define MIPS_KW_OS "os" 26122827d3e1SOleksandr Tymoshenko #define MIPS_KW_USR "usr" 26132827d3e1SOleksandr Tymoshenko #define MIPS_KW_ANYTHREAD "anythread" 2614660df75eSGeorge V. Neville-Neil 2615660df75eSGeorge V. Neville-Neil static int 26162827d3e1SOleksandr Tymoshenko mips_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 2617660df75eSGeorge V. Neville-Neil struct pmc_op_pmcallocate *pmc_config __unused) 2618660df75eSGeorge V. Neville-Neil { 2619660df75eSGeorge V. Neville-Neil char *p; 2620660df75eSGeorge V. Neville-Neil 2621660df75eSGeorge V. Neville-Neil (void) pe; 2622660df75eSGeorge V. Neville-Neil 2623660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2624660df75eSGeorge V. Neville-Neil 2625660df75eSGeorge V. Neville-Neil while ((p = strsep(&ctrspec, ",")) != NULL) { 26262827d3e1SOleksandr Tymoshenko if (KWMATCH(p, MIPS_KW_OS)) 2627660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= PMC_CAP_SYSTEM; 26282827d3e1SOleksandr Tymoshenko else if (KWMATCH(p, MIPS_KW_USR)) 2629660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= PMC_CAP_USER; 26302827d3e1SOleksandr Tymoshenko else if (KWMATCH(p, MIPS_KW_ANYTHREAD)) 2631660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= (PMC_CAP_USER | PMC_CAP_SYSTEM); 2632660df75eSGeorge V. Neville-Neil else 2633660df75eSGeorge V. Neville-Neil return (-1); 2634660df75eSGeorge V. Neville-Neil } 2635660df75eSGeorge V. Neville-Neil 2636660df75eSGeorge V. Neville-Neil return (0); 2637660df75eSGeorge V. Neville-Neil } 26382827d3e1SOleksandr Tymoshenko 2639660df75eSGeorge V. Neville-Neil #endif /* __mips__ */ 2640660df75eSGeorge V. Neville-Neil 26417b25dccaSJustin Hibbits #if defined(__powerpc__) 26427b25dccaSJustin Hibbits 26437b25dccaSJustin Hibbits static struct pmc_event_alias ppc7450_aliases[] = { 26447b25dccaSJustin Hibbits EV_ALIAS("instructions", "INSTR_COMPLETED"), 26457b25dccaSJustin Hibbits EV_ALIAS("branches", "BRANCHES_COMPLETED"), 26467b25dccaSJustin Hibbits EV_ALIAS("branch-mispredicts", "MISPREDICTED_BRANCHES"), 26477b25dccaSJustin Hibbits EV_ALIAS(NULL, NULL) 26487b25dccaSJustin Hibbits }; 26497b25dccaSJustin Hibbits 2650169dd953SJustin Hibbits static struct pmc_event_alias ppc970_aliases[] = { 2651169dd953SJustin Hibbits EV_ALIAS("instructions", "INSTR_COMPLETED"), 2652169dd953SJustin Hibbits EV_ALIAS("cycles", "CYCLES"), 2653169dd953SJustin Hibbits EV_ALIAS(NULL, NULL) 2654169dd953SJustin Hibbits }; 2655169dd953SJustin Hibbits 2656a7452468SJustin Hibbits static struct pmc_event_alias e500_aliases[] = { 2657a7452468SJustin Hibbits EV_ALIAS("instructions", "INSTR_COMPLETED"), 2658a7452468SJustin Hibbits EV_ALIAS("cycles", "CYCLES"), 2659a7452468SJustin Hibbits EV_ALIAS(NULL, NULL) 2660a7452468SJustin Hibbits }; 2661a7452468SJustin Hibbits 2662169dd953SJustin Hibbits #define POWERPC_KW_OS "os" 2663169dd953SJustin Hibbits #define POWERPC_KW_USR "usr" 2664169dd953SJustin Hibbits #define POWERPC_KW_ANYTHREAD "anythread" 26657b25dccaSJustin Hibbits 26667b25dccaSJustin Hibbits static int 2667169dd953SJustin Hibbits powerpc_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 26687b25dccaSJustin Hibbits struct pmc_op_pmcallocate *pmc_config __unused) 26697b25dccaSJustin Hibbits { 26707b25dccaSJustin Hibbits char *p; 26717b25dccaSJustin Hibbits 26727b25dccaSJustin Hibbits (void) pe; 26737b25dccaSJustin Hibbits 26747b25dccaSJustin Hibbits pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 26757b25dccaSJustin Hibbits 26767b25dccaSJustin Hibbits while ((p = strsep(&ctrspec, ",")) != NULL) { 2677169dd953SJustin Hibbits if (KWMATCH(p, POWERPC_KW_OS)) 26787b25dccaSJustin Hibbits pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2679169dd953SJustin Hibbits else if (KWMATCH(p, POWERPC_KW_USR)) 26807b25dccaSJustin Hibbits pmc_config->pm_caps |= PMC_CAP_USER; 2681169dd953SJustin Hibbits else if (KWMATCH(p, POWERPC_KW_ANYTHREAD)) 26827b25dccaSJustin Hibbits pmc_config->pm_caps |= (PMC_CAP_USER | PMC_CAP_SYSTEM); 26837b25dccaSJustin Hibbits else 26847b25dccaSJustin Hibbits return (-1); 26857b25dccaSJustin Hibbits } 26867b25dccaSJustin Hibbits 26877b25dccaSJustin Hibbits return (0); 26887b25dccaSJustin Hibbits } 2689169dd953SJustin Hibbits 26907b25dccaSJustin Hibbits #endif /* __powerpc__ */ 26917b25dccaSJustin Hibbits 2692660df75eSGeorge V. Neville-Neil 2693789140c0SJoseph Koshy /* 2694789140c0SJoseph Koshy * Match an event name `name' with its canonical form. 2695789140c0SJoseph Koshy * 26960cfab8ddSJoseph Koshy * Matches are case insensitive and spaces, periods, underscores and 26970cfab8ddSJoseph Koshy * hyphen characters are considered to match each other. 2698789140c0SJoseph Koshy * 2699789140c0SJoseph Koshy * Returns 1 for a match, 0 otherwise. 2700789140c0SJoseph Koshy */ 2701789140c0SJoseph Koshy 2702789140c0SJoseph Koshy static int 2703789140c0SJoseph Koshy pmc_match_event_name(const char *name, const char *canonicalname) 2704789140c0SJoseph Koshy { 2705789140c0SJoseph Koshy int cc, nc; 2706789140c0SJoseph Koshy const unsigned char *c, *n; 2707789140c0SJoseph Koshy 2708789140c0SJoseph Koshy c = (const unsigned char *) canonicalname; 2709789140c0SJoseph Koshy n = (const unsigned char *) name; 2710789140c0SJoseph Koshy 2711789140c0SJoseph Koshy for (; (nc = *n) && (cc = *c); n++, c++) { 2712789140c0SJoseph Koshy 27130cfab8ddSJoseph Koshy if ((nc == ' ' || nc == '_' || nc == '-' || nc == '.') && 27140cfab8ddSJoseph Koshy (cc == ' ' || cc == '_' || cc == '-' || cc == '.')) 2715789140c0SJoseph Koshy continue; 2716789140c0SJoseph Koshy 27170cfab8ddSJoseph Koshy if (toupper(nc) == toupper(cc)) 2718789140c0SJoseph Koshy continue; 2719789140c0SJoseph Koshy 27200cfab8ddSJoseph Koshy 2721789140c0SJoseph Koshy return (0); 2722789140c0SJoseph Koshy } 2723789140c0SJoseph Koshy 2724789140c0SJoseph Koshy if (*n == '\0' && *c == '\0') 2725789140c0SJoseph Koshy return (1); 2726789140c0SJoseph Koshy 2727789140c0SJoseph Koshy return (0); 2728789140c0SJoseph Koshy } 2729789140c0SJoseph Koshy 2730789140c0SJoseph Koshy /* 2731789140c0SJoseph Koshy * Match an event name against all the event named supported by a 2732789140c0SJoseph Koshy * PMC class. 2733789140c0SJoseph Koshy * 2734789140c0SJoseph Koshy * Returns an event descriptor pointer on match or NULL otherwise. 2735789140c0SJoseph Koshy */ 2736789140c0SJoseph Koshy static const struct pmc_event_descr * 2737789140c0SJoseph Koshy pmc_match_event_class(const char *name, 2738789140c0SJoseph Koshy const struct pmc_class_descr *pcd) 2739789140c0SJoseph Koshy { 2740789140c0SJoseph Koshy size_t n; 2741789140c0SJoseph Koshy const struct pmc_event_descr *ev; 2742789140c0SJoseph Koshy 2743789140c0SJoseph Koshy ev = pcd->pm_evc_event_table; 2744789140c0SJoseph Koshy for (n = 0; n < pcd->pm_evc_event_table_size; n++, ev++) 2745789140c0SJoseph Koshy if (pmc_match_event_name(name, ev->pm_ev_name)) 2746789140c0SJoseph Koshy return (ev); 2747789140c0SJoseph Koshy 2748789140c0SJoseph Koshy return (NULL); 2749789140c0SJoseph Koshy } 2750789140c0SJoseph Koshy 2751789140c0SJoseph Koshy static int 2752789140c0SJoseph Koshy pmc_mdep_is_compatible_class(enum pmc_class pc) 2753789140c0SJoseph Koshy { 2754789140c0SJoseph Koshy size_t n; 2755789140c0SJoseph Koshy 2756789140c0SJoseph Koshy for (n = 0; n < pmc_mdep_class_list_size; n++) 2757789140c0SJoseph Koshy if (pmc_mdep_class_list[n] == pc) 2758789140c0SJoseph Koshy return (1); 2759789140c0SJoseph Koshy return (0); 2760789140c0SJoseph Koshy } 2761789140c0SJoseph Koshy 2762ebccf1e3SJoseph Koshy /* 2763ebccf1e3SJoseph Koshy * API entry points 2764ebccf1e3SJoseph Koshy */ 2765ebccf1e3SJoseph Koshy 2766ebccf1e3SJoseph Koshy int 2767ebccf1e3SJoseph Koshy pmc_allocate(const char *ctrspec, enum pmc_mode mode, 2768ebccf1e3SJoseph Koshy uint32_t flags, int cpu, pmc_id_t *pmcid) 2769ebccf1e3SJoseph Koshy { 2770789140c0SJoseph Koshy size_t n; 2771ebccf1e3SJoseph Koshy int retval; 2772ebccf1e3SJoseph Koshy char *r, *spec_copy; 2773ebccf1e3SJoseph Koshy const char *ctrname; 2774789140c0SJoseph Koshy const struct pmc_event_descr *ev; 2775789140c0SJoseph Koshy const struct pmc_event_alias *alias; 2776ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate pmc_config; 2777789140c0SJoseph Koshy const struct pmc_class_descr *pcd; 2778ebccf1e3SJoseph Koshy 2779ebccf1e3SJoseph Koshy spec_copy = NULL; 2780ebccf1e3SJoseph Koshy retval = -1; 2781ebccf1e3SJoseph Koshy 2782ebccf1e3SJoseph Koshy if (mode != PMC_MODE_SS && mode != PMC_MODE_TS && 2783ebccf1e3SJoseph Koshy mode != PMC_MODE_SC && mode != PMC_MODE_TC) { 2784*4f9b4ac4SEric van Gyzen errno = EINVAL; 2785*4f9b4ac4SEric van Gyzen goto out; 2786959826caSMatt Macy } 2787959826caSMatt Macy bzero(&pmc_config, sizeof(pmc_config)); 2788959826caSMatt Macy pmc_config.pm_cpu = cpu; 2789959826caSMatt Macy pmc_config.pm_mode = mode; 2790959826caSMatt Macy pmc_config.pm_flags = flags; 2791959826caSMatt Macy if (PMC_IS_SAMPLING_MODE(mode)) 2792959826caSMatt Macy pmc_config.pm_caps |= PMC_CAP_INTERRUPT; 2793959826caSMatt Macy /* 2794959826caSMatt Macy * Can we pull this straight from the pmu table? 2795959826caSMatt Macy */ 2796959826caSMatt Macy r = spec_copy = strdup(ctrspec); 2797959826caSMatt Macy ctrname = strsep(&r, ","); 2798959826caSMatt Macy if (pmc_pmu_pmcallocate(ctrname, &pmc_config) == 0) { 2799ed50b918SMatt Macy if (PMC_CALL(PMCALLOCATE, &pmc_config) < 0) { 2800ed50b918SMatt Macy goto out; 2801ed50b918SMatt Macy } 28021a32aa0fSMatt Macy retval = 0; 2803959826caSMatt Macy *pmcid = pmc_config.pm_pmcid; 2804ed50b918SMatt Macy goto out; 2805959826caSMatt Macy } else { 2806959826caSMatt Macy free(spec_copy); 2807959826caSMatt Macy spec_copy = NULL; 2808ebccf1e3SJoseph Koshy } 2809ebccf1e3SJoseph Koshy 2810ebccf1e3SJoseph Koshy /* replace an event alias with the canonical event specifier */ 2811ebccf1e3SJoseph Koshy if (pmc_mdep_event_aliases) 2812789140c0SJoseph Koshy for (alias = pmc_mdep_event_aliases; alias->pm_alias; alias++) 2813789140c0SJoseph Koshy if (!strcasecmp(ctrspec, alias->pm_alias)) { 2814789140c0SJoseph Koshy spec_copy = strdup(alias->pm_spec); 2815ebccf1e3SJoseph Koshy break; 2816ebccf1e3SJoseph Koshy } 2817ebccf1e3SJoseph Koshy 2818ebccf1e3SJoseph Koshy if (spec_copy == NULL) 2819ebccf1e3SJoseph Koshy spec_copy = strdup(ctrspec); 2820ebccf1e3SJoseph Koshy 2821ebccf1e3SJoseph Koshy r = spec_copy; 2822ebccf1e3SJoseph Koshy ctrname = strsep(&r, ","); 2823ebccf1e3SJoseph Koshy 2824789140c0SJoseph Koshy /* 2825789140c0SJoseph Koshy * If a explicit class prefix was given by the user, restrict the 2826789140c0SJoseph Koshy * search for the event to the specified PMC class. 2827789140c0SJoseph Koshy */ 2828789140c0SJoseph Koshy ev = NULL; 28290cfab8ddSJoseph Koshy for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) { 28300cfab8ddSJoseph Koshy pcd = pmc_class_table[n]; 2831789140c0SJoseph Koshy if (pmc_mdep_is_compatible_class(pcd->pm_evc_class) && 2832789140c0SJoseph Koshy strncasecmp(ctrname, pcd->pm_evc_name, 2833789140c0SJoseph Koshy pcd->pm_evc_name_size) == 0) { 2834789140c0SJoseph Koshy if ((ev = pmc_match_event_class(ctrname + 2835789140c0SJoseph Koshy pcd->pm_evc_name_size, pcd)) == NULL) { 2836789140c0SJoseph Koshy errno = EINVAL; 2837789140c0SJoseph Koshy goto out; 2838789140c0SJoseph Koshy } 2839ebccf1e3SJoseph Koshy break; 2840789140c0SJoseph Koshy } 2841789140c0SJoseph Koshy } 2842ebccf1e3SJoseph Koshy 2843789140c0SJoseph Koshy /* 2844789140c0SJoseph Koshy * Otherwise, search for this event in all compatible PMC 2845789140c0SJoseph Koshy * classes. 2846789140c0SJoseph Koshy */ 28470cfab8ddSJoseph Koshy for (n = 0; ev == NULL && n < PMC_CLASS_TABLE_SIZE; n++) { 28480cfab8ddSJoseph Koshy pcd = pmc_class_table[n]; 2849789140c0SJoseph Koshy if (pmc_mdep_is_compatible_class(pcd->pm_evc_class)) 2850789140c0SJoseph Koshy ev = pmc_match_event_class(ctrname, pcd); 2851789140c0SJoseph Koshy } 2852789140c0SJoseph Koshy 2853789140c0SJoseph Koshy if (ev == NULL) { 2854ebccf1e3SJoseph Koshy errno = EINVAL; 2855ebccf1e3SJoseph Koshy goto out; 2856ebccf1e3SJoseph Koshy } 2857ebccf1e3SJoseph Koshy 2858789140c0SJoseph Koshy pmc_config.pm_ev = ev->pm_ev_code; 2859789140c0SJoseph Koshy pmc_config.pm_class = pcd->pm_evc_class; 2860ebccf1e3SJoseph Koshy 2861789140c0SJoseph Koshy if (pcd->pm_evc_allocate_pmc(ev->pm_ev_code, r, &pmc_config) < 0) { 2862ebccf1e3SJoseph Koshy errno = EINVAL; 2863ebccf1e3SJoseph Koshy goto out; 2864ebccf1e3SJoseph Koshy } 2865ebccf1e3SJoseph Koshy 2866ebccf1e3SJoseph Koshy if (PMC_CALL(PMCALLOCATE, &pmc_config) < 0) 2867ebccf1e3SJoseph Koshy goto out; 2868ebccf1e3SJoseph Koshy 2869ebccf1e3SJoseph Koshy *pmcid = pmc_config.pm_pmcid; 2870ebccf1e3SJoseph Koshy 2871ebccf1e3SJoseph Koshy retval = 0; 2872ebccf1e3SJoseph Koshy 2873ebccf1e3SJoseph Koshy out: 2874ebccf1e3SJoseph Koshy if (spec_copy) 2875ebccf1e3SJoseph Koshy free(spec_copy); 2876ebccf1e3SJoseph Koshy 2877aa342b1fSJoseph Koshy return (retval); 2878ebccf1e3SJoseph Koshy } 2879ebccf1e3SJoseph Koshy 2880ebccf1e3SJoseph Koshy int 2881ebccf1e3SJoseph Koshy pmc_attach(pmc_id_t pmc, pid_t pid) 2882ebccf1e3SJoseph Koshy { 2883ebccf1e3SJoseph Koshy struct pmc_op_pmcattach pmc_attach_args; 2884ebccf1e3SJoseph Koshy 2885ebccf1e3SJoseph Koshy pmc_attach_args.pm_pmc = pmc; 2886ebccf1e3SJoseph Koshy pmc_attach_args.pm_pid = pid; 2887ebccf1e3SJoseph Koshy 2888aa342b1fSJoseph Koshy return (PMC_CALL(PMCATTACH, &pmc_attach_args)); 2889ebccf1e3SJoseph Koshy } 2890ebccf1e3SJoseph Koshy 2891ebccf1e3SJoseph Koshy int 2892c5153e19SJoseph Koshy pmc_capabilities(pmc_id_t pmcid, uint32_t *caps) 2893c5153e19SJoseph Koshy { 2894c5153e19SJoseph Koshy unsigned int i; 2895c5153e19SJoseph Koshy enum pmc_class cl; 2896c5153e19SJoseph Koshy 2897c5153e19SJoseph Koshy cl = PMC_ID_TO_CLASS(pmcid); 2898c5153e19SJoseph Koshy for (i = 0; i < cpu_info.pm_nclass; i++) 2899c5153e19SJoseph Koshy if (cpu_info.pm_classes[i].pm_class == cl) { 2900c5153e19SJoseph Koshy *caps = cpu_info.pm_classes[i].pm_caps; 2901aa342b1fSJoseph Koshy return (0); 2902c5153e19SJoseph Koshy } 2903484202faSJoseph Koshy errno = EINVAL; 2904484202faSJoseph Koshy return (-1); 2905c5153e19SJoseph Koshy } 2906c5153e19SJoseph Koshy 2907f263522aSJoseph Koshy int 2908f263522aSJoseph Koshy pmc_configure_logfile(int fd) 2909ebccf1e3SJoseph Koshy { 2910f263522aSJoseph Koshy struct pmc_op_configurelog cla; 2911f263522aSJoseph Koshy 2912f263522aSJoseph Koshy cla.pm_logfd = fd; 2913f263522aSJoseph Koshy if (PMC_CALL(CONFIGURELOG, &cla) < 0) 2914aa342b1fSJoseph Koshy return (-1); 2915aa342b1fSJoseph Koshy return (0); 2916ebccf1e3SJoseph Koshy } 2917ebccf1e3SJoseph Koshy 2918f263522aSJoseph Koshy int 2919f263522aSJoseph Koshy pmc_cpuinfo(const struct pmc_cpuinfo **pci) 2920ebccf1e3SJoseph Koshy { 2921f263522aSJoseph Koshy if (pmc_syscall == -1) { 2922f263522aSJoseph Koshy errno = ENXIO; 2923aa342b1fSJoseph Koshy return (-1); 2924ebccf1e3SJoseph Koshy } 2925ebccf1e3SJoseph Koshy 29261455fcd3SJoseph Koshy *pci = &cpu_info; 2927aa342b1fSJoseph Koshy return (0); 2928ebccf1e3SJoseph Koshy } 2929ebccf1e3SJoseph Koshy 2930f263522aSJoseph Koshy int 2931f263522aSJoseph Koshy pmc_detach(pmc_id_t pmc, pid_t pid) 2932ebccf1e3SJoseph Koshy { 2933f263522aSJoseph Koshy struct pmc_op_pmcattach pmc_detach_args; 2934ebccf1e3SJoseph Koshy 2935f263522aSJoseph Koshy pmc_detach_args.pm_pmc = pmc; 2936f263522aSJoseph Koshy pmc_detach_args.pm_pid = pid; 2937aa342b1fSJoseph Koshy return (PMC_CALL(PMCDETACH, &pmc_detach_args)); 2938ebccf1e3SJoseph Koshy } 2939ebccf1e3SJoseph Koshy 2940f263522aSJoseph Koshy int 2941f263522aSJoseph Koshy pmc_disable(int cpu, int pmc) 2942ebccf1e3SJoseph Koshy { 2943f263522aSJoseph Koshy struct pmc_op_pmcadmin ssa; 2944ebccf1e3SJoseph Koshy 2945f263522aSJoseph Koshy ssa.pm_cpu = cpu; 2946f263522aSJoseph Koshy ssa.pm_pmc = pmc; 2947f263522aSJoseph Koshy ssa.pm_state = PMC_STATE_DISABLED; 2948aa342b1fSJoseph Koshy return (PMC_CALL(PMCADMIN, &ssa)); 2949ebccf1e3SJoseph Koshy } 2950ebccf1e3SJoseph Koshy 2951f263522aSJoseph Koshy int 2952f263522aSJoseph Koshy pmc_enable(int cpu, int pmc) 2953ebccf1e3SJoseph Koshy { 2954f263522aSJoseph Koshy struct pmc_op_pmcadmin ssa; 2955ebccf1e3SJoseph Koshy 2956f263522aSJoseph Koshy ssa.pm_cpu = cpu; 2957f263522aSJoseph Koshy ssa.pm_pmc = pmc; 2958f263522aSJoseph Koshy ssa.pm_state = PMC_STATE_FREE; 2959aa342b1fSJoseph Koshy return (PMC_CALL(PMCADMIN, &ssa)); 2960ebccf1e3SJoseph Koshy } 2961ebccf1e3SJoseph Koshy 2962ebccf1e3SJoseph Koshy /* 2963ebccf1e3SJoseph Koshy * Return a list of events known to a given PMC class. 'cl' is the 2964ebccf1e3SJoseph Koshy * PMC class identifier, 'eventnames' is the returned list of 'const 2965ebccf1e3SJoseph Koshy * char *' pointers pointing to the names of the events. 'nevents' is 2966ebccf1e3SJoseph Koshy * the number of event name pointers returned. 2967ebccf1e3SJoseph Koshy * 2968ebccf1e3SJoseph Koshy * The space for 'eventnames' is allocated using malloc(3). The caller 2969ebccf1e3SJoseph Koshy * is responsible for freeing this space when done. 2970ebccf1e3SJoseph Koshy */ 2971ebccf1e3SJoseph Koshy int 2972ebccf1e3SJoseph Koshy pmc_event_names_of_class(enum pmc_class cl, const char ***eventnames, 2973ebccf1e3SJoseph Koshy int *nevents) 2974ebccf1e3SJoseph Koshy { 2975ebccf1e3SJoseph Koshy int count; 2976ebccf1e3SJoseph Koshy const char **names; 2977ebccf1e3SJoseph Koshy const struct pmc_event_descr *ev; 2978ebccf1e3SJoseph Koshy 2979ebccf1e3SJoseph Koshy switch (cl) 2980ebccf1e3SJoseph Koshy { 29810cfab8ddSJoseph Koshy case PMC_CLASS_IAF: 29820cfab8ddSJoseph Koshy ev = iaf_event_table; 29830cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(iaf); 29840cfab8ddSJoseph Koshy break; 29850cfab8ddSJoseph Koshy case PMC_CLASS_IAP: 29860cfab8ddSJoseph Koshy /* 29870cfab8ddSJoseph Koshy * Return the most appropriate set of event name 29880cfab8ddSJoseph Koshy * spellings for the current CPU. 29890cfab8ddSJoseph Koshy */ 29900cfab8ddSJoseph Koshy switch (cpu_info.pm_cputype) { 29910cfab8ddSJoseph Koshy default: 29920cfab8ddSJoseph Koshy case PMC_CPU_INTEL_ATOM: 29930cfab8ddSJoseph Koshy ev = atom_event_table; 29940cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(atom); 29950cfab8ddSJoseph Koshy break; 2996e8f021a3SHiren Panchasara case PMC_CPU_INTEL_ATOM_SILVERMONT: 2997e8f021a3SHiren Panchasara ev = atom_silvermont_event_table; 2998e8f021a3SHiren Panchasara count = PMC_EVENT_TABLE_SIZE(atom_silvermont); 2999e8f021a3SHiren Panchasara break; 30000cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE: 30010cfab8ddSJoseph Koshy ev = core_event_table; 30020cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(core); 30030cfab8ddSJoseph Koshy break; 30040cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE2: 3005b4d091f3SJoseph Koshy case PMC_CPU_INTEL_CORE2EXTREME: 30060cfab8ddSJoseph Koshy ev = core2_event_table; 30070cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(core2); 30080cfab8ddSJoseph Koshy break; 3009597979c4SJeff Roberson case PMC_CPU_INTEL_COREI7: 3010597979c4SJeff Roberson ev = corei7_event_table; 3011597979c4SJeff Roberson count = PMC_EVENT_TABLE_SIZE(corei7); 3012597979c4SJeff Roberson break; 301349fe48abSKonstantin Belousov case PMC_CPU_INTEL_NEHALEM_EX: 301449fe48abSKonstantin Belousov ev = nehalem_ex_event_table; 301549fe48abSKonstantin Belousov count = PMC_EVENT_TABLE_SIZE(nehalem_ex); 301649fe48abSKonstantin Belousov break; 3017cc0c1555SSean Bruno case PMC_CPU_INTEL_HASWELL: 3018cc0c1555SSean Bruno ev = haswell_event_table; 3019cc0c1555SSean Bruno count = PMC_EVENT_TABLE_SIZE(haswell); 3020cc0c1555SSean Bruno break; 3021d95b3509SRandall Stewart case PMC_CPU_INTEL_HASWELL_XEON: 3022d95b3509SRandall Stewart ev = haswell_xeon_event_table; 3023d95b3509SRandall Stewart count = PMC_EVENT_TABLE_SIZE(haswell_xeon); 3024d95b3509SRandall Stewart break; 3025f19bae41SRandall Stewart case PMC_CPU_INTEL_BROADWELL: 3026f19bae41SRandall Stewart ev = broadwell_event_table; 3027f19bae41SRandall Stewart count = PMC_EVENT_TABLE_SIZE(broadwell); 3028f19bae41SRandall Stewart break; 3029f19bae41SRandall Stewart case PMC_CPU_INTEL_BROADWELL_XEON: 3030f19bae41SRandall Stewart ev = broadwell_xeon_event_table; 3031f19bae41SRandall Stewart count = PMC_EVENT_TABLE_SIZE(broadwell_xeon); 3032f19bae41SRandall Stewart break; 3033f19bae41SRandall Stewart case PMC_CPU_INTEL_SKYLAKE: 3034f19bae41SRandall Stewart ev = skylake_event_table; 3035f19bae41SRandall Stewart count = PMC_EVENT_TABLE_SIZE(skylake); 3036f19bae41SRandall Stewart break; 3037b99b705dSKonstantin Belousov case PMC_CPU_INTEL_SKYLAKE_XEON: 3038b99b705dSKonstantin Belousov ev = skylake_xeon_event_table; 3039b99b705dSKonstantin Belousov count = PMC_EVENT_TABLE_SIZE(skylake_xeon); 3040b99b705dSKonstantin Belousov break; 30411e862e5aSFabien Thomas case PMC_CPU_INTEL_IVYBRIDGE: 30421e862e5aSFabien Thomas ev = ivybridge_event_table; 30431e862e5aSFabien Thomas count = PMC_EVENT_TABLE_SIZE(ivybridge); 30441e862e5aSFabien Thomas break; 30453f929d8cSSean Bruno case PMC_CPU_INTEL_IVYBRIDGE_XEON: 30463f929d8cSSean Bruno ev = ivybridge_xeon_event_table; 30473f929d8cSSean Bruno count = PMC_EVENT_TABLE_SIZE(ivybridge_xeon); 30483f929d8cSSean Bruno break; 304978d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 305078d763a2SDavide Italiano ev = sandybridge_event_table; 305178d763a2SDavide Italiano count = PMC_EVENT_TABLE_SIZE(sandybridge); 305278d763a2SDavide Italiano break; 3053fabe02f5SSean Bruno case PMC_CPU_INTEL_SANDYBRIDGE_XEON: 3054fabe02f5SSean Bruno ev = sandybridge_xeon_event_table; 3055fabe02f5SSean Bruno count = PMC_EVENT_TABLE_SIZE(sandybridge_xeon); 3056fabe02f5SSean Bruno break; 30571fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 30581fa7f10bSFabien Thomas ev = westmere_event_table; 30591fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(westmere); 30601fa7f10bSFabien Thomas break; 306149fe48abSKonstantin Belousov case PMC_CPU_INTEL_WESTMERE_EX: 306249fe48abSKonstantin Belousov ev = westmere_ex_event_table; 306349fe48abSKonstantin Belousov count = PMC_EVENT_TABLE_SIZE(westmere_ex); 306449fe48abSKonstantin Belousov break; 30651fa7f10bSFabien Thomas } 30661fa7f10bSFabien Thomas break; 30671fa7f10bSFabien Thomas case PMC_CLASS_UCF: 30681fa7f10bSFabien Thomas ev = ucf_event_table; 30691fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(ucf); 30701fa7f10bSFabien Thomas break; 30711fa7f10bSFabien Thomas case PMC_CLASS_UCP: 30721fa7f10bSFabien Thomas /* 30731fa7f10bSFabien Thomas * Return the most appropriate set of event name 30741fa7f10bSFabien Thomas * spellings for the current CPU. 30751fa7f10bSFabien Thomas */ 30761fa7f10bSFabien Thomas switch (cpu_info.pm_cputype) { 30771fa7f10bSFabien Thomas default: 30781fa7f10bSFabien Thomas case PMC_CPU_INTEL_COREI7: 30791fa7f10bSFabien Thomas ev = corei7uc_event_table; 30801fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(corei7uc); 30811fa7f10bSFabien Thomas break; 3082cc0c1555SSean Bruno case PMC_CPU_INTEL_HASWELL: 3083cc0c1555SSean Bruno ev = haswelluc_event_table; 3084cc0c1555SSean Bruno count = PMC_EVENT_TABLE_SIZE(haswelluc); 3085cc0c1555SSean Bruno break; 3086f19bae41SRandall Stewart case PMC_CPU_INTEL_BROADWELL: 3087f19bae41SRandall Stewart ev = broadwelluc_event_table; 3088f19bae41SRandall Stewart count = PMC_EVENT_TABLE_SIZE(broadwelluc); 3089f19bae41SRandall Stewart break; 309078d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 309178d763a2SDavide Italiano ev = sandybridgeuc_event_table; 309278d763a2SDavide Italiano count = PMC_EVENT_TABLE_SIZE(sandybridgeuc); 309378d763a2SDavide Italiano break; 30941fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 30951fa7f10bSFabien Thomas ev = westmereuc_event_table; 30961fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(westmereuc); 30971fa7f10bSFabien Thomas break; 30980cfab8ddSJoseph Koshy } 30990cfab8ddSJoseph Koshy break; 3100ebccf1e3SJoseph Koshy case PMC_CLASS_TSC: 3101789140c0SJoseph Koshy ev = tsc_event_table; 3102789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(tsc); 3103ebccf1e3SJoseph Koshy break; 3104ebccf1e3SJoseph Koshy case PMC_CLASS_K7: 3105789140c0SJoseph Koshy ev = k7_event_table; 3106789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(k7); 3107ebccf1e3SJoseph Koshy break; 3108ebccf1e3SJoseph Koshy case PMC_CLASS_K8: 3109789140c0SJoseph Koshy ev = k8_event_table; 3110789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(k8); 3111ebccf1e3SJoseph Koshy break; 3112ebccf1e3SJoseph Koshy case PMC_CLASS_P4: 3113789140c0SJoseph Koshy ev = p4_event_table; 3114789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p4); 3115789140c0SJoseph Koshy break; 3116789140c0SJoseph Koshy case PMC_CLASS_P5: 3117789140c0SJoseph Koshy ev = p5_event_table; 3118789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p5); 3119789140c0SJoseph Koshy break; 3120789140c0SJoseph Koshy case PMC_CLASS_P6: 3121789140c0SJoseph Koshy ev = p6_event_table; 3122789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p6); 3123ebccf1e3SJoseph Koshy break; 31240ce207d2SRui Paulo case PMC_CLASS_XSCALE: 31250ce207d2SRui Paulo ev = xscale_event_table; 31260ce207d2SRui Paulo count = PMC_EVENT_TABLE_SIZE(xscale); 31270ce207d2SRui Paulo break; 31286411d14dSRuslan Bukin case PMC_CLASS_ARMV7: 31293e0bfdd8SRuslan Bukin switch (cpu_info.pm_cputype) { 31303e0bfdd8SRuslan Bukin default: 31313e0bfdd8SRuslan Bukin case PMC_CPU_ARMV7_CORTEX_A8: 31323e0bfdd8SRuslan Bukin ev = cortex_a8_event_table; 31333e0bfdd8SRuslan Bukin count = PMC_EVENT_TABLE_SIZE(cortex_a8); 31343e0bfdd8SRuslan Bukin break; 31353e0bfdd8SRuslan Bukin case PMC_CPU_ARMV7_CORTEX_A9: 31363e0bfdd8SRuslan Bukin ev = cortex_a9_event_table; 31373e0bfdd8SRuslan Bukin count = PMC_EVENT_TABLE_SIZE(cortex_a9); 31383e0bfdd8SRuslan Bukin break; 31393e0bfdd8SRuslan Bukin } 31406411d14dSRuslan Bukin break; 3141bc88bb2bSRuslan Bukin case PMC_CLASS_ARMV8: 3142bc88bb2bSRuslan Bukin switch (cpu_info.pm_cputype) { 3143bc88bb2bSRuslan Bukin default: 3144bc88bb2bSRuslan Bukin case PMC_CPU_ARMV8_CORTEX_A53: 3145bc88bb2bSRuslan Bukin ev = cortex_a53_event_table; 3146bc88bb2bSRuslan Bukin count = PMC_EVENT_TABLE_SIZE(cortex_a53); 3147bc88bb2bSRuslan Bukin break; 3148bc88bb2bSRuslan Bukin case PMC_CPU_ARMV8_CORTEX_A57: 3149bc88bb2bSRuslan Bukin ev = cortex_a57_event_table; 3150bc88bb2bSRuslan Bukin count = PMC_EVENT_TABLE_SIZE(cortex_a57); 3151bc88bb2bSRuslan Bukin break; 3152bc88bb2bSRuslan Bukin } 3153bc88bb2bSRuslan Bukin break; 3154660df75eSGeorge V. Neville-Neil case PMC_CLASS_MIPS24K: 3155660df75eSGeorge V. Neville-Neil ev = mips24k_event_table; 3156660df75eSGeorge V. Neville-Neil count = PMC_EVENT_TABLE_SIZE(mips24k); 3157660df75eSGeorge V. Neville-Neil break; 3158f6e6460dSAdrian Chadd case PMC_CLASS_MIPS74K: 3159f6e6460dSAdrian Chadd ev = mips74k_event_table; 3160f6e6460dSAdrian Chadd count = PMC_EVENT_TABLE_SIZE(mips74k); 3161f6e6460dSAdrian Chadd break; 3162c2657f80SOleksandr Tymoshenko case PMC_CLASS_OCTEON: 3163c2657f80SOleksandr Tymoshenko ev = octeon_event_table; 3164c2657f80SOleksandr Tymoshenko count = PMC_EVENT_TABLE_SIZE(octeon); 3165c2657f80SOleksandr Tymoshenko break; 31667b25dccaSJustin Hibbits case PMC_CLASS_PPC7450: 31677b25dccaSJustin Hibbits ev = ppc7450_event_table; 31687b25dccaSJustin Hibbits count = PMC_EVENT_TABLE_SIZE(ppc7450); 31697b25dccaSJustin Hibbits break; 3170169dd953SJustin Hibbits case PMC_CLASS_PPC970: 3171169dd953SJustin Hibbits ev = ppc970_event_table; 3172169dd953SJustin Hibbits count = PMC_EVENT_TABLE_SIZE(ppc970); 3173169dd953SJustin Hibbits break; 3174a7452468SJustin Hibbits case PMC_CLASS_E500: 3175a7452468SJustin Hibbits ev = e500_event_table; 3176a7452468SJustin Hibbits count = PMC_EVENT_TABLE_SIZE(e500); 3177a7452468SJustin Hibbits break; 3178f5f9340bSFabien Thomas case PMC_CLASS_SOFT: 3179f5f9340bSFabien Thomas ev = soft_event_table; 3180f5f9340bSFabien Thomas count = soft_event_info.pm_nevent; 3181f5f9340bSFabien Thomas break; 3182ebccf1e3SJoseph Koshy default: 3183ebccf1e3SJoseph Koshy errno = EINVAL; 3184aa342b1fSJoseph Koshy return (-1); 3185ebccf1e3SJoseph Koshy } 3186ebccf1e3SJoseph Koshy 3187ebccf1e3SJoseph Koshy if ((names = malloc(count * sizeof(const char *))) == NULL) 3188aa342b1fSJoseph Koshy return (-1); 3189ebccf1e3SJoseph Koshy 3190ebccf1e3SJoseph Koshy *eventnames = names; 3191ebccf1e3SJoseph Koshy *nevents = count; 3192ebccf1e3SJoseph Koshy 3193ebccf1e3SJoseph Koshy for (;count--; ev++, names++) 3194ebccf1e3SJoseph Koshy *names = ev->pm_ev_name; 3195f5f9340bSFabien Thomas 3196aa342b1fSJoseph Koshy return (0); 3197ebccf1e3SJoseph Koshy } 3198ebccf1e3SJoseph Koshy 3199f263522aSJoseph Koshy int 3200f263522aSJoseph Koshy pmc_flush_logfile(void) 3201f263522aSJoseph Koshy { 3202aa342b1fSJoseph Koshy return (PMC_CALL(FLUSHLOG,0)); 3203f263522aSJoseph Koshy } 3204ebccf1e3SJoseph Koshy 3205ebccf1e3SJoseph Koshy int 3206dceed24aSFabien Thomas pmc_close_logfile(void) 3207dceed24aSFabien Thomas { 3208dceed24aSFabien Thomas return (PMC_CALL(CLOSELOG,0)); 3209dceed24aSFabien Thomas } 3210dceed24aSFabien Thomas 3211dceed24aSFabien Thomas int 3212f263522aSJoseph Koshy pmc_get_driver_stats(struct pmc_driverstats *ds) 3213ebccf1e3SJoseph Koshy { 3214f263522aSJoseph Koshy struct pmc_op_getdriverstats gms; 3215f263522aSJoseph Koshy 3216f263522aSJoseph Koshy if (PMC_CALL(GETDRIVERSTATS, &gms) < 0) 3217aa342b1fSJoseph Koshy return (-1); 3218f263522aSJoseph Koshy 3219f263522aSJoseph Koshy /* copy out fields in the current userland<->library interface */ 3220f263522aSJoseph Koshy ds->pm_intr_ignored = gms.pm_intr_ignored; 3221f263522aSJoseph Koshy ds->pm_intr_processed = gms.pm_intr_processed; 3222f263522aSJoseph Koshy ds->pm_intr_bufferfull = gms.pm_intr_bufferfull; 3223f263522aSJoseph Koshy ds->pm_syscalls = gms.pm_syscalls; 3224f263522aSJoseph Koshy ds->pm_syscall_errors = gms.pm_syscall_errors; 3225f263522aSJoseph Koshy ds->pm_buffer_requests = gms.pm_buffer_requests; 3226f263522aSJoseph Koshy ds->pm_buffer_requests_failed = gms.pm_buffer_requests_failed; 3227f263522aSJoseph Koshy ds->pm_log_sweeps = gms.pm_log_sweeps; 3228aa342b1fSJoseph Koshy return (0); 3229f263522aSJoseph Koshy } 3230f263522aSJoseph Koshy 3231f263522aSJoseph Koshy int 3232f263522aSJoseph Koshy pmc_get_msr(pmc_id_t pmc, uint32_t *msr) 3233f263522aSJoseph Koshy { 3234f263522aSJoseph Koshy struct pmc_op_getmsr gm; 3235ebccf1e3SJoseph Koshy 3236ebccf1e3SJoseph Koshy gm.pm_pmcid = pmc; 3237f263522aSJoseph Koshy if (PMC_CALL(PMCGETMSR, &gm) < 0) 3238aa342b1fSJoseph Koshy return (-1); 3239ebccf1e3SJoseph Koshy *msr = gm.pm_msr; 3240aa342b1fSJoseph Koshy return (0); 3241ebccf1e3SJoseph Koshy } 3242ebccf1e3SJoseph Koshy 3243f263522aSJoseph Koshy int 3244f263522aSJoseph Koshy pmc_init(void) 3245f263522aSJoseph Koshy { 3246f263522aSJoseph Koshy int error, pmc_mod_id; 32471455fcd3SJoseph Koshy unsigned int n; 3248f263522aSJoseph Koshy uint32_t abi_version; 3249f263522aSJoseph Koshy struct module_stat pmc_modstat; 32501455fcd3SJoseph Koshy struct pmc_op_getcpuinfo op_cpu_info; 3251791f5d5bSJoseph Koshy #if defined(__amd64__) || defined(__i386__) 3252791f5d5bSJoseph Koshy int cpu_has_iaf_counters; 3253791f5d5bSJoseph Koshy unsigned int t; 3254791f5d5bSJoseph Koshy #endif 3255f263522aSJoseph Koshy 3256f263522aSJoseph Koshy if (pmc_syscall != -1) /* already inited */ 3257aa342b1fSJoseph Koshy return (0); 3258f263522aSJoseph Koshy 3259f263522aSJoseph Koshy /* retrieve the system call number from the KLD */ 3260f263522aSJoseph Koshy if ((pmc_mod_id = modfind(PMC_MODULE_NAME)) < 0) 3261aa342b1fSJoseph Koshy return (-1); 3262f263522aSJoseph Koshy 3263f263522aSJoseph Koshy pmc_modstat.version = sizeof(struct module_stat); 3264f263522aSJoseph Koshy if ((error = modstat(pmc_mod_id, &pmc_modstat)) < 0) 3265aa342b1fSJoseph Koshy return (-1); 3266f263522aSJoseph Koshy 3267f263522aSJoseph Koshy pmc_syscall = pmc_modstat.data.intval; 3268f263522aSJoseph Koshy 3269f263522aSJoseph Koshy /* check the kernel module's ABI against our compiled-in version */ 3270f263522aSJoseph Koshy abi_version = PMC_VERSION; 3271f263522aSJoseph Koshy if (PMC_CALL(GETMODULEVERSION, &abi_version) < 0) 3272f263522aSJoseph Koshy return (pmc_syscall = -1); 3273f263522aSJoseph Koshy 327475f46cf6SPedro F. Giffuni /* ignore patch & minor numbers for the comparison */ 3275f263522aSJoseph Koshy if ((abi_version & 0xFF000000) != (PMC_VERSION & 0xFF000000)) { 3276f263522aSJoseph Koshy errno = EPROGMISMATCH; 3277f263522aSJoseph Koshy return (pmc_syscall = -1); 3278f263522aSJoseph Koshy } 3279f263522aSJoseph Koshy 32801455fcd3SJoseph Koshy if (PMC_CALL(GETCPUINFO, &op_cpu_info) < 0) 3281f263522aSJoseph Koshy return (pmc_syscall = -1); 3282f263522aSJoseph Koshy 32831455fcd3SJoseph Koshy cpu_info.pm_cputype = op_cpu_info.pm_cputype; 32841455fcd3SJoseph Koshy cpu_info.pm_ncpu = op_cpu_info.pm_ncpu; 32851455fcd3SJoseph Koshy cpu_info.pm_npmc = op_cpu_info.pm_npmc; 32861455fcd3SJoseph Koshy cpu_info.pm_nclass = op_cpu_info.pm_nclass; 32871455fcd3SJoseph Koshy for (n = 0; n < cpu_info.pm_nclass; n++) 3288b83aeb5cSJustin Hibbits memcpy(&cpu_info.pm_classes[n], &op_cpu_info.pm_classes[n], 3289b83aeb5cSJustin Hibbits sizeof(cpu_info.pm_classes[n])); 32901455fcd3SJoseph Koshy 32910cfab8ddSJoseph Koshy pmc_class_table = malloc(PMC_CLASS_TABLE_SIZE * 32920cfab8ddSJoseph Koshy sizeof(struct pmc_class_descr *)); 32930cfab8ddSJoseph Koshy 32940cfab8ddSJoseph Koshy if (pmc_class_table == NULL) 32950cfab8ddSJoseph Koshy return (-1); 32960cfab8ddSJoseph Koshy 3297791f5d5bSJoseph Koshy for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) 3298791f5d5bSJoseph Koshy pmc_class_table[n] = NULL; 32990cfab8ddSJoseph Koshy 33000cfab8ddSJoseph Koshy /* 3301f5f9340bSFabien Thomas * Get soft events list. 3302f5f9340bSFabien Thomas */ 3303f5f9340bSFabien Thomas soft_event_info.pm_class = PMC_CLASS_SOFT; 3304f5f9340bSFabien Thomas if (PMC_CALL(GETDYNEVENTINFO, &soft_event_info) < 0) 3305f5f9340bSFabien Thomas return (pmc_syscall = -1); 3306f5f9340bSFabien Thomas 3307f5f9340bSFabien Thomas /* Map soft events to static list. */ 3308f5f9340bSFabien Thomas for (n = 0; n < soft_event_info.pm_nevent; n++) { 3309f5f9340bSFabien Thomas soft_event_table[n].pm_ev_name = 3310f5f9340bSFabien Thomas soft_event_info.pm_events[n].pm_ev_name; 3311f5f9340bSFabien Thomas soft_event_table[n].pm_ev_code = 3312f5f9340bSFabien Thomas soft_event_info.pm_events[n].pm_ev_code; 3313f5f9340bSFabien Thomas } 3314f5f9340bSFabien Thomas soft_class_table_descr.pm_evc_event_table_size = \ 3315f5f9340bSFabien Thomas soft_event_info.pm_nevent; 3316f5f9340bSFabien Thomas soft_class_table_descr.pm_evc_event_table = \ 3317f5f9340bSFabien Thomas soft_event_table; 3318f5f9340bSFabien Thomas 3319f5f9340bSFabien Thomas /* 33200cfab8ddSJoseph Koshy * Fill in the class table. 33210cfab8ddSJoseph Koshy */ 33220cfab8ddSJoseph Koshy n = 0; 3323f5f9340bSFabien Thomas 3324f5f9340bSFabien Thomas /* Fill soft events information. */ 3325f5f9340bSFabien Thomas pmc_class_table[n++] = &soft_class_table_descr; 33260cfab8ddSJoseph Koshy #if defined(__amd64__) || defined(__i386__) 3327f5f9340bSFabien Thomas if (cpu_info.pm_cputype != PMC_CPU_GENERIC) 33280cfab8ddSJoseph Koshy pmc_class_table[n++] = &tsc_class_table_descr; 3329791f5d5bSJoseph Koshy 3330791f5d5bSJoseph Koshy /* 3331791f5d5bSJoseph Koshy * Check if this CPU has fixed function counters. 3332791f5d5bSJoseph Koshy */ 3333791f5d5bSJoseph Koshy cpu_has_iaf_counters = 0; 3334791f5d5bSJoseph Koshy for (t = 0; t < cpu_info.pm_nclass; t++) 33352aef9dd6SFabien Thomas if (cpu_info.pm_classes[t].pm_class == PMC_CLASS_IAF && 33362aef9dd6SFabien Thomas cpu_info.pm_classes[t].pm_num > 0) 3337791f5d5bSJoseph Koshy cpu_has_iaf_counters = 1; 33380cfab8ddSJoseph Koshy #endif 33390cfab8ddSJoseph Koshy 3340789140c0SJoseph Koshy #define PMC_MDEP_INIT(C) do { \ 3341789140c0SJoseph Koshy pmc_mdep_event_aliases = C##_aliases; \ 3342789140c0SJoseph Koshy pmc_mdep_class_list = C##_pmc_classes; \ 3343789140c0SJoseph Koshy pmc_mdep_class_list_size = \ 3344789140c0SJoseph Koshy PMC_TABLE_SIZE(C##_pmc_classes); \ 3345789140c0SJoseph Koshy } while (0) 3346789140c0SJoseph Koshy 3347791f5d5bSJoseph Koshy #define PMC_MDEP_INIT_INTEL_V2(C) do { \ 3348791f5d5bSJoseph Koshy PMC_MDEP_INIT(C); \ 3349791f5d5bSJoseph Koshy pmc_class_table[n++] = &iaf_class_table_descr; \ 33502aef9dd6SFabien Thomas if (!cpu_has_iaf_counters) \ 3351791f5d5bSJoseph Koshy pmc_mdep_event_aliases = \ 3352791f5d5bSJoseph Koshy C##_aliases_without_iaf; \ 3353791f5d5bSJoseph Koshy pmc_class_table[n] = &C##_class_table_descr; \ 3354791f5d5bSJoseph Koshy } while (0) 3355791f5d5bSJoseph Koshy 3356789140c0SJoseph Koshy /* Configure the event name parser. */ 3357f263522aSJoseph Koshy switch (cpu_info.pm_cputype) { 3358f263522aSJoseph Koshy #if defined(__i386__) 3359f263522aSJoseph Koshy case PMC_CPU_AMD_K7: 3360789140c0SJoseph Koshy PMC_MDEP_INIT(k7); 33610cfab8ddSJoseph Koshy pmc_class_table[n] = &k7_class_table_descr; 3362f263522aSJoseph Koshy break; 3363f263522aSJoseph Koshy case PMC_CPU_INTEL_P5: 3364789140c0SJoseph Koshy PMC_MDEP_INIT(p5); 33650cfab8ddSJoseph Koshy pmc_class_table[n] = &p5_class_table_descr; 3366f263522aSJoseph Koshy break; 3367f263522aSJoseph Koshy case PMC_CPU_INTEL_P6: /* P6 ... Pentium M CPUs have */ 3368f263522aSJoseph Koshy case PMC_CPU_INTEL_PII: /* similar PMCs. */ 3369f263522aSJoseph Koshy case PMC_CPU_INTEL_PIII: 3370f263522aSJoseph Koshy case PMC_CPU_INTEL_PM: 3371789140c0SJoseph Koshy PMC_MDEP_INIT(p6); 33720cfab8ddSJoseph Koshy pmc_class_table[n] = &p6_class_table_descr; 3373f263522aSJoseph Koshy break; 337486a65549SJoseph Koshy #endif 337586a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 3376f263522aSJoseph Koshy case PMC_CPU_AMD_K8: 3377789140c0SJoseph Koshy PMC_MDEP_INIT(k8); 33780cfab8ddSJoseph Koshy pmc_class_table[n] = &k8_class_table_descr; 33790cfab8ddSJoseph Koshy break; 33800cfab8ddSJoseph Koshy case PMC_CPU_INTEL_ATOM: 3381791f5d5bSJoseph Koshy PMC_MDEP_INIT_INTEL_V2(atom); 33820cfab8ddSJoseph Koshy break; 3383e8f021a3SHiren Panchasara case PMC_CPU_INTEL_ATOM_SILVERMONT: 3384e8f021a3SHiren Panchasara PMC_MDEP_INIT_INTEL_V2(atom_silvermont); 3385e8f021a3SHiren Panchasara break; 33860cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE: 33870cfab8ddSJoseph Koshy PMC_MDEP_INIT(core); 3388bc315bbdSJoseph Koshy pmc_class_table[n] = &core_class_table_descr; 33890cfab8ddSJoseph Koshy break; 33900cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE2: 3391b4d091f3SJoseph Koshy case PMC_CPU_INTEL_CORE2EXTREME: 3392791f5d5bSJoseph Koshy PMC_MDEP_INIT_INTEL_V2(core2); 3393789140c0SJoseph Koshy break; 3394597979c4SJeff Roberson case PMC_CPU_INTEL_COREI7: 33951fa7f10bSFabien Thomas pmc_class_table[n++] = &ucf_class_table_descr; 33961fa7f10bSFabien Thomas pmc_class_table[n++] = &corei7uc_class_table_descr; 3397791f5d5bSJoseph Koshy PMC_MDEP_INIT_INTEL_V2(corei7); 3398597979c4SJeff Roberson break; 339949fe48abSKonstantin Belousov case PMC_CPU_INTEL_NEHALEM_EX: 340049fe48abSKonstantin Belousov PMC_MDEP_INIT_INTEL_V2(nehalem_ex); 340149fe48abSKonstantin Belousov break; 3402cc0c1555SSean Bruno case PMC_CPU_INTEL_HASWELL: 3403cc0c1555SSean Bruno pmc_class_table[n++] = &ucf_class_table_descr; 3404cc0c1555SSean Bruno pmc_class_table[n++] = &haswelluc_class_table_descr; 3405cc0c1555SSean Bruno PMC_MDEP_INIT_INTEL_V2(haswell); 3406cc0c1555SSean Bruno break; 3407d95b3509SRandall Stewart case PMC_CPU_INTEL_HASWELL_XEON: 3408d95b3509SRandall Stewart PMC_MDEP_INIT_INTEL_V2(haswell_xeon); 3409d95b3509SRandall Stewart break; 3410f19bae41SRandall Stewart case PMC_CPU_INTEL_BROADWELL: 3411f19bae41SRandall Stewart pmc_class_table[n++] = &ucf_class_table_descr; 3412f19bae41SRandall Stewart pmc_class_table[n++] = &broadwelluc_class_table_descr; 3413f19bae41SRandall Stewart PMC_MDEP_INIT_INTEL_V2(broadwell); 3414f19bae41SRandall Stewart break; 3415f19bae41SRandall Stewart case PMC_CPU_INTEL_BROADWELL_XEON: 3416f19bae41SRandall Stewart PMC_MDEP_INIT_INTEL_V2(broadwell_xeon); 3417f19bae41SRandall Stewart break; 3418f19bae41SRandall Stewart case PMC_CPU_INTEL_SKYLAKE: 3419f19bae41SRandall Stewart PMC_MDEP_INIT_INTEL_V2(skylake); 3420f19bae41SRandall Stewart break; 3421b99b705dSKonstantin Belousov case PMC_CPU_INTEL_SKYLAKE_XEON: 3422b99b705dSKonstantin Belousov PMC_MDEP_INIT_INTEL_V2(skylake_xeon); 3423b99b705dSKonstantin Belousov break; 34241e862e5aSFabien Thomas case PMC_CPU_INTEL_IVYBRIDGE: 34251e862e5aSFabien Thomas PMC_MDEP_INIT_INTEL_V2(ivybridge); 34261e862e5aSFabien Thomas break; 34273f929d8cSSean Bruno case PMC_CPU_INTEL_IVYBRIDGE_XEON: 34283f929d8cSSean Bruno PMC_MDEP_INIT_INTEL_V2(ivybridge_xeon); 34293f929d8cSSean Bruno break; 343078d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 343178d763a2SDavide Italiano pmc_class_table[n++] = &ucf_class_table_descr; 343278d763a2SDavide Italiano pmc_class_table[n++] = &sandybridgeuc_class_table_descr; 343378d763a2SDavide Italiano PMC_MDEP_INIT_INTEL_V2(sandybridge); 343478d763a2SDavide Italiano break; 3435fabe02f5SSean Bruno case PMC_CPU_INTEL_SANDYBRIDGE_XEON: 3436fabe02f5SSean Bruno PMC_MDEP_INIT_INTEL_V2(sandybridge_xeon); 3437fabe02f5SSean Bruno break; 34381fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 34391fa7f10bSFabien Thomas pmc_class_table[n++] = &ucf_class_table_descr; 34401fa7f10bSFabien Thomas pmc_class_table[n++] = &westmereuc_class_table_descr; 34411fa7f10bSFabien Thomas PMC_MDEP_INIT_INTEL_V2(westmere); 34421fa7f10bSFabien Thomas break; 344349fe48abSKonstantin Belousov case PMC_CPU_INTEL_WESTMERE_EX: 344449fe48abSKonstantin Belousov PMC_MDEP_INIT_INTEL_V2(westmere_ex); 344549fe48abSKonstantin Belousov break; 3446789140c0SJoseph Koshy case PMC_CPU_INTEL_PIV: 3447789140c0SJoseph Koshy PMC_MDEP_INIT(p4); 34480cfab8ddSJoseph Koshy pmc_class_table[n] = &p4_class_table_descr; 3449f263522aSJoseph Koshy break; 3450ebccf1e3SJoseph Koshy #endif 3451f5f9340bSFabien Thomas case PMC_CPU_GENERIC: 3452f5f9340bSFabien Thomas PMC_MDEP_INIT(generic); 3453f5f9340bSFabien Thomas break; 34546411d14dSRuslan Bukin #if defined(__arm__) 34550ce207d2SRui Paulo #if defined(__XSCALE__) 34560ce207d2SRui Paulo case PMC_CPU_INTEL_XSCALE: 34570ce207d2SRui Paulo PMC_MDEP_INIT(xscale); 34580ce207d2SRui Paulo pmc_class_table[n] = &xscale_class_table_descr; 34590ce207d2SRui Paulo break; 34600ce207d2SRui Paulo #endif 34613e0bfdd8SRuslan Bukin case PMC_CPU_ARMV7_CORTEX_A8: 34623e0bfdd8SRuslan Bukin PMC_MDEP_INIT(cortex_a8); 34633e0bfdd8SRuslan Bukin pmc_class_table[n] = &cortex_a8_class_table_descr; 34643e0bfdd8SRuslan Bukin break; 34653e0bfdd8SRuslan Bukin case PMC_CPU_ARMV7_CORTEX_A9: 34663e0bfdd8SRuslan Bukin PMC_MDEP_INIT(cortex_a9); 34673e0bfdd8SRuslan Bukin pmc_class_table[n] = &cortex_a9_class_table_descr; 34686411d14dSRuslan Bukin break; 34696411d14dSRuslan Bukin #endif 3470bc88bb2bSRuslan Bukin #if defined(__aarch64__) 3471bc88bb2bSRuslan Bukin case PMC_CPU_ARMV8_CORTEX_A53: 3472bc88bb2bSRuslan Bukin PMC_MDEP_INIT(cortex_a53); 3473bc88bb2bSRuslan Bukin pmc_class_table[n] = &cortex_a53_class_table_descr; 3474bc88bb2bSRuslan Bukin break; 3475bc88bb2bSRuslan Bukin case PMC_CPU_ARMV8_CORTEX_A57: 3476bc88bb2bSRuslan Bukin PMC_MDEP_INIT(cortex_a57); 3477bc88bb2bSRuslan Bukin pmc_class_table[n] = &cortex_a57_class_table_descr; 3478bc88bb2bSRuslan Bukin break; 3479bc88bb2bSRuslan Bukin #endif 3480660df75eSGeorge V. Neville-Neil #if defined(__mips__) 3481660df75eSGeorge V. Neville-Neil case PMC_CPU_MIPS_24K: 3482660df75eSGeorge V. Neville-Neil PMC_MDEP_INIT(mips24k); 3483660df75eSGeorge V. Neville-Neil pmc_class_table[n] = &mips24k_class_table_descr; 3484660df75eSGeorge V. Neville-Neil break; 3485f6e6460dSAdrian Chadd case PMC_CPU_MIPS_74K: 3486f6e6460dSAdrian Chadd PMC_MDEP_INIT(mips74k); 3487f6e6460dSAdrian Chadd pmc_class_table[n] = &mips74k_class_table_descr; 3488f6e6460dSAdrian Chadd break; 3489c2657f80SOleksandr Tymoshenko case PMC_CPU_MIPS_OCTEON: 3490c2657f80SOleksandr Tymoshenko PMC_MDEP_INIT(octeon); 3491c2657f80SOleksandr Tymoshenko pmc_class_table[n] = &octeon_class_table_descr; 3492c2657f80SOleksandr Tymoshenko break; 3493660df75eSGeorge V. Neville-Neil #endif /* __mips__ */ 34947b25dccaSJustin Hibbits #if defined(__powerpc__) 34957b25dccaSJustin Hibbits case PMC_CPU_PPC_7450: 34967b25dccaSJustin Hibbits PMC_MDEP_INIT(ppc7450); 34977b25dccaSJustin Hibbits pmc_class_table[n] = &ppc7450_class_table_descr; 34987b25dccaSJustin Hibbits break; 3499169dd953SJustin Hibbits case PMC_CPU_PPC_970: 3500169dd953SJustin Hibbits PMC_MDEP_INIT(ppc970); 3501169dd953SJustin Hibbits pmc_class_table[n] = &ppc970_class_table_descr; 3502169dd953SJustin Hibbits break; 3503a7452468SJustin Hibbits case PMC_CPU_PPC_E500: 3504a7452468SJustin Hibbits PMC_MDEP_INIT(e500); 3505a7452468SJustin Hibbits pmc_class_table[n] = &e500_class_table_descr; 3506a7452468SJustin Hibbits break; 35077b25dccaSJustin Hibbits #endif 3508f263522aSJoseph Koshy default: 3509f263522aSJoseph Koshy /* 3510f263522aSJoseph Koshy * Some kind of CPU this version of the library knows nothing 3511f263522aSJoseph Koshy * about. This shouldn't happen since the abi version check 3512f263522aSJoseph Koshy * should have caught this. 3513f263522aSJoseph Koshy */ 3514f263522aSJoseph Koshy errno = ENXIO; 3515f263522aSJoseph Koshy return (pmc_syscall = -1); 3516f263522aSJoseph Koshy } 3517f263522aSJoseph Koshy 3518aa342b1fSJoseph Koshy return (0); 3519f263522aSJoseph Koshy } 3520f263522aSJoseph Koshy 3521f263522aSJoseph Koshy const char * 3522f263522aSJoseph Koshy pmc_name_of_capability(enum pmc_caps cap) 3523f263522aSJoseph Koshy { 3524f263522aSJoseph Koshy int i; 3525f263522aSJoseph Koshy 3526f263522aSJoseph Koshy /* 3527f263522aSJoseph Koshy * 'cap' should have a single bit set and should be in 3528f263522aSJoseph Koshy * range. 3529f263522aSJoseph Koshy */ 3530f263522aSJoseph Koshy if ((cap & (cap - 1)) || cap < PMC_CAP_FIRST || 3531f263522aSJoseph Koshy cap > PMC_CAP_LAST) { 3532f263522aSJoseph Koshy errno = EINVAL; 3533aa342b1fSJoseph Koshy return (NULL); 3534f263522aSJoseph Koshy } 3535f263522aSJoseph Koshy 3536f263522aSJoseph Koshy i = ffs(cap); 3537aa342b1fSJoseph Koshy return (pmc_capability_names[i - 1]); 3538f263522aSJoseph Koshy } 3539f263522aSJoseph Koshy 3540f263522aSJoseph Koshy const char * 3541f263522aSJoseph Koshy pmc_name_of_class(enum pmc_class pc) 3542f263522aSJoseph Koshy { 35430ceb54c2SJohn Baldwin size_t n; 35440ceb54c2SJohn Baldwin 35450ceb54c2SJohn Baldwin for (n = 0; n < PMC_TABLE_SIZE(pmc_class_names); n++) 35460ceb54c2SJohn Baldwin if (pc == pmc_class_names[n].pm_class) 35470ceb54c2SJohn Baldwin return (pmc_class_names[n].pm_name); 3548f263522aSJoseph Koshy 3549f263522aSJoseph Koshy errno = EINVAL; 3550aa342b1fSJoseph Koshy return (NULL); 3551f263522aSJoseph Koshy } 3552f263522aSJoseph Koshy 3553f263522aSJoseph Koshy const char * 3554f263522aSJoseph Koshy pmc_name_of_cputype(enum pmc_cputype cp) 3555f263522aSJoseph Koshy { 3556789140c0SJoseph Koshy size_t n; 3557789140c0SJoseph Koshy 3558789140c0SJoseph Koshy for (n = 0; n < PMC_TABLE_SIZE(pmc_cputype_names); n++) 3559789140c0SJoseph Koshy if (cp == pmc_cputype_names[n].pm_cputype) 3560789140c0SJoseph Koshy return (pmc_cputype_names[n].pm_name); 3561789140c0SJoseph Koshy 3562f263522aSJoseph Koshy errno = EINVAL; 3563aa342b1fSJoseph Koshy return (NULL); 3564f263522aSJoseph Koshy } 3565f263522aSJoseph Koshy 3566f263522aSJoseph Koshy const char * 3567f263522aSJoseph Koshy pmc_name_of_disposition(enum pmc_disp pd) 3568f263522aSJoseph Koshy { 3569f263522aSJoseph Koshy if ((int) pd >= PMC_DISP_FIRST && 3570f263522aSJoseph Koshy pd <= PMC_DISP_LAST) 3571aa342b1fSJoseph Koshy return (pmc_disposition_names[pd]); 3572f263522aSJoseph Koshy 3573f263522aSJoseph Koshy errno = EINVAL; 3574aa342b1fSJoseph Koshy return (NULL); 3575f263522aSJoseph Koshy } 3576f263522aSJoseph Koshy 3577f263522aSJoseph Koshy const char * 35780cfab8ddSJoseph Koshy _pmc_name_of_event(enum pmc_event pe, enum pmc_cputype cpu) 3579f263522aSJoseph Koshy { 3580789140c0SJoseph Koshy const struct pmc_event_descr *ev, *evfence; 3581789140c0SJoseph Koshy 3582789140c0SJoseph Koshy ev = evfence = NULL; 35830cfab8ddSJoseph Koshy if (pe >= PMC_EV_IAF_FIRST && pe <= PMC_EV_IAF_LAST) { 35840cfab8ddSJoseph Koshy ev = iaf_event_table; 35850cfab8ddSJoseph Koshy evfence = iaf_event_table + PMC_EVENT_TABLE_SIZE(iaf); 35860cfab8ddSJoseph Koshy } else if (pe >= PMC_EV_IAP_FIRST && pe <= PMC_EV_IAP_LAST) { 35870cfab8ddSJoseph Koshy switch (cpu) { 35880cfab8ddSJoseph Koshy case PMC_CPU_INTEL_ATOM: 35890cfab8ddSJoseph Koshy ev = atom_event_table; 35900cfab8ddSJoseph Koshy evfence = atom_event_table + PMC_EVENT_TABLE_SIZE(atom); 35910cfab8ddSJoseph Koshy break; 3592e8f021a3SHiren Panchasara case PMC_CPU_INTEL_ATOM_SILVERMONT: 3593e8f021a3SHiren Panchasara ev = atom_silvermont_event_table; 3594e8f021a3SHiren Panchasara evfence = atom_silvermont_event_table + 3595e8f021a3SHiren Panchasara PMC_EVENT_TABLE_SIZE(atom_silvermont); 3596e8f021a3SHiren Panchasara break; 35970cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE: 35980cfab8ddSJoseph Koshy ev = core_event_table; 35990cfab8ddSJoseph Koshy evfence = core_event_table + PMC_EVENT_TABLE_SIZE(core); 36000cfab8ddSJoseph Koshy break; 36010cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE2: 3602b4d091f3SJoseph Koshy case PMC_CPU_INTEL_CORE2EXTREME: 36030cfab8ddSJoseph Koshy ev = core2_event_table; 36040cfab8ddSJoseph Koshy evfence = core2_event_table + PMC_EVENT_TABLE_SIZE(core2); 36050cfab8ddSJoseph Koshy break; 3606597979c4SJeff Roberson case PMC_CPU_INTEL_COREI7: 3607597979c4SJeff Roberson ev = corei7_event_table; 3608597979c4SJeff Roberson evfence = corei7_event_table + PMC_EVENT_TABLE_SIZE(corei7); 3609597979c4SJeff Roberson break; 361049fe48abSKonstantin Belousov case PMC_CPU_INTEL_NEHALEM_EX: 361149fe48abSKonstantin Belousov ev = nehalem_ex_event_table; 361249fe48abSKonstantin Belousov evfence = nehalem_ex_event_table + 361349fe48abSKonstantin Belousov PMC_EVENT_TABLE_SIZE(nehalem_ex); 361449fe48abSKonstantin Belousov break; 3615cc0c1555SSean Bruno case PMC_CPU_INTEL_HASWELL: 3616cc0c1555SSean Bruno ev = haswell_event_table; 3617cc0c1555SSean Bruno evfence = haswell_event_table + PMC_EVENT_TABLE_SIZE(haswell); 3618cc0c1555SSean Bruno break; 3619d95b3509SRandall Stewart case PMC_CPU_INTEL_HASWELL_XEON: 3620d95b3509SRandall Stewart ev = haswell_xeon_event_table; 3621d95b3509SRandall Stewart evfence = haswell_xeon_event_table + PMC_EVENT_TABLE_SIZE(haswell_xeon); 3622d95b3509SRandall Stewart break; 3623f19bae41SRandall Stewart case PMC_CPU_INTEL_BROADWELL: 3624f19bae41SRandall Stewart ev = broadwell_event_table; 3625f19bae41SRandall Stewart evfence = broadwell_event_table + PMC_EVENT_TABLE_SIZE(broadwell); 3626f19bae41SRandall Stewart break; 3627f19bae41SRandall Stewart case PMC_CPU_INTEL_BROADWELL_XEON: 3628f19bae41SRandall Stewart ev = broadwell_xeon_event_table; 3629f19bae41SRandall Stewart evfence = broadwell_xeon_event_table + PMC_EVENT_TABLE_SIZE(broadwell_xeon); 3630f19bae41SRandall Stewart break; 3631f19bae41SRandall Stewart case PMC_CPU_INTEL_SKYLAKE: 3632f19bae41SRandall Stewart ev = skylake_event_table; 36339491ba75SKonstantin Belousov evfence = skylake_event_table + 36349491ba75SKonstantin Belousov PMC_EVENT_TABLE_SIZE(skylake); 3635f19bae41SRandall Stewart break; 3636b99b705dSKonstantin Belousov case PMC_CPU_INTEL_SKYLAKE_XEON: 3637b99b705dSKonstantin Belousov ev = skylake_xeon_event_table; 3638b99b705dSKonstantin Belousov evfence = skylake_xeon_event_table + 3639b99b705dSKonstantin Belousov PMC_EVENT_TABLE_SIZE(skylake_xeon); 3640b99b705dSKonstantin Belousov break; 36411e862e5aSFabien Thomas case PMC_CPU_INTEL_IVYBRIDGE: 36421e862e5aSFabien Thomas ev = ivybridge_event_table; 36431e862e5aSFabien Thomas evfence = ivybridge_event_table + PMC_EVENT_TABLE_SIZE(ivybridge); 36441e862e5aSFabien Thomas break; 36453f929d8cSSean Bruno case PMC_CPU_INTEL_IVYBRIDGE_XEON: 36463f929d8cSSean Bruno ev = ivybridge_xeon_event_table; 36473f929d8cSSean Bruno evfence = ivybridge_xeon_event_table + PMC_EVENT_TABLE_SIZE(ivybridge_xeon); 36483f929d8cSSean Bruno break; 364978d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 365078d763a2SDavide Italiano ev = sandybridge_event_table; 365178d763a2SDavide Italiano evfence = sandybridge_event_table + PMC_EVENT_TABLE_SIZE(sandybridge); 365278d763a2SDavide Italiano break; 3653fabe02f5SSean Bruno case PMC_CPU_INTEL_SANDYBRIDGE_XEON: 3654fabe02f5SSean Bruno ev = sandybridge_xeon_event_table; 3655fabe02f5SSean Bruno evfence = sandybridge_xeon_event_table + PMC_EVENT_TABLE_SIZE(sandybridge_xeon); 3656fabe02f5SSean Bruno break; 36571fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 36581fa7f10bSFabien Thomas ev = westmere_event_table; 36591fa7f10bSFabien Thomas evfence = westmere_event_table + PMC_EVENT_TABLE_SIZE(westmere); 36601fa7f10bSFabien Thomas break; 366149fe48abSKonstantin Belousov case PMC_CPU_INTEL_WESTMERE_EX: 366249fe48abSKonstantin Belousov ev = westmere_ex_event_table; 366349fe48abSKonstantin Belousov evfence = westmere_ex_event_table + 366449fe48abSKonstantin Belousov PMC_EVENT_TABLE_SIZE(westmere_ex); 366549fe48abSKonstantin Belousov break; 36660cfab8ddSJoseph Koshy default: /* Unknown CPU type. */ 36670cfab8ddSJoseph Koshy break; 36680cfab8ddSJoseph Koshy } 36691fa7f10bSFabien Thomas } else if (pe >= PMC_EV_UCF_FIRST && pe <= PMC_EV_UCF_LAST) { 36701fa7f10bSFabien Thomas ev = ucf_event_table; 36711fa7f10bSFabien Thomas evfence = ucf_event_table + PMC_EVENT_TABLE_SIZE(ucf); 36721fa7f10bSFabien Thomas } else if (pe >= PMC_EV_UCP_FIRST && pe <= PMC_EV_UCP_LAST) { 36731fa7f10bSFabien Thomas switch (cpu) { 36741fa7f10bSFabien Thomas case PMC_CPU_INTEL_COREI7: 36751fa7f10bSFabien Thomas ev = corei7uc_event_table; 36761fa7f10bSFabien Thomas evfence = corei7uc_event_table + PMC_EVENT_TABLE_SIZE(corei7uc); 36771fa7f10bSFabien Thomas break; 367878d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 367978d763a2SDavide Italiano ev = sandybridgeuc_event_table; 368078d763a2SDavide Italiano evfence = sandybridgeuc_event_table + PMC_EVENT_TABLE_SIZE(sandybridgeuc); 368178d763a2SDavide Italiano break; 36821fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 36831fa7f10bSFabien Thomas ev = westmereuc_event_table; 36841fa7f10bSFabien Thomas evfence = westmereuc_event_table + PMC_EVENT_TABLE_SIZE(westmereuc); 36851fa7f10bSFabien Thomas break; 36861fa7f10bSFabien Thomas default: /* Unknown CPU type. */ 36871fa7f10bSFabien Thomas break; 36881fa7f10bSFabien Thomas } 36891fa7f10bSFabien Thomas } else if (pe >= PMC_EV_K7_FIRST && pe <= PMC_EV_K7_LAST) { 3690789140c0SJoseph Koshy ev = k7_event_table; 3691789140c0SJoseph Koshy evfence = k7_event_table + PMC_EVENT_TABLE_SIZE(k7); 3692789140c0SJoseph Koshy } else if (pe >= PMC_EV_K8_FIRST && pe <= PMC_EV_K8_LAST) { 3693789140c0SJoseph Koshy ev = k8_event_table; 3694789140c0SJoseph Koshy evfence = k8_event_table + PMC_EVENT_TABLE_SIZE(k8); 3695789140c0SJoseph Koshy } else if (pe >= PMC_EV_P4_FIRST && pe <= PMC_EV_P4_LAST) { 3696789140c0SJoseph Koshy ev = p4_event_table; 3697789140c0SJoseph Koshy evfence = p4_event_table + PMC_EVENT_TABLE_SIZE(p4); 3698789140c0SJoseph Koshy } else if (pe >= PMC_EV_P5_FIRST && pe <= PMC_EV_P5_LAST) { 3699789140c0SJoseph Koshy ev = p5_event_table; 3700789140c0SJoseph Koshy evfence = p5_event_table + PMC_EVENT_TABLE_SIZE(p5); 3701789140c0SJoseph Koshy } else if (pe >= PMC_EV_P6_FIRST && pe <= PMC_EV_P6_LAST) { 3702789140c0SJoseph Koshy ev = p6_event_table; 3703789140c0SJoseph Koshy evfence = p6_event_table + PMC_EVENT_TABLE_SIZE(p6); 37040ce207d2SRui Paulo } else if (pe >= PMC_EV_XSCALE_FIRST && pe <= PMC_EV_XSCALE_LAST) { 37050ce207d2SRui Paulo ev = xscale_event_table; 37060ce207d2SRui Paulo evfence = xscale_event_table + PMC_EVENT_TABLE_SIZE(xscale); 37076411d14dSRuslan Bukin } else if (pe >= PMC_EV_ARMV7_FIRST && pe <= PMC_EV_ARMV7_LAST) { 37083e0bfdd8SRuslan Bukin switch (cpu) { 37093e0bfdd8SRuslan Bukin case PMC_CPU_ARMV7_CORTEX_A8: 37103e0bfdd8SRuslan Bukin ev = cortex_a8_event_table; 37113e0bfdd8SRuslan Bukin evfence = cortex_a8_event_table + PMC_EVENT_TABLE_SIZE(cortex_a8); 37123e0bfdd8SRuslan Bukin break; 37133e0bfdd8SRuslan Bukin case PMC_CPU_ARMV7_CORTEX_A9: 37143e0bfdd8SRuslan Bukin ev = cortex_a9_event_table; 37153e0bfdd8SRuslan Bukin evfence = cortex_a9_event_table + PMC_EVENT_TABLE_SIZE(cortex_a9); 37163e0bfdd8SRuslan Bukin break; 37173e0bfdd8SRuslan Bukin default: /* Unknown CPU type. */ 37183e0bfdd8SRuslan Bukin break; 37193e0bfdd8SRuslan Bukin } 3720bc88bb2bSRuslan Bukin } else if (pe >= PMC_EV_ARMV8_FIRST && pe <= PMC_EV_ARMV8_LAST) { 3721bc88bb2bSRuslan Bukin switch (cpu) { 3722bc88bb2bSRuslan Bukin case PMC_CPU_ARMV8_CORTEX_A53: 3723bc88bb2bSRuslan Bukin ev = cortex_a53_event_table; 3724bc88bb2bSRuslan Bukin evfence = cortex_a53_event_table + PMC_EVENT_TABLE_SIZE(cortex_a53); 3725bc88bb2bSRuslan Bukin break; 3726bc88bb2bSRuslan Bukin case PMC_CPU_ARMV8_CORTEX_A57: 3727bc88bb2bSRuslan Bukin ev = cortex_a57_event_table; 3728bc88bb2bSRuslan Bukin evfence = cortex_a57_event_table + PMC_EVENT_TABLE_SIZE(cortex_a57); 3729bc88bb2bSRuslan Bukin break; 3730bc88bb2bSRuslan Bukin default: /* Unknown CPU type. */ 3731bc88bb2bSRuslan Bukin break; 3732bc88bb2bSRuslan Bukin } 3733660df75eSGeorge V. Neville-Neil } else if (pe >= PMC_EV_MIPS24K_FIRST && pe <= PMC_EV_MIPS24K_LAST) { 3734660df75eSGeorge V. Neville-Neil ev = mips24k_event_table; 3735f5f9340bSFabien Thomas evfence = mips24k_event_table + PMC_EVENT_TABLE_SIZE(mips24k); 3736f6e6460dSAdrian Chadd } else if (pe >= PMC_EV_MIPS74K_FIRST && pe <= PMC_EV_MIPS74K_LAST) { 3737f6e6460dSAdrian Chadd ev = mips74k_event_table; 3738f6e6460dSAdrian Chadd evfence = mips74k_event_table + PMC_EVENT_TABLE_SIZE(mips74k); 3739c2657f80SOleksandr Tymoshenko } else if (pe >= PMC_EV_OCTEON_FIRST && pe <= PMC_EV_OCTEON_LAST) { 3740c2657f80SOleksandr Tymoshenko ev = octeon_event_table; 3741c2657f80SOleksandr Tymoshenko evfence = octeon_event_table + PMC_EVENT_TABLE_SIZE(octeon); 37427b25dccaSJustin Hibbits } else if (pe >= PMC_EV_PPC7450_FIRST && pe <= PMC_EV_PPC7450_LAST) { 37437b25dccaSJustin Hibbits ev = ppc7450_event_table; 3744f5f9340bSFabien Thomas evfence = ppc7450_event_table + PMC_EVENT_TABLE_SIZE(ppc7450); 3745169dd953SJustin Hibbits } else if (pe >= PMC_EV_PPC970_FIRST && pe <= PMC_EV_PPC970_LAST) { 3746169dd953SJustin Hibbits ev = ppc970_event_table; 3747169dd953SJustin Hibbits evfence = ppc970_event_table + PMC_EVENT_TABLE_SIZE(ppc970); 3748a7452468SJustin Hibbits } else if (pe >= PMC_EV_E500_FIRST && pe <= PMC_EV_E500_LAST) { 3749a7452468SJustin Hibbits ev = e500_event_table; 3750a7452468SJustin Hibbits evfence = e500_event_table + PMC_EVENT_TABLE_SIZE(e500); 3751789140c0SJoseph Koshy } else if (pe == PMC_EV_TSC_TSC) { 3752789140c0SJoseph Koshy ev = tsc_event_table; 3753789140c0SJoseph Koshy evfence = tsc_event_table + PMC_EVENT_TABLE_SIZE(tsc); 3754f0bbe9aaSDimitry Andric } else if ((int)pe >= PMC_EV_SOFT_FIRST && (int)pe <= PMC_EV_SOFT_LAST) { 3755f5f9340bSFabien Thomas ev = soft_event_table; 3756f5f9340bSFabien Thomas evfence = soft_event_table + soft_event_info.pm_nevent; 3757789140c0SJoseph Koshy } 3758789140c0SJoseph Koshy 3759789140c0SJoseph Koshy for (; ev != evfence; ev++) 3760789140c0SJoseph Koshy if (pe == ev->pm_ev_code) 3761789140c0SJoseph Koshy return (ev->pm_ev_name); 3762f263522aSJoseph Koshy 37630cfab8ddSJoseph Koshy return (NULL); 37640cfab8ddSJoseph Koshy } 37650cfab8ddSJoseph Koshy 37660cfab8ddSJoseph Koshy const char * 37670cfab8ddSJoseph Koshy pmc_name_of_event(enum pmc_event pe) 37680cfab8ddSJoseph Koshy { 37690cfab8ddSJoseph Koshy const char *n; 37700cfab8ddSJoseph Koshy 37710cfab8ddSJoseph Koshy if ((n = _pmc_name_of_event(pe, cpu_info.pm_cputype)) != NULL) 37720cfab8ddSJoseph Koshy return (n); 37730cfab8ddSJoseph Koshy 3774f263522aSJoseph Koshy errno = EINVAL; 3775aa342b1fSJoseph Koshy return (NULL); 3776f263522aSJoseph Koshy } 3777f263522aSJoseph Koshy 3778f263522aSJoseph Koshy const char * 3779f263522aSJoseph Koshy pmc_name_of_mode(enum pmc_mode pm) 3780f263522aSJoseph Koshy { 3781f263522aSJoseph Koshy if ((int) pm >= PMC_MODE_FIRST && 3782f263522aSJoseph Koshy pm <= PMC_MODE_LAST) 3783aa342b1fSJoseph Koshy return (pmc_mode_names[pm]); 3784f263522aSJoseph Koshy 3785f263522aSJoseph Koshy errno = EINVAL; 3786aa342b1fSJoseph Koshy return (NULL); 3787f263522aSJoseph Koshy } 3788f263522aSJoseph Koshy 3789f263522aSJoseph Koshy const char * 3790f263522aSJoseph Koshy pmc_name_of_state(enum pmc_state ps) 3791f263522aSJoseph Koshy { 3792f263522aSJoseph Koshy if ((int) ps >= PMC_STATE_FIRST && 3793f263522aSJoseph Koshy ps <= PMC_STATE_LAST) 3794aa342b1fSJoseph Koshy return (pmc_state_names[ps]); 3795f263522aSJoseph Koshy 3796f263522aSJoseph Koshy errno = EINVAL; 3797aa342b1fSJoseph Koshy return (NULL); 3798f263522aSJoseph Koshy } 3799f263522aSJoseph Koshy 3800f263522aSJoseph Koshy int 3801f263522aSJoseph Koshy pmc_ncpu(void) 3802f263522aSJoseph Koshy { 3803f263522aSJoseph Koshy if (pmc_syscall == -1) { 3804f263522aSJoseph Koshy errno = ENXIO; 3805aa342b1fSJoseph Koshy return (-1); 3806f263522aSJoseph Koshy } 3807f263522aSJoseph Koshy 3808aa342b1fSJoseph Koshy return (cpu_info.pm_ncpu); 3809f263522aSJoseph Koshy } 3810f263522aSJoseph Koshy 3811f263522aSJoseph Koshy int 3812f263522aSJoseph Koshy pmc_npmc(int cpu) 3813f263522aSJoseph Koshy { 3814f263522aSJoseph Koshy if (pmc_syscall == -1) { 3815f263522aSJoseph Koshy errno = ENXIO; 3816aa342b1fSJoseph Koshy return (-1); 3817f263522aSJoseph Koshy } 3818f263522aSJoseph Koshy 3819f263522aSJoseph Koshy if (cpu < 0 || cpu >= (int) cpu_info.pm_ncpu) { 3820f263522aSJoseph Koshy errno = EINVAL; 3821aa342b1fSJoseph Koshy return (-1); 3822f263522aSJoseph Koshy } 3823f263522aSJoseph Koshy 3824aa342b1fSJoseph Koshy return (cpu_info.pm_npmc); 3825f263522aSJoseph Koshy } 3826f263522aSJoseph Koshy 3827f263522aSJoseph Koshy int 3828f263522aSJoseph Koshy pmc_pmcinfo(int cpu, struct pmc_pmcinfo **ppmci) 3829f263522aSJoseph Koshy { 3830f263522aSJoseph Koshy int nbytes, npmc; 3831f263522aSJoseph Koshy struct pmc_op_getpmcinfo *pmci; 3832f263522aSJoseph Koshy 3833f263522aSJoseph Koshy if ((npmc = pmc_npmc(cpu)) < 0) 3834aa342b1fSJoseph Koshy return (-1); 3835f263522aSJoseph Koshy 3836f263522aSJoseph Koshy nbytes = sizeof(struct pmc_op_getpmcinfo) + 3837f263522aSJoseph Koshy npmc * sizeof(struct pmc_info); 3838f263522aSJoseph Koshy 3839f263522aSJoseph Koshy if ((pmci = calloc(1, nbytes)) == NULL) 3840aa342b1fSJoseph Koshy return (-1); 3841f263522aSJoseph Koshy 3842f263522aSJoseph Koshy pmci->pm_cpu = cpu; 3843f263522aSJoseph Koshy 3844f263522aSJoseph Koshy if (PMC_CALL(GETPMCINFO, pmci) < 0) { 3845f263522aSJoseph Koshy free(pmci); 3846aa342b1fSJoseph Koshy return (-1); 3847f263522aSJoseph Koshy } 3848f263522aSJoseph Koshy 3849f263522aSJoseph Koshy /* kernel<->library, library<->userland interfaces are identical */ 3850f263522aSJoseph Koshy *ppmci = (struct pmc_pmcinfo *) pmci; 3851aa342b1fSJoseph Koshy return (0); 3852f263522aSJoseph Koshy } 3853f263522aSJoseph Koshy 3854f263522aSJoseph Koshy int 3855f263522aSJoseph Koshy pmc_read(pmc_id_t pmc, pmc_value_t *value) 3856f263522aSJoseph Koshy { 3857f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_read_op; 3858f263522aSJoseph Koshy 3859f263522aSJoseph Koshy pmc_read_op.pm_pmcid = pmc; 3860f263522aSJoseph Koshy pmc_read_op.pm_flags = PMC_F_OLDVALUE; 3861f263522aSJoseph Koshy pmc_read_op.pm_value = -1; 3862f263522aSJoseph Koshy 3863f263522aSJoseph Koshy if (PMC_CALL(PMCRW, &pmc_read_op) < 0) 3864aa342b1fSJoseph Koshy return (-1); 3865f263522aSJoseph Koshy 3866f263522aSJoseph Koshy *value = pmc_read_op.pm_value; 3867aa342b1fSJoseph Koshy return (0); 3868f263522aSJoseph Koshy } 3869f263522aSJoseph Koshy 3870f263522aSJoseph Koshy int 3871f263522aSJoseph Koshy pmc_release(pmc_id_t pmc) 3872f263522aSJoseph Koshy { 3873f263522aSJoseph Koshy struct pmc_op_simple pmc_release_args; 3874f263522aSJoseph Koshy 3875f263522aSJoseph Koshy pmc_release_args.pm_pmcid = pmc; 3876aa342b1fSJoseph Koshy return (PMC_CALL(PMCRELEASE, &pmc_release_args)); 3877f263522aSJoseph Koshy } 3878f263522aSJoseph Koshy 3879f263522aSJoseph Koshy int 3880f263522aSJoseph Koshy pmc_rw(pmc_id_t pmc, pmc_value_t newvalue, pmc_value_t *oldvaluep) 3881f263522aSJoseph Koshy { 3882f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_rw_op; 3883f263522aSJoseph Koshy 3884f263522aSJoseph Koshy pmc_rw_op.pm_pmcid = pmc; 3885f263522aSJoseph Koshy pmc_rw_op.pm_flags = PMC_F_NEWVALUE | PMC_F_OLDVALUE; 3886f263522aSJoseph Koshy pmc_rw_op.pm_value = newvalue; 3887f263522aSJoseph Koshy 3888f263522aSJoseph Koshy if (PMC_CALL(PMCRW, &pmc_rw_op) < 0) 3889aa342b1fSJoseph Koshy return (-1); 3890f263522aSJoseph Koshy 3891f263522aSJoseph Koshy *oldvaluep = pmc_rw_op.pm_value; 3892aa342b1fSJoseph Koshy return (0); 3893f263522aSJoseph Koshy } 3894f263522aSJoseph Koshy 3895f263522aSJoseph Koshy int 3896f263522aSJoseph Koshy pmc_set(pmc_id_t pmc, pmc_value_t value) 3897f263522aSJoseph Koshy { 3898f263522aSJoseph Koshy struct pmc_op_pmcsetcount sc; 3899f263522aSJoseph Koshy 3900f263522aSJoseph Koshy sc.pm_pmcid = pmc; 3901f263522aSJoseph Koshy sc.pm_count = value; 3902f263522aSJoseph Koshy 3903f263522aSJoseph Koshy if (PMC_CALL(PMCSETCOUNT, &sc) < 0) 3904aa342b1fSJoseph Koshy return (-1); 3905aa342b1fSJoseph Koshy return (0); 3906f263522aSJoseph Koshy } 3907f263522aSJoseph Koshy 3908f263522aSJoseph Koshy int 3909f263522aSJoseph Koshy pmc_start(pmc_id_t pmc) 3910f263522aSJoseph Koshy { 3911f263522aSJoseph Koshy struct pmc_op_simple pmc_start_args; 3912f263522aSJoseph Koshy 3913f263522aSJoseph Koshy pmc_start_args.pm_pmcid = pmc; 3914aa342b1fSJoseph Koshy return (PMC_CALL(PMCSTART, &pmc_start_args)); 3915f263522aSJoseph Koshy } 3916f263522aSJoseph Koshy 3917f263522aSJoseph Koshy int 3918f263522aSJoseph Koshy pmc_stop(pmc_id_t pmc) 3919f263522aSJoseph Koshy { 3920f263522aSJoseph Koshy struct pmc_op_simple pmc_stop_args; 3921f263522aSJoseph Koshy 3922f263522aSJoseph Koshy pmc_stop_args.pm_pmcid = pmc; 3923aa342b1fSJoseph Koshy return (PMC_CALL(PMCSTOP, &pmc_stop_args)); 3924f263522aSJoseph Koshy } 3925f263522aSJoseph Koshy 3926f263522aSJoseph Koshy int 3927f263522aSJoseph Koshy pmc_width(pmc_id_t pmcid, uint32_t *width) 3928f263522aSJoseph Koshy { 3929f263522aSJoseph Koshy unsigned int i; 3930f263522aSJoseph Koshy enum pmc_class cl; 3931f263522aSJoseph Koshy 3932f263522aSJoseph Koshy cl = PMC_ID_TO_CLASS(pmcid); 3933f263522aSJoseph Koshy for (i = 0; i < cpu_info.pm_nclass; i++) 3934f263522aSJoseph Koshy if (cpu_info.pm_classes[i].pm_class == cl) { 3935f263522aSJoseph Koshy *width = cpu_info.pm_classes[i].pm_width; 3936aa342b1fSJoseph Koshy return (0); 3937f263522aSJoseph Koshy } 3938484202faSJoseph Koshy errno = EINVAL; 3939484202faSJoseph Koshy return (-1); 3940f263522aSJoseph Koshy } 3941f263522aSJoseph Koshy 3942f263522aSJoseph Koshy int 3943f263522aSJoseph Koshy pmc_write(pmc_id_t pmc, pmc_value_t value) 3944f263522aSJoseph Koshy { 3945f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_write_op; 3946f263522aSJoseph Koshy 3947f263522aSJoseph Koshy pmc_write_op.pm_pmcid = pmc; 3948f263522aSJoseph Koshy pmc_write_op.pm_flags = PMC_F_NEWVALUE; 3949f263522aSJoseph Koshy pmc_write_op.pm_value = value; 3950aa342b1fSJoseph Koshy return (PMC_CALL(PMCRW, &pmc_write_op)); 3951f263522aSJoseph Koshy } 3952f263522aSJoseph Koshy 3953f263522aSJoseph Koshy int 3954f263522aSJoseph Koshy pmc_writelog(uint32_t userdata) 3955f263522aSJoseph Koshy { 3956f263522aSJoseph Koshy struct pmc_op_writelog wl; 3957f263522aSJoseph Koshy 3958f263522aSJoseph Koshy wl.pm_userdata = userdata; 3959aa342b1fSJoseph Koshy return (PMC_CALL(WRITELOG, &wl)); 3960f263522aSJoseph Koshy } 3961