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 80ebccf1e3SJoseph Koshy 81660df75eSGeorge V. Neville-Neil #if defined(__mips__) 82660df75eSGeorge V. Neville-Neil static int mips24k_allocate_pmc(enum pmc_event _pe, char* ctrspec, 83660df75eSGeorge V. Neville-Neil struct pmc_op_pmcallocate *_pmc_config); 84660df75eSGeorge V. Neville-Neil #endif /* __mips__ */ 85660df75eSGeorge V. Neville-Neil 86*7b25dccaSJustin Hibbits #if defined(__powerpc__) 87*7b25dccaSJustin Hibbits static int ppc7450_allocate_pmc(enum pmc_event _pe, char* ctrspec, 88*7b25dccaSJustin Hibbits struct pmc_op_pmcallocate *_pmc_config); 89*7b25dccaSJustin Hibbits #endif /* __powerpc__ */ 90660df75eSGeorge V. Neville-Neil 91ebccf1e3SJoseph Koshy #define PMC_CALL(cmd, params) \ 92ebccf1e3SJoseph Koshy syscall(pmc_syscall, PMC_OP_##cmd, (params)) 93ebccf1e3SJoseph Koshy 94ebccf1e3SJoseph Koshy /* 95ebccf1e3SJoseph Koshy * Event aliases provide a way for the user to ask for generic events 96ebccf1e3SJoseph Koshy * like "cache-misses", or "instructions-retired". These aliases are 97ebccf1e3SJoseph Koshy * mapped to the appropriate canonical event descriptions using a 98ebccf1e3SJoseph Koshy * lookup table. 99ebccf1e3SJoseph Koshy */ 100ebccf1e3SJoseph Koshy struct pmc_event_alias { 101ebccf1e3SJoseph Koshy const char *pm_alias; 102ebccf1e3SJoseph Koshy const char *pm_spec; 103ebccf1e3SJoseph Koshy }; 104ebccf1e3SJoseph Koshy 105ebccf1e3SJoseph Koshy static const struct pmc_event_alias *pmc_mdep_event_aliases; 106ebccf1e3SJoseph Koshy 107ebccf1e3SJoseph Koshy /* 108789140c0SJoseph Koshy * The pmc_event_descr structure maps symbolic names known to the user 109ebccf1e3SJoseph Koshy * to integer codes used by the PMC KLD. 110ebccf1e3SJoseph Koshy */ 111ebccf1e3SJoseph Koshy struct pmc_event_descr { 112ebccf1e3SJoseph Koshy const char *pm_ev_name; 113ebccf1e3SJoseph Koshy enum pmc_event pm_ev_code; 114ebccf1e3SJoseph Koshy }; 115ebccf1e3SJoseph Koshy 116789140c0SJoseph Koshy /* 117789140c0SJoseph Koshy * The pmc_class_descr structure maps class name prefixes for 118789140c0SJoseph Koshy * event names to event tables and other PMC class data. 119789140c0SJoseph Koshy */ 120789140c0SJoseph Koshy struct pmc_class_descr { 121789140c0SJoseph Koshy const char *pm_evc_name; 122789140c0SJoseph Koshy size_t pm_evc_name_size; 123789140c0SJoseph Koshy enum pmc_class pm_evc_class; 124789140c0SJoseph Koshy const struct pmc_event_descr *pm_evc_event_table; 125789140c0SJoseph Koshy size_t pm_evc_event_table_size; 126789140c0SJoseph Koshy int (*pm_evc_allocate_pmc)(enum pmc_event _pe, 127789140c0SJoseph Koshy char *_ctrspec, struct pmc_op_pmcallocate *_pa); 128ebccf1e3SJoseph Koshy }; 129ebccf1e3SJoseph Koshy 130789140c0SJoseph Koshy #define PMC_TABLE_SIZE(N) (sizeof(N)/sizeof(N[0])) 131789140c0SJoseph Koshy #define PMC_EVENT_TABLE_SIZE(N) PMC_TABLE_SIZE(N##_event_table) 132789140c0SJoseph Koshy 133789140c0SJoseph Koshy #undef __PMC_EV 134789140c0SJoseph Koshy #define __PMC_EV(C,N) { #N, PMC_EV_ ## C ## _ ## N }, 135789140c0SJoseph Koshy 136789140c0SJoseph Koshy /* 1370cfab8ddSJoseph Koshy * PMC_CLASSDEP_TABLE(NAME, CLASS) 138789140c0SJoseph Koshy * 1390cfab8ddSJoseph Koshy * Define a table mapping event names and aliases to HWPMC event IDs. 140789140c0SJoseph Koshy */ 1410cfab8ddSJoseph Koshy #define PMC_CLASSDEP_TABLE(N, C) \ 142789140c0SJoseph Koshy static const struct pmc_event_descr N##_event_table[] = \ 143789140c0SJoseph Koshy { \ 144789140c0SJoseph Koshy __PMC_EV_##C() \ 1450cfab8ddSJoseph Koshy } 1460cfab8ddSJoseph Koshy 1470cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(iaf, IAF); 1480cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(k7, K7); 1490cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(k8, K8); 1500cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(p4, P4); 1510cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(p5, P5); 1520cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(p6, P6); 1530ce207d2SRui Paulo PMC_CLASSDEP_TABLE(xscale, XSCALE); 154660df75eSGeorge V. Neville-Neil PMC_CLASSDEP_TABLE(mips24k, MIPS24K); 1551fa7f10bSFabien Thomas PMC_CLASSDEP_TABLE(ucf, UCF); 156*7b25dccaSJustin Hibbits PMC_CLASSDEP_TABLE(ppc7450, PPC7450); 1570cfab8ddSJoseph Koshy 1580cfab8ddSJoseph Koshy #undef __PMC_EV_ALIAS 1590cfab8ddSJoseph Koshy #define __PMC_EV_ALIAS(N,CODE) { N, PMC_EV_##CODE }, 1600cfab8ddSJoseph Koshy 1610cfab8ddSJoseph Koshy static const struct pmc_event_descr atom_event_table[] = 1620cfab8ddSJoseph Koshy { 1630cfab8ddSJoseph Koshy __PMC_EV_ALIAS_ATOM() 1640cfab8ddSJoseph Koshy }; 1650cfab8ddSJoseph Koshy 1660cfab8ddSJoseph Koshy static const struct pmc_event_descr core_event_table[] = 1670cfab8ddSJoseph Koshy { 1680cfab8ddSJoseph Koshy __PMC_EV_ALIAS_CORE() 1690cfab8ddSJoseph Koshy }; 1700cfab8ddSJoseph Koshy 1710cfab8ddSJoseph Koshy 1720cfab8ddSJoseph Koshy static const struct pmc_event_descr core2_event_table[] = 1730cfab8ddSJoseph Koshy { 1740cfab8ddSJoseph Koshy __PMC_EV_ALIAS_CORE2() 1750cfab8ddSJoseph Koshy }; 1760cfab8ddSJoseph Koshy 177597979c4SJeff Roberson static const struct pmc_event_descr corei7_event_table[] = 178597979c4SJeff Roberson { 179597979c4SJeff Roberson __PMC_EV_ALIAS_COREI7() 180597979c4SJeff Roberson }; 181597979c4SJeff Roberson 1821fa7f10bSFabien Thomas static const struct pmc_event_descr westmere_event_table[] = 1831fa7f10bSFabien Thomas { 1841fa7f10bSFabien Thomas __PMC_EV_ALIAS_WESTMERE() 1851fa7f10bSFabien Thomas }; 1861fa7f10bSFabien Thomas 1871fa7f10bSFabien Thomas static const struct pmc_event_descr corei7uc_event_table[] = 1881fa7f10bSFabien Thomas { 1891fa7f10bSFabien Thomas __PMC_EV_ALIAS_COREI7UC() 1901fa7f10bSFabien Thomas }; 1911fa7f10bSFabien Thomas 1921fa7f10bSFabien Thomas static const struct pmc_event_descr westmereuc_event_table[] = 1931fa7f10bSFabien Thomas { 1941fa7f10bSFabien Thomas __PMC_EV_ALIAS_WESTMEREUC() 1951fa7f10bSFabien Thomas }; 1961fa7f10bSFabien Thomas 1970cfab8ddSJoseph Koshy /* 1980cfab8ddSJoseph Koshy * PMC_MDEP_TABLE(NAME, PRIMARYCLASS, ADDITIONAL_CLASSES...) 1990cfab8ddSJoseph Koshy * 2000cfab8ddSJoseph Koshy * Map a CPU to the PMC classes it supports. 2010cfab8ddSJoseph Koshy */ 2020cfab8ddSJoseph Koshy #define PMC_MDEP_TABLE(N,C,...) \ 203789140c0SJoseph Koshy static const enum pmc_class N##_pmc_classes[] = { \ 204789140c0SJoseph Koshy PMC_CLASS_##C, __VA_ARGS__ \ 205789140c0SJoseph Koshy } 206789140c0SJoseph Koshy 2070cfab8ddSJoseph Koshy PMC_MDEP_TABLE(atom, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC); 2080cfab8ddSJoseph Koshy PMC_MDEP_TABLE(core, IAP, PMC_CLASS_TSC); 2090cfab8ddSJoseph Koshy PMC_MDEP_TABLE(core2, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC); 2101fa7f10bSFabien Thomas PMC_MDEP_TABLE(corei7, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 2111fa7f10bSFabien Thomas PMC_MDEP_TABLE(westmere, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 212789140c0SJoseph Koshy PMC_MDEP_TABLE(k7, K7, PMC_CLASS_TSC); 213789140c0SJoseph Koshy PMC_MDEP_TABLE(k8, K8, PMC_CLASS_TSC); 214789140c0SJoseph Koshy PMC_MDEP_TABLE(p4, P4, PMC_CLASS_TSC); 215789140c0SJoseph Koshy PMC_MDEP_TABLE(p5, P5, PMC_CLASS_TSC); 216789140c0SJoseph Koshy PMC_MDEP_TABLE(p6, P6, PMC_CLASS_TSC); 2170ce207d2SRui Paulo PMC_MDEP_TABLE(xscale, XSCALE, PMC_CLASS_XSCALE); 218660df75eSGeorge V. Neville-Neil PMC_MDEP_TABLE(mips24k, MIPS24K, PMC_CLASS_MIPS24K); 219*7b25dccaSJustin Hibbits PMC_MDEP_TABLE(ppc7450, PPC7450, PMC_CLASS_PPC7450); 220789140c0SJoseph Koshy 221789140c0SJoseph Koshy static const struct pmc_event_descr tsc_event_table[] = 222789140c0SJoseph Koshy { 223789140c0SJoseph Koshy __PMC_EV_TSC() 224789140c0SJoseph Koshy }; 225789140c0SJoseph Koshy 226789140c0SJoseph Koshy #undef PMC_CLASS_TABLE_DESC 2270cfab8ddSJoseph Koshy #define PMC_CLASS_TABLE_DESC(NAME, CLASS, EVENTS, ALLOCATOR) \ 2280cfab8ddSJoseph Koshy static const struct pmc_class_descr NAME##_class_table_descr = \ 2290cfab8ddSJoseph Koshy { \ 2300cfab8ddSJoseph Koshy .pm_evc_name = #CLASS "-", \ 2310cfab8ddSJoseph Koshy .pm_evc_name_size = sizeof(#CLASS "-") - 1, \ 2320cfab8ddSJoseph Koshy .pm_evc_class = PMC_CLASS_##CLASS , \ 2330cfab8ddSJoseph Koshy .pm_evc_event_table = EVENTS##_event_table , \ 234789140c0SJoseph Koshy .pm_evc_event_table_size = \ 2350cfab8ddSJoseph Koshy PMC_EVENT_TABLE_SIZE(EVENTS), \ 2360cfab8ddSJoseph Koshy .pm_evc_allocate_pmc = ALLOCATOR##_allocate_pmc \ 237789140c0SJoseph Koshy } 238789140c0SJoseph Koshy 239789140c0SJoseph Koshy #if defined(__i386__) || defined(__amd64__) 2400cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(iaf, IAF, iaf, iaf); 2410cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(atom, IAP, atom, iap); 2420cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(core, IAP, core, iap); 2430cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(core2, IAP, core2, iap); 244597979c4SJeff Roberson PMC_CLASS_TABLE_DESC(corei7, IAP, corei7, iap); 2451fa7f10bSFabien Thomas PMC_CLASS_TABLE_DESC(westmere, IAP, westmere, iap); 2461fa7f10bSFabien Thomas PMC_CLASS_TABLE_DESC(ucf, UCF, ucf, ucf); 2471fa7f10bSFabien Thomas PMC_CLASS_TABLE_DESC(corei7uc, UCP, corei7uc, ucp); 2481fa7f10bSFabien Thomas PMC_CLASS_TABLE_DESC(westmereuc, UCP, westmereuc, ucp); 249789140c0SJoseph Koshy #endif 250789140c0SJoseph Koshy #if defined(__i386__) 2510cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(k7, K7, k7, k7); 252789140c0SJoseph Koshy #endif 253789140c0SJoseph Koshy #if defined(__i386__) || defined(__amd64__) 2540cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(k8, K8, k8, k8); 2550cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(p4, P4, p4, p4); 256789140c0SJoseph Koshy #endif 2570cfab8ddSJoseph Koshy #if defined(__i386__) 2580cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(p5, P5, p5, p5); 2590cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(p6, P6, p6, p6); 2600cfab8ddSJoseph Koshy #endif 2610cfab8ddSJoseph Koshy #if defined(__i386__) || defined(__amd64__) 2620cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(tsc, TSC, tsc, tsc); 2630cfab8ddSJoseph Koshy #endif 2640ce207d2SRui Paulo #if defined(__XSCALE__) 2650ce207d2SRui Paulo PMC_CLASS_TABLE_DESC(xscale, XSCALE, xscale, xscale); 2660ce207d2SRui Paulo #endif 267789140c0SJoseph Koshy 268660df75eSGeorge V. Neville-Neil #if defined(__mips__) 269660df75eSGeorge V. Neville-Neil PMC_CLASS_TABLE_DESC(mips24k, MIPS24K, mips24k, mips24k); 270660df75eSGeorge V. Neville-Neil #endif /* __mips__ */ 271660df75eSGeorge V. Neville-Neil 272*7b25dccaSJustin Hibbits #if defined(__powerpc__) 273*7b25dccaSJustin Hibbits PMC_CLASS_TABLE_DESC(ppc7450, PPC7450, ppc7450, ppc7450); 274*7b25dccaSJustin Hibbits #endif 275*7b25dccaSJustin Hibbits 276789140c0SJoseph Koshy #undef PMC_CLASS_TABLE_DESC 277789140c0SJoseph Koshy 2780cfab8ddSJoseph Koshy static const struct pmc_class_descr **pmc_class_table; 2790cfab8ddSJoseph Koshy #define PMC_CLASS_TABLE_SIZE cpu_info.pm_nclass 2800cfab8ddSJoseph Koshy 281789140c0SJoseph Koshy static const enum pmc_class *pmc_mdep_class_list; 282789140c0SJoseph Koshy static size_t pmc_mdep_class_list_size; 283789140c0SJoseph Koshy 284ebccf1e3SJoseph Koshy /* 285ebccf1e3SJoseph Koshy * Mapping tables, mapping enumeration values to human readable 286ebccf1e3SJoseph Koshy * strings. 287ebccf1e3SJoseph Koshy */ 288ebccf1e3SJoseph Koshy 289ebccf1e3SJoseph Koshy static const char * pmc_capability_names[] = { 290ebccf1e3SJoseph Koshy #undef __PMC_CAP 291ebccf1e3SJoseph Koshy #define __PMC_CAP(N,V,D) #N , 292ebccf1e3SJoseph Koshy __PMC_CAPS() 293ebccf1e3SJoseph Koshy }; 294ebccf1e3SJoseph Koshy 295ebccf1e3SJoseph Koshy static const char * pmc_class_names[] = { 296ebccf1e3SJoseph Koshy #undef __PMC_CLASS 297ebccf1e3SJoseph Koshy #define __PMC_CLASS(C) #C , 298ebccf1e3SJoseph Koshy __PMC_CLASSES() 299ebccf1e3SJoseph Koshy }; 300ebccf1e3SJoseph Koshy 301789140c0SJoseph Koshy struct pmc_cputype_map { 302562fc14bSDimitry Andric enum pmc_cputype pm_cputype; 303789140c0SJoseph Koshy const char *pm_name; 304789140c0SJoseph Koshy }; 305789140c0SJoseph Koshy 306789140c0SJoseph Koshy static const struct pmc_cputype_map pmc_cputype_names[] = { 307ebccf1e3SJoseph Koshy #undef __PMC_CPU 308789140c0SJoseph Koshy #define __PMC_CPU(S, V, D) { .pm_cputype = PMC_CPU_##S, .pm_name = #S } , 309ebccf1e3SJoseph Koshy __PMC_CPUS() 310ebccf1e3SJoseph Koshy }; 311ebccf1e3SJoseph Koshy 312ebccf1e3SJoseph Koshy static const char * pmc_disposition_names[] = { 313ebccf1e3SJoseph Koshy #undef __PMC_DISP 314ebccf1e3SJoseph Koshy #define __PMC_DISP(D) #D , 315ebccf1e3SJoseph Koshy __PMC_DISPOSITIONS() 316ebccf1e3SJoseph Koshy }; 317ebccf1e3SJoseph Koshy 318ebccf1e3SJoseph Koshy static const char * pmc_mode_names[] = { 319ebccf1e3SJoseph Koshy #undef __PMC_MODE 320ebccf1e3SJoseph Koshy #define __PMC_MODE(M,N) #M , 321ebccf1e3SJoseph Koshy __PMC_MODES() 322ebccf1e3SJoseph Koshy }; 323ebccf1e3SJoseph Koshy 324ebccf1e3SJoseph Koshy static const char * pmc_state_names[] = { 325ebccf1e3SJoseph Koshy #undef __PMC_STATE 326ebccf1e3SJoseph Koshy #define __PMC_STATE(S) #S , 327ebccf1e3SJoseph Koshy __PMC_STATES() 328ebccf1e3SJoseph Koshy }; 329ebccf1e3SJoseph Koshy 330ebccf1e3SJoseph Koshy static int pmc_syscall = -1; /* filled in by pmc_init() */ 331ebccf1e3SJoseph Koshy 3321455fcd3SJoseph Koshy static struct pmc_cpuinfo cpu_info; /* filled in by pmc_init() */ 3331455fcd3SJoseph Koshy 334ebccf1e3SJoseph Koshy /* Event masks for events */ 335ebccf1e3SJoseph Koshy struct pmc_masks { 336ebccf1e3SJoseph Koshy const char *pm_name; 337ebccf1e3SJoseph Koshy const uint32_t pm_value; 338ebccf1e3SJoseph Koshy }; 339ebccf1e3SJoseph Koshy #define PMCMASK(N,V) { .pm_name = #N, .pm_value = (V) } 3401fa7f10bSFabien Thomas #define NULLMASK { .pm_name = NULL } 341ebccf1e3SJoseph Koshy 34286a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 343ebccf1e3SJoseph Koshy static int 344ebccf1e3SJoseph Koshy pmc_parse_mask(const struct pmc_masks *pmask, char *p, uint32_t *evmask) 345ebccf1e3SJoseph Koshy { 346ebccf1e3SJoseph Koshy const struct pmc_masks *pm; 347ebccf1e3SJoseph Koshy char *q, *r; 348ebccf1e3SJoseph Koshy int c; 349ebccf1e3SJoseph Koshy 350ebccf1e3SJoseph Koshy if (pmask == NULL) /* no mask keywords */ 351aa342b1fSJoseph Koshy return (-1); 352ebccf1e3SJoseph Koshy q = strchr(p, '='); /* skip '=' */ 353ebccf1e3SJoseph Koshy if (*++q == '\0') /* no more data */ 354aa342b1fSJoseph Koshy return (-1); 355ebccf1e3SJoseph Koshy c = 0; /* count of mask keywords seen */ 356ebccf1e3SJoseph Koshy while ((r = strsep(&q, "+")) != NULL) { 357789140c0SJoseph Koshy for (pm = pmask; pm->pm_name && strcasecmp(r, pm->pm_name); 358789140c0SJoseph Koshy pm++) 359ebccf1e3SJoseph Koshy ; 360ebccf1e3SJoseph Koshy if (pm->pm_name == NULL) /* not found */ 361aa342b1fSJoseph Koshy return (-1); 362ebccf1e3SJoseph Koshy *evmask |= pm->pm_value; 363ebccf1e3SJoseph Koshy c++; 364ebccf1e3SJoseph Koshy } 365aa342b1fSJoseph Koshy return (c); 366ebccf1e3SJoseph Koshy } 36704e9feb0SMarcel Moolenaar #endif 368ebccf1e3SJoseph Koshy 369ebccf1e3SJoseph Koshy #define KWMATCH(p,kw) (strcasecmp((p), (kw)) == 0) 370ebccf1e3SJoseph Koshy #define KWPREFIXMATCH(p,kw) (strncasecmp((p), (kw), sizeof((kw)) - 1) == 0) 371ebccf1e3SJoseph Koshy #define EV_ALIAS(N,S) { .pm_alias = N, .pm_spec = S } 372ebccf1e3SJoseph Koshy 37304e9feb0SMarcel Moolenaar #if defined(__i386__) 374ebccf1e3SJoseph Koshy 375ebccf1e3SJoseph Koshy /* 376ebccf1e3SJoseph Koshy * AMD K7 (Athlon) CPUs. 377ebccf1e3SJoseph Koshy */ 378ebccf1e3SJoseph Koshy 379ebccf1e3SJoseph Koshy static struct pmc_event_alias k7_aliases[] = { 380ebccf1e3SJoseph Koshy EV_ALIAS("branches", "k7-retired-branches"), 381ebccf1e3SJoseph Koshy EV_ALIAS("branch-mispredicts", "k7-retired-branches-mispredicted"), 382ebccf1e3SJoseph Koshy EV_ALIAS("cycles", "tsc"), 3836aa5a193SJoseph Koshy EV_ALIAS("dc-misses", "k7-dc-misses"), 384ebccf1e3SJoseph Koshy EV_ALIAS("ic-misses", "k7-ic-misses"), 385ebccf1e3SJoseph Koshy EV_ALIAS("instructions", "k7-retired-instructions"), 386ebccf1e3SJoseph Koshy EV_ALIAS("interrupts", "k7-hardware-interrupts"), 387ebccf1e3SJoseph Koshy EV_ALIAS(NULL, NULL) 388ebccf1e3SJoseph Koshy }; 389ebccf1e3SJoseph Koshy 390ebccf1e3SJoseph Koshy #define K7_KW_COUNT "count" 391ebccf1e3SJoseph Koshy #define K7_KW_EDGE "edge" 392ebccf1e3SJoseph Koshy #define K7_KW_INV "inv" 393ebccf1e3SJoseph Koshy #define K7_KW_OS "os" 394ebccf1e3SJoseph Koshy #define K7_KW_UNITMASK "unitmask" 395ebccf1e3SJoseph Koshy #define K7_KW_USR "usr" 396ebccf1e3SJoseph Koshy 397ebccf1e3SJoseph Koshy static int 398ebccf1e3SJoseph Koshy k7_allocate_pmc(enum pmc_event pe, char *ctrspec, 399ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 400ebccf1e3SJoseph Koshy { 401ebccf1e3SJoseph Koshy char *e, *p, *q; 402ebccf1e3SJoseph Koshy int c, has_unitmask; 403ebccf1e3SJoseph Koshy uint32_t count, unitmask; 404ebccf1e3SJoseph Koshy 405f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 406789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 407ebccf1e3SJoseph Koshy 408ebccf1e3SJoseph Koshy if (pe == PMC_EV_K7_DC_REFILLS_FROM_L2 || 409ebccf1e3SJoseph Koshy pe == PMC_EV_K7_DC_REFILLS_FROM_SYSTEM || 410ebccf1e3SJoseph Koshy pe == PMC_EV_K7_DC_WRITEBACKS) { 411ebccf1e3SJoseph Koshy has_unitmask = 1; 412f263522aSJoseph Koshy unitmask = AMD_PMC_UNITMASK_MOESI; 413ebccf1e3SJoseph Koshy } else 414ebccf1e3SJoseph Koshy unitmask = has_unitmask = 0; 415ebccf1e3SJoseph Koshy 416ebccf1e3SJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 417ebccf1e3SJoseph Koshy if (KWPREFIXMATCH(p, K7_KW_COUNT "=")) { 418ebccf1e3SJoseph Koshy q = strchr(p, '='); 419ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 420aa342b1fSJoseph Koshy return (-1); 421ebccf1e3SJoseph Koshy 422ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 423ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 424aa342b1fSJoseph Koshy return (-1); 425ebccf1e3SJoseph Koshy 426ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 427f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config |= 428f263522aSJoseph Koshy AMD_PMC_TO_COUNTER(count); 429ebccf1e3SJoseph Koshy 430ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_EDGE)) { 431ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 432ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_INV)) { 433ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 434ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_OS)) { 435ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 436ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, K7_KW_UNITMASK "=")) { 437ebccf1e3SJoseph Koshy if (has_unitmask == 0) 438aa342b1fSJoseph Koshy return (-1); 439ebccf1e3SJoseph Koshy unitmask = 0; 440ebccf1e3SJoseph Koshy q = strchr(p, '='); 441ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 442aa342b1fSJoseph Koshy return (-1); 443ebccf1e3SJoseph Koshy 444ebccf1e3SJoseph Koshy while ((c = tolower(*q++)) != 0) 445ebccf1e3SJoseph Koshy if (c == 'm') 446f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_M; 447ebccf1e3SJoseph Koshy else if (c == 'o') 448f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_O; 449ebccf1e3SJoseph Koshy else if (c == 'e') 450f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_E; 451ebccf1e3SJoseph Koshy else if (c == 's') 452f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_S; 453ebccf1e3SJoseph Koshy else if (c == 'i') 454f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_I; 455ebccf1e3SJoseph Koshy else if (c == '+') 456ebccf1e3SJoseph Koshy continue; 457ebccf1e3SJoseph Koshy else 458aa342b1fSJoseph Koshy return (-1); 459ebccf1e3SJoseph Koshy 460ebccf1e3SJoseph Koshy if (unitmask == 0) 461aa342b1fSJoseph Koshy return (-1); 462ebccf1e3SJoseph Koshy 463ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_USR)) { 464ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 465ebccf1e3SJoseph Koshy } else 466aa342b1fSJoseph Koshy return (-1); 467ebccf1e3SJoseph Koshy } 468ebccf1e3SJoseph Koshy 469ebccf1e3SJoseph Koshy if (has_unitmask) { 470ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 471f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config |= 472f263522aSJoseph Koshy AMD_PMC_TO_UNITMASK(unitmask); 473ebccf1e3SJoseph Koshy } 474ebccf1e3SJoseph Koshy 475aa342b1fSJoseph Koshy return (0); 476ebccf1e3SJoseph Koshy 477ebccf1e3SJoseph Koshy } 478ebccf1e3SJoseph Koshy 479f263522aSJoseph Koshy #endif 480f263522aSJoseph Koshy 48186a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 482f263522aSJoseph Koshy 483f263522aSJoseph Koshy /* 4840cfab8ddSJoseph Koshy * Intel Core (Family 6, Model E) PMCs. 4850cfab8ddSJoseph Koshy */ 4860cfab8ddSJoseph Koshy 4870cfab8ddSJoseph Koshy static struct pmc_event_alias core_aliases[] = { 4880cfab8ddSJoseph Koshy EV_ALIAS("branches", "iap-br-instr-ret"), 4890cfab8ddSJoseph Koshy EV_ALIAS("branch-mispredicts", "iap-br-mispred-ret"), 4900cfab8ddSJoseph Koshy EV_ALIAS("cycles", "tsc-tsc"), 4910cfab8ddSJoseph Koshy EV_ALIAS("ic-misses", "iap-icache-misses"), 4920cfab8ddSJoseph Koshy EV_ALIAS("instructions", "iap-instr-ret"), 4930cfab8ddSJoseph Koshy EV_ALIAS("interrupts", "iap-core-hw-int-rx"), 4940cfab8ddSJoseph Koshy EV_ALIAS("unhalted-cycles", "iap-unhalted-core-cycles"), 4950cfab8ddSJoseph Koshy EV_ALIAS(NULL, NULL) 4960cfab8ddSJoseph Koshy }; 4970cfab8ddSJoseph Koshy 4980cfab8ddSJoseph Koshy /* 4990cfab8ddSJoseph Koshy * Intel Core2 (Family 6, Model F), Core2Extreme (Family 6, Model 17H) 5000cfab8ddSJoseph Koshy * and Atom (Family 6, model 1CH) PMCs. 501791f5d5bSJoseph Koshy * 502791f5d5bSJoseph Koshy * We map aliases to events on the fixed-function counters if these 503791f5d5bSJoseph Koshy * are present. Note that not all CPUs in this family contain fixed-function 504791f5d5bSJoseph Koshy * counters. 5050cfab8ddSJoseph Koshy */ 5060cfab8ddSJoseph Koshy 5070cfab8ddSJoseph Koshy static struct pmc_event_alias core2_aliases[] = { 5080cfab8ddSJoseph Koshy EV_ALIAS("branches", "iap-br-inst-retired.any"), 5090cfab8ddSJoseph Koshy EV_ALIAS("branch-mispredicts", "iap-br-inst-retired.mispred"), 5100cfab8ddSJoseph Koshy EV_ALIAS("cycles", "tsc-tsc"), 5110cfab8ddSJoseph Koshy EV_ALIAS("ic-misses", "iap-l1i-misses"), 5120cfab8ddSJoseph Koshy EV_ALIAS("instructions", "iaf-instr-retired.any"), 5130cfab8ddSJoseph Koshy EV_ALIAS("interrupts", "iap-hw-int-rcv"), 5140cfab8ddSJoseph Koshy EV_ALIAS("unhalted-cycles", "iaf-cpu-clk-unhalted.core"), 5150cfab8ddSJoseph Koshy EV_ALIAS(NULL, NULL) 5160cfab8ddSJoseph Koshy }; 517791f5d5bSJoseph Koshy 518791f5d5bSJoseph Koshy static struct pmc_event_alias core2_aliases_without_iaf[] = { 519791f5d5bSJoseph Koshy EV_ALIAS("branches", "iap-br-inst-retired.any"), 520791f5d5bSJoseph Koshy EV_ALIAS("branch-mispredicts", "iap-br-inst-retired.mispred"), 521791f5d5bSJoseph Koshy EV_ALIAS("cycles", "tsc-tsc"), 522791f5d5bSJoseph Koshy EV_ALIAS("ic-misses", "iap-l1i-misses"), 523791f5d5bSJoseph Koshy EV_ALIAS("instructions", "iap-inst-retired.any_p"), 524791f5d5bSJoseph Koshy EV_ALIAS("interrupts", "iap-hw-int-rcv"), 525791f5d5bSJoseph Koshy EV_ALIAS("unhalted-cycles", "iap-cpu-clk-unhalted.core_p"), 526791f5d5bSJoseph Koshy EV_ALIAS(NULL, NULL) 527791f5d5bSJoseph Koshy }; 528791f5d5bSJoseph Koshy 5290cfab8ddSJoseph Koshy #define atom_aliases core2_aliases 530791f5d5bSJoseph Koshy #define atom_aliases_without_iaf core2_aliases_without_iaf 531597979c4SJeff Roberson #define corei7_aliases core2_aliases 532791f5d5bSJoseph Koshy #define corei7_aliases_without_iaf core2_aliases_without_iaf 5331fa7f10bSFabien Thomas #define westmere_aliases core2_aliases 5341fa7f10bSFabien Thomas #define westmere_aliases_without_iaf core2_aliases_without_iaf 5350cfab8ddSJoseph Koshy 5360cfab8ddSJoseph Koshy #define IAF_KW_OS "os" 5370cfab8ddSJoseph Koshy #define IAF_KW_USR "usr" 5380cfab8ddSJoseph Koshy #define IAF_KW_ANYTHREAD "anythread" 5390cfab8ddSJoseph Koshy 5400cfab8ddSJoseph Koshy /* 5410cfab8ddSJoseph Koshy * Parse an event specifier for Intel fixed function counters. 5420cfab8ddSJoseph Koshy */ 5430cfab8ddSJoseph Koshy static int 5440cfab8ddSJoseph Koshy iaf_allocate_pmc(enum pmc_event pe, char *ctrspec, 5450cfab8ddSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 5460cfab8ddSJoseph Koshy { 5470cfab8ddSJoseph Koshy char *p; 5480cfab8ddSJoseph Koshy 5490cfab8ddSJoseph Koshy (void) pe; 5500cfab8ddSJoseph Koshy 5510cfab8ddSJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 5520cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iaf.pm_iaf_flags = 0; 5530cfab8ddSJoseph Koshy 5540cfab8ddSJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 5550cfab8ddSJoseph Koshy if (KWMATCH(p, IAF_KW_OS)) 5560cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 5570cfab8ddSJoseph Koshy else if (KWMATCH(p, IAF_KW_USR)) 5580cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 5590cfab8ddSJoseph Koshy else if (KWMATCH(p, IAF_KW_ANYTHREAD)) 5600cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iaf.pm_iaf_flags |= IAF_ANY; 5610cfab8ddSJoseph Koshy else 5620cfab8ddSJoseph Koshy return (-1); 5630cfab8ddSJoseph Koshy } 5640cfab8ddSJoseph Koshy 5650cfab8ddSJoseph Koshy return (0); 5660cfab8ddSJoseph Koshy } 5670cfab8ddSJoseph Koshy 5680cfab8ddSJoseph Koshy /* 5690cfab8ddSJoseph Koshy * Core/Core2 support. 5700cfab8ddSJoseph Koshy */ 5710cfab8ddSJoseph Koshy 5720cfab8ddSJoseph Koshy #define IAP_KW_AGENT "agent" 5730cfab8ddSJoseph Koshy #define IAP_KW_ANYTHREAD "anythread" 5740cfab8ddSJoseph Koshy #define IAP_KW_CACHESTATE "cachestate" 5750cfab8ddSJoseph Koshy #define IAP_KW_CMASK "cmask" 5760cfab8ddSJoseph Koshy #define IAP_KW_CORE "core" 5770cfab8ddSJoseph Koshy #define IAP_KW_EDGE "edge" 5780cfab8ddSJoseph Koshy #define IAP_KW_INV "inv" 5790cfab8ddSJoseph Koshy #define IAP_KW_OS "os" 5800cfab8ddSJoseph Koshy #define IAP_KW_PREFETCH "prefetch" 5810cfab8ddSJoseph Koshy #define IAP_KW_SNOOPRESPONSE "snoopresponse" 5820cfab8ddSJoseph Koshy #define IAP_KW_SNOOPTYPE "snooptype" 5830cfab8ddSJoseph Koshy #define IAP_KW_TRANSITION "trans" 5840cfab8ddSJoseph Koshy #define IAP_KW_USR "usr" 5851fa7f10bSFabien Thomas #define IAP_KW_RSP "rsp" 5860cfab8ddSJoseph Koshy 5870cfab8ddSJoseph Koshy static struct pmc_masks iap_core_mask[] = { 5880cfab8ddSJoseph Koshy PMCMASK(all, (0x3 << 14)), 5890cfab8ddSJoseph Koshy PMCMASK(this, (0x1 << 14)), 5900cfab8ddSJoseph Koshy NULLMASK 5910cfab8ddSJoseph Koshy }; 5920cfab8ddSJoseph Koshy 5930cfab8ddSJoseph Koshy static struct pmc_masks iap_agent_mask[] = { 5940cfab8ddSJoseph Koshy PMCMASK(this, 0), 5950cfab8ddSJoseph Koshy PMCMASK(any, (0x1 << 13)), 5960cfab8ddSJoseph Koshy NULLMASK 5970cfab8ddSJoseph Koshy }; 5980cfab8ddSJoseph Koshy 5990cfab8ddSJoseph Koshy static struct pmc_masks iap_prefetch_mask[] = { 6000cfab8ddSJoseph Koshy PMCMASK(both, (0x3 << 12)), 6010cfab8ddSJoseph Koshy PMCMASK(only, (0x1 << 12)), 6020cfab8ddSJoseph Koshy PMCMASK(exclude, 0), 6030cfab8ddSJoseph Koshy NULLMASK 6040cfab8ddSJoseph Koshy }; 6050cfab8ddSJoseph Koshy 6060cfab8ddSJoseph Koshy static struct pmc_masks iap_cachestate_mask[] = { 6070cfab8ddSJoseph Koshy PMCMASK(i, (1 << 8)), 6080cfab8ddSJoseph Koshy PMCMASK(s, (1 << 9)), 6090cfab8ddSJoseph Koshy PMCMASK(e, (1 << 10)), 6100cfab8ddSJoseph Koshy PMCMASK(m, (1 << 11)), 6110cfab8ddSJoseph Koshy NULLMASK 6120cfab8ddSJoseph Koshy }; 6130cfab8ddSJoseph Koshy 6140cfab8ddSJoseph Koshy static struct pmc_masks iap_snoopresponse_mask[] = { 6150cfab8ddSJoseph Koshy PMCMASK(clean, (1 << 8)), 6160cfab8ddSJoseph Koshy PMCMASK(hit, (1 << 9)), 6170cfab8ddSJoseph Koshy PMCMASK(hitm, (1 << 11)), 6180cfab8ddSJoseph Koshy NULLMASK 6190cfab8ddSJoseph Koshy }; 6200cfab8ddSJoseph Koshy 6210cfab8ddSJoseph Koshy static struct pmc_masks iap_snooptype_mask[] = { 6220cfab8ddSJoseph Koshy PMCMASK(cmp2s, (1 << 8)), 6230cfab8ddSJoseph Koshy PMCMASK(cmp2i, (1 << 9)), 6240cfab8ddSJoseph Koshy NULLMASK 6250cfab8ddSJoseph Koshy }; 6260cfab8ddSJoseph Koshy 6270cfab8ddSJoseph Koshy static struct pmc_masks iap_transition_mask[] = { 6280cfab8ddSJoseph Koshy PMCMASK(any, 0x00), 6290cfab8ddSJoseph Koshy PMCMASK(frequency, 0x10), 6300cfab8ddSJoseph Koshy NULLMASK 6310cfab8ddSJoseph Koshy }; 6320cfab8ddSJoseph Koshy 6331fa7f10bSFabien Thomas static struct pmc_masks iap_rsp_mask[] = { 6341fa7f10bSFabien Thomas PMCMASK(DMND_DATA_RD, (1 << 0)), 6351fa7f10bSFabien Thomas PMCMASK(DMND_RFO, (1 << 1)), 6361fa7f10bSFabien Thomas PMCMASK(DMND_IFETCH, (1 << 2)), 6371fa7f10bSFabien Thomas PMCMASK(WB, (1 << 3)), 6381fa7f10bSFabien Thomas PMCMASK(PF_DATA_RD, (1 << 4)), 6391fa7f10bSFabien Thomas PMCMASK(PF_RFO, (1 << 5)), 6401fa7f10bSFabien Thomas PMCMASK(PF_IFETCH, (1 << 6)), 6411fa7f10bSFabien Thomas PMCMASK(OTHER, (1 << 7)), 6421fa7f10bSFabien Thomas PMCMASK(UNCORE_HIT, (1 << 8)), 6431fa7f10bSFabien Thomas PMCMASK(OTHER_CORE_HIT_SNP, (1 << 9)), 6441fa7f10bSFabien Thomas PMCMASK(OTHER_CORE_HITM, (1 << 10)), 6451fa7f10bSFabien Thomas PMCMASK(REMOTE_CACHE_FWD, (1 << 12)), 6461fa7f10bSFabien Thomas PMCMASK(REMOTE_DRAM, (1 << 13)), 6471fa7f10bSFabien Thomas PMCMASK(LOCAL_DRAM, (1 << 14)), 6481fa7f10bSFabien Thomas PMCMASK(NON_DRAM, (1 << 15)), 6491fa7f10bSFabien Thomas NULLMASK 6501fa7f10bSFabien Thomas }; 6511fa7f10bSFabien Thomas 6520cfab8ddSJoseph Koshy static int 6530cfab8ddSJoseph Koshy iap_allocate_pmc(enum pmc_event pe, char *ctrspec, 6540cfab8ddSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 6550cfab8ddSJoseph Koshy { 6560cfab8ddSJoseph Koshy char *e, *p, *q; 6571fa7f10bSFabien Thomas uint32_t cachestate, evmask, rsp; 6580cfab8ddSJoseph Koshy int count, n; 6590cfab8ddSJoseph Koshy 6600cfab8ddSJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE | 6610cfab8ddSJoseph Koshy PMC_CAP_QUALIFIER); 6620cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config = 0; 6630cfab8ddSJoseph Koshy 6641fa7f10bSFabien Thomas cachestate = evmask = rsp = 0; 6650cfab8ddSJoseph Koshy 6660cfab8ddSJoseph Koshy /* Parse additional modifiers if present */ 6670cfab8ddSJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 6680cfab8ddSJoseph Koshy 6690cfab8ddSJoseph Koshy n = 0; 6700cfab8ddSJoseph Koshy if (KWPREFIXMATCH(p, IAP_KW_CMASK "=")) { 6710cfab8ddSJoseph Koshy q = strchr(p, '='); 6720cfab8ddSJoseph Koshy if (*++q == '\0') /* skip '=' */ 6730cfab8ddSJoseph Koshy return (-1); 6740cfab8ddSJoseph Koshy count = strtol(q, &e, 0); 6750cfab8ddSJoseph Koshy if (e == q || *e != '\0') 6760cfab8ddSJoseph Koshy return (-1); 6770cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 6780cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= 6790cfab8ddSJoseph Koshy IAP_CMASK(count); 6800cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_EDGE)) { 6810cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 6820cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_INV)) { 6830cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 6840cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_OS)) { 6850cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 6860cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_USR)) { 6870cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 6880cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_ANYTHREAD)) { 6890cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= IAP_ANY; 690b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_CORE "=")) { 6910cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_core_mask, p, &evmask); 6920cfab8ddSJoseph Koshy if (n != 1) 6930cfab8ddSJoseph Koshy return (-1); 694b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_AGENT "=")) { 6950cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_agent_mask, p, &evmask); 6960cfab8ddSJoseph Koshy if (n != 1) 6970cfab8ddSJoseph Koshy return (-1); 698b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_PREFETCH "=")) { 6990cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_prefetch_mask, p, &evmask); 7000cfab8ddSJoseph Koshy if (n != 1) 7010cfab8ddSJoseph Koshy return (-1); 702b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_CACHESTATE "=")) { 7030cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_cachestate_mask, p, &cachestate); 7040cfab8ddSJoseph Koshy } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_CORE && 705b47ea38eSJoseph Koshy KWPREFIXMATCH(p, IAP_KW_TRANSITION "=")) { 7060cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_transition_mask, p, &evmask); 7070cfab8ddSJoseph Koshy if (n != 1) 7080cfab8ddSJoseph Koshy return (-1); 7090cfab8ddSJoseph Koshy } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM || 710b4d091f3SJoseph Koshy cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2 || 7111fa7f10bSFabien Thomas cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2EXTREME) { 712b47ea38eSJoseph Koshy if (KWPREFIXMATCH(p, IAP_KW_SNOOPRESPONSE "=")) { 7130cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_snoopresponse_mask, p, 7140cfab8ddSJoseph Koshy &evmask); 715b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_SNOOPTYPE "=")) { 7160cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_snooptype_mask, p, 7170cfab8ddSJoseph Koshy &evmask); 7180cfab8ddSJoseph Koshy } else 7190cfab8ddSJoseph Koshy return (-1); 7201fa7f10bSFabien Thomas } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_COREI7 || 7211fa7f10bSFabien Thomas cpu_info.pm_cputype == PMC_CPU_INTEL_WESTMERE) { 7221fa7f10bSFabien Thomas if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 7231fa7f10bSFabien Thomas n = pmc_parse_mask(iap_rsp_mask, p, &rsp); 7241fa7f10bSFabien Thomas } else 7251fa7f10bSFabien Thomas return (-1); 7260cfab8ddSJoseph Koshy } else 7270cfab8ddSJoseph Koshy return (-1); 7280cfab8ddSJoseph Koshy 7290cfab8ddSJoseph Koshy if (n < 0) /* Parsing failed. */ 7300cfab8ddSJoseph Koshy return (-1); 7310cfab8ddSJoseph Koshy } 7320cfab8ddSJoseph Koshy 7330cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= evmask; 7340cfab8ddSJoseph Koshy 7350cfab8ddSJoseph Koshy /* 7360cfab8ddSJoseph Koshy * If the event requires a 'cachestate' qualifier but was not 7370cfab8ddSJoseph Koshy * specified by the user, use a sensible default. 7380cfab8ddSJoseph Koshy */ 7390cfab8ddSJoseph Koshy switch (pe) { 7400cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_28H: /* Core, Core2, Atom */ 7410cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_29H: /* Core, Core2, Atom */ 7420cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_2AH: /* Core, Core2, Atom */ 7430cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_2BH: /* Atom, Core2 */ 7440cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_2EH: /* Core, Core2, Atom */ 7450cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_30H: /* Core, Core2, Atom */ 7460cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_32H: /* Core */ 7470cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_40H: /* Core */ 7480cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_41H: /* Core */ 7490cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_42H: /* Core, Core2, Atom */ 7500cfab8ddSJoseph Koshy if (cachestate == 0) 7510cfab8ddSJoseph Koshy cachestate = (0xF << 8); 752aa1b887bSRyan Stone break; 753aa1b887bSRyan Stone case PMC_EV_IAP_EVENT_77H: /* Atom */ 754aa1b887bSRyan Stone /* IAP_EVENT_77H only accepts a cachestate qualifier on the 755aa1b887bSRyan Stone * Atom processor 756aa1b887bSRyan Stone */ 757aa1b887bSRyan Stone if(cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM && cachestate == 0) 758aa1b887bSRyan Stone cachestate = (0xF << 8); 759aa1b887bSRyan Stone break; 7600cfab8ddSJoseph Koshy default: 7610cfab8ddSJoseph Koshy break; 7620cfab8ddSJoseph Koshy } 7630cfab8ddSJoseph Koshy 7640cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= cachestate; 7651fa7f10bSFabien Thomas pmc_config->pm_md.pm_iap.pm_iap_rsp = rsp; 7661fa7f10bSFabien Thomas 7671fa7f10bSFabien Thomas return (0); 7681fa7f10bSFabien Thomas } 7691fa7f10bSFabien Thomas 7701fa7f10bSFabien Thomas /* 7711fa7f10bSFabien Thomas * Intel Uncore. 7721fa7f10bSFabien Thomas */ 7731fa7f10bSFabien Thomas 7741fa7f10bSFabien Thomas static int 7751fa7f10bSFabien Thomas ucf_allocate_pmc(enum pmc_event pe, char *ctrspec, 7761fa7f10bSFabien Thomas struct pmc_op_pmcallocate *pmc_config) 7771fa7f10bSFabien Thomas { 7781fa7f10bSFabien Thomas (void) pe; 7791fa7f10bSFabien Thomas (void) ctrspec; 7801fa7f10bSFabien Thomas 7811fa7f10bSFabien Thomas pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 7821fa7f10bSFabien Thomas pmc_config->pm_md.pm_ucf.pm_ucf_flags = 0; 7831fa7f10bSFabien Thomas 7841fa7f10bSFabien Thomas return (0); 7851fa7f10bSFabien Thomas } 7861fa7f10bSFabien Thomas 7871fa7f10bSFabien Thomas #define UCP_KW_CMASK "cmask" 7881fa7f10bSFabien Thomas #define UCP_KW_EDGE "edge" 7891fa7f10bSFabien Thomas #define UCP_KW_INV "inv" 7901fa7f10bSFabien Thomas 7911fa7f10bSFabien Thomas static int 7921fa7f10bSFabien Thomas ucp_allocate_pmc(enum pmc_event pe, char *ctrspec, 7931fa7f10bSFabien Thomas struct pmc_op_pmcallocate *pmc_config) 7941fa7f10bSFabien Thomas { 7951fa7f10bSFabien Thomas char *e, *p, *q; 7961fa7f10bSFabien Thomas int count, n; 7971fa7f10bSFabien Thomas 7981fa7f10bSFabien Thomas (void) pe; 7991fa7f10bSFabien Thomas 8001fa7f10bSFabien Thomas pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE | 8011fa7f10bSFabien Thomas PMC_CAP_QUALIFIER); 8021fa7f10bSFabien Thomas pmc_config->pm_md.pm_ucp.pm_ucp_config = 0; 8031fa7f10bSFabien Thomas 8041fa7f10bSFabien Thomas /* Parse additional modifiers if present */ 8051fa7f10bSFabien Thomas while ((p = strsep(&ctrspec, ",")) != NULL) { 8061fa7f10bSFabien Thomas 8071fa7f10bSFabien Thomas n = 0; 8081fa7f10bSFabien Thomas if (KWPREFIXMATCH(p, UCP_KW_CMASK "=")) { 8091fa7f10bSFabien Thomas q = strchr(p, '='); 8101fa7f10bSFabien Thomas if (*++q == '\0') /* skip '=' */ 8111fa7f10bSFabien Thomas return (-1); 8121fa7f10bSFabien Thomas count = strtol(q, &e, 0); 8131fa7f10bSFabien Thomas if (e == q || *e != '\0') 8141fa7f10bSFabien Thomas return (-1); 8151fa7f10bSFabien Thomas pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 8161fa7f10bSFabien Thomas pmc_config->pm_md.pm_ucp.pm_ucp_config |= 8171fa7f10bSFabien Thomas UCP_CMASK(count); 8181fa7f10bSFabien Thomas } else if (KWMATCH(p, UCP_KW_EDGE)) { 8191fa7f10bSFabien Thomas pmc_config->pm_caps |= PMC_CAP_EDGE; 8201fa7f10bSFabien Thomas } else if (KWMATCH(p, UCP_KW_INV)) { 8211fa7f10bSFabien Thomas pmc_config->pm_caps |= PMC_CAP_INVERT; 8221fa7f10bSFabien Thomas } else 8231fa7f10bSFabien Thomas return (-1); 8241fa7f10bSFabien Thomas 8251fa7f10bSFabien Thomas if (n < 0) /* Parsing failed. */ 8261fa7f10bSFabien Thomas return (-1); 8271fa7f10bSFabien Thomas } 8280cfab8ddSJoseph Koshy 8290cfab8ddSJoseph Koshy return (0); 8300cfab8ddSJoseph Koshy } 8310cfab8ddSJoseph Koshy 8320cfab8ddSJoseph Koshy /* 833f263522aSJoseph Koshy * AMD K8 PMCs. 834f263522aSJoseph Koshy * 835f263522aSJoseph Koshy * These are very similar to AMD K7 PMCs, but support more kinds of 836f263522aSJoseph Koshy * events. 837f263522aSJoseph Koshy */ 838f263522aSJoseph Koshy 839f263522aSJoseph Koshy static struct pmc_event_alias k8_aliases[] = { 840f263522aSJoseph Koshy EV_ALIAS("branches", "k8-fr-retired-taken-branches"), 841f263522aSJoseph Koshy EV_ALIAS("branch-mispredicts", 842f263522aSJoseph Koshy "k8-fr-retired-taken-branches-mispredicted"), 843f263522aSJoseph Koshy EV_ALIAS("cycles", "tsc"), 844f263522aSJoseph Koshy EV_ALIAS("dc-misses", "k8-dc-miss"), 845f263522aSJoseph Koshy EV_ALIAS("ic-misses", "k8-ic-miss"), 846f263522aSJoseph Koshy EV_ALIAS("instructions", "k8-fr-retired-x86-instructions"), 847f263522aSJoseph Koshy EV_ALIAS("interrupts", "k8-fr-taken-hardware-interrupts"), 848177a2f22SJoseph Koshy EV_ALIAS("unhalted-cycles", "k8-bu-cpu-clk-unhalted"), 849f263522aSJoseph Koshy EV_ALIAS(NULL, NULL) 850f263522aSJoseph Koshy }; 851f263522aSJoseph Koshy 852f263522aSJoseph Koshy #define __K8MASK(N,V) PMCMASK(N,(1 << (V))) 853f263522aSJoseph Koshy 854f263522aSJoseph Koshy /* 855f263522aSJoseph Koshy * Parsing tables 856f263522aSJoseph Koshy */ 857f263522aSJoseph Koshy 858f263522aSJoseph Koshy /* fp dispatched fpu ops */ 859f263522aSJoseph Koshy static const struct pmc_masks k8_mask_fdfo[] = { 860f263522aSJoseph Koshy __K8MASK(add-pipe-excluding-junk-ops, 0), 861f263522aSJoseph Koshy __K8MASK(multiply-pipe-excluding-junk-ops, 1), 862f263522aSJoseph Koshy __K8MASK(store-pipe-excluding-junk-ops, 2), 863f263522aSJoseph Koshy __K8MASK(add-pipe-junk-ops, 3), 864f263522aSJoseph Koshy __K8MASK(multiply-pipe-junk-ops, 4), 865f263522aSJoseph Koshy __K8MASK(store-pipe-junk-ops, 5), 866f263522aSJoseph Koshy NULLMASK 867f263522aSJoseph Koshy }; 868f263522aSJoseph Koshy 869f263522aSJoseph Koshy /* ls segment register loads */ 870f263522aSJoseph Koshy static const struct pmc_masks k8_mask_lsrl[] = { 871f263522aSJoseph Koshy __K8MASK(es, 0), 872f263522aSJoseph Koshy __K8MASK(cs, 1), 873f263522aSJoseph Koshy __K8MASK(ss, 2), 874f263522aSJoseph Koshy __K8MASK(ds, 3), 875f263522aSJoseph Koshy __K8MASK(fs, 4), 876f263522aSJoseph Koshy __K8MASK(gs, 5), 877f263522aSJoseph Koshy __K8MASK(hs, 6), 878f263522aSJoseph Koshy NULLMASK 879f263522aSJoseph Koshy }; 880f263522aSJoseph Koshy 881f263522aSJoseph Koshy /* ls locked operation */ 882f263522aSJoseph Koshy static const struct pmc_masks k8_mask_llo[] = { 883f263522aSJoseph Koshy __K8MASK(locked-instructions, 0), 884f263522aSJoseph Koshy __K8MASK(cycles-in-request, 1), 885f263522aSJoseph Koshy __K8MASK(cycles-to-complete, 2), 886f263522aSJoseph Koshy NULLMASK 887f263522aSJoseph Koshy }; 888f263522aSJoseph Koshy 889f263522aSJoseph Koshy /* dc refill from {l2,system} and dc copyback */ 890f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dc[] = { 891f263522aSJoseph Koshy __K8MASK(invalid, 0), 892f263522aSJoseph Koshy __K8MASK(shared, 1), 893f263522aSJoseph Koshy __K8MASK(exclusive, 2), 894f263522aSJoseph Koshy __K8MASK(owner, 3), 895f263522aSJoseph Koshy __K8MASK(modified, 4), 896f263522aSJoseph Koshy NULLMASK 897f263522aSJoseph Koshy }; 898f263522aSJoseph Koshy 899f263522aSJoseph Koshy /* dc one bit ecc error */ 900f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dobee[] = { 901f263522aSJoseph Koshy __K8MASK(scrubber, 0), 902f263522aSJoseph Koshy __K8MASK(piggyback, 1), 903f263522aSJoseph Koshy NULLMASK 904f263522aSJoseph Koshy }; 905f263522aSJoseph Koshy 906f263522aSJoseph Koshy /* dc dispatched prefetch instructions */ 907f263522aSJoseph Koshy static const struct pmc_masks k8_mask_ddpi[] = { 908f263522aSJoseph Koshy __K8MASK(load, 0), 909f263522aSJoseph Koshy __K8MASK(store, 1), 910f263522aSJoseph Koshy __K8MASK(nta, 2), 911f263522aSJoseph Koshy NULLMASK 912f263522aSJoseph Koshy }; 913f263522aSJoseph Koshy 914f263522aSJoseph Koshy /* dc dcache accesses by locks */ 915f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dabl[] = { 916f263522aSJoseph Koshy __K8MASK(accesses, 0), 917f263522aSJoseph Koshy __K8MASK(misses, 1), 918f263522aSJoseph Koshy NULLMASK 919f263522aSJoseph Koshy }; 920f263522aSJoseph Koshy 921f263522aSJoseph Koshy /* bu internal l2 request */ 922f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bilr[] = { 923f263522aSJoseph Koshy __K8MASK(ic-fill, 0), 924f263522aSJoseph Koshy __K8MASK(dc-fill, 1), 925f263522aSJoseph Koshy __K8MASK(tlb-reload, 2), 926f263522aSJoseph Koshy __K8MASK(tag-snoop, 3), 927f263522aSJoseph Koshy __K8MASK(cancelled, 4), 928f263522aSJoseph Koshy NULLMASK 929f263522aSJoseph Koshy }; 930f263522aSJoseph Koshy 931f263522aSJoseph Koshy /* bu fill request l2 miss */ 932f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bfrlm[] = { 933f263522aSJoseph Koshy __K8MASK(ic-fill, 0), 934f263522aSJoseph Koshy __K8MASK(dc-fill, 1), 935f263522aSJoseph Koshy __K8MASK(tlb-reload, 2), 936f263522aSJoseph Koshy NULLMASK 937f263522aSJoseph Koshy }; 938f263522aSJoseph Koshy 939f263522aSJoseph Koshy /* bu fill into l2 */ 940f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bfil[] = { 941f263522aSJoseph Koshy __K8MASK(dirty-l2-victim, 0), 942f263522aSJoseph Koshy __K8MASK(victim-from-l2, 1), 943f263522aSJoseph Koshy NULLMASK 944f263522aSJoseph Koshy }; 945f263522aSJoseph Koshy 946f263522aSJoseph Koshy /* fr retired fpu instructions */ 947f263522aSJoseph Koshy static const struct pmc_masks k8_mask_frfi[] = { 948f263522aSJoseph Koshy __K8MASK(x87, 0), 949f263522aSJoseph Koshy __K8MASK(mmx-3dnow, 1), 950f263522aSJoseph Koshy __K8MASK(packed-sse-sse2, 2), 951f263522aSJoseph Koshy __K8MASK(scalar-sse-sse2, 3), 952f263522aSJoseph Koshy NULLMASK 953f263522aSJoseph Koshy }; 954f263522aSJoseph Koshy 955f263522aSJoseph Koshy /* fr retired fastpath double op instructions */ 956f263522aSJoseph Koshy static const struct pmc_masks k8_mask_frfdoi[] = { 957f263522aSJoseph Koshy __K8MASK(low-op-pos-0, 0), 958f263522aSJoseph Koshy __K8MASK(low-op-pos-1, 1), 959f263522aSJoseph Koshy __K8MASK(low-op-pos-2, 2), 960f263522aSJoseph Koshy NULLMASK 961f263522aSJoseph Koshy }; 962f263522aSJoseph Koshy 963f263522aSJoseph Koshy /* fr fpu exceptions */ 964f263522aSJoseph Koshy static const struct pmc_masks k8_mask_ffe[] = { 965f263522aSJoseph Koshy __K8MASK(x87-reclass-microfaults, 0), 966f263522aSJoseph Koshy __K8MASK(sse-retype-microfaults, 1), 967f263522aSJoseph Koshy __K8MASK(sse-reclass-microfaults, 2), 968f263522aSJoseph Koshy __K8MASK(sse-and-x87-microtraps, 3), 969f263522aSJoseph Koshy NULLMASK 970f263522aSJoseph Koshy }; 971f263522aSJoseph Koshy 972f263522aSJoseph Koshy /* nb memory controller page access event */ 973f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmcpae[] = { 974f263522aSJoseph Koshy __K8MASK(page-hit, 0), 975f263522aSJoseph Koshy __K8MASK(page-miss, 1), 976f263522aSJoseph Koshy __K8MASK(page-conflict, 2), 977f263522aSJoseph Koshy NULLMASK 978f263522aSJoseph Koshy }; 979f263522aSJoseph Koshy 980f263522aSJoseph Koshy /* nb memory controller turnaround */ 981f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmct[] = { 982f263522aSJoseph Koshy __K8MASK(dimm-turnaround, 0), 983f263522aSJoseph Koshy __K8MASK(read-to-write-turnaround, 1), 984f263522aSJoseph Koshy __K8MASK(write-to-read-turnaround, 2), 985f263522aSJoseph Koshy NULLMASK 986f263522aSJoseph Koshy }; 987f263522aSJoseph Koshy 988f263522aSJoseph Koshy /* nb memory controller bypass saturation */ 989f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmcbs[] = { 990f263522aSJoseph Koshy __K8MASK(memory-controller-hi-pri-bypass, 0), 991f263522aSJoseph Koshy __K8MASK(memory-controller-lo-pri-bypass, 1), 992f263522aSJoseph Koshy __K8MASK(dram-controller-interface-bypass, 2), 993f263522aSJoseph Koshy __K8MASK(dram-controller-queue-bypass, 3), 994f263522aSJoseph Koshy NULLMASK 995f263522aSJoseph Koshy }; 996f263522aSJoseph Koshy 997f263522aSJoseph Koshy /* nb sized commands */ 998f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nsc[] = { 999f263522aSJoseph Koshy __K8MASK(nonpostwrszbyte, 0), 1000f263522aSJoseph Koshy __K8MASK(nonpostwrszdword, 1), 1001f263522aSJoseph Koshy __K8MASK(postwrszbyte, 2), 1002f263522aSJoseph Koshy __K8MASK(postwrszdword, 3), 1003f263522aSJoseph Koshy __K8MASK(rdszbyte, 4), 1004f263522aSJoseph Koshy __K8MASK(rdszdword, 5), 1005f263522aSJoseph Koshy __K8MASK(rdmodwr, 6), 1006f263522aSJoseph Koshy NULLMASK 1007f263522aSJoseph Koshy }; 1008f263522aSJoseph Koshy 1009f263522aSJoseph Koshy /* nb probe result */ 1010f263522aSJoseph Koshy static const struct pmc_masks k8_mask_npr[] = { 1011f263522aSJoseph Koshy __K8MASK(probe-miss, 0), 1012f263522aSJoseph Koshy __K8MASK(probe-hit, 1), 1013f263522aSJoseph Koshy __K8MASK(probe-hit-dirty-no-memory-cancel, 2), 1014f263522aSJoseph Koshy __K8MASK(probe-hit-dirty-with-memory-cancel, 3), 1015f263522aSJoseph Koshy NULLMASK 1016f263522aSJoseph Koshy }; 1017f263522aSJoseph Koshy 1018f263522aSJoseph Koshy /* nb hypertransport bus bandwidth */ 1019f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nhbb[] = { /* HT bus bandwidth */ 1020f263522aSJoseph Koshy __K8MASK(command, 0), 1021f263522aSJoseph Koshy __K8MASK(data, 1), 1022f263522aSJoseph Koshy __K8MASK(buffer-release, 2), 1023f263522aSJoseph Koshy __K8MASK(nop, 3), 1024f263522aSJoseph Koshy NULLMASK 1025f263522aSJoseph Koshy }; 1026f263522aSJoseph Koshy 1027f263522aSJoseph Koshy #undef __K8MASK 1028f263522aSJoseph Koshy 1029f263522aSJoseph Koshy #define K8_KW_COUNT "count" 1030f263522aSJoseph Koshy #define K8_KW_EDGE "edge" 1031f263522aSJoseph Koshy #define K8_KW_INV "inv" 1032f263522aSJoseph Koshy #define K8_KW_MASK "mask" 1033f263522aSJoseph Koshy #define K8_KW_OS "os" 1034f263522aSJoseph Koshy #define K8_KW_USR "usr" 1035f263522aSJoseph Koshy 1036f263522aSJoseph Koshy static int 1037f263522aSJoseph Koshy k8_allocate_pmc(enum pmc_event pe, char *ctrspec, 1038f263522aSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 1039f263522aSJoseph Koshy { 1040f263522aSJoseph Koshy char *e, *p, *q; 1041f263522aSJoseph Koshy int n; 1042f263522aSJoseph Koshy uint32_t count, evmask; 1043f263522aSJoseph Koshy const struct pmc_masks *pm, *pmask; 1044f263522aSJoseph Koshy 1045789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1046f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 1047f263522aSJoseph Koshy 1048f263522aSJoseph Koshy pmask = NULL; 1049f263522aSJoseph Koshy evmask = 0; 1050f263522aSJoseph Koshy 1051f263522aSJoseph Koshy #define __K8SETMASK(M) pmask = k8_mask_##M 1052f263522aSJoseph Koshy 1053f263522aSJoseph Koshy /* setup parsing tables */ 1054f263522aSJoseph Koshy switch (pe) { 1055f263522aSJoseph Koshy case PMC_EV_K8_FP_DISPATCHED_FPU_OPS: 1056f263522aSJoseph Koshy __K8SETMASK(fdfo); 1057f263522aSJoseph Koshy break; 1058f263522aSJoseph Koshy case PMC_EV_K8_LS_SEGMENT_REGISTER_LOAD: 1059f263522aSJoseph Koshy __K8SETMASK(lsrl); 1060f263522aSJoseph Koshy break; 1061f263522aSJoseph Koshy case PMC_EV_K8_LS_LOCKED_OPERATION: 1062f263522aSJoseph Koshy __K8SETMASK(llo); 1063f263522aSJoseph Koshy break; 1064f263522aSJoseph Koshy case PMC_EV_K8_DC_REFILL_FROM_L2: 1065f263522aSJoseph Koshy case PMC_EV_K8_DC_REFILL_FROM_SYSTEM: 1066f263522aSJoseph Koshy case PMC_EV_K8_DC_COPYBACK: 1067f263522aSJoseph Koshy __K8SETMASK(dc); 1068f263522aSJoseph Koshy break; 1069f263522aSJoseph Koshy case PMC_EV_K8_DC_ONE_BIT_ECC_ERROR: 1070f263522aSJoseph Koshy __K8SETMASK(dobee); 1071f263522aSJoseph Koshy break; 1072f263522aSJoseph Koshy case PMC_EV_K8_DC_DISPATCHED_PREFETCH_INSTRUCTIONS: 1073f263522aSJoseph Koshy __K8SETMASK(ddpi); 1074f263522aSJoseph Koshy break; 1075f263522aSJoseph Koshy case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS: 1076f263522aSJoseph Koshy __K8SETMASK(dabl); 1077f263522aSJoseph Koshy break; 1078f263522aSJoseph Koshy case PMC_EV_K8_BU_INTERNAL_L2_REQUEST: 1079f263522aSJoseph Koshy __K8SETMASK(bilr); 1080f263522aSJoseph Koshy break; 1081f263522aSJoseph Koshy case PMC_EV_K8_BU_FILL_REQUEST_L2_MISS: 1082f263522aSJoseph Koshy __K8SETMASK(bfrlm); 1083f263522aSJoseph Koshy break; 1084f263522aSJoseph Koshy case PMC_EV_K8_BU_FILL_INTO_L2: 1085f263522aSJoseph Koshy __K8SETMASK(bfil); 1086f263522aSJoseph Koshy break; 1087f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS: 1088f263522aSJoseph Koshy __K8SETMASK(frfi); 1089f263522aSJoseph Koshy break; 1090f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS: 1091f263522aSJoseph Koshy __K8SETMASK(frfdoi); 1092f263522aSJoseph Koshy break; 1093f263522aSJoseph Koshy case PMC_EV_K8_FR_FPU_EXCEPTIONS: 1094f263522aSJoseph Koshy __K8SETMASK(ffe); 1095f263522aSJoseph Koshy break; 1096f263522aSJoseph Koshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_PAGE_ACCESS_EVENT: 1097f263522aSJoseph Koshy __K8SETMASK(nmcpae); 1098f263522aSJoseph Koshy break; 1099f263522aSJoseph Koshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_TURNAROUND: 1100f263522aSJoseph Koshy __K8SETMASK(nmct); 1101f263522aSJoseph Koshy break; 1102f263522aSJoseph Koshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_BYPASS_SATURATION: 1103f263522aSJoseph Koshy __K8SETMASK(nmcbs); 1104f263522aSJoseph Koshy break; 1105f263522aSJoseph Koshy case PMC_EV_K8_NB_SIZED_COMMANDS: 1106f263522aSJoseph Koshy __K8SETMASK(nsc); 1107f263522aSJoseph Koshy break; 1108f263522aSJoseph Koshy case PMC_EV_K8_NB_PROBE_RESULT: 1109f263522aSJoseph Koshy __K8SETMASK(npr); 1110f263522aSJoseph Koshy break; 1111f263522aSJoseph Koshy case PMC_EV_K8_NB_HT_BUS0_BANDWIDTH: 1112f263522aSJoseph Koshy case PMC_EV_K8_NB_HT_BUS1_BANDWIDTH: 1113f263522aSJoseph Koshy case PMC_EV_K8_NB_HT_BUS2_BANDWIDTH: 1114f263522aSJoseph Koshy __K8SETMASK(nhbb); 1115f263522aSJoseph Koshy break; 1116f263522aSJoseph Koshy 1117f263522aSJoseph Koshy default: 1118f263522aSJoseph Koshy break; /* no options defined */ 1119f263522aSJoseph Koshy } 1120f263522aSJoseph Koshy 1121f263522aSJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 1122f263522aSJoseph Koshy if (KWPREFIXMATCH(p, K8_KW_COUNT "=")) { 1123f263522aSJoseph Koshy q = strchr(p, '='); 1124f263522aSJoseph Koshy if (*++q == '\0') /* skip '=' */ 1125aa342b1fSJoseph Koshy return (-1); 1126f263522aSJoseph Koshy 1127f263522aSJoseph Koshy count = strtol(q, &e, 0); 1128f263522aSJoseph Koshy if (e == q || *e != '\0') 1129aa342b1fSJoseph Koshy return (-1); 1130f263522aSJoseph Koshy 1131f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 1132f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config |= 1133f263522aSJoseph Koshy AMD_PMC_TO_COUNTER(count); 1134f263522aSJoseph Koshy 1135f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_EDGE)) { 1136f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1137f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_INV)) { 1138f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 1139f263522aSJoseph Koshy } else if (KWPREFIXMATCH(p, K8_KW_MASK "=")) { 1140f263522aSJoseph Koshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 1141aa342b1fSJoseph Koshy return (-1); 1142f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1143f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_OS)) { 1144f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 1145f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_USR)) { 1146f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 1147f263522aSJoseph Koshy } else 1148aa342b1fSJoseph Koshy return (-1); 1149f263522aSJoseph Koshy } 1150f263522aSJoseph Koshy 1151f263522aSJoseph Koshy /* other post processing */ 1152f263522aSJoseph Koshy switch (pe) { 1153f263522aSJoseph Koshy case PMC_EV_K8_FP_DISPATCHED_FPU_OPS: 1154f263522aSJoseph Koshy case PMC_EV_K8_FP_CYCLES_WITH_NO_FPU_OPS_RETIRED: 1155f263522aSJoseph Koshy case PMC_EV_K8_FP_DISPATCHED_FPU_FAST_FLAG_OPS: 1156f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS: 1157f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS: 1158f263522aSJoseph Koshy case PMC_EV_K8_FR_FPU_EXCEPTIONS: 1159f263522aSJoseph Koshy /* XXX only available in rev B and later */ 1160f263522aSJoseph Koshy break; 1161f263522aSJoseph Koshy case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS: 1162f263522aSJoseph Koshy /* XXX only available in rev C and later */ 1163f263522aSJoseph Koshy break; 1164f263522aSJoseph Koshy case PMC_EV_K8_LS_LOCKED_OPERATION: 1165f263522aSJoseph Koshy /* XXX CPU Rev A,B evmask is to be zero */ 1166f263522aSJoseph Koshy if (evmask & (evmask - 1)) /* > 1 bit set */ 1167aa342b1fSJoseph Koshy return (-1); 1168f263522aSJoseph Koshy if (evmask == 0) { 1169f263522aSJoseph Koshy evmask = 0x01; /* Rev C and later: #instrs */ 1170f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1171f263522aSJoseph Koshy } 1172f263522aSJoseph Koshy break; 1173f263522aSJoseph Koshy default: 1174f263522aSJoseph Koshy if (evmask == 0 && pmask != NULL) { 1175f263522aSJoseph Koshy for (pm = pmask; pm->pm_name; pm++) 1176f263522aSJoseph Koshy evmask |= pm->pm_value; 1177f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1178f263522aSJoseph Koshy } 1179f263522aSJoseph Koshy } 1180f263522aSJoseph Koshy 1181f263522aSJoseph Koshy if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) 1182f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 1183f263522aSJoseph Koshy AMD_PMC_TO_UNITMASK(evmask); 1184f263522aSJoseph Koshy 1185aa342b1fSJoseph Koshy return (0); 1186f263522aSJoseph Koshy } 1187f263522aSJoseph Koshy 1188f263522aSJoseph Koshy #endif 1189f263522aSJoseph Koshy 119086a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 1191f263522aSJoseph Koshy 1192ebccf1e3SJoseph Koshy /* 1193ebccf1e3SJoseph Koshy * Intel P4 PMCs 1194ebccf1e3SJoseph Koshy */ 1195ebccf1e3SJoseph Koshy 1196ebccf1e3SJoseph Koshy static struct pmc_event_alias p4_aliases[] = { 1197d56c5d4bSJoseph Koshy EV_ALIAS("branches", "p4-branch-retired,mask=mmtp+mmtm"), 1198d56c5d4bSJoseph Koshy EV_ALIAS("branch-mispredicts", "p4-mispred-branch-retired"), 1199ebccf1e3SJoseph Koshy EV_ALIAS("cycles", "tsc"), 1200d56c5d4bSJoseph Koshy EV_ALIAS("instructions", 1201d56c5d4bSJoseph Koshy "p4-instr-retired,mask=nbogusntag+nbogustag"), 1202177a2f22SJoseph Koshy EV_ALIAS("unhalted-cycles", "p4-global-power-events"), 1203ebccf1e3SJoseph Koshy EV_ALIAS(NULL, NULL) 1204ebccf1e3SJoseph Koshy }; 1205ebccf1e3SJoseph Koshy 1206ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE "active" 1207ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_ANY "any" 1208ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_BOTH "both" 1209ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_NONE "none" 1210ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_SINGLE "single" 1211ebccf1e3SJoseph Koshy #define P4_KW_BUSREQTYPE "busreqtype" 1212ebccf1e3SJoseph Koshy #define P4_KW_CASCADE "cascade" 1213ebccf1e3SJoseph Koshy #define P4_KW_EDGE "edge" 1214ebccf1e3SJoseph Koshy #define P4_KW_INV "complement" 1215ebccf1e3SJoseph Koshy #define P4_KW_OS "os" 1216ebccf1e3SJoseph Koshy #define P4_KW_MASK "mask" 1217ebccf1e3SJoseph Koshy #define P4_KW_PRECISE "precise" 1218ebccf1e3SJoseph Koshy #define P4_KW_TAG "tag" 1219ebccf1e3SJoseph Koshy #define P4_KW_THRESHOLD "threshold" 1220ebccf1e3SJoseph Koshy #define P4_KW_USR "usr" 1221ebccf1e3SJoseph Koshy 1222ebccf1e3SJoseph Koshy #define __P4MASK(N,V) PMCMASK(N, (1 << (V))) 1223ebccf1e3SJoseph Koshy 1224ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_tcdm[] = { /* tc deliver mode */ 1225ebccf1e3SJoseph Koshy __P4MASK(dd, 0), 1226ebccf1e3SJoseph Koshy __P4MASK(db, 1), 1227ebccf1e3SJoseph Koshy __P4MASK(di, 2), 1228ebccf1e3SJoseph Koshy __P4MASK(bd, 3), 1229ebccf1e3SJoseph Koshy __P4MASK(bb, 4), 1230ebccf1e3SJoseph Koshy __P4MASK(bi, 5), 1231ebccf1e3SJoseph Koshy __P4MASK(id, 6), 1232ebccf1e3SJoseph Koshy __P4MASK(ib, 7), 1233ebccf1e3SJoseph Koshy NULLMASK 1234ebccf1e3SJoseph Koshy }; 1235ebccf1e3SJoseph Koshy 1236ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_bfr[] = { /* bpu fetch request */ 1237ebccf1e3SJoseph Koshy __P4MASK(tcmiss, 0), 1238ebccf1e3SJoseph Koshy NULLMASK, 1239ebccf1e3SJoseph Koshy }; 1240ebccf1e3SJoseph Koshy 1241ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ir[] = { /* itlb reference */ 1242ebccf1e3SJoseph Koshy __P4MASK(hit, 0), 1243ebccf1e3SJoseph Koshy __P4MASK(miss, 1), 1244ebccf1e3SJoseph Koshy __P4MASK(hit-uc, 2), 1245ebccf1e3SJoseph Koshy NULLMASK 1246ebccf1e3SJoseph Koshy }; 1247ebccf1e3SJoseph Koshy 1248ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_memcan[] = { /* memory cancel */ 1249ebccf1e3SJoseph Koshy __P4MASK(st-rb-full, 2), 1250ebccf1e3SJoseph Koshy __P4MASK(64k-conf, 3), 1251ebccf1e3SJoseph Koshy NULLMASK 1252ebccf1e3SJoseph Koshy }; 1253ebccf1e3SJoseph Koshy 1254ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_memcomp[] = { /* memory complete */ 1255ebccf1e3SJoseph Koshy __P4MASK(lsc, 0), 1256ebccf1e3SJoseph Koshy __P4MASK(ssc, 1), 1257ebccf1e3SJoseph Koshy NULLMASK 1258ebccf1e3SJoseph Koshy }; 1259ebccf1e3SJoseph Koshy 1260ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_lpr[] = { /* load port replay */ 1261ebccf1e3SJoseph Koshy __P4MASK(split-ld, 1), 1262ebccf1e3SJoseph Koshy NULLMASK 1263ebccf1e3SJoseph Koshy }; 1264ebccf1e3SJoseph Koshy 1265ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_spr[] = { /* store port replay */ 1266ebccf1e3SJoseph Koshy __P4MASK(split-st, 1), 1267ebccf1e3SJoseph Koshy NULLMASK 1268ebccf1e3SJoseph Koshy }; 1269ebccf1e3SJoseph Koshy 1270ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_mlr[] = { /* mob load replay */ 1271ebccf1e3SJoseph Koshy __P4MASK(no-sta, 1), 1272ebccf1e3SJoseph Koshy __P4MASK(no-std, 3), 1273ebccf1e3SJoseph Koshy __P4MASK(partial-data, 4), 1274ebccf1e3SJoseph Koshy __P4MASK(unalgn-addr, 5), 1275ebccf1e3SJoseph Koshy NULLMASK 1276ebccf1e3SJoseph Koshy }; 1277ebccf1e3SJoseph Koshy 1278ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_pwt[] = { /* page walk type */ 1279ebccf1e3SJoseph Koshy __P4MASK(dtmiss, 0), 1280ebccf1e3SJoseph Koshy __P4MASK(itmiss, 1), 1281ebccf1e3SJoseph Koshy NULLMASK 1282ebccf1e3SJoseph Koshy }; 1283ebccf1e3SJoseph Koshy 1284ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_bcr[] = { /* bsq cache reference */ 1285ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-hits, 0), 1286ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-hite, 1), 1287ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-hitm, 2), 1288ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-hits, 3), 1289ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-hite, 4), 1290ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-hitm, 5), 1291ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-miss, 8), 1292ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-miss, 9), 1293ebccf1e3SJoseph Koshy __P4MASK(wr-2ndl-miss, 10), 1294ebccf1e3SJoseph Koshy NULLMASK 1295ebccf1e3SJoseph Koshy }; 1296ebccf1e3SJoseph Koshy 1297ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ia[] = { /* ioq allocation */ 1298ebccf1e3SJoseph Koshy __P4MASK(all-read, 5), 1299ebccf1e3SJoseph Koshy __P4MASK(all-write, 6), 1300ebccf1e3SJoseph Koshy __P4MASK(mem-uc, 7), 1301ebccf1e3SJoseph Koshy __P4MASK(mem-wc, 8), 1302ebccf1e3SJoseph Koshy __P4MASK(mem-wt, 9), 1303ebccf1e3SJoseph Koshy __P4MASK(mem-wp, 10), 1304ebccf1e3SJoseph Koshy __P4MASK(mem-wb, 11), 1305ebccf1e3SJoseph Koshy __P4MASK(own, 13), 1306ebccf1e3SJoseph Koshy __P4MASK(other, 14), 1307ebccf1e3SJoseph Koshy __P4MASK(prefetch, 15), 1308ebccf1e3SJoseph Koshy NULLMASK 1309ebccf1e3SJoseph Koshy }; 1310ebccf1e3SJoseph Koshy 1311ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_iae[] = { /* ioq active entries */ 1312ebccf1e3SJoseph Koshy __P4MASK(all-read, 5), 1313ebccf1e3SJoseph Koshy __P4MASK(all-write, 6), 1314ebccf1e3SJoseph Koshy __P4MASK(mem-uc, 7), 1315ebccf1e3SJoseph Koshy __P4MASK(mem-wc, 8), 1316ebccf1e3SJoseph Koshy __P4MASK(mem-wt, 9), 1317ebccf1e3SJoseph Koshy __P4MASK(mem-wp, 10), 1318ebccf1e3SJoseph Koshy __P4MASK(mem-wb, 11), 1319ebccf1e3SJoseph Koshy __P4MASK(own, 13), 1320ebccf1e3SJoseph Koshy __P4MASK(other, 14), 1321ebccf1e3SJoseph Koshy __P4MASK(prefetch, 15), 1322ebccf1e3SJoseph Koshy NULLMASK 1323ebccf1e3SJoseph Koshy }; 1324ebccf1e3SJoseph Koshy 1325ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_fda[] = { /* fsb data activity */ 1326ebccf1e3SJoseph Koshy __P4MASK(drdy-drv, 0), 1327ebccf1e3SJoseph Koshy __P4MASK(drdy-own, 1), 1328ebccf1e3SJoseph Koshy __P4MASK(drdy-other, 2), 1329ebccf1e3SJoseph Koshy __P4MASK(dbsy-drv, 3), 1330ebccf1e3SJoseph Koshy __P4MASK(dbsy-own, 4), 1331ebccf1e3SJoseph Koshy __P4MASK(dbsy-other, 5), 1332ebccf1e3SJoseph Koshy NULLMASK 1333ebccf1e3SJoseph Koshy }; 1334ebccf1e3SJoseph Koshy 1335ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ba[] = { /* bsq allocation */ 1336ebccf1e3SJoseph Koshy __P4MASK(req-type0, 0), 1337ebccf1e3SJoseph Koshy __P4MASK(req-type1, 1), 1338ebccf1e3SJoseph Koshy __P4MASK(req-len0, 2), 1339ebccf1e3SJoseph Koshy __P4MASK(req-len1, 3), 1340ebccf1e3SJoseph Koshy __P4MASK(req-io-type, 5), 1341ebccf1e3SJoseph Koshy __P4MASK(req-lock-type, 6), 1342ebccf1e3SJoseph Koshy __P4MASK(req-cache-type, 7), 1343ebccf1e3SJoseph Koshy __P4MASK(req-split-type, 8), 1344ebccf1e3SJoseph Koshy __P4MASK(req-dem-type, 9), 1345ebccf1e3SJoseph Koshy __P4MASK(req-ord-type, 10), 1346ebccf1e3SJoseph Koshy __P4MASK(mem-type0, 11), 1347ebccf1e3SJoseph Koshy __P4MASK(mem-type1, 12), 1348ebccf1e3SJoseph Koshy __P4MASK(mem-type2, 13), 1349ebccf1e3SJoseph Koshy NULLMASK 1350ebccf1e3SJoseph Koshy }; 1351ebccf1e3SJoseph Koshy 1352ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_sia[] = { /* sse input assist */ 1353ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1354ebccf1e3SJoseph Koshy NULLMASK 1355ebccf1e3SJoseph Koshy }; 1356ebccf1e3SJoseph Koshy 1357ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_psu[] = { /* packed sp uop */ 1358ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1359ebccf1e3SJoseph Koshy NULLMASK 1360ebccf1e3SJoseph Koshy }; 1361ebccf1e3SJoseph Koshy 1362ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_pdu[] = { /* packed dp uop */ 1363ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1364ebccf1e3SJoseph Koshy NULLMASK 1365ebccf1e3SJoseph Koshy }; 1366ebccf1e3SJoseph Koshy 1367ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ssu[] = { /* scalar sp uop */ 1368ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1369ebccf1e3SJoseph Koshy NULLMASK 1370ebccf1e3SJoseph Koshy }; 1371ebccf1e3SJoseph Koshy 1372ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_sdu[] = { /* scalar dp uop */ 1373ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1374ebccf1e3SJoseph Koshy NULLMASK 1375ebccf1e3SJoseph Koshy }; 1376ebccf1e3SJoseph Koshy 1377ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_64bmu[] = { /* 64 bit mmx uop */ 1378ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1379ebccf1e3SJoseph Koshy NULLMASK 1380ebccf1e3SJoseph Koshy }; 1381ebccf1e3SJoseph Koshy 1382ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_128bmu[] = { /* 128 bit mmx uop */ 1383ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1384ebccf1e3SJoseph Koshy NULLMASK 1385ebccf1e3SJoseph Koshy }; 1386ebccf1e3SJoseph Koshy 1387ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xfu[] = { /* X87 fp uop */ 1388ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1389ebccf1e3SJoseph Koshy NULLMASK 1390ebccf1e3SJoseph Koshy }; 1391ebccf1e3SJoseph Koshy 1392ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xsmu[] = { /* x87 simd moves uop */ 1393ebccf1e3SJoseph Koshy __P4MASK(allp0, 3), 1394ebccf1e3SJoseph Koshy __P4MASK(allp2, 4), 1395ebccf1e3SJoseph Koshy NULLMASK 1396ebccf1e3SJoseph Koshy }; 1397ebccf1e3SJoseph Koshy 1398ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_gpe[] = { /* global power events */ 1399ebccf1e3SJoseph Koshy __P4MASK(running, 0), 1400ebccf1e3SJoseph Koshy NULLMASK 1401ebccf1e3SJoseph Koshy }; 1402ebccf1e3SJoseph Koshy 1403ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_tmx[] = { /* TC ms xfer */ 1404ebccf1e3SJoseph Koshy __P4MASK(cisc, 0), 1405ebccf1e3SJoseph Koshy NULLMASK 1406ebccf1e3SJoseph Koshy }; 1407ebccf1e3SJoseph Koshy 1408ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_uqw[] = { /* uop queue writes */ 1409ebccf1e3SJoseph Koshy __P4MASK(from-tc-build, 0), 1410ebccf1e3SJoseph Koshy __P4MASK(from-tc-deliver, 1), 1411ebccf1e3SJoseph Koshy __P4MASK(from-rom, 2), 1412ebccf1e3SJoseph Koshy NULLMASK 1413ebccf1e3SJoseph Koshy }; 1414ebccf1e3SJoseph Koshy 1415d56c5d4bSJoseph Koshy static const struct pmc_masks p4_mask_rmbt[] = { 1416d56c5d4bSJoseph Koshy /* retired mispred branch type */ 1417ebccf1e3SJoseph Koshy __P4MASK(conditional, 1), 1418ebccf1e3SJoseph Koshy __P4MASK(call, 2), 1419ebccf1e3SJoseph Koshy __P4MASK(return, 3), 1420ebccf1e3SJoseph Koshy __P4MASK(indirect, 4), 1421ebccf1e3SJoseph Koshy NULLMASK 1422ebccf1e3SJoseph Koshy }; 1423ebccf1e3SJoseph Koshy 1424ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_rbt[] = { /* retired branch type */ 1425ebccf1e3SJoseph Koshy __P4MASK(conditional, 1), 1426ebccf1e3SJoseph Koshy __P4MASK(call, 2), 1427ebccf1e3SJoseph Koshy __P4MASK(retired, 3), 1428ebccf1e3SJoseph Koshy __P4MASK(indirect, 4), 1429ebccf1e3SJoseph Koshy NULLMASK 1430ebccf1e3SJoseph Koshy }; 1431ebccf1e3SJoseph Koshy 1432ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_rs[] = { /* resource stall */ 1433ebccf1e3SJoseph Koshy __P4MASK(sbfull, 5), 1434ebccf1e3SJoseph Koshy NULLMASK 1435ebccf1e3SJoseph Koshy }; 1436ebccf1e3SJoseph Koshy 1437ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_wb[] = { /* WC buffer */ 1438ebccf1e3SJoseph Koshy __P4MASK(wcb-evicts, 0), 1439ebccf1e3SJoseph Koshy __P4MASK(wcb-full-evict, 1), 1440ebccf1e3SJoseph Koshy NULLMASK 1441ebccf1e3SJoseph Koshy }; 1442ebccf1e3SJoseph Koshy 1443ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_fee[] = { /* front end event */ 1444ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1445ebccf1e3SJoseph Koshy __P4MASK(bogus, 1), 1446ebccf1e3SJoseph Koshy NULLMASK 1447ebccf1e3SJoseph Koshy }; 1448ebccf1e3SJoseph Koshy 1449ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ee[] = { /* execution event */ 1450ebccf1e3SJoseph Koshy __P4MASK(nbogus0, 0), 1451ebccf1e3SJoseph Koshy __P4MASK(nbogus1, 1), 1452ebccf1e3SJoseph Koshy __P4MASK(nbogus2, 2), 1453ebccf1e3SJoseph Koshy __P4MASK(nbogus3, 3), 1454ebccf1e3SJoseph Koshy __P4MASK(bogus0, 4), 1455ebccf1e3SJoseph Koshy __P4MASK(bogus1, 5), 1456ebccf1e3SJoseph Koshy __P4MASK(bogus2, 6), 1457ebccf1e3SJoseph Koshy __P4MASK(bogus3, 7), 1458ebccf1e3SJoseph Koshy NULLMASK 1459ebccf1e3SJoseph Koshy }; 1460ebccf1e3SJoseph Koshy 1461ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_re[] = { /* replay event */ 1462ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1463ebccf1e3SJoseph Koshy __P4MASK(bogus, 1), 1464ebccf1e3SJoseph Koshy NULLMASK 1465ebccf1e3SJoseph Koshy }; 1466ebccf1e3SJoseph Koshy 1467ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_insret[] = { /* instr retired */ 1468ebccf1e3SJoseph Koshy __P4MASK(nbogusntag, 0), 1469ebccf1e3SJoseph Koshy __P4MASK(nbogustag, 1), 1470ebccf1e3SJoseph Koshy __P4MASK(bogusntag, 2), 1471ebccf1e3SJoseph Koshy __P4MASK(bogustag, 3), 1472ebccf1e3SJoseph Koshy NULLMASK 1473ebccf1e3SJoseph Koshy }; 1474ebccf1e3SJoseph Koshy 1475ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ur[] = { /* uops retired */ 1476ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1477ebccf1e3SJoseph Koshy __P4MASK(bogus, 1), 1478ebccf1e3SJoseph Koshy NULLMASK 1479ebccf1e3SJoseph Koshy }; 1480ebccf1e3SJoseph Koshy 1481ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ut[] = { /* uop type */ 1482ebccf1e3SJoseph Koshy __P4MASK(tagloads, 1), 1483ebccf1e3SJoseph Koshy __P4MASK(tagstores, 2), 1484ebccf1e3SJoseph Koshy NULLMASK 1485ebccf1e3SJoseph Koshy }; 1486ebccf1e3SJoseph Koshy 1487ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_br[] = { /* branch retired */ 1488ebccf1e3SJoseph Koshy __P4MASK(mmnp, 0), 1489ebccf1e3SJoseph Koshy __P4MASK(mmnm, 1), 1490ebccf1e3SJoseph Koshy __P4MASK(mmtp, 2), 1491ebccf1e3SJoseph Koshy __P4MASK(mmtm, 3), 1492ebccf1e3SJoseph Koshy NULLMASK 1493ebccf1e3SJoseph Koshy }; 1494ebccf1e3SJoseph Koshy 1495ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_mbr[] = { /* mispred branch retired */ 1496ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1497ebccf1e3SJoseph Koshy NULLMASK 1498ebccf1e3SJoseph Koshy }; 1499ebccf1e3SJoseph Koshy 1500ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xa[] = { /* x87 assist */ 1501ebccf1e3SJoseph Koshy __P4MASK(fpsu, 0), 1502ebccf1e3SJoseph Koshy __P4MASK(fpso, 1), 1503ebccf1e3SJoseph Koshy __P4MASK(poao, 2), 1504ebccf1e3SJoseph Koshy __P4MASK(poau, 3), 1505ebccf1e3SJoseph Koshy __P4MASK(prea, 4), 1506ebccf1e3SJoseph Koshy NULLMASK 1507ebccf1e3SJoseph Koshy }; 1508ebccf1e3SJoseph Koshy 1509ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_machclr[] = { /* machine clear */ 1510ebccf1e3SJoseph Koshy __P4MASK(clear, 0), 1511ebccf1e3SJoseph Koshy __P4MASK(moclear, 2), 1512ebccf1e3SJoseph Koshy __P4MASK(smclear, 3), 1513ebccf1e3SJoseph Koshy NULLMASK 1514ebccf1e3SJoseph Koshy }; 1515ebccf1e3SJoseph Koshy 1516ebccf1e3SJoseph Koshy /* P4 event parser */ 1517ebccf1e3SJoseph Koshy static int 1518ebccf1e3SJoseph Koshy p4_allocate_pmc(enum pmc_event pe, char *ctrspec, 1519ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 1520ebccf1e3SJoseph Koshy { 1521ebccf1e3SJoseph Koshy 1522ebccf1e3SJoseph Koshy char *e, *p, *q; 1523ebccf1e3SJoseph Koshy int count, has_tag, has_busreqtype, n; 1524ebccf1e3SJoseph Koshy uint32_t evmask, cccractivemask; 1525ebccf1e3SJoseph Koshy const struct pmc_masks *pm, *pmask; 1526ebccf1e3SJoseph Koshy 1527789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1528f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig = 1529f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 0; 1530ebccf1e3SJoseph Koshy 1531ebccf1e3SJoseph Koshy pmask = NULL; 1532ebccf1e3SJoseph Koshy evmask = 0; 1533ebccf1e3SJoseph Koshy cccractivemask = 0x3; 1534ebccf1e3SJoseph Koshy has_tag = has_busreqtype = 0; 1535ebccf1e3SJoseph Koshy 1536ebccf1e3SJoseph Koshy #define __P4SETMASK(M) do { \ 1537ebccf1e3SJoseph Koshy pmask = p4_mask_##M; \ 1538ebccf1e3SJoseph Koshy } while (0) 1539ebccf1e3SJoseph Koshy 1540ebccf1e3SJoseph Koshy switch (pe) { 1541ebccf1e3SJoseph Koshy case PMC_EV_P4_TC_DELIVER_MODE: 1542ebccf1e3SJoseph Koshy __P4SETMASK(tcdm); 1543ebccf1e3SJoseph Koshy break; 1544ebccf1e3SJoseph Koshy case PMC_EV_P4_BPU_FETCH_REQUEST: 1545ebccf1e3SJoseph Koshy __P4SETMASK(bfr); 1546ebccf1e3SJoseph Koshy break; 1547ebccf1e3SJoseph Koshy case PMC_EV_P4_ITLB_REFERENCE: 1548ebccf1e3SJoseph Koshy __P4SETMASK(ir); 1549ebccf1e3SJoseph Koshy break; 1550ebccf1e3SJoseph Koshy case PMC_EV_P4_MEMORY_CANCEL: 1551ebccf1e3SJoseph Koshy __P4SETMASK(memcan); 1552ebccf1e3SJoseph Koshy break; 1553ebccf1e3SJoseph Koshy case PMC_EV_P4_MEMORY_COMPLETE: 1554ebccf1e3SJoseph Koshy __P4SETMASK(memcomp); 1555ebccf1e3SJoseph Koshy break; 1556ebccf1e3SJoseph Koshy case PMC_EV_P4_LOAD_PORT_REPLAY: 1557ebccf1e3SJoseph Koshy __P4SETMASK(lpr); 1558ebccf1e3SJoseph Koshy break; 1559ebccf1e3SJoseph Koshy case PMC_EV_P4_STORE_PORT_REPLAY: 1560ebccf1e3SJoseph Koshy __P4SETMASK(spr); 1561ebccf1e3SJoseph Koshy break; 1562ebccf1e3SJoseph Koshy case PMC_EV_P4_MOB_LOAD_REPLAY: 1563ebccf1e3SJoseph Koshy __P4SETMASK(mlr); 1564ebccf1e3SJoseph Koshy break; 1565ebccf1e3SJoseph Koshy case PMC_EV_P4_PAGE_WALK_TYPE: 1566ebccf1e3SJoseph Koshy __P4SETMASK(pwt); 1567ebccf1e3SJoseph Koshy break; 1568ebccf1e3SJoseph Koshy case PMC_EV_P4_BSQ_CACHE_REFERENCE: 1569ebccf1e3SJoseph Koshy __P4SETMASK(bcr); 1570ebccf1e3SJoseph Koshy break; 1571ebccf1e3SJoseph Koshy case PMC_EV_P4_IOQ_ALLOCATION: 1572ebccf1e3SJoseph Koshy __P4SETMASK(ia); 1573ebccf1e3SJoseph Koshy has_busreqtype = 1; 1574ebccf1e3SJoseph Koshy break; 1575ebccf1e3SJoseph Koshy case PMC_EV_P4_IOQ_ACTIVE_ENTRIES: 1576ebccf1e3SJoseph Koshy __P4SETMASK(iae); 1577ebccf1e3SJoseph Koshy has_busreqtype = 1; 1578ebccf1e3SJoseph Koshy break; 1579ebccf1e3SJoseph Koshy case PMC_EV_P4_FSB_DATA_ACTIVITY: 1580ebccf1e3SJoseph Koshy __P4SETMASK(fda); 1581ebccf1e3SJoseph Koshy break; 1582ebccf1e3SJoseph Koshy case PMC_EV_P4_BSQ_ALLOCATION: 1583ebccf1e3SJoseph Koshy __P4SETMASK(ba); 1584ebccf1e3SJoseph Koshy break; 1585ebccf1e3SJoseph Koshy case PMC_EV_P4_SSE_INPUT_ASSIST: 1586ebccf1e3SJoseph Koshy __P4SETMASK(sia); 1587ebccf1e3SJoseph Koshy break; 1588ebccf1e3SJoseph Koshy case PMC_EV_P4_PACKED_SP_UOP: 1589ebccf1e3SJoseph Koshy __P4SETMASK(psu); 1590ebccf1e3SJoseph Koshy break; 1591ebccf1e3SJoseph Koshy case PMC_EV_P4_PACKED_DP_UOP: 1592ebccf1e3SJoseph Koshy __P4SETMASK(pdu); 1593ebccf1e3SJoseph Koshy break; 1594ebccf1e3SJoseph Koshy case PMC_EV_P4_SCALAR_SP_UOP: 1595ebccf1e3SJoseph Koshy __P4SETMASK(ssu); 1596ebccf1e3SJoseph Koshy break; 1597ebccf1e3SJoseph Koshy case PMC_EV_P4_SCALAR_DP_UOP: 1598ebccf1e3SJoseph Koshy __P4SETMASK(sdu); 1599ebccf1e3SJoseph Koshy break; 1600ebccf1e3SJoseph Koshy case PMC_EV_P4_64BIT_MMX_UOP: 1601ebccf1e3SJoseph Koshy __P4SETMASK(64bmu); 1602ebccf1e3SJoseph Koshy break; 1603ebccf1e3SJoseph Koshy case PMC_EV_P4_128BIT_MMX_UOP: 1604ebccf1e3SJoseph Koshy __P4SETMASK(128bmu); 1605ebccf1e3SJoseph Koshy break; 1606ebccf1e3SJoseph Koshy case PMC_EV_P4_X87_FP_UOP: 1607ebccf1e3SJoseph Koshy __P4SETMASK(xfu); 1608ebccf1e3SJoseph Koshy break; 1609ebccf1e3SJoseph Koshy case PMC_EV_P4_X87_SIMD_MOVES_UOP: 1610ebccf1e3SJoseph Koshy __P4SETMASK(xsmu); 1611ebccf1e3SJoseph Koshy break; 1612ebccf1e3SJoseph Koshy case PMC_EV_P4_GLOBAL_POWER_EVENTS: 1613ebccf1e3SJoseph Koshy __P4SETMASK(gpe); 1614ebccf1e3SJoseph Koshy break; 1615ebccf1e3SJoseph Koshy case PMC_EV_P4_TC_MS_XFER: 1616ebccf1e3SJoseph Koshy __P4SETMASK(tmx); 1617ebccf1e3SJoseph Koshy break; 1618ebccf1e3SJoseph Koshy case PMC_EV_P4_UOP_QUEUE_WRITES: 1619ebccf1e3SJoseph Koshy __P4SETMASK(uqw); 1620ebccf1e3SJoseph Koshy break; 1621ebccf1e3SJoseph Koshy case PMC_EV_P4_RETIRED_MISPRED_BRANCH_TYPE: 1622ebccf1e3SJoseph Koshy __P4SETMASK(rmbt); 1623ebccf1e3SJoseph Koshy break; 1624ebccf1e3SJoseph Koshy case PMC_EV_P4_RETIRED_BRANCH_TYPE: 1625ebccf1e3SJoseph Koshy __P4SETMASK(rbt); 1626ebccf1e3SJoseph Koshy break; 1627ebccf1e3SJoseph Koshy case PMC_EV_P4_RESOURCE_STALL: 1628ebccf1e3SJoseph Koshy __P4SETMASK(rs); 1629ebccf1e3SJoseph Koshy break; 1630ebccf1e3SJoseph Koshy case PMC_EV_P4_WC_BUFFER: 1631ebccf1e3SJoseph Koshy __P4SETMASK(wb); 1632ebccf1e3SJoseph Koshy break; 1633ebccf1e3SJoseph Koshy case PMC_EV_P4_BSQ_ACTIVE_ENTRIES: 1634ebccf1e3SJoseph Koshy case PMC_EV_P4_B2B_CYCLES: 1635ebccf1e3SJoseph Koshy case PMC_EV_P4_BNR: 1636ebccf1e3SJoseph Koshy case PMC_EV_P4_SNOOP: 1637ebccf1e3SJoseph Koshy case PMC_EV_P4_RESPONSE: 1638ebccf1e3SJoseph Koshy break; 1639ebccf1e3SJoseph Koshy case PMC_EV_P4_FRONT_END_EVENT: 1640ebccf1e3SJoseph Koshy __P4SETMASK(fee); 1641ebccf1e3SJoseph Koshy break; 1642ebccf1e3SJoseph Koshy case PMC_EV_P4_EXECUTION_EVENT: 1643ebccf1e3SJoseph Koshy __P4SETMASK(ee); 1644ebccf1e3SJoseph Koshy break; 1645ebccf1e3SJoseph Koshy case PMC_EV_P4_REPLAY_EVENT: 1646ebccf1e3SJoseph Koshy __P4SETMASK(re); 1647ebccf1e3SJoseph Koshy break; 1648ebccf1e3SJoseph Koshy case PMC_EV_P4_INSTR_RETIRED: 1649ebccf1e3SJoseph Koshy __P4SETMASK(insret); 1650ebccf1e3SJoseph Koshy break; 1651ebccf1e3SJoseph Koshy case PMC_EV_P4_UOPS_RETIRED: 1652ebccf1e3SJoseph Koshy __P4SETMASK(ur); 1653ebccf1e3SJoseph Koshy break; 1654ebccf1e3SJoseph Koshy case PMC_EV_P4_UOP_TYPE: 1655ebccf1e3SJoseph Koshy __P4SETMASK(ut); 1656ebccf1e3SJoseph Koshy break; 1657ebccf1e3SJoseph Koshy case PMC_EV_P4_BRANCH_RETIRED: 1658ebccf1e3SJoseph Koshy __P4SETMASK(br); 1659ebccf1e3SJoseph Koshy break; 1660ebccf1e3SJoseph Koshy case PMC_EV_P4_MISPRED_BRANCH_RETIRED: 1661ebccf1e3SJoseph Koshy __P4SETMASK(mbr); 1662ebccf1e3SJoseph Koshy break; 1663ebccf1e3SJoseph Koshy case PMC_EV_P4_X87_ASSIST: 1664ebccf1e3SJoseph Koshy __P4SETMASK(xa); 1665ebccf1e3SJoseph Koshy break; 1666ebccf1e3SJoseph Koshy case PMC_EV_P4_MACHINE_CLEAR: 1667ebccf1e3SJoseph Koshy __P4SETMASK(machclr); 1668ebccf1e3SJoseph Koshy break; 1669ebccf1e3SJoseph Koshy default: 1670aa342b1fSJoseph Koshy return (-1); 1671ebccf1e3SJoseph Koshy } 1672ebccf1e3SJoseph Koshy 1673ebccf1e3SJoseph Koshy /* process additional flags */ 1674ebccf1e3SJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 1675ebccf1e3SJoseph Koshy if (KWPREFIXMATCH(p, P4_KW_ACTIVE)) { 1676ebccf1e3SJoseph Koshy q = strchr(p, '='); 1677ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1678aa342b1fSJoseph Koshy return (-1); 1679ebccf1e3SJoseph Koshy 1680789140c0SJoseph Koshy if (strcasecmp(q, P4_KW_ACTIVE_NONE) == 0) 1681ebccf1e3SJoseph Koshy cccractivemask = 0x0; 1682789140c0SJoseph Koshy else if (strcasecmp(q, P4_KW_ACTIVE_SINGLE) == 0) 1683ebccf1e3SJoseph Koshy cccractivemask = 0x1; 1684789140c0SJoseph Koshy else if (strcasecmp(q, P4_KW_ACTIVE_BOTH) == 0) 1685ebccf1e3SJoseph Koshy cccractivemask = 0x2; 1686789140c0SJoseph Koshy else if (strcasecmp(q, P4_KW_ACTIVE_ANY) == 0) 1687ebccf1e3SJoseph Koshy cccractivemask = 0x3; 1688ebccf1e3SJoseph Koshy else 1689aa342b1fSJoseph Koshy return (-1); 1690ebccf1e3SJoseph Koshy 1691ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, P4_KW_BUSREQTYPE)) { 1692ebccf1e3SJoseph Koshy if (has_busreqtype == 0) 1693aa342b1fSJoseph Koshy return (-1); 1694ebccf1e3SJoseph Koshy 1695ebccf1e3SJoseph Koshy q = strchr(p, '='); 1696ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1697aa342b1fSJoseph Koshy return (-1); 1698ebccf1e3SJoseph Koshy 1699ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 1700ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 1701aa342b1fSJoseph Koshy return (-1); 1702ebccf1e3SJoseph Koshy evmask = (evmask & ~0x1F) | (count & 0x1F); 1703ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P4_KW_CASCADE)) 1704ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_CASCADE; 1705ebccf1e3SJoseph Koshy else if (KWMATCH(p, P4_KW_EDGE)) 1706ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1707ebccf1e3SJoseph Koshy else if (KWMATCH(p, P4_KW_INV)) 1708ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 1709ebccf1e3SJoseph Koshy else if (KWPREFIXMATCH(p, P4_KW_MASK "=")) { 1710ebccf1e3SJoseph Koshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 1711aa342b1fSJoseph Koshy return (-1); 1712ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1713ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P4_KW_OS)) 1714ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 1715ebccf1e3SJoseph Koshy else if (KWMATCH(p, P4_KW_PRECISE)) 1716ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_PRECISE; 1717ebccf1e3SJoseph Koshy else if (KWPREFIXMATCH(p, P4_KW_TAG "=")) { 1718ebccf1e3SJoseph Koshy if (has_tag == 0) 1719aa342b1fSJoseph Koshy return (-1); 1720ebccf1e3SJoseph Koshy 1721ebccf1e3SJoseph Koshy q = strchr(p, '='); 1722ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1723aa342b1fSJoseph Koshy return (-1); 1724ebccf1e3SJoseph Koshy 1725ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 1726ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 1727aa342b1fSJoseph Koshy return (-1); 1728ebccf1e3SJoseph Koshy 1729ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_TAGGING; 1730f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig |= 1731ebccf1e3SJoseph Koshy P4_ESCR_TO_TAG_VALUE(count); 1732ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, P4_KW_THRESHOLD "=")) { 1733ebccf1e3SJoseph Koshy q = strchr(p, '='); 1734ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1735aa342b1fSJoseph Koshy return (-1); 1736ebccf1e3SJoseph Koshy 1737ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 1738ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 1739aa342b1fSJoseph Koshy return (-1); 1740ebccf1e3SJoseph Koshy 1741ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 1742f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig &= 1743f263522aSJoseph Koshy ~P4_CCCR_THRESHOLD_MASK; 1744f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |= 1745f263522aSJoseph Koshy P4_CCCR_TO_THRESHOLD(count); 1746ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P4_KW_USR)) 1747ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 1748ebccf1e3SJoseph Koshy else 1749aa342b1fSJoseph Koshy return (-1); 1750ebccf1e3SJoseph Koshy } 1751ebccf1e3SJoseph Koshy 1752ebccf1e3SJoseph Koshy /* other post processing */ 1753ebccf1e3SJoseph Koshy if (pe == PMC_EV_P4_IOQ_ALLOCATION || 1754ebccf1e3SJoseph Koshy pe == PMC_EV_P4_FSB_DATA_ACTIVITY || 1755ebccf1e3SJoseph Koshy pe == PMC_EV_P4_BSQ_ALLOCATION) 1756ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1757ebccf1e3SJoseph Koshy 1758ebccf1e3SJoseph Koshy /* fill in thread activity mask */ 1759f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |= 1760ebccf1e3SJoseph Koshy P4_CCCR_TO_ACTIVE_THREAD(cccractivemask); 1761ebccf1e3SJoseph Koshy 1762ebccf1e3SJoseph Koshy if (evmask) 1763ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1764ebccf1e3SJoseph Koshy 1765ebccf1e3SJoseph Koshy switch (pe) { 1766ebccf1e3SJoseph Koshy case PMC_EV_P4_FSB_DATA_ACTIVITY: 1767ebccf1e3SJoseph Koshy if ((evmask & 0x06) == 0x06 || 1768ebccf1e3SJoseph Koshy (evmask & 0x18) == 0x18) 1769aa342b1fSJoseph Koshy return (-1); /* can't have own+other bits together */ 1770ebccf1e3SJoseph Koshy if (evmask == 0) /* default:drdy-{drv,own}+dbsy{drv,own} */ 1771ebccf1e3SJoseph Koshy evmask = 0x1D; 1772ebccf1e3SJoseph Koshy break; 1773ebccf1e3SJoseph Koshy case PMC_EV_P4_MACHINE_CLEAR: 1774ebccf1e3SJoseph Koshy /* only one bit is allowed to be set */ 1775ebccf1e3SJoseph Koshy if ((evmask & (evmask - 1)) != 0) 1776aa342b1fSJoseph Koshy return (-1); 1777ebccf1e3SJoseph Koshy if (evmask == 0) { 1778ebccf1e3SJoseph Koshy evmask = 0x1; /* 'CLEAR' */ 1779ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1780ebccf1e3SJoseph Koshy } 1781ebccf1e3SJoseph Koshy break; 1782ebccf1e3SJoseph Koshy default: 1783ebccf1e3SJoseph Koshy if (evmask == 0 && pmask) { 1784ebccf1e3SJoseph Koshy for (pm = pmask; pm->pm_name; pm++) 1785ebccf1e3SJoseph Koshy evmask |= pm->pm_value; 1786ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1787ebccf1e3SJoseph Koshy } 1788ebccf1e3SJoseph Koshy } 1789ebccf1e3SJoseph Koshy 1790f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 1791f263522aSJoseph Koshy P4_ESCR_TO_EVENT_MASK(evmask); 1792ebccf1e3SJoseph Koshy 1793aa342b1fSJoseph Koshy return (0); 1794ebccf1e3SJoseph Koshy } 1795ebccf1e3SJoseph Koshy 179686a65549SJoseph Koshy #endif 179786a65549SJoseph Koshy 179886a65549SJoseph Koshy #if defined(__i386__) 179986a65549SJoseph Koshy 1800ebccf1e3SJoseph Koshy /* 1801f263522aSJoseph Koshy * Pentium style PMCs 1802f263522aSJoseph Koshy */ 1803f263522aSJoseph Koshy 1804f263522aSJoseph Koshy static struct pmc_event_alias p5_aliases[] = { 18050b9b757dSJoseph Koshy EV_ALIAS("branches", "p5-taken-branches"), 1806f263522aSJoseph Koshy EV_ALIAS("cycles", "tsc"), 18070b9b757dSJoseph Koshy EV_ALIAS("dc-misses", "p5-data-read-miss-or-write-miss"), 18080b9b757dSJoseph Koshy EV_ALIAS("ic-misses", "p5-code-cache-miss"), 18090b9b757dSJoseph Koshy EV_ALIAS("instructions", "p5-instructions-executed"), 18100b9b757dSJoseph Koshy EV_ALIAS("interrupts", "p5-hardware-interrupts"), 18110b9b757dSJoseph Koshy EV_ALIAS("unhalted-cycles", 18120b9b757dSJoseph Koshy "p5-number-of-cycles-not-in-halt-state"), 1813f263522aSJoseph Koshy EV_ALIAS(NULL, NULL) 1814f263522aSJoseph Koshy }; 1815f263522aSJoseph Koshy 1816f263522aSJoseph Koshy static int 1817f263522aSJoseph Koshy p5_allocate_pmc(enum pmc_event pe, char *ctrspec, 1818f263522aSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 1819f263522aSJoseph Koshy { 1820aa342b1fSJoseph Koshy return (-1 || pe || ctrspec || pmc_config); /* shut up gcc */ 1821f263522aSJoseph Koshy } 1822f263522aSJoseph Koshy 1823f263522aSJoseph Koshy /* 1824ebccf1e3SJoseph Koshy * Pentium Pro style PMCs. These PMCs are found in Pentium II, Pentium III, 1825ebccf1e3SJoseph Koshy * and Pentium M CPUs. 1826ebccf1e3SJoseph Koshy */ 1827ebccf1e3SJoseph Koshy 1828ebccf1e3SJoseph Koshy static struct pmc_event_alias p6_aliases[] = { 1829ebccf1e3SJoseph Koshy EV_ALIAS("branches", "p6-br-inst-retired"), 1830ebccf1e3SJoseph Koshy EV_ALIAS("branch-mispredicts", "p6-br-miss-pred-retired"), 1831ebccf1e3SJoseph Koshy EV_ALIAS("cycles", "tsc"), 1832d56c5d4bSJoseph Koshy EV_ALIAS("dc-misses", "p6-dcu-lines-in"), 183373e2d811SJoseph Koshy EV_ALIAS("ic-misses", "p6-ifu-fetch-miss"), 1834ebccf1e3SJoseph Koshy EV_ALIAS("instructions", "p6-inst-retired"), 1835ebccf1e3SJoseph Koshy EV_ALIAS("interrupts", "p6-hw-int-rx"), 1836177a2f22SJoseph Koshy EV_ALIAS("unhalted-cycles", "p6-cpu-clk-unhalted"), 1837ebccf1e3SJoseph Koshy EV_ALIAS(NULL, NULL) 1838ebccf1e3SJoseph Koshy }; 1839ebccf1e3SJoseph Koshy 1840ebccf1e3SJoseph Koshy #define P6_KW_CMASK "cmask" 1841ebccf1e3SJoseph Koshy #define P6_KW_EDGE "edge" 1842ebccf1e3SJoseph Koshy #define P6_KW_INV "inv" 1843ebccf1e3SJoseph Koshy #define P6_KW_OS "os" 1844ebccf1e3SJoseph Koshy #define P6_KW_UMASK "umask" 1845ebccf1e3SJoseph Koshy #define P6_KW_USR "usr" 1846ebccf1e3SJoseph Koshy 1847ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mesi[] = { 1848ebccf1e3SJoseph Koshy PMCMASK(m, 0x01), 1849ebccf1e3SJoseph Koshy PMCMASK(e, 0x02), 1850ebccf1e3SJoseph Koshy PMCMASK(s, 0x04), 1851ebccf1e3SJoseph Koshy PMCMASK(i, 0x08), 1852ebccf1e3SJoseph Koshy NULLMASK 1853ebccf1e3SJoseph Koshy }; 1854ebccf1e3SJoseph Koshy 1855ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mesihw[] = { 1856ebccf1e3SJoseph Koshy PMCMASK(m, 0x01), 1857ebccf1e3SJoseph Koshy PMCMASK(e, 0x02), 1858ebccf1e3SJoseph Koshy PMCMASK(s, 0x04), 1859ebccf1e3SJoseph Koshy PMCMASK(i, 0x08), 1860ebccf1e3SJoseph Koshy PMCMASK(nonhw, 0x00), 1861ebccf1e3SJoseph Koshy PMCMASK(hw, 0x10), 1862ebccf1e3SJoseph Koshy PMCMASK(both, 0x30), 1863ebccf1e3SJoseph Koshy NULLMASK 1864ebccf1e3SJoseph Koshy }; 1865ebccf1e3SJoseph Koshy 1866ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_hw[] = { 1867ebccf1e3SJoseph Koshy PMCMASK(nonhw, 0x00), 1868ebccf1e3SJoseph Koshy PMCMASK(hw, 0x10), 1869ebccf1e3SJoseph Koshy PMCMASK(both, 0x30), 1870ebccf1e3SJoseph Koshy NULLMASK 1871ebccf1e3SJoseph Koshy }; 1872ebccf1e3SJoseph Koshy 1873ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_any[] = { 1874ebccf1e3SJoseph Koshy PMCMASK(self, 0x00), 1875ebccf1e3SJoseph Koshy PMCMASK(any, 0x20), 1876ebccf1e3SJoseph Koshy NULLMASK 1877ebccf1e3SJoseph Koshy }; 1878ebccf1e3SJoseph Koshy 1879ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_ekp[] = { 1880ebccf1e3SJoseph Koshy PMCMASK(nta, 0x00), 1881ebccf1e3SJoseph Koshy PMCMASK(t1, 0x01), 1882ebccf1e3SJoseph Koshy PMCMASK(t2, 0x02), 1883ebccf1e3SJoseph Koshy PMCMASK(wos, 0x03), 1884ebccf1e3SJoseph Koshy NULLMASK 1885ebccf1e3SJoseph Koshy }; 1886ebccf1e3SJoseph Koshy 1887ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_pps[] = { 1888ebccf1e3SJoseph Koshy PMCMASK(packed-and-scalar, 0x00), 1889ebccf1e3SJoseph Koshy PMCMASK(scalar, 0x01), 1890ebccf1e3SJoseph Koshy NULLMASK 1891ebccf1e3SJoseph Koshy }; 1892ebccf1e3SJoseph Koshy 1893ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mite[] = { 1894ebccf1e3SJoseph Koshy PMCMASK(packed-multiply, 0x01), 1895ebccf1e3SJoseph Koshy PMCMASK(packed-shift, 0x02), 1896ebccf1e3SJoseph Koshy PMCMASK(pack, 0x04), 1897ebccf1e3SJoseph Koshy PMCMASK(unpack, 0x08), 1898ebccf1e3SJoseph Koshy PMCMASK(packed-logical, 0x10), 1899ebccf1e3SJoseph Koshy PMCMASK(packed-arithmetic, 0x20), 1900ebccf1e3SJoseph Koshy NULLMASK 1901ebccf1e3SJoseph Koshy }; 1902ebccf1e3SJoseph Koshy 1903ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_fmt[] = { 1904ebccf1e3SJoseph Koshy PMCMASK(mmxtofp, 0x00), 1905ebccf1e3SJoseph Koshy PMCMASK(fptommx, 0x01), 1906ebccf1e3SJoseph Koshy NULLMASK 1907ebccf1e3SJoseph Koshy }; 1908ebccf1e3SJoseph Koshy 1909ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_sr[] = { 1910ebccf1e3SJoseph Koshy PMCMASK(es, 0x01), 1911ebccf1e3SJoseph Koshy PMCMASK(ds, 0x02), 1912ebccf1e3SJoseph Koshy PMCMASK(fs, 0x04), 1913ebccf1e3SJoseph Koshy PMCMASK(gs, 0x08), 1914ebccf1e3SJoseph Koshy NULLMASK 1915ebccf1e3SJoseph Koshy }; 1916ebccf1e3SJoseph Koshy 1917ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_eet[] = { 1918ebccf1e3SJoseph Koshy PMCMASK(all, 0x00), 1919ebccf1e3SJoseph Koshy PMCMASK(freq, 0x02), 1920ebccf1e3SJoseph Koshy NULLMASK 1921ebccf1e3SJoseph Koshy }; 1922ebccf1e3SJoseph Koshy 1923ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_efur[] = { 1924ebccf1e3SJoseph Koshy PMCMASK(all, 0x00), 1925ebccf1e3SJoseph Koshy PMCMASK(loadop, 0x01), 1926ebccf1e3SJoseph Koshy PMCMASK(stdsta, 0x02), 1927ebccf1e3SJoseph Koshy NULLMASK 1928ebccf1e3SJoseph Koshy }; 1929ebccf1e3SJoseph Koshy 1930ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_essir[] = { 1931ebccf1e3SJoseph Koshy PMCMASK(sse-packed-single, 0x00), 1932ebccf1e3SJoseph Koshy PMCMASK(sse-packed-single-scalar-single, 0x01), 1933ebccf1e3SJoseph Koshy PMCMASK(sse2-packed-double, 0x02), 1934ebccf1e3SJoseph Koshy PMCMASK(sse2-scalar-double, 0x03), 1935ebccf1e3SJoseph Koshy NULLMASK 1936ebccf1e3SJoseph Koshy }; 1937ebccf1e3SJoseph Koshy 1938ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_esscir[] = { 1939ebccf1e3SJoseph Koshy PMCMASK(sse-packed-single, 0x00), 1940ebccf1e3SJoseph Koshy PMCMASK(sse-scalar-single, 0x01), 1941ebccf1e3SJoseph Koshy PMCMASK(sse2-packed-double, 0x02), 1942ebccf1e3SJoseph Koshy PMCMASK(sse2-scalar-double, 0x03), 1943ebccf1e3SJoseph Koshy NULLMASK 1944ebccf1e3SJoseph Koshy }; 1945ebccf1e3SJoseph Koshy 1946ebccf1e3SJoseph Koshy /* P6 event parser */ 1947ebccf1e3SJoseph Koshy static int 1948ebccf1e3SJoseph Koshy p6_allocate_pmc(enum pmc_event pe, char *ctrspec, 1949ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 1950ebccf1e3SJoseph Koshy { 1951ebccf1e3SJoseph Koshy char *e, *p, *q; 1952ebccf1e3SJoseph Koshy uint32_t evmask; 1953ebccf1e3SJoseph Koshy int count, n; 1954ebccf1e3SJoseph Koshy const struct pmc_masks *pm, *pmask; 1955ebccf1e3SJoseph Koshy 1956789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1957f263522aSJoseph Koshy pmc_config->pm_md.pm_ppro.pm_ppro_config = 0; 1958ebccf1e3SJoseph Koshy 1959ebccf1e3SJoseph Koshy evmask = 0; 1960ebccf1e3SJoseph Koshy 1961ebccf1e3SJoseph Koshy #define P6MASKSET(M) pmask = p6_mask_ ## M 1962ebccf1e3SJoseph Koshy 1963ebccf1e3SJoseph Koshy switch(pe) { 1964ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_IFETCH: P6MASKSET(mesi); break; 1965ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_LD: P6MASKSET(mesi); break; 1966ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_ST: P6MASKSET(mesi); break; 1967ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_RQSTS: P6MASKSET(mesi); break; 1968ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_DRDY_CLOCKS: 1969ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_LOCK_CLOCKS: 1970ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BRD: 1971ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_RFO: 1972ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_WB: 1973ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_IFETCH: 1974ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_INVAL: 1975ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_PWR: 1976ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_P: 1977ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_IO: 1978ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_DEF: 1979ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BURST: 1980ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_ANY: 1981ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_MEM: 1982ebccf1e3SJoseph Koshy P6MASKSET(any); break; 1983ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED: 1984ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_MISS: 1985ebccf1e3SJoseph Koshy P6MASKSET(ekp); break; 1986ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_INST_RETIRED: 1987ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_COMP_INST_RET: 1988ebccf1e3SJoseph Koshy P6MASKSET(pps); break; 1989ebccf1e3SJoseph Koshy case PMC_EV_P6_MMX_INSTR_TYPE_EXEC: 1990ebccf1e3SJoseph Koshy P6MASKSET(mite); break; 1991ebccf1e3SJoseph Koshy case PMC_EV_P6_FP_MMX_TRANS: 1992ebccf1e3SJoseph Koshy P6MASKSET(fmt); break; 1993ebccf1e3SJoseph Koshy case PMC_EV_P6_SEG_RENAME_STALLS: 1994ebccf1e3SJoseph Koshy case PMC_EV_P6_SEG_REG_RENAMES: 1995ebccf1e3SJoseph Koshy P6MASKSET(sr); break; 1996ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_EST_TRANS: 1997ebccf1e3SJoseph Koshy P6MASKSET(eet); break; 1998ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_FUSED_UOPS_RET: 1999ebccf1e3SJoseph Koshy P6MASKSET(efur); break; 2000ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED: 2001ebccf1e3SJoseph Koshy P6MASKSET(essir); break; 2002ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED: 2003ebccf1e3SJoseph Koshy P6MASKSET(esscir); break; 2004ebccf1e3SJoseph Koshy default: 2005ebccf1e3SJoseph Koshy pmask = NULL; 2006ebccf1e3SJoseph Koshy break; 2007ebccf1e3SJoseph Koshy } 2008ebccf1e3SJoseph Koshy 2009ebccf1e3SJoseph Koshy /* Pentium M PMCs have a few events with different semantics */ 2010ebccf1e3SJoseph Koshy if (cpu_info.pm_cputype == PMC_CPU_INTEL_PM) { 2011ebccf1e3SJoseph Koshy if (pe == PMC_EV_P6_L2_LD || 2012ebccf1e3SJoseph Koshy pe == PMC_EV_P6_L2_LINES_IN || 2013ebccf1e3SJoseph Koshy pe == PMC_EV_P6_L2_LINES_OUT) 2014ebccf1e3SJoseph Koshy P6MASKSET(mesihw); 2015ebccf1e3SJoseph Koshy else if (pe == PMC_EV_P6_L2_M_LINES_OUTM) 2016ebccf1e3SJoseph Koshy P6MASKSET(hw); 2017ebccf1e3SJoseph Koshy } 2018ebccf1e3SJoseph Koshy 2019ebccf1e3SJoseph Koshy /* Parse additional modifiers if present */ 2020ebccf1e3SJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 2021ebccf1e3SJoseph Koshy if (KWPREFIXMATCH(p, P6_KW_CMASK "=")) { 2022ebccf1e3SJoseph Koshy q = strchr(p, '='); 2023ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 2024aa342b1fSJoseph Koshy return (-1); 2025ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 2026ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 2027aa342b1fSJoseph Koshy return (-1); 2028ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 2029f263522aSJoseph Koshy pmc_config->pm_md.pm_ppro.pm_ppro_config |= 2030f263522aSJoseph Koshy P6_EVSEL_TO_CMASK(count); 2031ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_EDGE)) { 2032ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 2033ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_INV)) { 2034ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 2035ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_OS)) { 2036ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2037ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, P6_KW_UMASK "=")) { 2038ebccf1e3SJoseph Koshy evmask = 0; 2039ebccf1e3SJoseph Koshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 2040aa342b1fSJoseph Koshy return (-1); 2041ebccf1e3SJoseph Koshy if ((pe == PMC_EV_P6_BUS_DRDY_CLOCKS || 2042ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_LOCK_CLOCKS || 2043ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_BRD || 2044ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_RFO || 2045ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_IFETCH || 2046ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_INVAL || 2047ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_PWR || 2048ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_DEF || 2049ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_BURST || 2050ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_ANY || 2051ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_MEM || 2052ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRANS_IO || 2053ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRANS_P || 2054ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRANS_WB || 2055ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_EST_TRANS || 2056ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_FUSED_UOPS_RET || 2057ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_COMP_INST_RET || 2058ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_INST_RETIRED || 2059ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_PREF_DISPATCHED || 2060ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_PREF_MISS || 2061ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED || 2062ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED || 2063ebccf1e3SJoseph Koshy pe == PMC_EV_P6_FP_MMX_TRANS) 2064aa342b1fSJoseph Koshy && (n > 1)) /* Only one mask keyword is allowed. */ 2065aa342b1fSJoseph Koshy return (-1); 2066ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2067ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_USR)) { 2068ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 2069ebccf1e3SJoseph Koshy } else 2070aa342b1fSJoseph Koshy return (-1); 2071ebccf1e3SJoseph Koshy } 2072ebccf1e3SJoseph Koshy 2073ebccf1e3SJoseph Koshy /* post processing */ 2074ebccf1e3SJoseph Koshy switch (pe) { 2075ebccf1e3SJoseph Koshy 2076ebccf1e3SJoseph Koshy /* 2077ebccf1e3SJoseph Koshy * The following events default to an evmask of 0 2078ebccf1e3SJoseph Koshy */ 2079ebccf1e3SJoseph Koshy 2080ebccf1e3SJoseph Koshy /* default => 'self' */ 2081ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_DRDY_CLOCKS: 2082ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_LOCK_CLOCKS: 2083ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BRD: 2084ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_RFO: 2085ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_WB: 2086ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_IFETCH: 2087ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_INVAL: 2088ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_PWR: 2089ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_P: 2090ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_IO: 2091ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_DEF: 2092ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BURST: 2093ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_ANY: 2094ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_MEM: 2095ebccf1e3SJoseph Koshy 2096ebccf1e3SJoseph Koshy /* default => 'nta' */ 2097ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED: 2098ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_MISS: 2099ebccf1e3SJoseph Koshy 2100ebccf1e3SJoseph Koshy /* default => 'packed and scalar' */ 2101ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_INST_RETIRED: 2102ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_COMP_INST_RET: 2103ebccf1e3SJoseph Koshy 2104ebccf1e3SJoseph Koshy /* default => 'mmx to fp transitions' */ 2105ebccf1e3SJoseph Koshy case PMC_EV_P6_FP_MMX_TRANS: 2106ebccf1e3SJoseph Koshy 2107ebccf1e3SJoseph Koshy /* default => 'SSE Packed Single' */ 2108ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED: 2109ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED: 2110ebccf1e3SJoseph Koshy 2111ebccf1e3SJoseph Koshy /* default => 'all fused micro-ops' */ 2112ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_FUSED_UOPS_RET: 2113ebccf1e3SJoseph Koshy 2114ebccf1e3SJoseph Koshy /* default => 'all transitions' */ 2115ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_EST_TRANS: 2116ebccf1e3SJoseph Koshy break; 2117ebccf1e3SJoseph Koshy 2118ebccf1e3SJoseph Koshy case PMC_EV_P6_MMX_UOPS_EXEC: 2119ebccf1e3SJoseph Koshy evmask = 0x0F; /* only value allowed */ 2120ebccf1e3SJoseph Koshy break; 2121ebccf1e3SJoseph Koshy 2122ebccf1e3SJoseph Koshy default: 2123ebccf1e3SJoseph Koshy /* 2124ebccf1e3SJoseph Koshy * For all other events, set the default event mask 2125ebccf1e3SJoseph Koshy * to a logical OR of all the allowed event mask bits. 2126ebccf1e3SJoseph Koshy */ 2127ebccf1e3SJoseph Koshy if (evmask == 0 && pmask) { 2128ebccf1e3SJoseph Koshy for (pm = pmask; pm->pm_name; pm++) 2129ebccf1e3SJoseph Koshy evmask |= pm->pm_value; 2130ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2131ebccf1e3SJoseph Koshy } 2132ebccf1e3SJoseph Koshy 2133ebccf1e3SJoseph Koshy break; 2134ebccf1e3SJoseph Koshy } 2135ebccf1e3SJoseph Koshy 2136ebccf1e3SJoseph Koshy if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) 2137f263522aSJoseph Koshy pmc_config->pm_md.pm_ppro.pm_ppro_config |= 2138f263522aSJoseph Koshy P6_EVSEL_TO_UMASK(evmask); 2139ebccf1e3SJoseph Koshy 2140aa342b1fSJoseph Koshy return (0); 2141ebccf1e3SJoseph Koshy } 2142ebccf1e3SJoseph Koshy 2143ebccf1e3SJoseph Koshy #endif 2144ebccf1e3SJoseph Koshy 2145789140c0SJoseph Koshy #if defined(__i386__) || defined(__amd64__) 2146789140c0SJoseph Koshy static int 2147789140c0SJoseph Koshy tsc_allocate_pmc(enum pmc_event pe, char *ctrspec, 2148789140c0SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 2149789140c0SJoseph Koshy { 2150789140c0SJoseph Koshy if (pe != PMC_EV_TSC_TSC) 2151789140c0SJoseph Koshy return (-1); 2152789140c0SJoseph Koshy 2153789140c0SJoseph Koshy /* TSC events must be unqualified. */ 2154789140c0SJoseph Koshy if (ctrspec && *ctrspec != '\0') 2155789140c0SJoseph Koshy return (-1); 2156789140c0SJoseph Koshy 2157789140c0SJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 2158789140c0SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_READ; 2159789140c0SJoseph Koshy 2160789140c0SJoseph Koshy return (0); 2161789140c0SJoseph Koshy } 2162789140c0SJoseph Koshy #endif 2163789140c0SJoseph Koshy 21640ce207d2SRui Paulo #if defined(__XSCALE__) 21650ce207d2SRui Paulo 21660ce207d2SRui Paulo static struct pmc_event_alias xscale_aliases[] = { 21670ce207d2SRui Paulo EV_ALIAS("branches", "BRANCH_RETIRED"), 21680ce207d2SRui Paulo EV_ALIAS("branch-mispredicts", "BRANCH_MISPRED"), 21690ce207d2SRui Paulo EV_ALIAS("dc-misses", "DC_MISS"), 21700ce207d2SRui Paulo EV_ALIAS("ic-misses", "IC_MISS"), 21710ce207d2SRui Paulo EV_ALIAS("instructions", "INSTR_RETIRED"), 21720ce207d2SRui Paulo EV_ALIAS(NULL, NULL) 21730ce207d2SRui Paulo }; 21740ce207d2SRui Paulo static int 21750ce207d2SRui Paulo xscale_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 21760ce207d2SRui Paulo struct pmc_op_pmcallocate *pmc_config __unused) 21770ce207d2SRui Paulo { 21780ce207d2SRui Paulo switch (pe) { 21790ce207d2SRui Paulo default: 21800ce207d2SRui Paulo break; 21810ce207d2SRui Paulo } 21820ce207d2SRui Paulo 21830ce207d2SRui Paulo return (0); 21840ce207d2SRui Paulo } 21850ce207d2SRui Paulo #endif 21860ce207d2SRui Paulo 2187660df75eSGeorge V. Neville-Neil #if defined(__mips__) 2188660df75eSGeorge V. Neville-Neil 2189660df75eSGeorge V. Neville-Neil static struct pmc_event_alias mips24k_aliases[] = { 2190660df75eSGeorge V. Neville-Neil EV_ALIAS("instructions", "INSTR_EXECUTED"), 2191660df75eSGeorge V. Neville-Neil EV_ALIAS("branches", "BRANCH_COMPLETED"), 2192660df75eSGeorge V. Neville-Neil EV_ALIAS("branch-mispredicts", "BRANCH_MISPRED"), 2193660df75eSGeorge V. Neville-Neil EV_ALIAS(NULL, NULL) 2194660df75eSGeorge V. Neville-Neil }; 2195660df75eSGeorge V. Neville-Neil 2196660df75eSGeorge V. Neville-Neil #define MIPS24K_KW_OS "os" 2197660df75eSGeorge V. Neville-Neil #define MIPS24K_KW_USR "usr" 2198660df75eSGeorge V. Neville-Neil #define MIPS24K_KW_ANYTHREAD "anythread" 2199660df75eSGeorge V. Neville-Neil 2200660df75eSGeorge V. Neville-Neil static int 2201660df75eSGeorge V. Neville-Neil mips24k_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 2202660df75eSGeorge V. Neville-Neil struct pmc_op_pmcallocate *pmc_config __unused) 2203660df75eSGeorge V. Neville-Neil { 2204660df75eSGeorge V. Neville-Neil char *p; 2205660df75eSGeorge V. Neville-Neil 2206660df75eSGeorge V. Neville-Neil (void) pe; 2207660df75eSGeorge V. Neville-Neil 2208660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2209660df75eSGeorge V. Neville-Neil 2210660df75eSGeorge V. Neville-Neil while ((p = strsep(&ctrspec, ",")) != NULL) { 2211660df75eSGeorge V. Neville-Neil if (KWMATCH(p, MIPS24K_KW_OS)) 2212660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2213660df75eSGeorge V. Neville-Neil else if (KWMATCH(p, MIPS24K_KW_USR)) 2214660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= PMC_CAP_USER; 2215660df75eSGeorge V. Neville-Neil else if (KWMATCH(p, MIPS24K_KW_ANYTHREAD)) 2216660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= (PMC_CAP_USER | PMC_CAP_SYSTEM); 2217660df75eSGeorge V. Neville-Neil else 2218660df75eSGeorge V. Neville-Neil return (-1); 2219660df75eSGeorge V. Neville-Neil } 2220660df75eSGeorge V. Neville-Neil 2221660df75eSGeorge V. Neville-Neil return (0); 2222660df75eSGeorge V. Neville-Neil } 2223660df75eSGeorge V. Neville-Neil #endif /* __mips__ */ 2224660df75eSGeorge V. Neville-Neil 2225*7b25dccaSJustin Hibbits #if defined(__powerpc__) 2226*7b25dccaSJustin Hibbits 2227*7b25dccaSJustin Hibbits static struct pmc_event_alias ppc7450_aliases[] = { 2228*7b25dccaSJustin Hibbits EV_ALIAS("instructions", "INSTR_COMPLETED"), 2229*7b25dccaSJustin Hibbits EV_ALIAS("branches", "BRANCHES_COMPLETED"), 2230*7b25dccaSJustin Hibbits EV_ALIAS("branch-mispredicts", "MISPREDICTED_BRANCHES"), 2231*7b25dccaSJustin Hibbits EV_ALIAS(NULL, NULL) 2232*7b25dccaSJustin Hibbits }; 2233*7b25dccaSJustin Hibbits 2234*7b25dccaSJustin Hibbits #define PPC7450_KW_OS "os" 2235*7b25dccaSJustin Hibbits #define PPC7450_KW_USR "usr" 2236*7b25dccaSJustin Hibbits #define PPC7450_KW_ANYTHREAD "anythread" 2237*7b25dccaSJustin Hibbits 2238*7b25dccaSJustin Hibbits static int 2239*7b25dccaSJustin Hibbits ppc7450_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 2240*7b25dccaSJustin Hibbits struct pmc_op_pmcallocate *pmc_config __unused) 2241*7b25dccaSJustin Hibbits { 2242*7b25dccaSJustin Hibbits char *p; 2243*7b25dccaSJustin Hibbits 2244*7b25dccaSJustin Hibbits (void) pe; 2245*7b25dccaSJustin Hibbits 2246*7b25dccaSJustin Hibbits pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2247*7b25dccaSJustin Hibbits 2248*7b25dccaSJustin Hibbits while ((p = strsep(&ctrspec, ",")) != NULL) { 2249*7b25dccaSJustin Hibbits if (KWMATCH(p, PPC7450_KW_OS)) 2250*7b25dccaSJustin Hibbits pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2251*7b25dccaSJustin Hibbits else if (KWMATCH(p, PPC7450_KW_USR)) 2252*7b25dccaSJustin Hibbits pmc_config->pm_caps |= PMC_CAP_USER; 2253*7b25dccaSJustin Hibbits else if (KWMATCH(p, PPC7450_KW_ANYTHREAD)) 2254*7b25dccaSJustin Hibbits pmc_config->pm_caps |= (PMC_CAP_USER | PMC_CAP_SYSTEM); 2255*7b25dccaSJustin Hibbits else 2256*7b25dccaSJustin Hibbits return (-1); 2257*7b25dccaSJustin Hibbits } 2258*7b25dccaSJustin Hibbits 2259*7b25dccaSJustin Hibbits return (0); 2260*7b25dccaSJustin Hibbits } 2261*7b25dccaSJustin Hibbits #endif /* __powerpc__ */ 2262*7b25dccaSJustin Hibbits 2263660df75eSGeorge V. Neville-Neil 2264789140c0SJoseph Koshy /* 2265789140c0SJoseph Koshy * Match an event name `name' with its canonical form. 2266789140c0SJoseph Koshy * 22670cfab8ddSJoseph Koshy * Matches are case insensitive and spaces, periods, underscores and 22680cfab8ddSJoseph Koshy * hyphen characters are considered to match each other. 2269789140c0SJoseph Koshy * 2270789140c0SJoseph Koshy * Returns 1 for a match, 0 otherwise. 2271789140c0SJoseph Koshy */ 2272789140c0SJoseph Koshy 2273789140c0SJoseph Koshy static int 2274789140c0SJoseph Koshy pmc_match_event_name(const char *name, const char *canonicalname) 2275789140c0SJoseph Koshy { 2276789140c0SJoseph Koshy int cc, nc; 2277789140c0SJoseph Koshy const unsigned char *c, *n; 2278789140c0SJoseph Koshy 2279789140c0SJoseph Koshy c = (const unsigned char *) canonicalname; 2280789140c0SJoseph Koshy n = (const unsigned char *) name; 2281789140c0SJoseph Koshy 2282789140c0SJoseph Koshy for (; (nc = *n) && (cc = *c); n++, c++) { 2283789140c0SJoseph Koshy 22840cfab8ddSJoseph Koshy if ((nc == ' ' || nc == '_' || nc == '-' || nc == '.') && 22850cfab8ddSJoseph Koshy (cc == ' ' || cc == '_' || cc == '-' || cc == '.')) 2286789140c0SJoseph Koshy continue; 2287789140c0SJoseph Koshy 22880cfab8ddSJoseph Koshy if (toupper(nc) == toupper(cc)) 2289789140c0SJoseph Koshy continue; 2290789140c0SJoseph Koshy 22910cfab8ddSJoseph Koshy 2292789140c0SJoseph Koshy return (0); 2293789140c0SJoseph Koshy } 2294789140c0SJoseph Koshy 2295789140c0SJoseph Koshy if (*n == '\0' && *c == '\0') 2296789140c0SJoseph Koshy return (1); 2297789140c0SJoseph Koshy 2298789140c0SJoseph Koshy return (0); 2299789140c0SJoseph Koshy } 2300789140c0SJoseph Koshy 2301789140c0SJoseph Koshy /* 2302789140c0SJoseph Koshy * Match an event name against all the event named supported by a 2303789140c0SJoseph Koshy * PMC class. 2304789140c0SJoseph Koshy * 2305789140c0SJoseph Koshy * Returns an event descriptor pointer on match or NULL otherwise. 2306789140c0SJoseph Koshy */ 2307789140c0SJoseph Koshy static const struct pmc_event_descr * 2308789140c0SJoseph Koshy pmc_match_event_class(const char *name, 2309789140c0SJoseph Koshy const struct pmc_class_descr *pcd) 2310789140c0SJoseph Koshy { 2311789140c0SJoseph Koshy size_t n; 2312789140c0SJoseph Koshy const struct pmc_event_descr *ev; 2313789140c0SJoseph Koshy 2314789140c0SJoseph Koshy ev = pcd->pm_evc_event_table; 2315789140c0SJoseph Koshy for (n = 0; n < pcd->pm_evc_event_table_size; n++, ev++) 2316789140c0SJoseph Koshy if (pmc_match_event_name(name, ev->pm_ev_name)) 2317789140c0SJoseph Koshy return (ev); 2318789140c0SJoseph Koshy 2319789140c0SJoseph Koshy return (NULL); 2320789140c0SJoseph Koshy } 2321789140c0SJoseph Koshy 2322789140c0SJoseph Koshy static int 2323789140c0SJoseph Koshy pmc_mdep_is_compatible_class(enum pmc_class pc) 2324789140c0SJoseph Koshy { 2325789140c0SJoseph Koshy size_t n; 2326789140c0SJoseph Koshy 2327789140c0SJoseph Koshy for (n = 0; n < pmc_mdep_class_list_size; n++) 2328789140c0SJoseph Koshy if (pmc_mdep_class_list[n] == pc) 2329789140c0SJoseph Koshy return (1); 2330789140c0SJoseph Koshy return (0); 2331789140c0SJoseph Koshy } 2332789140c0SJoseph Koshy 2333ebccf1e3SJoseph Koshy /* 2334ebccf1e3SJoseph Koshy * API entry points 2335ebccf1e3SJoseph Koshy */ 2336ebccf1e3SJoseph Koshy 2337ebccf1e3SJoseph Koshy int 2338ebccf1e3SJoseph Koshy pmc_allocate(const char *ctrspec, enum pmc_mode mode, 2339ebccf1e3SJoseph Koshy uint32_t flags, int cpu, pmc_id_t *pmcid) 2340ebccf1e3SJoseph Koshy { 2341789140c0SJoseph Koshy size_t n; 2342ebccf1e3SJoseph Koshy int retval; 2343ebccf1e3SJoseph Koshy char *r, *spec_copy; 2344ebccf1e3SJoseph Koshy const char *ctrname; 2345789140c0SJoseph Koshy const struct pmc_event_descr *ev; 2346789140c0SJoseph Koshy const struct pmc_event_alias *alias; 2347ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate pmc_config; 2348789140c0SJoseph Koshy const struct pmc_class_descr *pcd; 2349ebccf1e3SJoseph Koshy 2350ebccf1e3SJoseph Koshy spec_copy = NULL; 2351ebccf1e3SJoseph Koshy retval = -1; 2352ebccf1e3SJoseph Koshy 2353ebccf1e3SJoseph Koshy if (mode != PMC_MODE_SS && mode != PMC_MODE_TS && 2354ebccf1e3SJoseph Koshy mode != PMC_MODE_SC && mode != PMC_MODE_TC) { 2355ebccf1e3SJoseph Koshy errno = EINVAL; 2356ebccf1e3SJoseph Koshy goto out; 2357ebccf1e3SJoseph Koshy } 2358ebccf1e3SJoseph Koshy 2359ebccf1e3SJoseph Koshy /* replace an event alias with the canonical event specifier */ 2360ebccf1e3SJoseph Koshy if (pmc_mdep_event_aliases) 2361789140c0SJoseph Koshy for (alias = pmc_mdep_event_aliases; alias->pm_alias; alias++) 2362789140c0SJoseph Koshy if (!strcasecmp(ctrspec, alias->pm_alias)) { 2363789140c0SJoseph Koshy spec_copy = strdup(alias->pm_spec); 2364ebccf1e3SJoseph Koshy break; 2365ebccf1e3SJoseph Koshy } 2366ebccf1e3SJoseph Koshy 2367ebccf1e3SJoseph Koshy if (spec_copy == NULL) 2368ebccf1e3SJoseph Koshy spec_copy = strdup(ctrspec); 2369ebccf1e3SJoseph Koshy 2370ebccf1e3SJoseph Koshy r = spec_copy; 2371ebccf1e3SJoseph Koshy ctrname = strsep(&r, ","); 2372ebccf1e3SJoseph Koshy 2373789140c0SJoseph Koshy /* 2374789140c0SJoseph Koshy * If a explicit class prefix was given by the user, restrict the 2375789140c0SJoseph Koshy * search for the event to the specified PMC class. 2376789140c0SJoseph Koshy */ 2377789140c0SJoseph Koshy ev = NULL; 23780cfab8ddSJoseph Koshy for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) { 23790cfab8ddSJoseph Koshy pcd = pmc_class_table[n]; 2380789140c0SJoseph Koshy if (pmc_mdep_is_compatible_class(pcd->pm_evc_class) && 2381789140c0SJoseph Koshy strncasecmp(ctrname, pcd->pm_evc_name, 2382789140c0SJoseph Koshy pcd->pm_evc_name_size) == 0) { 2383789140c0SJoseph Koshy if ((ev = pmc_match_event_class(ctrname + 2384789140c0SJoseph Koshy pcd->pm_evc_name_size, pcd)) == NULL) { 2385789140c0SJoseph Koshy errno = EINVAL; 2386789140c0SJoseph Koshy goto out; 2387789140c0SJoseph Koshy } 2388ebccf1e3SJoseph Koshy break; 2389789140c0SJoseph Koshy } 2390789140c0SJoseph Koshy } 2391ebccf1e3SJoseph Koshy 2392789140c0SJoseph Koshy /* 2393789140c0SJoseph Koshy * Otherwise, search for this event in all compatible PMC 2394789140c0SJoseph Koshy * classes. 2395789140c0SJoseph Koshy */ 23960cfab8ddSJoseph Koshy for (n = 0; ev == NULL && n < PMC_CLASS_TABLE_SIZE; n++) { 23970cfab8ddSJoseph Koshy pcd = pmc_class_table[n]; 2398789140c0SJoseph Koshy if (pmc_mdep_is_compatible_class(pcd->pm_evc_class)) 2399789140c0SJoseph Koshy ev = pmc_match_event_class(ctrname, pcd); 2400789140c0SJoseph Koshy } 2401789140c0SJoseph Koshy 2402789140c0SJoseph Koshy if (ev == NULL) { 2403ebccf1e3SJoseph Koshy errno = EINVAL; 2404ebccf1e3SJoseph Koshy goto out; 2405ebccf1e3SJoseph Koshy } 2406ebccf1e3SJoseph Koshy 2407ebccf1e3SJoseph Koshy bzero(&pmc_config, sizeof(pmc_config)); 2408789140c0SJoseph Koshy pmc_config.pm_ev = ev->pm_ev_code; 2409789140c0SJoseph Koshy pmc_config.pm_class = pcd->pm_evc_class; 2410ebccf1e3SJoseph Koshy pmc_config.pm_cpu = cpu; 2411ebccf1e3SJoseph Koshy pmc_config.pm_mode = mode; 2412ebccf1e3SJoseph Koshy pmc_config.pm_flags = flags; 2413ebccf1e3SJoseph Koshy 2414ebccf1e3SJoseph Koshy if (PMC_IS_SAMPLING_MODE(mode)) 2415ebccf1e3SJoseph Koshy pmc_config.pm_caps |= PMC_CAP_INTERRUPT; 2416ebccf1e3SJoseph Koshy 2417789140c0SJoseph Koshy if (pcd->pm_evc_allocate_pmc(ev->pm_ev_code, r, &pmc_config) < 0) { 2418ebccf1e3SJoseph Koshy errno = EINVAL; 2419ebccf1e3SJoseph Koshy goto out; 2420ebccf1e3SJoseph Koshy } 2421ebccf1e3SJoseph Koshy 2422ebccf1e3SJoseph Koshy if (PMC_CALL(PMCALLOCATE, &pmc_config) < 0) 2423ebccf1e3SJoseph Koshy goto out; 2424ebccf1e3SJoseph Koshy 2425ebccf1e3SJoseph Koshy *pmcid = pmc_config.pm_pmcid; 2426ebccf1e3SJoseph Koshy 2427ebccf1e3SJoseph Koshy retval = 0; 2428ebccf1e3SJoseph Koshy 2429ebccf1e3SJoseph Koshy out: 2430ebccf1e3SJoseph Koshy if (spec_copy) 2431ebccf1e3SJoseph Koshy free(spec_copy); 2432ebccf1e3SJoseph Koshy 2433aa342b1fSJoseph Koshy return (retval); 2434ebccf1e3SJoseph Koshy } 2435ebccf1e3SJoseph Koshy 2436ebccf1e3SJoseph Koshy int 2437ebccf1e3SJoseph Koshy pmc_attach(pmc_id_t pmc, pid_t pid) 2438ebccf1e3SJoseph Koshy { 2439ebccf1e3SJoseph Koshy struct pmc_op_pmcattach pmc_attach_args; 2440ebccf1e3SJoseph Koshy 2441ebccf1e3SJoseph Koshy pmc_attach_args.pm_pmc = pmc; 2442ebccf1e3SJoseph Koshy pmc_attach_args.pm_pid = pid; 2443ebccf1e3SJoseph Koshy 2444aa342b1fSJoseph Koshy return (PMC_CALL(PMCATTACH, &pmc_attach_args)); 2445ebccf1e3SJoseph Koshy } 2446ebccf1e3SJoseph Koshy 2447ebccf1e3SJoseph Koshy int 2448c5153e19SJoseph Koshy pmc_capabilities(pmc_id_t pmcid, uint32_t *caps) 2449c5153e19SJoseph Koshy { 2450c5153e19SJoseph Koshy unsigned int i; 2451c5153e19SJoseph Koshy enum pmc_class cl; 2452c5153e19SJoseph Koshy 2453c5153e19SJoseph Koshy cl = PMC_ID_TO_CLASS(pmcid); 2454c5153e19SJoseph Koshy for (i = 0; i < cpu_info.pm_nclass; i++) 2455c5153e19SJoseph Koshy if (cpu_info.pm_classes[i].pm_class == cl) { 2456c5153e19SJoseph Koshy *caps = cpu_info.pm_classes[i].pm_caps; 2457aa342b1fSJoseph Koshy return (0); 2458c5153e19SJoseph Koshy } 2459484202faSJoseph Koshy errno = EINVAL; 2460484202faSJoseph Koshy return (-1); 2461c5153e19SJoseph Koshy } 2462c5153e19SJoseph Koshy 2463f263522aSJoseph Koshy int 2464f263522aSJoseph Koshy pmc_configure_logfile(int fd) 2465ebccf1e3SJoseph Koshy { 2466f263522aSJoseph Koshy struct pmc_op_configurelog cla; 2467f263522aSJoseph Koshy 2468f263522aSJoseph Koshy cla.pm_logfd = fd; 2469f263522aSJoseph Koshy if (PMC_CALL(CONFIGURELOG, &cla) < 0) 2470aa342b1fSJoseph Koshy return (-1); 2471aa342b1fSJoseph Koshy return (0); 2472ebccf1e3SJoseph Koshy } 2473ebccf1e3SJoseph Koshy 2474f263522aSJoseph Koshy int 2475f263522aSJoseph Koshy pmc_cpuinfo(const struct pmc_cpuinfo **pci) 2476ebccf1e3SJoseph Koshy { 2477f263522aSJoseph Koshy if (pmc_syscall == -1) { 2478f263522aSJoseph Koshy errno = ENXIO; 2479aa342b1fSJoseph Koshy return (-1); 2480ebccf1e3SJoseph Koshy } 2481ebccf1e3SJoseph Koshy 24821455fcd3SJoseph Koshy *pci = &cpu_info; 2483aa342b1fSJoseph Koshy return (0); 2484ebccf1e3SJoseph Koshy } 2485ebccf1e3SJoseph Koshy 2486f263522aSJoseph Koshy int 2487f263522aSJoseph Koshy pmc_detach(pmc_id_t pmc, pid_t pid) 2488ebccf1e3SJoseph Koshy { 2489f263522aSJoseph Koshy struct pmc_op_pmcattach pmc_detach_args; 2490ebccf1e3SJoseph Koshy 2491f263522aSJoseph Koshy pmc_detach_args.pm_pmc = pmc; 2492f263522aSJoseph Koshy pmc_detach_args.pm_pid = pid; 2493aa342b1fSJoseph Koshy return (PMC_CALL(PMCDETACH, &pmc_detach_args)); 2494ebccf1e3SJoseph Koshy } 2495ebccf1e3SJoseph Koshy 2496f263522aSJoseph Koshy int 2497f263522aSJoseph Koshy pmc_disable(int cpu, int pmc) 2498ebccf1e3SJoseph Koshy { 2499f263522aSJoseph Koshy struct pmc_op_pmcadmin ssa; 2500ebccf1e3SJoseph Koshy 2501f263522aSJoseph Koshy ssa.pm_cpu = cpu; 2502f263522aSJoseph Koshy ssa.pm_pmc = pmc; 2503f263522aSJoseph Koshy ssa.pm_state = PMC_STATE_DISABLED; 2504aa342b1fSJoseph Koshy return (PMC_CALL(PMCADMIN, &ssa)); 2505ebccf1e3SJoseph Koshy } 2506ebccf1e3SJoseph Koshy 2507f263522aSJoseph Koshy int 2508f263522aSJoseph Koshy pmc_enable(int cpu, int pmc) 2509ebccf1e3SJoseph Koshy { 2510f263522aSJoseph Koshy struct pmc_op_pmcadmin ssa; 2511ebccf1e3SJoseph Koshy 2512f263522aSJoseph Koshy ssa.pm_cpu = cpu; 2513f263522aSJoseph Koshy ssa.pm_pmc = pmc; 2514f263522aSJoseph Koshy ssa.pm_state = PMC_STATE_FREE; 2515aa342b1fSJoseph Koshy return (PMC_CALL(PMCADMIN, &ssa)); 2516ebccf1e3SJoseph Koshy } 2517ebccf1e3SJoseph Koshy 2518ebccf1e3SJoseph Koshy /* 2519ebccf1e3SJoseph Koshy * Return a list of events known to a given PMC class. 'cl' is the 2520ebccf1e3SJoseph Koshy * PMC class identifier, 'eventnames' is the returned list of 'const 2521ebccf1e3SJoseph Koshy * char *' pointers pointing to the names of the events. 'nevents' is 2522ebccf1e3SJoseph Koshy * the number of event name pointers returned. 2523ebccf1e3SJoseph Koshy * 2524ebccf1e3SJoseph Koshy * The space for 'eventnames' is allocated using malloc(3). The caller 2525ebccf1e3SJoseph Koshy * is responsible for freeing this space when done. 2526ebccf1e3SJoseph Koshy */ 2527ebccf1e3SJoseph Koshy int 2528ebccf1e3SJoseph Koshy pmc_event_names_of_class(enum pmc_class cl, const char ***eventnames, 2529ebccf1e3SJoseph Koshy int *nevents) 2530ebccf1e3SJoseph Koshy { 2531ebccf1e3SJoseph Koshy int count; 2532ebccf1e3SJoseph Koshy const char **names; 2533ebccf1e3SJoseph Koshy const struct pmc_event_descr *ev; 2534ebccf1e3SJoseph Koshy 2535ebccf1e3SJoseph Koshy switch (cl) 2536ebccf1e3SJoseph Koshy { 25370cfab8ddSJoseph Koshy case PMC_CLASS_IAF: 25380cfab8ddSJoseph Koshy ev = iaf_event_table; 25390cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(iaf); 25400cfab8ddSJoseph Koshy break; 25410cfab8ddSJoseph Koshy case PMC_CLASS_IAP: 25420cfab8ddSJoseph Koshy /* 25430cfab8ddSJoseph Koshy * Return the most appropriate set of event name 25440cfab8ddSJoseph Koshy * spellings for the current CPU. 25450cfab8ddSJoseph Koshy */ 25460cfab8ddSJoseph Koshy switch (cpu_info.pm_cputype) { 25470cfab8ddSJoseph Koshy default: 25480cfab8ddSJoseph Koshy case PMC_CPU_INTEL_ATOM: 25490cfab8ddSJoseph Koshy ev = atom_event_table; 25500cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(atom); 25510cfab8ddSJoseph Koshy break; 25520cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE: 25530cfab8ddSJoseph Koshy ev = core_event_table; 25540cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(core); 25550cfab8ddSJoseph Koshy break; 25560cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE2: 2557b4d091f3SJoseph Koshy case PMC_CPU_INTEL_CORE2EXTREME: 25580cfab8ddSJoseph Koshy ev = core2_event_table; 25590cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(core2); 25600cfab8ddSJoseph Koshy break; 2561597979c4SJeff Roberson case PMC_CPU_INTEL_COREI7: 2562597979c4SJeff Roberson ev = corei7_event_table; 2563597979c4SJeff Roberson count = PMC_EVENT_TABLE_SIZE(corei7); 2564597979c4SJeff Roberson break; 25651fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 25661fa7f10bSFabien Thomas ev = westmere_event_table; 25671fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(westmere); 25681fa7f10bSFabien Thomas break; 25691fa7f10bSFabien Thomas } 25701fa7f10bSFabien Thomas break; 25711fa7f10bSFabien Thomas case PMC_CLASS_UCF: 25721fa7f10bSFabien Thomas ev = ucf_event_table; 25731fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(ucf); 25741fa7f10bSFabien Thomas break; 25751fa7f10bSFabien Thomas case PMC_CLASS_UCP: 25761fa7f10bSFabien Thomas /* 25771fa7f10bSFabien Thomas * Return the most appropriate set of event name 25781fa7f10bSFabien Thomas * spellings for the current CPU. 25791fa7f10bSFabien Thomas */ 25801fa7f10bSFabien Thomas switch (cpu_info.pm_cputype) { 25811fa7f10bSFabien Thomas default: 25821fa7f10bSFabien Thomas case PMC_CPU_INTEL_COREI7: 25831fa7f10bSFabien Thomas ev = corei7uc_event_table; 25841fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(corei7uc); 25851fa7f10bSFabien Thomas break; 25861fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 25871fa7f10bSFabien Thomas ev = westmereuc_event_table; 25881fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(westmereuc); 25891fa7f10bSFabien Thomas break; 25900cfab8ddSJoseph Koshy } 25910cfab8ddSJoseph Koshy break; 2592ebccf1e3SJoseph Koshy case PMC_CLASS_TSC: 2593789140c0SJoseph Koshy ev = tsc_event_table; 2594789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(tsc); 2595ebccf1e3SJoseph Koshy break; 2596ebccf1e3SJoseph Koshy case PMC_CLASS_K7: 2597789140c0SJoseph Koshy ev = k7_event_table; 2598789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(k7); 2599ebccf1e3SJoseph Koshy break; 2600ebccf1e3SJoseph Koshy case PMC_CLASS_K8: 2601789140c0SJoseph Koshy ev = k8_event_table; 2602789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(k8); 2603ebccf1e3SJoseph Koshy break; 2604ebccf1e3SJoseph Koshy case PMC_CLASS_P4: 2605789140c0SJoseph Koshy ev = p4_event_table; 2606789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p4); 2607789140c0SJoseph Koshy break; 2608789140c0SJoseph Koshy case PMC_CLASS_P5: 2609789140c0SJoseph Koshy ev = p5_event_table; 2610789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p5); 2611789140c0SJoseph Koshy break; 2612789140c0SJoseph Koshy case PMC_CLASS_P6: 2613789140c0SJoseph Koshy ev = p6_event_table; 2614789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p6); 2615ebccf1e3SJoseph Koshy break; 26160ce207d2SRui Paulo case PMC_CLASS_XSCALE: 26170ce207d2SRui Paulo ev = xscale_event_table; 26180ce207d2SRui Paulo count = PMC_EVENT_TABLE_SIZE(xscale); 26190ce207d2SRui Paulo break; 2620660df75eSGeorge V. Neville-Neil case PMC_CLASS_MIPS24K: 2621660df75eSGeorge V. Neville-Neil ev = mips24k_event_table; 2622660df75eSGeorge V. Neville-Neil count = PMC_EVENT_TABLE_SIZE(mips24k); 2623660df75eSGeorge V. Neville-Neil break; 2624*7b25dccaSJustin Hibbits case PMC_CLASS_PPC7450: 2625*7b25dccaSJustin Hibbits ev = ppc7450_event_table; 2626*7b25dccaSJustin Hibbits count = PMC_EVENT_TABLE_SIZE(ppc7450); 2627*7b25dccaSJustin Hibbits break; 2628ebccf1e3SJoseph Koshy default: 2629ebccf1e3SJoseph Koshy errno = EINVAL; 2630aa342b1fSJoseph Koshy return (-1); 2631ebccf1e3SJoseph Koshy } 2632ebccf1e3SJoseph Koshy 2633ebccf1e3SJoseph Koshy if ((names = malloc(count * sizeof(const char *))) == NULL) 2634aa342b1fSJoseph Koshy return (-1); 2635ebccf1e3SJoseph Koshy 2636ebccf1e3SJoseph Koshy *eventnames = names; 2637ebccf1e3SJoseph Koshy *nevents = count; 2638ebccf1e3SJoseph Koshy 2639ebccf1e3SJoseph Koshy for (;count--; ev++, names++) 2640ebccf1e3SJoseph Koshy *names = ev->pm_ev_name; 2641aa342b1fSJoseph Koshy return (0); 2642ebccf1e3SJoseph Koshy } 2643ebccf1e3SJoseph Koshy 2644f263522aSJoseph Koshy int 2645f263522aSJoseph Koshy pmc_flush_logfile(void) 2646f263522aSJoseph Koshy { 2647aa342b1fSJoseph Koshy return (PMC_CALL(FLUSHLOG,0)); 2648f263522aSJoseph Koshy } 2649ebccf1e3SJoseph Koshy 2650ebccf1e3SJoseph Koshy int 2651dceed24aSFabien Thomas pmc_close_logfile(void) 2652dceed24aSFabien Thomas { 2653dceed24aSFabien Thomas return (PMC_CALL(CLOSELOG,0)); 2654dceed24aSFabien Thomas } 2655dceed24aSFabien Thomas 2656dceed24aSFabien Thomas int 2657f263522aSJoseph Koshy pmc_get_driver_stats(struct pmc_driverstats *ds) 2658ebccf1e3SJoseph Koshy { 2659f263522aSJoseph Koshy struct pmc_op_getdriverstats gms; 2660f263522aSJoseph Koshy 2661f263522aSJoseph Koshy if (PMC_CALL(GETDRIVERSTATS, &gms) < 0) 2662aa342b1fSJoseph Koshy return (-1); 2663f263522aSJoseph Koshy 2664f263522aSJoseph Koshy /* copy out fields in the current userland<->library interface */ 2665f263522aSJoseph Koshy ds->pm_intr_ignored = gms.pm_intr_ignored; 2666f263522aSJoseph Koshy ds->pm_intr_processed = gms.pm_intr_processed; 2667f263522aSJoseph Koshy ds->pm_intr_bufferfull = gms.pm_intr_bufferfull; 2668f263522aSJoseph Koshy ds->pm_syscalls = gms.pm_syscalls; 2669f263522aSJoseph Koshy ds->pm_syscall_errors = gms.pm_syscall_errors; 2670f263522aSJoseph Koshy ds->pm_buffer_requests = gms.pm_buffer_requests; 2671f263522aSJoseph Koshy ds->pm_buffer_requests_failed = gms.pm_buffer_requests_failed; 2672f263522aSJoseph Koshy ds->pm_log_sweeps = gms.pm_log_sweeps; 2673aa342b1fSJoseph Koshy return (0); 2674f263522aSJoseph Koshy } 2675f263522aSJoseph Koshy 2676f263522aSJoseph Koshy int 2677f263522aSJoseph Koshy pmc_get_msr(pmc_id_t pmc, uint32_t *msr) 2678f263522aSJoseph Koshy { 2679f263522aSJoseph Koshy struct pmc_op_getmsr gm; 2680ebccf1e3SJoseph Koshy 2681ebccf1e3SJoseph Koshy gm.pm_pmcid = pmc; 2682f263522aSJoseph Koshy if (PMC_CALL(PMCGETMSR, &gm) < 0) 2683aa342b1fSJoseph Koshy return (-1); 2684ebccf1e3SJoseph Koshy *msr = gm.pm_msr; 2685aa342b1fSJoseph Koshy return (0); 2686ebccf1e3SJoseph Koshy } 2687ebccf1e3SJoseph Koshy 2688f263522aSJoseph Koshy int 2689f263522aSJoseph Koshy pmc_init(void) 2690f263522aSJoseph Koshy { 2691f263522aSJoseph Koshy int error, pmc_mod_id; 26921455fcd3SJoseph Koshy unsigned int n; 2693f263522aSJoseph Koshy uint32_t abi_version; 2694f263522aSJoseph Koshy struct module_stat pmc_modstat; 26951455fcd3SJoseph Koshy struct pmc_op_getcpuinfo op_cpu_info; 2696791f5d5bSJoseph Koshy #if defined(__amd64__) || defined(__i386__) 2697791f5d5bSJoseph Koshy int cpu_has_iaf_counters; 2698791f5d5bSJoseph Koshy unsigned int t; 2699791f5d5bSJoseph Koshy #endif 2700f263522aSJoseph Koshy 2701f263522aSJoseph Koshy if (pmc_syscall != -1) /* already inited */ 2702aa342b1fSJoseph Koshy return (0); 2703f263522aSJoseph Koshy 2704f263522aSJoseph Koshy /* retrieve the system call number from the KLD */ 2705f263522aSJoseph Koshy if ((pmc_mod_id = modfind(PMC_MODULE_NAME)) < 0) 2706aa342b1fSJoseph Koshy return (-1); 2707f263522aSJoseph Koshy 2708f263522aSJoseph Koshy pmc_modstat.version = sizeof(struct module_stat); 2709f263522aSJoseph Koshy if ((error = modstat(pmc_mod_id, &pmc_modstat)) < 0) 2710aa342b1fSJoseph Koshy return (-1); 2711f263522aSJoseph Koshy 2712f263522aSJoseph Koshy pmc_syscall = pmc_modstat.data.intval; 2713f263522aSJoseph Koshy 2714f263522aSJoseph Koshy /* check the kernel module's ABI against our compiled-in version */ 2715f263522aSJoseph Koshy abi_version = PMC_VERSION; 2716f263522aSJoseph Koshy if (PMC_CALL(GETMODULEVERSION, &abi_version) < 0) 2717f263522aSJoseph Koshy return (pmc_syscall = -1); 2718f263522aSJoseph Koshy 2719f263522aSJoseph Koshy /* ignore patch & minor numbers for the comparision */ 2720f263522aSJoseph Koshy if ((abi_version & 0xFF000000) != (PMC_VERSION & 0xFF000000)) { 2721f263522aSJoseph Koshy errno = EPROGMISMATCH; 2722f263522aSJoseph Koshy return (pmc_syscall = -1); 2723f263522aSJoseph Koshy } 2724f263522aSJoseph Koshy 27251455fcd3SJoseph Koshy if (PMC_CALL(GETCPUINFO, &op_cpu_info) < 0) 2726f263522aSJoseph Koshy return (pmc_syscall = -1); 2727f263522aSJoseph Koshy 27281455fcd3SJoseph Koshy cpu_info.pm_cputype = op_cpu_info.pm_cputype; 27291455fcd3SJoseph Koshy cpu_info.pm_ncpu = op_cpu_info.pm_ncpu; 27301455fcd3SJoseph Koshy cpu_info.pm_npmc = op_cpu_info.pm_npmc; 27311455fcd3SJoseph Koshy cpu_info.pm_nclass = op_cpu_info.pm_nclass; 27321455fcd3SJoseph Koshy for (n = 0; n < cpu_info.pm_nclass; n++) 27331455fcd3SJoseph Koshy cpu_info.pm_classes[n] = op_cpu_info.pm_classes[n]; 27341455fcd3SJoseph Koshy 27350cfab8ddSJoseph Koshy pmc_class_table = malloc(PMC_CLASS_TABLE_SIZE * 27360cfab8ddSJoseph Koshy sizeof(struct pmc_class_descr *)); 27370cfab8ddSJoseph Koshy 27380cfab8ddSJoseph Koshy if (pmc_class_table == NULL) 27390cfab8ddSJoseph Koshy return (-1); 27400cfab8ddSJoseph Koshy 2741791f5d5bSJoseph Koshy for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) 2742791f5d5bSJoseph Koshy pmc_class_table[n] = NULL; 27430cfab8ddSJoseph Koshy 27440cfab8ddSJoseph Koshy /* 27450cfab8ddSJoseph Koshy * Fill in the class table. 27460cfab8ddSJoseph Koshy */ 27470cfab8ddSJoseph Koshy n = 0; 27480cfab8ddSJoseph Koshy #if defined(__amd64__) || defined(__i386__) 27490cfab8ddSJoseph Koshy pmc_class_table[n++] = &tsc_class_table_descr; 2750791f5d5bSJoseph Koshy 2751791f5d5bSJoseph Koshy /* 2752791f5d5bSJoseph Koshy * Check if this CPU has fixed function counters. 2753791f5d5bSJoseph Koshy */ 2754791f5d5bSJoseph Koshy cpu_has_iaf_counters = 0; 2755791f5d5bSJoseph Koshy for (t = 0; t < cpu_info.pm_nclass; t++) 27562aef9dd6SFabien Thomas if (cpu_info.pm_classes[t].pm_class == PMC_CLASS_IAF && 27572aef9dd6SFabien Thomas cpu_info.pm_classes[t].pm_num > 0) 2758791f5d5bSJoseph Koshy cpu_has_iaf_counters = 1; 27590cfab8ddSJoseph Koshy #endif 27600cfab8ddSJoseph Koshy 2761789140c0SJoseph Koshy #define PMC_MDEP_INIT(C) do { \ 2762789140c0SJoseph Koshy pmc_mdep_event_aliases = C##_aliases; \ 2763789140c0SJoseph Koshy pmc_mdep_class_list = C##_pmc_classes; \ 2764789140c0SJoseph Koshy pmc_mdep_class_list_size = \ 2765789140c0SJoseph Koshy PMC_TABLE_SIZE(C##_pmc_classes); \ 2766789140c0SJoseph Koshy } while (0) 2767789140c0SJoseph Koshy 2768791f5d5bSJoseph Koshy #define PMC_MDEP_INIT_INTEL_V2(C) do { \ 2769791f5d5bSJoseph Koshy PMC_MDEP_INIT(C); \ 2770791f5d5bSJoseph Koshy pmc_class_table[n++] = &iaf_class_table_descr; \ 27712aef9dd6SFabien Thomas if (!cpu_has_iaf_counters) \ 2772791f5d5bSJoseph Koshy pmc_mdep_event_aliases = \ 2773791f5d5bSJoseph Koshy C##_aliases_without_iaf; \ 2774791f5d5bSJoseph Koshy pmc_class_table[n] = &C##_class_table_descr; \ 2775791f5d5bSJoseph Koshy } while (0) 2776791f5d5bSJoseph Koshy 2777789140c0SJoseph Koshy /* Configure the event name parser. */ 2778f263522aSJoseph Koshy switch (cpu_info.pm_cputype) { 2779f263522aSJoseph Koshy #if defined(__i386__) 2780f263522aSJoseph Koshy case PMC_CPU_AMD_K7: 2781789140c0SJoseph Koshy PMC_MDEP_INIT(k7); 27820cfab8ddSJoseph Koshy pmc_class_table[n] = &k7_class_table_descr; 2783f263522aSJoseph Koshy break; 2784f263522aSJoseph Koshy case PMC_CPU_INTEL_P5: 2785789140c0SJoseph Koshy PMC_MDEP_INIT(p5); 27860cfab8ddSJoseph Koshy pmc_class_table[n] = &p5_class_table_descr; 2787f263522aSJoseph Koshy break; 2788f263522aSJoseph Koshy case PMC_CPU_INTEL_P6: /* P6 ... Pentium M CPUs have */ 2789f263522aSJoseph Koshy case PMC_CPU_INTEL_PII: /* similar PMCs. */ 2790f263522aSJoseph Koshy case PMC_CPU_INTEL_PIII: 2791f263522aSJoseph Koshy case PMC_CPU_INTEL_PM: 2792789140c0SJoseph Koshy PMC_MDEP_INIT(p6); 27930cfab8ddSJoseph Koshy pmc_class_table[n] = &p6_class_table_descr; 2794f263522aSJoseph Koshy break; 279586a65549SJoseph Koshy #endif 279686a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 2797f263522aSJoseph Koshy case PMC_CPU_AMD_K8: 2798789140c0SJoseph Koshy PMC_MDEP_INIT(k8); 27990cfab8ddSJoseph Koshy pmc_class_table[n] = &k8_class_table_descr; 28000cfab8ddSJoseph Koshy break; 28010cfab8ddSJoseph Koshy case PMC_CPU_INTEL_ATOM: 2802791f5d5bSJoseph Koshy PMC_MDEP_INIT_INTEL_V2(atom); 28030cfab8ddSJoseph Koshy break; 28040cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE: 28050cfab8ddSJoseph Koshy PMC_MDEP_INIT(core); 2806bc315bbdSJoseph Koshy pmc_class_table[n] = &core_class_table_descr; 28070cfab8ddSJoseph Koshy break; 28080cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE2: 2809b4d091f3SJoseph Koshy case PMC_CPU_INTEL_CORE2EXTREME: 2810791f5d5bSJoseph Koshy PMC_MDEP_INIT_INTEL_V2(core2); 2811789140c0SJoseph Koshy break; 2812597979c4SJeff Roberson case PMC_CPU_INTEL_COREI7: 28131fa7f10bSFabien Thomas pmc_class_table[n++] = &ucf_class_table_descr; 28141fa7f10bSFabien Thomas pmc_class_table[n++] = &corei7uc_class_table_descr; 2815791f5d5bSJoseph Koshy PMC_MDEP_INIT_INTEL_V2(corei7); 2816597979c4SJeff Roberson break; 28171fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 28181fa7f10bSFabien Thomas pmc_class_table[n++] = &ucf_class_table_descr; 28191fa7f10bSFabien Thomas pmc_class_table[n++] = &westmereuc_class_table_descr; 28201fa7f10bSFabien Thomas PMC_MDEP_INIT_INTEL_V2(westmere); 28211fa7f10bSFabien Thomas break; 2822789140c0SJoseph Koshy case PMC_CPU_INTEL_PIV: 2823789140c0SJoseph Koshy PMC_MDEP_INIT(p4); 28240cfab8ddSJoseph Koshy pmc_class_table[n] = &p4_class_table_descr; 2825f263522aSJoseph Koshy break; 2826ebccf1e3SJoseph Koshy #endif 28270ce207d2SRui Paulo #if defined(__XSCALE__) 28280ce207d2SRui Paulo case PMC_CPU_INTEL_XSCALE: 28290ce207d2SRui Paulo PMC_MDEP_INIT(xscale); 28300ce207d2SRui Paulo pmc_class_table[n] = &xscale_class_table_descr; 28310ce207d2SRui Paulo break; 28320ce207d2SRui Paulo #endif 2833660df75eSGeorge V. Neville-Neil #if defined(__mips__) 2834660df75eSGeorge V. Neville-Neil case PMC_CPU_MIPS_24K: 2835660df75eSGeorge V. Neville-Neil PMC_MDEP_INIT(mips24k); 2836660df75eSGeorge V. Neville-Neil pmc_class_table[n] = &mips24k_class_table_descr; 2837660df75eSGeorge V. Neville-Neil break; 2838660df75eSGeorge V. Neville-Neil #endif /* __mips__ */ 2839*7b25dccaSJustin Hibbits #if defined(__powerpc__) 2840*7b25dccaSJustin Hibbits case PMC_CPU_PPC_7450: 2841*7b25dccaSJustin Hibbits PMC_MDEP_INIT(ppc7450); 2842*7b25dccaSJustin Hibbits pmc_class_table[n] = &ppc7450_class_table_descr; 2843*7b25dccaSJustin Hibbits break; 2844*7b25dccaSJustin Hibbits #endif 2845f263522aSJoseph Koshy default: 2846f263522aSJoseph Koshy /* 2847f263522aSJoseph Koshy * Some kind of CPU this version of the library knows nothing 2848f263522aSJoseph Koshy * about. This shouldn't happen since the abi version check 2849f263522aSJoseph Koshy * should have caught this. 2850f263522aSJoseph Koshy */ 2851f263522aSJoseph Koshy errno = ENXIO; 2852f263522aSJoseph Koshy return (pmc_syscall = -1); 2853f263522aSJoseph Koshy } 2854f263522aSJoseph Koshy 2855aa342b1fSJoseph Koshy return (0); 2856f263522aSJoseph Koshy } 2857f263522aSJoseph Koshy 2858f263522aSJoseph Koshy const char * 2859f263522aSJoseph Koshy pmc_name_of_capability(enum pmc_caps cap) 2860f263522aSJoseph Koshy { 2861f263522aSJoseph Koshy int i; 2862f263522aSJoseph Koshy 2863f263522aSJoseph Koshy /* 2864f263522aSJoseph Koshy * 'cap' should have a single bit set and should be in 2865f263522aSJoseph Koshy * range. 2866f263522aSJoseph Koshy */ 2867f263522aSJoseph Koshy if ((cap & (cap - 1)) || cap < PMC_CAP_FIRST || 2868f263522aSJoseph Koshy cap > PMC_CAP_LAST) { 2869f263522aSJoseph Koshy errno = EINVAL; 2870aa342b1fSJoseph Koshy return (NULL); 2871f263522aSJoseph Koshy } 2872f263522aSJoseph Koshy 2873f263522aSJoseph Koshy i = ffs(cap); 2874aa342b1fSJoseph Koshy return (pmc_capability_names[i - 1]); 2875f263522aSJoseph Koshy } 2876f263522aSJoseph Koshy 2877f263522aSJoseph Koshy const char * 2878f263522aSJoseph Koshy pmc_name_of_class(enum pmc_class pc) 2879f263522aSJoseph Koshy { 2880f263522aSJoseph Koshy if ((int) pc >= PMC_CLASS_FIRST && 2881f263522aSJoseph Koshy pc <= PMC_CLASS_LAST) 2882aa342b1fSJoseph Koshy return (pmc_class_names[pc]); 2883f263522aSJoseph Koshy 2884f263522aSJoseph Koshy errno = EINVAL; 2885aa342b1fSJoseph Koshy return (NULL); 2886f263522aSJoseph Koshy } 2887f263522aSJoseph Koshy 2888f263522aSJoseph Koshy const char * 2889f263522aSJoseph Koshy pmc_name_of_cputype(enum pmc_cputype cp) 2890f263522aSJoseph Koshy { 2891789140c0SJoseph Koshy size_t n; 2892789140c0SJoseph Koshy 2893789140c0SJoseph Koshy for (n = 0; n < PMC_TABLE_SIZE(pmc_cputype_names); n++) 2894789140c0SJoseph Koshy if (cp == pmc_cputype_names[n].pm_cputype) 2895789140c0SJoseph Koshy return (pmc_cputype_names[n].pm_name); 2896789140c0SJoseph Koshy 2897f263522aSJoseph Koshy errno = EINVAL; 2898aa342b1fSJoseph Koshy return (NULL); 2899f263522aSJoseph Koshy } 2900f263522aSJoseph Koshy 2901f263522aSJoseph Koshy const char * 2902f263522aSJoseph Koshy pmc_name_of_disposition(enum pmc_disp pd) 2903f263522aSJoseph Koshy { 2904f263522aSJoseph Koshy if ((int) pd >= PMC_DISP_FIRST && 2905f263522aSJoseph Koshy pd <= PMC_DISP_LAST) 2906aa342b1fSJoseph Koshy return (pmc_disposition_names[pd]); 2907f263522aSJoseph Koshy 2908f263522aSJoseph Koshy errno = EINVAL; 2909aa342b1fSJoseph Koshy return (NULL); 2910f263522aSJoseph Koshy } 2911f263522aSJoseph Koshy 2912f263522aSJoseph Koshy const char * 29130cfab8ddSJoseph Koshy _pmc_name_of_event(enum pmc_event pe, enum pmc_cputype cpu) 2914f263522aSJoseph Koshy { 2915789140c0SJoseph Koshy const struct pmc_event_descr *ev, *evfence; 2916789140c0SJoseph Koshy 2917789140c0SJoseph Koshy ev = evfence = NULL; 29180cfab8ddSJoseph Koshy if (pe >= PMC_EV_IAF_FIRST && pe <= PMC_EV_IAF_LAST) { 29190cfab8ddSJoseph Koshy ev = iaf_event_table; 29200cfab8ddSJoseph Koshy evfence = iaf_event_table + PMC_EVENT_TABLE_SIZE(iaf); 29210cfab8ddSJoseph Koshy } else if (pe >= PMC_EV_IAP_FIRST && pe <= PMC_EV_IAP_LAST) { 29220cfab8ddSJoseph Koshy switch (cpu) { 29230cfab8ddSJoseph Koshy case PMC_CPU_INTEL_ATOM: 29240cfab8ddSJoseph Koshy ev = atom_event_table; 29250cfab8ddSJoseph Koshy evfence = atom_event_table + PMC_EVENT_TABLE_SIZE(atom); 29260cfab8ddSJoseph Koshy break; 29270cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE: 29280cfab8ddSJoseph Koshy ev = core_event_table; 29290cfab8ddSJoseph Koshy evfence = core_event_table + PMC_EVENT_TABLE_SIZE(core); 29300cfab8ddSJoseph Koshy break; 29310cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE2: 2932b4d091f3SJoseph Koshy case PMC_CPU_INTEL_CORE2EXTREME: 29330cfab8ddSJoseph Koshy ev = core2_event_table; 29340cfab8ddSJoseph Koshy evfence = core2_event_table + PMC_EVENT_TABLE_SIZE(core2); 29350cfab8ddSJoseph Koshy break; 2936597979c4SJeff Roberson case PMC_CPU_INTEL_COREI7: 2937597979c4SJeff Roberson ev = corei7_event_table; 2938597979c4SJeff Roberson evfence = corei7_event_table + PMC_EVENT_TABLE_SIZE(corei7); 2939597979c4SJeff Roberson break; 29401fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 29411fa7f10bSFabien Thomas ev = westmere_event_table; 29421fa7f10bSFabien Thomas evfence = westmere_event_table + PMC_EVENT_TABLE_SIZE(westmere); 29431fa7f10bSFabien Thomas break; 29440cfab8ddSJoseph Koshy default: /* Unknown CPU type. */ 29450cfab8ddSJoseph Koshy break; 29460cfab8ddSJoseph Koshy } 29471fa7f10bSFabien Thomas } else if (pe >= PMC_EV_UCF_FIRST && pe <= PMC_EV_UCF_LAST) { 29481fa7f10bSFabien Thomas ev = ucf_event_table; 29491fa7f10bSFabien Thomas evfence = ucf_event_table + PMC_EVENT_TABLE_SIZE(ucf); 29501fa7f10bSFabien Thomas } else if (pe >= PMC_EV_UCP_FIRST && pe <= PMC_EV_UCP_LAST) { 29511fa7f10bSFabien Thomas switch (cpu) { 29521fa7f10bSFabien Thomas case PMC_CPU_INTEL_COREI7: 29531fa7f10bSFabien Thomas ev = corei7uc_event_table; 29541fa7f10bSFabien Thomas evfence = corei7uc_event_table + PMC_EVENT_TABLE_SIZE(corei7uc); 29551fa7f10bSFabien Thomas break; 29561fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 29571fa7f10bSFabien Thomas ev = westmereuc_event_table; 29581fa7f10bSFabien Thomas evfence = westmereuc_event_table + PMC_EVENT_TABLE_SIZE(westmereuc); 29591fa7f10bSFabien Thomas break; 29601fa7f10bSFabien Thomas default: /* Unknown CPU type. */ 29611fa7f10bSFabien Thomas break; 29621fa7f10bSFabien Thomas } 29631fa7f10bSFabien Thomas } else if (pe >= PMC_EV_K7_FIRST && pe <= PMC_EV_K7_LAST) { 2964789140c0SJoseph Koshy ev = k7_event_table; 2965789140c0SJoseph Koshy evfence = k7_event_table + PMC_EVENT_TABLE_SIZE(k7); 2966789140c0SJoseph Koshy } else if (pe >= PMC_EV_K8_FIRST && pe <= PMC_EV_K8_LAST) { 2967789140c0SJoseph Koshy ev = k8_event_table; 2968789140c0SJoseph Koshy evfence = k8_event_table + PMC_EVENT_TABLE_SIZE(k8); 2969789140c0SJoseph Koshy } else if (pe >= PMC_EV_P4_FIRST && pe <= PMC_EV_P4_LAST) { 2970789140c0SJoseph Koshy ev = p4_event_table; 2971789140c0SJoseph Koshy evfence = p4_event_table + PMC_EVENT_TABLE_SIZE(p4); 2972789140c0SJoseph Koshy } else if (pe >= PMC_EV_P5_FIRST && pe <= PMC_EV_P5_LAST) { 2973789140c0SJoseph Koshy ev = p5_event_table; 2974789140c0SJoseph Koshy evfence = p5_event_table + PMC_EVENT_TABLE_SIZE(p5); 2975789140c0SJoseph Koshy } else if (pe >= PMC_EV_P6_FIRST && pe <= PMC_EV_P6_LAST) { 2976789140c0SJoseph Koshy ev = p6_event_table; 2977789140c0SJoseph Koshy evfence = p6_event_table + PMC_EVENT_TABLE_SIZE(p6); 29780ce207d2SRui Paulo } else if (pe >= PMC_EV_XSCALE_FIRST && pe <= PMC_EV_XSCALE_LAST) { 29790ce207d2SRui Paulo ev = xscale_event_table; 29800ce207d2SRui Paulo evfence = xscale_event_table + PMC_EVENT_TABLE_SIZE(xscale); 2981660df75eSGeorge V. Neville-Neil } else if (pe >= PMC_EV_MIPS24K_FIRST && pe <= PMC_EV_MIPS24K_LAST) { 2982660df75eSGeorge V. Neville-Neil ev = mips24k_event_table; 2983660df75eSGeorge V. Neville-Neil evfence = mips24k_event_table + PMC_EVENT_TABLE_SIZE(mips24k 2984660df75eSGeorge V. Neville-Neil ); 2985*7b25dccaSJustin Hibbits } else if (pe >= PMC_EV_PPC7450_FIRST && pe <= PMC_EV_PPC7450_LAST) { 2986*7b25dccaSJustin Hibbits ev = ppc7450_event_table; 2987*7b25dccaSJustin Hibbits evfence = ppc7450_event_table + PMC_EVENT_TABLE_SIZE(ppc7450 2988*7b25dccaSJustin Hibbits ); 2989789140c0SJoseph Koshy } else if (pe == PMC_EV_TSC_TSC) { 2990789140c0SJoseph Koshy ev = tsc_event_table; 2991789140c0SJoseph Koshy evfence = tsc_event_table + PMC_EVENT_TABLE_SIZE(tsc); 2992789140c0SJoseph Koshy } 2993789140c0SJoseph Koshy 2994789140c0SJoseph Koshy for (; ev != evfence; ev++) 2995789140c0SJoseph Koshy if (pe == ev->pm_ev_code) 2996789140c0SJoseph Koshy return (ev->pm_ev_name); 2997f263522aSJoseph Koshy 29980cfab8ddSJoseph Koshy return (NULL); 29990cfab8ddSJoseph Koshy } 30000cfab8ddSJoseph Koshy 30010cfab8ddSJoseph Koshy const char * 30020cfab8ddSJoseph Koshy pmc_name_of_event(enum pmc_event pe) 30030cfab8ddSJoseph Koshy { 30040cfab8ddSJoseph Koshy const char *n; 30050cfab8ddSJoseph Koshy 30060cfab8ddSJoseph Koshy if ((n = _pmc_name_of_event(pe, cpu_info.pm_cputype)) != NULL) 30070cfab8ddSJoseph Koshy return (n); 30080cfab8ddSJoseph Koshy 3009f263522aSJoseph Koshy errno = EINVAL; 3010aa342b1fSJoseph Koshy return (NULL); 3011f263522aSJoseph Koshy } 3012f263522aSJoseph Koshy 3013f263522aSJoseph Koshy const char * 3014f263522aSJoseph Koshy pmc_name_of_mode(enum pmc_mode pm) 3015f263522aSJoseph Koshy { 3016f263522aSJoseph Koshy if ((int) pm >= PMC_MODE_FIRST && 3017f263522aSJoseph Koshy pm <= PMC_MODE_LAST) 3018aa342b1fSJoseph Koshy return (pmc_mode_names[pm]); 3019f263522aSJoseph Koshy 3020f263522aSJoseph Koshy errno = EINVAL; 3021aa342b1fSJoseph Koshy return (NULL); 3022f263522aSJoseph Koshy } 3023f263522aSJoseph Koshy 3024f263522aSJoseph Koshy const char * 3025f263522aSJoseph Koshy pmc_name_of_state(enum pmc_state ps) 3026f263522aSJoseph Koshy { 3027f263522aSJoseph Koshy if ((int) ps >= PMC_STATE_FIRST && 3028f263522aSJoseph Koshy ps <= PMC_STATE_LAST) 3029aa342b1fSJoseph Koshy return (pmc_state_names[ps]); 3030f263522aSJoseph Koshy 3031f263522aSJoseph Koshy errno = EINVAL; 3032aa342b1fSJoseph Koshy return (NULL); 3033f263522aSJoseph Koshy } 3034f263522aSJoseph Koshy 3035f263522aSJoseph Koshy int 3036f263522aSJoseph Koshy pmc_ncpu(void) 3037f263522aSJoseph Koshy { 3038f263522aSJoseph Koshy if (pmc_syscall == -1) { 3039f263522aSJoseph Koshy errno = ENXIO; 3040aa342b1fSJoseph Koshy return (-1); 3041f263522aSJoseph Koshy } 3042f263522aSJoseph Koshy 3043aa342b1fSJoseph Koshy return (cpu_info.pm_ncpu); 3044f263522aSJoseph Koshy } 3045f263522aSJoseph Koshy 3046f263522aSJoseph Koshy int 3047f263522aSJoseph Koshy pmc_npmc(int cpu) 3048f263522aSJoseph Koshy { 3049f263522aSJoseph Koshy if (pmc_syscall == -1) { 3050f263522aSJoseph Koshy errno = ENXIO; 3051aa342b1fSJoseph Koshy return (-1); 3052f263522aSJoseph Koshy } 3053f263522aSJoseph Koshy 3054f263522aSJoseph Koshy if (cpu < 0 || cpu >= (int) cpu_info.pm_ncpu) { 3055f263522aSJoseph Koshy errno = EINVAL; 3056aa342b1fSJoseph Koshy return (-1); 3057f263522aSJoseph Koshy } 3058f263522aSJoseph Koshy 3059aa342b1fSJoseph Koshy return (cpu_info.pm_npmc); 3060f263522aSJoseph Koshy } 3061f263522aSJoseph Koshy 3062f263522aSJoseph Koshy int 3063f263522aSJoseph Koshy pmc_pmcinfo(int cpu, struct pmc_pmcinfo **ppmci) 3064f263522aSJoseph Koshy { 3065f263522aSJoseph Koshy int nbytes, npmc; 3066f263522aSJoseph Koshy struct pmc_op_getpmcinfo *pmci; 3067f263522aSJoseph Koshy 3068f263522aSJoseph Koshy if ((npmc = pmc_npmc(cpu)) < 0) 3069aa342b1fSJoseph Koshy return (-1); 3070f263522aSJoseph Koshy 3071f263522aSJoseph Koshy nbytes = sizeof(struct pmc_op_getpmcinfo) + 3072f263522aSJoseph Koshy npmc * sizeof(struct pmc_info); 3073f263522aSJoseph Koshy 3074f263522aSJoseph Koshy if ((pmci = calloc(1, nbytes)) == NULL) 3075aa342b1fSJoseph Koshy return (-1); 3076f263522aSJoseph Koshy 3077f263522aSJoseph Koshy pmci->pm_cpu = cpu; 3078f263522aSJoseph Koshy 3079f263522aSJoseph Koshy if (PMC_CALL(GETPMCINFO, pmci) < 0) { 3080f263522aSJoseph Koshy free(pmci); 3081aa342b1fSJoseph Koshy return (-1); 3082f263522aSJoseph Koshy } 3083f263522aSJoseph Koshy 3084f263522aSJoseph Koshy /* kernel<->library, library<->userland interfaces are identical */ 3085f263522aSJoseph Koshy *ppmci = (struct pmc_pmcinfo *) pmci; 3086aa342b1fSJoseph Koshy return (0); 3087f263522aSJoseph Koshy } 3088f263522aSJoseph Koshy 3089f263522aSJoseph Koshy int 3090f263522aSJoseph Koshy pmc_read(pmc_id_t pmc, pmc_value_t *value) 3091f263522aSJoseph Koshy { 3092f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_read_op; 3093f263522aSJoseph Koshy 3094f263522aSJoseph Koshy pmc_read_op.pm_pmcid = pmc; 3095f263522aSJoseph Koshy pmc_read_op.pm_flags = PMC_F_OLDVALUE; 3096f263522aSJoseph Koshy pmc_read_op.pm_value = -1; 3097f263522aSJoseph Koshy 3098f263522aSJoseph Koshy if (PMC_CALL(PMCRW, &pmc_read_op) < 0) 3099aa342b1fSJoseph Koshy return (-1); 3100f263522aSJoseph Koshy 3101f263522aSJoseph Koshy *value = pmc_read_op.pm_value; 3102aa342b1fSJoseph Koshy return (0); 3103f263522aSJoseph Koshy } 3104f263522aSJoseph Koshy 3105f263522aSJoseph Koshy int 3106f263522aSJoseph Koshy pmc_release(pmc_id_t pmc) 3107f263522aSJoseph Koshy { 3108f263522aSJoseph Koshy struct pmc_op_simple pmc_release_args; 3109f263522aSJoseph Koshy 3110f263522aSJoseph Koshy pmc_release_args.pm_pmcid = pmc; 3111aa342b1fSJoseph Koshy return (PMC_CALL(PMCRELEASE, &pmc_release_args)); 3112f263522aSJoseph Koshy } 3113f263522aSJoseph Koshy 3114f263522aSJoseph Koshy int 3115f263522aSJoseph Koshy pmc_rw(pmc_id_t pmc, pmc_value_t newvalue, pmc_value_t *oldvaluep) 3116f263522aSJoseph Koshy { 3117f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_rw_op; 3118f263522aSJoseph Koshy 3119f263522aSJoseph Koshy pmc_rw_op.pm_pmcid = pmc; 3120f263522aSJoseph Koshy pmc_rw_op.pm_flags = PMC_F_NEWVALUE | PMC_F_OLDVALUE; 3121f263522aSJoseph Koshy pmc_rw_op.pm_value = newvalue; 3122f263522aSJoseph Koshy 3123f263522aSJoseph Koshy if (PMC_CALL(PMCRW, &pmc_rw_op) < 0) 3124aa342b1fSJoseph Koshy return (-1); 3125f263522aSJoseph Koshy 3126f263522aSJoseph Koshy *oldvaluep = pmc_rw_op.pm_value; 3127aa342b1fSJoseph Koshy return (0); 3128f263522aSJoseph Koshy } 3129f263522aSJoseph Koshy 3130f263522aSJoseph Koshy int 3131f263522aSJoseph Koshy pmc_set(pmc_id_t pmc, pmc_value_t value) 3132f263522aSJoseph Koshy { 3133f263522aSJoseph Koshy struct pmc_op_pmcsetcount sc; 3134f263522aSJoseph Koshy 3135f263522aSJoseph Koshy sc.pm_pmcid = pmc; 3136f263522aSJoseph Koshy sc.pm_count = value; 3137f263522aSJoseph Koshy 3138f263522aSJoseph Koshy if (PMC_CALL(PMCSETCOUNT, &sc) < 0) 3139aa342b1fSJoseph Koshy return (-1); 3140aa342b1fSJoseph Koshy return (0); 3141f263522aSJoseph Koshy } 3142f263522aSJoseph Koshy 3143f263522aSJoseph Koshy int 3144f263522aSJoseph Koshy pmc_start(pmc_id_t pmc) 3145f263522aSJoseph Koshy { 3146f263522aSJoseph Koshy struct pmc_op_simple pmc_start_args; 3147f263522aSJoseph Koshy 3148f263522aSJoseph Koshy pmc_start_args.pm_pmcid = pmc; 3149aa342b1fSJoseph Koshy return (PMC_CALL(PMCSTART, &pmc_start_args)); 3150f263522aSJoseph Koshy } 3151f263522aSJoseph Koshy 3152f263522aSJoseph Koshy int 3153f263522aSJoseph Koshy pmc_stop(pmc_id_t pmc) 3154f263522aSJoseph Koshy { 3155f263522aSJoseph Koshy struct pmc_op_simple pmc_stop_args; 3156f263522aSJoseph Koshy 3157f263522aSJoseph Koshy pmc_stop_args.pm_pmcid = pmc; 3158aa342b1fSJoseph Koshy return (PMC_CALL(PMCSTOP, &pmc_stop_args)); 3159f263522aSJoseph Koshy } 3160f263522aSJoseph Koshy 3161f263522aSJoseph Koshy int 3162f263522aSJoseph Koshy pmc_width(pmc_id_t pmcid, uint32_t *width) 3163f263522aSJoseph Koshy { 3164f263522aSJoseph Koshy unsigned int i; 3165f263522aSJoseph Koshy enum pmc_class cl; 3166f263522aSJoseph Koshy 3167f263522aSJoseph Koshy cl = PMC_ID_TO_CLASS(pmcid); 3168f263522aSJoseph Koshy for (i = 0; i < cpu_info.pm_nclass; i++) 3169f263522aSJoseph Koshy if (cpu_info.pm_classes[i].pm_class == cl) { 3170f263522aSJoseph Koshy *width = cpu_info.pm_classes[i].pm_width; 3171aa342b1fSJoseph Koshy return (0); 3172f263522aSJoseph Koshy } 3173484202faSJoseph Koshy errno = EINVAL; 3174484202faSJoseph Koshy return (-1); 3175f263522aSJoseph Koshy } 3176f263522aSJoseph Koshy 3177f263522aSJoseph Koshy int 3178f263522aSJoseph Koshy pmc_write(pmc_id_t pmc, pmc_value_t value) 3179f263522aSJoseph Koshy { 3180f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_write_op; 3181f263522aSJoseph Koshy 3182f263522aSJoseph Koshy pmc_write_op.pm_pmcid = pmc; 3183f263522aSJoseph Koshy pmc_write_op.pm_flags = PMC_F_NEWVALUE; 3184f263522aSJoseph Koshy pmc_write_op.pm_value = value; 3185aa342b1fSJoseph Koshy return (PMC_CALL(PMCRW, &pmc_write_op)); 3186f263522aSJoseph Koshy } 3187f263522aSJoseph Koshy 3188f263522aSJoseph Koshy int 3189f263522aSJoseph Koshy pmc_writelog(uint32_t userdata) 3190f263522aSJoseph Koshy { 3191f263522aSJoseph Koshy struct pmc_op_writelog wl; 3192f263522aSJoseph Koshy 3193f263522aSJoseph Koshy wl.pm_userdata = userdata; 3194aa342b1fSJoseph Koshy return (PMC_CALL(WRITELOG, &wl)); 3195f263522aSJoseph Koshy } 3196