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) { 2784ebccf1e3SJoseph Koshy errno = EINVAL; 2785ebccf1e3SJoseph Koshy goto out; 2786ebccf1e3SJoseph Koshy } 2787ebccf1e3SJoseph Koshy 2788ebccf1e3SJoseph Koshy /* replace an event alias with the canonical event specifier */ 2789ebccf1e3SJoseph Koshy if (pmc_mdep_event_aliases) 2790789140c0SJoseph Koshy for (alias = pmc_mdep_event_aliases; alias->pm_alias; alias++) 2791789140c0SJoseph Koshy if (!strcasecmp(ctrspec, alias->pm_alias)) { 2792789140c0SJoseph Koshy spec_copy = strdup(alias->pm_spec); 2793ebccf1e3SJoseph Koshy break; 2794ebccf1e3SJoseph Koshy } 2795ebccf1e3SJoseph Koshy 2796ebccf1e3SJoseph Koshy if (spec_copy == NULL) 2797ebccf1e3SJoseph Koshy spec_copy = strdup(ctrspec); 2798ebccf1e3SJoseph Koshy 2799ebccf1e3SJoseph Koshy r = spec_copy; 2800ebccf1e3SJoseph Koshy ctrname = strsep(&r, ","); 2801ebccf1e3SJoseph Koshy 2802789140c0SJoseph Koshy /* 2803789140c0SJoseph Koshy * If a explicit class prefix was given by the user, restrict the 2804789140c0SJoseph Koshy * search for the event to the specified PMC class. 2805789140c0SJoseph Koshy */ 2806789140c0SJoseph Koshy ev = NULL; 28070cfab8ddSJoseph Koshy for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) { 28080cfab8ddSJoseph Koshy pcd = pmc_class_table[n]; 2809789140c0SJoseph Koshy if (pmc_mdep_is_compatible_class(pcd->pm_evc_class) && 2810789140c0SJoseph Koshy strncasecmp(ctrname, pcd->pm_evc_name, 2811789140c0SJoseph Koshy pcd->pm_evc_name_size) == 0) { 2812789140c0SJoseph Koshy if ((ev = pmc_match_event_class(ctrname + 2813789140c0SJoseph Koshy pcd->pm_evc_name_size, pcd)) == NULL) { 2814789140c0SJoseph Koshy errno = EINVAL; 2815789140c0SJoseph Koshy goto out; 2816789140c0SJoseph Koshy } 2817ebccf1e3SJoseph Koshy break; 2818789140c0SJoseph Koshy } 2819789140c0SJoseph Koshy } 2820ebccf1e3SJoseph Koshy 2821789140c0SJoseph Koshy /* 2822789140c0SJoseph Koshy * Otherwise, search for this event in all compatible PMC 2823789140c0SJoseph Koshy * classes. 2824789140c0SJoseph Koshy */ 28250cfab8ddSJoseph Koshy for (n = 0; ev == NULL && n < PMC_CLASS_TABLE_SIZE; n++) { 28260cfab8ddSJoseph Koshy pcd = pmc_class_table[n]; 2827789140c0SJoseph Koshy if (pmc_mdep_is_compatible_class(pcd->pm_evc_class)) 2828789140c0SJoseph Koshy ev = pmc_match_event_class(ctrname, pcd); 2829789140c0SJoseph Koshy } 2830789140c0SJoseph Koshy 2831789140c0SJoseph Koshy if (ev == NULL) { 2832ebccf1e3SJoseph Koshy errno = EINVAL; 2833ebccf1e3SJoseph Koshy goto out; 2834ebccf1e3SJoseph Koshy } 2835ebccf1e3SJoseph Koshy 2836ebccf1e3SJoseph Koshy bzero(&pmc_config, sizeof(pmc_config)); 2837789140c0SJoseph Koshy pmc_config.pm_ev = ev->pm_ev_code; 2838789140c0SJoseph Koshy pmc_config.pm_class = pcd->pm_evc_class; 2839ebccf1e3SJoseph Koshy pmc_config.pm_cpu = cpu; 2840ebccf1e3SJoseph Koshy pmc_config.pm_mode = mode; 2841ebccf1e3SJoseph Koshy pmc_config.pm_flags = flags; 2842ebccf1e3SJoseph Koshy 2843ebccf1e3SJoseph Koshy if (PMC_IS_SAMPLING_MODE(mode)) 2844ebccf1e3SJoseph Koshy pmc_config.pm_caps |= PMC_CAP_INTERRUPT; 2845ebccf1e3SJoseph Koshy 2846789140c0SJoseph Koshy if (pcd->pm_evc_allocate_pmc(ev->pm_ev_code, r, &pmc_config) < 0) { 2847ebccf1e3SJoseph Koshy errno = EINVAL; 2848ebccf1e3SJoseph Koshy goto out; 2849ebccf1e3SJoseph Koshy } 2850ebccf1e3SJoseph Koshy 2851ebccf1e3SJoseph Koshy if (PMC_CALL(PMCALLOCATE, &pmc_config) < 0) 2852ebccf1e3SJoseph Koshy goto out; 2853ebccf1e3SJoseph Koshy 2854ebccf1e3SJoseph Koshy *pmcid = pmc_config.pm_pmcid; 2855ebccf1e3SJoseph Koshy 2856ebccf1e3SJoseph Koshy retval = 0; 2857ebccf1e3SJoseph Koshy 2858ebccf1e3SJoseph Koshy out: 2859ebccf1e3SJoseph Koshy if (spec_copy) 2860ebccf1e3SJoseph Koshy free(spec_copy); 2861ebccf1e3SJoseph Koshy 2862aa342b1fSJoseph Koshy return (retval); 2863ebccf1e3SJoseph Koshy } 2864ebccf1e3SJoseph Koshy 2865ebccf1e3SJoseph Koshy int 2866ebccf1e3SJoseph Koshy pmc_attach(pmc_id_t pmc, pid_t pid) 2867ebccf1e3SJoseph Koshy { 2868ebccf1e3SJoseph Koshy struct pmc_op_pmcattach pmc_attach_args; 2869ebccf1e3SJoseph Koshy 2870ebccf1e3SJoseph Koshy pmc_attach_args.pm_pmc = pmc; 2871ebccf1e3SJoseph Koshy pmc_attach_args.pm_pid = pid; 2872ebccf1e3SJoseph Koshy 2873aa342b1fSJoseph Koshy return (PMC_CALL(PMCATTACH, &pmc_attach_args)); 2874ebccf1e3SJoseph Koshy } 2875ebccf1e3SJoseph Koshy 2876ebccf1e3SJoseph Koshy int 2877c5153e19SJoseph Koshy pmc_capabilities(pmc_id_t pmcid, uint32_t *caps) 2878c5153e19SJoseph Koshy { 2879c5153e19SJoseph Koshy unsigned int i; 2880c5153e19SJoseph Koshy enum pmc_class cl; 2881c5153e19SJoseph Koshy 2882c5153e19SJoseph Koshy cl = PMC_ID_TO_CLASS(pmcid); 2883c5153e19SJoseph Koshy for (i = 0; i < cpu_info.pm_nclass; i++) 2884c5153e19SJoseph Koshy if (cpu_info.pm_classes[i].pm_class == cl) { 2885c5153e19SJoseph Koshy *caps = cpu_info.pm_classes[i].pm_caps; 2886aa342b1fSJoseph Koshy return (0); 2887c5153e19SJoseph Koshy } 2888484202faSJoseph Koshy errno = EINVAL; 2889484202faSJoseph Koshy return (-1); 2890c5153e19SJoseph Koshy } 2891c5153e19SJoseph Koshy 2892f263522aSJoseph Koshy int 2893f263522aSJoseph Koshy pmc_configure_logfile(int fd) 2894ebccf1e3SJoseph Koshy { 2895f263522aSJoseph Koshy struct pmc_op_configurelog cla; 2896f263522aSJoseph Koshy 2897f263522aSJoseph Koshy cla.pm_logfd = fd; 2898f263522aSJoseph Koshy if (PMC_CALL(CONFIGURELOG, &cla) < 0) 2899aa342b1fSJoseph Koshy return (-1); 2900aa342b1fSJoseph Koshy return (0); 2901ebccf1e3SJoseph Koshy } 2902ebccf1e3SJoseph Koshy 2903f263522aSJoseph Koshy int 2904f263522aSJoseph Koshy pmc_cpuinfo(const struct pmc_cpuinfo **pci) 2905ebccf1e3SJoseph Koshy { 2906f263522aSJoseph Koshy if (pmc_syscall == -1) { 2907f263522aSJoseph Koshy errno = ENXIO; 2908aa342b1fSJoseph Koshy return (-1); 2909ebccf1e3SJoseph Koshy } 2910ebccf1e3SJoseph Koshy 29111455fcd3SJoseph Koshy *pci = &cpu_info; 2912aa342b1fSJoseph Koshy return (0); 2913ebccf1e3SJoseph Koshy } 2914ebccf1e3SJoseph Koshy 2915f263522aSJoseph Koshy int 2916f263522aSJoseph Koshy pmc_detach(pmc_id_t pmc, pid_t pid) 2917ebccf1e3SJoseph Koshy { 2918f263522aSJoseph Koshy struct pmc_op_pmcattach pmc_detach_args; 2919ebccf1e3SJoseph Koshy 2920f263522aSJoseph Koshy pmc_detach_args.pm_pmc = pmc; 2921f263522aSJoseph Koshy pmc_detach_args.pm_pid = pid; 2922aa342b1fSJoseph Koshy return (PMC_CALL(PMCDETACH, &pmc_detach_args)); 2923ebccf1e3SJoseph Koshy } 2924ebccf1e3SJoseph Koshy 2925f263522aSJoseph Koshy int 2926f263522aSJoseph Koshy pmc_disable(int cpu, int pmc) 2927ebccf1e3SJoseph Koshy { 2928f263522aSJoseph Koshy struct pmc_op_pmcadmin ssa; 2929ebccf1e3SJoseph Koshy 2930f263522aSJoseph Koshy ssa.pm_cpu = cpu; 2931f263522aSJoseph Koshy ssa.pm_pmc = pmc; 2932f263522aSJoseph Koshy ssa.pm_state = PMC_STATE_DISABLED; 2933aa342b1fSJoseph Koshy return (PMC_CALL(PMCADMIN, &ssa)); 2934ebccf1e3SJoseph Koshy } 2935ebccf1e3SJoseph Koshy 2936f263522aSJoseph Koshy int 2937f263522aSJoseph Koshy pmc_enable(int cpu, int pmc) 2938ebccf1e3SJoseph Koshy { 2939f263522aSJoseph Koshy struct pmc_op_pmcadmin ssa; 2940ebccf1e3SJoseph Koshy 2941f263522aSJoseph Koshy ssa.pm_cpu = cpu; 2942f263522aSJoseph Koshy ssa.pm_pmc = pmc; 2943f263522aSJoseph Koshy ssa.pm_state = PMC_STATE_FREE; 2944aa342b1fSJoseph Koshy return (PMC_CALL(PMCADMIN, &ssa)); 2945ebccf1e3SJoseph Koshy } 2946ebccf1e3SJoseph Koshy 2947ebccf1e3SJoseph Koshy /* 2948ebccf1e3SJoseph Koshy * Return a list of events known to a given PMC class. 'cl' is the 2949ebccf1e3SJoseph Koshy * PMC class identifier, 'eventnames' is the returned list of 'const 2950ebccf1e3SJoseph Koshy * char *' pointers pointing to the names of the events. 'nevents' is 2951ebccf1e3SJoseph Koshy * the number of event name pointers returned. 2952ebccf1e3SJoseph Koshy * 2953ebccf1e3SJoseph Koshy * The space for 'eventnames' is allocated using malloc(3). The caller 2954ebccf1e3SJoseph Koshy * is responsible for freeing this space when done. 2955ebccf1e3SJoseph Koshy */ 2956ebccf1e3SJoseph Koshy int 2957ebccf1e3SJoseph Koshy pmc_event_names_of_class(enum pmc_class cl, const char ***eventnames, 2958ebccf1e3SJoseph Koshy int *nevents) 2959ebccf1e3SJoseph Koshy { 2960ebccf1e3SJoseph Koshy int count; 2961ebccf1e3SJoseph Koshy const char **names; 2962ebccf1e3SJoseph Koshy const struct pmc_event_descr *ev; 2963ebccf1e3SJoseph Koshy 2964ebccf1e3SJoseph Koshy switch (cl) 2965ebccf1e3SJoseph Koshy { 29660cfab8ddSJoseph Koshy case PMC_CLASS_IAF: 29670cfab8ddSJoseph Koshy ev = iaf_event_table; 29680cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(iaf); 29690cfab8ddSJoseph Koshy break; 29700cfab8ddSJoseph Koshy case PMC_CLASS_IAP: 29710cfab8ddSJoseph Koshy /* 29720cfab8ddSJoseph Koshy * Return the most appropriate set of event name 29730cfab8ddSJoseph Koshy * spellings for the current CPU. 29740cfab8ddSJoseph Koshy */ 29750cfab8ddSJoseph Koshy switch (cpu_info.pm_cputype) { 29760cfab8ddSJoseph Koshy default: 29770cfab8ddSJoseph Koshy case PMC_CPU_INTEL_ATOM: 29780cfab8ddSJoseph Koshy ev = atom_event_table; 29790cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(atom); 29800cfab8ddSJoseph Koshy break; 2981e8f021a3SHiren Panchasara case PMC_CPU_INTEL_ATOM_SILVERMONT: 2982e8f021a3SHiren Panchasara ev = atom_silvermont_event_table; 2983e8f021a3SHiren Panchasara count = PMC_EVENT_TABLE_SIZE(atom_silvermont); 2984e8f021a3SHiren Panchasara break; 29850cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE: 29860cfab8ddSJoseph Koshy ev = core_event_table; 29870cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(core); 29880cfab8ddSJoseph Koshy break; 29890cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE2: 2990b4d091f3SJoseph Koshy case PMC_CPU_INTEL_CORE2EXTREME: 29910cfab8ddSJoseph Koshy ev = core2_event_table; 29920cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(core2); 29930cfab8ddSJoseph Koshy break; 2994597979c4SJeff Roberson case PMC_CPU_INTEL_COREI7: 2995597979c4SJeff Roberson ev = corei7_event_table; 2996597979c4SJeff Roberson count = PMC_EVENT_TABLE_SIZE(corei7); 2997597979c4SJeff Roberson break; 299849fe48abSKonstantin Belousov case PMC_CPU_INTEL_NEHALEM_EX: 299949fe48abSKonstantin Belousov ev = nehalem_ex_event_table; 300049fe48abSKonstantin Belousov count = PMC_EVENT_TABLE_SIZE(nehalem_ex); 300149fe48abSKonstantin Belousov break; 3002cc0c1555SSean Bruno case PMC_CPU_INTEL_HASWELL: 3003cc0c1555SSean Bruno ev = haswell_event_table; 3004cc0c1555SSean Bruno count = PMC_EVENT_TABLE_SIZE(haswell); 3005cc0c1555SSean Bruno break; 3006d95b3509SRandall Stewart case PMC_CPU_INTEL_HASWELL_XEON: 3007d95b3509SRandall Stewart ev = haswell_xeon_event_table; 3008d95b3509SRandall Stewart count = PMC_EVENT_TABLE_SIZE(haswell_xeon); 3009d95b3509SRandall Stewart break; 3010f19bae41SRandall Stewart case PMC_CPU_INTEL_BROADWELL: 3011f19bae41SRandall Stewart ev = broadwell_event_table; 3012f19bae41SRandall Stewart count = PMC_EVENT_TABLE_SIZE(broadwell); 3013f19bae41SRandall Stewart break; 3014f19bae41SRandall Stewart case PMC_CPU_INTEL_BROADWELL_XEON: 3015f19bae41SRandall Stewart ev = broadwell_xeon_event_table; 3016f19bae41SRandall Stewart count = PMC_EVENT_TABLE_SIZE(broadwell_xeon); 3017f19bae41SRandall Stewart break; 3018f19bae41SRandall Stewart case PMC_CPU_INTEL_SKYLAKE: 3019f19bae41SRandall Stewart ev = skylake_event_table; 3020f19bae41SRandall Stewart count = PMC_EVENT_TABLE_SIZE(skylake); 3021f19bae41SRandall Stewart break; 3022b99b705dSKonstantin Belousov case PMC_CPU_INTEL_SKYLAKE_XEON: 3023b99b705dSKonstantin Belousov ev = skylake_xeon_event_table; 3024b99b705dSKonstantin Belousov count = PMC_EVENT_TABLE_SIZE(skylake_xeon); 3025b99b705dSKonstantin Belousov break; 30261e862e5aSFabien Thomas case PMC_CPU_INTEL_IVYBRIDGE: 30271e862e5aSFabien Thomas ev = ivybridge_event_table; 30281e862e5aSFabien Thomas count = PMC_EVENT_TABLE_SIZE(ivybridge); 30291e862e5aSFabien Thomas break; 30303f929d8cSSean Bruno case PMC_CPU_INTEL_IVYBRIDGE_XEON: 30313f929d8cSSean Bruno ev = ivybridge_xeon_event_table; 30323f929d8cSSean Bruno count = PMC_EVENT_TABLE_SIZE(ivybridge_xeon); 30333f929d8cSSean Bruno break; 303478d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 303578d763a2SDavide Italiano ev = sandybridge_event_table; 303678d763a2SDavide Italiano count = PMC_EVENT_TABLE_SIZE(sandybridge); 303778d763a2SDavide Italiano break; 3038fabe02f5SSean Bruno case PMC_CPU_INTEL_SANDYBRIDGE_XEON: 3039fabe02f5SSean Bruno ev = sandybridge_xeon_event_table; 3040fabe02f5SSean Bruno count = PMC_EVENT_TABLE_SIZE(sandybridge_xeon); 3041fabe02f5SSean Bruno break; 30421fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 30431fa7f10bSFabien Thomas ev = westmere_event_table; 30441fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(westmere); 30451fa7f10bSFabien Thomas break; 304649fe48abSKonstantin Belousov case PMC_CPU_INTEL_WESTMERE_EX: 304749fe48abSKonstantin Belousov ev = westmere_ex_event_table; 304849fe48abSKonstantin Belousov count = PMC_EVENT_TABLE_SIZE(westmere_ex); 304949fe48abSKonstantin Belousov break; 30501fa7f10bSFabien Thomas } 30511fa7f10bSFabien Thomas break; 30521fa7f10bSFabien Thomas case PMC_CLASS_UCF: 30531fa7f10bSFabien Thomas ev = ucf_event_table; 30541fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(ucf); 30551fa7f10bSFabien Thomas break; 30561fa7f10bSFabien Thomas case PMC_CLASS_UCP: 30571fa7f10bSFabien Thomas /* 30581fa7f10bSFabien Thomas * Return the most appropriate set of event name 30591fa7f10bSFabien Thomas * spellings for the current CPU. 30601fa7f10bSFabien Thomas */ 30611fa7f10bSFabien Thomas switch (cpu_info.pm_cputype) { 30621fa7f10bSFabien Thomas default: 30631fa7f10bSFabien Thomas case PMC_CPU_INTEL_COREI7: 30641fa7f10bSFabien Thomas ev = corei7uc_event_table; 30651fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(corei7uc); 30661fa7f10bSFabien Thomas break; 3067cc0c1555SSean Bruno case PMC_CPU_INTEL_HASWELL: 3068cc0c1555SSean Bruno ev = haswelluc_event_table; 3069cc0c1555SSean Bruno count = PMC_EVENT_TABLE_SIZE(haswelluc); 3070cc0c1555SSean Bruno break; 3071f19bae41SRandall Stewart case PMC_CPU_INTEL_BROADWELL: 3072f19bae41SRandall Stewart ev = broadwelluc_event_table; 3073f19bae41SRandall Stewart count = PMC_EVENT_TABLE_SIZE(broadwelluc); 3074f19bae41SRandall Stewart break; 307578d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 307678d763a2SDavide Italiano ev = sandybridgeuc_event_table; 307778d763a2SDavide Italiano count = PMC_EVENT_TABLE_SIZE(sandybridgeuc); 307878d763a2SDavide Italiano break; 30791fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 30801fa7f10bSFabien Thomas ev = westmereuc_event_table; 30811fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(westmereuc); 30821fa7f10bSFabien Thomas break; 30830cfab8ddSJoseph Koshy } 30840cfab8ddSJoseph Koshy break; 3085ebccf1e3SJoseph Koshy case PMC_CLASS_TSC: 3086789140c0SJoseph Koshy ev = tsc_event_table; 3087789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(tsc); 3088ebccf1e3SJoseph Koshy break; 3089ebccf1e3SJoseph Koshy case PMC_CLASS_K7: 3090789140c0SJoseph Koshy ev = k7_event_table; 3091789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(k7); 3092ebccf1e3SJoseph Koshy break; 3093ebccf1e3SJoseph Koshy case PMC_CLASS_K8: 3094789140c0SJoseph Koshy ev = k8_event_table; 3095789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(k8); 3096ebccf1e3SJoseph Koshy break; 3097ebccf1e3SJoseph Koshy case PMC_CLASS_P4: 3098789140c0SJoseph Koshy ev = p4_event_table; 3099789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p4); 3100789140c0SJoseph Koshy break; 3101789140c0SJoseph Koshy case PMC_CLASS_P5: 3102789140c0SJoseph Koshy ev = p5_event_table; 3103789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p5); 3104789140c0SJoseph Koshy break; 3105789140c0SJoseph Koshy case PMC_CLASS_P6: 3106789140c0SJoseph Koshy ev = p6_event_table; 3107789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p6); 3108ebccf1e3SJoseph Koshy break; 31090ce207d2SRui Paulo case PMC_CLASS_XSCALE: 31100ce207d2SRui Paulo ev = xscale_event_table; 31110ce207d2SRui Paulo count = PMC_EVENT_TABLE_SIZE(xscale); 31120ce207d2SRui Paulo break; 31136411d14dSRuslan Bukin case PMC_CLASS_ARMV7: 31143e0bfdd8SRuslan Bukin switch (cpu_info.pm_cputype) { 31153e0bfdd8SRuslan Bukin default: 31163e0bfdd8SRuslan Bukin case PMC_CPU_ARMV7_CORTEX_A8: 31173e0bfdd8SRuslan Bukin ev = cortex_a8_event_table; 31183e0bfdd8SRuslan Bukin count = PMC_EVENT_TABLE_SIZE(cortex_a8); 31193e0bfdd8SRuslan Bukin break; 31203e0bfdd8SRuslan Bukin case PMC_CPU_ARMV7_CORTEX_A9: 31213e0bfdd8SRuslan Bukin ev = cortex_a9_event_table; 31223e0bfdd8SRuslan Bukin count = PMC_EVENT_TABLE_SIZE(cortex_a9); 31233e0bfdd8SRuslan Bukin break; 31243e0bfdd8SRuslan Bukin } 31256411d14dSRuslan Bukin break; 3126bc88bb2bSRuslan Bukin case PMC_CLASS_ARMV8: 3127bc88bb2bSRuslan Bukin switch (cpu_info.pm_cputype) { 3128bc88bb2bSRuslan Bukin default: 3129bc88bb2bSRuslan Bukin case PMC_CPU_ARMV8_CORTEX_A53: 3130bc88bb2bSRuslan Bukin ev = cortex_a53_event_table; 3131bc88bb2bSRuslan Bukin count = PMC_EVENT_TABLE_SIZE(cortex_a53); 3132bc88bb2bSRuslan Bukin break; 3133bc88bb2bSRuslan Bukin case PMC_CPU_ARMV8_CORTEX_A57: 3134bc88bb2bSRuslan Bukin ev = cortex_a57_event_table; 3135bc88bb2bSRuslan Bukin count = PMC_EVENT_TABLE_SIZE(cortex_a57); 3136bc88bb2bSRuslan Bukin break; 3137bc88bb2bSRuslan Bukin } 3138bc88bb2bSRuslan Bukin break; 3139660df75eSGeorge V. Neville-Neil case PMC_CLASS_MIPS24K: 3140660df75eSGeorge V. Neville-Neil ev = mips24k_event_table; 3141660df75eSGeorge V. Neville-Neil count = PMC_EVENT_TABLE_SIZE(mips24k); 3142660df75eSGeorge V. Neville-Neil break; 3143f6e6460dSAdrian Chadd case PMC_CLASS_MIPS74K: 3144f6e6460dSAdrian Chadd ev = mips74k_event_table; 3145f6e6460dSAdrian Chadd count = PMC_EVENT_TABLE_SIZE(mips74k); 3146f6e6460dSAdrian Chadd break; 3147c2657f80SOleksandr Tymoshenko case PMC_CLASS_OCTEON: 3148c2657f80SOleksandr Tymoshenko ev = octeon_event_table; 3149c2657f80SOleksandr Tymoshenko count = PMC_EVENT_TABLE_SIZE(octeon); 3150c2657f80SOleksandr Tymoshenko break; 31517b25dccaSJustin Hibbits case PMC_CLASS_PPC7450: 31527b25dccaSJustin Hibbits ev = ppc7450_event_table; 31537b25dccaSJustin Hibbits count = PMC_EVENT_TABLE_SIZE(ppc7450); 31547b25dccaSJustin Hibbits break; 3155169dd953SJustin Hibbits case PMC_CLASS_PPC970: 3156169dd953SJustin Hibbits ev = ppc970_event_table; 3157169dd953SJustin Hibbits count = PMC_EVENT_TABLE_SIZE(ppc970); 3158169dd953SJustin Hibbits break; 3159a7452468SJustin Hibbits case PMC_CLASS_E500: 3160a7452468SJustin Hibbits ev = e500_event_table; 3161a7452468SJustin Hibbits count = PMC_EVENT_TABLE_SIZE(e500); 3162a7452468SJustin Hibbits break; 3163f5f9340bSFabien Thomas case PMC_CLASS_SOFT: 3164f5f9340bSFabien Thomas ev = soft_event_table; 3165f5f9340bSFabien Thomas count = soft_event_info.pm_nevent; 3166f5f9340bSFabien Thomas break; 3167ebccf1e3SJoseph Koshy default: 3168ebccf1e3SJoseph Koshy errno = EINVAL; 3169aa342b1fSJoseph Koshy return (-1); 3170ebccf1e3SJoseph Koshy } 3171ebccf1e3SJoseph Koshy 3172ebccf1e3SJoseph Koshy if ((names = malloc(count * sizeof(const char *))) == NULL) 3173aa342b1fSJoseph Koshy return (-1); 3174ebccf1e3SJoseph Koshy 3175ebccf1e3SJoseph Koshy *eventnames = names; 3176ebccf1e3SJoseph Koshy *nevents = count; 3177ebccf1e3SJoseph Koshy 3178ebccf1e3SJoseph Koshy for (;count--; ev++, names++) 3179ebccf1e3SJoseph Koshy *names = ev->pm_ev_name; 3180f5f9340bSFabien Thomas 3181aa342b1fSJoseph Koshy return (0); 3182ebccf1e3SJoseph Koshy } 3183ebccf1e3SJoseph Koshy 3184f263522aSJoseph Koshy int 3185f263522aSJoseph Koshy pmc_flush_logfile(void) 3186f263522aSJoseph Koshy { 3187aa342b1fSJoseph Koshy return (PMC_CALL(FLUSHLOG,0)); 3188f263522aSJoseph Koshy } 3189ebccf1e3SJoseph Koshy 3190ebccf1e3SJoseph Koshy int 3191dceed24aSFabien Thomas pmc_close_logfile(void) 3192dceed24aSFabien Thomas { 3193dceed24aSFabien Thomas return (PMC_CALL(CLOSELOG,0)); 3194dceed24aSFabien Thomas } 3195dceed24aSFabien Thomas 3196dceed24aSFabien Thomas int 3197f263522aSJoseph Koshy pmc_get_driver_stats(struct pmc_driverstats *ds) 3198ebccf1e3SJoseph Koshy { 3199f263522aSJoseph Koshy struct pmc_op_getdriverstats gms; 3200f263522aSJoseph Koshy 3201f263522aSJoseph Koshy if (PMC_CALL(GETDRIVERSTATS, &gms) < 0) 3202aa342b1fSJoseph Koshy return (-1); 3203f263522aSJoseph Koshy 3204f263522aSJoseph Koshy /* copy out fields in the current userland<->library interface */ 3205f263522aSJoseph Koshy ds->pm_intr_ignored = gms.pm_intr_ignored; 3206f263522aSJoseph Koshy ds->pm_intr_processed = gms.pm_intr_processed; 3207f263522aSJoseph Koshy ds->pm_intr_bufferfull = gms.pm_intr_bufferfull; 3208f263522aSJoseph Koshy ds->pm_syscalls = gms.pm_syscalls; 3209f263522aSJoseph Koshy ds->pm_syscall_errors = gms.pm_syscall_errors; 3210f263522aSJoseph Koshy ds->pm_buffer_requests = gms.pm_buffer_requests; 3211f263522aSJoseph Koshy ds->pm_buffer_requests_failed = gms.pm_buffer_requests_failed; 3212f263522aSJoseph Koshy ds->pm_log_sweeps = gms.pm_log_sweeps; 3213aa342b1fSJoseph Koshy return (0); 3214f263522aSJoseph Koshy } 3215f263522aSJoseph Koshy 3216f263522aSJoseph Koshy int 3217f263522aSJoseph Koshy pmc_get_msr(pmc_id_t pmc, uint32_t *msr) 3218f263522aSJoseph Koshy { 3219f263522aSJoseph Koshy struct pmc_op_getmsr gm; 3220ebccf1e3SJoseph Koshy 3221ebccf1e3SJoseph Koshy gm.pm_pmcid = pmc; 3222f263522aSJoseph Koshy if (PMC_CALL(PMCGETMSR, &gm) < 0) 3223aa342b1fSJoseph Koshy return (-1); 3224ebccf1e3SJoseph Koshy *msr = gm.pm_msr; 3225aa342b1fSJoseph Koshy return (0); 3226ebccf1e3SJoseph Koshy } 3227ebccf1e3SJoseph Koshy 3228f263522aSJoseph Koshy int 3229f263522aSJoseph Koshy pmc_init(void) 3230f263522aSJoseph Koshy { 3231f263522aSJoseph Koshy int error, pmc_mod_id; 32321455fcd3SJoseph Koshy unsigned int n; 3233f263522aSJoseph Koshy uint32_t abi_version; 3234f263522aSJoseph Koshy struct module_stat pmc_modstat; 32351455fcd3SJoseph Koshy struct pmc_op_getcpuinfo op_cpu_info; 3236791f5d5bSJoseph Koshy #if defined(__amd64__) || defined(__i386__) 3237791f5d5bSJoseph Koshy int cpu_has_iaf_counters; 3238791f5d5bSJoseph Koshy unsigned int t; 3239791f5d5bSJoseph Koshy #endif 3240f263522aSJoseph Koshy 3241f263522aSJoseph Koshy if (pmc_syscall != -1) /* already inited */ 3242aa342b1fSJoseph Koshy return (0); 3243f263522aSJoseph Koshy 3244f263522aSJoseph Koshy /* retrieve the system call number from the KLD */ 3245f263522aSJoseph Koshy if ((pmc_mod_id = modfind(PMC_MODULE_NAME)) < 0) 3246aa342b1fSJoseph Koshy return (-1); 3247f263522aSJoseph Koshy 3248f263522aSJoseph Koshy pmc_modstat.version = sizeof(struct module_stat); 3249f263522aSJoseph Koshy if ((error = modstat(pmc_mod_id, &pmc_modstat)) < 0) 3250aa342b1fSJoseph Koshy return (-1); 3251f263522aSJoseph Koshy 3252f263522aSJoseph Koshy pmc_syscall = pmc_modstat.data.intval; 3253f263522aSJoseph Koshy 3254f263522aSJoseph Koshy /* check the kernel module's ABI against our compiled-in version */ 3255f263522aSJoseph Koshy abi_version = PMC_VERSION; 3256f263522aSJoseph Koshy if (PMC_CALL(GETMODULEVERSION, &abi_version) < 0) 3257f263522aSJoseph Koshy return (pmc_syscall = -1); 3258f263522aSJoseph Koshy 325975f46cf6SPedro F. Giffuni /* ignore patch & minor numbers for the comparison */ 3260f263522aSJoseph Koshy if ((abi_version & 0xFF000000) != (PMC_VERSION & 0xFF000000)) { 3261f263522aSJoseph Koshy errno = EPROGMISMATCH; 3262f263522aSJoseph Koshy return (pmc_syscall = -1); 3263f263522aSJoseph Koshy } 3264f263522aSJoseph Koshy 32651455fcd3SJoseph Koshy if (PMC_CALL(GETCPUINFO, &op_cpu_info) < 0) 3266f263522aSJoseph Koshy return (pmc_syscall = -1); 3267f263522aSJoseph Koshy 32681455fcd3SJoseph Koshy cpu_info.pm_cputype = op_cpu_info.pm_cputype; 32691455fcd3SJoseph Koshy cpu_info.pm_ncpu = op_cpu_info.pm_ncpu; 32701455fcd3SJoseph Koshy cpu_info.pm_npmc = op_cpu_info.pm_npmc; 32711455fcd3SJoseph Koshy cpu_info.pm_nclass = op_cpu_info.pm_nclass; 32721455fcd3SJoseph Koshy for (n = 0; n < cpu_info.pm_nclass; n++) 3273*b83aeb5cSJustin Hibbits memcpy(&cpu_info.pm_classes[n], &op_cpu_info.pm_classes[n], 3274*b83aeb5cSJustin Hibbits sizeof(cpu_info.pm_classes[n])); 32751455fcd3SJoseph Koshy 32760cfab8ddSJoseph Koshy pmc_class_table = malloc(PMC_CLASS_TABLE_SIZE * 32770cfab8ddSJoseph Koshy sizeof(struct pmc_class_descr *)); 32780cfab8ddSJoseph Koshy 32790cfab8ddSJoseph Koshy if (pmc_class_table == NULL) 32800cfab8ddSJoseph Koshy return (-1); 32810cfab8ddSJoseph Koshy 3282791f5d5bSJoseph Koshy for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) 3283791f5d5bSJoseph Koshy pmc_class_table[n] = NULL; 32840cfab8ddSJoseph Koshy 32850cfab8ddSJoseph Koshy /* 3286f5f9340bSFabien Thomas * Get soft events list. 3287f5f9340bSFabien Thomas */ 3288f5f9340bSFabien Thomas soft_event_info.pm_class = PMC_CLASS_SOFT; 3289f5f9340bSFabien Thomas if (PMC_CALL(GETDYNEVENTINFO, &soft_event_info) < 0) 3290f5f9340bSFabien Thomas return (pmc_syscall = -1); 3291f5f9340bSFabien Thomas 3292f5f9340bSFabien Thomas /* Map soft events to static list. */ 3293f5f9340bSFabien Thomas for (n = 0; n < soft_event_info.pm_nevent; n++) { 3294f5f9340bSFabien Thomas soft_event_table[n].pm_ev_name = 3295f5f9340bSFabien Thomas soft_event_info.pm_events[n].pm_ev_name; 3296f5f9340bSFabien Thomas soft_event_table[n].pm_ev_code = 3297f5f9340bSFabien Thomas soft_event_info.pm_events[n].pm_ev_code; 3298f5f9340bSFabien Thomas } 3299f5f9340bSFabien Thomas soft_class_table_descr.pm_evc_event_table_size = \ 3300f5f9340bSFabien Thomas soft_event_info.pm_nevent; 3301f5f9340bSFabien Thomas soft_class_table_descr.pm_evc_event_table = \ 3302f5f9340bSFabien Thomas soft_event_table; 3303f5f9340bSFabien Thomas 3304f5f9340bSFabien Thomas /* 33050cfab8ddSJoseph Koshy * Fill in the class table. 33060cfab8ddSJoseph Koshy */ 33070cfab8ddSJoseph Koshy n = 0; 3308f5f9340bSFabien Thomas 3309f5f9340bSFabien Thomas /* Fill soft events information. */ 3310f5f9340bSFabien Thomas pmc_class_table[n++] = &soft_class_table_descr; 33110cfab8ddSJoseph Koshy #if defined(__amd64__) || defined(__i386__) 3312f5f9340bSFabien Thomas if (cpu_info.pm_cputype != PMC_CPU_GENERIC) 33130cfab8ddSJoseph Koshy pmc_class_table[n++] = &tsc_class_table_descr; 3314791f5d5bSJoseph Koshy 3315791f5d5bSJoseph Koshy /* 3316791f5d5bSJoseph Koshy * Check if this CPU has fixed function counters. 3317791f5d5bSJoseph Koshy */ 3318791f5d5bSJoseph Koshy cpu_has_iaf_counters = 0; 3319791f5d5bSJoseph Koshy for (t = 0; t < cpu_info.pm_nclass; t++) 33202aef9dd6SFabien Thomas if (cpu_info.pm_classes[t].pm_class == PMC_CLASS_IAF && 33212aef9dd6SFabien Thomas cpu_info.pm_classes[t].pm_num > 0) 3322791f5d5bSJoseph Koshy cpu_has_iaf_counters = 1; 33230cfab8ddSJoseph Koshy #endif 33240cfab8ddSJoseph Koshy 3325789140c0SJoseph Koshy #define PMC_MDEP_INIT(C) do { \ 3326789140c0SJoseph Koshy pmc_mdep_event_aliases = C##_aliases; \ 3327789140c0SJoseph Koshy pmc_mdep_class_list = C##_pmc_classes; \ 3328789140c0SJoseph Koshy pmc_mdep_class_list_size = \ 3329789140c0SJoseph Koshy PMC_TABLE_SIZE(C##_pmc_classes); \ 3330789140c0SJoseph Koshy } while (0) 3331789140c0SJoseph Koshy 3332791f5d5bSJoseph Koshy #define PMC_MDEP_INIT_INTEL_V2(C) do { \ 3333791f5d5bSJoseph Koshy PMC_MDEP_INIT(C); \ 3334791f5d5bSJoseph Koshy pmc_class_table[n++] = &iaf_class_table_descr; \ 33352aef9dd6SFabien Thomas if (!cpu_has_iaf_counters) \ 3336791f5d5bSJoseph Koshy pmc_mdep_event_aliases = \ 3337791f5d5bSJoseph Koshy C##_aliases_without_iaf; \ 3338791f5d5bSJoseph Koshy pmc_class_table[n] = &C##_class_table_descr; \ 3339791f5d5bSJoseph Koshy } while (0) 3340791f5d5bSJoseph Koshy 3341789140c0SJoseph Koshy /* Configure the event name parser. */ 3342f263522aSJoseph Koshy switch (cpu_info.pm_cputype) { 3343f263522aSJoseph Koshy #if defined(__i386__) 3344f263522aSJoseph Koshy case PMC_CPU_AMD_K7: 3345789140c0SJoseph Koshy PMC_MDEP_INIT(k7); 33460cfab8ddSJoseph Koshy pmc_class_table[n] = &k7_class_table_descr; 3347f263522aSJoseph Koshy break; 3348f263522aSJoseph Koshy case PMC_CPU_INTEL_P5: 3349789140c0SJoseph Koshy PMC_MDEP_INIT(p5); 33500cfab8ddSJoseph Koshy pmc_class_table[n] = &p5_class_table_descr; 3351f263522aSJoseph Koshy break; 3352f263522aSJoseph Koshy case PMC_CPU_INTEL_P6: /* P6 ... Pentium M CPUs have */ 3353f263522aSJoseph Koshy case PMC_CPU_INTEL_PII: /* similar PMCs. */ 3354f263522aSJoseph Koshy case PMC_CPU_INTEL_PIII: 3355f263522aSJoseph Koshy case PMC_CPU_INTEL_PM: 3356789140c0SJoseph Koshy PMC_MDEP_INIT(p6); 33570cfab8ddSJoseph Koshy pmc_class_table[n] = &p6_class_table_descr; 3358f263522aSJoseph Koshy break; 335986a65549SJoseph Koshy #endif 336086a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 3361f263522aSJoseph Koshy case PMC_CPU_AMD_K8: 3362789140c0SJoseph Koshy PMC_MDEP_INIT(k8); 33630cfab8ddSJoseph Koshy pmc_class_table[n] = &k8_class_table_descr; 33640cfab8ddSJoseph Koshy break; 33650cfab8ddSJoseph Koshy case PMC_CPU_INTEL_ATOM: 3366791f5d5bSJoseph Koshy PMC_MDEP_INIT_INTEL_V2(atom); 33670cfab8ddSJoseph Koshy break; 3368e8f021a3SHiren Panchasara case PMC_CPU_INTEL_ATOM_SILVERMONT: 3369e8f021a3SHiren Panchasara PMC_MDEP_INIT_INTEL_V2(atom_silvermont); 3370e8f021a3SHiren Panchasara break; 33710cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE: 33720cfab8ddSJoseph Koshy PMC_MDEP_INIT(core); 3373bc315bbdSJoseph Koshy pmc_class_table[n] = &core_class_table_descr; 33740cfab8ddSJoseph Koshy break; 33750cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE2: 3376b4d091f3SJoseph Koshy case PMC_CPU_INTEL_CORE2EXTREME: 3377791f5d5bSJoseph Koshy PMC_MDEP_INIT_INTEL_V2(core2); 3378789140c0SJoseph Koshy break; 3379597979c4SJeff Roberson case PMC_CPU_INTEL_COREI7: 33801fa7f10bSFabien Thomas pmc_class_table[n++] = &ucf_class_table_descr; 33811fa7f10bSFabien Thomas pmc_class_table[n++] = &corei7uc_class_table_descr; 3382791f5d5bSJoseph Koshy PMC_MDEP_INIT_INTEL_V2(corei7); 3383597979c4SJeff Roberson break; 338449fe48abSKonstantin Belousov case PMC_CPU_INTEL_NEHALEM_EX: 338549fe48abSKonstantin Belousov PMC_MDEP_INIT_INTEL_V2(nehalem_ex); 338649fe48abSKonstantin Belousov break; 3387cc0c1555SSean Bruno case PMC_CPU_INTEL_HASWELL: 3388cc0c1555SSean Bruno pmc_class_table[n++] = &ucf_class_table_descr; 3389cc0c1555SSean Bruno pmc_class_table[n++] = &haswelluc_class_table_descr; 3390cc0c1555SSean Bruno PMC_MDEP_INIT_INTEL_V2(haswell); 3391cc0c1555SSean Bruno break; 3392d95b3509SRandall Stewart case PMC_CPU_INTEL_HASWELL_XEON: 3393d95b3509SRandall Stewart PMC_MDEP_INIT_INTEL_V2(haswell_xeon); 3394d95b3509SRandall Stewart break; 3395f19bae41SRandall Stewart case PMC_CPU_INTEL_BROADWELL: 3396f19bae41SRandall Stewart pmc_class_table[n++] = &ucf_class_table_descr; 3397f19bae41SRandall Stewart pmc_class_table[n++] = &broadwelluc_class_table_descr; 3398f19bae41SRandall Stewart PMC_MDEP_INIT_INTEL_V2(broadwell); 3399f19bae41SRandall Stewart break; 3400f19bae41SRandall Stewart case PMC_CPU_INTEL_BROADWELL_XEON: 3401f19bae41SRandall Stewart PMC_MDEP_INIT_INTEL_V2(broadwell_xeon); 3402f19bae41SRandall Stewart break; 3403f19bae41SRandall Stewart case PMC_CPU_INTEL_SKYLAKE: 3404f19bae41SRandall Stewart PMC_MDEP_INIT_INTEL_V2(skylake); 3405f19bae41SRandall Stewart break; 3406b99b705dSKonstantin Belousov case PMC_CPU_INTEL_SKYLAKE_XEON: 3407b99b705dSKonstantin Belousov PMC_MDEP_INIT_INTEL_V2(skylake_xeon); 3408b99b705dSKonstantin Belousov break; 34091e862e5aSFabien Thomas case PMC_CPU_INTEL_IVYBRIDGE: 34101e862e5aSFabien Thomas PMC_MDEP_INIT_INTEL_V2(ivybridge); 34111e862e5aSFabien Thomas break; 34123f929d8cSSean Bruno case PMC_CPU_INTEL_IVYBRIDGE_XEON: 34133f929d8cSSean Bruno PMC_MDEP_INIT_INTEL_V2(ivybridge_xeon); 34143f929d8cSSean Bruno break; 341578d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 341678d763a2SDavide Italiano pmc_class_table[n++] = &ucf_class_table_descr; 341778d763a2SDavide Italiano pmc_class_table[n++] = &sandybridgeuc_class_table_descr; 341878d763a2SDavide Italiano PMC_MDEP_INIT_INTEL_V2(sandybridge); 341978d763a2SDavide Italiano break; 3420fabe02f5SSean Bruno case PMC_CPU_INTEL_SANDYBRIDGE_XEON: 3421fabe02f5SSean Bruno PMC_MDEP_INIT_INTEL_V2(sandybridge_xeon); 3422fabe02f5SSean Bruno break; 34231fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 34241fa7f10bSFabien Thomas pmc_class_table[n++] = &ucf_class_table_descr; 34251fa7f10bSFabien Thomas pmc_class_table[n++] = &westmereuc_class_table_descr; 34261fa7f10bSFabien Thomas PMC_MDEP_INIT_INTEL_V2(westmere); 34271fa7f10bSFabien Thomas break; 342849fe48abSKonstantin Belousov case PMC_CPU_INTEL_WESTMERE_EX: 342949fe48abSKonstantin Belousov PMC_MDEP_INIT_INTEL_V2(westmere_ex); 343049fe48abSKonstantin Belousov break; 3431789140c0SJoseph Koshy case PMC_CPU_INTEL_PIV: 3432789140c0SJoseph Koshy PMC_MDEP_INIT(p4); 34330cfab8ddSJoseph Koshy pmc_class_table[n] = &p4_class_table_descr; 3434f263522aSJoseph Koshy break; 3435ebccf1e3SJoseph Koshy #endif 3436f5f9340bSFabien Thomas case PMC_CPU_GENERIC: 3437f5f9340bSFabien Thomas PMC_MDEP_INIT(generic); 3438f5f9340bSFabien Thomas break; 34396411d14dSRuslan Bukin #if defined(__arm__) 34400ce207d2SRui Paulo #if defined(__XSCALE__) 34410ce207d2SRui Paulo case PMC_CPU_INTEL_XSCALE: 34420ce207d2SRui Paulo PMC_MDEP_INIT(xscale); 34430ce207d2SRui Paulo pmc_class_table[n] = &xscale_class_table_descr; 34440ce207d2SRui Paulo break; 34450ce207d2SRui Paulo #endif 34463e0bfdd8SRuslan Bukin case PMC_CPU_ARMV7_CORTEX_A8: 34473e0bfdd8SRuslan Bukin PMC_MDEP_INIT(cortex_a8); 34483e0bfdd8SRuslan Bukin pmc_class_table[n] = &cortex_a8_class_table_descr; 34493e0bfdd8SRuslan Bukin break; 34503e0bfdd8SRuslan Bukin case PMC_CPU_ARMV7_CORTEX_A9: 34513e0bfdd8SRuslan Bukin PMC_MDEP_INIT(cortex_a9); 34523e0bfdd8SRuslan Bukin pmc_class_table[n] = &cortex_a9_class_table_descr; 34536411d14dSRuslan Bukin break; 34546411d14dSRuslan Bukin #endif 3455bc88bb2bSRuslan Bukin #if defined(__aarch64__) 3456bc88bb2bSRuslan Bukin case PMC_CPU_ARMV8_CORTEX_A53: 3457bc88bb2bSRuslan Bukin PMC_MDEP_INIT(cortex_a53); 3458bc88bb2bSRuslan Bukin pmc_class_table[n] = &cortex_a53_class_table_descr; 3459bc88bb2bSRuslan Bukin break; 3460bc88bb2bSRuslan Bukin case PMC_CPU_ARMV8_CORTEX_A57: 3461bc88bb2bSRuslan Bukin PMC_MDEP_INIT(cortex_a57); 3462bc88bb2bSRuslan Bukin pmc_class_table[n] = &cortex_a57_class_table_descr; 3463bc88bb2bSRuslan Bukin break; 3464bc88bb2bSRuslan Bukin #endif 3465660df75eSGeorge V. Neville-Neil #if defined(__mips__) 3466660df75eSGeorge V. Neville-Neil case PMC_CPU_MIPS_24K: 3467660df75eSGeorge V. Neville-Neil PMC_MDEP_INIT(mips24k); 3468660df75eSGeorge V. Neville-Neil pmc_class_table[n] = &mips24k_class_table_descr; 3469660df75eSGeorge V. Neville-Neil break; 3470f6e6460dSAdrian Chadd case PMC_CPU_MIPS_74K: 3471f6e6460dSAdrian Chadd PMC_MDEP_INIT(mips74k); 3472f6e6460dSAdrian Chadd pmc_class_table[n] = &mips74k_class_table_descr; 3473f6e6460dSAdrian Chadd break; 3474c2657f80SOleksandr Tymoshenko case PMC_CPU_MIPS_OCTEON: 3475c2657f80SOleksandr Tymoshenko PMC_MDEP_INIT(octeon); 3476c2657f80SOleksandr Tymoshenko pmc_class_table[n] = &octeon_class_table_descr; 3477c2657f80SOleksandr Tymoshenko break; 3478660df75eSGeorge V. Neville-Neil #endif /* __mips__ */ 34797b25dccaSJustin Hibbits #if defined(__powerpc__) 34807b25dccaSJustin Hibbits case PMC_CPU_PPC_7450: 34817b25dccaSJustin Hibbits PMC_MDEP_INIT(ppc7450); 34827b25dccaSJustin Hibbits pmc_class_table[n] = &ppc7450_class_table_descr; 34837b25dccaSJustin Hibbits break; 3484169dd953SJustin Hibbits case PMC_CPU_PPC_970: 3485169dd953SJustin Hibbits PMC_MDEP_INIT(ppc970); 3486169dd953SJustin Hibbits pmc_class_table[n] = &ppc970_class_table_descr; 3487169dd953SJustin Hibbits break; 3488a7452468SJustin Hibbits case PMC_CPU_PPC_E500: 3489a7452468SJustin Hibbits PMC_MDEP_INIT(e500); 3490a7452468SJustin Hibbits pmc_class_table[n] = &e500_class_table_descr; 3491a7452468SJustin Hibbits break; 34927b25dccaSJustin Hibbits #endif 3493f263522aSJoseph Koshy default: 3494f263522aSJoseph Koshy /* 3495f263522aSJoseph Koshy * Some kind of CPU this version of the library knows nothing 3496f263522aSJoseph Koshy * about. This shouldn't happen since the abi version check 3497f263522aSJoseph Koshy * should have caught this. 3498f263522aSJoseph Koshy */ 3499f263522aSJoseph Koshy errno = ENXIO; 3500f263522aSJoseph Koshy return (pmc_syscall = -1); 3501f263522aSJoseph Koshy } 3502f263522aSJoseph Koshy 3503aa342b1fSJoseph Koshy return (0); 3504f263522aSJoseph Koshy } 3505f263522aSJoseph Koshy 3506f263522aSJoseph Koshy const char * 3507f263522aSJoseph Koshy pmc_name_of_capability(enum pmc_caps cap) 3508f263522aSJoseph Koshy { 3509f263522aSJoseph Koshy int i; 3510f263522aSJoseph Koshy 3511f263522aSJoseph Koshy /* 3512f263522aSJoseph Koshy * 'cap' should have a single bit set and should be in 3513f263522aSJoseph Koshy * range. 3514f263522aSJoseph Koshy */ 3515f263522aSJoseph Koshy if ((cap & (cap - 1)) || cap < PMC_CAP_FIRST || 3516f263522aSJoseph Koshy cap > PMC_CAP_LAST) { 3517f263522aSJoseph Koshy errno = EINVAL; 3518aa342b1fSJoseph Koshy return (NULL); 3519f263522aSJoseph Koshy } 3520f263522aSJoseph Koshy 3521f263522aSJoseph Koshy i = ffs(cap); 3522aa342b1fSJoseph Koshy return (pmc_capability_names[i - 1]); 3523f263522aSJoseph Koshy } 3524f263522aSJoseph Koshy 3525f263522aSJoseph Koshy const char * 3526f263522aSJoseph Koshy pmc_name_of_class(enum pmc_class pc) 3527f263522aSJoseph Koshy { 35280ceb54c2SJohn Baldwin size_t n; 35290ceb54c2SJohn Baldwin 35300ceb54c2SJohn Baldwin for (n = 0; n < PMC_TABLE_SIZE(pmc_class_names); n++) 35310ceb54c2SJohn Baldwin if (pc == pmc_class_names[n].pm_class) 35320ceb54c2SJohn Baldwin return (pmc_class_names[n].pm_name); 3533f263522aSJoseph Koshy 3534f263522aSJoseph Koshy errno = EINVAL; 3535aa342b1fSJoseph Koshy return (NULL); 3536f263522aSJoseph Koshy } 3537f263522aSJoseph Koshy 3538f263522aSJoseph Koshy const char * 3539f263522aSJoseph Koshy pmc_name_of_cputype(enum pmc_cputype cp) 3540f263522aSJoseph Koshy { 3541789140c0SJoseph Koshy size_t n; 3542789140c0SJoseph Koshy 3543789140c0SJoseph Koshy for (n = 0; n < PMC_TABLE_SIZE(pmc_cputype_names); n++) 3544789140c0SJoseph Koshy if (cp == pmc_cputype_names[n].pm_cputype) 3545789140c0SJoseph Koshy return (pmc_cputype_names[n].pm_name); 3546789140c0SJoseph Koshy 3547f263522aSJoseph Koshy errno = EINVAL; 3548aa342b1fSJoseph Koshy return (NULL); 3549f263522aSJoseph Koshy } 3550f263522aSJoseph Koshy 3551f263522aSJoseph Koshy const char * 3552f263522aSJoseph Koshy pmc_name_of_disposition(enum pmc_disp pd) 3553f263522aSJoseph Koshy { 3554f263522aSJoseph Koshy if ((int) pd >= PMC_DISP_FIRST && 3555f263522aSJoseph Koshy pd <= PMC_DISP_LAST) 3556aa342b1fSJoseph Koshy return (pmc_disposition_names[pd]); 3557f263522aSJoseph Koshy 3558f263522aSJoseph Koshy errno = EINVAL; 3559aa342b1fSJoseph Koshy return (NULL); 3560f263522aSJoseph Koshy } 3561f263522aSJoseph Koshy 3562f263522aSJoseph Koshy const char * 35630cfab8ddSJoseph Koshy _pmc_name_of_event(enum pmc_event pe, enum pmc_cputype cpu) 3564f263522aSJoseph Koshy { 3565789140c0SJoseph Koshy const struct pmc_event_descr *ev, *evfence; 3566789140c0SJoseph Koshy 3567789140c0SJoseph Koshy ev = evfence = NULL; 35680cfab8ddSJoseph Koshy if (pe >= PMC_EV_IAF_FIRST && pe <= PMC_EV_IAF_LAST) { 35690cfab8ddSJoseph Koshy ev = iaf_event_table; 35700cfab8ddSJoseph Koshy evfence = iaf_event_table + PMC_EVENT_TABLE_SIZE(iaf); 35710cfab8ddSJoseph Koshy } else if (pe >= PMC_EV_IAP_FIRST && pe <= PMC_EV_IAP_LAST) { 35720cfab8ddSJoseph Koshy switch (cpu) { 35730cfab8ddSJoseph Koshy case PMC_CPU_INTEL_ATOM: 35740cfab8ddSJoseph Koshy ev = atom_event_table; 35750cfab8ddSJoseph Koshy evfence = atom_event_table + PMC_EVENT_TABLE_SIZE(atom); 35760cfab8ddSJoseph Koshy break; 3577e8f021a3SHiren Panchasara case PMC_CPU_INTEL_ATOM_SILVERMONT: 3578e8f021a3SHiren Panchasara ev = atom_silvermont_event_table; 3579e8f021a3SHiren Panchasara evfence = atom_silvermont_event_table + 3580e8f021a3SHiren Panchasara PMC_EVENT_TABLE_SIZE(atom_silvermont); 3581e8f021a3SHiren Panchasara break; 35820cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE: 35830cfab8ddSJoseph Koshy ev = core_event_table; 35840cfab8ddSJoseph Koshy evfence = core_event_table + PMC_EVENT_TABLE_SIZE(core); 35850cfab8ddSJoseph Koshy break; 35860cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE2: 3587b4d091f3SJoseph Koshy case PMC_CPU_INTEL_CORE2EXTREME: 35880cfab8ddSJoseph Koshy ev = core2_event_table; 35890cfab8ddSJoseph Koshy evfence = core2_event_table + PMC_EVENT_TABLE_SIZE(core2); 35900cfab8ddSJoseph Koshy break; 3591597979c4SJeff Roberson case PMC_CPU_INTEL_COREI7: 3592597979c4SJeff Roberson ev = corei7_event_table; 3593597979c4SJeff Roberson evfence = corei7_event_table + PMC_EVENT_TABLE_SIZE(corei7); 3594597979c4SJeff Roberson break; 359549fe48abSKonstantin Belousov case PMC_CPU_INTEL_NEHALEM_EX: 359649fe48abSKonstantin Belousov ev = nehalem_ex_event_table; 359749fe48abSKonstantin Belousov evfence = nehalem_ex_event_table + 359849fe48abSKonstantin Belousov PMC_EVENT_TABLE_SIZE(nehalem_ex); 359949fe48abSKonstantin Belousov break; 3600cc0c1555SSean Bruno case PMC_CPU_INTEL_HASWELL: 3601cc0c1555SSean Bruno ev = haswell_event_table; 3602cc0c1555SSean Bruno evfence = haswell_event_table + PMC_EVENT_TABLE_SIZE(haswell); 3603cc0c1555SSean Bruno break; 3604d95b3509SRandall Stewart case PMC_CPU_INTEL_HASWELL_XEON: 3605d95b3509SRandall Stewart ev = haswell_xeon_event_table; 3606d95b3509SRandall Stewart evfence = haswell_xeon_event_table + PMC_EVENT_TABLE_SIZE(haswell_xeon); 3607d95b3509SRandall Stewart break; 3608f19bae41SRandall Stewart case PMC_CPU_INTEL_BROADWELL: 3609f19bae41SRandall Stewart ev = broadwell_event_table; 3610f19bae41SRandall Stewart evfence = broadwell_event_table + PMC_EVENT_TABLE_SIZE(broadwell); 3611f19bae41SRandall Stewart break; 3612f19bae41SRandall Stewart case PMC_CPU_INTEL_BROADWELL_XEON: 3613f19bae41SRandall Stewart ev = broadwell_xeon_event_table; 3614f19bae41SRandall Stewart evfence = broadwell_xeon_event_table + PMC_EVENT_TABLE_SIZE(broadwell_xeon); 3615f19bae41SRandall Stewart break; 3616f19bae41SRandall Stewart case PMC_CPU_INTEL_SKYLAKE: 3617f19bae41SRandall Stewart ev = skylake_event_table; 36189491ba75SKonstantin Belousov evfence = skylake_event_table + 36199491ba75SKonstantin Belousov PMC_EVENT_TABLE_SIZE(skylake); 3620f19bae41SRandall Stewart break; 3621b99b705dSKonstantin Belousov case PMC_CPU_INTEL_SKYLAKE_XEON: 3622b99b705dSKonstantin Belousov ev = skylake_xeon_event_table; 3623b99b705dSKonstantin Belousov evfence = skylake_xeon_event_table + 3624b99b705dSKonstantin Belousov PMC_EVENT_TABLE_SIZE(skylake_xeon); 3625b99b705dSKonstantin Belousov break; 36261e862e5aSFabien Thomas case PMC_CPU_INTEL_IVYBRIDGE: 36271e862e5aSFabien Thomas ev = ivybridge_event_table; 36281e862e5aSFabien Thomas evfence = ivybridge_event_table + PMC_EVENT_TABLE_SIZE(ivybridge); 36291e862e5aSFabien Thomas break; 36303f929d8cSSean Bruno case PMC_CPU_INTEL_IVYBRIDGE_XEON: 36313f929d8cSSean Bruno ev = ivybridge_xeon_event_table; 36323f929d8cSSean Bruno evfence = ivybridge_xeon_event_table + PMC_EVENT_TABLE_SIZE(ivybridge_xeon); 36333f929d8cSSean Bruno break; 363478d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 363578d763a2SDavide Italiano ev = sandybridge_event_table; 363678d763a2SDavide Italiano evfence = sandybridge_event_table + PMC_EVENT_TABLE_SIZE(sandybridge); 363778d763a2SDavide Italiano break; 3638fabe02f5SSean Bruno case PMC_CPU_INTEL_SANDYBRIDGE_XEON: 3639fabe02f5SSean Bruno ev = sandybridge_xeon_event_table; 3640fabe02f5SSean Bruno evfence = sandybridge_xeon_event_table + PMC_EVENT_TABLE_SIZE(sandybridge_xeon); 3641fabe02f5SSean Bruno break; 36421fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 36431fa7f10bSFabien Thomas ev = westmere_event_table; 36441fa7f10bSFabien Thomas evfence = westmere_event_table + PMC_EVENT_TABLE_SIZE(westmere); 36451fa7f10bSFabien Thomas break; 364649fe48abSKonstantin Belousov case PMC_CPU_INTEL_WESTMERE_EX: 364749fe48abSKonstantin Belousov ev = westmere_ex_event_table; 364849fe48abSKonstantin Belousov evfence = westmere_ex_event_table + 364949fe48abSKonstantin Belousov PMC_EVENT_TABLE_SIZE(westmere_ex); 365049fe48abSKonstantin Belousov break; 36510cfab8ddSJoseph Koshy default: /* Unknown CPU type. */ 36520cfab8ddSJoseph Koshy break; 36530cfab8ddSJoseph Koshy } 36541fa7f10bSFabien Thomas } else if (pe >= PMC_EV_UCF_FIRST && pe <= PMC_EV_UCF_LAST) { 36551fa7f10bSFabien Thomas ev = ucf_event_table; 36561fa7f10bSFabien Thomas evfence = ucf_event_table + PMC_EVENT_TABLE_SIZE(ucf); 36571fa7f10bSFabien Thomas } else if (pe >= PMC_EV_UCP_FIRST && pe <= PMC_EV_UCP_LAST) { 36581fa7f10bSFabien Thomas switch (cpu) { 36591fa7f10bSFabien Thomas case PMC_CPU_INTEL_COREI7: 36601fa7f10bSFabien Thomas ev = corei7uc_event_table; 36611fa7f10bSFabien Thomas evfence = corei7uc_event_table + PMC_EVENT_TABLE_SIZE(corei7uc); 36621fa7f10bSFabien Thomas break; 366378d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 366478d763a2SDavide Italiano ev = sandybridgeuc_event_table; 366578d763a2SDavide Italiano evfence = sandybridgeuc_event_table + PMC_EVENT_TABLE_SIZE(sandybridgeuc); 366678d763a2SDavide Italiano break; 36671fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 36681fa7f10bSFabien Thomas ev = westmereuc_event_table; 36691fa7f10bSFabien Thomas evfence = westmereuc_event_table + PMC_EVENT_TABLE_SIZE(westmereuc); 36701fa7f10bSFabien Thomas break; 36711fa7f10bSFabien Thomas default: /* Unknown CPU type. */ 36721fa7f10bSFabien Thomas break; 36731fa7f10bSFabien Thomas } 36741fa7f10bSFabien Thomas } else if (pe >= PMC_EV_K7_FIRST && pe <= PMC_EV_K7_LAST) { 3675789140c0SJoseph Koshy ev = k7_event_table; 3676789140c0SJoseph Koshy evfence = k7_event_table + PMC_EVENT_TABLE_SIZE(k7); 3677789140c0SJoseph Koshy } else if (pe >= PMC_EV_K8_FIRST && pe <= PMC_EV_K8_LAST) { 3678789140c0SJoseph Koshy ev = k8_event_table; 3679789140c0SJoseph Koshy evfence = k8_event_table + PMC_EVENT_TABLE_SIZE(k8); 3680789140c0SJoseph Koshy } else if (pe >= PMC_EV_P4_FIRST && pe <= PMC_EV_P4_LAST) { 3681789140c0SJoseph Koshy ev = p4_event_table; 3682789140c0SJoseph Koshy evfence = p4_event_table + PMC_EVENT_TABLE_SIZE(p4); 3683789140c0SJoseph Koshy } else if (pe >= PMC_EV_P5_FIRST && pe <= PMC_EV_P5_LAST) { 3684789140c0SJoseph Koshy ev = p5_event_table; 3685789140c0SJoseph Koshy evfence = p5_event_table + PMC_EVENT_TABLE_SIZE(p5); 3686789140c0SJoseph Koshy } else if (pe >= PMC_EV_P6_FIRST && pe <= PMC_EV_P6_LAST) { 3687789140c0SJoseph Koshy ev = p6_event_table; 3688789140c0SJoseph Koshy evfence = p6_event_table + PMC_EVENT_TABLE_SIZE(p6); 36890ce207d2SRui Paulo } else if (pe >= PMC_EV_XSCALE_FIRST && pe <= PMC_EV_XSCALE_LAST) { 36900ce207d2SRui Paulo ev = xscale_event_table; 36910ce207d2SRui Paulo evfence = xscale_event_table + PMC_EVENT_TABLE_SIZE(xscale); 36926411d14dSRuslan Bukin } else if (pe >= PMC_EV_ARMV7_FIRST && pe <= PMC_EV_ARMV7_LAST) { 36933e0bfdd8SRuslan Bukin switch (cpu) { 36943e0bfdd8SRuslan Bukin case PMC_CPU_ARMV7_CORTEX_A8: 36953e0bfdd8SRuslan Bukin ev = cortex_a8_event_table; 36963e0bfdd8SRuslan Bukin evfence = cortex_a8_event_table + PMC_EVENT_TABLE_SIZE(cortex_a8); 36973e0bfdd8SRuslan Bukin break; 36983e0bfdd8SRuslan Bukin case PMC_CPU_ARMV7_CORTEX_A9: 36993e0bfdd8SRuslan Bukin ev = cortex_a9_event_table; 37003e0bfdd8SRuslan Bukin evfence = cortex_a9_event_table + PMC_EVENT_TABLE_SIZE(cortex_a9); 37013e0bfdd8SRuslan Bukin break; 37023e0bfdd8SRuslan Bukin default: /* Unknown CPU type. */ 37033e0bfdd8SRuslan Bukin break; 37043e0bfdd8SRuslan Bukin } 3705bc88bb2bSRuslan Bukin } else if (pe >= PMC_EV_ARMV8_FIRST && pe <= PMC_EV_ARMV8_LAST) { 3706bc88bb2bSRuslan Bukin switch (cpu) { 3707bc88bb2bSRuslan Bukin case PMC_CPU_ARMV8_CORTEX_A53: 3708bc88bb2bSRuslan Bukin ev = cortex_a53_event_table; 3709bc88bb2bSRuslan Bukin evfence = cortex_a53_event_table + PMC_EVENT_TABLE_SIZE(cortex_a53); 3710bc88bb2bSRuslan Bukin break; 3711bc88bb2bSRuslan Bukin case PMC_CPU_ARMV8_CORTEX_A57: 3712bc88bb2bSRuslan Bukin ev = cortex_a57_event_table; 3713bc88bb2bSRuslan Bukin evfence = cortex_a57_event_table + PMC_EVENT_TABLE_SIZE(cortex_a57); 3714bc88bb2bSRuslan Bukin break; 3715bc88bb2bSRuslan Bukin default: /* Unknown CPU type. */ 3716bc88bb2bSRuslan Bukin break; 3717bc88bb2bSRuslan Bukin } 3718660df75eSGeorge V. Neville-Neil } else if (pe >= PMC_EV_MIPS24K_FIRST && pe <= PMC_EV_MIPS24K_LAST) { 3719660df75eSGeorge V. Neville-Neil ev = mips24k_event_table; 3720f5f9340bSFabien Thomas evfence = mips24k_event_table + PMC_EVENT_TABLE_SIZE(mips24k); 3721f6e6460dSAdrian Chadd } else if (pe >= PMC_EV_MIPS74K_FIRST && pe <= PMC_EV_MIPS74K_LAST) { 3722f6e6460dSAdrian Chadd ev = mips74k_event_table; 3723f6e6460dSAdrian Chadd evfence = mips74k_event_table + PMC_EVENT_TABLE_SIZE(mips74k); 3724c2657f80SOleksandr Tymoshenko } else if (pe >= PMC_EV_OCTEON_FIRST && pe <= PMC_EV_OCTEON_LAST) { 3725c2657f80SOleksandr Tymoshenko ev = octeon_event_table; 3726c2657f80SOleksandr Tymoshenko evfence = octeon_event_table + PMC_EVENT_TABLE_SIZE(octeon); 37277b25dccaSJustin Hibbits } else if (pe >= PMC_EV_PPC7450_FIRST && pe <= PMC_EV_PPC7450_LAST) { 37287b25dccaSJustin Hibbits ev = ppc7450_event_table; 3729f5f9340bSFabien Thomas evfence = ppc7450_event_table + PMC_EVENT_TABLE_SIZE(ppc7450); 3730169dd953SJustin Hibbits } else if (pe >= PMC_EV_PPC970_FIRST && pe <= PMC_EV_PPC970_LAST) { 3731169dd953SJustin Hibbits ev = ppc970_event_table; 3732169dd953SJustin Hibbits evfence = ppc970_event_table + PMC_EVENT_TABLE_SIZE(ppc970); 3733a7452468SJustin Hibbits } else if (pe >= PMC_EV_E500_FIRST && pe <= PMC_EV_E500_LAST) { 3734a7452468SJustin Hibbits ev = e500_event_table; 3735a7452468SJustin Hibbits evfence = e500_event_table + PMC_EVENT_TABLE_SIZE(e500); 3736789140c0SJoseph Koshy } else if (pe == PMC_EV_TSC_TSC) { 3737789140c0SJoseph Koshy ev = tsc_event_table; 3738789140c0SJoseph Koshy evfence = tsc_event_table + PMC_EVENT_TABLE_SIZE(tsc); 3739f0bbe9aaSDimitry Andric } else if ((int)pe >= PMC_EV_SOFT_FIRST && (int)pe <= PMC_EV_SOFT_LAST) { 3740f5f9340bSFabien Thomas ev = soft_event_table; 3741f5f9340bSFabien Thomas evfence = soft_event_table + soft_event_info.pm_nevent; 3742789140c0SJoseph Koshy } 3743789140c0SJoseph Koshy 3744789140c0SJoseph Koshy for (; ev != evfence; ev++) 3745789140c0SJoseph Koshy if (pe == ev->pm_ev_code) 3746789140c0SJoseph Koshy return (ev->pm_ev_name); 3747f263522aSJoseph Koshy 37480cfab8ddSJoseph Koshy return (NULL); 37490cfab8ddSJoseph Koshy } 37500cfab8ddSJoseph Koshy 37510cfab8ddSJoseph Koshy const char * 37520cfab8ddSJoseph Koshy pmc_name_of_event(enum pmc_event pe) 37530cfab8ddSJoseph Koshy { 37540cfab8ddSJoseph Koshy const char *n; 37550cfab8ddSJoseph Koshy 37560cfab8ddSJoseph Koshy if ((n = _pmc_name_of_event(pe, cpu_info.pm_cputype)) != NULL) 37570cfab8ddSJoseph Koshy return (n); 37580cfab8ddSJoseph Koshy 3759f263522aSJoseph Koshy errno = EINVAL; 3760aa342b1fSJoseph Koshy return (NULL); 3761f263522aSJoseph Koshy } 3762f263522aSJoseph Koshy 3763f263522aSJoseph Koshy const char * 3764f263522aSJoseph Koshy pmc_name_of_mode(enum pmc_mode pm) 3765f263522aSJoseph Koshy { 3766f263522aSJoseph Koshy if ((int) pm >= PMC_MODE_FIRST && 3767f263522aSJoseph Koshy pm <= PMC_MODE_LAST) 3768aa342b1fSJoseph Koshy return (pmc_mode_names[pm]); 3769f263522aSJoseph Koshy 3770f263522aSJoseph Koshy errno = EINVAL; 3771aa342b1fSJoseph Koshy return (NULL); 3772f263522aSJoseph Koshy } 3773f263522aSJoseph Koshy 3774f263522aSJoseph Koshy const char * 3775f263522aSJoseph Koshy pmc_name_of_state(enum pmc_state ps) 3776f263522aSJoseph Koshy { 3777f263522aSJoseph Koshy if ((int) ps >= PMC_STATE_FIRST && 3778f263522aSJoseph Koshy ps <= PMC_STATE_LAST) 3779aa342b1fSJoseph Koshy return (pmc_state_names[ps]); 3780f263522aSJoseph Koshy 3781f263522aSJoseph Koshy errno = EINVAL; 3782aa342b1fSJoseph Koshy return (NULL); 3783f263522aSJoseph Koshy } 3784f263522aSJoseph Koshy 3785f263522aSJoseph Koshy int 3786f263522aSJoseph Koshy pmc_ncpu(void) 3787f263522aSJoseph Koshy { 3788f263522aSJoseph Koshy if (pmc_syscall == -1) { 3789f263522aSJoseph Koshy errno = ENXIO; 3790aa342b1fSJoseph Koshy return (-1); 3791f263522aSJoseph Koshy } 3792f263522aSJoseph Koshy 3793aa342b1fSJoseph Koshy return (cpu_info.pm_ncpu); 3794f263522aSJoseph Koshy } 3795f263522aSJoseph Koshy 3796f263522aSJoseph Koshy int 3797f263522aSJoseph Koshy pmc_npmc(int cpu) 3798f263522aSJoseph Koshy { 3799f263522aSJoseph Koshy if (pmc_syscall == -1) { 3800f263522aSJoseph Koshy errno = ENXIO; 3801aa342b1fSJoseph Koshy return (-1); 3802f263522aSJoseph Koshy } 3803f263522aSJoseph Koshy 3804f263522aSJoseph Koshy if (cpu < 0 || cpu >= (int) cpu_info.pm_ncpu) { 3805f263522aSJoseph Koshy errno = EINVAL; 3806aa342b1fSJoseph Koshy return (-1); 3807f263522aSJoseph Koshy } 3808f263522aSJoseph Koshy 3809aa342b1fSJoseph Koshy return (cpu_info.pm_npmc); 3810f263522aSJoseph Koshy } 3811f263522aSJoseph Koshy 3812f263522aSJoseph Koshy int 3813f263522aSJoseph Koshy pmc_pmcinfo(int cpu, struct pmc_pmcinfo **ppmci) 3814f263522aSJoseph Koshy { 3815f263522aSJoseph Koshy int nbytes, npmc; 3816f263522aSJoseph Koshy struct pmc_op_getpmcinfo *pmci; 3817f263522aSJoseph Koshy 3818f263522aSJoseph Koshy if ((npmc = pmc_npmc(cpu)) < 0) 3819aa342b1fSJoseph Koshy return (-1); 3820f263522aSJoseph Koshy 3821f263522aSJoseph Koshy nbytes = sizeof(struct pmc_op_getpmcinfo) + 3822f263522aSJoseph Koshy npmc * sizeof(struct pmc_info); 3823f263522aSJoseph Koshy 3824f263522aSJoseph Koshy if ((pmci = calloc(1, nbytes)) == NULL) 3825aa342b1fSJoseph Koshy return (-1); 3826f263522aSJoseph Koshy 3827f263522aSJoseph Koshy pmci->pm_cpu = cpu; 3828f263522aSJoseph Koshy 3829f263522aSJoseph Koshy if (PMC_CALL(GETPMCINFO, pmci) < 0) { 3830f263522aSJoseph Koshy free(pmci); 3831aa342b1fSJoseph Koshy return (-1); 3832f263522aSJoseph Koshy } 3833f263522aSJoseph Koshy 3834f263522aSJoseph Koshy /* kernel<->library, library<->userland interfaces are identical */ 3835f263522aSJoseph Koshy *ppmci = (struct pmc_pmcinfo *) pmci; 3836aa342b1fSJoseph Koshy return (0); 3837f263522aSJoseph Koshy } 3838f263522aSJoseph Koshy 3839f263522aSJoseph Koshy int 3840f263522aSJoseph Koshy pmc_read(pmc_id_t pmc, pmc_value_t *value) 3841f263522aSJoseph Koshy { 3842f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_read_op; 3843f263522aSJoseph Koshy 3844f263522aSJoseph Koshy pmc_read_op.pm_pmcid = pmc; 3845f263522aSJoseph Koshy pmc_read_op.pm_flags = PMC_F_OLDVALUE; 3846f263522aSJoseph Koshy pmc_read_op.pm_value = -1; 3847f263522aSJoseph Koshy 3848f263522aSJoseph Koshy if (PMC_CALL(PMCRW, &pmc_read_op) < 0) 3849aa342b1fSJoseph Koshy return (-1); 3850f263522aSJoseph Koshy 3851f263522aSJoseph Koshy *value = pmc_read_op.pm_value; 3852aa342b1fSJoseph Koshy return (0); 3853f263522aSJoseph Koshy } 3854f263522aSJoseph Koshy 3855f263522aSJoseph Koshy int 3856f263522aSJoseph Koshy pmc_release(pmc_id_t pmc) 3857f263522aSJoseph Koshy { 3858f263522aSJoseph Koshy struct pmc_op_simple pmc_release_args; 3859f263522aSJoseph Koshy 3860f263522aSJoseph Koshy pmc_release_args.pm_pmcid = pmc; 3861aa342b1fSJoseph Koshy return (PMC_CALL(PMCRELEASE, &pmc_release_args)); 3862f263522aSJoseph Koshy } 3863f263522aSJoseph Koshy 3864f263522aSJoseph Koshy int 3865f263522aSJoseph Koshy pmc_rw(pmc_id_t pmc, pmc_value_t newvalue, pmc_value_t *oldvaluep) 3866f263522aSJoseph Koshy { 3867f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_rw_op; 3868f263522aSJoseph Koshy 3869f263522aSJoseph Koshy pmc_rw_op.pm_pmcid = pmc; 3870f263522aSJoseph Koshy pmc_rw_op.pm_flags = PMC_F_NEWVALUE | PMC_F_OLDVALUE; 3871f263522aSJoseph Koshy pmc_rw_op.pm_value = newvalue; 3872f263522aSJoseph Koshy 3873f263522aSJoseph Koshy if (PMC_CALL(PMCRW, &pmc_rw_op) < 0) 3874aa342b1fSJoseph Koshy return (-1); 3875f263522aSJoseph Koshy 3876f263522aSJoseph Koshy *oldvaluep = pmc_rw_op.pm_value; 3877aa342b1fSJoseph Koshy return (0); 3878f263522aSJoseph Koshy } 3879f263522aSJoseph Koshy 3880f263522aSJoseph Koshy int 3881f263522aSJoseph Koshy pmc_set(pmc_id_t pmc, pmc_value_t value) 3882f263522aSJoseph Koshy { 3883f263522aSJoseph Koshy struct pmc_op_pmcsetcount sc; 3884f263522aSJoseph Koshy 3885f263522aSJoseph Koshy sc.pm_pmcid = pmc; 3886f263522aSJoseph Koshy sc.pm_count = value; 3887f263522aSJoseph Koshy 3888f263522aSJoseph Koshy if (PMC_CALL(PMCSETCOUNT, &sc) < 0) 3889aa342b1fSJoseph Koshy return (-1); 3890aa342b1fSJoseph Koshy return (0); 3891f263522aSJoseph Koshy } 3892f263522aSJoseph Koshy 3893f263522aSJoseph Koshy int 3894f263522aSJoseph Koshy pmc_start(pmc_id_t pmc) 3895f263522aSJoseph Koshy { 3896f263522aSJoseph Koshy struct pmc_op_simple pmc_start_args; 3897f263522aSJoseph Koshy 3898f263522aSJoseph Koshy pmc_start_args.pm_pmcid = pmc; 3899aa342b1fSJoseph Koshy return (PMC_CALL(PMCSTART, &pmc_start_args)); 3900f263522aSJoseph Koshy } 3901f263522aSJoseph Koshy 3902f263522aSJoseph Koshy int 3903f263522aSJoseph Koshy pmc_stop(pmc_id_t pmc) 3904f263522aSJoseph Koshy { 3905f263522aSJoseph Koshy struct pmc_op_simple pmc_stop_args; 3906f263522aSJoseph Koshy 3907f263522aSJoseph Koshy pmc_stop_args.pm_pmcid = pmc; 3908aa342b1fSJoseph Koshy return (PMC_CALL(PMCSTOP, &pmc_stop_args)); 3909f263522aSJoseph Koshy } 3910f263522aSJoseph Koshy 3911f263522aSJoseph Koshy int 3912f263522aSJoseph Koshy pmc_width(pmc_id_t pmcid, uint32_t *width) 3913f263522aSJoseph Koshy { 3914f263522aSJoseph Koshy unsigned int i; 3915f263522aSJoseph Koshy enum pmc_class cl; 3916f263522aSJoseph Koshy 3917f263522aSJoseph Koshy cl = PMC_ID_TO_CLASS(pmcid); 3918f263522aSJoseph Koshy for (i = 0; i < cpu_info.pm_nclass; i++) 3919f263522aSJoseph Koshy if (cpu_info.pm_classes[i].pm_class == cl) { 3920f263522aSJoseph Koshy *width = cpu_info.pm_classes[i].pm_width; 3921aa342b1fSJoseph Koshy return (0); 3922f263522aSJoseph Koshy } 3923484202faSJoseph Koshy errno = EINVAL; 3924484202faSJoseph Koshy return (-1); 3925f263522aSJoseph Koshy } 3926f263522aSJoseph Koshy 3927f263522aSJoseph Koshy int 3928f263522aSJoseph Koshy pmc_write(pmc_id_t pmc, pmc_value_t value) 3929f263522aSJoseph Koshy { 3930f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_write_op; 3931f263522aSJoseph Koshy 3932f263522aSJoseph Koshy pmc_write_op.pm_pmcid = pmc; 3933f263522aSJoseph Koshy pmc_write_op.pm_flags = PMC_F_NEWVALUE; 3934f263522aSJoseph Koshy pmc_write_op.pm_value = value; 3935aa342b1fSJoseph Koshy return (PMC_CALL(PMCRW, &pmc_write_op)); 3936f263522aSJoseph Koshy } 3937f263522aSJoseph Koshy 3938f263522aSJoseph Koshy int 3939f263522aSJoseph Koshy pmc_writelog(uint32_t userdata) 3940f263522aSJoseph Koshy { 3941f263522aSJoseph Koshy struct pmc_op_writelog wl; 3942f263522aSJoseph Koshy 3943f263522aSJoseph Koshy wl.pm_userdata = userdata; 3944aa342b1fSJoseph Koshy return (PMC_CALL(WRITELOG, &wl)); 3945f263522aSJoseph Koshy } 3946