1ebccf1e3SJoseph Koshy /*- 2484202faSJoseph Koshy * Copyright (c) 2003-2008 Joseph Koshy 3ebccf1e3SJoseph Koshy * All rights reserved. 4ebccf1e3SJoseph Koshy * 5ebccf1e3SJoseph Koshy * Redistribution and use in source and binary forms, with or without 6ebccf1e3SJoseph Koshy * modification, are permitted provided that the following conditions 7ebccf1e3SJoseph Koshy * are met: 8ebccf1e3SJoseph Koshy * 1. Redistributions of source code must retain the above copyright 9ebccf1e3SJoseph Koshy * notice, this list of conditions and the following disclaimer. 10ebccf1e3SJoseph Koshy * 2. Redistributions in binary form must reproduce the above copyright 11ebccf1e3SJoseph Koshy * notice, this list of conditions and the following disclaimer in the 12ebccf1e3SJoseph Koshy * documentation and/or other materials provided with the distribution. 13ebccf1e3SJoseph Koshy * 14ebccf1e3SJoseph Koshy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15ebccf1e3SJoseph Koshy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16ebccf1e3SJoseph Koshy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17ebccf1e3SJoseph Koshy * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18ebccf1e3SJoseph Koshy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19ebccf1e3SJoseph Koshy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20ebccf1e3SJoseph Koshy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21ebccf1e3SJoseph Koshy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22ebccf1e3SJoseph Koshy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23ebccf1e3SJoseph Koshy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24ebccf1e3SJoseph Koshy * SUCH DAMAGE. 25ebccf1e3SJoseph Koshy */ 26ebccf1e3SJoseph Koshy 27ebccf1e3SJoseph Koshy #include <sys/cdefs.h> 28ebccf1e3SJoseph Koshy __FBSDID("$FreeBSD$"); 29ebccf1e3SJoseph Koshy 30ebccf1e3SJoseph Koshy #include <sys/types.h> 31ebccf1e3SJoseph Koshy #include <sys/module.h> 32ebccf1e3SJoseph Koshy #include <sys/pmc.h> 33ebccf1e3SJoseph Koshy #include <sys/syscall.h> 34ebccf1e3SJoseph Koshy 35ebccf1e3SJoseph Koshy #include <ctype.h> 36ebccf1e3SJoseph Koshy #include <errno.h> 37ebccf1e3SJoseph Koshy #include <fcntl.h> 38ebccf1e3SJoseph Koshy #include <pmc.h> 39ebccf1e3SJoseph Koshy #include <stdio.h> 40ebccf1e3SJoseph Koshy #include <stdlib.h> 41ebccf1e3SJoseph Koshy #include <string.h> 42ebccf1e3SJoseph Koshy #include <strings.h> 43ebccf1e3SJoseph Koshy #include <unistd.h> 44ebccf1e3SJoseph Koshy 450cfab8ddSJoseph Koshy #include "libpmcinternal.h" 460cfab8ddSJoseph Koshy 47ebccf1e3SJoseph Koshy /* Function prototypes */ 4804e9feb0SMarcel Moolenaar #if defined(__i386__) 49ebccf1e3SJoseph Koshy static int k7_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 50ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 51f263522aSJoseph Koshy #endif 5286a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 530cfab8ddSJoseph Koshy static int iaf_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 540cfab8ddSJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 550cfab8ddSJoseph Koshy static int iap_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 560cfab8ddSJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 571fa7f10bSFabien Thomas static int ucf_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 581fa7f10bSFabien Thomas struct pmc_op_pmcallocate *_pmc_config); 591fa7f10bSFabien Thomas static int ucp_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 601fa7f10bSFabien Thomas struct pmc_op_pmcallocate *_pmc_config); 61f263522aSJoseph Koshy static int k8_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 62ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 6386a65549SJoseph Koshy static int p4_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 6486a65549SJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 65f263522aSJoseph Koshy #endif 66f263522aSJoseph Koshy #if defined(__i386__) 67ebccf1e3SJoseph Koshy static int p5_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 68ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 69f263522aSJoseph Koshy static int p6_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 70ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 71ebccf1e3SJoseph Koshy #endif 72789140c0SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 73789140c0SJoseph Koshy static int tsc_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 74789140c0SJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 75789140c0SJoseph Koshy #endif 760ce207d2SRui Paulo #if defined(__XSCALE__) 770ce207d2SRui Paulo static int xscale_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 780ce207d2SRui Paulo struct pmc_op_pmcallocate *_pmc_config); 790ce207d2SRui Paulo #endif 80660df75eSGeorge V. Neville-Neil #if defined(__mips__) 812827d3e1SOleksandr Tymoshenko static int mips_allocate_pmc(enum pmc_event _pe, char* ctrspec, 82660df75eSGeorge V. Neville-Neil struct pmc_op_pmcallocate *_pmc_config); 83660df75eSGeorge V. Neville-Neil #endif /* __mips__ */ 84f5f9340bSFabien Thomas static int soft_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 85f5f9340bSFabien Thomas struct pmc_op_pmcallocate *_pmc_config); 86660df75eSGeorge V. Neville-Neil 877b25dccaSJustin Hibbits #if defined(__powerpc__) 887b25dccaSJustin Hibbits static int ppc7450_allocate_pmc(enum pmc_event _pe, char* ctrspec, 897b25dccaSJustin Hibbits struct pmc_op_pmcallocate *_pmc_config); 907b25dccaSJustin Hibbits #endif /* __powerpc__ */ 91660df75eSGeorge V. Neville-Neil 92ebccf1e3SJoseph Koshy #define PMC_CALL(cmd, params) \ 93ebccf1e3SJoseph Koshy syscall(pmc_syscall, PMC_OP_##cmd, (params)) 94ebccf1e3SJoseph Koshy 95ebccf1e3SJoseph Koshy /* 96ebccf1e3SJoseph Koshy * Event aliases provide a way for the user to ask for generic events 97ebccf1e3SJoseph Koshy * like "cache-misses", or "instructions-retired". These aliases are 98ebccf1e3SJoseph Koshy * mapped to the appropriate canonical event descriptions using a 99ebccf1e3SJoseph Koshy * lookup table. 100ebccf1e3SJoseph Koshy */ 101ebccf1e3SJoseph Koshy struct pmc_event_alias { 102ebccf1e3SJoseph Koshy const char *pm_alias; 103ebccf1e3SJoseph Koshy const char *pm_spec; 104ebccf1e3SJoseph Koshy }; 105ebccf1e3SJoseph Koshy 106ebccf1e3SJoseph Koshy static const struct pmc_event_alias *pmc_mdep_event_aliases; 107ebccf1e3SJoseph Koshy 108ebccf1e3SJoseph Koshy /* 109789140c0SJoseph Koshy * The pmc_event_descr structure maps symbolic names known to the user 110ebccf1e3SJoseph Koshy * to integer codes used by the PMC KLD. 111ebccf1e3SJoseph Koshy */ 112ebccf1e3SJoseph Koshy struct pmc_event_descr { 113ebccf1e3SJoseph Koshy const char *pm_ev_name; 114ebccf1e3SJoseph Koshy enum pmc_event pm_ev_code; 115ebccf1e3SJoseph Koshy }; 116ebccf1e3SJoseph Koshy 117789140c0SJoseph Koshy /* 118789140c0SJoseph Koshy * The pmc_class_descr structure maps class name prefixes for 119789140c0SJoseph Koshy * event names to event tables and other PMC class data. 120789140c0SJoseph Koshy */ 121789140c0SJoseph Koshy struct pmc_class_descr { 122789140c0SJoseph Koshy const char *pm_evc_name; 123789140c0SJoseph Koshy size_t pm_evc_name_size; 124789140c0SJoseph Koshy enum pmc_class pm_evc_class; 125789140c0SJoseph Koshy const struct pmc_event_descr *pm_evc_event_table; 126789140c0SJoseph Koshy size_t pm_evc_event_table_size; 127789140c0SJoseph Koshy int (*pm_evc_allocate_pmc)(enum pmc_event _pe, 128789140c0SJoseph Koshy char *_ctrspec, struct pmc_op_pmcallocate *_pa); 129ebccf1e3SJoseph Koshy }; 130ebccf1e3SJoseph Koshy 131789140c0SJoseph Koshy #define PMC_TABLE_SIZE(N) (sizeof(N)/sizeof(N[0])) 132789140c0SJoseph Koshy #define PMC_EVENT_TABLE_SIZE(N) PMC_TABLE_SIZE(N##_event_table) 133789140c0SJoseph Koshy 134789140c0SJoseph Koshy #undef __PMC_EV 135789140c0SJoseph Koshy #define __PMC_EV(C,N) { #N, PMC_EV_ ## C ## _ ## N }, 136789140c0SJoseph Koshy 137789140c0SJoseph Koshy /* 1380cfab8ddSJoseph Koshy * PMC_CLASSDEP_TABLE(NAME, CLASS) 139789140c0SJoseph Koshy * 1400cfab8ddSJoseph Koshy * Define a table mapping event names and aliases to HWPMC event IDs. 141789140c0SJoseph Koshy */ 1420cfab8ddSJoseph Koshy #define PMC_CLASSDEP_TABLE(N, C) \ 143789140c0SJoseph Koshy static const struct pmc_event_descr N##_event_table[] = \ 144789140c0SJoseph Koshy { \ 145789140c0SJoseph Koshy __PMC_EV_##C() \ 1460cfab8ddSJoseph Koshy } 1470cfab8ddSJoseph Koshy 1480cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(iaf, IAF); 1490cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(k7, K7); 1500cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(k8, K8); 1510cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(p4, P4); 1520cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(p5, P5); 1530cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(p6, P6); 1540ce207d2SRui Paulo PMC_CLASSDEP_TABLE(xscale, XSCALE); 155660df75eSGeorge V. Neville-Neil PMC_CLASSDEP_TABLE(mips24k, MIPS24K); 156c2657f80SOleksandr Tymoshenko PMC_CLASSDEP_TABLE(octeon, OCTEON); 1571fa7f10bSFabien Thomas PMC_CLASSDEP_TABLE(ucf, UCF); 1587b25dccaSJustin Hibbits PMC_CLASSDEP_TABLE(ppc7450, PPC7450); 1590cfab8ddSJoseph Koshy 160f5f9340bSFabien Thomas static struct pmc_event_descr soft_event_table[PMC_EV_DYN_COUNT]; 161f5f9340bSFabien Thomas 1620cfab8ddSJoseph Koshy #undef __PMC_EV_ALIAS 1630cfab8ddSJoseph Koshy #define __PMC_EV_ALIAS(N,CODE) { N, PMC_EV_##CODE }, 1640cfab8ddSJoseph Koshy 1650cfab8ddSJoseph Koshy static const struct pmc_event_descr atom_event_table[] = 1660cfab8ddSJoseph Koshy { 1670cfab8ddSJoseph Koshy __PMC_EV_ALIAS_ATOM() 1680cfab8ddSJoseph Koshy }; 1690cfab8ddSJoseph Koshy 1700cfab8ddSJoseph Koshy static const struct pmc_event_descr core_event_table[] = 1710cfab8ddSJoseph Koshy { 1720cfab8ddSJoseph Koshy __PMC_EV_ALIAS_CORE() 1730cfab8ddSJoseph Koshy }; 1740cfab8ddSJoseph Koshy 1750cfab8ddSJoseph Koshy 1760cfab8ddSJoseph Koshy static const struct pmc_event_descr core2_event_table[] = 1770cfab8ddSJoseph Koshy { 1780cfab8ddSJoseph Koshy __PMC_EV_ALIAS_CORE2() 1790cfab8ddSJoseph Koshy }; 1800cfab8ddSJoseph Koshy 181597979c4SJeff Roberson static const struct pmc_event_descr corei7_event_table[] = 182597979c4SJeff Roberson { 183597979c4SJeff Roberson __PMC_EV_ALIAS_COREI7() 184597979c4SJeff Roberson }; 185597979c4SJeff Roberson 186*1e862e5aSFabien Thomas static const struct pmc_event_descr ivybridge_event_table[] = 187*1e862e5aSFabien Thomas { 188*1e862e5aSFabien Thomas __PMC_EV_ALIAS_IVYBRIDGE() 189*1e862e5aSFabien Thomas }; 190*1e862e5aSFabien Thomas 19178d763a2SDavide Italiano static const struct pmc_event_descr sandybridge_event_table[] = 19278d763a2SDavide Italiano { 19378d763a2SDavide Italiano __PMC_EV_ALIAS_SANDYBRIDGE() 19478d763a2SDavide Italiano }; 19578d763a2SDavide Italiano 1961fa7f10bSFabien Thomas static const struct pmc_event_descr westmere_event_table[] = 1971fa7f10bSFabien Thomas { 1981fa7f10bSFabien Thomas __PMC_EV_ALIAS_WESTMERE() 1991fa7f10bSFabien Thomas }; 2001fa7f10bSFabien Thomas 2011fa7f10bSFabien Thomas static const struct pmc_event_descr corei7uc_event_table[] = 2021fa7f10bSFabien Thomas { 2031fa7f10bSFabien Thomas __PMC_EV_ALIAS_COREI7UC() 2041fa7f10bSFabien Thomas }; 2051fa7f10bSFabien Thomas 20678d763a2SDavide Italiano static const struct pmc_event_descr sandybridgeuc_event_table[] = 20778d763a2SDavide Italiano { 20878d763a2SDavide Italiano __PMC_EV_ALIAS_SANDYBRIDGEUC() 20978d763a2SDavide Italiano }; 21078d763a2SDavide Italiano 2111fa7f10bSFabien Thomas static const struct pmc_event_descr westmereuc_event_table[] = 2121fa7f10bSFabien Thomas { 2131fa7f10bSFabien Thomas __PMC_EV_ALIAS_WESTMEREUC() 2141fa7f10bSFabien Thomas }; 2151fa7f10bSFabien Thomas 2160cfab8ddSJoseph Koshy /* 2170cfab8ddSJoseph Koshy * PMC_MDEP_TABLE(NAME, PRIMARYCLASS, ADDITIONAL_CLASSES...) 2180cfab8ddSJoseph Koshy * 2190cfab8ddSJoseph Koshy * Map a CPU to the PMC classes it supports. 2200cfab8ddSJoseph Koshy */ 2210cfab8ddSJoseph Koshy #define PMC_MDEP_TABLE(N,C,...) \ 222789140c0SJoseph Koshy static const enum pmc_class N##_pmc_classes[] = { \ 223789140c0SJoseph Koshy PMC_CLASS_##C, __VA_ARGS__ \ 224789140c0SJoseph Koshy } 225789140c0SJoseph Koshy 226f5f9340bSFabien Thomas PMC_MDEP_TABLE(atom, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 227f5f9340bSFabien Thomas PMC_MDEP_TABLE(core, IAP, PMC_CLASS_SOFT, PMC_CLASS_TSC); 228f5f9340bSFabien Thomas PMC_MDEP_TABLE(core2, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 229f5f9340bSFabien Thomas PMC_MDEP_TABLE(corei7, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 230*1e862e5aSFabien Thomas PMC_MDEP_TABLE(ivybridge, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 231f5f9340bSFabien Thomas PMC_MDEP_TABLE(sandybridge, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 232f5f9340bSFabien Thomas PMC_MDEP_TABLE(westmere, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 233f5f9340bSFabien Thomas PMC_MDEP_TABLE(k7, K7, PMC_CLASS_SOFT, PMC_CLASS_TSC); 234f5f9340bSFabien Thomas PMC_MDEP_TABLE(k8, K8, PMC_CLASS_SOFT, PMC_CLASS_TSC); 235f5f9340bSFabien Thomas PMC_MDEP_TABLE(p4, P4, PMC_CLASS_SOFT, PMC_CLASS_TSC); 236f5f9340bSFabien Thomas PMC_MDEP_TABLE(p5, P5, PMC_CLASS_SOFT, PMC_CLASS_TSC); 237f5f9340bSFabien Thomas PMC_MDEP_TABLE(p6, P6, PMC_CLASS_SOFT, PMC_CLASS_TSC); 238f5f9340bSFabien Thomas PMC_MDEP_TABLE(xscale, XSCALE, PMC_CLASS_SOFT, PMC_CLASS_XSCALE); 239f5f9340bSFabien Thomas PMC_MDEP_TABLE(mips24k, MIPS24K, PMC_CLASS_SOFT, PMC_CLASS_MIPS24K); 240f5f9340bSFabien Thomas PMC_MDEP_TABLE(octeon, OCTEON, PMC_CLASS_SOFT, PMC_CLASS_OCTEON); 241f5f9340bSFabien Thomas PMC_MDEP_TABLE(ppc7450, PPC7450, PMC_CLASS_SOFT, PMC_CLASS_PPC7450); 242f5f9340bSFabien Thomas PMC_MDEP_TABLE(generic, SOFT, PMC_CLASS_SOFT); 243789140c0SJoseph Koshy 244789140c0SJoseph Koshy static const struct pmc_event_descr tsc_event_table[] = 245789140c0SJoseph Koshy { 246789140c0SJoseph Koshy __PMC_EV_TSC() 247789140c0SJoseph Koshy }; 248789140c0SJoseph Koshy 249789140c0SJoseph Koshy #undef PMC_CLASS_TABLE_DESC 2500cfab8ddSJoseph Koshy #define PMC_CLASS_TABLE_DESC(NAME, CLASS, EVENTS, ALLOCATOR) \ 2510cfab8ddSJoseph Koshy static const struct pmc_class_descr NAME##_class_table_descr = \ 2520cfab8ddSJoseph Koshy { \ 2530cfab8ddSJoseph Koshy .pm_evc_name = #CLASS "-", \ 2540cfab8ddSJoseph Koshy .pm_evc_name_size = sizeof(#CLASS "-") - 1, \ 2550cfab8ddSJoseph Koshy .pm_evc_class = PMC_CLASS_##CLASS , \ 2560cfab8ddSJoseph Koshy .pm_evc_event_table = EVENTS##_event_table , \ 257789140c0SJoseph Koshy .pm_evc_event_table_size = \ 2580cfab8ddSJoseph Koshy PMC_EVENT_TABLE_SIZE(EVENTS), \ 2590cfab8ddSJoseph Koshy .pm_evc_allocate_pmc = ALLOCATOR##_allocate_pmc \ 260789140c0SJoseph Koshy } 261789140c0SJoseph Koshy 262789140c0SJoseph Koshy #if defined(__i386__) || defined(__amd64__) 2630cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(iaf, IAF, iaf, iaf); 2640cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(atom, IAP, atom, iap); 2650cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(core, IAP, core, iap); 2660cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(core2, IAP, core2, iap); 267597979c4SJeff Roberson PMC_CLASS_TABLE_DESC(corei7, IAP, corei7, iap); 268*1e862e5aSFabien Thomas PMC_CLASS_TABLE_DESC(ivybridge, IAP, ivybridge, iap); 26978d763a2SDavide Italiano PMC_CLASS_TABLE_DESC(sandybridge, IAP, sandybridge, iap); 2701fa7f10bSFabien Thomas PMC_CLASS_TABLE_DESC(westmere, IAP, westmere, iap); 2711fa7f10bSFabien Thomas PMC_CLASS_TABLE_DESC(ucf, UCF, ucf, ucf); 2721fa7f10bSFabien Thomas PMC_CLASS_TABLE_DESC(corei7uc, UCP, corei7uc, ucp); 27378d763a2SDavide Italiano PMC_CLASS_TABLE_DESC(sandybridgeuc, UCP, sandybridgeuc, ucp); 2741fa7f10bSFabien Thomas PMC_CLASS_TABLE_DESC(westmereuc, UCP, westmereuc, ucp); 275789140c0SJoseph Koshy #endif 276789140c0SJoseph Koshy #if defined(__i386__) 2770cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(k7, K7, k7, k7); 278789140c0SJoseph Koshy #endif 279789140c0SJoseph Koshy #if defined(__i386__) || defined(__amd64__) 2800cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(k8, K8, k8, k8); 2810cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(p4, P4, p4, p4); 282789140c0SJoseph Koshy #endif 2830cfab8ddSJoseph Koshy #if defined(__i386__) 2840cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(p5, P5, p5, p5); 2850cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(p6, P6, p6, p6); 2860cfab8ddSJoseph Koshy #endif 2870cfab8ddSJoseph Koshy #if defined(__i386__) || defined(__amd64__) 2880cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(tsc, TSC, tsc, tsc); 2890cfab8ddSJoseph Koshy #endif 2900ce207d2SRui Paulo #if defined(__XSCALE__) 2910ce207d2SRui Paulo PMC_CLASS_TABLE_DESC(xscale, XSCALE, xscale, xscale); 2920ce207d2SRui Paulo #endif 293660df75eSGeorge V. Neville-Neil #if defined(__mips__) 2942827d3e1SOleksandr Tymoshenko PMC_CLASS_TABLE_DESC(mips24k, MIPS24K, mips24k, mips); 295c2657f80SOleksandr Tymoshenko PMC_CLASS_TABLE_DESC(octeon, OCTEON, octeon, mips); 296660df75eSGeorge V. Neville-Neil #endif /* __mips__ */ 2977b25dccaSJustin Hibbits #if defined(__powerpc__) 2987b25dccaSJustin Hibbits PMC_CLASS_TABLE_DESC(ppc7450, PPC7450, ppc7450, ppc7450); 2997b25dccaSJustin Hibbits #endif 3007b25dccaSJustin Hibbits 301f5f9340bSFabien Thomas static struct pmc_class_descr soft_class_table_descr = 302f5f9340bSFabien Thomas { 303f5f9340bSFabien Thomas .pm_evc_name = "SOFT-", 304f5f9340bSFabien Thomas .pm_evc_name_size = sizeof("SOFT-") - 1, 305f5f9340bSFabien Thomas .pm_evc_class = PMC_CLASS_SOFT, 306f5f9340bSFabien Thomas .pm_evc_event_table = NULL, 307f5f9340bSFabien Thomas .pm_evc_event_table_size = 0, 308f5f9340bSFabien Thomas .pm_evc_allocate_pmc = soft_allocate_pmc 309f5f9340bSFabien Thomas }; 310f5f9340bSFabien Thomas 311789140c0SJoseph Koshy #undef PMC_CLASS_TABLE_DESC 312789140c0SJoseph Koshy 3130cfab8ddSJoseph Koshy static const struct pmc_class_descr **pmc_class_table; 3140cfab8ddSJoseph Koshy #define PMC_CLASS_TABLE_SIZE cpu_info.pm_nclass 3150cfab8ddSJoseph Koshy 316789140c0SJoseph Koshy static const enum pmc_class *pmc_mdep_class_list; 317789140c0SJoseph Koshy static size_t pmc_mdep_class_list_size; 318789140c0SJoseph Koshy 319ebccf1e3SJoseph Koshy /* 320ebccf1e3SJoseph Koshy * Mapping tables, mapping enumeration values to human readable 321ebccf1e3SJoseph Koshy * strings. 322ebccf1e3SJoseph Koshy */ 323ebccf1e3SJoseph Koshy 324ebccf1e3SJoseph Koshy static const char * pmc_capability_names[] = { 325ebccf1e3SJoseph Koshy #undef __PMC_CAP 326ebccf1e3SJoseph Koshy #define __PMC_CAP(N,V,D) #N , 327ebccf1e3SJoseph Koshy __PMC_CAPS() 328ebccf1e3SJoseph Koshy }; 329ebccf1e3SJoseph Koshy 330ebccf1e3SJoseph Koshy static const char * pmc_class_names[] = { 331ebccf1e3SJoseph Koshy #undef __PMC_CLASS 332ebccf1e3SJoseph Koshy #define __PMC_CLASS(C) #C , 333ebccf1e3SJoseph Koshy __PMC_CLASSES() 334ebccf1e3SJoseph Koshy }; 335ebccf1e3SJoseph Koshy 336789140c0SJoseph Koshy struct pmc_cputype_map { 337562fc14bSDimitry Andric enum pmc_cputype pm_cputype; 338789140c0SJoseph Koshy const char *pm_name; 339789140c0SJoseph Koshy }; 340789140c0SJoseph Koshy 341789140c0SJoseph Koshy static const struct pmc_cputype_map pmc_cputype_names[] = { 342ebccf1e3SJoseph Koshy #undef __PMC_CPU 343789140c0SJoseph Koshy #define __PMC_CPU(S, V, D) { .pm_cputype = PMC_CPU_##S, .pm_name = #S } , 344ebccf1e3SJoseph Koshy __PMC_CPUS() 345ebccf1e3SJoseph Koshy }; 346ebccf1e3SJoseph Koshy 347ebccf1e3SJoseph Koshy static const char * pmc_disposition_names[] = { 348ebccf1e3SJoseph Koshy #undef __PMC_DISP 349ebccf1e3SJoseph Koshy #define __PMC_DISP(D) #D , 350ebccf1e3SJoseph Koshy __PMC_DISPOSITIONS() 351ebccf1e3SJoseph Koshy }; 352ebccf1e3SJoseph Koshy 353ebccf1e3SJoseph Koshy static const char * pmc_mode_names[] = { 354ebccf1e3SJoseph Koshy #undef __PMC_MODE 355ebccf1e3SJoseph Koshy #define __PMC_MODE(M,N) #M , 356ebccf1e3SJoseph Koshy __PMC_MODES() 357ebccf1e3SJoseph Koshy }; 358ebccf1e3SJoseph Koshy 359ebccf1e3SJoseph Koshy static const char * pmc_state_names[] = { 360ebccf1e3SJoseph Koshy #undef __PMC_STATE 361ebccf1e3SJoseph Koshy #define __PMC_STATE(S) #S , 362ebccf1e3SJoseph Koshy __PMC_STATES() 363ebccf1e3SJoseph Koshy }; 364ebccf1e3SJoseph Koshy 365f5f9340bSFabien Thomas /* 366f5f9340bSFabien Thomas * Filled in by pmc_init(). 367f5f9340bSFabien Thomas */ 368f5f9340bSFabien Thomas static int pmc_syscall = -1; 369f5f9340bSFabien Thomas static struct pmc_cpuinfo cpu_info; 370f5f9340bSFabien Thomas static struct pmc_op_getdyneventinfo soft_event_info; 3711455fcd3SJoseph Koshy 372ebccf1e3SJoseph Koshy /* Event masks for events */ 373ebccf1e3SJoseph Koshy struct pmc_masks { 374ebccf1e3SJoseph Koshy const char *pm_name; 375*1e862e5aSFabien Thomas const uint64_t pm_value; 376ebccf1e3SJoseph Koshy }; 377ebccf1e3SJoseph Koshy #define PMCMASK(N,V) { .pm_name = #N, .pm_value = (V) } 3781fa7f10bSFabien Thomas #define NULLMASK { .pm_name = NULL } 379ebccf1e3SJoseph Koshy 38086a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 381ebccf1e3SJoseph Koshy static int 382*1e862e5aSFabien Thomas pmc_parse_mask(const struct pmc_masks *pmask, char *p, uint64_t *evmask) 383ebccf1e3SJoseph Koshy { 384ebccf1e3SJoseph Koshy const struct pmc_masks *pm; 385ebccf1e3SJoseph Koshy char *q, *r; 386ebccf1e3SJoseph Koshy int c; 387ebccf1e3SJoseph Koshy 388ebccf1e3SJoseph Koshy if (pmask == NULL) /* no mask keywords */ 389aa342b1fSJoseph Koshy return (-1); 390ebccf1e3SJoseph Koshy q = strchr(p, '='); /* skip '=' */ 391ebccf1e3SJoseph Koshy if (*++q == '\0') /* no more data */ 392aa342b1fSJoseph Koshy return (-1); 393ebccf1e3SJoseph Koshy c = 0; /* count of mask keywords seen */ 394ebccf1e3SJoseph Koshy while ((r = strsep(&q, "+")) != NULL) { 395789140c0SJoseph Koshy for (pm = pmask; pm->pm_name && strcasecmp(r, pm->pm_name); 396789140c0SJoseph Koshy pm++) 397ebccf1e3SJoseph Koshy ; 398ebccf1e3SJoseph Koshy if (pm->pm_name == NULL) /* not found */ 399aa342b1fSJoseph Koshy return (-1); 400ebccf1e3SJoseph Koshy *evmask |= pm->pm_value; 401ebccf1e3SJoseph Koshy c++; 402ebccf1e3SJoseph Koshy } 403aa342b1fSJoseph Koshy return (c); 404ebccf1e3SJoseph Koshy } 40504e9feb0SMarcel Moolenaar #endif 406ebccf1e3SJoseph Koshy 407ebccf1e3SJoseph Koshy #define KWMATCH(p,kw) (strcasecmp((p), (kw)) == 0) 408ebccf1e3SJoseph Koshy #define KWPREFIXMATCH(p,kw) (strncasecmp((p), (kw), sizeof((kw)) - 1) == 0) 409ebccf1e3SJoseph Koshy #define EV_ALIAS(N,S) { .pm_alias = N, .pm_spec = S } 410ebccf1e3SJoseph Koshy 41104e9feb0SMarcel Moolenaar #if defined(__i386__) 412ebccf1e3SJoseph Koshy 413ebccf1e3SJoseph Koshy /* 414ebccf1e3SJoseph Koshy * AMD K7 (Athlon) CPUs. 415ebccf1e3SJoseph Koshy */ 416ebccf1e3SJoseph Koshy 417ebccf1e3SJoseph Koshy static struct pmc_event_alias k7_aliases[] = { 418ebccf1e3SJoseph Koshy EV_ALIAS("branches", "k7-retired-branches"), 419ebccf1e3SJoseph Koshy EV_ALIAS("branch-mispredicts", "k7-retired-branches-mispredicted"), 420ebccf1e3SJoseph Koshy EV_ALIAS("cycles", "tsc"), 4216aa5a193SJoseph Koshy EV_ALIAS("dc-misses", "k7-dc-misses"), 422ebccf1e3SJoseph Koshy EV_ALIAS("ic-misses", "k7-ic-misses"), 423ebccf1e3SJoseph Koshy EV_ALIAS("instructions", "k7-retired-instructions"), 424ebccf1e3SJoseph Koshy EV_ALIAS("interrupts", "k7-hardware-interrupts"), 425ebccf1e3SJoseph Koshy EV_ALIAS(NULL, NULL) 426ebccf1e3SJoseph Koshy }; 427ebccf1e3SJoseph Koshy 428ebccf1e3SJoseph Koshy #define K7_KW_COUNT "count" 429ebccf1e3SJoseph Koshy #define K7_KW_EDGE "edge" 430ebccf1e3SJoseph Koshy #define K7_KW_INV "inv" 431ebccf1e3SJoseph Koshy #define K7_KW_OS "os" 432ebccf1e3SJoseph Koshy #define K7_KW_UNITMASK "unitmask" 433ebccf1e3SJoseph Koshy #define K7_KW_USR "usr" 434ebccf1e3SJoseph Koshy 435ebccf1e3SJoseph Koshy static int 436ebccf1e3SJoseph Koshy k7_allocate_pmc(enum pmc_event pe, char *ctrspec, 437ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 438ebccf1e3SJoseph Koshy { 439ebccf1e3SJoseph Koshy char *e, *p, *q; 440ebccf1e3SJoseph Koshy int c, has_unitmask; 441ebccf1e3SJoseph Koshy uint32_t count, unitmask; 442ebccf1e3SJoseph Koshy 443f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 444789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 445ebccf1e3SJoseph Koshy 446ebccf1e3SJoseph Koshy if (pe == PMC_EV_K7_DC_REFILLS_FROM_L2 || 447ebccf1e3SJoseph Koshy pe == PMC_EV_K7_DC_REFILLS_FROM_SYSTEM || 448ebccf1e3SJoseph Koshy pe == PMC_EV_K7_DC_WRITEBACKS) { 449ebccf1e3SJoseph Koshy has_unitmask = 1; 450f263522aSJoseph Koshy unitmask = AMD_PMC_UNITMASK_MOESI; 451ebccf1e3SJoseph Koshy } else 452ebccf1e3SJoseph Koshy unitmask = has_unitmask = 0; 453ebccf1e3SJoseph Koshy 454ebccf1e3SJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 455ebccf1e3SJoseph Koshy if (KWPREFIXMATCH(p, K7_KW_COUNT "=")) { 456ebccf1e3SJoseph Koshy q = strchr(p, '='); 457ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 458aa342b1fSJoseph Koshy return (-1); 459ebccf1e3SJoseph Koshy 460ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 461ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 462aa342b1fSJoseph Koshy return (-1); 463ebccf1e3SJoseph Koshy 464ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 465f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config |= 466f263522aSJoseph Koshy AMD_PMC_TO_COUNTER(count); 467ebccf1e3SJoseph Koshy 468ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_EDGE)) { 469ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 470ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_INV)) { 471ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 472ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_OS)) { 473ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 474ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, K7_KW_UNITMASK "=")) { 475ebccf1e3SJoseph Koshy if (has_unitmask == 0) 476aa342b1fSJoseph Koshy return (-1); 477ebccf1e3SJoseph Koshy unitmask = 0; 478ebccf1e3SJoseph Koshy q = strchr(p, '='); 479ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 480aa342b1fSJoseph Koshy return (-1); 481ebccf1e3SJoseph Koshy 482ebccf1e3SJoseph Koshy while ((c = tolower(*q++)) != 0) 483ebccf1e3SJoseph Koshy if (c == 'm') 484f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_M; 485ebccf1e3SJoseph Koshy else if (c == 'o') 486f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_O; 487ebccf1e3SJoseph Koshy else if (c == 'e') 488f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_E; 489ebccf1e3SJoseph Koshy else if (c == 's') 490f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_S; 491ebccf1e3SJoseph Koshy else if (c == 'i') 492f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_I; 493ebccf1e3SJoseph Koshy else if (c == '+') 494ebccf1e3SJoseph Koshy continue; 495ebccf1e3SJoseph Koshy else 496aa342b1fSJoseph Koshy return (-1); 497ebccf1e3SJoseph Koshy 498ebccf1e3SJoseph Koshy if (unitmask == 0) 499aa342b1fSJoseph Koshy return (-1); 500ebccf1e3SJoseph Koshy 501ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_USR)) { 502ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 503ebccf1e3SJoseph Koshy } else 504aa342b1fSJoseph Koshy return (-1); 505ebccf1e3SJoseph Koshy } 506ebccf1e3SJoseph Koshy 507ebccf1e3SJoseph Koshy if (has_unitmask) { 508ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 509f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config |= 510f263522aSJoseph Koshy AMD_PMC_TO_UNITMASK(unitmask); 511ebccf1e3SJoseph Koshy } 512ebccf1e3SJoseph Koshy 513aa342b1fSJoseph Koshy return (0); 514ebccf1e3SJoseph Koshy 515ebccf1e3SJoseph Koshy } 516ebccf1e3SJoseph Koshy 517f263522aSJoseph Koshy #endif 518f263522aSJoseph Koshy 51986a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 520f263522aSJoseph Koshy 521f263522aSJoseph Koshy /* 5220cfab8ddSJoseph Koshy * Intel Core (Family 6, Model E) PMCs. 5230cfab8ddSJoseph Koshy */ 5240cfab8ddSJoseph Koshy 5250cfab8ddSJoseph Koshy static struct pmc_event_alias core_aliases[] = { 5260cfab8ddSJoseph Koshy EV_ALIAS("branches", "iap-br-instr-ret"), 5270cfab8ddSJoseph Koshy EV_ALIAS("branch-mispredicts", "iap-br-mispred-ret"), 5280cfab8ddSJoseph Koshy EV_ALIAS("cycles", "tsc-tsc"), 5290cfab8ddSJoseph Koshy EV_ALIAS("ic-misses", "iap-icache-misses"), 5300cfab8ddSJoseph Koshy EV_ALIAS("instructions", "iap-instr-ret"), 5310cfab8ddSJoseph Koshy EV_ALIAS("interrupts", "iap-core-hw-int-rx"), 5320cfab8ddSJoseph Koshy EV_ALIAS("unhalted-cycles", "iap-unhalted-core-cycles"), 5330cfab8ddSJoseph Koshy EV_ALIAS(NULL, NULL) 5340cfab8ddSJoseph Koshy }; 5350cfab8ddSJoseph Koshy 5360cfab8ddSJoseph Koshy /* 5370cfab8ddSJoseph Koshy * Intel Core2 (Family 6, Model F), Core2Extreme (Family 6, Model 17H) 5380cfab8ddSJoseph Koshy * and Atom (Family 6, model 1CH) PMCs. 539791f5d5bSJoseph Koshy * 540791f5d5bSJoseph Koshy * We map aliases to events on the fixed-function counters if these 541791f5d5bSJoseph Koshy * are present. Note that not all CPUs in this family contain fixed-function 542791f5d5bSJoseph Koshy * counters. 5430cfab8ddSJoseph Koshy */ 5440cfab8ddSJoseph Koshy 5450cfab8ddSJoseph Koshy static struct pmc_event_alias core2_aliases[] = { 5460cfab8ddSJoseph Koshy EV_ALIAS("branches", "iap-br-inst-retired.any"), 5470cfab8ddSJoseph Koshy EV_ALIAS("branch-mispredicts", "iap-br-inst-retired.mispred"), 5480cfab8ddSJoseph Koshy EV_ALIAS("cycles", "tsc-tsc"), 5490cfab8ddSJoseph Koshy EV_ALIAS("ic-misses", "iap-l1i-misses"), 5500cfab8ddSJoseph Koshy EV_ALIAS("instructions", "iaf-instr-retired.any"), 5510cfab8ddSJoseph Koshy EV_ALIAS("interrupts", "iap-hw-int-rcv"), 5520cfab8ddSJoseph Koshy EV_ALIAS("unhalted-cycles", "iaf-cpu-clk-unhalted.core"), 5530cfab8ddSJoseph Koshy EV_ALIAS(NULL, NULL) 5540cfab8ddSJoseph Koshy }; 555791f5d5bSJoseph Koshy 556791f5d5bSJoseph Koshy static struct pmc_event_alias core2_aliases_without_iaf[] = { 557791f5d5bSJoseph Koshy EV_ALIAS("branches", "iap-br-inst-retired.any"), 558791f5d5bSJoseph Koshy EV_ALIAS("branch-mispredicts", "iap-br-inst-retired.mispred"), 559791f5d5bSJoseph Koshy EV_ALIAS("cycles", "tsc-tsc"), 560791f5d5bSJoseph Koshy EV_ALIAS("ic-misses", "iap-l1i-misses"), 561791f5d5bSJoseph Koshy EV_ALIAS("instructions", "iap-inst-retired.any_p"), 562791f5d5bSJoseph Koshy EV_ALIAS("interrupts", "iap-hw-int-rcv"), 563791f5d5bSJoseph Koshy EV_ALIAS("unhalted-cycles", "iap-cpu-clk-unhalted.core_p"), 564791f5d5bSJoseph Koshy EV_ALIAS(NULL, NULL) 565791f5d5bSJoseph Koshy }; 566791f5d5bSJoseph Koshy 5670cfab8ddSJoseph Koshy #define atom_aliases core2_aliases 568791f5d5bSJoseph Koshy #define atom_aliases_without_iaf core2_aliases_without_iaf 569597979c4SJeff Roberson #define corei7_aliases core2_aliases 570791f5d5bSJoseph Koshy #define corei7_aliases_without_iaf core2_aliases_without_iaf 571*1e862e5aSFabien Thomas #define ivybridge_aliases core2_aliases 572*1e862e5aSFabien Thomas #define ivybridge_aliases_without_iaf core2_aliases_without_iaf 57378d763a2SDavide Italiano #define sandybridge_aliases core2_aliases 57478d763a2SDavide Italiano #define sandybridge_aliases_without_iaf core2_aliases_without_iaf 5751fa7f10bSFabien Thomas #define westmere_aliases core2_aliases 5761fa7f10bSFabien Thomas #define westmere_aliases_without_iaf core2_aliases_without_iaf 5770cfab8ddSJoseph Koshy 5780cfab8ddSJoseph Koshy #define IAF_KW_OS "os" 5790cfab8ddSJoseph Koshy #define IAF_KW_USR "usr" 5800cfab8ddSJoseph Koshy #define IAF_KW_ANYTHREAD "anythread" 5810cfab8ddSJoseph Koshy 5820cfab8ddSJoseph Koshy /* 5830cfab8ddSJoseph Koshy * Parse an event specifier for Intel fixed function counters. 5840cfab8ddSJoseph Koshy */ 5850cfab8ddSJoseph Koshy static int 5860cfab8ddSJoseph Koshy iaf_allocate_pmc(enum pmc_event pe, char *ctrspec, 5870cfab8ddSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 5880cfab8ddSJoseph Koshy { 5890cfab8ddSJoseph Koshy char *p; 5900cfab8ddSJoseph Koshy 5910cfab8ddSJoseph Koshy (void) pe; 5920cfab8ddSJoseph Koshy 5930cfab8ddSJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 5940cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iaf.pm_iaf_flags = 0; 5950cfab8ddSJoseph Koshy 5960cfab8ddSJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 5970cfab8ddSJoseph Koshy if (KWMATCH(p, IAF_KW_OS)) 5980cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 5990cfab8ddSJoseph Koshy else if (KWMATCH(p, IAF_KW_USR)) 6000cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 6010cfab8ddSJoseph Koshy else if (KWMATCH(p, IAF_KW_ANYTHREAD)) 6020cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iaf.pm_iaf_flags |= IAF_ANY; 6030cfab8ddSJoseph Koshy else 6040cfab8ddSJoseph Koshy return (-1); 6050cfab8ddSJoseph Koshy } 6060cfab8ddSJoseph Koshy 6070cfab8ddSJoseph Koshy return (0); 6080cfab8ddSJoseph Koshy } 6090cfab8ddSJoseph Koshy 6100cfab8ddSJoseph Koshy /* 6110cfab8ddSJoseph Koshy * Core/Core2 support. 6120cfab8ddSJoseph Koshy */ 6130cfab8ddSJoseph Koshy 6140cfab8ddSJoseph Koshy #define IAP_KW_AGENT "agent" 6150cfab8ddSJoseph Koshy #define IAP_KW_ANYTHREAD "anythread" 6160cfab8ddSJoseph Koshy #define IAP_KW_CACHESTATE "cachestate" 6170cfab8ddSJoseph Koshy #define IAP_KW_CMASK "cmask" 6180cfab8ddSJoseph Koshy #define IAP_KW_CORE "core" 6190cfab8ddSJoseph Koshy #define IAP_KW_EDGE "edge" 6200cfab8ddSJoseph Koshy #define IAP_KW_INV "inv" 6210cfab8ddSJoseph Koshy #define IAP_KW_OS "os" 6220cfab8ddSJoseph Koshy #define IAP_KW_PREFETCH "prefetch" 6230cfab8ddSJoseph Koshy #define IAP_KW_SNOOPRESPONSE "snoopresponse" 6240cfab8ddSJoseph Koshy #define IAP_KW_SNOOPTYPE "snooptype" 6250cfab8ddSJoseph Koshy #define IAP_KW_TRANSITION "trans" 6260cfab8ddSJoseph Koshy #define IAP_KW_USR "usr" 6271fa7f10bSFabien Thomas #define IAP_KW_RSP "rsp" 6280cfab8ddSJoseph Koshy 6290cfab8ddSJoseph Koshy static struct pmc_masks iap_core_mask[] = { 6300cfab8ddSJoseph Koshy PMCMASK(all, (0x3 << 14)), 6310cfab8ddSJoseph Koshy PMCMASK(this, (0x1 << 14)), 6320cfab8ddSJoseph Koshy NULLMASK 6330cfab8ddSJoseph Koshy }; 6340cfab8ddSJoseph Koshy 6350cfab8ddSJoseph Koshy static struct pmc_masks iap_agent_mask[] = { 6360cfab8ddSJoseph Koshy PMCMASK(this, 0), 6370cfab8ddSJoseph Koshy PMCMASK(any, (0x1 << 13)), 6380cfab8ddSJoseph Koshy NULLMASK 6390cfab8ddSJoseph Koshy }; 6400cfab8ddSJoseph Koshy 6410cfab8ddSJoseph Koshy static struct pmc_masks iap_prefetch_mask[] = { 6420cfab8ddSJoseph Koshy PMCMASK(both, (0x3 << 12)), 6430cfab8ddSJoseph Koshy PMCMASK(only, (0x1 << 12)), 6440cfab8ddSJoseph Koshy PMCMASK(exclude, 0), 6450cfab8ddSJoseph Koshy NULLMASK 6460cfab8ddSJoseph Koshy }; 6470cfab8ddSJoseph Koshy 6480cfab8ddSJoseph Koshy static struct pmc_masks iap_cachestate_mask[] = { 6490cfab8ddSJoseph Koshy PMCMASK(i, (1 << 8)), 6500cfab8ddSJoseph Koshy PMCMASK(s, (1 << 9)), 6510cfab8ddSJoseph Koshy PMCMASK(e, (1 << 10)), 6520cfab8ddSJoseph Koshy PMCMASK(m, (1 << 11)), 6530cfab8ddSJoseph Koshy NULLMASK 6540cfab8ddSJoseph Koshy }; 6550cfab8ddSJoseph Koshy 6560cfab8ddSJoseph Koshy static struct pmc_masks iap_snoopresponse_mask[] = { 6570cfab8ddSJoseph Koshy PMCMASK(clean, (1 << 8)), 6580cfab8ddSJoseph Koshy PMCMASK(hit, (1 << 9)), 6590cfab8ddSJoseph Koshy PMCMASK(hitm, (1 << 11)), 6600cfab8ddSJoseph Koshy NULLMASK 6610cfab8ddSJoseph Koshy }; 6620cfab8ddSJoseph Koshy 6630cfab8ddSJoseph Koshy static struct pmc_masks iap_snooptype_mask[] = { 6640cfab8ddSJoseph Koshy PMCMASK(cmp2s, (1 << 8)), 6650cfab8ddSJoseph Koshy PMCMASK(cmp2i, (1 << 9)), 6660cfab8ddSJoseph Koshy NULLMASK 6670cfab8ddSJoseph Koshy }; 6680cfab8ddSJoseph Koshy 6690cfab8ddSJoseph Koshy static struct pmc_masks iap_transition_mask[] = { 6700cfab8ddSJoseph Koshy PMCMASK(any, 0x00), 6710cfab8ddSJoseph Koshy PMCMASK(frequency, 0x10), 6720cfab8ddSJoseph Koshy NULLMASK 6730cfab8ddSJoseph Koshy }; 6740cfab8ddSJoseph Koshy 675*1e862e5aSFabien Thomas static struct pmc_masks iap_rsp_mask_i7_wm[] = { 6761fa7f10bSFabien Thomas PMCMASK(DMND_DATA_RD, (1 << 0)), 6771fa7f10bSFabien Thomas PMCMASK(DMND_RFO, (1 << 1)), 6781fa7f10bSFabien Thomas PMCMASK(DMND_IFETCH, (1 << 2)), 6791fa7f10bSFabien Thomas PMCMASK(WB, (1 << 3)), 6801fa7f10bSFabien Thomas PMCMASK(PF_DATA_RD, (1 << 4)), 6811fa7f10bSFabien Thomas PMCMASK(PF_RFO, (1 << 5)), 6821fa7f10bSFabien Thomas PMCMASK(PF_IFETCH, (1 << 6)), 6831fa7f10bSFabien Thomas PMCMASK(OTHER, (1 << 7)), 6841fa7f10bSFabien Thomas PMCMASK(UNCORE_HIT, (1 << 8)), 6851fa7f10bSFabien Thomas PMCMASK(OTHER_CORE_HIT_SNP, (1 << 9)), 6861fa7f10bSFabien Thomas PMCMASK(OTHER_CORE_HITM, (1 << 10)), 6871fa7f10bSFabien Thomas PMCMASK(REMOTE_CACHE_FWD, (1 << 12)), 6881fa7f10bSFabien Thomas PMCMASK(REMOTE_DRAM, (1 << 13)), 6891fa7f10bSFabien Thomas PMCMASK(LOCAL_DRAM, (1 << 14)), 6901fa7f10bSFabien Thomas PMCMASK(NON_DRAM, (1 << 15)), 6911fa7f10bSFabien Thomas NULLMASK 6921fa7f10bSFabien Thomas }; 6931fa7f10bSFabien Thomas 694*1e862e5aSFabien Thomas static struct pmc_masks iap_rsp_mask_sb_ib[] = { 695*1e862e5aSFabien Thomas PMCMASK(REQ_DMND_DATA_RD, (1ULL << 0)), 696*1e862e5aSFabien Thomas PMCMASK(REQ_DMND_RFO, (1ULL << 1)), 697*1e862e5aSFabien Thomas PMCMASK(REQ_DMND_IFETCH, (1ULL << 2)), 698*1e862e5aSFabien Thomas PMCMASK(REQ_WB, (1ULL << 3)), 699*1e862e5aSFabien Thomas PMCMASK(REQ_PF_DATA_RD, (1ULL << 4)), 700*1e862e5aSFabien Thomas PMCMASK(REQ_PF_RFO, (1ULL << 5)), 701*1e862e5aSFabien Thomas PMCMASK(REQ_PF_IFETCH, (1ULL << 6)), 702*1e862e5aSFabien Thomas PMCMASK(REQ_PF_LLC_DATA_RD, (1ULL << 7)), 703*1e862e5aSFabien Thomas PMCMASK(REQ_PF_LLC_RFO, (1ULL << 8)), 704*1e862e5aSFabien Thomas PMCMASK(REQ_PF_LLC_IFETCH, (1ULL << 9)), 705*1e862e5aSFabien Thomas PMCMASK(REQ_BUS_LOCKS, (1ULL << 10)), 706*1e862e5aSFabien Thomas PMCMASK(REQ_STRM_ST, (1ULL << 11)), 707*1e862e5aSFabien Thomas PMCMASK(REQ_OTHER, (1ULL << 15)), 708*1e862e5aSFabien Thomas PMCMASK(RES_ANY, (1ULL << 16)), 709*1e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_SUPP, (1ULL << 17)), 710*1e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_LLC_HITM, (1ULL << 18)), 711*1e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_LLC_HITE, (1ULL << 19)), 712*1e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_LLC_HITS, (1ULL << 20)), 713*1e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_LLC_HITF, (1ULL << 21)), 714*1e862e5aSFabien Thomas PMCMASK(RES_SUPPLIER_LOCAL, (1ULL << 22)), 715*1e862e5aSFabien Thomas PMCMASK(RES_SNOOP_SNPI_NONE, (1ULL << 31)), 716*1e862e5aSFabien Thomas PMCMASK(RES_SNOOP_SNP_NO_NEEDED,(1ULL << 32)), 717*1e862e5aSFabien Thomas PMCMASK(RES_SNOOP_SNP_MISS, (1ULL << 33)), 718*1e862e5aSFabien Thomas PMCMASK(RES_SNOOP_HIT_NO_FWD, (1ULL << 34)), 719*1e862e5aSFabien Thomas PMCMASK(RES_SNOOP_HIT_FWD, (1ULL << 35)), 720*1e862e5aSFabien Thomas PMCMASK(RES_SNOOP_HITM, (1ULL << 36)), 721*1e862e5aSFabien Thomas PMCMASK(RES_NON_DRAM, (1ULL << 37)), 722*1e862e5aSFabien Thomas NULLMASK 723*1e862e5aSFabien Thomas }; 724*1e862e5aSFabien Thomas 7250cfab8ddSJoseph Koshy static int 7260cfab8ddSJoseph Koshy iap_allocate_pmc(enum pmc_event pe, char *ctrspec, 7270cfab8ddSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 7280cfab8ddSJoseph Koshy { 7290cfab8ddSJoseph Koshy char *e, *p, *q; 730*1e862e5aSFabien Thomas uint64_t cachestate, evmask, rsp; 7310cfab8ddSJoseph Koshy int count, n; 7320cfab8ddSJoseph Koshy 7330cfab8ddSJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE | 7340cfab8ddSJoseph Koshy PMC_CAP_QUALIFIER); 7350cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config = 0; 7360cfab8ddSJoseph Koshy 7371fa7f10bSFabien Thomas cachestate = evmask = rsp = 0; 7380cfab8ddSJoseph Koshy 7390cfab8ddSJoseph Koshy /* Parse additional modifiers if present */ 7400cfab8ddSJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 7410cfab8ddSJoseph Koshy 7420cfab8ddSJoseph Koshy n = 0; 7430cfab8ddSJoseph Koshy if (KWPREFIXMATCH(p, IAP_KW_CMASK "=")) { 7440cfab8ddSJoseph Koshy q = strchr(p, '='); 7450cfab8ddSJoseph Koshy if (*++q == '\0') /* skip '=' */ 7460cfab8ddSJoseph Koshy return (-1); 7470cfab8ddSJoseph Koshy count = strtol(q, &e, 0); 7480cfab8ddSJoseph Koshy if (e == q || *e != '\0') 7490cfab8ddSJoseph Koshy return (-1); 7500cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 7510cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= 7520cfab8ddSJoseph Koshy IAP_CMASK(count); 7530cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_EDGE)) { 7540cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 7550cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_INV)) { 7560cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 7570cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_OS)) { 7580cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 7590cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_USR)) { 7600cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 7610cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_ANYTHREAD)) { 7620cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= IAP_ANY; 763b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_CORE "=")) { 7640cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_core_mask, p, &evmask); 7650cfab8ddSJoseph Koshy if (n != 1) 7660cfab8ddSJoseph Koshy return (-1); 767b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_AGENT "=")) { 7680cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_agent_mask, p, &evmask); 7690cfab8ddSJoseph Koshy if (n != 1) 7700cfab8ddSJoseph Koshy return (-1); 771b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_PREFETCH "=")) { 7720cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_prefetch_mask, p, &evmask); 7730cfab8ddSJoseph Koshy if (n != 1) 7740cfab8ddSJoseph Koshy return (-1); 775b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_CACHESTATE "=")) { 7760cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_cachestate_mask, p, &cachestate); 7770cfab8ddSJoseph Koshy } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_CORE && 778b47ea38eSJoseph Koshy KWPREFIXMATCH(p, IAP_KW_TRANSITION "=")) { 7790cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_transition_mask, p, &evmask); 7800cfab8ddSJoseph Koshy if (n != 1) 7810cfab8ddSJoseph Koshy return (-1); 7820cfab8ddSJoseph Koshy } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM || 783b4d091f3SJoseph Koshy cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2 || 7841fa7f10bSFabien Thomas cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2EXTREME) { 785b47ea38eSJoseph Koshy if (KWPREFIXMATCH(p, IAP_KW_SNOOPRESPONSE "=")) { 7860cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_snoopresponse_mask, p, 7870cfab8ddSJoseph Koshy &evmask); 788b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_SNOOPTYPE "=")) { 7890cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_snooptype_mask, p, 7900cfab8ddSJoseph Koshy &evmask); 7910cfab8ddSJoseph Koshy } else 7920cfab8ddSJoseph Koshy return (-1); 7931fa7f10bSFabien Thomas } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_COREI7 || 7941fa7f10bSFabien Thomas cpu_info.pm_cputype == PMC_CPU_INTEL_WESTMERE) { 7951fa7f10bSFabien Thomas if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 796*1e862e5aSFabien Thomas n = pmc_parse_mask(iap_rsp_mask_i7_wm, p, &rsp); 797*1e862e5aSFabien Thomas } else 798*1e862e5aSFabien Thomas return (-1); 799*1e862e5aSFabien Thomas } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_SANDYBRIDGE || 800*1e862e5aSFabien Thomas cpu_info.pm_cputype == PMC_CPU_INTEL_IVYBRIDGE) { 801*1e862e5aSFabien Thomas if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 802*1e862e5aSFabien Thomas n = pmc_parse_mask(iap_rsp_mask_sb_ib, p, &rsp); 8031fa7f10bSFabien Thomas } else 8041fa7f10bSFabien Thomas return (-1); 8050cfab8ddSJoseph Koshy } else 8060cfab8ddSJoseph Koshy return (-1); 8070cfab8ddSJoseph Koshy 8080cfab8ddSJoseph Koshy if (n < 0) /* Parsing failed. */ 8090cfab8ddSJoseph Koshy return (-1); 8100cfab8ddSJoseph Koshy } 8110cfab8ddSJoseph Koshy 8120cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= evmask; 8130cfab8ddSJoseph Koshy 8140cfab8ddSJoseph Koshy /* 8150cfab8ddSJoseph Koshy * If the event requires a 'cachestate' qualifier but was not 8160cfab8ddSJoseph Koshy * specified by the user, use a sensible default. 8170cfab8ddSJoseph Koshy */ 8180cfab8ddSJoseph Koshy switch (pe) { 8190cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_28H: /* Core, Core2, Atom */ 8200cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_29H: /* Core, Core2, Atom */ 8210cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_2AH: /* Core, Core2, Atom */ 8220cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_2BH: /* Atom, Core2 */ 8230cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_2EH: /* Core, Core2, Atom */ 8240cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_30H: /* Core, Core2, Atom */ 8250cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_32H: /* Core */ 8260cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_40H: /* Core */ 8270cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_41H: /* Core */ 8280cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_42H: /* Core, Core2, Atom */ 8290cfab8ddSJoseph Koshy if (cachestate == 0) 8300cfab8ddSJoseph Koshy cachestate = (0xF << 8); 831aa1b887bSRyan Stone break; 832aa1b887bSRyan Stone case PMC_EV_IAP_EVENT_77H: /* Atom */ 833aa1b887bSRyan Stone /* IAP_EVENT_77H only accepts a cachestate qualifier on the 834aa1b887bSRyan Stone * Atom processor 835aa1b887bSRyan Stone */ 836aa1b887bSRyan Stone if(cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM && cachestate == 0) 837aa1b887bSRyan Stone cachestate = (0xF << 8); 838aa1b887bSRyan Stone break; 8390cfab8ddSJoseph Koshy default: 8400cfab8ddSJoseph Koshy break; 8410cfab8ddSJoseph Koshy } 8420cfab8ddSJoseph Koshy 8430cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= cachestate; 8441fa7f10bSFabien Thomas pmc_config->pm_md.pm_iap.pm_iap_rsp = rsp; 8451fa7f10bSFabien Thomas 8461fa7f10bSFabien Thomas return (0); 8471fa7f10bSFabien Thomas } 8481fa7f10bSFabien Thomas 8491fa7f10bSFabien Thomas /* 8501fa7f10bSFabien Thomas * Intel Uncore. 8511fa7f10bSFabien Thomas */ 8521fa7f10bSFabien Thomas 8531fa7f10bSFabien Thomas static int 8541fa7f10bSFabien Thomas ucf_allocate_pmc(enum pmc_event pe, char *ctrspec, 8551fa7f10bSFabien Thomas struct pmc_op_pmcallocate *pmc_config) 8561fa7f10bSFabien Thomas { 8571fa7f10bSFabien Thomas (void) pe; 8581fa7f10bSFabien Thomas (void) ctrspec; 8591fa7f10bSFabien Thomas 8601fa7f10bSFabien Thomas pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 8611fa7f10bSFabien Thomas pmc_config->pm_md.pm_ucf.pm_ucf_flags = 0; 8621fa7f10bSFabien Thomas 8631fa7f10bSFabien Thomas return (0); 8641fa7f10bSFabien Thomas } 8651fa7f10bSFabien Thomas 8661fa7f10bSFabien Thomas #define UCP_KW_CMASK "cmask" 8671fa7f10bSFabien Thomas #define UCP_KW_EDGE "edge" 8681fa7f10bSFabien Thomas #define UCP_KW_INV "inv" 8691fa7f10bSFabien Thomas 8701fa7f10bSFabien Thomas static int 8711fa7f10bSFabien Thomas ucp_allocate_pmc(enum pmc_event pe, char *ctrspec, 8721fa7f10bSFabien Thomas struct pmc_op_pmcallocate *pmc_config) 8731fa7f10bSFabien Thomas { 8741fa7f10bSFabien Thomas char *e, *p, *q; 8751fa7f10bSFabien Thomas int count, n; 8761fa7f10bSFabien Thomas 8771fa7f10bSFabien Thomas (void) pe; 8781fa7f10bSFabien Thomas 8791fa7f10bSFabien Thomas pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE | 8801fa7f10bSFabien Thomas PMC_CAP_QUALIFIER); 8811fa7f10bSFabien Thomas pmc_config->pm_md.pm_ucp.pm_ucp_config = 0; 8821fa7f10bSFabien Thomas 8831fa7f10bSFabien Thomas /* Parse additional modifiers if present */ 8841fa7f10bSFabien Thomas while ((p = strsep(&ctrspec, ",")) != NULL) { 8851fa7f10bSFabien Thomas 8861fa7f10bSFabien Thomas n = 0; 8871fa7f10bSFabien Thomas if (KWPREFIXMATCH(p, UCP_KW_CMASK "=")) { 8881fa7f10bSFabien Thomas q = strchr(p, '='); 8891fa7f10bSFabien Thomas if (*++q == '\0') /* skip '=' */ 8901fa7f10bSFabien Thomas return (-1); 8911fa7f10bSFabien Thomas count = strtol(q, &e, 0); 8921fa7f10bSFabien Thomas if (e == q || *e != '\0') 8931fa7f10bSFabien Thomas return (-1); 8941fa7f10bSFabien Thomas pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 8951fa7f10bSFabien Thomas pmc_config->pm_md.pm_ucp.pm_ucp_config |= 8961fa7f10bSFabien Thomas UCP_CMASK(count); 8971fa7f10bSFabien Thomas } else if (KWMATCH(p, UCP_KW_EDGE)) { 8981fa7f10bSFabien Thomas pmc_config->pm_caps |= PMC_CAP_EDGE; 8991fa7f10bSFabien Thomas } else if (KWMATCH(p, UCP_KW_INV)) { 9001fa7f10bSFabien Thomas pmc_config->pm_caps |= PMC_CAP_INVERT; 9011fa7f10bSFabien Thomas } else 9021fa7f10bSFabien Thomas return (-1); 9031fa7f10bSFabien Thomas 9041fa7f10bSFabien Thomas if (n < 0) /* Parsing failed. */ 9051fa7f10bSFabien Thomas return (-1); 9061fa7f10bSFabien Thomas } 9070cfab8ddSJoseph Koshy 9080cfab8ddSJoseph Koshy return (0); 9090cfab8ddSJoseph Koshy } 9100cfab8ddSJoseph Koshy 9110cfab8ddSJoseph Koshy /* 912f263522aSJoseph Koshy * AMD K8 PMCs. 913f263522aSJoseph Koshy * 914f263522aSJoseph Koshy * These are very similar to AMD K7 PMCs, but support more kinds of 915f263522aSJoseph Koshy * events. 916f263522aSJoseph Koshy */ 917f263522aSJoseph Koshy 918f263522aSJoseph Koshy static struct pmc_event_alias k8_aliases[] = { 919f263522aSJoseph Koshy EV_ALIAS("branches", "k8-fr-retired-taken-branches"), 920f263522aSJoseph Koshy EV_ALIAS("branch-mispredicts", 921f263522aSJoseph Koshy "k8-fr-retired-taken-branches-mispredicted"), 922f263522aSJoseph Koshy EV_ALIAS("cycles", "tsc"), 923f263522aSJoseph Koshy EV_ALIAS("dc-misses", "k8-dc-miss"), 924f263522aSJoseph Koshy EV_ALIAS("ic-misses", "k8-ic-miss"), 925f263522aSJoseph Koshy EV_ALIAS("instructions", "k8-fr-retired-x86-instructions"), 926f263522aSJoseph Koshy EV_ALIAS("interrupts", "k8-fr-taken-hardware-interrupts"), 927177a2f22SJoseph Koshy EV_ALIAS("unhalted-cycles", "k8-bu-cpu-clk-unhalted"), 928f263522aSJoseph Koshy EV_ALIAS(NULL, NULL) 929f263522aSJoseph Koshy }; 930f263522aSJoseph Koshy 931f263522aSJoseph Koshy #define __K8MASK(N,V) PMCMASK(N,(1 << (V))) 932f263522aSJoseph Koshy 933f263522aSJoseph Koshy /* 934f263522aSJoseph Koshy * Parsing tables 935f263522aSJoseph Koshy */ 936f263522aSJoseph Koshy 937f263522aSJoseph Koshy /* fp dispatched fpu ops */ 938f263522aSJoseph Koshy static const struct pmc_masks k8_mask_fdfo[] = { 939f263522aSJoseph Koshy __K8MASK(add-pipe-excluding-junk-ops, 0), 940f263522aSJoseph Koshy __K8MASK(multiply-pipe-excluding-junk-ops, 1), 941f263522aSJoseph Koshy __K8MASK(store-pipe-excluding-junk-ops, 2), 942f263522aSJoseph Koshy __K8MASK(add-pipe-junk-ops, 3), 943f263522aSJoseph Koshy __K8MASK(multiply-pipe-junk-ops, 4), 944f263522aSJoseph Koshy __K8MASK(store-pipe-junk-ops, 5), 945f263522aSJoseph Koshy NULLMASK 946f263522aSJoseph Koshy }; 947f263522aSJoseph Koshy 948f263522aSJoseph Koshy /* ls segment register loads */ 949f263522aSJoseph Koshy static const struct pmc_masks k8_mask_lsrl[] = { 950f263522aSJoseph Koshy __K8MASK(es, 0), 951f263522aSJoseph Koshy __K8MASK(cs, 1), 952f263522aSJoseph Koshy __K8MASK(ss, 2), 953f263522aSJoseph Koshy __K8MASK(ds, 3), 954f263522aSJoseph Koshy __K8MASK(fs, 4), 955f263522aSJoseph Koshy __K8MASK(gs, 5), 956f263522aSJoseph Koshy __K8MASK(hs, 6), 957f263522aSJoseph Koshy NULLMASK 958f263522aSJoseph Koshy }; 959f263522aSJoseph Koshy 960f263522aSJoseph Koshy /* ls locked operation */ 961f263522aSJoseph Koshy static const struct pmc_masks k8_mask_llo[] = { 962f263522aSJoseph Koshy __K8MASK(locked-instructions, 0), 963f263522aSJoseph Koshy __K8MASK(cycles-in-request, 1), 964f263522aSJoseph Koshy __K8MASK(cycles-to-complete, 2), 965f263522aSJoseph Koshy NULLMASK 966f263522aSJoseph Koshy }; 967f263522aSJoseph Koshy 968f263522aSJoseph Koshy /* dc refill from {l2,system} and dc copyback */ 969f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dc[] = { 970f263522aSJoseph Koshy __K8MASK(invalid, 0), 971f263522aSJoseph Koshy __K8MASK(shared, 1), 972f263522aSJoseph Koshy __K8MASK(exclusive, 2), 973f263522aSJoseph Koshy __K8MASK(owner, 3), 974f263522aSJoseph Koshy __K8MASK(modified, 4), 975f263522aSJoseph Koshy NULLMASK 976f263522aSJoseph Koshy }; 977f263522aSJoseph Koshy 978f263522aSJoseph Koshy /* dc one bit ecc error */ 979f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dobee[] = { 980f263522aSJoseph Koshy __K8MASK(scrubber, 0), 981f263522aSJoseph Koshy __K8MASK(piggyback, 1), 982f263522aSJoseph Koshy NULLMASK 983f263522aSJoseph Koshy }; 984f263522aSJoseph Koshy 985f263522aSJoseph Koshy /* dc dispatched prefetch instructions */ 986f263522aSJoseph Koshy static const struct pmc_masks k8_mask_ddpi[] = { 987f263522aSJoseph Koshy __K8MASK(load, 0), 988f263522aSJoseph Koshy __K8MASK(store, 1), 989f263522aSJoseph Koshy __K8MASK(nta, 2), 990f263522aSJoseph Koshy NULLMASK 991f263522aSJoseph Koshy }; 992f263522aSJoseph Koshy 993f263522aSJoseph Koshy /* dc dcache accesses by locks */ 994f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dabl[] = { 995f263522aSJoseph Koshy __K8MASK(accesses, 0), 996f263522aSJoseph Koshy __K8MASK(misses, 1), 997f263522aSJoseph Koshy NULLMASK 998f263522aSJoseph Koshy }; 999f263522aSJoseph Koshy 1000f263522aSJoseph Koshy /* bu internal l2 request */ 1001f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bilr[] = { 1002f263522aSJoseph Koshy __K8MASK(ic-fill, 0), 1003f263522aSJoseph Koshy __K8MASK(dc-fill, 1), 1004f263522aSJoseph Koshy __K8MASK(tlb-reload, 2), 1005f263522aSJoseph Koshy __K8MASK(tag-snoop, 3), 1006f263522aSJoseph Koshy __K8MASK(cancelled, 4), 1007f263522aSJoseph Koshy NULLMASK 1008f263522aSJoseph Koshy }; 1009f263522aSJoseph Koshy 1010f263522aSJoseph Koshy /* bu fill request l2 miss */ 1011f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bfrlm[] = { 1012f263522aSJoseph Koshy __K8MASK(ic-fill, 0), 1013f263522aSJoseph Koshy __K8MASK(dc-fill, 1), 1014f263522aSJoseph Koshy __K8MASK(tlb-reload, 2), 1015f263522aSJoseph Koshy NULLMASK 1016f263522aSJoseph Koshy }; 1017f263522aSJoseph Koshy 1018f263522aSJoseph Koshy /* bu fill into l2 */ 1019f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bfil[] = { 1020f263522aSJoseph Koshy __K8MASK(dirty-l2-victim, 0), 1021f263522aSJoseph Koshy __K8MASK(victim-from-l2, 1), 1022f263522aSJoseph Koshy NULLMASK 1023f263522aSJoseph Koshy }; 1024f263522aSJoseph Koshy 1025f263522aSJoseph Koshy /* fr retired fpu instructions */ 1026f263522aSJoseph Koshy static const struct pmc_masks k8_mask_frfi[] = { 1027f263522aSJoseph Koshy __K8MASK(x87, 0), 1028f263522aSJoseph Koshy __K8MASK(mmx-3dnow, 1), 1029f263522aSJoseph Koshy __K8MASK(packed-sse-sse2, 2), 1030f263522aSJoseph Koshy __K8MASK(scalar-sse-sse2, 3), 1031f263522aSJoseph Koshy NULLMASK 1032f263522aSJoseph Koshy }; 1033f263522aSJoseph Koshy 1034f263522aSJoseph Koshy /* fr retired fastpath double op instructions */ 1035f263522aSJoseph Koshy static const struct pmc_masks k8_mask_frfdoi[] = { 1036f263522aSJoseph Koshy __K8MASK(low-op-pos-0, 0), 1037f263522aSJoseph Koshy __K8MASK(low-op-pos-1, 1), 1038f263522aSJoseph Koshy __K8MASK(low-op-pos-2, 2), 1039f263522aSJoseph Koshy NULLMASK 1040f263522aSJoseph Koshy }; 1041f263522aSJoseph Koshy 1042f263522aSJoseph Koshy /* fr fpu exceptions */ 1043f263522aSJoseph Koshy static const struct pmc_masks k8_mask_ffe[] = { 1044f263522aSJoseph Koshy __K8MASK(x87-reclass-microfaults, 0), 1045f263522aSJoseph Koshy __K8MASK(sse-retype-microfaults, 1), 1046f263522aSJoseph Koshy __K8MASK(sse-reclass-microfaults, 2), 1047f263522aSJoseph Koshy __K8MASK(sse-and-x87-microtraps, 3), 1048f263522aSJoseph Koshy NULLMASK 1049f263522aSJoseph Koshy }; 1050f263522aSJoseph Koshy 1051f263522aSJoseph Koshy /* nb memory controller page access event */ 1052f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmcpae[] = { 1053f263522aSJoseph Koshy __K8MASK(page-hit, 0), 1054f263522aSJoseph Koshy __K8MASK(page-miss, 1), 1055f263522aSJoseph Koshy __K8MASK(page-conflict, 2), 1056f263522aSJoseph Koshy NULLMASK 1057f263522aSJoseph Koshy }; 1058f263522aSJoseph Koshy 1059f263522aSJoseph Koshy /* nb memory controller turnaround */ 1060f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmct[] = { 1061f263522aSJoseph Koshy __K8MASK(dimm-turnaround, 0), 1062f263522aSJoseph Koshy __K8MASK(read-to-write-turnaround, 1), 1063f263522aSJoseph Koshy __K8MASK(write-to-read-turnaround, 2), 1064f263522aSJoseph Koshy NULLMASK 1065f263522aSJoseph Koshy }; 1066f263522aSJoseph Koshy 1067f263522aSJoseph Koshy /* nb memory controller bypass saturation */ 1068f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmcbs[] = { 1069f263522aSJoseph Koshy __K8MASK(memory-controller-hi-pri-bypass, 0), 1070f263522aSJoseph Koshy __K8MASK(memory-controller-lo-pri-bypass, 1), 1071f263522aSJoseph Koshy __K8MASK(dram-controller-interface-bypass, 2), 1072f263522aSJoseph Koshy __K8MASK(dram-controller-queue-bypass, 3), 1073f263522aSJoseph Koshy NULLMASK 1074f263522aSJoseph Koshy }; 1075f263522aSJoseph Koshy 1076f263522aSJoseph Koshy /* nb sized commands */ 1077f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nsc[] = { 1078f263522aSJoseph Koshy __K8MASK(nonpostwrszbyte, 0), 1079f263522aSJoseph Koshy __K8MASK(nonpostwrszdword, 1), 1080f263522aSJoseph Koshy __K8MASK(postwrszbyte, 2), 1081f263522aSJoseph Koshy __K8MASK(postwrszdword, 3), 1082f263522aSJoseph Koshy __K8MASK(rdszbyte, 4), 1083f263522aSJoseph Koshy __K8MASK(rdszdword, 5), 1084f263522aSJoseph Koshy __K8MASK(rdmodwr, 6), 1085f263522aSJoseph Koshy NULLMASK 1086f263522aSJoseph Koshy }; 1087f263522aSJoseph Koshy 1088f263522aSJoseph Koshy /* nb probe result */ 1089f263522aSJoseph Koshy static const struct pmc_masks k8_mask_npr[] = { 1090f263522aSJoseph Koshy __K8MASK(probe-miss, 0), 1091f263522aSJoseph Koshy __K8MASK(probe-hit, 1), 1092f263522aSJoseph Koshy __K8MASK(probe-hit-dirty-no-memory-cancel, 2), 1093f263522aSJoseph Koshy __K8MASK(probe-hit-dirty-with-memory-cancel, 3), 1094f263522aSJoseph Koshy NULLMASK 1095f263522aSJoseph Koshy }; 1096f263522aSJoseph Koshy 1097f263522aSJoseph Koshy /* nb hypertransport bus bandwidth */ 1098f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nhbb[] = { /* HT bus bandwidth */ 1099f263522aSJoseph Koshy __K8MASK(command, 0), 1100f263522aSJoseph Koshy __K8MASK(data, 1), 1101f263522aSJoseph Koshy __K8MASK(buffer-release, 2), 1102f263522aSJoseph Koshy __K8MASK(nop, 3), 1103f263522aSJoseph Koshy NULLMASK 1104f263522aSJoseph Koshy }; 1105f263522aSJoseph Koshy 1106f263522aSJoseph Koshy #undef __K8MASK 1107f263522aSJoseph Koshy 1108f263522aSJoseph Koshy #define K8_KW_COUNT "count" 1109f263522aSJoseph Koshy #define K8_KW_EDGE "edge" 1110f263522aSJoseph Koshy #define K8_KW_INV "inv" 1111f263522aSJoseph Koshy #define K8_KW_MASK "mask" 1112f263522aSJoseph Koshy #define K8_KW_OS "os" 1113f263522aSJoseph Koshy #define K8_KW_USR "usr" 1114f263522aSJoseph Koshy 1115f263522aSJoseph Koshy static int 1116f263522aSJoseph Koshy k8_allocate_pmc(enum pmc_event pe, char *ctrspec, 1117f263522aSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 1118f263522aSJoseph Koshy { 1119f263522aSJoseph Koshy char *e, *p, *q; 1120f263522aSJoseph Koshy int n; 1121*1e862e5aSFabien Thomas uint32_t count; 1122*1e862e5aSFabien Thomas uint64_t evmask; 1123f263522aSJoseph Koshy const struct pmc_masks *pm, *pmask; 1124f263522aSJoseph Koshy 1125789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1126f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 1127f263522aSJoseph Koshy 1128f263522aSJoseph Koshy pmask = NULL; 1129f263522aSJoseph Koshy evmask = 0; 1130f263522aSJoseph Koshy 1131f263522aSJoseph Koshy #define __K8SETMASK(M) pmask = k8_mask_##M 1132f263522aSJoseph Koshy 1133f263522aSJoseph Koshy /* setup parsing tables */ 1134f263522aSJoseph Koshy switch (pe) { 1135f263522aSJoseph Koshy case PMC_EV_K8_FP_DISPATCHED_FPU_OPS: 1136f263522aSJoseph Koshy __K8SETMASK(fdfo); 1137f263522aSJoseph Koshy break; 1138f263522aSJoseph Koshy case PMC_EV_K8_LS_SEGMENT_REGISTER_LOAD: 1139f263522aSJoseph Koshy __K8SETMASK(lsrl); 1140f263522aSJoseph Koshy break; 1141f263522aSJoseph Koshy case PMC_EV_K8_LS_LOCKED_OPERATION: 1142f263522aSJoseph Koshy __K8SETMASK(llo); 1143f263522aSJoseph Koshy break; 1144f263522aSJoseph Koshy case PMC_EV_K8_DC_REFILL_FROM_L2: 1145f263522aSJoseph Koshy case PMC_EV_K8_DC_REFILL_FROM_SYSTEM: 1146f263522aSJoseph Koshy case PMC_EV_K8_DC_COPYBACK: 1147f263522aSJoseph Koshy __K8SETMASK(dc); 1148f263522aSJoseph Koshy break; 1149f263522aSJoseph Koshy case PMC_EV_K8_DC_ONE_BIT_ECC_ERROR: 1150f263522aSJoseph Koshy __K8SETMASK(dobee); 1151f263522aSJoseph Koshy break; 1152f263522aSJoseph Koshy case PMC_EV_K8_DC_DISPATCHED_PREFETCH_INSTRUCTIONS: 1153f263522aSJoseph Koshy __K8SETMASK(ddpi); 1154f263522aSJoseph Koshy break; 1155f263522aSJoseph Koshy case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS: 1156f263522aSJoseph Koshy __K8SETMASK(dabl); 1157f263522aSJoseph Koshy break; 1158f263522aSJoseph Koshy case PMC_EV_K8_BU_INTERNAL_L2_REQUEST: 1159f263522aSJoseph Koshy __K8SETMASK(bilr); 1160f263522aSJoseph Koshy break; 1161f263522aSJoseph Koshy case PMC_EV_K8_BU_FILL_REQUEST_L2_MISS: 1162f263522aSJoseph Koshy __K8SETMASK(bfrlm); 1163f263522aSJoseph Koshy break; 1164f263522aSJoseph Koshy case PMC_EV_K8_BU_FILL_INTO_L2: 1165f263522aSJoseph Koshy __K8SETMASK(bfil); 1166f263522aSJoseph Koshy break; 1167f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS: 1168f263522aSJoseph Koshy __K8SETMASK(frfi); 1169f263522aSJoseph Koshy break; 1170f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS: 1171f263522aSJoseph Koshy __K8SETMASK(frfdoi); 1172f263522aSJoseph Koshy break; 1173f263522aSJoseph Koshy case PMC_EV_K8_FR_FPU_EXCEPTIONS: 1174f263522aSJoseph Koshy __K8SETMASK(ffe); 1175f263522aSJoseph Koshy break; 1176f263522aSJoseph Koshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_PAGE_ACCESS_EVENT: 1177f263522aSJoseph Koshy __K8SETMASK(nmcpae); 1178f263522aSJoseph Koshy break; 1179f263522aSJoseph Koshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_TURNAROUND: 1180f263522aSJoseph Koshy __K8SETMASK(nmct); 1181f263522aSJoseph Koshy break; 1182f263522aSJoseph Koshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_BYPASS_SATURATION: 1183f263522aSJoseph Koshy __K8SETMASK(nmcbs); 1184f263522aSJoseph Koshy break; 1185f263522aSJoseph Koshy case PMC_EV_K8_NB_SIZED_COMMANDS: 1186f263522aSJoseph Koshy __K8SETMASK(nsc); 1187f263522aSJoseph Koshy break; 1188f263522aSJoseph Koshy case PMC_EV_K8_NB_PROBE_RESULT: 1189f263522aSJoseph Koshy __K8SETMASK(npr); 1190f263522aSJoseph Koshy break; 1191f263522aSJoseph Koshy case PMC_EV_K8_NB_HT_BUS0_BANDWIDTH: 1192f263522aSJoseph Koshy case PMC_EV_K8_NB_HT_BUS1_BANDWIDTH: 1193f263522aSJoseph Koshy case PMC_EV_K8_NB_HT_BUS2_BANDWIDTH: 1194f263522aSJoseph Koshy __K8SETMASK(nhbb); 1195f263522aSJoseph Koshy break; 1196f263522aSJoseph Koshy 1197f263522aSJoseph Koshy default: 1198f263522aSJoseph Koshy break; /* no options defined */ 1199f263522aSJoseph Koshy } 1200f263522aSJoseph Koshy 1201f263522aSJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 1202f263522aSJoseph Koshy if (KWPREFIXMATCH(p, K8_KW_COUNT "=")) { 1203f263522aSJoseph Koshy q = strchr(p, '='); 1204f263522aSJoseph Koshy if (*++q == '\0') /* skip '=' */ 1205aa342b1fSJoseph Koshy return (-1); 1206f263522aSJoseph Koshy 1207f263522aSJoseph Koshy count = strtol(q, &e, 0); 1208f263522aSJoseph Koshy if (e == q || *e != '\0') 1209aa342b1fSJoseph Koshy return (-1); 1210f263522aSJoseph Koshy 1211f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 1212f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config |= 1213f263522aSJoseph Koshy AMD_PMC_TO_COUNTER(count); 1214f263522aSJoseph Koshy 1215f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_EDGE)) { 1216f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1217f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_INV)) { 1218f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 1219f263522aSJoseph Koshy } else if (KWPREFIXMATCH(p, K8_KW_MASK "=")) { 1220f263522aSJoseph Koshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 1221aa342b1fSJoseph Koshy return (-1); 1222f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1223f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_OS)) { 1224f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 1225f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_USR)) { 1226f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 1227f263522aSJoseph Koshy } else 1228aa342b1fSJoseph Koshy return (-1); 1229f263522aSJoseph Koshy } 1230f263522aSJoseph Koshy 1231f263522aSJoseph Koshy /* other post processing */ 1232f263522aSJoseph Koshy switch (pe) { 1233f263522aSJoseph Koshy case PMC_EV_K8_FP_DISPATCHED_FPU_OPS: 1234f263522aSJoseph Koshy case PMC_EV_K8_FP_CYCLES_WITH_NO_FPU_OPS_RETIRED: 1235f263522aSJoseph Koshy case PMC_EV_K8_FP_DISPATCHED_FPU_FAST_FLAG_OPS: 1236f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS: 1237f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS: 1238f263522aSJoseph Koshy case PMC_EV_K8_FR_FPU_EXCEPTIONS: 1239f263522aSJoseph Koshy /* XXX only available in rev B and later */ 1240f263522aSJoseph Koshy break; 1241f263522aSJoseph Koshy case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS: 1242f263522aSJoseph Koshy /* XXX only available in rev C and later */ 1243f263522aSJoseph Koshy break; 1244f263522aSJoseph Koshy case PMC_EV_K8_LS_LOCKED_OPERATION: 1245f263522aSJoseph Koshy /* XXX CPU Rev A,B evmask is to be zero */ 1246f263522aSJoseph Koshy if (evmask & (evmask - 1)) /* > 1 bit set */ 1247aa342b1fSJoseph Koshy return (-1); 1248f263522aSJoseph Koshy if (evmask == 0) { 1249f263522aSJoseph Koshy evmask = 0x01; /* Rev C and later: #instrs */ 1250f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1251f263522aSJoseph Koshy } 1252f263522aSJoseph Koshy break; 1253f263522aSJoseph Koshy default: 1254f263522aSJoseph Koshy if (evmask == 0 && pmask != NULL) { 1255f263522aSJoseph Koshy for (pm = pmask; pm->pm_name; pm++) 1256f263522aSJoseph Koshy evmask |= pm->pm_value; 1257f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1258f263522aSJoseph Koshy } 1259f263522aSJoseph Koshy } 1260f263522aSJoseph Koshy 1261f263522aSJoseph Koshy if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) 1262f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 1263f263522aSJoseph Koshy AMD_PMC_TO_UNITMASK(evmask); 1264f263522aSJoseph Koshy 1265aa342b1fSJoseph Koshy return (0); 1266f263522aSJoseph Koshy } 1267f263522aSJoseph Koshy 1268f263522aSJoseph Koshy #endif 1269f263522aSJoseph Koshy 127086a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 1271f263522aSJoseph Koshy 1272ebccf1e3SJoseph Koshy /* 1273ebccf1e3SJoseph Koshy * Intel P4 PMCs 1274ebccf1e3SJoseph Koshy */ 1275ebccf1e3SJoseph Koshy 1276ebccf1e3SJoseph Koshy static struct pmc_event_alias p4_aliases[] = { 1277d56c5d4bSJoseph Koshy EV_ALIAS("branches", "p4-branch-retired,mask=mmtp+mmtm"), 1278d56c5d4bSJoseph Koshy EV_ALIAS("branch-mispredicts", "p4-mispred-branch-retired"), 1279ebccf1e3SJoseph Koshy EV_ALIAS("cycles", "tsc"), 1280d56c5d4bSJoseph Koshy EV_ALIAS("instructions", 1281d56c5d4bSJoseph Koshy "p4-instr-retired,mask=nbogusntag+nbogustag"), 1282177a2f22SJoseph Koshy EV_ALIAS("unhalted-cycles", "p4-global-power-events"), 1283ebccf1e3SJoseph Koshy EV_ALIAS(NULL, NULL) 1284ebccf1e3SJoseph Koshy }; 1285ebccf1e3SJoseph Koshy 1286ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE "active" 1287ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_ANY "any" 1288ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_BOTH "both" 1289ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_NONE "none" 1290ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_SINGLE "single" 1291ebccf1e3SJoseph Koshy #define P4_KW_BUSREQTYPE "busreqtype" 1292ebccf1e3SJoseph Koshy #define P4_KW_CASCADE "cascade" 1293ebccf1e3SJoseph Koshy #define P4_KW_EDGE "edge" 1294ebccf1e3SJoseph Koshy #define P4_KW_INV "complement" 1295ebccf1e3SJoseph Koshy #define P4_KW_OS "os" 1296ebccf1e3SJoseph Koshy #define P4_KW_MASK "mask" 1297ebccf1e3SJoseph Koshy #define P4_KW_PRECISE "precise" 1298ebccf1e3SJoseph Koshy #define P4_KW_TAG "tag" 1299ebccf1e3SJoseph Koshy #define P4_KW_THRESHOLD "threshold" 1300ebccf1e3SJoseph Koshy #define P4_KW_USR "usr" 1301ebccf1e3SJoseph Koshy 1302ebccf1e3SJoseph Koshy #define __P4MASK(N,V) PMCMASK(N, (1 << (V))) 1303ebccf1e3SJoseph Koshy 1304ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_tcdm[] = { /* tc deliver mode */ 1305ebccf1e3SJoseph Koshy __P4MASK(dd, 0), 1306ebccf1e3SJoseph Koshy __P4MASK(db, 1), 1307ebccf1e3SJoseph Koshy __P4MASK(di, 2), 1308ebccf1e3SJoseph Koshy __P4MASK(bd, 3), 1309ebccf1e3SJoseph Koshy __P4MASK(bb, 4), 1310ebccf1e3SJoseph Koshy __P4MASK(bi, 5), 1311ebccf1e3SJoseph Koshy __P4MASK(id, 6), 1312ebccf1e3SJoseph Koshy __P4MASK(ib, 7), 1313ebccf1e3SJoseph Koshy NULLMASK 1314ebccf1e3SJoseph Koshy }; 1315ebccf1e3SJoseph Koshy 1316ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_bfr[] = { /* bpu fetch request */ 1317ebccf1e3SJoseph Koshy __P4MASK(tcmiss, 0), 1318ebccf1e3SJoseph Koshy NULLMASK, 1319ebccf1e3SJoseph Koshy }; 1320ebccf1e3SJoseph Koshy 1321ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ir[] = { /* itlb reference */ 1322ebccf1e3SJoseph Koshy __P4MASK(hit, 0), 1323ebccf1e3SJoseph Koshy __P4MASK(miss, 1), 1324ebccf1e3SJoseph Koshy __P4MASK(hit-uc, 2), 1325ebccf1e3SJoseph Koshy NULLMASK 1326ebccf1e3SJoseph Koshy }; 1327ebccf1e3SJoseph Koshy 1328ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_memcan[] = { /* memory cancel */ 1329ebccf1e3SJoseph Koshy __P4MASK(st-rb-full, 2), 1330ebccf1e3SJoseph Koshy __P4MASK(64k-conf, 3), 1331ebccf1e3SJoseph Koshy NULLMASK 1332ebccf1e3SJoseph Koshy }; 1333ebccf1e3SJoseph Koshy 1334ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_memcomp[] = { /* memory complete */ 1335ebccf1e3SJoseph Koshy __P4MASK(lsc, 0), 1336ebccf1e3SJoseph Koshy __P4MASK(ssc, 1), 1337ebccf1e3SJoseph Koshy NULLMASK 1338ebccf1e3SJoseph Koshy }; 1339ebccf1e3SJoseph Koshy 1340ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_lpr[] = { /* load port replay */ 1341ebccf1e3SJoseph Koshy __P4MASK(split-ld, 1), 1342ebccf1e3SJoseph Koshy NULLMASK 1343ebccf1e3SJoseph Koshy }; 1344ebccf1e3SJoseph Koshy 1345ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_spr[] = { /* store port replay */ 1346ebccf1e3SJoseph Koshy __P4MASK(split-st, 1), 1347ebccf1e3SJoseph Koshy NULLMASK 1348ebccf1e3SJoseph Koshy }; 1349ebccf1e3SJoseph Koshy 1350ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_mlr[] = { /* mob load replay */ 1351ebccf1e3SJoseph Koshy __P4MASK(no-sta, 1), 1352ebccf1e3SJoseph Koshy __P4MASK(no-std, 3), 1353ebccf1e3SJoseph Koshy __P4MASK(partial-data, 4), 1354ebccf1e3SJoseph Koshy __P4MASK(unalgn-addr, 5), 1355ebccf1e3SJoseph Koshy NULLMASK 1356ebccf1e3SJoseph Koshy }; 1357ebccf1e3SJoseph Koshy 1358ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_pwt[] = { /* page walk type */ 1359ebccf1e3SJoseph Koshy __P4MASK(dtmiss, 0), 1360ebccf1e3SJoseph Koshy __P4MASK(itmiss, 1), 1361ebccf1e3SJoseph Koshy NULLMASK 1362ebccf1e3SJoseph Koshy }; 1363ebccf1e3SJoseph Koshy 1364ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_bcr[] = { /* bsq cache reference */ 1365ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-hits, 0), 1366ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-hite, 1), 1367ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-hitm, 2), 1368ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-hits, 3), 1369ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-hite, 4), 1370ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-hitm, 5), 1371ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-miss, 8), 1372ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-miss, 9), 1373ebccf1e3SJoseph Koshy __P4MASK(wr-2ndl-miss, 10), 1374ebccf1e3SJoseph Koshy NULLMASK 1375ebccf1e3SJoseph Koshy }; 1376ebccf1e3SJoseph Koshy 1377ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ia[] = { /* ioq allocation */ 1378ebccf1e3SJoseph Koshy __P4MASK(all-read, 5), 1379ebccf1e3SJoseph Koshy __P4MASK(all-write, 6), 1380ebccf1e3SJoseph Koshy __P4MASK(mem-uc, 7), 1381ebccf1e3SJoseph Koshy __P4MASK(mem-wc, 8), 1382ebccf1e3SJoseph Koshy __P4MASK(mem-wt, 9), 1383ebccf1e3SJoseph Koshy __P4MASK(mem-wp, 10), 1384ebccf1e3SJoseph Koshy __P4MASK(mem-wb, 11), 1385ebccf1e3SJoseph Koshy __P4MASK(own, 13), 1386ebccf1e3SJoseph Koshy __P4MASK(other, 14), 1387ebccf1e3SJoseph Koshy __P4MASK(prefetch, 15), 1388ebccf1e3SJoseph Koshy NULLMASK 1389ebccf1e3SJoseph Koshy }; 1390ebccf1e3SJoseph Koshy 1391ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_iae[] = { /* ioq active entries */ 1392ebccf1e3SJoseph Koshy __P4MASK(all-read, 5), 1393ebccf1e3SJoseph Koshy __P4MASK(all-write, 6), 1394ebccf1e3SJoseph Koshy __P4MASK(mem-uc, 7), 1395ebccf1e3SJoseph Koshy __P4MASK(mem-wc, 8), 1396ebccf1e3SJoseph Koshy __P4MASK(mem-wt, 9), 1397ebccf1e3SJoseph Koshy __P4MASK(mem-wp, 10), 1398ebccf1e3SJoseph Koshy __P4MASK(mem-wb, 11), 1399ebccf1e3SJoseph Koshy __P4MASK(own, 13), 1400ebccf1e3SJoseph Koshy __P4MASK(other, 14), 1401ebccf1e3SJoseph Koshy __P4MASK(prefetch, 15), 1402ebccf1e3SJoseph Koshy NULLMASK 1403ebccf1e3SJoseph Koshy }; 1404ebccf1e3SJoseph Koshy 1405ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_fda[] = { /* fsb data activity */ 1406ebccf1e3SJoseph Koshy __P4MASK(drdy-drv, 0), 1407ebccf1e3SJoseph Koshy __P4MASK(drdy-own, 1), 1408ebccf1e3SJoseph Koshy __P4MASK(drdy-other, 2), 1409ebccf1e3SJoseph Koshy __P4MASK(dbsy-drv, 3), 1410ebccf1e3SJoseph Koshy __P4MASK(dbsy-own, 4), 1411ebccf1e3SJoseph Koshy __P4MASK(dbsy-other, 5), 1412ebccf1e3SJoseph Koshy NULLMASK 1413ebccf1e3SJoseph Koshy }; 1414ebccf1e3SJoseph Koshy 1415ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ba[] = { /* bsq allocation */ 1416ebccf1e3SJoseph Koshy __P4MASK(req-type0, 0), 1417ebccf1e3SJoseph Koshy __P4MASK(req-type1, 1), 1418ebccf1e3SJoseph Koshy __P4MASK(req-len0, 2), 1419ebccf1e3SJoseph Koshy __P4MASK(req-len1, 3), 1420ebccf1e3SJoseph Koshy __P4MASK(req-io-type, 5), 1421ebccf1e3SJoseph Koshy __P4MASK(req-lock-type, 6), 1422ebccf1e3SJoseph Koshy __P4MASK(req-cache-type, 7), 1423ebccf1e3SJoseph Koshy __P4MASK(req-split-type, 8), 1424ebccf1e3SJoseph Koshy __P4MASK(req-dem-type, 9), 1425ebccf1e3SJoseph Koshy __P4MASK(req-ord-type, 10), 1426ebccf1e3SJoseph Koshy __P4MASK(mem-type0, 11), 1427ebccf1e3SJoseph Koshy __P4MASK(mem-type1, 12), 1428ebccf1e3SJoseph Koshy __P4MASK(mem-type2, 13), 1429ebccf1e3SJoseph Koshy NULLMASK 1430ebccf1e3SJoseph Koshy }; 1431ebccf1e3SJoseph Koshy 1432ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_sia[] = { /* sse input assist */ 1433ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1434ebccf1e3SJoseph Koshy NULLMASK 1435ebccf1e3SJoseph Koshy }; 1436ebccf1e3SJoseph Koshy 1437ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_psu[] = { /* packed sp uop */ 1438ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1439ebccf1e3SJoseph Koshy NULLMASK 1440ebccf1e3SJoseph Koshy }; 1441ebccf1e3SJoseph Koshy 1442ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_pdu[] = { /* packed dp uop */ 1443ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1444ebccf1e3SJoseph Koshy NULLMASK 1445ebccf1e3SJoseph Koshy }; 1446ebccf1e3SJoseph Koshy 1447ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ssu[] = { /* scalar sp uop */ 1448ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1449ebccf1e3SJoseph Koshy NULLMASK 1450ebccf1e3SJoseph Koshy }; 1451ebccf1e3SJoseph Koshy 1452ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_sdu[] = { /* scalar dp uop */ 1453ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1454ebccf1e3SJoseph Koshy NULLMASK 1455ebccf1e3SJoseph Koshy }; 1456ebccf1e3SJoseph Koshy 1457ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_64bmu[] = { /* 64 bit mmx uop */ 1458ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1459ebccf1e3SJoseph Koshy NULLMASK 1460ebccf1e3SJoseph Koshy }; 1461ebccf1e3SJoseph Koshy 1462ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_128bmu[] = { /* 128 bit mmx uop */ 1463ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1464ebccf1e3SJoseph Koshy NULLMASK 1465ebccf1e3SJoseph Koshy }; 1466ebccf1e3SJoseph Koshy 1467ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xfu[] = { /* X87 fp uop */ 1468ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1469ebccf1e3SJoseph Koshy NULLMASK 1470ebccf1e3SJoseph Koshy }; 1471ebccf1e3SJoseph Koshy 1472ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xsmu[] = { /* x87 simd moves uop */ 1473ebccf1e3SJoseph Koshy __P4MASK(allp0, 3), 1474ebccf1e3SJoseph Koshy __P4MASK(allp2, 4), 1475ebccf1e3SJoseph Koshy NULLMASK 1476ebccf1e3SJoseph Koshy }; 1477ebccf1e3SJoseph Koshy 1478ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_gpe[] = { /* global power events */ 1479ebccf1e3SJoseph Koshy __P4MASK(running, 0), 1480ebccf1e3SJoseph Koshy NULLMASK 1481ebccf1e3SJoseph Koshy }; 1482ebccf1e3SJoseph Koshy 1483ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_tmx[] = { /* TC ms xfer */ 1484ebccf1e3SJoseph Koshy __P4MASK(cisc, 0), 1485ebccf1e3SJoseph Koshy NULLMASK 1486ebccf1e3SJoseph Koshy }; 1487ebccf1e3SJoseph Koshy 1488ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_uqw[] = { /* uop queue writes */ 1489ebccf1e3SJoseph Koshy __P4MASK(from-tc-build, 0), 1490ebccf1e3SJoseph Koshy __P4MASK(from-tc-deliver, 1), 1491ebccf1e3SJoseph Koshy __P4MASK(from-rom, 2), 1492ebccf1e3SJoseph Koshy NULLMASK 1493ebccf1e3SJoseph Koshy }; 1494ebccf1e3SJoseph Koshy 1495d56c5d4bSJoseph Koshy static const struct pmc_masks p4_mask_rmbt[] = { 1496d56c5d4bSJoseph Koshy /* retired mispred branch type */ 1497ebccf1e3SJoseph Koshy __P4MASK(conditional, 1), 1498ebccf1e3SJoseph Koshy __P4MASK(call, 2), 1499ebccf1e3SJoseph Koshy __P4MASK(return, 3), 1500ebccf1e3SJoseph Koshy __P4MASK(indirect, 4), 1501ebccf1e3SJoseph Koshy NULLMASK 1502ebccf1e3SJoseph Koshy }; 1503ebccf1e3SJoseph Koshy 1504ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_rbt[] = { /* retired branch type */ 1505ebccf1e3SJoseph Koshy __P4MASK(conditional, 1), 1506ebccf1e3SJoseph Koshy __P4MASK(call, 2), 1507ebccf1e3SJoseph Koshy __P4MASK(retired, 3), 1508ebccf1e3SJoseph Koshy __P4MASK(indirect, 4), 1509ebccf1e3SJoseph Koshy NULLMASK 1510ebccf1e3SJoseph Koshy }; 1511ebccf1e3SJoseph Koshy 1512ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_rs[] = { /* resource stall */ 1513ebccf1e3SJoseph Koshy __P4MASK(sbfull, 5), 1514ebccf1e3SJoseph Koshy NULLMASK 1515ebccf1e3SJoseph Koshy }; 1516ebccf1e3SJoseph Koshy 1517ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_wb[] = { /* WC buffer */ 1518ebccf1e3SJoseph Koshy __P4MASK(wcb-evicts, 0), 1519ebccf1e3SJoseph Koshy __P4MASK(wcb-full-evict, 1), 1520ebccf1e3SJoseph Koshy NULLMASK 1521ebccf1e3SJoseph Koshy }; 1522ebccf1e3SJoseph Koshy 1523ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_fee[] = { /* front end event */ 1524ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1525ebccf1e3SJoseph Koshy __P4MASK(bogus, 1), 1526ebccf1e3SJoseph Koshy NULLMASK 1527ebccf1e3SJoseph Koshy }; 1528ebccf1e3SJoseph Koshy 1529ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ee[] = { /* execution event */ 1530ebccf1e3SJoseph Koshy __P4MASK(nbogus0, 0), 1531ebccf1e3SJoseph Koshy __P4MASK(nbogus1, 1), 1532ebccf1e3SJoseph Koshy __P4MASK(nbogus2, 2), 1533ebccf1e3SJoseph Koshy __P4MASK(nbogus3, 3), 1534ebccf1e3SJoseph Koshy __P4MASK(bogus0, 4), 1535ebccf1e3SJoseph Koshy __P4MASK(bogus1, 5), 1536ebccf1e3SJoseph Koshy __P4MASK(bogus2, 6), 1537ebccf1e3SJoseph Koshy __P4MASK(bogus3, 7), 1538ebccf1e3SJoseph Koshy NULLMASK 1539ebccf1e3SJoseph Koshy }; 1540ebccf1e3SJoseph Koshy 1541ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_re[] = { /* replay event */ 1542ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1543ebccf1e3SJoseph Koshy __P4MASK(bogus, 1), 1544ebccf1e3SJoseph Koshy NULLMASK 1545ebccf1e3SJoseph Koshy }; 1546ebccf1e3SJoseph Koshy 1547ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_insret[] = { /* instr retired */ 1548ebccf1e3SJoseph Koshy __P4MASK(nbogusntag, 0), 1549ebccf1e3SJoseph Koshy __P4MASK(nbogustag, 1), 1550ebccf1e3SJoseph Koshy __P4MASK(bogusntag, 2), 1551ebccf1e3SJoseph Koshy __P4MASK(bogustag, 3), 1552ebccf1e3SJoseph Koshy NULLMASK 1553ebccf1e3SJoseph Koshy }; 1554ebccf1e3SJoseph Koshy 1555ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ur[] = { /* uops retired */ 1556ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1557ebccf1e3SJoseph Koshy __P4MASK(bogus, 1), 1558ebccf1e3SJoseph Koshy NULLMASK 1559ebccf1e3SJoseph Koshy }; 1560ebccf1e3SJoseph Koshy 1561ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ut[] = { /* uop type */ 1562ebccf1e3SJoseph Koshy __P4MASK(tagloads, 1), 1563ebccf1e3SJoseph Koshy __P4MASK(tagstores, 2), 1564ebccf1e3SJoseph Koshy NULLMASK 1565ebccf1e3SJoseph Koshy }; 1566ebccf1e3SJoseph Koshy 1567ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_br[] = { /* branch retired */ 1568ebccf1e3SJoseph Koshy __P4MASK(mmnp, 0), 1569ebccf1e3SJoseph Koshy __P4MASK(mmnm, 1), 1570ebccf1e3SJoseph Koshy __P4MASK(mmtp, 2), 1571ebccf1e3SJoseph Koshy __P4MASK(mmtm, 3), 1572ebccf1e3SJoseph Koshy NULLMASK 1573ebccf1e3SJoseph Koshy }; 1574ebccf1e3SJoseph Koshy 1575ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_mbr[] = { /* mispred branch retired */ 1576ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1577ebccf1e3SJoseph Koshy NULLMASK 1578ebccf1e3SJoseph Koshy }; 1579ebccf1e3SJoseph Koshy 1580ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xa[] = { /* x87 assist */ 1581ebccf1e3SJoseph Koshy __P4MASK(fpsu, 0), 1582ebccf1e3SJoseph Koshy __P4MASK(fpso, 1), 1583ebccf1e3SJoseph Koshy __P4MASK(poao, 2), 1584ebccf1e3SJoseph Koshy __P4MASK(poau, 3), 1585ebccf1e3SJoseph Koshy __P4MASK(prea, 4), 1586ebccf1e3SJoseph Koshy NULLMASK 1587ebccf1e3SJoseph Koshy }; 1588ebccf1e3SJoseph Koshy 1589ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_machclr[] = { /* machine clear */ 1590ebccf1e3SJoseph Koshy __P4MASK(clear, 0), 1591ebccf1e3SJoseph Koshy __P4MASK(moclear, 2), 1592ebccf1e3SJoseph Koshy __P4MASK(smclear, 3), 1593ebccf1e3SJoseph Koshy NULLMASK 1594ebccf1e3SJoseph Koshy }; 1595ebccf1e3SJoseph Koshy 1596ebccf1e3SJoseph Koshy /* P4 event parser */ 1597ebccf1e3SJoseph Koshy static int 1598ebccf1e3SJoseph Koshy p4_allocate_pmc(enum pmc_event pe, char *ctrspec, 1599ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 1600ebccf1e3SJoseph Koshy { 1601ebccf1e3SJoseph Koshy 1602ebccf1e3SJoseph Koshy char *e, *p, *q; 1603ebccf1e3SJoseph Koshy int count, has_tag, has_busreqtype, n; 1604*1e862e5aSFabien Thomas uint32_t cccractivemask; 1605*1e862e5aSFabien Thomas uint64_t evmask; 1606ebccf1e3SJoseph Koshy const struct pmc_masks *pm, *pmask; 1607ebccf1e3SJoseph Koshy 1608789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1609f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig = 1610f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 0; 1611ebccf1e3SJoseph Koshy 1612ebccf1e3SJoseph Koshy pmask = NULL; 1613ebccf1e3SJoseph Koshy evmask = 0; 1614ebccf1e3SJoseph Koshy cccractivemask = 0x3; 1615ebccf1e3SJoseph Koshy has_tag = has_busreqtype = 0; 1616ebccf1e3SJoseph Koshy 1617ebccf1e3SJoseph Koshy #define __P4SETMASK(M) do { \ 1618ebccf1e3SJoseph Koshy pmask = p4_mask_##M; \ 1619ebccf1e3SJoseph Koshy } while (0) 1620ebccf1e3SJoseph Koshy 1621ebccf1e3SJoseph Koshy switch (pe) { 1622ebccf1e3SJoseph Koshy case PMC_EV_P4_TC_DELIVER_MODE: 1623ebccf1e3SJoseph Koshy __P4SETMASK(tcdm); 1624ebccf1e3SJoseph Koshy break; 1625ebccf1e3SJoseph Koshy case PMC_EV_P4_BPU_FETCH_REQUEST: 1626ebccf1e3SJoseph Koshy __P4SETMASK(bfr); 1627ebccf1e3SJoseph Koshy break; 1628ebccf1e3SJoseph Koshy case PMC_EV_P4_ITLB_REFERENCE: 1629ebccf1e3SJoseph Koshy __P4SETMASK(ir); 1630ebccf1e3SJoseph Koshy break; 1631ebccf1e3SJoseph Koshy case PMC_EV_P4_MEMORY_CANCEL: 1632ebccf1e3SJoseph Koshy __P4SETMASK(memcan); 1633ebccf1e3SJoseph Koshy break; 1634ebccf1e3SJoseph Koshy case PMC_EV_P4_MEMORY_COMPLETE: 1635ebccf1e3SJoseph Koshy __P4SETMASK(memcomp); 1636ebccf1e3SJoseph Koshy break; 1637ebccf1e3SJoseph Koshy case PMC_EV_P4_LOAD_PORT_REPLAY: 1638ebccf1e3SJoseph Koshy __P4SETMASK(lpr); 1639ebccf1e3SJoseph Koshy break; 1640ebccf1e3SJoseph Koshy case PMC_EV_P4_STORE_PORT_REPLAY: 1641ebccf1e3SJoseph Koshy __P4SETMASK(spr); 1642ebccf1e3SJoseph Koshy break; 1643ebccf1e3SJoseph Koshy case PMC_EV_P4_MOB_LOAD_REPLAY: 1644ebccf1e3SJoseph Koshy __P4SETMASK(mlr); 1645ebccf1e3SJoseph Koshy break; 1646ebccf1e3SJoseph Koshy case PMC_EV_P4_PAGE_WALK_TYPE: 1647ebccf1e3SJoseph Koshy __P4SETMASK(pwt); 1648ebccf1e3SJoseph Koshy break; 1649ebccf1e3SJoseph Koshy case PMC_EV_P4_BSQ_CACHE_REFERENCE: 1650ebccf1e3SJoseph Koshy __P4SETMASK(bcr); 1651ebccf1e3SJoseph Koshy break; 1652ebccf1e3SJoseph Koshy case PMC_EV_P4_IOQ_ALLOCATION: 1653ebccf1e3SJoseph Koshy __P4SETMASK(ia); 1654ebccf1e3SJoseph Koshy has_busreqtype = 1; 1655ebccf1e3SJoseph Koshy break; 1656ebccf1e3SJoseph Koshy case PMC_EV_P4_IOQ_ACTIVE_ENTRIES: 1657ebccf1e3SJoseph Koshy __P4SETMASK(iae); 1658ebccf1e3SJoseph Koshy has_busreqtype = 1; 1659ebccf1e3SJoseph Koshy break; 1660ebccf1e3SJoseph Koshy case PMC_EV_P4_FSB_DATA_ACTIVITY: 1661ebccf1e3SJoseph Koshy __P4SETMASK(fda); 1662ebccf1e3SJoseph Koshy break; 1663ebccf1e3SJoseph Koshy case PMC_EV_P4_BSQ_ALLOCATION: 1664ebccf1e3SJoseph Koshy __P4SETMASK(ba); 1665ebccf1e3SJoseph Koshy break; 1666ebccf1e3SJoseph Koshy case PMC_EV_P4_SSE_INPUT_ASSIST: 1667ebccf1e3SJoseph Koshy __P4SETMASK(sia); 1668ebccf1e3SJoseph Koshy break; 1669ebccf1e3SJoseph Koshy case PMC_EV_P4_PACKED_SP_UOP: 1670ebccf1e3SJoseph Koshy __P4SETMASK(psu); 1671ebccf1e3SJoseph Koshy break; 1672ebccf1e3SJoseph Koshy case PMC_EV_P4_PACKED_DP_UOP: 1673ebccf1e3SJoseph Koshy __P4SETMASK(pdu); 1674ebccf1e3SJoseph Koshy break; 1675ebccf1e3SJoseph Koshy case PMC_EV_P4_SCALAR_SP_UOP: 1676ebccf1e3SJoseph Koshy __P4SETMASK(ssu); 1677ebccf1e3SJoseph Koshy break; 1678ebccf1e3SJoseph Koshy case PMC_EV_P4_SCALAR_DP_UOP: 1679ebccf1e3SJoseph Koshy __P4SETMASK(sdu); 1680ebccf1e3SJoseph Koshy break; 1681ebccf1e3SJoseph Koshy case PMC_EV_P4_64BIT_MMX_UOP: 1682ebccf1e3SJoseph Koshy __P4SETMASK(64bmu); 1683ebccf1e3SJoseph Koshy break; 1684ebccf1e3SJoseph Koshy case PMC_EV_P4_128BIT_MMX_UOP: 1685ebccf1e3SJoseph Koshy __P4SETMASK(128bmu); 1686ebccf1e3SJoseph Koshy break; 1687ebccf1e3SJoseph Koshy case PMC_EV_P4_X87_FP_UOP: 1688ebccf1e3SJoseph Koshy __P4SETMASK(xfu); 1689ebccf1e3SJoseph Koshy break; 1690ebccf1e3SJoseph Koshy case PMC_EV_P4_X87_SIMD_MOVES_UOP: 1691ebccf1e3SJoseph Koshy __P4SETMASK(xsmu); 1692ebccf1e3SJoseph Koshy break; 1693ebccf1e3SJoseph Koshy case PMC_EV_P4_GLOBAL_POWER_EVENTS: 1694ebccf1e3SJoseph Koshy __P4SETMASK(gpe); 1695ebccf1e3SJoseph Koshy break; 1696ebccf1e3SJoseph Koshy case PMC_EV_P4_TC_MS_XFER: 1697ebccf1e3SJoseph Koshy __P4SETMASK(tmx); 1698ebccf1e3SJoseph Koshy break; 1699ebccf1e3SJoseph Koshy case PMC_EV_P4_UOP_QUEUE_WRITES: 1700ebccf1e3SJoseph Koshy __P4SETMASK(uqw); 1701ebccf1e3SJoseph Koshy break; 1702ebccf1e3SJoseph Koshy case PMC_EV_P4_RETIRED_MISPRED_BRANCH_TYPE: 1703ebccf1e3SJoseph Koshy __P4SETMASK(rmbt); 1704ebccf1e3SJoseph Koshy break; 1705ebccf1e3SJoseph Koshy case PMC_EV_P4_RETIRED_BRANCH_TYPE: 1706ebccf1e3SJoseph Koshy __P4SETMASK(rbt); 1707ebccf1e3SJoseph Koshy break; 1708ebccf1e3SJoseph Koshy case PMC_EV_P4_RESOURCE_STALL: 1709ebccf1e3SJoseph Koshy __P4SETMASK(rs); 1710ebccf1e3SJoseph Koshy break; 1711ebccf1e3SJoseph Koshy case PMC_EV_P4_WC_BUFFER: 1712ebccf1e3SJoseph Koshy __P4SETMASK(wb); 1713ebccf1e3SJoseph Koshy break; 1714ebccf1e3SJoseph Koshy case PMC_EV_P4_BSQ_ACTIVE_ENTRIES: 1715ebccf1e3SJoseph Koshy case PMC_EV_P4_B2B_CYCLES: 1716ebccf1e3SJoseph Koshy case PMC_EV_P4_BNR: 1717ebccf1e3SJoseph Koshy case PMC_EV_P4_SNOOP: 1718ebccf1e3SJoseph Koshy case PMC_EV_P4_RESPONSE: 1719ebccf1e3SJoseph Koshy break; 1720ebccf1e3SJoseph Koshy case PMC_EV_P4_FRONT_END_EVENT: 1721ebccf1e3SJoseph Koshy __P4SETMASK(fee); 1722ebccf1e3SJoseph Koshy break; 1723ebccf1e3SJoseph Koshy case PMC_EV_P4_EXECUTION_EVENT: 1724ebccf1e3SJoseph Koshy __P4SETMASK(ee); 1725ebccf1e3SJoseph Koshy break; 1726ebccf1e3SJoseph Koshy case PMC_EV_P4_REPLAY_EVENT: 1727ebccf1e3SJoseph Koshy __P4SETMASK(re); 1728ebccf1e3SJoseph Koshy break; 1729ebccf1e3SJoseph Koshy case PMC_EV_P4_INSTR_RETIRED: 1730ebccf1e3SJoseph Koshy __P4SETMASK(insret); 1731ebccf1e3SJoseph Koshy break; 1732ebccf1e3SJoseph Koshy case PMC_EV_P4_UOPS_RETIRED: 1733ebccf1e3SJoseph Koshy __P4SETMASK(ur); 1734ebccf1e3SJoseph Koshy break; 1735ebccf1e3SJoseph Koshy case PMC_EV_P4_UOP_TYPE: 1736ebccf1e3SJoseph Koshy __P4SETMASK(ut); 1737ebccf1e3SJoseph Koshy break; 1738ebccf1e3SJoseph Koshy case PMC_EV_P4_BRANCH_RETIRED: 1739ebccf1e3SJoseph Koshy __P4SETMASK(br); 1740ebccf1e3SJoseph Koshy break; 1741ebccf1e3SJoseph Koshy case PMC_EV_P4_MISPRED_BRANCH_RETIRED: 1742ebccf1e3SJoseph Koshy __P4SETMASK(mbr); 1743ebccf1e3SJoseph Koshy break; 1744ebccf1e3SJoseph Koshy case PMC_EV_P4_X87_ASSIST: 1745ebccf1e3SJoseph Koshy __P4SETMASK(xa); 1746ebccf1e3SJoseph Koshy break; 1747ebccf1e3SJoseph Koshy case PMC_EV_P4_MACHINE_CLEAR: 1748ebccf1e3SJoseph Koshy __P4SETMASK(machclr); 1749ebccf1e3SJoseph Koshy break; 1750ebccf1e3SJoseph Koshy default: 1751aa342b1fSJoseph Koshy return (-1); 1752ebccf1e3SJoseph Koshy } 1753ebccf1e3SJoseph Koshy 1754ebccf1e3SJoseph Koshy /* process additional flags */ 1755ebccf1e3SJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 1756ebccf1e3SJoseph Koshy if (KWPREFIXMATCH(p, P4_KW_ACTIVE)) { 1757ebccf1e3SJoseph Koshy q = strchr(p, '='); 1758ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1759aa342b1fSJoseph Koshy return (-1); 1760ebccf1e3SJoseph Koshy 1761789140c0SJoseph Koshy if (strcasecmp(q, P4_KW_ACTIVE_NONE) == 0) 1762ebccf1e3SJoseph Koshy cccractivemask = 0x0; 1763789140c0SJoseph Koshy else if (strcasecmp(q, P4_KW_ACTIVE_SINGLE) == 0) 1764ebccf1e3SJoseph Koshy cccractivemask = 0x1; 1765789140c0SJoseph Koshy else if (strcasecmp(q, P4_KW_ACTIVE_BOTH) == 0) 1766ebccf1e3SJoseph Koshy cccractivemask = 0x2; 1767789140c0SJoseph Koshy else if (strcasecmp(q, P4_KW_ACTIVE_ANY) == 0) 1768ebccf1e3SJoseph Koshy cccractivemask = 0x3; 1769ebccf1e3SJoseph Koshy else 1770aa342b1fSJoseph Koshy return (-1); 1771ebccf1e3SJoseph Koshy 1772ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, P4_KW_BUSREQTYPE)) { 1773ebccf1e3SJoseph Koshy if (has_busreqtype == 0) 1774aa342b1fSJoseph Koshy return (-1); 1775ebccf1e3SJoseph Koshy 1776ebccf1e3SJoseph Koshy q = strchr(p, '='); 1777ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1778aa342b1fSJoseph Koshy return (-1); 1779ebccf1e3SJoseph Koshy 1780ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 1781ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 1782aa342b1fSJoseph Koshy return (-1); 1783ebccf1e3SJoseph Koshy evmask = (evmask & ~0x1F) | (count & 0x1F); 1784ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P4_KW_CASCADE)) 1785ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_CASCADE; 1786ebccf1e3SJoseph Koshy else if (KWMATCH(p, P4_KW_EDGE)) 1787ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1788ebccf1e3SJoseph Koshy else if (KWMATCH(p, P4_KW_INV)) 1789ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 1790ebccf1e3SJoseph Koshy else if (KWPREFIXMATCH(p, P4_KW_MASK "=")) { 1791ebccf1e3SJoseph Koshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 1792aa342b1fSJoseph Koshy return (-1); 1793ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1794ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P4_KW_OS)) 1795ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 1796ebccf1e3SJoseph Koshy else if (KWMATCH(p, P4_KW_PRECISE)) 1797ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_PRECISE; 1798ebccf1e3SJoseph Koshy else if (KWPREFIXMATCH(p, P4_KW_TAG "=")) { 1799ebccf1e3SJoseph Koshy if (has_tag == 0) 1800aa342b1fSJoseph Koshy return (-1); 1801ebccf1e3SJoseph Koshy 1802ebccf1e3SJoseph Koshy q = strchr(p, '='); 1803ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1804aa342b1fSJoseph Koshy return (-1); 1805ebccf1e3SJoseph Koshy 1806ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 1807ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 1808aa342b1fSJoseph Koshy return (-1); 1809ebccf1e3SJoseph Koshy 1810ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_TAGGING; 1811f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig |= 1812ebccf1e3SJoseph Koshy P4_ESCR_TO_TAG_VALUE(count); 1813ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, P4_KW_THRESHOLD "=")) { 1814ebccf1e3SJoseph Koshy q = strchr(p, '='); 1815ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1816aa342b1fSJoseph Koshy return (-1); 1817ebccf1e3SJoseph Koshy 1818ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 1819ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 1820aa342b1fSJoseph Koshy return (-1); 1821ebccf1e3SJoseph Koshy 1822ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 1823f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig &= 1824f263522aSJoseph Koshy ~P4_CCCR_THRESHOLD_MASK; 1825f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |= 1826f263522aSJoseph Koshy P4_CCCR_TO_THRESHOLD(count); 1827ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P4_KW_USR)) 1828ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 1829ebccf1e3SJoseph Koshy else 1830aa342b1fSJoseph Koshy return (-1); 1831ebccf1e3SJoseph Koshy } 1832ebccf1e3SJoseph Koshy 1833ebccf1e3SJoseph Koshy /* other post processing */ 1834ebccf1e3SJoseph Koshy if (pe == PMC_EV_P4_IOQ_ALLOCATION || 1835ebccf1e3SJoseph Koshy pe == PMC_EV_P4_FSB_DATA_ACTIVITY || 1836ebccf1e3SJoseph Koshy pe == PMC_EV_P4_BSQ_ALLOCATION) 1837ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1838ebccf1e3SJoseph Koshy 1839ebccf1e3SJoseph Koshy /* fill in thread activity mask */ 1840f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |= 1841ebccf1e3SJoseph Koshy P4_CCCR_TO_ACTIVE_THREAD(cccractivemask); 1842ebccf1e3SJoseph Koshy 1843ebccf1e3SJoseph Koshy if (evmask) 1844ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1845ebccf1e3SJoseph Koshy 1846ebccf1e3SJoseph Koshy switch (pe) { 1847ebccf1e3SJoseph Koshy case PMC_EV_P4_FSB_DATA_ACTIVITY: 1848ebccf1e3SJoseph Koshy if ((evmask & 0x06) == 0x06 || 1849ebccf1e3SJoseph Koshy (evmask & 0x18) == 0x18) 1850aa342b1fSJoseph Koshy return (-1); /* can't have own+other bits together */ 1851ebccf1e3SJoseph Koshy if (evmask == 0) /* default:drdy-{drv,own}+dbsy{drv,own} */ 1852ebccf1e3SJoseph Koshy evmask = 0x1D; 1853ebccf1e3SJoseph Koshy break; 1854ebccf1e3SJoseph Koshy case PMC_EV_P4_MACHINE_CLEAR: 1855ebccf1e3SJoseph Koshy /* only one bit is allowed to be set */ 1856ebccf1e3SJoseph Koshy if ((evmask & (evmask - 1)) != 0) 1857aa342b1fSJoseph Koshy return (-1); 1858ebccf1e3SJoseph Koshy if (evmask == 0) { 1859ebccf1e3SJoseph Koshy evmask = 0x1; /* 'CLEAR' */ 1860ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1861ebccf1e3SJoseph Koshy } 1862ebccf1e3SJoseph Koshy break; 1863ebccf1e3SJoseph Koshy default: 1864ebccf1e3SJoseph Koshy if (evmask == 0 && pmask) { 1865ebccf1e3SJoseph Koshy for (pm = pmask; pm->pm_name; pm++) 1866ebccf1e3SJoseph Koshy evmask |= pm->pm_value; 1867ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1868ebccf1e3SJoseph Koshy } 1869ebccf1e3SJoseph Koshy } 1870ebccf1e3SJoseph Koshy 1871f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 1872f263522aSJoseph Koshy P4_ESCR_TO_EVENT_MASK(evmask); 1873ebccf1e3SJoseph Koshy 1874aa342b1fSJoseph Koshy return (0); 1875ebccf1e3SJoseph Koshy } 1876ebccf1e3SJoseph Koshy 187786a65549SJoseph Koshy #endif 187886a65549SJoseph Koshy 187986a65549SJoseph Koshy #if defined(__i386__) 188086a65549SJoseph Koshy 1881ebccf1e3SJoseph Koshy /* 1882f263522aSJoseph Koshy * Pentium style PMCs 1883f263522aSJoseph Koshy */ 1884f263522aSJoseph Koshy 1885f263522aSJoseph Koshy static struct pmc_event_alias p5_aliases[] = { 18860b9b757dSJoseph Koshy EV_ALIAS("branches", "p5-taken-branches"), 1887f263522aSJoseph Koshy EV_ALIAS("cycles", "tsc"), 18880b9b757dSJoseph Koshy EV_ALIAS("dc-misses", "p5-data-read-miss-or-write-miss"), 18890b9b757dSJoseph Koshy EV_ALIAS("ic-misses", "p5-code-cache-miss"), 18900b9b757dSJoseph Koshy EV_ALIAS("instructions", "p5-instructions-executed"), 18910b9b757dSJoseph Koshy EV_ALIAS("interrupts", "p5-hardware-interrupts"), 18920b9b757dSJoseph Koshy EV_ALIAS("unhalted-cycles", 18930b9b757dSJoseph Koshy "p5-number-of-cycles-not-in-halt-state"), 1894f263522aSJoseph Koshy EV_ALIAS(NULL, NULL) 1895f263522aSJoseph Koshy }; 1896f263522aSJoseph Koshy 1897f263522aSJoseph Koshy static int 1898f263522aSJoseph Koshy p5_allocate_pmc(enum pmc_event pe, char *ctrspec, 1899f263522aSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 1900f263522aSJoseph Koshy { 1901aa342b1fSJoseph Koshy return (-1 || pe || ctrspec || pmc_config); /* shut up gcc */ 1902f263522aSJoseph Koshy } 1903f263522aSJoseph Koshy 1904f263522aSJoseph Koshy /* 1905ebccf1e3SJoseph Koshy * Pentium Pro style PMCs. These PMCs are found in Pentium II, Pentium III, 1906ebccf1e3SJoseph Koshy * and Pentium M CPUs. 1907ebccf1e3SJoseph Koshy */ 1908ebccf1e3SJoseph Koshy 1909ebccf1e3SJoseph Koshy static struct pmc_event_alias p6_aliases[] = { 1910ebccf1e3SJoseph Koshy EV_ALIAS("branches", "p6-br-inst-retired"), 1911ebccf1e3SJoseph Koshy EV_ALIAS("branch-mispredicts", "p6-br-miss-pred-retired"), 1912ebccf1e3SJoseph Koshy EV_ALIAS("cycles", "tsc"), 1913d56c5d4bSJoseph Koshy EV_ALIAS("dc-misses", "p6-dcu-lines-in"), 191473e2d811SJoseph Koshy EV_ALIAS("ic-misses", "p6-ifu-fetch-miss"), 1915ebccf1e3SJoseph Koshy EV_ALIAS("instructions", "p6-inst-retired"), 1916ebccf1e3SJoseph Koshy EV_ALIAS("interrupts", "p6-hw-int-rx"), 1917177a2f22SJoseph Koshy EV_ALIAS("unhalted-cycles", "p6-cpu-clk-unhalted"), 1918ebccf1e3SJoseph Koshy EV_ALIAS(NULL, NULL) 1919ebccf1e3SJoseph Koshy }; 1920ebccf1e3SJoseph Koshy 1921ebccf1e3SJoseph Koshy #define P6_KW_CMASK "cmask" 1922ebccf1e3SJoseph Koshy #define P6_KW_EDGE "edge" 1923ebccf1e3SJoseph Koshy #define P6_KW_INV "inv" 1924ebccf1e3SJoseph Koshy #define P6_KW_OS "os" 1925ebccf1e3SJoseph Koshy #define P6_KW_UMASK "umask" 1926ebccf1e3SJoseph Koshy #define P6_KW_USR "usr" 1927ebccf1e3SJoseph Koshy 1928ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mesi[] = { 1929ebccf1e3SJoseph Koshy PMCMASK(m, 0x01), 1930ebccf1e3SJoseph Koshy PMCMASK(e, 0x02), 1931ebccf1e3SJoseph Koshy PMCMASK(s, 0x04), 1932ebccf1e3SJoseph Koshy PMCMASK(i, 0x08), 1933ebccf1e3SJoseph Koshy NULLMASK 1934ebccf1e3SJoseph Koshy }; 1935ebccf1e3SJoseph Koshy 1936ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mesihw[] = { 1937ebccf1e3SJoseph Koshy PMCMASK(m, 0x01), 1938ebccf1e3SJoseph Koshy PMCMASK(e, 0x02), 1939ebccf1e3SJoseph Koshy PMCMASK(s, 0x04), 1940ebccf1e3SJoseph Koshy PMCMASK(i, 0x08), 1941ebccf1e3SJoseph Koshy PMCMASK(nonhw, 0x00), 1942ebccf1e3SJoseph Koshy PMCMASK(hw, 0x10), 1943ebccf1e3SJoseph Koshy PMCMASK(both, 0x30), 1944ebccf1e3SJoseph Koshy NULLMASK 1945ebccf1e3SJoseph Koshy }; 1946ebccf1e3SJoseph Koshy 1947ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_hw[] = { 1948ebccf1e3SJoseph Koshy PMCMASK(nonhw, 0x00), 1949ebccf1e3SJoseph Koshy PMCMASK(hw, 0x10), 1950ebccf1e3SJoseph Koshy PMCMASK(both, 0x30), 1951ebccf1e3SJoseph Koshy NULLMASK 1952ebccf1e3SJoseph Koshy }; 1953ebccf1e3SJoseph Koshy 1954ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_any[] = { 1955ebccf1e3SJoseph Koshy PMCMASK(self, 0x00), 1956ebccf1e3SJoseph Koshy PMCMASK(any, 0x20), 1957ebccf1e3SJoseph Koshy NULLMASK 1958ebccf1e3SJoseph Koshy }; 1959ebccf1e3SJoseph Koshy 1960ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_ekp[] = { 1961ebccf1e3SJoseph Koshy PMCMASK(nta, 0x00), 1962ebccf1e3SJoseph Koshy PMCMASK(t1, 0x01), 1963ebccf1e3SJoseph Koshy PMCMASK(t2, 0x02), 1964ebccf1e3SJoseph Koshy PMCMASK(wos, 0x03), 1965ebccf1e3SJoseph Koshy NULLMASK 1966ebccf1e3SJoseph Koshy }; 1967ebccf1e3SJoseph Koshy 1968ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_pps[] = { 1969ebccf1e3SJoseph Koshy PMCMASK(packed-and-scalar, 0x00), 1970ebccf1e3SJoseph Koshy PMCMASK(scalar, 0x01), 1971ebccf1e3SJoseph Koshy NULLMASK 1972ebccf1e3SJoseph Koshy }; 1973ebccf1e3SJoseph Koshy 1974ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mite[] = { 1975ebccf1e3SJoseph Koshy PMCMASK(packed-multiply, 0x01), 1976ebccf1e3SJoseph Koshy PMCMASK(packed-shift, 0x02), 1977ebccf1e3SJoseph Koshy PMCMASK(pack, 0x04), 1978ebccf1e3SJoseph Koshy PMCMASK(unpack, 0x08), 1979ebccf1e3SJoseph Koshy PMCMASK(packed-logical, 0x10), 1980ebccf1e3SJoseph Koshy PMCMASK(packed-arithmetic, 0x20), 1981ebccf1e3SJoseph Koshy NULLMASK 1982ebccf1e3SJoseph Koshy }; 1983ebccf1e3SJoseph Koshy 1984ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_fmt[] = { 1985ebccf1e3SJoseph Koshy PMCMASK(mmxtofp, 0x00), 1986ebccf1e3SJoseph Koshy PMCMASK(fptommx, 0x01), 1987ebccf1e3SJoseph Koshy NULLMASK 1988ebccf1e3SJoseph Koshy }; 1989ebccf1e3SJoseph Koshy 1990ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_sr[] = { 1991ebccf1e3SJoseph Koshy PMCMASK(es, 0x01), 1992ebccf1e3SJoseph Koshy PMCMASK(ds, 0x02), 1993ebccf1e3SJoseph Koshy PMCMASK(fs, 0x04), 1994ebccf1e3SJoseph Koshy PMCMASK(gs, 0x08), 1995ebccf1e3SJoseph Koshy NULLMASK 1996ebccf1e3SJoseph Koshy }; 1997ebccf1e3SJoseph Koshy 1998ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_eet[] = { 1999ebccf1e3SJoseph Koshy PMCMASK(all, 0x00), 2000ebccf1e3SJoseph Koshy PMCMASK(freq, 0x02), 2001ebccf1e3SJoseph Koshy NULLMASK 2002ebccf1e3SJoseph Koshy }; 2003ebccf1e3SJoseph Koshy 2004ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_efur[] = { 2005ebccf1e3SJoseph Koshy PMCMASK(all, 0x00), 2006ebccf1e3SJoseph Koshy PMCMASK(loadop, 0x01), 2007ebccf1e3SJoseph Koshy PMCMASK(stdsta, 0x02), 2008ebccf1e3SJoseph Koshy NULLMASK 2009ebccf1e3SJoseph Koshy }; 2010ebccf1e3SJoseph Koshy 2011ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_essir[] = { 2012ebccf1e3SJoseph Koshy PMCMASK(sse-packed-single, 0x00), 2013ebccf1e3SJoseph Koshy PMCMASK(sse-packed-single-scalar-single, 0x01), 2014ebccf1e3SJoseph Koshy PMCMASK(sse2-packed-double, 0x02), 2015ebccf1e3SJoseph Koshy PMCMASK(sse2-scalar-double, 0x03), 2016ebccf1e3SJoseph Koshy NULLMASK 2017ebccf1e3SJoseph Koshy }; 2018ebccf1e3SJoseph Koshy 2019ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_esscir[] = { 2020ebccf1e3SJoseph Koshy PMCMASK(sse-packed-single, 0x00), 2021ebccf1e3SJoseph Koshy PMCMASK(sse-scalar-single, 0x01), 2022ebccf1e3SJoseph Koshy PMCMASK(sse2-packed-double, 0x02), 2023ebccf1e3SJoseph Koshy PMCMASK(sse2-scalar-double, 0x03), 2024ebccf1e3SJoseph Koshy NULLMASK 2025ebccf1e3SJoseph Koshy }; 2026ebccf1e3SJoseph Koshy 2027ebccf1e3SJoseph Koshy /* P6 event parser */ 2028ebccf1e3SJoseph Koshy static int 2029ebccf1e3SJoseph Koshy p6_allocate_pmc(enum pmc_event pe, char *ctrspec, 2030ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 2031ebccf1e3SJoseph Koshy { 2032ebccf1e3SJoseph Koshy char *e, *p, *q; 2033*1e862e5aSFabien Thomas uint64_t evmask; 2034ebccf1e3SJoseph Koshy int count, n; 2035ebccf1e3SJoseph Koshy const struct pmc_masks *pm, *pmask; 2036ebccf1e3SJoseph Koshy 2037789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2038f263522aSJoseph Koshy pmc_config->pm_md.pm_ppro.pm_ppro_config = 0; 2039ebccf1e3SJoseph Koshy 2040ebccf1e3SJoseph Koshy evmask = 0; 2041ebccf1e3SJoseph Koshy 2042ebccf1e3SJoseph Koshy #define P6MASKSET(M) pmask = p6_mask_ ## M 2043ebccf1e3SJoseph Koshy 2044ebccf1e3SJoseph Koshy switch(pe) { 2045ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_IFETCH: P6MASKSET(mesi); break; 2046ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_LD: P6MASKSET(mesi); break; 2047ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_ST: P6MASKSET(mesi); break; 2048ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_RQSTS: P6MASKSET(mesi); break; 2049ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_DRDY_CLOCKS: 2050ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_LOCK_CLOCKS: 2051ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BRD: 2052ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_RFO: 2053ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_WB: 2054ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_IFETCH: 2055ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_INVAL: 2056ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_PWR: 2057ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_P: 2058ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_IO: 2059ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_DEF: 2060ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BURST: 2061ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_ANY: 2062ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_MEM: 2063ebccf1e3SJoseph Koshy P6MASKSET(any); break; 2064ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED: 2065ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_MISS: 2066ebccf1e3SJoseph Koshy P6MASKSET(ekp); break; 2067ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_INST_RETIRED: 2068ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_COMP_INST_RET: 2069ebccf1e3SJoseph Koshy P6MASKSET(pps); break; 2070ebccf1e3SJoseph Koshy case PMC_EV_P6_MMX_INSTR_TYPE_EXEC: 2071ebccf1e3SJoseph Koshy P6MASKSET(mite); break; 2072ebccf1e3SJoseph Koshy case PMC_EV_P6_FP_MMX_TRANS: 2073ebccf1e3SJoseph Koshy P6MASKSET(fmt); break; 2074ebccf1e3SJoseph Koshy case PMC_EV_P6_SEG_RENAME_STALLS: 2075ebccf1e3SJoseph Koshy case PMC_EV_P6_SEG_REG_RENAMES: 2076ebccf1e3SJoseph Koshy P6MASKSET(sr); break; 2077ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_EST_TRANS: 2078ebccf1e3SJoseph Koshy P6MASKSET(eet); break; 2079ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_FUSED_UOPS_RET: 2080ebccf1e3SJoseph Koshy P6MASKSET(efur); break; 2081ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED: 2082ebccf1e3SJoseph Koshy P6MASKSET(essir); break; 2083ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED: 2084ebccf1e3SJoseph Koshy P6MASKSET(esscir); break; 2085ebccf1e3SJoseph Koshy default: 2086ebccf1e3SJoseph Koshy pmask = NULL; 2087ebccf1e3SJoseph Koshy break; 2088ebccf1e3SJoseph Koshy } 2089ebccf1e3SJoseph Koshy 2090ebccf1e3SJoseph Koshy /* Pentium M PMCs have a few events with different semantics */ 2091ebccf1e3SJoseph Koshy if (cpu_info.pm_cputype == PMC_CPU_INTEL_PM) { 2092ebccf1e3SJoseph Koshy if (pe == PMC_EV_P6_L2_LD || 2093ebccf1e3SJoseph Koshy pe == PMC_EV_P6_L2_LINES_IN || 2094ebccf1e3SJoseph Koshy pe == PMC_EV_P6_L2_LINES_OUT) 2095ebccf1e3SJoseph Koshy P6MASKSET(mesihw); 2096ebccf1e3SJoseph Koshy else if (pe == PMC_EV_P6_L2_M_LINES_OUTM) 2097ebccf1e3SJoseph Koshy P6MASKSET(hw); 2098ebccf1e3SJoseph Koshy } 2099ebccf1e3SJoseph Koshy 2100ebccf1e3SJoseph Koshy /* Parse additional modifiers if present */ 2101ebccf1e3SJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 2102ebccf1e3SJoseph Koshy if (KWPREFIXMATCH(p, P6_KW_CMASK "=")) { 2103ebccf1e3SJoseph Koshy q = strchr(p, '='); 2104ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 2105aa342b1fSJoseph Koshy return (-1); 2106ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 2107ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 2108aa342b1fSJoseph Koshy return (-1); 2109ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 2110f263522aSJoseph Koshy pmc_config->pm_md.pm_ppro.pm_ppro_config |= 2111f263522aSJoseph Koshy P6_EVSEL_TO_CMASK(count); 2112ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_EDGE)) { 2113ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 2114ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_INV)) { 2115ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 2116ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_OS)) { 2117ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2118ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, P6_KW_UMASK "=")) { 2119ebccf1e3SJoseph Koshy evmask = 0; 2120ebccf1e3SJoseph Koshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 2121aa342b1fSJoseph Koshy return (-1); 2122ebccf1e3SJoseph Koshy if ((pe == PMC_EV_P6_BUS_DRDY_CLOCKS || 2123ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_LOCK_CLOCKS || 2124ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_BRD || 2125ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_RFO || 2126ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_IFETCH || 2127ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_INVAL || 2128ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_PWR || 2129ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_DEF || 2130ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_BURST || 2131ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_ANY || 2132ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_MEM || 2133ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRANS_IO || 2134ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRANS_P || 2135ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRANS_WB || 2136ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_EST_TRANS || 2137ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_FUSED_UOPS_RET || 2138ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_COMP_INST_RET || 2139ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_INST_RETIRED || 2140ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_PREF_DISPATCHED || 2141ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_PREF_MISS || 2142ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED || 2143ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED || 2144ebccf1e3SJoseph Koshy pe == PMC_EV_P6_FP_MMX_TRANS) 2145aa342b1fSJoseph Koshy && (n > 1)) /* Only one mask keyword is allowed. */ 2146aa342b1fSJoseph Koshy return (-1); 2147ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2148ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_USR)) { 2149ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 2150ebccf1e3SJoseph Koshy } else 2151aa342b1fSJoseph Koshy return (-1); 2152ebccf1e3SJoseph Koshy } 2153ebccf1e3SJoseph Koshy 2154ebccf1e3SJoseph Koshy /* post processing */ 2155ebccf1e3SJoseph Koshy switch (pe) { 2156ebccf1e3SJoseph Koshy 2157ebccf1e3SJoseph Koshy /* 2158ebccf1e3SJoseph Koshy * The following events default to an evmask of 0 2159ebccf1e3SJoseph Koshy */ 2160ebccf1e3SJoseph Koshy 2161ebccf1e3SJoseph Koshy /* default => 'self' */ 2162ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_DRDY_CLOCKS: 2163ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_LOCK_CLOCKS: 2164ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BRD: 2165ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_RFO: 2166ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_WB: 2167ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_IFETCH: 2168ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_INVAL: 2169ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_PWR: 2170ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_P: 2171ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_IO: 2172ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_DEF: 2173ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BURST: 2174ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_ANY: 2175ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_MEM: 2176ebccf1e3SJoseph Koshy 2177ebccf1e3SJoseph Koshy /* default => 'nta' */ 2178ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED: 2179ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_MISS: 2180ebccf1e3SJoseph Koshy 2181ebccf1e3SJoseph Koshy /* default => 'packed and scalar' */ 2182ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_INST_RETIRED: 2183ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_COMP_INST_RET: 2184ebccf1e3SJoseph Koshy 2185ebccf1e3SJoseph Koshy /* default => 'mmx to fp transitions' */ 2186ebccf1e3SJoseph Koshy case PMC_EV_P6_FP_MMX_TRANS: 2187ebccf1e3SJoseph Koshy 2188ebccf1e3SJoseph Koshy /* default => 'SSE Packed Single' */ 2189ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED: 2190ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED: 2191ebccf1e3SJoseph Koshy 2192ebccf1e3SJoseph Koshy /* default => 'all fused micro-ops' */ 2193ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_FUSED_UOPS_RET: 2194ebccf1e3SJoseph Koshy 2195ebccf1e3SJoseph Koshy /* default => 'all transitions' */ 2196ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_EST_TRANS: 2197ebccf1e3SJoseph Koshy break; 2198ebccf1e3SJoseph Koshy 2199ebccf1e3SJoseph Koshy case PMC_EV_P6_MMX_UOPS_EXEC: 2200ebccf1e3SJoseph Koshy evmask = 0x0F; /* only value allowed */ 2201ebccf1e3SJoseph Koshy break; 2202ebccf1e3SJoseph Koshy 2203ebccf1e3SJoseph Koshy default: 2204ebccf1e3SJoseph Koshy /* 2205ebccf1e3SJoseph Koshy * For all other events, set the default event mask 2206ebccf1e3SJoseph Koshy * to a logical OR of all the allowed event mask bits. 2207ebccf1e3SJoseph Koshy */ 2208ebccf1e3SJoseph Koshy if (evmask == 0 && pmask) { 2209ebccf1e3SJoseph Koshy for (pm = pmask; pm->pm_name; pm++) 2210ebccf1e3SJoseph Koshy evmask |= pm->pm_value; 2211ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2212ebccf1e3SJoseph Koshy } 2213ebccf1e3SJoseph Koshy 2214ebccf1e3SJoseph Koshy break; 2215ebccf1e3SJoseph Koshy } 2216ebccf1e3SJoseph Koshy 2217ebccf1e3SJoseph Koshy if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) 2218f263522aSJoseph Koshy pmc_config->pm_md.pm_ppro.pm_ppro_config |= 2219f263522aSJoseph Koshy P6_EVSEL_TO_UMASK(evmask); 2220ebccf1e3SJoseph Koshy 2221aa342b1fSJoseph Koshy return (0); 2222ebccf1e3SJoseph Koshy } 2223ebccf1e3SJoseph Koshy 2224ebccf1e3SJoseph Koshy #endif 2225ebccf1e3SJoseph Koshy 2226789140c0SJoseph Koshy #if defined(__i386__) || defined(__amd64__) 2227789140c0SJoseph Koshy static int 2228789140c0SJoseph Koshy tsc_allocate_pmc(enum pmc_event pe, char *ctrspec, 2229789140c0SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 2230789140c0SJoseph Koshy { 2231789140c0SJoseph Koshy if (pe != PMC_EV_TSC_TSC) 2232789140c0SJoseph Koshy return (-1); 2233789140c0SJoseph Koshy 2234789140c0SJoseph Koshy /* TSC events must be unqualified. */ 2235789140c0SJoseph Koshy if (ctrspec && *ctrspec != '\0') 2236789140c0SJoseph Koshy return (-1); 2237789140c0SJoseph Koshy 2238789140c0SJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 2239789140c0SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_READ; 2240789140c0SJoseph Koshy 2241789140c0SJoseph Koshy return (0); 2242789140c0SJoseph Koshy } 2243789140c0SJoseph Koshy #endif 2244789140c0SJoseph Koshy 2245f5f9340bSFabien Thomas static struct pmc_event_alias generic_aliases[] = { 2246f5f9340bSFabien Thomas EV_ALIAS("instructions", "SOFT-CLOCK.HARD"), 2247f5f9340bSFabien Thomas EV_ALIAS(NULL, NULL) 2248f5f9340bSFabien Thomas }; 2249f5f9340bSFabien Thomas 2250f5f9340bSFabien Thomas static int 2251f5f9340bSFabien Thomas soft_allocate_pmc(enum pmc_event pe, char *ctrspec, 2252f5f9340bSFabien Thomas struct pmc_op_pmcallocate *pmc_config) 2253f5f9340bSFabien Thomas { 2254f5f9340bSFabien Thomas (void)ctrspec; 2255f5f9340bSFabien Thomas (void)pmc_config; 2256f5f9340bSFabien Thomas 2257f5f9340bSFabien Thomas if (pe < PMC_EV_SOFT_FIRST || pe > PMC_EV_SOFT_LAST) 2258f5f9340bSFabien Thomas return (-1); 2259f5f9340bSFabien Thomas 2260f5f9340bSFabien Thomas pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2261f5f9340bSFabien Thomas return (0); 2262f5f9340bSFabien Thomas } 2263f5f9340bSFabien Thomas 22640ce207d2SRui Paulo #if defined(__XSCALE__) 22650ce207d2SRui Paulo 22660ce207d2SRui Paulo static struct pmc_event_alias xscale_aliases[] = { 22670ce207d2SRui Paulo EV_ALIAS("branches", "BRANCH_RETIRED"), 22680ce207d2SRui Paulo EV_ALIAS("branch-mispredicts", "BRANCH_MISPRED"), 22690ce207d2SRui Paulo EV_ALIAS("dc-misses", "DC_MISS"), 22700ce207d2SRui Paulo EV_ALIAS("ic-misses", "IC_MISS"), 22710ce207d2SRui Paulo EV_ALIAS("instructions", "INSTR_RETIRED"), 22720ce207d2SRui Paulo EV_ALIAS(NULL, NULL) 22730ce207d2SRui Paulo }; 22740ce207d2SRui Paulo static int 22750ce207d2SRui Paulo xscale_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 22760ce207d2SRui Paulo struct pmc_op_pmcallocate *pmc_config __unused) 22770ce207d2SRui Paulo { 22780ce207d2SRui Paulo switch (pe) { 22790ce207d2SRui Paulo default: 22800ce207d2SRui Paulo break; 22810ce207d2SRui Paulo } 22820ce207d2SRui Paulo 22830ce207d2SRui Paulo return (0); 22840ce207d2SRui Paulo } 22850ce207d2SRui Paulo #endif 22860ce207d2SRui Paulo 2287660df75eSGeorge V. Neville-Neil #if defined(__mips__) 2288660df75eSGeorge V. Neville-Neil 2289660df75eSGeorge V. Neville-Neil static struct pmc_event_alias mips24k_aliases[] = { 2290660df75eSGeorge V. Neville-Neil EV_ALIAS("instructions", "INSTR_EXECUTED"), 2291660df75eSGeorge V. Neville-Neil EV_ALIAS("branches", "BRANCH_COMPLETED"), 2292660df75eSGeorge V. Neville-Neil EV_ALIAS("branch-mispredicts", "BRANCH_MISPRED"), 2293660df75eSGeorge V. Neville-Neil EV_ALIAS(NULL, NULL) 2294660df75eSGeorge V. Neville-Neil }; 2295660df75eSGeorge V. Neville-Neil 2296c2657f80SOleksandr Tymoshenko static struct pmc_event_alias octeon_aliases[] = { 2297c2657f80SOleksandr Tymoshenko EV_ALIAS("instructions", "RET"), 2298c2657f80SOleksandr Tymoshenko EV_ALIAS("branches", "BR"), 2299c2657f80SOleksandr Tymoshenko EV_ALIAS("branch-mispredicts", "BRMIS"), 2300c2657f80SOleksandr Tymoshenko EV_ALIAS(NULL, NULL) 2301c2657f80SOleksandr Tymoshenko }; 2302c2657f80SOleksandr Tymoshenko 23032827d3e1SOleksandr Tymoshenko #define MIPS_KW_OS "os" 23042827d3e1SOleksandr Tymoshenko #define MIPS_KW_USR "usr" 23052827d3e1SOleksandr Tymoshenko #define MIPS_KW_ANYTHREAD "anythread" 2306660df75eSGeorge V. Neville-Neil 2307660df75eSGeorge V. Neville-Neil static int 23082827d3e1SOleksandr Tymoshenko mips_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 2309660df75eSGeorge V. Neville-Neil struct pmc_op_pmcallocate *pmc_config __unused) 2310660df75eSGeorge V. Neville-Neil { 2311660df75eSGeorge V. Neville-Neil char *p; 2312660df75eSGeorge V. Neville-Neil 2313660df75eSGeorge V. Neville-Neil (void) pe; 2314660df75eSGeorge V. Neville-Neil 2315660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2316660df75eSGeorge V. Neville-Neil 2317660df75eSGeorge V. Neville-Neil while ((p = strsep(&ctrspec, ",")) != NULL) { 23182827d3e1SOleksandr Tymoshenko if (KWMATCH(p, MIPS_KW_OS)) 2319660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= PMC_CAP_SYSTEM; 23202827d3e1SOleksandr Tymoshenko else if (KWMATCH(p, MIPS_KW_USR)) 2321660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= PMC_CAP_USER; 23222827d3e1SOleksandr Tymoshenko else if (KWMATCH(p, MIPS_KW_ANYTHREAD)) 2323660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= (PMC_CAP_USER | PMC_CAP_SYSTEM); 2324660df75eSGeorge V. Neville-Neil else 2325660df75eSGeorge V. Neville-Neil return (-1); 2326660df75eSGeorge V. Neville-Neil } 2327660df75eSGeorge V. Neville-Neil 2328660df75eSGeorge V. Neville-Neil return (0); 2329660df75eSGeorge V. Neville-Neil } 23302827d3e1SOleksandr Tymoshenko 2331660df75eSGeorge V. Neville-Neil #endif /* __mips__ */ 2332660df75eSGeorge V. Neville-Neil 23337b25dccaSJustin Hibbits #if defined(__powerpc__) 23347b25dccaSJustin Hibbits 23357b25dccaSJustin Hibbits static struct pmc_event_alias ppc7450_aliases[] = { 23367b25dccaSJustin Hibbits EV_ALIAS("instructions", "INSTR_COMPLETED"), 23377b25dccaSJustin Hibbits EV_ALIAS("branches", "BRANCHES_COMPLETED"), 23387b25dccaSJustin Hibbits EV_ALIAS("branch-mispredicts", "MISPREDICTED_BRANCHES"), 23397b25dccaSJustin Hibbits EV_ALIAS(NULL, NULL) 23407b25dccaSJustin Hibbits }; 23417b25dccaSJustin Hibbits 23427b25dccaSJustin Hibbits #define PPC7450_KW_OS "os" 23437b25dccaSJustin Hibbits #define PPC7450_KW_USR "usr" 23447b25dccaSJustin Hibbits #define PPC7450_KW_ANYTHREAD "anythread" 23457b25dccaSJustin Hibbits 23467b25dccaSJustin Hibbits static int 23477b25dccaSJustin Hibbits ppc7450_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 23487b25dccaSJustin Hibbits struct pmc_op_pmcallocate *pmc_config __unused) 23497b25dccaSJustin Hibbits { 23507b25dccaSJustin Hibbits char *p; 23517b25dccaSJustin Hibbits 23527b25dccaSJustin Hibbits (void) pe; 23537b25dccaSJustin Hibbits 23547b25dccaSJustin Hibbits pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 23557b25dccaSJustin Hibbits 23567b25dccaSJustin Hibbits while ((p = strsep(&ctrspec, ",")) != NULL) { 23577b25dccaSJustin Hibbits if (KWMATCH(p, PPC7450_KW_OS)) 23587b25dccaSJustin Hibbits pmc_config->pm_caps |= PMC_CAP_SYSTEM; 23597b25dccaSJustin Hibbits else if (KWMATCH(p, PPC7450_KW_USR)) 23607b25dccaSJustin Hibbits pmc_config->pm_caps |= PMC_CAP_USER; 23617b25dccaSJustin Hibbits else if (KWMATCH(p, PPC7450_KW_ANYTHREAD)) 23627b25dccaSJustin Hibbits pmc_config->pm_caps |= (PMC_CAP_USER | PMC_CAP_SYSTEM); 23637b25dccaSJustin Hibbits else 23647b25dccaSJustin Hibbits return (-1); 23657b25dccaSJustin Hibbits } 23667b25dccaSJustin Hibbits 23677b25dccaSJustin Hibbits return (0); 23687b25dccaSJustin Hibbits } 23697b25dccaSJustin Hibbits #endif /* __powerpc__ */ 23707b25dccaSJustin Hibbits 2371660df75eSGeorge V. Neville-Neil 2372789140c0SJoseph Koshy /* 2373789140c0SJoseph Koshy * Match an event name `name' with its canonical form. 2374789140c0SJoseph Koshy * 23750cfab8ddSJoseph Koshy * Matches are case insensitive and spaces, periods, underscores and 23760cfab8ddSJoseph Koshy * hyphen characters are considered to match each other. 2377789140c0SJoseph Koshy * 2378789140c0SJoseph Koshy * Returns 1 for a match, 0 otherwise. 2379789140c0SJoseph Koshy */ 2380789140c0SJoseph Koshy 2381789140c0SJoseph Koshy static int 2382789140c0SJoseph Koshy pmc_match_event_name(const char *name, const char *canonicalname) 2383789140c0SJoseph Koshy { 2384789140c0SJoseph Koshy int cc, nc; 2385789140c0SJoseph Koshy const unsigned char *c, *n; 2386789140c0SJoseph Koshy 2387789140c0SJoseph Koshy c = (const unsigned char *) canonicalname; 2388789140c0SJoseph Koshy n = (const unsigned char *) name; 2389789140c0SJoseph Koshy 2390789140c0SJoseph Koshy for (; (nc = *n) && (cc = *c); n++, c++) { 2391789140c0SJoseph Koshy 23920cfab8ddSJoseph Koshy if ((nc == ' ' || nc == '_' || nc == '-' || nc == '.') && 23930cfab8ddSJoseph Koshy (cc == ' ' || cc == '_' || cc == '-' || cc == '.')) 2394789140c0SJoseph Koshy continue; 2395789140c0SJoseph Koshy 23960cfab8ddSJoseph Koshy if (toupper(nc) == toupper(cc)) 2397789140c0SJoseph Koshy continue; 2398789140c0SJoseph Koshy 23990cfab8ddSJoseph Koshy 2400789140c0SJoseph Koshy return (0); 2401789140c0SJoseph Koshy } 2402789140c0SJoseph Koshy 2403789140c0SJoseph Koshy if (*n == '\0' && *c == '\0') 2404789140c0SJoseph Koshy return (1); 2405789140c0SJoseph Koshy 2406789140c0SJoseph Koshy return (0); 2407789140c0SJoseph Koshy } 2408789140c0SJoseph Koshy 2409789140c0SJoseph Koshy /* 2410789140c0SJoseph Koshy * Match an event name against all the event named supported by a 2411789140c0SJoseph Koshy * PMC class. 2412789140c0SJoseph Koshy * 2413789140c0SJoseph Koshy * Returns an event descriptor pointer on match or NULL otherwise. 2414789140c0SJoseph Koshy */ 2415789140c0SJoseph Koshy static const struct pmc_event_descr * 2416789140c0SJoseph Koshy pmc_match_event_class(const char *name, 2417789140c0SJoseph Koshy const struct pmc_class_descr *pcd) 2418789140c0SJoseph Koshy { 2419789140c0SJoseph Koshy size_t n; 2420789140c0SJoseph Koshy const struct pmc_event_descr *ev; 2421789140c0SJoseph Koshy 2422789140c0SJoseph Koshy ev = pcd->pm_evc_event_table; 2423789140c0SJoseph Koshy for (n = 0; n < pcd->pm_evc_event_table_size; n++, ev++) 2424789140c0SJoseph Koshy if (pmc_match_event_name(name, ev->pm_ev_name)) 2425789140c0SJoseph Koshy return (ev); 2426789140c0SJoseph Koshy 2427789140c0SJoseph Koshy return (NULL); 2428789140c0SJoseph Koshy } 2429789140c0SJoseph Koshy 2430789140c0SJoseph Koshy static int 2431789140c0SJoseph Koshy pmc_mdep_is_compatible_class(enum pmc_class pc) 2432789140c0SJoseph Koshy { 2433789140c0SJoseph Koshy size_t n; 2434789140c0SJoseph Koshy 2435789140c0SJoseph Koshy for (n = 0; n < pmc_mdep_class_list_size; n++) 2436789140c0SJoseph Koshy if (pmc_mdep_class_list[n] == pc) 2437789140c0SJoseph Koshy return (1); 2438789140c0SJoseph Koshy return (0); 2439789140c0SJoseph Koshy } 2440789140c0SJoseph Koshy 2441ebccf1e3SJoseph Koshy /* 2442ebccf1e3SJoseph Koshy * API entry points 2443ebccf1e3SJoseph Koshy */ 2444ebccf1e3SJoseph Koshy 2445ebccf1e3SJoseph Koshy int 2446ebccf1e3SJoseph Koshy pmc_allocate(const char *ctrspec, enum pmc_mode mode, 2447ebccf1e3SJoseph Koshy uint32_t flags, int cpu, pmc_id_t *pmcid) 2448ebccf1e3SJoseph Koshy { 2449789140c0SJoseph Koshy size_t n; 2450ebccf1e3SJoseph Koshy int retval; 2451ebccf1e3SJoseph Koshy char *r, *spec_copy; 2452ebccf1e3SJoseph Koshy const char *ctrname; 2453789140c0SJoseph Koshy const struct pmc_event_descr *ev; 2454789140c0SJoseph Koshy const struct pmc_event_alias *alias; 2455ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate pmc_config; 2456789140c0SJoseph Koshy const struct pmc_class_descr *pcd; 2457ebccf1e3SJoseph Koshy 2458ebccf1e3SJoseph Koshy spec_copy = NULL; 2459ebccf1e3SJoseph Koshy retval = -1; 2460ebccf1e3SJoseph Koshy 2461ebccf1e3SJoseph Koshy if (mode != PMC_MODE_SS && mode != PMC_MODE_TS && 2462ebccf1e3SJoseph Koshy mode != PMC_MODE_SC && mode != PMC_MODE_TC) { 2463ebccf1e3SJoseph Koshy errno = EINVAL; 2464ebccf1e3SJoseph Koshy goto out; 2465ebccf1e3SJoseph Koshy } 2466ebccf1e3SJoseph Koshy 2467ebccf1e3SJoseph Koshy /* replace an event alias with the canonical event specifier */ 2468ebccf1e3SJoseph Koshy if (pmc_mdep_event_aliases) 2469789140c0SJoseph Koshy for (alias = pmc_mdep_event_aliases; alias->pm_alias; alias++) 2470789140c0SJoseph Koshy if (!strcasecmp(ctrspec, alias->pm_alias)) { 2471789140c0SJoseph Koshy spec_copy = strdup(alias->pm_spec); 2472ebccf1e3SJoseph Koshy break; 2473ebccf1e3SJoseph Koshy } 2474ebccf1e3SJoseph Koshy 2475ebccf1e3SJoseph Koshy if (spec_copy == NULL) 2476ebccf1e3SJoseph Koshy spec_copy = strdup(ctrspec); 2477ebccf1e3SJoseph Koshy 2478ebccf1e3SJoseph Koshy r = spec_copy; 2479ebccf1e3SJoseph Koshy ctrname = strsep(&r, ","); 2480ebccf1e3SJoseph Koshy 2481789140c0SJoseph Koshy /* 2482789140c0SJoseph Koshy * If a explicit class prefix was given by the user, restrict the 2483789140c0SJoseph Koshy * search for the event to the specified PMC class. 2484789140c0SJoseph Koshy */ 2485789140c0SJoseph Koshy ev = NULL; 24860cfab8ddSJoseph Koshy for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) { 24870cfab8ddSJoseph Koshy pcd = pmc_class_table[n]; 2488789140c0SJoseph Koshy if (pmc_mdep_is_compatible_class(pcd->pm_evc_class) && 2489789140c0SJoseph Koshy strncasecmp(ctrname, pcd->pm_evc_name, 2490789140c0SJoseph Koshy pcd->pm_evc_name_size) == 0) { 2491789140c0SJoseph Koshy if ((ev = pmc_match_event_class(ctrname + 2492789140c0SJoseph Koshy pcd->pm_evc_name_size, pcd)) == NULL) { 2493789140c0SJoseph Koshy errno = EINVAL; 2494789140c0SJoseph Koshy goto out; 2495789140c0SJoseph Koshy } 2496ebccf1e3SJoseph Koshy break; 2497789140c0SJoseph Koshy } 2498789140c0SJoseph Koshy } 2499ebccf1e3SJoseph Koshy 2500789140c0SJoseph Koshy /* 2501789140c0SJoseph Koshy * Otherwise, search for this event in all compatible PMC 2502789140c0SJoseph Koshy * classes. 2503789140c0SJoseph Koshy */ 25040cfab8ddSJoseph Koshy for (n = 0; ev == NULL && n < PMC_CLASS_TABLE_SIZE; n++) { 25050cfab8ddSJoseph Koshy pcd = pmc_class_table[n]; 2506789140c0SJoseph Koshy if (pmc_mdep_is_compatible_class(pcd->pm_evc_class)) 2507789140c0SJoseph Koshy ev = pmc_match_event_class(ctrname, pcd); 2508789140c0SJoseph Koshy } 2509789140c0SJoseph Koshy 2510789140c0SJoseph Koshy if (ev == NULL) { 2511ebccf1e3SJoseph Koshy errno = EINVAL; 2512ebccf1e3SJoseph Koshy goto out; 2513ebccf1e3SJoseph Koshy } 2514ebccf1e3SJoseph Koshy 2515ebccf1e3SJoseph Koshy bzero(&pmc_config, sizeof(pmc_config)); 2516789140c0SJoseph Koshy pmc_config.pm_ev = ev->pm_ev_code; 2517789140c0SJoseph Koshy pmc_config.pm_class = pcd->pm_evc_class; 2518ebccf1e3SJoseph Koshy pmc_config.pm_cpu = cpu; 2519ebccf1e3SJoseph Koshy pmc_config.pm_mode = mode; 2520ebccf1e3SJoseph Koshy pmc_config.pm_flags = flags; 2521ebccf1e3SJoseph Koshy 2522ebccf1e3SJoseph Koshy if (PMC_IS_SAMPLING_MODE(mode)) 2523ebccf1e3SJoseph Koshy pmc_config.pm_caps |= PMC_CAP_INTERRUPT; 2524ebccf1e3SJoseph Koshy 2525789140c0SJoseph Koshy if (pcd->pm_evc_allocate_pmc(ev->pm_ev_code, r, &pmc_config) < 0) { 2526ebccf1e3SJoseph Koshy errno = EINVAL; 2527ebccf1e3SJoseph Koshy goto out; 2528ebccf1e3SJoseph Koshy } 2529ebccf1e3SJoseph Koshy 2530ebccf1e3SJoseph Koshy if (PMC_CALL(PMCALLOCATE, &pmc_config) < 0) 2531ebccf1e3SJoseph Koshy goto out; 2532ebccf1e3SJoseph Koshy 2533ebccf1e3SJoseph Koshy *pmcid = pmc_config.pm_pmcid; 2534ebccf1e3SJoseph Koshy 2535ebccf1e3SJoseph Koshy retval = 0; 2536ebccf1e3SJoseph Koshy 2537ebccf1e3SJoseph Koshy out: 2538ebccf1e3SJoseph Koshy if (spec_copy) 2539ebccf1e3SJoseph Koshy free(spec_copy); 2540ebccf1e3SJoseph Koshy 2541aa342b1fSJoseph Koshy return (retval); 2542ebccf1e3SJoseph Koshy } 2543ebccf1e3SJoseph Koshy 2544ebccf1e3SJoseph Koshy int 2545ebccf1e3SJoseph Koshy pmc_attach(pmc_id_t pmc, pid_t pid) 2546ebccf1e3SJoseph Koshy { 2547ebccf1e3SJoseph Koshy struct pmc_op_pmcattach pmc_attach_args; 2548ebccf1e3SJoseph Koshy 2549ebccf1e3SJoseph Koshy pmc_attach_args.pm_pmc = pmc; 2550ebccf1e3SJoseph Koshy pmc_attach_args.pm_pid = pid; 2551ebccf1e3SJoseph Koshy 2552aa342b1fSJoseph Koshy return (PMC_CALL(PMCATTACH, &pmc_attach_args)); 2553ebccf1e3SJoseph Koshy } 2554ebccf1e3SJoseph Koshy 2555ebccf1e3SJoseph Koshy int 2556c5153e19SJoseph Koshy pmc_capabilities(pmc_id_t pmcid, uint32_t *caps) 2557c5153e19SJoseph Koshy { 2558c5153e19SJoseph Koshy unsigned int i; 2559c5153e19SJoseph Koshy enum pmc_class cl; 2560c5153e19SJoseph Koshy 2561c5153e19SJoseph Koshy cl = PMC_ID_TO_CLASS(pmcid); 2562c5153e19SJoseph Koshy for (i = 0; i < cpu_info.pm_nclass; i++) 2563c5153e19SJoseph Koshy if (cpu_info.pm_classes[i].pm_class == cl) { 2564c5153e19SJoseph Koshy *caps = cpu_info.pm_classes[i].pm_caps; 2565aa342b1fSJoseph Koshy return (0); 2566c5153e19SJoseph Koshy } 2567484202faSJoseph Koshy errno = EINVAL; 2568484202faSJoseph Koshy return (-1); 2569c5153e19SJoseph Koshy } 2570c5153e19SJoseph Koshy 2571f263522aSJoseph Koshy int 2572f263522aSJoseph Koshy pmc_configure_logfile(int fd) 2573ebccf1e3SJoseph Koshy { 2574f263522aSJoseph Koshy struct pmc_op_configurelog cla; 2575f263522aSJoseph Koshy 2576f263522aSJoseph Koshy cla.pm_logfd = fd; 2577f263522aSJoseph Koshy if (PMC_CALL(CONFIGURELOG, &cla) < 0) 2578aa342b1fSJoseph Koshy return (-1); 2579aa342b1fSJoseph Koshy return (0); 2580ebccf1e3SJoseph Koshy } 2581ebccf1e3SJoseph Koshy 2582f263522aSJoseph Koshy int 2583f263522aSJoseph Koshy pmc_cpuinfo(const struct pmc_cpuinfo **pci) 2584ebccf1e3SJoseph Koshy { 2585f263522aSJoseph Koshy if (pmc_syscall == -1) { 2586f263522aSJoseph Koshy errno = ENXIO; 2587aa342b1fSJoseph Koshy return (-1); 2588ebccf1e3SJoseph Koshy } 2589ebccf1e3SJoseph Koshy 25901455fcd3SJoseph Koshy *pci = &cpu_info; 2591aa342b1fSJoseph Koshy return (0); 2592ebccf1e3SJoseph Koshy } 2593ebccf1e3SJoseph Koshy 2594f263522aSJoseph Koshy int 2595f263522aSJoseph Koshy pmc_detach(pmc_id_t pmc, pid_t pid) 2596ebccf1e3SJoseph Koshy { 2597f263522aSJoseph Koshy struct pmc_op_pmcattach pmc_detach_args; 2598ebccf1e3SJoseph Koshy 2599f263522aSJoseph Koshy pmc_detach_args.pm_pmc = pmc; 2600f263522aSJoseph Koshy pmc_detach_args.pm_pid = pid; 2601aa342b1fSJoseph Koshy return (PMC_CALL(PMCDETACH, &pmc_detach_args)); 2602ebccf1e3SJoseph Koshy } 2603ebccf1e3SJoseph Koshy 2604f263522aSJoseph Koshy int 2605f263522aSJoseph Koshy pmc_disable(int cpu, int pmc) 2606ebccf1e3SJoseph Koshy { 2607f263522aSJoseph Koshy struct pmc_op_pmcadmin ssa; 2608ebccf1e3SJoseph Koshy 2609f263522aSJoseph Koshy ssa.pm_cpu = cpu; 2610f263522aSJoseph Koshy ssa.pm_pmc = pmc; 2611f263522aSJoseph Koshy ssa.pm_state = PMC_STATE_DISABLED; 2612aa342b1fSJoseph Koshy return (PMC_CALL(PMCADMIN, &ssa)); 2613ebccf1e3SJoseph Koshy } 2614ebccf1e3SJoseph Koshy 2615f263522aSJoseph Koshy int 2616f263522aSJoseph Koshy pmc_enable(int cpu, int pmc) 2617ebccf1e3SJoseph Koshy { 2618f263522aSJoseph Koshy struct pmc_op_pmcadmin ssa; 2619ebccf1e3SJoseph Koshy 2620f263522aSJoseph Koshy ssa.pm_cpu = cpu; 2621f263522aSJoseph Koshy ssa.pm_pmc = pmc; 2622f263522aSJoseph Koshy ssa.pm_state = PMC_STATE_FREE; 2623aa342b1fSJoseph Koshy return (PMC_CALL(PMCADMIN, &ssa)); 2624ebccf1e3SJoseph Koshy } 2625ebccf1e3SJoseph Koshy 2626ebccf1e3SJoseph Koshy /* 2627ebccf1e3SJoseph Koshy * Return a list of events known to a given PMC class. 'cl' is the 2628ebccf1e3SJoseph Koshy * PMC class identifier, 'eventnames' is the returned list of 'const 2629ebccf1e3SJoseph Koshy * char *' pointers pointing to the names of the events. 'nevents' is 2630ebccf1e3SJoseph Koshy * the number of event name pointers returned. 2631ebccf1e3SJoseph Koshy * 2632ebccf1e3SJoseph Koshy * The space for 'eventnames' is allocated using malloc(3). The caller 2633ebccf1e3SJoseph Koshy * is responsible for freeing this space when done. 2634ebccf1e3SJoseph Koshy */ 2635ebccf1e3SJoseph Koshy int 2636ebccf1e3SJoseph Koshy pmc_event_names_of_class(enum pmc_class cl, const char ***eventnames, 2637ebccf1e3SJoseph Koshy int *nevents) 2638ebccf1e3SJoseph Koshy { 2639ebccf1e3SJoseph Koshy int count; 2640ebccf1e3SJoseph Koshy const char **names; 2641ebccf1e3SJoseph Koshy const struct pmc_event_descr *ev; 2642ebccf1e3SJoseph Koshy 2643ebccf1e3SJoseph Koshy switch (cl) 2644ebccf1e3SJoseph Koshy { 26450cfab8ddSJoseph Koshy case PMC_CLASS_IAF: 26460cfab8ddSJoseph Koshy ev = iaf_event_table; 26470cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(iaf); 26480cfab8ddSJoseph Koshy break; 26490cfab8ddSJoseph Koshy case PMC_CLASS_IAP: 26500cfab8ddSJoseph Koshy /* 26510cfab8ddSJoseph Koshy * Return the most appropriate set of event name 26520cfab8ddSJoseph Koshy * spellings for the current CPU. 26530cfab8ddSJoseph Koshy */ 26540cfab8ddSJoseph Koshy switch (cpu_info.pm_cputype) { 26550cfab8ddSJoseph Koshy default: 26560cfab8ddSJoseph Koshy case PMC_CPU_INTEL_ATOM: 26570cfab8ddSJoseph Koshy ev = atom_event_table; 26580cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(atom); 26590cfab8ddSJoseph Koshy break; 26600cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE: 26610cfab8ddSJoseph Koshy ev = core_event_table; 26620cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(core); 26630cfab8ddSJoseph Koshy break; 26640cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE2: 2665b4d091f3SJoseph Koshy case PMC_CPU_INTEL_CORE2EXTREME: 26660cfab8ddSJoseph Koshy ev = core2_event_table; 26670cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(core2); 26680cfab8ddSJoseph Koshy break; 2669597979c4SJeff Roberson case PMC_CPU_INTEL_COREI7: 2670597979c4SJeff Roberson ev = corei7_event_table; 2671597979c4SJeff Roberson count = PMC_EVENT_TABLE_SIZE(corei7); 2672597979c4SJeff Roberson break; 2673*1e862e5aSFabien Thomas case PMC_CPU_INTEL_IVYBRIDGE: 2674*1e862e5aSFabien Thomas ev = ivybridge_event_table; 2675*1e862e5aSFabien Thomas count = PMC_EVENT_TABLE_SIZE(ivybridge); 2676*1e862e5aSFabien Thomas break; 267778d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 267878d763a2SDavide Italiano ev = sandybridge_event_table; 267978d763a2SDavide Italiano count = PMC_EVENT_TABLE_SIZE(sandybridge); 268078d763a2SDavide Italiano break; 26811fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 26821fa7f10bSFabien Thomas ev = westmere_event_table; 26831fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(westmere); 26841fa7f10bSFabien Thomas break; 26851fa7f10bSFabien Thomas } 26861fa7f10bSFabien Thomas break; 26871fa7f10bSFabien Thomas case PMC_CLASS_UCF: 26881fa7f10bSFabien Thomas ev = ucf_event_table; 26891fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(ucf); 26901fa7f10bSFabien Thomas break; 26911fa7f10bSFabien Thomas case PMC_CLASS_UCP: 26921fa7f10bSFabien Thomas /* 26931fa7f10bSFabien Thomas * Return the most appropriate set of event name 26941fa7f10bSFabien Thomas * spellings for the current CPU. 26951fa7f10bSFabien Thomas */ 26961fa7f10bSFabien Thomas switch (cpu_info.pm_cputype) { 26971fa7f10bSFabien Thomas default: 26981fa7f10bSFabien Thomas case PMC_CPU_INTEL_COREI7: 26991fa7f10bSFabien Thomas ev = corei7uc_event_table; 27001fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(corei7uc); 27011fa7f10bSFabien Thomas break; 270278d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 270378d763a2SDavide Italiano ev = sandybridgeuc_event_table; 270478d763a2SDavide Italiano count = PMC_EVENT_TABLE_SIZE(sandybridgeuc); 270578d763a2SDavide Italiano break; 27061fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 27071fa7f10bSFabien Thomas ev = westmereuc_event_table; 27081fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(westmereuc); 27091fa7f10bSFabien Thomas break; 27100cfab8ddSJoseph Koshy } 27110cfab8ddSJoseph Koshy break; 2712ebccf1e3SJoseph Koshy case PMC_CLASS_TSC: 2713789140c0SJoseph Koshy ev = tsc_event_table; 2714789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(tsc); 2715ebccf1e3SJoseph Koshy break; 2716ebccf1e3SJoseph Koshy case PMC_CLASS_K7: 2717789140c0SJoseph Koshy ev = k7_event_table; 2718789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(k7); 2719ebccf1e3SJoseph Koshy break; 2720ebccf1e3SJoseph Koshy case PMC_CLASS_K8: 2721789140c0SJoseph Koshy ev = k8_event_table; 2722789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(k8); 2723ebccf1e3SJoseph Koshy break; 2724ebccf1e3SJoseph Koshy case PMC_CLASS_P4: 2725789140c0SJoseph Koshy ev = p4_event_table; 2726789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p4); 2727789140c0SJoseph Koshy break; 2728789140c0SJoseph Koshy case PMC_CLASS_P5: 2729789140c0SJoseph Koshy ev = p5_event_table; 2730789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p5); 2731789140c0SJoseph Koshy break; 2732789140c0SJoseph Koshy case PMC_CLASS_P6: 2733789140c0SJoseph Koshy ev = p6_event_table; 2734789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p6); 2735ebccf1e3SJoseph Koshy break; 27360ce207d2SRui Paulo case PMC_CLASS_XSCALE: 27370ce207d2SRui Paulo ev = xscale_event_table; 27380ce207d2SRui Paulo count = PMC_EVENT_TABLE_SIZE(xscale); 27390ce207d2SRui Paulo break; 2740660df75eSGeorge V. Neville-Neil case PMC_CLASS_MIPS24K: 2741660df75eSGeorge V. Neville-Neil ev = mips24k_event_table; 2742660df75eSGeorge V. Neville-Neil count = PMC_EVENT_TABLE_SIZE(mips24k); 2743660df75eSGeorge V. Neville-Neil break; 2744c2657f80SOleksandr Tymoshenko case PMC_CLASS_OCTEON: 2745c2657f80SOleksandr Tymoshenko ev = octeon_event_table; 2746c2657f80SOleksandr Tymoshenko count = PMC_EVENT_TABLE_SIZE(octeon); 2747c2657f80SOleksandr Tymoshenko break; 27487b25dccaSJustin Hibbits case PMC_CLASS_PPC7450: 27497b25dccaSJustin Hibbits ev = ppc7450_event_table; 27507b25dccaSJustin Hibbits count = PMC_EVENT_TABLE_SIZE(ppc7450); 27517b25dccaSJustin Hibbits break; 2752f5f9340bSFabien Thomas case PMC_CLASS_SOFT: 2753f5f9340bSFabien Thomas ev = soft_event_table; 2754f5f9340bSFabien Thomas count = soft_event_info.pm_nevent; 2755f5f9340bSFabien Thomas break; 2756ebccf1e3SJoseph Koshy default: 2757ebccf1e3SJoseph Koshy errno = EINVAL; 2758aa342b1fSJoseph Koshy return (-1); 2759ebccf1e3SJoseph Koshy } 2760ebccf1e3SJoseph Koshy 2761ebccf1e3SJoseph Koshy if ((names = malloc(count * sizeof(const char *))) == NULL) 2762aa342b1fSJoseph Koshy return (-1); 2763ebccf1e3SJoseph Koshy 2764ebccf1e3SJoseph Koshy *eventnames = names; 2765ebccf1e3SJoseph Koshy *nevents = count; 2766ebccf1e3SJoseph Koshy 2767ebccf1e3SJoseph Koshy for (;count--; ev++, names++) 2768ebccf1e3SJoseph Koshy *names = ev->pm_ev_name; 2769f5f9340bSFabien Thomas 2770aa342b1fSJoseph Koshy return (0); 2771ebccf1e3SJoseph Koshy } 2772ebccf1e3SJoseph Koshy 2773f263522aSJoseph Koshy int 2774f263522aSJoseph Koshy pmc_flush_logfile(void) 2775f263522aSJoseph Koshy { 2776aa342b1fSJoseph Koshy return (PMC_CALL(FLUSHLOG,0)); 2777f263522aSJoseph Koshy } 2778ebccf1e3SJoseph Koshy 2779ebccf1e3SJoseph Koshy int 2780dceed24aSFabien Thomas pmc_close_logfile(void) 2781dceed24aSFabien Thomas { 2782dceed24aSFabien Thomas return (PMC_CALL(CLOSELOG,0)); 2783dceed24aSFabien Thomas } 2784dceed24aSFabien Thomas 2785dceed24aSFabien Thomas int 2786f263522aSJoseph Koshy pmc_get_driver_stats(struct pmc_driverstats *ds) 2787ebccf1e3SJoseph Koshy { 2788f263522aSJoseph Koshy struct pmc_op_getdriverstats gms; 2789f263522aSJoseph Koshy 2790f263522aSJoseph Koshy if (PMC_CALL(GETDRIVERSTATS, &gms) < 0) 2791aa342b1fSJoseph Koshy return (-1); 2792f263522aSJoseph Koshy 2793f263522aSJoseph Koshy /* copy out fields in the current userland<->library interface */ 2794f263522aSJoseph Koshy ds->pm_intr_ignored = gms.pm_intr_ignored; 2795f263522aSJoseph Koshy ds->pm_intr_processed = gms.pm_intr_processed; 2796f263522aSJoseph Koshy ds->pm_intr_bufferfull = gms.pm_intr_bufferfull; 2797f263522aSJoseph Koshy ds->pm_syscalls = gms.pm_syscalls; 2798f263522aSJoseph Koshy ds->pm_syscall_errors = gms.pm_syscall_errors; 2799f263522aSJoseph Koshy ds->pm_buffer_requests = gms.pm_buffer_requests; 2800f263522aSJoseph Koshy ds->pm_buffer_requests_failed = gms.pm_buffer_requests_failed; 2801f263522aSJoseph Koshy ds->pm_log_sweeps = gms.pm_log_sweeps; 2802aa342b1fSJoseph Koshy return (0); 2803f263522aSJoseph Koshy } 2804f263522aSJoseph Koshy 2805f263522aSJoseph Koshy int 2806f263522aSJoseph Koshy pmc_get_msr(pmc_id_t pmc, uint32_t *msr) 2807f263522aSJoseph Koshy { 2808f263522aSJoseph Koshy struct pmc_op_getmsr gm; 2809ebccf1e3SJoseph Koshy 2810ebccf1e3SJoseph Koshy gm.pm_pmcid = pmc; 2811f263522aSJoseph Koshy if (PMC_CALL(PMCGETMSR, &gm) < 0) 2812aa342b1fSJoseph Koshy return (-1); 2813ebccf1e3SJoseph Koshy *msr = gm.pm_msr; 2814aa342b1fSJoseph Koshy return (0); 2815ebccf1e3SJoseph Koshy } 2816ebccf1e3SJoseph Koshy 2817f263522aSJoseph Koshy int 2818f263522aSJoseph Koshy pmc_init(void) 2819f263522aSJoseph Koshy { 2820f263522aSJoseph Koshy int error, pmc_mod_id; 28211455fcd3SJoseph Koshy unsigned int n; 2822f263522aSJoseph Koshy uint32_t abi_version; 2823f263522aSJoseph Koshy struct module_stat pmc_modstat; 28241455fcd3SJoseph Koshy struct pmc_op_getcpuinfo op_cpu_info; 2825791f5d5bSJoseph Koshy #if defined(__amd64__) || defined(__i386__) 2826791f5d5bSJoseph Koshy int cpu_has_iaf_counters; 2827791f5d5bSJoseph Koshy unsigned int t; 2828791f5d5bSJoseph Koshy #endif 2829f263522aSJoseph Koshy 2830f263522aSJoseph Koshy if (pmc_syscall != -1) /* already inited */ 2831aa342b1fSJoseph Koshy return (0); 2832f263522aSJoseph Koshy 2833f263522aSJoseph Koshy /* retrieve the system call number from the KLD */ 2834f263522aSJoseph Koshy if ((pmc_mod_id = modfind(PMC_MODULE_NAME)) < 0) 2835aa342b1fSJoseph Koshy return (-1); 2836f263522aSJoseph Koshy 2837f263522aSJoseph Koshy pmc_modstat.version = sizeof(struct module_stat); 2838f263522aSJoseph Koshy if ((error = modstat(pmc_mod_id, &pmc_modstat)) < 0) 2839aa342b1fSJoseph Koshy return (-1); 2840f263522aSJoseph Koshy 2841f263522aSJoseph Koshy pmc_syscall = pmc_modstat.data.intval; 2842f263522aSJoseph Koshy 2843f263522aSJoseph Koshy /* check the kernel module's ABI against our compiled-in version */ 2844f263522aSJoseph Koshy abi_version = PMC_VERSION; 2845f263522aSJoseph Koshy if (PMC_CALL(GETMODULEVERSION, &abi_version) < 0) 2846f263522aSJoseph Koshy return (pmc_syscall = -1); 2847f263522aSJoseph Koshy 2848f263522aSJoseph Koshy /* ignore patch & minor numbers for the comparision */ 2849f263522aSJoseph Koshy if ((abi_version & 0xFF000000) != (PMC_VERSION & 0xFF000000)) { 2850f263522aSJoseph Koshy errno = EPROGMISMATCH; 2851f263522aSJoseph Koshy return (pmc_syscall = -1); 2852f263522aSJoseph Koshy } 2853f263522aSJoseph Koshy 28541455fcd3SJoseph Koshy if (PMC_CALL(GETCPUINFO, &op_cpu_info) < 0) 2855f263522aSJoseph Koshy return (pmc_syscall = -1); 2856f263522aSJoseph Koshy 28571455fcd3SJoseph Koshy cpu_info.pm_cputype = op_cpu_info.pm_cputype; 28581455fcd3SJoseph Koshy cpu_info.pm_ncpu = op_cpu_info.pm_ncpu; 28591455fcd3SJoseph Koshy cpu_info.pm_npmc = op_cpu_info.pm_npmc; 28601455fcd3SJoseph Koshy cpu_info.pm_nclass = op_cpu_info.pm_nclass; 28611455fcd3SJoseph Koshy for (n = 0; n < cpu_info.pm_nclass; n++) 28621455fcd3SJoseph Koshy cpu_info.pm_classes[n] = op_cpu_info.pm_classes[n]; 28631455fcd3SJoseph Koshy 28640cfab8ddSJoseph Koshy pmc_class_table = malloc(PMC_CLASS_TABLE_SIZE * 28650cfab8ddSJoseph Koshy sizeof(struct pmc_class_descr *)); 28660cfab8ddSJoseph Koshy 28670cfab8ddSJoseph Koshy if (pmc_class_table == NULL) 28680cfab8ddSJoseph Koshy return (-1); 28690cfab8ddSJoseph Koshy 2870791f5d5bSJoseph Koshy for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) 2871791f5d5bSJoseph Koshy pmc_class_table[n] = NULL; 28720cfab8ddSJoseph Koshy 28730cfab8ddSJoseph Koshy /* 2874f5f9340bSFabien Thomas * Get soft events list. 2875f5f9340bSFabien Thomas */ 2876f5f9340bSFabien Thomas soft_event_info.pm_class = PMC_CLASS_SOFT; 2877f5f9340bSFabien Thomas if (PMC_CALL(GETDYNEVENTINFO, &soft_event_info) < 0) 2878f5f9340bSFabien Thomas return (pmc_syscall = -1); 2879f5f9340bSFabien Thomas 2880f5f9340bSFabien Thomas /* Map soft events to static list. */ 2881f5f9340bSFabien Thomas for (n = 0; n < soft_event_info.pm_nevent; n++) { 2882f5f9340bSFabien Thomas soft_event_table[n].pm_ev_name = 2883f5f9340bSFabien Thomas soft_event_info.pm_events[n].pm_ev_name; 2884f5f9340bSFabien Thomas soft_event_table[n].pm_ev_code = 2885f5f9340bSFabien Thomas soft_event_info.pm_events[n].pm_ev_code; 2886f5f9340bSFabien Thomas } 2887f5f9340bSFabien Thomas soft_class_table_descr.pm_evc_event_table_size = \ 2888f5f9340bSFabien Thomas soft_event_info.pm_nevent; 2889f5f9340bSFabien Thomas soft_class_table_descr.pm_evc_event_table = \ 2890f5f9340bSFabien Thomas soft_event_table; 2891f5f9340bSFabien Thomas 2892f5f9340bSFabien Thomas /* 28930cfab8ddSJoseph Koshy * Fill in the class table. 28940cfab8ddSJoseph Koshy */ 28950cfab8ddSJoseph Koshy n = 0; 2896f5f9340bSFabien Thomas 2897f5f9340bSFabien Thomas /* Fill soft events information. */ 2898f5f9340bSFabien Thomas pmc_class_table[n++] = &soft_class_table_descr; 28990cfab8ddSJoseph Koshy #if defined(__amd64__) || defined(__i386__) 2900f5f9340bSFabien Thomas if (cpu_info.pm_cputype != PMC_CPU_GENERIC) 29010cfab8ddSJoseph Koshy pmc_class_table[n++] = &tsc_class_table_descr; 2902791f5d5bSJoseph Koshy 2903791f5d5bSJoseph Koshy /* 2904791f5d5bSJoseph Koshy * Check if this CPU has fixed function counters. 2905791f5d5bSJoseph Koshy */ 2906791f5d5bSJoseph Koshy cpu_has_iaf_counters = 0; 2907791f5d5bSJoseph Koshy for (t = 0; t < cpu_info.pm_nclass; t++) 29082aef9dd6SFabien Thomas if (cpu_info.pm_classes[t].pm_class == PMC_CLASS_IAF && 29092aef9dd6SFabien Thomas cpu_info.pm_classes[t].pm_num > 0) 2910791f5d5bSJoseph Koshy cpu_has_iaf_counters = 1; 29110cfab8ddSJoseph Koshy #endif 29120cfab8ddSJoseph Koshy 2913789140c0SJoseph Koshy #define PMC_MDEP_INIT(C) do { \ 2914789140c0SJoseph Koshy pmc_mdep_event_aliases = C##_aliases; \ 2915789140c0SJoseph Koshy pmc_mdep_class_list = C##_pmc_classes; \ 2916789140c0SJoseph Koshy pmc_mdep_class_list_size = \ 2917789140c0SJoseph Koshy PMC_TABLE_SIZE(C##_pmc_classes); \ 2918789140c0SJoseph Koshy } while (0) 2919789140c0SJoseph Koshy 2920791f5d5bSJoseph Koshy #define PMC_MDEP_INIT_INTEL_V2(C) do { \ 2921791f5d5bSJoseph Koshy PMC_MDEP_INIT(C); \ 2922791f5d5bSJoseph Koshy pmc_class_table[n++] = &iaf_class_table_descr; \ 29232aef9dd6SFabien Thomas if (!cpu_has_iaf_counters) \ 2924791f5d5bSJoseph Koshy pmc_mdep_event_aliases = \ 2925791f5d5bSJoseph Koshy C##_aliases_without_iaf; \ 2926791f5d5bSJoseph Koshy pmc_class_table[n] = &C##_class_table_descr; \ 2927791f5d5bSJoseph Koshy } while (0) 2928791f5d5bSJoseph Koshy 2929789140c0SJoseph Koshy /* Configure the event name parser. */ 2930f263522aSJoseph Koshy switch (cpu_info.pm_cputype) { 2931f263522aSJoseph Koshy #if defined(__i386__) 2932f263522aSJoseph Koshy case PMC_CPU_AMD_K7: 2933789140c0SJoseph Koshy PMC_MDEP_INIT(k7); 29340cfab8ddSJoseph Koshy pmc_class_table[n] = &k7_class_table_descr; 2935f263522aSJoseph Koshy break; 2936f263522aSJoseph Koshy case PMC_CPU_INTEL_P5: 2937789140c0SJoseph Koshy PMC_MDEP_INIT(p5); 29380cfab8ddSJoseph Koshy pmc_class_table[n] = &p5_class_table_descr; 2939f263522aSJoseph Koshy break; 2940f263522aSJoseph Koshy case PMC_CPU_INTEL_P6: /* P6 ... Pentium M CPUs have */ 2941f263522aSJoseph Koshy case PMC_CPU_INTEL_PII: /* similar PMCs. */ 2942f263522aSJoseph Koshy case PMC_CPU_INTEL_PIII: 2943f263522aSJoseph Koshy case PMC_CPU_INTEL_PM: 2944789140c0SJoseph Koshy PMC_MDEP_INIT(p6); 29450cfab8ddSJoseph Koshy pmc_class_table[n] = &p6_class_table_descr; 2946f263522aSJoseph Koshy break; 294786a65549SJoseph Koshy #endif 294886a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 2949f263522aSJoseph Koshy case PMC_CPU_AMD_K8: 2950789140c0SJoseph Koshy PMC_MDEP_INIT(k8); 29510cfab8ddSJoseph Koshy pmc_class_table[n] = &k8_class_table_descr; 29520cfab8ddSJoseph Koshy break; 29530cfab8ddSJoseph Koshy case PMC_CPU_INTEL_ATOM: 2954791f5d5bSJoseph Koshy PMC_MDEP_INIT_INTEL_V2(atom); 29550cfab8ddSJoseph Koshy break; 29560cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE: 29570cfab8ddSJoseph Koshy PMC_MDEP_INIT(core); 2958bc315bbdSJoseph Koshy pmc_class_table[n] = &core_class_table_descr; 29590cfab8ddSJoseph Koshy break; 29600cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE2: 2961b4d091f3SJoseph Koshy case PMC_CPU_INTEL_CORE2EXTREME: 2962791f5d5bSJoseph Koshy PMC_MDEP_INIT_INTEL_V2(core2); 2963789140c0SJoseph Koshy break; 2964597979c4SJeff Roberson case PMC_CPU_INTEL_COREI7: 29651fa7f10bSFabien Thomas pmc_class_table[n++] = &ucf_class_table_descr; 29661fa7f10bSFabien Thomas pmc_class_table[n++] = &corei7uc_class_table_descr; 2967791f5d5bSJoseph Koshy PMC_MDEP_INIT_INTEL_V2(corei7); 2968597979c4SJeff Roberson break; 2969*1e862e5aSFabien Thomas case PMC_CPU_INTEL_IVYBRIDGE: 2970*1e862e5aSFabien Thomas PMC_MDEP_INIT_INTEL_V2(ivybridge); 2971*1e862e5aSFabien Thomas break; 297278d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 297378d763a2SDavide Italiano pmc_class_table[n++] = &ucf_class_table_descr; 297478d763a2SDavide Italiano pmc_class_table[n++] = &sandybridgeuc_class_table_descr; 297578d763a2SDavide Italiano PMC_MDEP_INIT_INTEL_V2(sandybridge); 297678d763a2SDavide Italiano break; 29771fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 29781fa7f10bSFabien Thomas pmc_class_table[n++] = &ucf_class_table_descr; 29791fa7f10bSFabien Thomas pmc_class_table[n++] = &westmereuc_class_table_descr; 29801fa7f10bSFabien Thomas PMC_MDEP_INIT_INTEL_V2(westmere); 29811fa7f10bSFabien Thomas break; 2982789140c0SJoseph Koshy case PMC_CPU_INTEL_PIV: 2983789140c0SJoseph Koshy PMC_MDEP_INIT(p4); 29840cfab8ddSJoseph Koshy pmc_class_table[n] = &p4_class_table_descr; 2985f263522aSJoseph Koshy break; 2986ebccf1e3SJoseph Koshy #endif 2987f5f9340bSFabien Thomas case PMC_CPU_GENERIC: 2988f5f9340bSFabien Thomas PMC_MDEP_INIT(generic); 2989f5f9340bSFabien Thomas break; 29900ce207d2SRui Paulo #if defined(__XSCALE__) 29910ce207d2SRui Paulo case PMC_CPU_INTEL_XSCALE: 29920ce207d2SRui Paulo PMC_MDEP_INIT(xscale); 29930ce207d2SRui Paulo pmc_class_table[n] = &xscale_class_table_descr; 29940ce207d2SRui Paulo break; 29950ce207d2SRui Paulo #endif 2996660df75eSGeorge V. Neville-Neil #if defined(__mips__) 2997660df75eSGeorge V. Neville-Neil case PMC_CPU_MIPS_24K: 2998660df75eSGeorge V. Neville-Neil PMC_MDEP_INIT(mips24k); 2999660df75eSGeorge V. Neville-Neil pmc_class_table[n] = &mips24k_class_table_descr; 3000660df75eSGeorge V. Neville-Neil break; 3001c2657f80SOleksandr Tymoshenko case PMC_CPU_MIPS_OCTEON: 3002c2657f80SOleksandr Tymoshenko PMC_MDEP_INIT(octeon); 3003c2657f80SOleksandr Tymoshenko pmc_class_table[n] = &octeon_class_table_descr; 3004c2657f80SOleksandr Tymoshenko break; 3005660df75eSGeorge V. Neville-Neil #endif /* __mips__ */ 30067b25dccaSJustin Hibbits #if defined(__powerpc__) 30077b25dccaSJustin Hibbits case PMC_CPU_PPC_7450: 30087b25dccaSJustin Hibbits PMC_MDEP_INIT(ppc7450); 30097b25dccaSJustin Hibbits pmc_class_table[n] = &ppc7450_class_table_descr; 30107b25dccaSJustin Hibbits break; 30117b25dccaSJustin Hibbits #endif 3012f263522aSJoseph Koshy default: 3013f263522aSJoseph Koshy /* 3014f263522aSJoseph Koshy * Some kind of CPU this version of the library knows nothing 3015f263522aSJoseph Koshy * about. This shouldn't happen since the abi version check 3016f263522aSJoseph Koshy * should have caught this. 3017f263522aSJoseph Koshy */ 3018f263522aSJoseph Koshy errno = ENXIO; 3019f263522aSJoseph Koshy return (pmc_syscall = -1); 3020f263522aSJoseph Koshy } 3021f263522aSJoseph Koshy 3022aa342b1fSJoseph Koshy return (0); 3023f263522aSJoseph Koshy } 3024f263522aSJoseph Koshy 3025f263522aSJoseph Koshy const char * 3026f263522aSJoseph Koshy pmc_name_of_capability(enum pmc_caps cap) 3027f263522aSJoseph Koshy { 3028f263522aSJoseph Koshy int i; 3029f263522aSJoseph Koshy 3030f263522aSJoseph Koshy /* 3031f263522aSJoseph Koshy * 'cap' should have a single bit set and should be in 3032f263522aSJoseph Koshy * range. 3033f263522aSJoseph Koshy */ 3034f263522aSJoseph Koshy if ((cap & (cap - 1)) || cap < PMC_CAP_FIRST || 3035f263522aSJoseph Koshy cap > PMC_CAP_LAST) { 3036f263522aSJoseph Koshy errno = EINVAL; 3037aa342b1fSJoseph Koshy return (NULL); 3038f263522aSJoseph Koshy } 3039f263522aSJoseph Koshy 3040f263522aSJoseph Koshy i = ffs(cap); 3041aa342b1fSJoseph Koshy return (pmc_capability_names[i - 1]); 3042f263522aSJoseph Koshy } 3043f263522aSJoseph Koshy 3044f263522aSJoseph Koshy const char * 3045f263522aSJoseph Koshy pmc_name_of_class(enum pmc_class pc) 3046f263522aSJoseph Koshy { 3047f263522aSJoseph Koshy if ((int) pc >= PMC_CLASS_FIRST && 3048f263522aSJoseph Koshy pc <= PMC_CLASS_LAST) 3049aa342b1fSJoseph Koshy return (pmc_class_names[pc]); 3050f263522aSJoseph Koshy 3051f263522aSJoseph Koshy errno = EINVAL; 3052aa342b1fSJoseph Koshy return (NULL); 3053f263522aSJoseph Koshy } 3054f263522aSJoseph Koshy 3055f263522aSJoseph Koshy const char * 3056f263522aSJoseph Koshy pmc_name_of_cputype(enum pmc_cputype cp) 3057f263522aSJoseph Koshy { 3058789140c0SJoseph Koshy size_t n; 3059789140c0SJoseph Koshy 3060789140c0SJoseph Koshy for (n = 0; n < PMC_TABLE_SIZE(pmc_cputype_names); n++) 3061789140c0SJoseph Koshy if (cp == pmc_cputype_names[n].pm_cputype) 3062789140c0SJoseph Koshy return (pmc_cputype_names[n].pm_name); 3063789140c0SJoseph Koshy 3064f263522aSJoseph Koshy errno = EINVAL; 3065aa342b1fSJoseph Koshy return (NULL); 3066f263522aSJoseph Koshy } 3067f263522aSJoseph Koshy 3068f263522aSJoseph Koshy const char * 3069f263522aSJoseph Koshy pmc_name_of_disposition(enum pmc_disp pd) 3070f263522aSJoseph Koshy { 3071f263522aSJoseph Koshy if ((int) pd >= PMC_DISP_FIRST && 3072f263522aSJoseph Koshy pd <= PMC_DISP_LAST) 3073aa342b1fSJoseph Koshy return (pmc_disposition_names[pd]); 3074f263522aSJoseph Koshy 3075f263522aSJoseph Koshy errno = EINVAL; 3076aa342b1fSJoseph Koshy return (NULL); 3077f263522aSJoseph Koshy } 3078f263522aSJoseph Koshy 3079f263522aSJoseph Koshy const char * 30800cfab8ddSJoseph Koshy _pmc_name_of_event(enum pmc_event pe, enum pmc_cputype cpu) 3081f263522aSJoseph Koshy { 3082789140c0SJoseph Koshy const struct pmc_event_descr *ev, *evfence; 3083789140c0SJoseph Koshy 3084789140c0SJoseph Koshy ev = evfence = NULL; 30850cfab8ddSJoseph Koshy if (pe >= PMC_EV_IAF_FIRST && pe <= PMC_EV_IAF_LAST) { 30860cfab8ddSJoseph Koshy ev = iaf_event_table; 30870cfab8ddSJoseph Koshy evfence = iaf_event_table + PMC_EVENT_TABLE_SIZE(iaf); 30880cfab8ddSJoseph Koshy } else if (pe >= PMC_EV_IAP_FIRST && pe <= PMC_EV_IAP_LAST) { 30890cfab8ddSJoseph Koshy switch (cpu) { 30900cfab8ddSJoseph Koshy case PMC_CPU_INTEL_ATOM: 30910cfab8ddSJoseph Koshy ev = atom_event_table; 30920cfab8ddSJoseph Koshy evfence = atom_event_table + PMC_EVENT_TABLE_SIZE(atom); 30930cfab8ddSJoseph Koshy break; 30940cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE: 30950cfab8ddSJoseph Koshy ev = core_event_table; 30960cfab8ddSJoseph Koshy evfence = core_event_table + PMC_EVENT_TABLE_SIZE(core); 30970cfab8ddSJoseph Koshy break; 30980cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE2: 3099b4d091f3SJoseph Koshy case PMC_CPU_INTEL_CORE2EXTREME: 31000cfab8ddSJoseph Koshy ev = core2_event_table; 31010cfab8ddSJoseph Koshy evfence = core2_event_table + PMC_EVENT_TABLE_SIZE(core2); 31020cfab8ddSJoseph Koshy break; 3103597979c4SJeff Roberson case PMC_CPU_INTEL_COREI7: 3104597979c4SJeff Roberson ev = corei7_event_table; 3105597979c4SJeff Roberson evfence = corei7_event_table + PMC_EVENT_TABLE_SIZE(corei7); 3106597979c4SJeff Roberson break; 3107*1e862e5aSFabien Thomas case PMC_CPU_INTEL_IVYBRIDGE: 3108*1e862e5aSFabien Thomas ev = ivybridge_event_table; 3109*1e862e5aSFabien Thomas evfence = ivybridge_event_table + PMC_EVENT_TABLE_SIZE(ivybridge); 3110*1e862e5aSFabien Thomas break; 311178d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 311278d763a2SDavide Italiano ev = sandybridge_event_table; 311378d763a2SDavide Italiano evfence = sandybridge_event_table + PMC_EVENT_TABLE_SIZE(sandybridge); 311478d763a2SDavide Italiano break; 31151fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 31161fa7f10bSFabien Thomas ev = westmere_event_table; 31171fa7f10bSFabien Thomas evfence = westmere_event_table + PMC_EVENT_TABLE_SIZE(westmere); 31181fa7f10bSFabien Thomas break; 31190cfab8ddSJoseph Koshy default: /* Unknown CPU type. */ 31200cfab8ddSJoseph Koshy break; 31210cfab8ddSJoseph Koshy } 31221fa7f10bSFabien Thomas } else if (pe >= PMC_EV_UCF_FIRST && pe <= PMC_EV_UCF_LAST) { 31231fa7f10bSFabien Thomas ev = ucf_event_table; 31241fa7f10bSFabien Thomas evfence = ucf_event_table + PMC_EVENT_TABLE_SIZE(ucf); 31251fa7f10bSFabien Thomas } else if (pe >= PMC_EV_UCP_FIRST && pe <= PMC_EV_UCP_LAST) { 31261fa7f10bSFabien Thomas switch (cpu) { 31271fa7f10bSFabien Thomas case PMC_CPU_INTEL_COREI7: 31281fa7f10bSFabien Thomas ev = corei7uc_event_table; 31291fa7f10bSFabien Thomas evfence = corei7uc_event_table + PMC_EVENT_TABLE_SIZE(corei7uc); 31301fa7f10bSFabien Thomas break; 313178d763a2SDavide Italiano case PMC_CPU_INTEL_SANDYBRIDGE: 313278d763a2SDavide Italiano ev = sandybridgeuc_event_table; 313378d763a2SDavide Italiano evfence = sandybridgeuc_event_table + PMC_EVENT_TABLE_SIZE(sandybridgeuc); 313478d763a2SDavide Italiano break; 31351fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 31361fa7f10bSFabien Thomas ev = westmereuc_event_table; 31371fa7f10bSFabien Thomas evfence = westmereuc_event_table + PMC_EVENT_TABLE_SIZE(westmereuc); 31381fa7f10bSFabien Thomas break; 31391fa7f10bSFabien Thomas default: /* Unknown CPU type. */ 31401fa7f10bSFabien Thomas break; 31411fa7f10bSFabien Thomas } 31421fa7f10bSFabien Thomas } else if (pe >= PMC_EV_K7_FIRST && pe <= PMC_EV_K7_LAST) { 3143789140c0SJoseph Koshy ev = k7_event_table; 3144789140c0SJoseph Koshy evfence = k7_event_table + PMC_EVENT_TABLE_SIZE(k7); 3145789140c0SJoseph Koshy } else if (pe >= PMC_EV_K8_FIRST && pe <= PMC_EV_K8_LAST) { 3146789140c0SJoseph Koshy ev = k8_event_table; 3147789140c0SJoseph Koshy evfence = k8_event_table + PMC_EVENT_TABLE_SIZE(k8); 3148789140c0SJoseph Koshy } else if (pe >= PMC_EV_P4_FIRST && pe <= PMC_EV_P4_LAST) { 3149789140c0SJoseph Koshy ev = p4_event_table; 3150789140c0SJoseph Koshy evfence = p4_event_table + PMC_EVENT_TABLE_SIZE(p4); 3151789140c0SJoseph Koshy } else if (pe >= PMC_EV_P5_FIRST && pe <= PMC_EV_P5_LAST) { 3152789140c0SJoseph Koshy ev = p5_event_table; 3153789140c0SJoseph Koshy evfence = p5_event_table + PMC_EVENT_TABLE_SIZE(p5); 3154789140c0SJoseph Koshy } else if (pe >= PMC_EV_P6_FIRST && pe <= PMC_EV_P6_LAST) { 3155789140c0SJoseph Koshy ev = p6_event_table; 3156789140c0SJoseph Koshy evfence = p6_event_table + PMC_EVENT_TABLE_SIZE(p6); 31570ce207d2SRui Paulo } else if (pe >= PMC_EV_XSCALE_FIRST && pe <= PMC_EV_XSCALE_LAST) { 31580ce207d2SRui Paulo ev = xscale_event_table; 31590ce207d2SRui Paulo evfence = xscale_event_table + PMC_EVENT_TABLE_SIZE(xscale); 3160660df75eSGeorge V. Neville-Neil } else if (pe >= PMC_EV_MIPS24K_FIRST && pe <= PMC_EV_MIPS24K_LAST) { 3161660df75eSGeorge V. Neville-Neil ev = mips24k_event_table; 3162f5f9340bSFabien Thomas evfence = mips24k_event_table + PMC_EVENT_TABLE_SIZE(mips24k); 3163c2657f80SOleksandr Tymoshenko } else if (pe >= PMC_EV_OCTEON_FIRST && pe <= PMC_EV_OCTEON_LAST) { 3164c2657f80SOleksandr Tymoshenko ev = octeon_event_table; 3165c2657f80SOleksandr Tymoshenko evfence = octeon_event_table + PMC_EVENT_TABLE_SIZE(octeon); 31667b25dccaSJustin Hibbits } else if (pe >= PMC_EV_PPC7450_FIRST && pe <= PMC_EV_PPC7450_LAST) { 31677b25dccaSJustin Hibbits ev = ppc7450_event_table; 3168f5f9340bSFabien Thomas evfence = ppc7450_event_table + PMC_EVENT_TABLE_SIZE(ppc7450); 3169789140c0SJoseph Koshy } else if (pe == PMC_EV_TSC_TSC) { 3170789140c0SJoseph Koshy ev = tsc_event_table; 3171789140c0SJoseph Koshy evfence = tsc_event_table + PMC_EVENT_TABLE_SIZE(tsc); 3172f5f9340bSFabien Thomas } else if (pe >= PMC_EV_SOFT_FIRST && pe <= PMC_EV_SOFT_LAST) { 3173f5f9340bSFabien Thomas ev = soft_event_table; 3174f5f9340bSFabien Thomas evfence = soft_event_table + soft_event_info.pm_nevent; 3175789140c0SJoseph Koshy } 3176789140c0SJoseph Koshy 3177789140c0SJoseph Koshy for (; ev != evfence; ev++) 3178789140c0SJoseph Koshy if (pe == ev->pm_ev_code) 3179789140c0SJoseph Koshy return (ev->pm_ev_name); 3180f263522aSJoseph Koshy 31810cfab8ddSJoseph Koshy return (NULL); 31820cfab8ddSJoseph Koshy } 31830cfab8ddSJoseph Koshy 31840cfab8ddSJoseph Koshy const char * 31850cfab8ddSJoseph Koshy pmc_name_of_event(enum pmc_event pe) 31860cfab8ddSJoseph Koshy { 31870cfab8ddSJoseph Koshy const char *n; 31880cfab8ddSJoseph Koshy 31890cfab8ddSJoseph Koshy if ((n = _pmc_name_of_event(pe, cpu_info.pm_cputype)) != NULL) 31900cfab8ddSJoseph Koshy return (n); 31910cfab8ddSJoseph Koshy 3192f263522aSJoseph Koshy errno = EINVAL; 3193aa342b1fSJoseph Koshy return (NULL); 3194f263522aSJoseph Koshy } 3195f263522aSJoseph Koshy 3196f263522aSJoseph Koshy const char * 3197f263522aSJoseph Koshy pmc_name_of_mode(enum pmc_mode pm) 3198f263522aSJoseph Koshy { 3199f263522aSJoseph Koshy if ((int) pm >= PMC_MODE_FIRST && 3200f263522aSJoseph Koshy pm <= PMC_MODE_LAST) 3201aa342b1fSJoseph Koshy return (pmc_mode_names[pm]); 3202f263522aSJoseph Koshy 3203f263522aSJoseph Koshy errno = EINVAL; 3204aa342b1fSJoseph Koshy return (NULL); 3205f263522aSJoseph Koshy } 3206f263522aSJoseph Koshy 3207f263522aSJoseph Koshy const char * 3208f263522aSJoseph Koshy pmc_name_of_state(enum pmc_state ps) 3209f263522aSJoseph Koshy { 3210f263522aSJoseph Koshy if ((int) ps >= PMC_STATE_FIRST && 3211f263522aSJoseph Koshy ps <= PMC_STATE_LAST) 3212aa342b1fSJoseph Koshy return (pmc_state_names[ps]); 3213f263522aSJoseph Koshy 3214f263522aSJoseph Koshy errno = EINVAL; 3215aa342b1fSJoseph Koshy return (NULL); 3216f263522aSJoseph Koshy } 3217f263522aSJoseph Koshy 3218f263522aSJoseph Koshy int 3219f263522aSJoseph Koshy pmc_ncpu(void) 3220f263522aSJoseph Koshy { 3221f263522aSJoseph Koshy if (pmc_syscall == -1) { 3222f263522aSJoseph Koshy errno = ENXIO; 3223aa342b1fSJoseph Koshy return (-1); 3224f263522aSJoseph Koshy } 3225f263522aSJoseph Koshy 3226aa342b1fSJoseph Koshy return (cpu_info.pm_ncpu); 3227f263522aSJoseph Koshy } 3228f263522aSJoseph Koshy 3229f263522aSJoseph Koshy int 3230f263522aSJoseph Koshy pmc_npmc(int cpu) 3231f263522aSJoseph Koshy { 3232f263522aSJoseph Koshy if (pmc_syscall == -1) { 3233f263522aSJoseph Koshy errno = ENXIO; 3234aa342b1fSJoseph Koshy return (-1); 3235f263522aSJoseph Koshy } 3236f263522aSJoseph Koshy 3237f263522aSJoseph Koshy if (cpu < 0 || cpu >= (int) cpu_info.pm_ncpu) { 3238f263522aSJoseph Koshy errno = EINVAL; 3239aa342b1fSJoseph Koshy return (-1); 3240f263522aSJoseph Koshy } 3241f263522aSJoseph Koshy 3242aa342b1fSJoseph Koshy return (cpu_info.pm_npmc); 3243f263522aSJoseph Koshy } 3244f263522aSJoseph Koshy 3245f263522aSJoseph Koshy int 3246f263522aSJoseph Koshy pmc_pmcinfo(int cpu, struct pmc_pmcinfo **ppmci) 3247f263522aSJoseph Koshy { 3248f263522aSJoseph Koshy int nbytes, npmc; 3249f263522aSJoseph Koshy struct pmc_op_getpmcinfo *pmci; 3250f263522aSJoseph Koshy 3251f263522aSJoseph Koshy if ((npmc = pmc_npmc(cpu)) < 0) 3252aa342b1fSJoseph Koshy return (-1); 3253f263522aSJoseph Koshy 3254f263522aSJoseph Koshy nbytes = sizeof(struct pmc_op_getpmcinfo) + 3255f263522aSJoseph Koshy npmc * sizeof(struct pmc_info); 3256f263522aSJoseph Koshy 3257f263522aSJoseph Koshy if ((pmci = calloc(1, nbytes)) == NULL) 3258aa342b1fSJoseph Koshy return (-1); 3259f263522aSJoseph Koshy 3260f263522aSJoseph Koshy pmci->pm_cpu = cpu; 3261f263522aSJoseph Koshy 3262f263522aSJoseph Koshy if (PMC_CALL(GETPMCINFO, pmci) < 0) { 3263f263522aSJoseph Koshy free(pmci); 3264aa342b1fSJoseph Koshy return (-1); 3265f263522aSJoseph Koshy } 3266f263522aSJoseph Koshy 3267f263522aSJoseph Koshy /* kernel<->library, library<->userland interfaces are identical */ 3268f263522aSJoseph Koshy *ppmci = (struct pmc_pmcinfo *) pmci; 3269aa342b1fSJoseph Koshy return (0); 3270f263522aSJoseph Koshy } 3271f263522aSJoseph Koshy 3272f263522aSJoseph Koshy int 3273f263522aSJoseph Koshy pmc_read(pmc_id_t pmc, pmc_value_t *value) 3274f263522aSJoseph Koshy { 3275f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_read_op; 3276f263522aSJoseph Koshy 3277f263522aSJoseph Koshy pmc_read_op.pm_pmcid = pmc; 3278f263522aSJoseph Koshy pmc_read_op.pm_flags = PMC_F_OLDVALUE; 3279f263522aSJoseph Koshy pmc_read_op.pm_value = -1; 3280f263522aSJoseph Koshy 3281f263522aSJoseph Koshy if (PMC_CALL(PMCRW, &pmc_read_op) < 0) 3282aa342b1fSJoseph Koshy return (-1); 3283f263522aSJoseph Koshy 3284f263522aSJoseph Koshy *value = pmc_read_op.pm_value; 3285aa342b1fSJoseph Koshy return (0); 3286f263522aSJoseph Koshy } 3287f263522aSJoseph Koshy 3288f263522aSJoseph Koshy int 3289f263522aSJoseph Koshy pmc_release(pmc_id_t pmc) 3290f263522aSJoseph Koshy { 3291f263522aSJoseph Koshy struct pmc_op_simple pmc_release_args; 3292f263522aSJoseph Koshy 3293f263522aSJoseph Koshy pmc_release_args.pm_pmcid = pmc; 3294aa342b1fSJoseph Koshy return (PMC_CALL(PMCRELEASE, &pmc_release_args)); 3295f263522aSJoseph Koshy } 3296f263522aSJoseph Koshy 3297f263522aSJoseph Koshy int 3298f263522aSJoseph Koshy pmc_rw(pmc_id_t pmc, pmc_value_t newvalue, pmc_value_t *oldvaluep) 3299f263522aSJoseph Koshy { 3300f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_rw_op; 3301f263522aSJoseph Koshy 3302f263522aSJoseph Koshy pmc_rw_op.pm_pmcid = pmc; 3303f263522aSJoseph Koshy pmc_rw_op.pm_flags = PMC_F_NEWVALUE | PMC_F_OLDVALUE; 3304f263522aSJoseph Koshy pmc_rw_op.pm_value = newvalue; 3305f263522aSJoseph Koshy 3306f263522aSJoseph Koshy if (PMC_CALL(PMCRW, &pmc_rw_op) < 0) 3307aa342b1fSJoseph Koshy return (-1); 3308f263522aSJoseph Koshy 3309f263522aSJoseph Koshy *oldvaluep = pmc_rw_op.pm_value; 3310aa342b1fSJoseph Koshy return (0); 3311f263522aSJoseph Koshy } 3312f263522aSJoseph Koshy 3313f263522aSJoseph Koshy int 3314f263522aSJoseph Koshy pmc_set(pmc_id_t pmc, pmc_value_t value) 3315f263522aSJoseph Koshy { 3316f263522aSJoseph Koshy struct pmc_op_pmcsetcount sc; 3317f263522aSJoseph Koshy 3318f263522aSJoseph Koshy sc.pm_pmcid = pmc; 3319f263522aSJoseph Koshy sc.pm_count = value; 3320f263522aSJoseph Koshy 3321f263522aSJoseph Koshy if (PMC_CALL(PMCSETCOUNT, &sc) < 0) 3322aa342b1fSJoseph Koshy return (-1); 3323aa342b1fSJoseph Koshy return (0); 3324f263522aSJoseph Koshy } 3325f263522aSJoseph Koshy 3326f263522aSJoseph Koshy int 3327f263522aSJoseph Koshy pmc_start(pmc_id_t pmc) 3328f263522aSJoseph Koshy { 3329f263522aSJoseph Koshy struct pmc_op_simple pmc_start_args; 3330f263522aSJoseph Koshy 3331f263522aSJoseph Koshy pmc_start_args.pm_pmcid = pmc; 3332aa342b1fSJoseph Koshy return (PMC_CALL(PMCSTART, &pmc_start_args)); 3333f263522aSJoseph Koshy } 3334f263522aSJoseph Koshy 3335f263522aSJoseph Koshy int 3336f263522aSJoseph Koshy pmc_stop(pmc_id_t pmc) 3337f263522aSJoseph Koshy { 3338f263522aSJoseph Koshy struct pmc_op_simple pmc_stop_args; 3339f263522aSJoseph Koshy 3340f263522aSJoseph Koshy pmc_stop_args.pm_pmcid = pmc; 3341aa342b1fSJoseph Koshy return (PMC_CALL(PMCSTOP, &pmc_stop_args)); 3342f263522aSJoseph Koshy } 3343f263522aSJoseph Koshy 3344f263522aSJoseph Koshy int 3345f263522aSJoseph Koshy pmc_width(pmc_id_t pmcid, uint32_t *width) 3346f263522aSJoseph Koshy { 3347f263522aSJoseph Koshy unsigned int i; 3348f263522aSJoseph Koshy enum pmc_class cl; 3349f263522aSJoseph Koshy 3350f263522aSJoseph Koshy cl = PMC_ID_TO_CLASS(pmcid); 3351f263522aSJoseph Koshy for (i = 0; i < cpu_info.pm_nclass; i++) 3352f263522aSJoseph Koshy if (cpu_info.pm_classes[i].pm_class == cl) { 3353f263522aSJoseph Koshy *width = cpu_info.pm_classes[i].pm_width; 3354aa342b1fSJoseph Koshy return (0); 3355f263522aSJoseph Koshy } 3356484202faSJoseph Koshy errno = EINVAL; 3357484202faSJoseph Koshy return (-1); 3358f263522aSJoseph Koshy } 3359f263522aSJoseph Koshy 3360f263522aSJoseph Koshy int 3361f263522aSJoseph Koshy pmc_write(pmc_id_t pmc, pmc_value_t value) 3362f263522aSJoseph Koshy { 3363f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_write_op; 3364f263522aSJoseph Koshy 3365f263522aSJoseph Koshy pmc_write_op.pm_pmcid = pmc; 3366f263522aSJoseph Koshy pmc_write_op.pm_flags = PMC_F_NEWVALUE; 3367f263522aSJoseph Koshy pmc_write_op.pm_value = value; 3368aa342b1fSJoseph Koshy return (PMC_CALL(PMCRW, &pmc_write_op)); 3369f263522aSJoseph Koshy } 3370f263522aSJoseph Koshy 3371f263522aSJoseph Koshy int 3372f263522aSJoseph Koshy pmc_writelog(uint32_t userdata) 3373f263522aSJoseph Koshy { 3374f263522aSJoseph Koshy struct pmc_op_writelog wl; 3375f263522aSJoseph Koshy 3376f263522aSJoseph Koshy wl.pm_userdata = userdata; 3377aa342b1fSJoseph Koshy return (PMC_CALL(WRITELOG, &wl)); 3378f263522aSJoseph Koshy } 3379