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 86660df75eSGeorge V. Neville-Neil 87ebccf1e3SJoseph Koshy #define PMC_CALL(cmd, params) \ 88ebccf1e3SJoseph Koshy syscall(pmc_syscall, PMC_OP_##cmd, (params)) 89ebccf1e3SJoseph Koshy 90ebccf1e3SJoseph Koshy /* 91ebccf1e3SJoseph Koshy * Event aliases provide a way for the user to ask for generic events 92ebccf1e3SJoseph Koshy * like "cache-misses", or "instructions-retired". These aliases are 93ebccf1e3SJoseph Koshy * mapped to the appropriate canonical event descriptions using a 94ebccf1e3SJoseph Koshy * lookup table. 95ebccf1e3SJoseph Koshy */ 96ebccf1e3SJoseph Koshy struct pmc_event_alias { 97ebccf1e3SJoseph Koshy const char *pm_alias; 98ebccf1e3SJoseph Koshy const char *pm_spec; 99ebccf1e3SJoseph Koshy }; 100ebccf1e3SJoseph Koshy 101ebccf1e3SJoseph Koshy static const struct pmc_event_alias *pmc_mdep_event_aliases; 102ebccf1e3SJoseph Koshy 103ebccf1e3SJoseph Koshy /* 104789140c0SJoseph Koshy * The pmc_event_descr structure maps symbolic names known to the user 105ebccf1e3SJoseph Koshy * to integer codes used by the PMC KLD. 106ebccf1e3SJoseph Koshy */ 107ebccf1e3SJoseph Koshy struct pmc_event_descr { 108ebccf1e3SJoseph Koshy const char *pm_ev_name; 109ebccf1e3SJoseph Koshy enum pmc_event pm_ev_code; 110ebccf1e3SJoseph Koshy }; 111ebccf1e3SJoseph Koshy 112789140c0SJoseph Koshy /* 113789140c0SJoseph Koshy * The pmc_class_descr structure maps class name prefixes for 114789140c0SJoseph Koshy * event names to event tables and other PMC class data. 115789140c0SJoseph Koshy */ 116789140c0SJoseph Koshy struct pmc_class_descr { 117789140c0SJoseph Koshy const char *pm_evc_name; 118789140c0SJoseph Koshy size_t pm_evc_name_size; 119789140c0SJoseph Koshy enum pmc_class pm_evc_class; 120789140c0SJoseph Koshy const struct pmc_event_descr *pm_evc_event_table; 121789140c0SJoseph Koshy size_t pm_evc_event_table_size; 122789140c0SJoseph Koshy int (*pm_evc_allocate_pmc)(enum pmc_event _pe, 123789140c0SJoseph Koshy char *_ctrspec, struct pmc_op_pmcallocate *_pa); 124ebccf1e3SJoseph Koshy }; 125ebccf1e3SJoseph Koshy 126789140c0SJoseph Koshy #define PMC_TABLE_SIZE(N) (sizeof(N)/sizeof(N[0])) 127789140c0SJoseph Koshy #define PMC_EVENT_TABLE_SIZE(N) PMC_TABLE_SIZE(N##_event_table) 128789140c0SJoseph Koshy 129789140c0SJoseph Koshy #undef __PMC_EV 130789140c0SJoseph Koshy #define __PMC_EV(C,N) { #N, PMC_EV_ ## C ## _ ## N }, 131789140c0SJoseph Koshy 132789140c0SJoseph Koshy /* 1330cfab8ddSJoseph Koshy * PMC_CLASSDEP_TABLE(NAME, CLASS) 134789140c0SJoseph Koshy * 1350cfab8ddSJoseph Koshy * Define a table mapping event names and aliases to HWPMC event IDs. 136789140c0SJoseph Koshy */ 1370cfab8ddSJoseph Koshy #define PMC_CLASSDEP_TABLE(N, C) \ 138789140c0SJoseph Koshy static const struct pmc_event_descr N##_event_table[] = \ 139789140c0SJoseph Koshy { \ 140789140c0SJoseph Koshy __PMC_EV_##C() \ 1410cfab8ddSJoseph Koshy } 1420cfab8ddSJoseph Koshy 1430cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(iaf, IAF); 1440cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(k7, K7); 1450cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(k8, K8); 1460cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(p4, P4); 1470cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(p5, P5); 1480cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(p6, P6); 1490ce207d2SRui Paulo PMC_CLASSDEP_TABLE(xscale, XSCALE); 150660df75eSGeorge V. Neville-Neil PMC_CLASSDEP_TABLE(mips24k, MIPS24K); 1511fa7f10bSFabien Thomas PMC_CLASSDEP_TABLE(ucf, UCF); 1520cfab8ddSJoseph Koshy 1530cfab8ddSJoseph Koshy #undef __PMC_EV_ALIAS 1540cfab8ddSJoseph Koshy #define __PMC_EV_ALIAS(N,CODE) { N, PMC_EV_##CODE }, 1550cfab8ddSJoseph Koshy 1560cfab8ddSJoseph Koshy static const struct pmc_event_descr atom_event_table[] = 1570cfab8ddSJoseph Koshy { 1580cfab8ddSJoseph Koshy __PMC_EV_ALIAS_ATOM() 1590cfab8ddSJoseph Koshy }; 1600cfab8ddSJoseph Koshy 1610cfab8ddSJoseph Koshy static const struct pmc_event_descr core_event_table[] = 1620cfab8ddSJoseph Koshy { 1630cfab8ddSJoseph Koshy __PMC_EV_ALIAS_CORE() 1640cfab8ddSJoseph Koshy }; 1650cfab8ddSJoseph Koshy 1660cfab8ddSJoseph Koshy 1670cfab8ddSJoseph Koshy static const struct pmc_event_descr core2_event_table[] = 1680cfab8ddSJoseph Koshy { 1690cfab8ddSJoseph Koshy __PMC_EV_ALIAS_CORE2() 1700cfab8ddSJoseph Koshy }; 1710cfab8ddSJoseph Koshy 172597979c4SJeff Roberson static const struct pmc_event_descr corei7_event_table[] = 173597979c4SJeff Roberson { 174597979c4SJeff Roberson __PMC_EV_ALIAS_COREI7() 175597979c4SJeff Roberson }; 176597979c4SJeff Roberson 1771fa7f10bSFabien Thomas static const struct pmc_event_descr westmere_event_table[] = 1781fa7f10bSFabien Thomas { 1791fa7f10bSFabien Thomas __PMC_EV_ALIAS_WESTMERE() 1801fa7f10bSFabien Thomas }; 1811fa7f10bSFabien Thomas 1821fa7f10bSFabien Thomas static const struct pmc_event_descr corei7uc_event_table[] = 1831fa7f10bSFabien Thomas { 1841fa7f10bSFabien Thomas __PMC_EV_ALIAS_COREI7UC() 1851fa7f10bSFabien Thomas }; 1861fa7f10bSFabien Thomas 1871fa7f10bSFabien Thomas static const struct pmc_event_descr westmereuc_event_table[] = 1881fa7f10bSFabien Thomas { 1891fa7f10bSFabien Thomas __PMC_EV_ALIAS_WESTMEREUC() 1901fa7f10bSFabien Thomas }; 1911fa7f10bSFabien Thomas 1920cfab8ddSJoseph Koshy /* 1930cfab8ddSJoseph Koshy * PMC_MDEP_TABLE(NAME, PRIMARYCLASS, ADDITIONAL_CLASSES...) 1940cfab8ddSJoseph Koshy * 1950cfab8ddSJoseph Koshy * Map a CPU to the PMC classes it supports. 1960cfab8ddSJoseph Koshy */ 1970cfab8ddSJoseph Koshy #define PMC_MDEP_TABLE(N,C,...) \ 198789140c0SJoseph Koshy static const enum pmc_class N##_pmc_classes[] = { \ 199789140c0SJoseph Koshy PMC_CLASS_##C, __VA_ARGS__ \ 200789140c0SJoseph Koshy } 201789140c0SJoseph Koshy 2020cfab8ddSJoseph Koshy PMC_MDEP_TABLE(atom, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC); 2030cfab8ddSJoseph Koshy PMC_MDEP_TABLE(core, IAP, PMC_CLASS_TSC); 2040cfab8ddSJoseph Koshy PMC_MDEP_TABLE(core2, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC); 2051fa7f10bSFabien Thomas PMC_MDEP_TABLE(corei7, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 2061fa7f10bSFabien Thomas PMC_MDEP_TABLE(westmere, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 207789140c0SJoseph Koshy PMC_MDEP_TABLE(k7, K7, PMC_CLASS_TSC); 208789140c0SJoseph Koshy PMC_MDEP_TABLE(k8, K8, PMC_CLASS_TSC); 209789140c0SJoseph Koshy PMC_MDEP_TABLE(p4, P4, PMC_CLASS_TSC); 210789140c0SJoseph Koshy PMC_MDEP_TABLE(p5, P5, PMC_CLASS_TSC); 211789140c0SJoseph Koshy PMC_MDEP_TABLE(p6, P6, PMC_CLASS_TSC); 2120ce207d2SRui Paulo PMC_MDEP_TABLE(xscale, XSCALE, PMC_CLASS_XSCALE); 213660df75eSGeorge V. Neville-Neil PMC_MDEP_TABLE(mips24k, MIPS24K, PMC_CLASS_MIPS24K); 214789140c0SJoseph Koshy 215789140c0SJoseph Koshy static const struct pmc_event_descr tsc_event_table[] = 216789140c0SJoseph Koshy { 217789140c0SJoseph Koshy __PMC_EV_TSC() 218789140c0SJoseph Koshy }; 219789140c0SJoseph Koshy 220789140c0SJoseph Koshy #undef PMC_CLASS_TABLE_DESC 2210cfab8ddSJoseph Koshy #define PMC_CLASS_TABLE_DESC(NAME, CLASS, EVENTS, ALLOCATOR) \ 2220cfab8ddSJoseph Koshy static const struct pmc_class_descr NAME##_class_table_descr = \ 2230cfab8ddSJoseph Koshy { \ 2240cfab8ddSJoseph Koshy .pm_evc_name = #CLASS "-", \ 2250cfab8ddSJoseph Koshy .pm_evc_name_size = sizeof(#CLASS "-") - 1, \ 2260cfab8ddSJoseph Koshy .pm_evc_class = PMC_CLASS_##CLASS , \ 2270cfab8ddSJoseph Koshy .pm_evc_event_table = EVENTS##_event_table , \ 228789140c0SJoseph Koshy .pm_evc_event_table_size = \ 2290cfab8ddSJoseph Koshy PMC_EVENT_TABLE_SIZE(EVENTS), \ 2300cfab8ddSJoseph Koshy .pm_evc_allocate_pmc = ALLOCATOR##_allocate_pmc \ 231789140c0SJoseph Koshy } 232789140c0SJoseph Koshy 233789140c0SJoseph Koshy #if defined(__i386__) || defined(__amd64__) 2340cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(iaf, IAF, iaf, iaf); 2350cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(atom, IAP, atom, iap); 2360cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(core, IAP, core, iap); 2370cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(core2, IAP, core2, iap); 238597979c4SJeff Roberson PMC_CLASS_TABLE_DESC(corei7, IAP, corei7, iap); 2391fa7f10bSFabien Thomas PMC_CLASS_TABLE_DESC(westmere, IAP, westmere, iap); 2401fa7f10bSFabien Thomas PMC_CLASS_TABLE_DESC(ucf, UCF, ucf, ucf); 2411fa7f10bSFabien Thomas PMC_CLASS_TABLE_DESC(corei7uc, UCP, corei7uc, ucp); 2421fa7f10bSFabien Thomas PMC_CLASS_TABLE_DESC(westmereuc, UCP, westmereuc, ucp); 243789140c0SJoseph Koshy #endif 244789140c0SJoseph Koshy #if defined(__i386__) 2450cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(k7, K7, k7, k7); 246789140c0SJoseph Koshy #endif 247789140c0SJoseph Koshy #if defined(__i386__) || defined(__amd64__) 2480cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(k8, K8, k8, k8); 2490cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(p4, P4, p4, p4); 250789140c0SJoseph Koshy #endif 2510cfab8ddSJoseph Koshy #if defined(__i386__) 2520cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(p5, P5, p5, p5); 2530cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(p6, P6, p6, p6); 2540cfab8ddSJoseph Koshy #endif 2550cfab8ddSJoseph Koshy #if defined(__i386__) || defined(__amd64__) 2560cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(tsc, TSC, tsc, tsc); 2570cfab8ddSJoseph Koshy #endif 2580ce207d2SRui Paulo #if defined(__XSCALE__) 2590ce207d2SRui Paulo PMC_CLASS_TABLE_DESC(xscale, XSCALE, xscale, xscale); 2600ce207d2SRui Paulo #endif 261789140c0SJoseph Koshy 262660df75eSGeorge V. Neville-Neil #if defined(__mips__) 263660df75eSGeorge V. Neville-Neil PMC_CLASS_TABLE_DESC(mips24k, MIPS24K, mips24k, mips24k); 264660df75eSGeorge V. Neville-Neil #endif /* __mips__ */ 265660df75eSGeorge V. Neville-Neil 266789140c0SJoseph Koshy #undef PMC_CLASS_TABLE_DESC 267789140c0SJoseph Koshy 2680cfab8ddSJoseph Koshy static const struct pmc_class_descr **pmc_class_table; 2690cfab8ddSJoseph Koshy #define PMC_CLASS_TABLE_SIZE cpu_info.pm_nclass 2700cfab8ddSJoseph Koshy 271789140c0SJoseph Koshy static const enum pmc_class *pmc_mdep_class_list; 272789140c0SJoseph Koshy static size_t pmc_mdep_class_list_size; 273789140c0SJoseph Koshy 274ebccf1e3SJoseph Koshy /* 275ebccf1e3SJoseph Koshy * Mapping tables, mapping enumeration values to human readable 276ebccf1e3SJoseph Koshy * strings. 277ebccf1e3SJoseph Koshy */ 278ebccf1e3SJoseph Koshy 279ebccf1e3SJoseph Koshy static const char * pmc_capability_names[] = { 280ebccf1e3SJoseph Koshy #undef __PMC_CAP 281ebccf1e3SJoseph Koshy #define __PMC_CAP(N,V,D) #N , 282ebccf1e3SJoseph Koshy __PMC_CAPS() 283ebccf1e3SJoseph Koshy }; 284ebccf1e3SJoseph Koshy 285ebccf1e3SJoseph Koshy static const char * pmc_class_names[] = { 286ebccf1e3SJoseph Koshy #undef __PMC_CLASS 287ebccf1e3SJoseph Koshy #define __PMC_CLASS(C) #C , 288ebccf1e3SJoseph Koshy __PMC_CLASSES() 289ebccf1e3SJoseph Koshy }; 290ebccf1e3SJoseph Koshy 291789140c0SJoseph Koshy struct pmc_cputype_map { 292789140c0SJoseph Koshy enum pmc_class pm_cputype; 293789140c0SJoseph Koshy const char *pm_name; 294789140c0SJoseph Koshy }; 295789140c0SJoseph Koshy 296789140c0SJoseph Koshy static const struct pmc_cputype_map pmc_cputype_names[] = { 297ebccf1e3SJoseph Koshy #undef __PMC_CPU 298789140c0SJoseph Koshy #define __PMC_CPU(S, V, D) { .pm_cputype = PMC_CPU_##S, .pm_name = #S } , 299ebccf1e3SJoseph Koshy __PMC_CPUS() 300ebccf1e3SJoseph Koshy }; 301ebccf1e3SJoseph Koshy 302ebccf1e3SJoseph Koshy static const char * pmc_disposition_names[] = { 303ebccf1e3SJoseph Koshy #undef __PMC_DISP 304ebccf1e3SJoseph Koshy #define __PMC_DISP(D) #D , 305ebccf1e3SJoseph Koshy __PMC_DISPOSITIONS() 306ebccf1e3SJoseph Koshy }; 307ebccf1e3SJoseph Koshy 308ebccf1e3SJoseph Koshy static const char * pmc_mode_names[] = { 309ebccf1e3SJoseph Koshy #undef __PMC_MODE 310ebccf1e3SJoseph Koshy #define __PMC_MODE(M,N) #M , 311ebccf1e3SJoseph Koshy __PMC_MODES() 312ebccf1e3SJoseph Koshy }; 313ebccf1e3SJoseph Koshy 314ebccf1e3SJoseph Koshy static const char * pmc_state_names[] = { 315ebccf1e3SJoseph Koshy #undef __PMC_STATE 316ebccf1e3SJoseph Koshy #define __PMC_STATE(S) #S , 317ebccf1e3SJoseph Koshy __PMC_STATES() 318ebccf1e3SJoseph Koshy }; 319ebccf1e3SJoseph Koshy 320ebccf1e3SJoseph Koshy static int pmc_syscall = -1; /* filled in by pmc_init() */ 321ebccf1e3SJoseph Koshy 3221455fcd3SJoseph Koshy static struct pmc_cpuinfo cpu_info; /* filled in by pmc_init() */ 3231455fcd3SJoseph Koshy 324ebccf1e3SJoseph Koshy /* Event masks for events */ 325ebccf1e3SJoseph Koshy struct pmc_masks { 326ebccf1e3SJoseph Koshy const char *pm_name; 327ebccf1e3SJoseph Koshy const uint32_t pm_value; 328ebccf1e3SJoseph Koshy }; 329ebccf1e3SJoseph Koshy #define PMCMASK(N,V) { .pm_name = #N, .pm_value = (V) } 3301fa7f10bSFabien Thomas #define NULLMASK { .pm_name = NULL } 331ebccf1e3SJoseph Koshy 33286a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 333ebccf1e3SJoseph Koshy static int 334ebccf1e3SJoseph Koshy pmc_parse_mask(const struct pmc_masks *pmask, char *p, uint32_t *evmask) 335ebccf1e3SJoseph Koshy { 336ebccf1e3SJoseph Koshy const struct pmc_masks *pm; 337ebccf1e3SJoseph Koshy char *q, *r; 338ebccf1e3SJoseph Koshy int c; 339ebccf1e3SJoseph Koshy 340ebccf1e3SJoseph Koshy if (pmask == NULL) /* no mask keywords */ 341aa342b1fSJoseph Koshy return (-1); 342ebccf1e3SJoseph Koshy q = strchr(p, '='); /* skip '=' */ 343ebccf1e3SJoseph Koshy if (*++q == '\0') /* no more data */ 344aa342b1fSJoseph Koshy return (-1); 345ebccf1e3SJoseph Koshy c = 0; /* count of mask keywords seen */ 346ebccf1e3SJoseph Koshy while ((r = strsep(&q, "+")) != NULL) { 347789140c0SJoseph Koshy for (pm = pmask; pm->pm_name && strcasecmp(r, pm->pm_name); 348789140c0SJoseph Koshy pm++) 349ebccf1e3SJoseph Koshy ; 350ebccf1e3SJoseph Koshy if (pm->pm_name == NULL) /* not found */ 351aa342b1fSJoseph Koshy return (-1); 352ebccf1e3SJoseph Koshy *evmask |= pm->pm_value; 353ebccf1e3SJoseph Koshy c++; 354ebccf1e3SJoseph Koshy } 355aa342b1fSJoseph Koshy return (c); 356ebccf1e3SJoseph Koshy } 35704e9feb0SMarcel Moolenaar #endif 358ebccf1e3SJoseph Koshy 359ebccf1e3SJoseph Koshy #define KWMATCH(p,kw) (strcasecmp((p), (kw)) == 0) 360ebccf1e3SJoseph Koshy #define KWPREFIXMATCH(p,kw) (strncasecmp((p), (kw), sizeof((kw)) - 1) == 0) 361ebccf1e3SJoseph Koshy #define EV_ALIAS(N,S) { .pm_alias = N, .pm_spec = S } 362ebccf1e3SJoseph Koshy 36304e9feb0SMarcel Moolenaar #if defined(__i386__) 364ebccf1e3SJoseph Koshy 365ebccf1e3SJoseph Koshy /* 366ebccf1e3SJoseph Koshy * AMD K7 (Athlon) CPUs. 367ebccf1e3SJoseph Koshy */ 368ebccf1e3SJoseph Koshy 369ebccf1e3SJoseph Koshy static struct pmc_event_alias k7_aliases[] = { 370ebccf1e3SJoseph Koshy EV_ALIAS("branches", "k7-retired-branches"), 371ebccf1e3SJoseph Koshy EV_ALIAS("branch-mispredicts", "k7-retired-branches-mispredicted"), 372ebccf1e3SJoseph Koshy EV_ALIAS("cycles", "tsc"), 3736aa5a193SJoseph Koshy EV_ALIAS("dc-misses", "k7-dc-misses"), 374ebccf1e3SJoseph Koshy EV_ALIAS("ic-misses", "k7-ic-misses"), 375ebccf1e3SJoseph Koshy EV_ALIAS("instructions", "k7-retired-instructions"), 376ebccf1e3SJoseph Koshy EV_ALIAS("interrupts", "k7-hardware-interrupts"), 377ebccf1e3SJoseph Koshy EV_ALIAS(NULL, NULL) 378ebccf1e3SJoseph Koshy }; 379ebccf1e3SJoseph Koshy 380ebccf1e3SJoseph Koshy #define K7_KW_COUNT "count" 381ebccf1e3SJoseph Koshy #define K7_KW_EDGE "edge" 382ebccf1e3SJoseph Koshy #define K7_KW_INV "inv" 383ebccf1e3SJoseph Koshy #define K7_KW_OS "os" 384ebccf1e3SJoseph Koshy #define K7_KW_UNITMASK "unitmask" 385ebccf1e3SJoseph Koshy #define K7_KW_USR "usr" 386ebccf1e3SJoseph Koshy 387ebccf1e3SJoseph Koshy static int 388ebccf1e3SJoseph Koshy k7_allocate_pmc(enum pmc_event pe, char *ctrspec, 389ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 390ebccf1e3SJoseph Koshy { 391ebccf1e3SJoseph Koshy char *e, *p, *q; 392ebccf1e3SJoseph Koshy int c, has_unitmask; 393ebccf1e3SJoseph Koshy uint32_t count, unitmask; 394ebccf1e3SJoseph Koshy 395f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 396789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 397ebccf1e3SJoseph Koshy 398ebccf1e3SJoseph Koshy if (pe == PMC_EV_K7_DC_REFILLS_FROM_L2 || 399ebccf1e3SJoseph Koshy pe == PMC_EV_K7_DC_REFILLS_FROM_SYSTEM || 400ebccf1e3SJoseph Koshy pe == PMC_EV_K7_DC_WRITEBACKS) { 401ebccf1e3SJoseph Koshy has_unitmask = 1; 402f263522aSJoseph Koshy unitmask = AMD_PMC_UNITMASK_MOESI; 403ebccf1e3SJoseph Koshy } else 404ebccf1e3SJoseph Koshy unitmask = has_unitmask = 0; 405ebccf1e3SJoseph Koshy 406ebccf1e3SJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 407ebccf1e3SJoseph Koshy if (KWPREFIXMATCH(p, K7_KW_COUNT "=")) { 408ebccf1e3SJoseph Koshy q = strchr(p, '='); 409ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 410aa342b1fSJoseph Koshy return (-1); 411ebccf1e3SJoseph Koshy 412ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 413ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 414aa342b1fSJoseph Koshy return (-1); 415ebccf1e3SJoseph Koshy 416ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 417f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config |= 418f263522aSJoseph Koshy AMD_PMC_TO_COUNTER(count); 419ebccf1e3SJoseph Koshy 420ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_EDGE)) { 421ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 422ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_INV)) { 423ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 424ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_OS)) { 425ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 426ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, K7_KW_UNITMASK "=")) { 427ebccf1e3SJoseph Koshy if (has_unitmask == 0) 428aa342b1fSJoseph Koshy return (-1); 429ebccf1e3SJoseph Koshy unitmask = 0; 430ebccf1e3SJoseph Koshy q = strchr(p, '='); 431ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 432aa342b1fSJoseph Koshy return (-1); 433ebccf1e3SJoseph Koshy 434ebccf1e3SJoseph Koshy while ((c = tolower(*q++)) != 0) 435ebccf1e3SJoseph Koshy if (c == 'm') 436f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_M; 437ebccf1e3SJoseph Koshy else if (c == 'o') 438f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_O; 439ebccf1e3SJoseph Koshy else if (c == 'e') 440f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_E; 441ebccf1e3SJoseph Koshy else if (c == 's') 442f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_S; 443ebccf1e3SJoseph Koshy else if (c == 'i') 444f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_I; 445ebccf1e3SJoseph Koshy else if (c == '+') 446ebccf1e3SJoseph Koshy continue; 447ebccf1e3SJoseph Koshy else 448aa342b1fSJoseph Koshy return (-1); 449ebccf1e3SJoseph Koshy 450ebccf1e3SJoseph Koshy if (unitmask == 0) 451aa342b1fSJoseph Koshy return (-1); 452ebccf1e3SJoseph Koshy 453ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_USR)) { 454ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 455ebccf1e3SJoseph Koshy } else 456aa342b1fSJoseph Koshy return (-1); 457ebccf1e3SJoseph Koshy } 458ebccf1e3SJoseph Koshy 459ebccf1e3SJoseph Koshy if (has_unitmask) { 460ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 461f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config |= 462f263522aSJoseph Koshy AMD_PMC_TO_UNITMASK(unitmask); 463ebccf1e3SJoseph Koshy } 464ebccf1e3SJoseph Koshy 465aa342b1fSJoseph Koshy return (0); 466ebccf1e3SJoseph Koshy 467ebccf1e3SJoseph Koshy } 468ebccf1e3SJoseph Koshy 469f263522aSJoseph Koshy #endif 470f263522aSJoseph Koshy 47186a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 472f263522aSJoseph Koshy 473f263522aSJoseph Koshy /* 4740cfab8ddSJoseph Koshy * Intel Core (Family 6, Model E) PMCs. 4750cfab8ddSJoseph Koshy */ 4760cfab8ddSJoseph Koshy 4770cfab8ddSJoseph Koshy static struct pmc_event_alias core_aliases[] = { 4780cfab8ddSJoseph Koshy EV_ALIAS("branches", "iap-br-instr-ret"), 4790cfab8ddSJoseph Koshy EV_ALIAS("branch-mispredicts", "iap-br-mispred-ret"), 4800cfab8ddSJoseph Koshy EV_ALIAS("cycles", "tsc-tsc"), 4810cfab8ddSJoseph Koshy EV_ALIAS("ic-misses", "iap-icache-misses"), 4820cfab8ddSJoseph Koshy EV_ALIAS("instructions", "iap-instr-ret"), 4830cfab8ddSJoseph Koshy EV_ALIAS("interrupts", "iap-core-hw-int-rx"), 4840cfab8ddSJoseph Koshy EV_ALIAS("unhalted-cycles", "iap-unhalted-core-cycles"), 4850cfab8ddSJoseph Koshy EV_ALIAS(NULL, NULL) 4860cfab8ddSJoseph Koshy }; 4870cfab8ddSJoseph Koshy 4880cfab8ddSJoseph Koshy /* 4890cfab8ddSJoseph Koshy * Intel Core2 (Family 6, Model F), Core2Extreme (Family 6, Model 17H) 4900cfab8ddSJoseph Koshy * and Atom (Family 6, model 1CH) PMCs. 491791f5d5bSJoseph Koshy * 492791f5d5bSJoseph Koshy * We map aliases to events on the fixed-function counters if these 493791f5d5bSJoseph Koshy * are present. Note that not all CPUs in this family contain fixed-function 494791f5d5bSJoseph Koshy * counters. 4950cfab8ddSJoseph Koshy */ 4960cfab8ddSJoseph Koshy 4970cfab8ddSJoseph Koshy static struct pmc_event_alias core2_aliases[] = { 4980cfab8ddSJoseph Koshy EV_ALIAS("branches", "iap-br-inst-retired.any"), 4990cfab8ddSJoseph Koshy EV_ALIAS("branch-mispredicts", "iap-br-inst-retired.mispred"), 5000cfab8ddSJoseph Koshy EV_ALIAS("cycles", "tsc-tsc"), 5010cfab8ddSJoseph Koshy EV_ALIAS("ic-misses", "iap-l1i-misses"), 5020cfab8ddSJoseph Koshy EV_ALIAS("instructions", "iaf-instr-retired.any"), 5030cfab8ddSJoseph Koshy EV_ALIAS("interrupts", "iap-hw-int-rcv"), 5040cfab8ddSJoseph Koshy EV_ALIAS("unhalted-cycles", "iaf-cpu-clk-unhalted.core"), 5050cfab8ddSJoseph Koshy EV_ALIAS(NULL, NULL) 5060cfab8ddSJoseph Koshy }; 507791f5d5bSJoseph Koshy 508791f5d5bSJoseph Koshy static struct pmc_event_alias core2_aliases_without_iaf[] = { 509791f5d5bSJoseph Koshy EV_ALIAS("branches", "iap-br-inst-retired.any"), 510791f5d5bSJoseph Koshy EV_ALIAS("branch-mispredicts", "iap-br-inst-retired.mispred"), 511791f5d5bSJoseph Koshy EV_ALIAS("cycles", "tsc-tsc"), 512791f5d5bSJoseph Koshy EV_ALIAS("ic-misses", "iap-l1i-misses"), 513791f5d5bSJoseph Koshy EV_ALIAS("instructions", "iap-inst-retired.any_p"), 514791f5d5bSJoseph Koshy EV_ALIAS("interrupts", "iap-hw-int-rcv"), 515791f5d5bSJoseph Koshy EV_ALIAS("unhalted-cycles", "iap-cpu-clk-unhalted.core_p"), 516791f5d5bSJoseph Koshy EV_ALIAS(NULL, NULL) 517791f5d5bSJoseph Koshy }; 518791f5d5bSJoseph Koshy 5190cfab8ddSJoseph Koshy #define atom_aliases core2_aliases 520791f5d5bSJoseph Koshy #define atom_aliases_without_iaf core2_aliases_without_iaf 521597979c4SJeff Roberson #define corei7_aliases core2_aliases 522791f5d5bSJoseph Koshy #define corei7_aliases_without_iaf core2_aliases_without_iaf 5231fa7f10bSFabien Thomas #define westmere_aliases core2_aliases 5241fa7f10bSFabien Thomas #define westmere_aliases_without_iaf core2_aliases_without_iaf 5250cfab8ddSJoseph Koshy 5260cfab8ddSJoseph Koshy #define IAF_KW_OS "os" 5270cfab8ddSJoseph Koshy #define IAF_KW_USR "usr" 5280cfab8ddSJoseph Koshy #define IAF_KW_ANYTHREAD "anythread" 5290cfab8ddSJoseph Koshy 5300cfab8ddSJoseph Koshy /* 5310cfab8ddSJoseph Koshy * Parse an event specifier for Intel fixed function counters. 5320cfab8ddSJoseph Koshy */ 5330cfab8ddSJoseph Koshy static int 5340cfab8ddSJoseph Koshy iaf_allocate_pmc(enum pmc_event pe, char *ctrspec, 5350cfab8ddSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 5360cfab8ddSJoseph Koshy { 5370cfab8ddSJoseph Koshy char *p; 5380cfab8ddSJoseph Koshy 5390cfab8ddSJoseph Koshy (void) pe; 5400cfab8ddSJoseph Koshy 5410cfab8ddSJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 5420cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iaf.pm_iaf_flags = 0; 5430cfab8ddSJoseph Koshy 5440cfab8ddSJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 5450cfab8ddSJoseph Koshy if (KWMATCH(p, IAF_KW_OS)) 5460cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 5470cfab8ddSJoseph Koshy else if (KWMATCH(p, IAF_KW_USR)) 5480cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 5490cfab8ddSJoseph Koshy else if (KWMATCH(p, IAF_KW_ANYTHREAD)) 5500cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iaf.pm_iaf_flags |= IAF_ANY; 5510cfab8ddSJoseph Koshy else 5520cfab8ddSJoseph Koshy return (-1); 5530cfab8ddSJoseph Koshy } 5540cfab8ddSJoseph Koshy 5550cfab8ddSJoseph Koshy return (0); 5560cfab8ddSJoseph Koshy } 5570cfab8ddSJoseph Koshy 5580cfab8ddSJoseph Koshy /* 5590cfab8ddSJoseph Koshy * Core/Core2 support. 5600cfab8ddSJoseph Koshy */ 5610cfab8ddSJoseph Koshy 5620cfab8ddSJoseph Koshy #define IAP_KW_AGENT "agent" 5630cfab8ddSJoseph Koshy #define IAP_KW_ANYTHREAD "anythread" 5640cfab8ddSJoseph Koshy #define IAP_KW_CACHESTATE "cachestate" 5650cfab8ddSJoseph Koshy #define IAP_KW_CMASK "cmask" 5660cfab8ddSJoseph Koshy #define IAP_KW_CORE "core" 5670cfab8ddSJoseph Koshy #define IAP_KW_EDGE "edge" 5680cfab8ddSJoseph Koshy #define IAP_KW_INV "inv" 5690cfab8ddSJoseph Koshy #define IAP_KW_OS "os" 5700cfab8ddSJoseph Koshy #define IAP_KW_PREFETCH "prefetch" 5710cfab8ddSJoseph Koshy #define IAP_KW_SNOOPRESPONSE "snoopresponse" 5720cfab8ddSJoseph Koshy #define IAP_KW_SNOOPTYPE "snooptype" 5730cfab8ddSJoseph Koshy #define IAP_KW_TRANSITION "trans" 5740cfab8ddSJoseph Koshy #define IAP_KW_USR "usr" 5751fa7f10bSFabien Thomas #define IAP_KW_RSP "rsp" 5760cfab8ddSJoseph Koshy 5770cfab8ddSJoseph Koshy static struct pmc_masks iap_core_mask[] = { 5780cfab8ddSJoseph Koshy PMCMASK(all, (0x3 << 14)), 5790cfab8ddSJoseph Koshy PMCMASK(this, (0x1 << 14)), 5800cfab8ddSJoseph Koshy NULLMASK 5810cfab8ddSJoseph Koshy }; 5820cfab8ddSJoseph Koshy 5830cfab8ddSJoseph Koshy static struct pmc_masks iap_agent_mask[] = { 5840cfab8ddSJoseph Koshy PMCMASK(this, 0), 5850cfab8ddSJoseph Koshy PMCMASK(any, (0x1 << 13)), 5860cfab8ddSJoseph Koshy NULLMASK 5870cfab8ddSJoseph Koshy }; 5880cfab8ddSJoseph Koshy 5890cfab8ddSJoseph Koshy static struct pmc_masks iap_prefetch_mask[] = { 5900cfab8ddSJoseph Koshy PMCMASK(both, (0x3 << 12)), 5910cfab8ddSJoseph Koshy PMCMASK(only, (0x1 << 12)), 5920cfab8ddSJoseph Koshy PMCMASK(exclude, 0), 5930cfab8ddSJoseph Koshy NULLMASK 5940cfab8ddSJoseph Koshy }; 5950cfab8ddSJoseph Koshy 5960cfab8ddSJoseph Koshy static struct pmc_masks iap_cachestate_mask[] = { 5970cfab8ddSJoseph Koshy PMCMASK(i, (1 << 8)), 5980cfab8ddSJoseph Koshy PMCMASK(s, (1 << 9)), 5990cfab8ddSJoseph Koshy PMCMASK(e, (1 << 10)), 6000cfab8ddSJoseph Koshy PMCMASK(m, (1 << 11)), 6010cfab8ddSJoseph Koshy NULLMASK 6020cfab8ddSJoseph Koshy }; 6030cfab8ddSJoseph Koshy 6040cfab8ddSJoseph Koshy static struct pmc_masks iap_snoopresponse_mask[] = { 6050cfab8ddSJoseph Koshy PMCMASK(clean, (1 << 8)), 6060cfab8ddSJoseph Koshy PMCMASK(hit, (1 << 9)), 6070cfab8ddSJoseph Koshy PMCMASK(hitm, (1 << 11)), 6080cfab8ddSJoseph Koshy NULLMASK 6090cfab8ddSJoseph Koshy }; 6100cfab8ddSJoseph Koshy 6110cfab8ddSJoseph Koshy static struct pmc_masks iap_snooptype_mask[] = { 6120cfab8ddSJoseph Koshy PMCMASK(cmp2s, (1 << 8)), 6130cfab8ddSJoseph Koshy PMCMASK(cmp2i, (1 << 9)), 6140cfab8ddSJoseph Koshy NULLMASK 6150cfab8ddSJoseph Koshy }; 6160cfab8ddSJoseph Koshy 6170cfab8ddSJoseph Koshy static struct pmc_masks iap_transition_mask[] = { 6180cfab8ddSJoseph Koshy PMCMASK(any, 0x00), 6190cfab8ddSJoseph Koshy PMCMASK(frequency, 0x10), 6200cfab8ddSJoseph Koshy NULLMASK 6210cfab8ddSJoseph Koshy }; 6220cfab8ddSJoseph Koshy 6231fa7f10bSFabien Thomas static struct pmc_masks iap_rsp_mask[] = { 6241fa7f10bSFabien Thomas PMCMASK(DMND_DATA_RD, (1 << 0)), 6251fa7f10bSFabien Thomas PMCMASK(DMND_RFO, (1 << 1)), 6261fa7f10bSFabien Thomas PMCMASK(DMND_IFETCH, (1 << 2)), 6271fa7f10bSFabien Thomas PMCMASK(WB, (1 << 3)), 6281fa7f10bSFabien Thomas PMCMASK(PF_DATA_RD, (1 << 4)), 6291fa7f10bSFabien Thomas PMCMASK(PF_RFO, (1 << 5)), 6301fa7f10bSFabien Thomas PMCMASK(PF_IFETCH, (1 << 6)), 6311fa7f10bSFabien Thomas PMCMASK(OTHER, (1 << 7)), 6321fa7f10bSFabien Thomas PMCMASK(UNCORE_HIT, (1 << 8)), 6331fa7f10bSFabien Thomas PMCMASK(OTHER_CORE_HIT_SNP, (1 << 9)), 6341fa7f10bSFabien Thomas PMCMASK(OTHER_CORE_HITM, (1 << 10)), 6351fa7f10bSFabien Thomas PMCMASK(REMOTE_CACHE_FWD, (1 << 12)), 6361fa7f10bSFabien Thomas PMCMASK(REMOTE_DRAM, (1 << 13)), 6371fa7f10bSFabien Thomas PMCMASK(LOCAL_DRAM, (1 << 14)), 6381fa7f10bSFabien Thomas PMCMASK(NON_DRAM, (1 << 15)), 6391fa7f10bSFabien Thomas NULLMASK 6401fa7f10bSFabien Thomas }; 6411fa7f10bSFabien Thomas 6420cfab8ddSJoseph Koshy static int 6430cfab8ddSJoseph Koshy iap_allocate_pmc(enum pmc_event pe, char *ctrspec, 6440cfab8ddSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 6450cfab8ddSJoseph Koshy { 6460cfab8ddSJoseph Koshy char *e, *p, *q; 6471fa7f10bSFabien Thomas uint32_t cachestate, evmask, rsp; 6480cfab8ddSJoseph Koshy int count, n; 6490cfab8ddSJoseph Koshy 6500cfab8ddSJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE | 6510cfab8ddSJoseph Koshy PMC_CAP_QUALIFIER); 6520cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config = 0; 6530cfab8ddSJoseph Koshy 6541fa7f10bSFabien Thomas cachestate = evmask = rsp = 0; 6550cfab8ddSJoseph Koshy 6560cfab8ddSJoseph Koshy /* Parse additional modifiers if present */ 6570cfab8ddSJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 6580cfab8ddSJoseph Koshy 6590cfab8ddSJoseph Koshy n = 0; 6600cfab8ddSJoseph Koshy if (KWPREFIXMATCH(p, IAP_KW_CMASK "=")) { 6610cfab8ddSJoseph Koshy q = strchr(p, '='); 6620cfab8ddSJoseph Koshy if (*++q == '\0') /* skip '=' */ 6630cfab8ddSJoseph Koshy return (-1); 6640cfab8ddSJoseph Koshy count = strtol(q, &e, 0); 6650cfab8ddSJoseph Koshy if (e == q || *e != '\0') 6660cfab8ddSJoseph Koshy return (-1); 6670cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 6680cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= 6690cfab8ddSJoseph Koshy IAP_CMASK(count); 6700cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_EDGE)) { 6710cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 6720cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_INV)) { 6730cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 6740cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_OS)) { 6750cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 6760cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_USR)) { 6770cfab8ddSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 6780cfab8ddSJoseph Koshy } else if (KWMATCH(p, IAP_KW_ANYTHREAD)) { 6790cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= IAP_ANY; 680b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_CORE "=")) { 6810cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_core_mask, p, &evmask); 6820cfab8ddSJoseph Koshy if (n != 1) 6830cfab8ddSJoseph Koshy return (-1); 684b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_AGENT "=")) { 6850cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_agent_mask, p, &evmask); 6860cfab8ddSJoseph Koshy if (n != 1) 6870cfab8ddSJoseph Koshy return (-1); 688b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_PREFETCH "=")) { 6890cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_prefetch_mask, p, &evmask); 6900cfab8ddSJoseph Koshy if (n != 1) 6910cfab8ddSJoseph Koshy return (-1); 692b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_CACHESTATE "=")) { 6930cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_cachestate_mask, p, &cachestate); 6940cfab8ddSJoseph Koshy } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_CORE && 695b47ea38eSJoseph Koshy KWPREFIXMATCH(p, IAP_KW_TRANSITION "=")) { 6960cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_transition_mask, p, &evmask); 6970cfab8ddSJoseph Koshy if (n != 1) 6980cfab8ddSJoseph Koshy return (-1); 6990cfab8ddSJoseph Koshy } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM || 700b4d091f3SJoseph Koshy cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2 || 7011fa7f10bSFabien Thomas cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2EXTREME) { 702b47ea38eSJoseph Koshy if (KWPREFIXMATCH(p, IAP_KW_SNOOPRESPONSE "=")) { 7030cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_snoopresponse_mask, p, 7040cfab8ddSJoseph Koshy &evmask); 705b47ea38eSJoseph Koshy } else if (KWPREFIXMATCH(p, IAP_KW_SNOOPTYPE "=")) { 7060cfab8ddSJoseph Koshy n = pmc_parse_mask(iap_snooptype_mask, p, 7070cfab8ddSJoseph Koshy &evmask); 7080cfab8ddSJoseph Koshy } else 7090cfab8ddSJoseph Koshy return (-1); 7101fa7f10bSFabien Thomas } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_COREI7 || 7111fa7f10bSFabien Thomas cpu_info.pm_cputype == PMC_CPU_INTEL_WESTMERE) { 7121fa7f10bSFabien Thomas if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 7131fa7f10bSFabien Thomas n = pmc_parse_mask(iap_rsp_mask, p, &rsp); 7141fa7f10bSFabien Thomas } else 7151fa7f10bSFabien Thomas return (-1); 7160cfab8ddSJoseph Koshy } else 7170cfab8ddSJoseph Koshy return (-1); 7180cfab8ddSJoseph Koshy 7190cfab8ddSJoseph Koshy if (n < 0) /* Parsing failed. */ 7200cfab8ddSJoseph Koshy return (-1); 7210cfab8ddSJoseph Koshy } 7220cfab8ddSJoseph Koshy 7230cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= evmask; 7240cfab8ddSJoseph Koshy 7250cfab8ddSJoseph Koshy /* 7260cfab8ddSJoseph Koshy * If the event requires a 'cachestate' qualifier but was not 7270cfab8ddSJoseph Koshy * specified by the user, use a sensible default. 7280cfab8ddSJoseph Koshy */ 7290cfab8ddSJoseph Koshy switch (pe) { 7300cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_28H: /* Core, Core2, Atom */ 7310cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_29H: /* Core, Core2, Atom */ 7320cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_2AH: /* Core, Core2, Atom */ 7330cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_2BH: /* Atom, Core2 */ 7340cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_2EH: /* Core, Core2, Atom */ 7350cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_30H: /* Core, Core2, Atom */ 7360cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_32H: /* Core */ 7370cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_40H: /* Core */ 7380cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_41H: /* Core */ 7390cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_42H: /* Core, Core2, Atom */ 7400cfab8ddSJoseph Koshy case PMC_EV_IAP_EVENT_77H: /* Core */ 7410cfab8ddSJoseph Koshy if (cachestate == 0) 7420cfab8ddSJoseph Koshy cachestate = (0xF << 8); 7430cfab8ddSJoseph Koshy default: 7440cfab8ddSJoseph Koshy break; 7450cfab8ddSJoseph Koshy } 7460cfab8ddSJoseph Koshy 7470cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= cachestate; 7481fa7f10bSFabien Thomas pmc_config->pm_md.pm_iap.pm_iap_rsp = rsp; 7491fa7f10bSFabien Thomas 7501fa7f10bSFabien Thomas return (0); 7511fa7f10bSFabien Thomas } 7521fa7f10bSFabien Thomas 7531fa7f10bSFabien Thomas /* 7541fa7f10bSFabien Thomas * Intel Uncore. 7551fa7f10bSFabien Thomas */ 7561fa7f10bSFabien Thomas 7571fa7f10bSFabien Thomas static int 7581fa7f10bSFabien Thomas ucf_allocate_pmc(enum pmc_event pe, char *ctrspec, 7591fa7f10bSFabien Thomas struct pmc_op_pmcallocate *pmc_config) 7601fa7f10bSFabien Thomas { 7611fa7f10bSFabien Thomas (void) pe; 7621fa7f10bSFabien Thomas (void) ctrspec; 7631fa7f10bSFabien Thomas 7641fa7f10bSFabien Thomas pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 7651fa7f10bSFabien Thomas pmc_config->pm_md.pm_ucf.pm_ucf_flags = 0; 7661fa7f10bSFabien Thomas 7671fa7f10bSFabien Thomas return (0); 7681fa7f10bSFabien Thomas } 7691fa7f10bSFabien Thomas 7701fa7f10bSFabien Thomas #define UCP_KW_CMASK "cmask" 7711fa7f10bSFabien Thomas #define UCP_KW_EDGE "edge" 7721fa7f10bSFabien Thomas #define UCP_KW_INV "inv" 7731fa7f10bSFabien Thomas 7741fa7f10bSFabien Thomas static int 7751fa7f10bSFabien Thomas ucp_allocate_pmc(enum pmc_event pe, char *ctrspec, 7761fa7f10bSFabien Thomas struct pmc_op_pmcallocate *pmc_config) 7771fa7f10bSFabien Thomas { 7781fa7f10bSFabien Thomas char *e, *p, *q; 7791fa7f10bSFabien Thomas int count, n; 7801fa7f10bSFabien Thomas 7811fa7f10bSFabien Thomas (void) pe; 7821fa7f10bSFabien Thomas 7831fa7f10bSFabien Thomas pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE | 7841fa7f10bSFabien Thomas PMC_CAP_QUALIFIER); 7851fa7f10bSFabien Thomas pmc_config->pm_md.pm_ucp.pm_ucp_config = 0; 7861fa7f10bSFabien Thomas 7871fa7f10bSFabien Thomas /* Parse additional modifiers if present */ 7881fa7f10bSFabien Thomas while ((p = strsep(&ctrspec, ",")) != NULL) { 7891fa7f10bSFabien Thomas 7901fa7f10bSFabien Thomas n = 0; 7911fa7f10bSFabien Thomas if (KWPREFIXMATCH(p, UCP_KW_CMASK "=")) { 7921fa7f10bSFabien Thomas q = strchr(p, '='); 7931fa7f10bSFabien Thomas if (*++q == '\0') /* skip '=' */ 7941fa7f10bSFabien Thomas return (-1); 7951fa7f10bSFabien Thomas count = strtol(q, &e, 0); 7961fa7f10bSFabien Thomas if (e == q || *e != '\0') 7971fa7f10bSFabien Thomas return (-1); 7981fa7f10bSFabien Thomas pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 7991fa7f10bSFabien Thomas pmc_config->pm_md.pm_ucp.pm_ucp_config |= 8001fa7f10bSFabien Thomas UCP_CMASK(count); 8011fa7f10bSFabien Thomas } else if (KWMATCH(p, UCP_KW_EDGE)) { 8021fa7f10bSFabien Thomas pmc_config->pm_caps |= PMC_CAP_EDGE; 8031fa7f10bSFabien Thomas } else if (KWMATCH(p, UCP_KW_INV)) { 8041fa7f10bSFabien Thomas pmc_config->pm_caps |= PMC_CAP_INVERT; 8051fa7f10bSFabien Thomas } else 8061fa7f10bSFabien Thomas return (-1); 8071fa7f10bSFabien Thomas 8081fa7f10bSFabien Thomas if (n < 0) /* Parsing failed. */ 8091fa7f10bSFabien Thomas return (-1); 8101fa7f10bSFabien Thomas } 8110cfab8ddSJoseph Koshy 8120cfab8ddSJoseph Koshy return (0); 8130cfab8ddSJoseph Koshy } 8140cfab8ddSJoseph Koshy 8150cfab8ddSJoseph Koshy /* 816f263522aSJoseph Koshy * AMD K8 PMCs. 817f263522aSJoseph Koshy * 818f263522aSJoseph Koshy * These are very similar to AMD K7 PMCs, but support more kinds of 819f263522aSJoseph Koshy * events. 820f263522aSJoseph Koshy */ 821f263522aSJoseph Koshy 822f263522aSJoseph Koshy static struct pmc_event_alias k8_aliases[] = { 823f263522aSJoseph Koshy EV_ALIAS("branches", "k8-fr-retired-taken-branches"), 824f263522aSJoseph Koshy EV_ALIAS("branch-mispredicts", 825f263522aSJoseph Koshy "k8-fr-retired-taken-branches-mispredicted"), 826f263522aSJoseph Koshy EV_ALIAS("cycles", "tsc"), 827f263522aSJoseph Koshy EV_ALIAS("dc-misses", "k8-dc-miss"), 828f263522aSJoseph Koshy EV_ALIAS("ic-misses", "k8-ic-miss"), 829f263522aSJoseph Koshy EV_ALIAS("instructions", "k8-fr-retired-x86-instructions"), 830f263522aSJoseph Koshy EV_ALIAS("interrupts", "k8-fr-taken-hardware-interrupts"), 831177a2f22SJoseph Koshy EV_ALIAS("unhalted-cycles", "k8-bu-cpu-clk-unhalted"), 832f263522aSJoseph Koshy EV_ALIAS(NULL, NULL) 833f263522aSJoseph Koshy }; 834f263522aSJoseph Koshy 835f263522aSJoseph Koshy #define __K8MASK(N,V) PMCMASK(N,(1 << (V))) 836f263522aSJoseph Koshy 837f263522aSJoseph Koshy /* 838f263522aSJoseph Koshy * Parsing tables 839f263522aSJoseph Koshy */ 840f263522aSJoseph Koshy 841f263522aSJoseph Koshy /* fp dispatched fpu ops */ 842f263522aSJoseph Koshy static const struct pmc_masks k8_mask_fdfo[] = { 843f263522aSJoseph Koshy __K8MASK(add-pipe-excluding-junk-ops, 0), 844f263522aSJoseph Koshy __K8MASK(multiply-pipe-excluding-junk-ops, 1), 845f263522aSJoseph Koshy __K8MASK(store-pipe-excluding-junk-ops, 2), 846f263522aSJoseph Koshy __K8MASK(add-pipe-junk-ops, 3), 847f263522aSJoseph Koshy __K8MASK(multiply-pipe-junk-ops, 4), 848f263522aSJoseph Koshy __K8MASK(store-pipe-junk-ops, 5), 849f263522aSJoseph Koshy NULLMASK 850f263522aSJoseph Koshy }; 851f263522aSJoseph Koshy 852f263522aSJoseph Koshy /* ls segment register loads */ 853f263522aSJoseph Koshy static const struct pmc_masks k8_mask_lsrl[] = { 854f263522aSJoseph Koshy __K8MASK(es, 0), 855f263522aSJoseph Koshy __K8MASK(cs, 1), 856f263522aSJoseph Koshy __K8MASK(ss, 2), 857f263522aSJoseph Koshy __K8MASK(ds, 3), 858f263522aSJoseph Koshy __K8MASK(fs, 4), 859f263522aSJoseph Koshy __K8MASK(gs, 5), 860f263522aSJoseph Koshy __K8MASK(hs, 6), 861f263522aSJoseph Koshy NULLMASK 862f263522aSJoseph Koshy }; 863f263522aSJoseph Koshy 864f263522aSJoseph Koshy /* ls locked operation */ 865f263522aSJoseph Koshy static const struct pmc_masks k8_mask_llo[] = { 866f263522aSJoseph Koshy __K8MASK(locked-instructions, 0), 867f263522aSJoseph Koshy __K8MASK(cycles-in-request, 1), 868f263522aSJoseph Koshy __K8MASK(cycles-to-complete, 2), 869f263522aSJoseph Koshy NULLMASK 870f263522aSJoseph Koshy }; 871f263522aSJoseph Koshy 872f263522aSJoseph Koshy /* dc refill from {l2,system} and dc copyback */ 873f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dc[] = { 874f263522aSJoseph Koshy __K8MASK(invalid, 0), 875f263522aSJoseph Koshy __K8MASK(shared, 1), 876f263522aSJoseph Koshy __K8MASK(exclusive, 2), 877f263522aSJoseph Koshy __K8MASK(owner, 3), 878f263522aSJoseph Koshy __K8MASK(modified, 4), 879f263522aSJoseph Koshy NULLMASK 880f263522aSJoseph Koshy }; 881f263522aSJoseph Koshy 882f263522aSJoseph Koshy /* dc one bit ecc error */ 883f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dobee[] = { 884f263522aSJoseph Koshy __K8MASK(scrubber, 0), 885f263522aSJoseph Koshy __K8MASK(piggyback, 1), 886f263522aSJoseph Koshy NULLMASK 887f263522aSJoseph Koshy }; 888f263522aSJoseph Koshy 889f263522aSJoseph Koshy /* dc dispatched prefetch instructions */ 890f263522aSJoseph Koshy static const struct pmc_masks k8_mask_ddpi[] = { 891f263522aSJoseph Koshy __K8MASK(load, 0), 892f263522aSJoseph Koshy __K8MASK(store, 1), 893f263522aSJoseph Koshy __K8MASK(nta, 2), 894f263522aSJoseph Koshy NULLMASK 895f263522aSJoseph Koshy }; 896f263522aSJoseph Koshy 897f263522aSJoseph Koshy /* dc dcache accesses by locks */ 898f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dabl[] = { 899f263522aSJoseph Koshy __K8MASK(accesses, 0), 900f263522aSJoseph Koshy __K8MASK(misses, 1), 901f263522aSJoseph Koshy NULLMASK 902f263522aSJoseph Koshy }; 903f263522aSJoseph Koshy 904f263522aSJoseph Koshy /* bu internal l2 request */ 905f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bilr[] = { 906f263522aSJoseph Koshy __K8MASK(ic-fill, 0), 907f263522aSJoseph Koshy __K8MASK(dc-fill, 1), 908f263522aSJoseph Koshy __K8MASK(tlb-reload, 2), 909f263522aSJoseph Koshy __K8MASK(tag-snoop, 3), 910f263522aSJoseph Koshy __K8MASK(cancelled, 4), 911f263522aSJoseph Koshy NULLMASK 912f263522aSJoseph Koshy }; 913f263522aSJoseph Koshy 914f263522aSJoseph Koshy /* bu fill request l2 miss */ 915f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bfrlm[] = { 916f263522aSJoseph Koshy __K8MASK(ic-fill, 0), 917f263522aSJoseph Koshy __K8MASK(dc-fill, 1), 918f263522aSJoseph Koshy __K8MASK(tlb-reload, 2), 919f263522aSJoseph Koshy NULLMASK 920f263522aSJoseph Koshy }; 921f263522aSJoseph Koshy 922f263522aSJoseph Koshy /* bu fill into l2 */ 923f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bfil[] = { 924f263522aSJoseph Koshy __K8MASK(dirty-l2-victim, 0), 925f263522aSJoseph Koshy __K8MASK(victim-from-l2, 1), 926f263522aSJoseph Koshy NULLMASK 927f263522aSJoseph Koshy }; 928f263522aSJoseph Koshy 929f263522aSJoseph Koshy /* fr retired fpu instructions */ 930f263522aSJoseph Koshy static const struct pmc_masks k8_mask_frfi[] = { 931f263522aSJoseph Koshy __K8MASK(x87, 0), 932f263522aSJoseph Koshy __K8MASK(mmx-3dnow, 1), 933f263522aSJoseph Koshy __K8MASK(packed-sse-sse2, 2), 934f263522aSJoseph Koshy __K8MASK(scalar-sse-sse2, 3), 935f263522aSJoseph Koshy NULLMASK 936f263522aSJoseph Koshy }; 937f263522aSJoseph Koshy 938f263522aSJoseph Koshy /* fr retired fastpath double op instructions */ 939f263522aSJoseph Koshy static const struct pmc_masks k8_mask_frfdoi[] = { 940f263522aSJoseph Koshy __K8MASK(low-op-pos-0, 0), 941f263522aSJoseph Koshy __K8MASK(low-op-pos-1, 1), 942f263522aSJoseph Koshy __K8MASK(low-op-pos-2, 2), 943f263522aSJoseph Koshy NULLMASK 944f263522aSJoseph Koshy }; 945f263522aSJoseph Koshy 946f263522aSJoseph Koshy /* fr fpu exceptions */ 947f263522aSJoseph Koshy static const struct pmc_masks k8_mask_ffe[] = { 948f263522aSJoseph Koshy __K8MASK(x87-reclass-microfaults, 0), 949f263522aSJoseph Koshy __K8MASK(sse-retype-microfaults, 1), 950f263522aSJoseph Koshy __K8MASK(sse-reclass-microfaults, 2), 951f263522aSJoseph Koshy __K8MASK(sse-and-x87-microtraps, 3), 952f263522aSJoseph Koshy NULLMASK 953f263522aSJoseph Koshy }; 954f263522aSJoseph Koshy 955f263522aSJoseph Koshy /* nb memory controller page access event */ 956f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmcpae[] = { 957f263522aSJoseph Koshy __K8MASK(page-hit, 0), 958f263522aSJoseph Koshy __K8MASK(page-miss, 1), 959f263522aSJoseph Koshy __K8MASK(page-conflict, 2), 960f263522aSJoseph Koshy NULLMASK 961f263522aSJoseph Koshy }; 962f263522aSJoseph Koshy 963f263522aSJoseph Koshy /* nb memory controller turnaround */ 964f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmct[] = { 965f263522aSJoseph Koshy __K8MASK(dimm-turnaround, 0), 966f263522aSJoseph Koshy __K8MASK(read-to-write-turnaround, 1), 967f263522aSJoseph Koshy __K8MASK(write-to-read-turnaround, 2), 968f263522aSJoseph Koshy NULLMASK 969f263522aSJoseph Koshy }; 970f263522aSJoseph Koshy 971f263522aSJoseph Koshy /* nb memory controller bypass saturation */ 972f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmcbs[] = { 973f263522aSJoseph Koshy __K8MASK(memory-controller-hi-pri-bypass, 0), 974f263522aSJoseph Koshy __K8MASK(memory-controller-lo-pri-bypass, 1), 975f263522aSJoseph Koshy __K8MASK(dram-controller-interface-bypass, 2), 976f263522aSJoseph Koshy __K8MASK(dram-controller-queue-bypass, 3), 977f263522aSJoseph Koshy NULLMASK 978f263522aSJoseph Koshy }; 979f263522aSJoseph Koshy 980f263522aSJoseph Koshy /* nb sized commands */ 981f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nsc[] = { 982f263522aSJoseph Koshy __K8MASK(nonpostwrszbyte, 0), 983f263522aSJoseph Koshy __K8MASK(nonpostwrszdword, 1), 984f263522aSJoseph Koshy __K8MASK(postwrszbyte, 2), 985f263522aSJoseph Koshy __K8MASK(postwrszdword, 3), 986f263522aSJoseph Koshy __K8MASK(rdszbyte, 4), 987f263522aSJoseph Koshy __K8MASK(rdszdword, 5), 988f263522aSJoseph Koshy __K8MASK(rdmodwr, 6), 989f263522aSJoseph Koshy NULLMASK 990f263522aSJoseph Koshy }; 991f263522aSJoseph Koshy 992f263522aSJoseph Koshy /* nb probe result */ 993f263522aSJoseph Koshy static const struct pmc_masks k8_mask_npr[] = { 994f263522aSJoseph Koshy __K8MASK(probe-miss, 0), 995f263522aSJoseph Koshy __K8MASK(probe-hit, 1), 996f263522aSJoseph Koshy __K8MASK(probe-hit-dirty-no-memory-cancel, 2), 997f263522aSJoseph Koshy __K8MASK(probe-hit-dirty-with-memory-cancel, 3), 998f263522aSJoseph Koshy NULLMASK 999f263522aSJoseph Koshy }; 1000f263522aSJoseph Koshy 1001f263522aSJoseph Koshy /* nb hypertransport bus bandwidth */ 1002f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nhbb[] = { /* HT bus bandwidth */ 1003f263522aSJoseph Koshy __K8MASK(command, 0), 1004f263522aSJoseph Koshy __K8MASK(data, 1), 1005f263522aSJoseph Koshy __K8MASK(buffer-release, 2), 1006f263522aSJoseph Koshy __K8MASK(nop, 3), 1007f263522aSJoseph Koshy NULLMASK 1008f263522aSJoseph Koshy }; 1009f263522aSJoseph Koshy 1010f263522aSJoseph Koshy #undef __K8MASK 1011f263522aSJoseph Koshy 1012f263522aSJoseph Koshy #define K8_KW_COUNT "count" 1013f263522aSJoseph Koshy #define K8_KW_EDGE "edge" 1014f263522aSJoseph Koshy #define K8_KW_INV "inv" 1015f263522aSJoseph Koshy #define K8_KW_MASK "mask" 1016f263522aSJoseph Koshy #define K8_KW_OS "os" 1017f263522aSJoseph Koshy #define K8_KW_USR "usr" 1018f263522aSJoseph Koshy 1019f263522aSJoseph Koshy static int 1020f263522aSJoseph Koshy k8_allocate_pmc(enum pmc_event pe, char *ctrspec, 1021f263522aSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 1022f263522aSJoseph Koshy { 1023f263522aSJoseph Koshy char *e, *p, *q; 1024f263522aSJoseph Koshy int n; 1025f263522aSJoseph Koshy uint32_t count, evmask; 1026f263522aSJoseph Koshy const struct pmc_masks *pm, *pmask; 1027f263522aSJoseph Koshy 1028789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1029f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 1030f263522aSJoseph Koshy 1031f263522aSJoseph Koshy pmask = NULL; 1032f263522aSJoseph Koshy evmask = 0; 1033f263522aSJoseph Koshy 1034f263522aSJoseph Koshy #define __K8SETMASK(M) pmask = k8_mask_##M 1035f263522aSJoseph Koshy 1036f263522aSJoseph Koshy /* setup parsing tables */ 1037f263522aSJoseph Koshy switch (pe) { 1038f263522aSJoseph Koshy case PMC_EV_K8_FP_DISPATCHED_FPU_OPS: 1039f263522aSJoseph Koshy __K8SETMASK(fdfo); 1040f263522aSJoseph Koshy break; 1041f263522aSJoseph Koshy case PMC_EV_K8_LS_SEGMENT_REGISTER_LOAD: 1042f263522aSJoseph Koshy __K8SETMASK(lsrl); 1043f263522aSJoseph Koshy break; 1044f263522aSJoseph Koshy case PMC_EV_K8_LS_LOCKED_OPERATION: 1045f263522aSJoseph Koshy __K8SETMASK(llo); 1046f263522aSJoseph Koshy break; 1047f263522aSJoseph Koshy case PMC_EV_K8_DC_REFILL_FROM_L2: 1048f263522aSJoseph Koshy case PMC_EV_K8_DC_REFILL_FROM_SYSTEM: 1049f263522aSJoseph Koshy case PMC_EV_K8_DC_COPYBACK: 1050f263522aSJoseph Koshy __K8SETMASK(dc); 1051f263522aSJoseph Koshy break; 1052f263522aSJoseph Koshy case PMC_EV_K8_DC_ONE_BIT_ECC_ERROR: 1053f263522aSJoseph Koshy __K8SETMASK(dobee); 1054f263522aSJoseph Koshy break; 1055f263522aSJoseph Koshy case PMC_EV_K8_DC_DISPATCHED_PREFETCH_INSTRUCTIONS: 1056f263522aSJoseph Koshy __K8SETMASK(ddpi); 1057f263522aSJoseph Koshy break; 1058f263522aSJoseph Koshy case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS: 1059f263522aSJoseph Koshy __K8SETMASK(dabl); 1060f263522aSJoseph Koshy break; 1061f263522aSJoseph Koshy case PMC_EV_K8_BU_INTERNAL_L2_REQUEST: 1062f263522aSJoseph Koshy __K8SETMASK(bilr); 1063f263522aSJoseph Koshy break; 1064f263522aSJoseph Koshy case PMC_EV_K8_BU_FILL_REQUEST_L2_MISS: 1065f263522aSJoseph Koshy __K8SETMASK(bfrlm); 1066f263522aSJoseph Koshy break; 1067f263522aSJoseph Koshy case PMC_EV_K8_BU_FILL_INTO_L2: 1068f263522aSJoseph Koshy __K8SETMASK(bfil); 1069f263522aSJoseph Koshy break; 1070f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS: 1071f263522aSJoseph Koshy __K8SETMASK(frfi); 1072f263522aSJoseph Koshy break; 1073f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS: 1074f263522aSJoseph Koshy __K8SETMASK(frfdoi); 1075f263522aSJoseph Koshy break; 1076f263522aSJoseph Koshy case PMC_EV_K8_FR_FPU_EXCEPTIONS: 1077f263522aSJoseph Koshy __K8SETMASK(ffe); 1078f263522aSJoseph Koshy break; 1079f263522aSJoseph Koshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_PAGE_ACCESS_EVENT: 1080f263522aSJoseph Koshy __K8SETMASK(nmcpae); 1081f263522aSJoseph Koshy break; 1082f263522aSJoseph Koshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_TURNAROUND: 1083f263522aSJoseph Koshy __K8SETMASK(nmct); 1084f263522aSJoseph Koshy break; 1085f263522aSJoseph Koshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_BYPASS_SATURATION: 1086f263522aSJoseph Koshy __K8SETMASK(nmcbs); 1087f263522aSJoseph Koshy break; 1088f263522aSJoseph Koshy case PMC_EV_K8_NB_SIZED_COMMANDS: 1089f263522aSJoseph Koshy __K8SETMASK(nsc); 1090f263522aSJoseph Koshy break; 1091f263522aSJoseph Koshy case PMC_EV_K8_NB_PROBE_RESULT: 1092f263522aSJoseph Koshy __K8SETMASK(npr); 1093f263522aSJoseph Koshy break; 1094f263522aSJoseph Koshy case PMC_EV_K8_NB_HT_BUS0_BANDWIDTH: 1095f263522aSJoseph Koshy case PMC_EV_K8_NB_HT_BUS1_BANDWIDTH: 1096f263522aSJoseph Koshy case PMC_EV_K8_NB_HT_BUS2_BANDWIDTH: 1097f263522aSJoseph Koshy __K8SETMASK(nhbb); 1098f263522aSJoseph Koshy break; 1099f263522aSJoseph Koshy 1100f263522aSJoseph Koshy default: 1101f263522aSJoseph Koshy break; /* no options defined */ 1102f263522aSJoseph Koshy } 1103f263522aSJoseph Koshy 1104f263522aSJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 1105f263522aSJoseph Koshy if (KWPREFIXMATCH(p, K8_KW_COUNT "=")) { 1106f263522aSJoseph Koshy q = strchr(p, '='); 1107f263522aSJoseph Koshy if (*++q == '\0') /* skip '=' */ 1108aa342b1fSJoseph Koshy return (-1); 1109f263522aSJoseph Koshy 1110f263522aSJoseph Koshy count = strtol(q, &e, 0); 1111f263522aSJoseph Koshy if (e == q || *e != '\0') 1112aa342b1fSJoseph Koshy return (-1); 1113f263522aSJoseph Koshy 1114f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 1115f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config |= 1116f263522aSJoseph Koshy AMD_PMC_TO_COUNTER(count); 1117f263522aSJoseph Koshy 1118f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_EDGE)) { 1119f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1120f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_INV)) { 1121f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 1122f263522aSJoseph Koshy } else if (KWPREFIXMATCH(p, K8_KW_MASK "=")) { 1123f263522aSJoseph Koshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 1124aa342b1fSJoseph Koshy return (-1); 1125f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1126f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_OS)) { 1127f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 1128f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_USR)) { 1129f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 1130f263522aSJoseph Koshy } else 1131aa342b1fSJoseph Koshy return (-1); 1132f263522aSJoseph Koshy } 1133f263522aSJoseph Koshy 1134f263522aSJoseph Koshy /* other post processing */ 1135f263522aSJoseph Koshy switch (pe) { 1136f263522aSJoseph Koshy case PMC_EV_K8_FP_DISPATCHED_FPU_OPS: 1137f263522aSJoseph Koshy case PMC_EV_K8_FP_CYCLES_WITH_NO_FPU_OPS_RETIRED: 1138f263522aSJoseph Koshy case PMC_EV_K8_FP_DISPATCHED_FPU_FAST_FLAG_OPS: 1139f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS: 1140f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS: 1141f263522aSJoseph Koshy case PMC_EV_K8_FR_FPU_EXCEPTIONS: 1142f263522aSJoseph Koshy /* XXX only available in rev B and later */ 1143f263522aSJoseph Koshy break; 1144f263522aSJoseph Koshy case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS: 1145f263522aSJoseph Koshy /* XXX only available in rev C and later */ 1146f263522aSJoseph Koshy break; 1147f263522aSJoseph Koshy case PMC_EV_K8_LS_LOCKED_OPERATION: 1148f263522aSJoseph Koshy /* XXX CPU Rev A,B evmask is to be zero */ 1149f263522aSJoseph Koshy if (evmask & (evmask - 1)) /* > 1 bit set */ 1150aa342b1fSJoseph Koshy return (-1); 1151f263522aSJoseph Koshy if (evmask == 0) { 1152f263522aSJoseph Koshy evmask = 0x01; /* Rev C and later: #instrs */ 1153f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1154f263522aSJoseph Koshy } 1155f263522aSJoseph Koshy break; 1156f263522aSJoseph Koshy default: 1157f263522aSJoseph Koshy if (evmask == 0 && pmask != NULL) { 1158f263522aSJoseph Koshy for (pm = pmask; pm->pm_name; pm++) 1159f263522aSJoseph Koshy evmask |= pm->pm_value; 1160f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1161f263522aSJoseph Koshy } 1162f263522aSJoseph Koshy } 1163f263522aSJoseph Koshy 1164f263522aSJoseph Koshy if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) 1165f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 1166f263522aSJoseph Koshy AMD_PMC_TO_UNITMASK(evmask); 1167f263522aSJoseph Koshy 1168aa342b1fSJoseph Koshy return (0); 1169f263522aSJoseph Koshy } 1170f263522aSJoseph Koshy 1171f263522aSJoseph Koshy #endif 1172f263522aSJoseph Koshy 117386a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 1174f263522aSJoseph Koshy 1175ebccf1e3SJoseph Koshy /* 1176ebccf1e3SJoseph Koshy * Intel P4 PMCs 1177ebccf1e3SJoseph Koshy */ 1178ebccf1e3SJoseph Koshy 1179ebccf1e3SJoseph Koshy static struct pmc_event_alias p4_aliases[] = { 1180d56c5d4bSJoseph Koshy EV_ALIAS("branches", "p4-branch-retired,mask=mmtp+mmtm"), 1181d56c5d4bSJoseph Koshy EV_ALIAS("branch-mispredicts", "p4-mispred-branch-retired"), 1182ebccf1e3SJoseph Koshy EV_ALIAS("cycles", "tsc"), 1183d56c5d4bSJoseph Koshy EV_ALIAS("instructions", 1184d56c5d4bSJoseph Koshy "p4-instr-retired,mask=nbogusntag+nbogustag"), 1185177a2f22SJoseph Koshy EV_ALIAS("unhalted-cycles", "p4-global-power-events"), 1186ebccf1e3SJoseph Koshy EV_ALIAS(NULL, NULL) 1187ebccf1e3SJoseph Koshy }; 1188ebccf1e3SJoseph Koshy 1189ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE "active" 1190ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_ANY "any" 1191ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_BOTH "both" 1192ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_NONE "none" 1193ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_SINGLE "single" 1194ebccf1e3SJoseph Koshy #define P4_KW_BUSREQTYPE "busreqtype" 1195ebccf1e3SJoseph Koshy #define P4_KW_CASCADE "cascade" 1196ebccf1e3SJoseph Koshy #define P4_KW_EDGE "edge" 1197ebccf1e3SJoseph Koshy #define P4_KW_INV "complement" 1198ebccf1e3SJoseph Koshy #define P4_KW_OS "os" 1199ebccf1e3SJoseph Koshy #define P4_KW_MASK "mask" 1200ebccf1e3SJoseph Koshy #define P4_KW_PRECISE "precise" 1201ebccf1e3SJoseph Koshy #define P4_KW_TAG "tag" 1202ebccf1e3SJoseph Koshy #define P4_KW_THRESHOLD "threshold" 1203ebccf1e3SJoseph Koshy #define P4_KW_USR "usr" 1204ebccf1e3SJoseph Koshy 1205ebccf1e3SJoseph Koshy #define __P4MASK(N,V) PMCMASK(N, (1 << (V))) 1206ebccf1e3SJoseph Koshy 1207ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_tcdm[] = { /* tc deliver mode */ 1208ebccf1e3SJoseph Koshy __P4MASK(dd, 0), 1209ebccf1e3SJoseph Koshy __P4MASK(db, 1), 1210ebccf1e3SJoseph Koshy __P4MASK(di, 2), 1211ebccf1e3SJoseph Koshy __P4MASK(bd, 3), 1212ebccf1e3SJoseph Koshy __P4MASK(bb, 4), 1213ebccf1e3SJoseph Koshy __P4MASK(bi, 5), 1214ebccf1e3SJoseph Koshy __P4MASK(id, 6), 1215ebccf1e3SJoseph Koshy __P4MASK(ib, 7), 1216ebccf1e3SJoseph Koshy NULLMASK 1217ebccf1e3SJoseph Koshy }; 1218ebccf1e3SJoseph Koshy 1219ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_bfr[] = { /* bpu fetch request */ 1220ebccf1e3SJoseph Koshy __P4MASK(tcmiss, 0), 1221ebccf1e3SJoseph Koshy NULLMASK, 1222ebccf1e3SJoseph Koshy }; 1223ebccf1e3SJoseph Koshy 1224ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ir[] = { /* itlb reference */ 1225ebccf1e3SJoseph Koshy __P4MASK(hit, 0), 1226ebccf1e3SJoseph Koshy __P4MASK(miss, 1), 1227ebccf1e3SJoseph Koshy __P4MASK(hit-uc, 2), 1228ebccf1e3SJoseph Koshy NULLMASK 1229ebccf1e3SJoseph Koshy }; 1230ebccf1e3SJoseph Koshy 1231ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_memcan[] = { /* memory cancel */ 1232ebccf1e3SJoseph Koshy __P4MASK(st-rb-full, 2), 1233ebccf1e3SJoseph Koshy __P4MASK(64k-conf, 3), 1234ebccf1e3SJoseph Koshy NULLMASK 1235ebccf1e3SJoseph Koshy }; 1236ebccf1e3SJoseph Koshy 1237ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_memcomp[] = { /* memory complete */ 1238ebccf1e3SJoseph Koshy __P4MASK(lsc, 0), 1239ebccf1e3SJoseph Koshy __P4MASK(ssc, 1), 1240ebccf1e3SJoseph Koshy NULLMASK 1241ebccf1e3SJoseph Koshy }; 1242ebccf1e3SJoseph Koshy 1243ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_lpr[] = { /* load port replay */ 1244ebccf1e3SJoseph Koshy __P4MASK(split-ld, 1), 1245ebccf1e3SJoseph Koshy NULLMASK 1246ebccf1e3SJoseph Koshy }; 1247ebccf1e3SJoseph Koshy 1248ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_spr[] = { /* store port replay */ 1249ebccf1e3SJoseph Koshy __P4MASK(split-st, 1), 1250ebccf1e3SJoseph Koshy NULLMASK 1251ebccf1e3SJoseph Koshy }; 1252ebccf1e3SJoseph Koshy 1253ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_mlr[] = { /* mob load replay */ 1254ebccf1e3SJoseph Koshy __P4MASK(no-sta, 1), 1255ebccf1e3SJoseph Koshy __P4MASK(no-std, 3), 1256ebccf1e3SJoseph Koshy __P4MASK(partial-data, 4), 1257ebccf1e3SJoseph Koshy __P4MASK(unalgn-addr, 5), 1258ebccf1e3SJoseph Koshy NULLMASK 1259ebccf1e3SJoseph Koshy }; 1260ebccf1e3SJoseph Koshy 1261ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_pwt[] = { /* page walk type */ 1262ebccf1e3SJoseph Koshy __P4MASK(dtmiss, 0), 1263ebccf1e3SJoseph Koshy __P4MASK(itmiss, 1), 1264ebccf1e3SJoseph Koshy NULLMASK 1265ebccf1e3SJoseph Koshy }; 1266ebccf1e3SJoseph Koshy 1267ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_bcr[] = { /* bsq cache reference */ 1268ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-hits, 0), 1269ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-hite, 1), 1270ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-hitm, 2), 1271ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-hits, 3), 1272ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-hite, 4), 1273ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-hitm, 5), 1274ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-miss, 8), 1275ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-miss, 9), 1276ebccf1e3SJoseph Koshy __P4MASK(wr-2ndl-miss, 10), 1277ebccf1e3SJoseph Koshy NULLMASK 1278ebccf1e3SJoseph Koshy }; 1279ebccf1e3SJoseph Koshy 1280ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ia[] = { /* ioq allocation */ 1281ebccf1e3SJoseph Koshy __P4MASK(all-read, 5), 1282ebccf1e3SJoseph Koshy __P4MASK(all-write, 6), 1283ebccf1e3SJoseph Koshy __P4MASK(mem-uc, 7), 1284ebccf1e3SJoseph Koshy __P4MASK(mem-wc, 8), 1285ebccf1e3SJoseph Koshy __P4MASK(mem-wt, 9), 1286ebccf1e3SJoseph Koshy __P4MASK(mem-wp, 10), 1287ebccf1e3SJoseph Koshy __P4MASK(mem-wb, 11), 1288ebccf1e3SJoseph Koshy __P4MASK(own, 13), 1289ebccf1e3SJoseph Koshy __P4MASK(other, 14), 1290ebccf1e3SJoseph Koshy __P4MASK(prefetch, 15), 1291ebccf1e3SJoseph Koshy NULLMASK 1292ebccf1e3SJoseph Koshy }; 1293ebccf1e3SJoseph Koshy 1294ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_iae[] = { /* ioq active entries */ 1295ebccf1e3SJoseph Koshy __P4MASK(all-read, 5), 1296ebccf1e3SJoseph Koshy __P4MASK(all-write, 6), 1297ebccf1e3SJoseph Koshy __P4MASK(mem-uc, 7), 1298ebccf1e3SJoseph Koshy __P4MASK(mem-wc, 8), 1299ebccf1e3SJoseph Koshy __P4MASK(mem-wt, 9), 1300ebccf1e3SJoseph Koshy __P4MASK(mem-wp, 10), 1301ebccf1e3SJoseph Koshy __P4MASK(mem-wb, 11), 1302ebccf1e3SJoseph Koshy __P4MASK(own, 13), 1303ebccf1e3SJoseph Koshy __P4MASK(other, 14), 1304ebccf1e3SJoseph Koshy __P4MASK(prefetch, 15), 1305ebccf1e3SJoseph Koshy NULLMASK 1306ebccf1e3SJoseph Koshy }; 1307ebccf1e3SJoseph Koshy 1308ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_fda[] = { /* fsb data activity */ 1309ebccf1e3SJoseph Koshy __P4MASK(drdy-drv, 0), 1310ebccf1e3SJoseph Koshy __P4MASK(drdy-own, 1), 1311ebccf1e3SJoseph Koshy __P4MASK(drdy-other, 2), 1312ebccf1e3SJoseph Koshy __P4MASK(dbsy-drv, 3), 1313ebccf1e3SJoseph Koshy __P4MASK(dbsy-own, 4), 1314ebccf1e3SJoseph Koshy __P4MASK(dbsy-other, 5), 1315ebccf1e3SJoseph Koshy NULLMASK 1316ebccf1e3SJoseph Koshy }; 1317ebccf1e3SJoseph Koshy 1318ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ba[] = { /* bsq allocation */ 1319ebccf1e3SJoseph Koshy __P4MASK(req-type0, 0), 1320ebccf1e3SJoseph Koshy __P4MASK(req-type1, 1), 1321ebccf1e3SJoseph Koshy __P4MASK(req-len0, 2), 1322ebccf1e3SJoseph Koshy __P4MASK(req-len1, 3), 1323ebccf1e3SJoseph Koshy __P4MASK(req-io-type, 5), 1324ebccf1e3SJoseph Koshy __P4MASK(req-lock-type, 6), 1325ebccf1e3SJoseph Koshy __P4MASK(req-cache-type, 7), 1326ebccf1e3SJoseph Koshy __P4MASK(req-split-type, 8), 1327ebccf1e3SJoseph Koshy __P4MASK(req-dem-type, 9), 1328ebccf1e3SJoseph Koshy __P4MASK(req-ord-type, 10), 1329ebccf1e3SJoseph Koshy __P4MASK(mem-type0, 11), 1330ebccf1e3SJoseph Koshy __P4MASK(mem-type1, 12), 1331ebccf1e3SJoseph Koshy __P4MASK(mem-type2, 13), 1332ebccf1e3SJoseph Koshy NULLMASK 1333ebccf1e3SJoseph Koshy }; 1334ebccf1e3SJoseph Koshy 1335ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_sia[] = { /* sse input assist */ 1336ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1337ebccf1e3SJoseph Koshy NULLMASK 1338ebccf1e3SJoseph Koshy }; 1339ebccf1e3SJoseph Koshy 1340ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_psu[] = { /* packed sp uop */ 1341ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1342ebccf1e3SJoseph Koshy NULLMASK 1343ebccf1e3SJoseph Koshy }; 1344ebccf1e3SJoseph Koshy 1345ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_pdu[] = { /* packed dp uop */ 1346ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1347ebccf1e3SJoseph Koshy NULLMASK 1348ebccf1e3SJoseph Koshy }; 1349ebccf1e3SJoseph Koshy 1350ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ssu[] = { /* scalar sp uop */ 1351ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1352ebccf1e3SJoseph Koshy NULLMASK 1353ebccf1e3SJoseph Koshy }; 1354ebccf1e3SJoseph Koshy 1355ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_sdu[] = { /* scalar dp uop */ 1356ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1357ebccf1e3SJoseph Koshy NULLMASK 1358ebccf1e3SJoseph Koshy }; 1359ebccf1e3SJoseph Koshy 1360ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_64bmu[] = { /* 64 bit mmx uop */ 1361ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1362ebccf1e3SJoseph Koshy NULLMASK 1363ebccf1e3SJoseph Koshy }; 1364ebccf1e3SJoseph Koshy 1365ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_128bmu[] = { /* 128 bit mmx uop */ 1366ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1367ebccf1e3SJoseph Koshy NULLMASK 1368ebccf1e3SJoseph Koshy }; 1369ebccf1e3SJoseph Koshy 1370ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xfu[] = { /* X87 fp uop */ 1371ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1372ebccf1e3SJoseph Koshy NULLMASK 1373ebccf1e3SJoseph Koshy }; 1374ebccf1e3SJoseph Koshy 1375ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xsmu[] = { /* x87 simd moves uop */ 1376ebccf1e3SJoseph Koshy __P4MASK(allp0, 3), 1377ebccf1e3SJoseph Koshy __P4MASK(allp2, 4), 1378ebccf1e3SJoseph Koshy NULLMASK 1379ebccf1e3SJoseph Koshy }; 1380ebccf1e3SJoseph Koshy 1381ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_gpe[] = { /* global power events */ 1382ebccf1e3SJoseph Koshy __P4MASK(running, 0), 1383ebccf1e3SJoseph Koshy NULLMASK 1384ebccf1e3SJoseph Koshy }; 1385ebccf1e3SJoseph Koshy 1386ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_tmx[] = { /* TC ms xfer */ 1387ebccf1e3SJoseph Koshy __P4MASK(cisc, 0), 1388ebccf1e3SJoseph Koshy NULLMASK 1389ebccf1e3SJoseph Koshy }; 1390ebccf1e3SJoseph Koshy 1391ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_uqw[] = { /* uop queue writes */ 1392ebccf1e3SJoseph Koshy __P4MASK(from-tc-build, 0), 1393ebccf1e3SJoseph Koshy __P4MASK(from-tc-deliver, 1), 1394ebccf1e3SJoseph Koshy __P4MASK(from-rom, 2), 1395ebccf1e3SJoseph Koshy NULLMASK 1396ebccf1e3SJoseph Koshy }; 1397ebccf1e3SJoseph Koshy 1398d56c5d4bSJoseph Koshy static const struct pmc_masks p4_mask_rmbt[] = { 1399d56c5d4bSJoseph Koshy /* retired mispred branch type */ 1400ebccf1e3SJoseph Koshy __P4MASK(conditional, 1), 1401ebccf1e3SJoseph Koshy __P4MASK(call, 2), 1402ebccf1e3SJoseph Koshy __P4MASK(return, 3), 1403ebccf1e3SJoseph Koshy __P4MASK(indirect, 4), 1404ebccf1e3SJoseph Koshy NULLMASK 1405ebccf1e3SJoseph Koshy }; 1406ebccf1e3SJoseph Koshy 1407ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_rbt[] = { /* retired branch type */ 1408ebccf1e3SJoseph Koshy __P4MASK(conditional, 1), 1409ebccf1e3SJoseph Koshy __P4MASK(call, 2), 1410ebccf1e3SJoseph Koshy __P4MASK(retired, 3), 1411ebccf1e3SJoseph Koshy __P4MASK(indirect, 4), 1412ebccf1e3SJoseph Koshy NULLMASK 1413ebccf1e3SJoseph Koshy }; 1414ebccf1e3SJoseph Koshy 1415ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_rs[] = { /* resource stall */ 1416ebccf1e3SJoseph Koshy __P4MASK(sbfull, 5), 1417ebccf1e3SJoseph Koshy NULLMASK 1418ebccf1e3SJoseph Koshy }; 1419ebccf1e3SJoseph Koshy 1420ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_wb[] = { /* WC buffer */ 1421ebccf1e3SJoseph Koshy __P4MASK(wcb-evicts, 0), 1422ebccf1e3SJoseph Koshy __P4MASK(wcb-full-evict, 1), 1423ebccf1e3SJoseph Koshy NULLMASK 1424ebccf1e3SJoseph Koshy }; 1425ebccf1e3SJoseph Koshy 1426ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_fee[] = { /* front end event */ 1427ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1428ebccf1e3SJoseph Koshy __P4MASK(bogus, 1), 1429ebccf1e3SJoseph Koshy NULLMASK 1430ebccf1e3SJoseph Koshy }; 1431ebccf1e3SJoseph Koshy 1432ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ee[] = { /* execution event */ 1433ebccf1e3SJoseph Koshy __P4MASK(nbogus0, 0), 1434ebccf1e3SJoseph Koshy __P4MASK(nbogus1, 1), 1435ebccf1e3SJoseph Koshy __P4MASK(nbogus2, 2), 1436ebccf1e3SJoseph Koshy __P4MASK(nbogus3, 3), 1437ebccf1e3SJoseph Koshy __P4MASK(bogus0, 4), 1438ebccf1e3SJoseph Koshy __P4MASK(bogus1, 5), 1439ebccf1e3SJoseph Koshy __P4MASK(bogus2, 6), 1440ebccf1e3SJoseph Koshy __P4MASK(bogus3, 7), 1441ebccf1e3SJoseph Koshy NULLMASK 1442ebccf1e3SJoseph Koshy }; 1443ebccf1e3SJoseph Koshy 1444ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_re[] = { /* replay event */ 1445ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1446ebccf1e3SJoseph Koshy __P4MASK(bogus, 1), 1447ebccf1e3SJoseph Koshy NULLMASK 1448ebccf1e3SJoseph Koshy }; 1449ebccf1e3SJoseph Koshy 1450ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_insret[] = { /* instr retired */ 1451ebccf1e3SJoseph Koshy __P4MASK(nbogusntag, 0), 1452ebccf1e3SJoseph Koshy __P4MASK(nbogustag, 1), 1453ebccf1e3SJoseph Koshy __P4MASK(bogusntag, 2), 1454ebccf1e3SJoseph Koshy __P4MASK(bogustag, 3), 1455ebccf1e3SJoseph Koshy NULLMASK 1456ebccf1e3SJoseph Koshy }; 1457ebccf1e3SJoseph Koshy 1458ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ur[] = { /* uops retired */ 1459ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1460ebccf1e3SJoseph Koshy __P4MASK(bogus, 1), 1461ebccf1e3SJoseph Koshy NULLMASK 1462ebccf1e3SJoseph Koshy }; 1463ebccf1e3SJoseph Koshy 1464ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ut[] = { /* uop type */ 1465ebccf1e3SJoseph Koshy __P4MASK(tagloads, 1), 1466ebccf1e3SJoseph Koshy __P4MASK(tagstores, 2), 1467ebccf1e3SJoseph Koshy NULLMASK 1468ebccf1e3SJoseph Koshy }; 1469ebccf1e3SJoseph Koshy 1470ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_br[] = { /* branch retired */ 1471ebccf1e3SJoseph Koshy __P4MASK(mmnp, 0), 1472ebccf1e3SJoseph Koshy __P4MASK(mmnm, 1), 1473ebccf1e3SJoseph Koshy __P4MASK(mmtp, 2), 1474ebccf1e3SJoseph Koshy __P4MASK(mmtm, 3), 1475ebccf1e3SJoseph Koshy NULLMASK 1476ebccf1e3SJoseph Koshy }; 1477ebccf1e3SJoseph Koshy 1478ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_mbr[] = { /* mispred branch retired */ 1479ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1480ebccf1e3SJoseph Koshy NULLMASK 1481ebccf1e3SJoseph Koshy }; 1482ebccf1e3SJoseph Koshy 1483ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xa[] = { /* x87 assist */ 1484ebccf1e3SJoseph Koshy __P4MASK(fpsu, 0), 1485ebccf1e3SJoseph Koshy __P4MASK(fpso, 1), 1486ebccf1e3SJoseph Koshy __P4MASK(poao, 2), 1487ebccf1e3SJoseph Koshy __P4MASK(poau, 3), 1488ebccf1e3SJoseph Koshy __P4MASK(prea, 4), 1489ebccf1e3SJoseph Koshy NULLMASK 1490ebccf1e3SJoseph Koshy }; 1491ebccf1e3SJoseph Koshy 1492ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_machclr[] = { /* machine clear */ 1493ebccf1e3SJoseph Koshy __P4MASK(clear, 0), 1494ebccf1e3SJoseph Koshy __P4MASK(moclear, 2), 1495ebccf1e3SJoseph Koshy __P4MASK(smclear, 3), 1496ebccf1e3SJoseph Koshy NULLMASK 1497ebccf1e3SJoseph Koshy }; 1498ebccf1e3SJoseph Koshy 1499ebccf1e3SJoseph Koshy /* P4 event parser */ 1500ebccf1e3SJoseph Koshy static int 1501ebccf1e3SJoseph Koshy p4_allocate_pmc(enum pmc_event pe, char *ctrspec, 1502ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 1503ebccf1e3SJoseph Koshy { 1504ebccf1e3SJoseph Koshy 1505ebccf1e3SJoseph Koshy char *e, *p, *q; 1506ebccf1e3SJoseph Koshy int count, has_tag, has_busreqtype, n; 1507ebccf1e3SJoseph Koshy uint32_t evmask, cccractivemask; 1508ebccf1e3SJoseph Koshy const struct pmc_masks *pm, *pmask; 1509ebccf1e3SJoseph Koshy 1510789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1511f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig = 1512f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 0; 1513ebccf1e3SJoseph Koshy 1514ebccf1e3SJoseph Koshy pmask = NULL; 1515ebccf1e3SJoseph Koshy evmask = 0; 1516ebccf1e3SJoseph Koshy cccractivemask = 0x3; 1517ebccf1e3SJoseph Koshy has_tag = has_busreqtype = 0; 1518ebccf1e3SJoseph Koshy 1519ebccf1e3SJoseph Koshy #define __P4SETMASK(M) do { \ 1520ebccf1e3SJoseph Koshy pmask = p4_mask_##M; \ 1521ebccf1e3SJoseph Koshy } while (0) 1522ebccf1e3SJoseph Koshy 1523ebccf1e3SJoseph Koshy switch (pe) { 1524ebccf1e3SJoseph Koshy case PMC_EV_P4_TC_DELIVER_MODE: 1525ebccf1e3SJoseph Koshy __P4SETMASK(tcdm); 1526ebccf1e3SJoseph Koshy break; 1527ebccf1e3SJoseph Koshy case PMC_EV_P4_BPU_FETCH_REQUEST: 1528ebccf1e3SJoseph Koshy __P4SETMASK(bfr); 1529ebccf1e3SJoseph Koshy break; 1530ebccf1e3SJoseph Koshy case PMC_EV_P4_ITLB_REFERENCE: 1531ebccf1e3SJoseph Koshy __P4SETMASK(ir); 1532ebccf1e3SJoseph Koshy break; 1533ebccf1e3SJoseph Koshy case PMC_EV_P4_MEMORY_CANCEL: 1534ebccf1e3SJoseph Koshy __P4SETMASK(memcan); 1535ebccf1e3SJoseph Koshy break; 1536ebccf1e3SJoseph Koshy case PMC_EV_P4_MEMORY_COMPLETE: 1537ebccf1e3SJoseph Koshy __P4SETMASK(memcomp); 1538ebccf1e3SJoseph Koshy break; 1539ebccf1e3SJoseph Koshy case PMC_EV_P4_LOAD_PORT_REPLAY: 1540ebccf1e3SJoseph Koshy __P4SETMASK(lpr); 1541ebccf1e3SJoseph Koshy break; 1542ebccf1e3SJoseph Koshy case PMC_EV_P4_STORE_PORT_REPLAY: 1543ebccf1e3SJoseph Koshy __P4SETMASK(spr); 1544ebccf1e3SJoseph Koshy break; 1545ebccf1e3SJoseph Koshy case PMC_EV_P4_MOB_LOAD_REPLAY: 1546ebccf1e3SJoseph Koshy __P4SETMASK(mlr); 1547ebccf1e3SJoseph Koshy break; 1548ebccf1e3SJoseph Koshy case PMC_EV_P4_PAGE_WALK_TYPE: 1549ebccf1e3SJoseph Koshy __P4SETMASK(pwt); 1550ebccf1e3SJoseph Koshy break; 1551ebccf1e3SJoseph Koshy case PMC_EV_P4_BSQ_CACHE_REFERENCE: 1552ebccf1e3SJoseph Koshy __P4SETMASK(bcr); 1553ebccf1e3SJoseph Koshy break; 1554ebccf1e3SJoseph Koshy case PMC_EV_P4_IOQ_ALLOCATION: 1555ebccf1e3SJoseph Koshy __P4SETMASK(ia); 1556ebccf1e3SJoseph Koshy has_busreqtype = 1; 1557ebccf1e3SJoseph Koshy break; 1558ebccf1e3SJoseph Koshy case PMC_EV_P4_IOQ_ACTIVE_ENTRIES: 1559ebccf1e3SJoseph Koshy __P4SETMASK(iae); 1560ebccf1e3SJoseph Koshy has_busreqtype = 1; 1561ebccf1e3SJoseph Koshy break; 1562ebccf1e3SJoseph Koshy case PMC_EV_P4_FSB_DATA_ACTIVITY: 1563ebccf1e3SJoseph Koshy __P4SETMASK(fda); 1564ebccf1e3SJoseph Koshy break; 1565ebccf1e3SJoseph Koshy case PMC_EV_P4_BSQ_ALLOCATION: 1566ebccf1e3SJoseph Koshy __P4SETMASK(ba); 1567ebccf1e3SJoseph Koshy break; 1568ebccf1e3SJoseph Koshy case PMC_EV_P4_SSE_INPUT_ASSIST: 1569ebccf1e3SJoseph Koshy __P4SETMASK(sia); 1570ebccf1e3SJoseph Koshy break; 1571ebccf1e3SJoseph Koshy case PMC_EV_P4_PACKED_SP_UOP: 1572ebccf1e3SJoseph Koshy __P4SETMASK(psu); 1573ebccf1e3SJoseph Koshy break; 1574ebccf1e3SJoseph Koshy case PMC_EV_P4_PACKED_DP_UOP: 1575ebccf1e3SJoseph Koshy __P4SETMASK(pdu); 1576ebccf1e3SJoseph Koshy break; 1577ebccf1e3SJoseph Koshy case PMC_EV_P4_SCALAR_SP_UOP: 1578ebccf1e3SJoseph Koshy __P4SETMASK(ssu); 1579ebccf1e3SJoseph Koshy break; 1580ebccf1e3SJoseph Koshy case PMC_EV_P4_SCALAR_DP_UOP: 1581ebccf1e3SJoseph Koshy __P4SETMASK(sdu); 1582ebccf1e3SJoseph Koshy break; 1583ebccf1e3SJoseph Koshy case PMC_EV_P4_64BIT_MMX_UOP: 1584ebccf1e3SJoseph Koshy __P4SETMASK(64bmu); 1585ebccf1e3SJoseph Koshy break; 1586ebccf1e3SJoseph Koshy case PMC_EV_P4_128BIT_MMX_UOP: 1587ebccf1e3SJoseph Koshy __P4SETMASK(128bmu); 1588ebccf1e3SJoseph Koshy break; 1589ebccf1e3SJoseph Koshy case PMC_EV_P4_X87_FP_UOP: 1590ebccf1e3SJoseph Koshy __P4SETMASK(xfu); 1591ebccf1e3SJoseph Koshy break; 1592ebccf1e3SJoseph Koshy case PMC_EV_P4_X87_SIMD_MOVES_UOP: 1593ebccf1e3SJoseph Koshy __P4SETMASK(xsmu); 1594ebccf1e3SJoseph Koshy break; 1595ebccf1e3SJoseph Koshy case PMC_EV_P4_GLOBAL_POWER_EVENTS: 1596ebccf1e3SJoseph Koshy __P4SETMASK(gpe); 1597ebccf1e3SJoseph Koshy break; 1598ebccf1e3SJoseph Koshy case PMC_EV_P4_TC_MS_XFER: 1599ebccf1e3SJoseph Koshy __P4SETMASK(tmx); 1600ebccf1e3SJoseph Koshy break; 1601ebccf1e3SJoseph Koshy case PMC_EV_P4_UOP_QUEUE_WRITES: 1602ebccf1e3SJoseph Koshy __P4SETMASK(uqw); 1603ebccf1e3SJoseph Koshy break; 1604ebccf1e3SJoseph Koshy case PMC_EV_P4_RETIRED_MISPRED_BRANCH_TYPE: 1605ebccf1e3SJoseph Koshy __P4SETMASK(rmbt); 1606ebccf1e3SJoseph Koshy break; 1607ebccf1e3SJoseph Koshy case PMC_EV_P4_RETIRED_BRANCH_TYPE: 1608ebccf1e3SJoseph Koshy __P4SETMASK(rbt); 1609ebccf1e3SJoseph Koshy break; 1610ebccf1e3SJoseph Koshy case PMC_EV_P4_RESOURCE_STALL: 1611ebccf1e3SJoseph Koshy __P4SETMASK(rs); 1612ebccf1e3SJoseph Koshy break; 1613ebccf1e3SJoseph Koshy case PMC_EV_P4_WC_BUFFER: 1614ebccf1e3SJoseph Koshy __P4SETMASK(wb); 1615ebccf1e3SJoseph Koshy break; 1616ebccf1e3SJoseph Koshy case PMC_EV_P4_BSQ_ACTIVE_ENTRIES: 1617ebccf1e3SJoseph Koshy case PMC_EV_P4_B2B_CYCLES: 1618ebccf1e3SJoseph Koshy case PMC_EV_P4_BNR: 1619ebccf1e3SJoseph Koshy case PMC_EV_P4_SNOOP: 1620ebccf1e3SJoseph Koshy case PMC_EV_P4_RESPONSE: 1621ebccf1e3SJoseph Koshy break; 1622ebccf1e3SJoseph Koshy case PMC_EV_P4_FRONT_END_EVENT: 1623ebccf1e3SJoseph Koshy __P4SETMASK(fee); 1624ebccf1e3SJoseph Koshy break; 1625ebccf1e3SJoseph Koshy case PMC_EV_P4_EXECUTION_EVENT: 1626ebccf1e3SJoseph Koshy __P4SETMASK(ee); 1627ebccf1e3SJoseph Koshy break; 1628ebccf1e3SJoseph Koshy case PMC_EV_P4_REPLAY_EVENT: 1629ebccf1e3SJoseph Koshy __P4SETMASK(re); 1630ebccf1e3SJoseph Koshy break; 1631ebccf1e3SJoseph Koshy case PMC_EV_P4_INSTR_RETIRED: 1632ebccf1e3SJoseph Koshy __P4SETMASK(insret); 1633ebccf1e3SJoseph Koshy break; 1634ebccf1e3SJoseph Koshy case PMC_EV_P4_UOPS_RETIRED: 1635ebccf1e3SJoseph Koshy __P4SETMASK(ur); 1636ebccf1e3SJoseph Koshy break; 1637ebccf1e3SJoseph Koshy case PMC_EV_P4_UOP_TYPE: 1638ebccf1e3SJoseph Koshy __P4SETMASK(ut); 1639ebccf1e3SJoseph Koshy break; 1640ebccf1e3SJoseph Koshy case PMC_EV_P4_BRANCH_RETIRED: 1641ebccf1e3SJoseph Koshy __P4SETMASK(br); 1642ebccf1e3SJoseph Koshy break; 1643ebccf1e3SJoseph Koshy case PMC_EV_P4_MISPRED_BRANCH_RETIRED: 1644ebccf1e3SJoseph Koshy __P4SETMASK(mbr); 1645ebccf1e3SJoseph Koshy break; 1646ebccf1e3SJoseph Koshy case PMC_EV_P4_X87_ASSIST: 1647ebccf1e3SJoseph Koshy __P4SETMASK(xa); 1648ebccf1e3SJoseph Koshy break; 1649ebccf1e3SJoseph Koshy case PMC_EV_P4_MACHINE_CLEAR: 1650ebccf1e3SJoseph Koshy __P4SETMASK(machclr); 1651ebccf1e3SJoseph Koshy break; 1652ebccf1e3SJoseph Koshy default: 1653aa342b1fSJoseph Koshy return (-1); 1654ebccf1e3SJoseph Koshy } 1655ebccf1e3SJoseph Koshy 1656ebccf1e3SJoseph Koshy /* process additional flags */ 1657ebccf1e3SJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 1658ebccf1e3SJoseph Koshy if (KWPREFIXMATCH(p, P4_KW_ACTIVE)) { 1659ebccf1e3SJoseph Koshy q = strchr(p, '='); 1660ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1661aa342b1fSJoseph Koshy return (-1); 1662ebccf1e3SJoseph Koshy 1663789140c0SJoseph Koshy if (strcasecmp(q, P4_KW_ACTIVE_NONE) == 0) 1664ebccf1e3SJoseph Koshy cccractivemask = 0x0; 1665789140c0SJoseph Koshy else if (strcasecmp(q, P4_KW_ACTIVE_SINGLE) == 0) 1666ebccf1e3SJoseph Koshy cccractivemask = 0x1; 1667789140c0SJoseph Koshy else if (strcasecmp(q, P4_KW_ACTIVE_BOTH) == 0) 1668ebccf1e3SJoseph Koshy cccractivemask = 0x2; 1669789140c0SJoseph Koshy else if (strcasecmp(q, P4_KW_ACTIVE_ANY) == 0) 1670ebccf1e3SJoseph Koshy cccractivemask = 0x3; 1671ebccf1e3SJoseph Koshy else 1672aa342b1fSJoseph Koshy return (-1); 1673ebccf1e3SJoseph Koshy 1674ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, P4_KW_BUSREQTYPE)) { 1675ebccf1e3SJoseph Koshy if (has_busreqtype == 0) 1676aa342b1fSJoseph Koshy return (-1); 1677ebccf1e3SJoseph Koshy 1678ebccf1e3SJoseph Koshy q = strchr(p, '='); 1679ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1680aa342b1fSJoseph Koshy return (-1); 1681ebccf1e3SJoseph Koshy 1682ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 1683ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 1684aa342b1fSJoseph Koshy return (-1); 1685ebccf1e3SJoseph Koshy evmask = (evmask & ~0x1F) | (count & 0x1F); 1686ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P4_KW_CASCADE)) 1687ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_CASCADE; 1688ebccf1e3SJoseph Koshy else if (KWMATCH(p, P4_KW_EDGE)) 1689ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1690ebccf1e3SJoseph Koshy else if (KWMATCH(p, P4_KW_INV)) 1691ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 1692ebccf1e3SJoseph Koshy else if (KWPREFIXMATCH(p, P4_KW_MASK "=")) { 1693ebccf1e3SJoseph Koshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 1694aa342b1fSJoseph Koshy return (-1); 1695ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1696ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P4_KW_OS)) 1697ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 1698ebccf1e3SJoseph Koshy else if (KWMATCH(p, P4_KW_PRECISE)) 1699ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_PRECISE; 1700ebccf1e3SJoseph Koshy else if (KWPREFIXMATCH(p, P4_KW_TAG "=")) { 1701ebccf1e3SJoseph Koshy if (has_tag == 0) 1702aa342b1fSJoseph Koshy return (-1); 1703ebccf1e3SJoseph Koshy 1704ebccf1e3SJoseph Koshy q = strchr(p, '='); 1705ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1706aa342b1fSJoseph Koshy return (-1); 1707ebccf1e3SJoseph Koshy 1708ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 1709ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 1710aa342b1fSJoseph Koshy return (-1); 1711ebccf1e3SJoseph Koshy 1712ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_TAGGING; 1713f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig |= 1714ebccf1e3SJoseph Koshy P4_ESCR_TO_TAG_VALUE(count); 1715ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, P4_KW_THRESHOLD "=")) { 1716ebccf1e3SJoseph Koshy q = strchr(p, '='); 1717ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1718aa342b1fSJoseph Koshy return (-1); 1719ebccf1e3SJoseph Koshy 1720ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 1721ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 1722aa342b1fSJoseph Koshy return (-1); 1723ebccf1e3SJoseph Koshy 1724ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 1725f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig &= 1726f263522aSJoseph Koshy ~P4_CCCR_THRESHOLD_MASK; 1727f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |= 1728f263522aSJoseph Koshy P4_CCCR_TO_THRESHOLD(count); 1729ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P4_KW_USR)) 1730ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 1731ebccf1e3SJoseph Koshy else 1732aa342b1fSJoseph Koshy return (-1); 1733ebccf1e3SJoseph Koshy } 1734ebccf1e3SJoseph Koshy 1735ebccf1e3SJoseph Koshy /* other post processing */ 1736ebccf1e3SJoseph Koshy if (pe == PMC_EV_P4_IOQ_ALLOCATION || 1737ebccf1e3SJoseph Koshy pe == PMC_EV_P4_FSB_DATA_ACTIVITY || 1738ebccf1e3SJoseph Koshy pe == PMC_EV_P4_BSQ_ALLOCATION) 1739ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1740ebccf1e3SJoseph Koshy 1741ebccf1e3SJoseph Koshy /* fill in thread activity mask */ 1742f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |= 1743ebccf1e3SJoseph Koshy P4_CCCR_TO_ACTIVE_THREAD(cccractivemask); 1744ebccf1e3SJoseph Koshy 1745ebccf1e3SJoseph Koshy if (evmask) 1746ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1747ebccf1e3SJoseph Koshy 1748ebccf1e3SJoseph Koshy switch (pe) { 1749ebccf1e3SJoseph Koshy case PMC_EV_P4_FSB_DATA_ACTIVITY: 1750ebccf1e3SJoseph Koshy if ((evmask & 0x06) == 0x06 || 1751ebccf1e3SJoseph Koshy (evmask & 0x18) == 0x18) 1752aa342b1fSJoseph Koshy return (-1); /* can't have own+other bits together */ 1753ebccf1e3SJoseph Koshy if (evmask == 0) /* default:drdy-{drv,own}+dbsy{drv,own} */ 1754ebccf1e3SJoseph Koshy evmask = 0x1D; 1755ebccf1e3SJoseph Koshy break; 1756ebccf1e3SJoseph Koshy case PMC_EV_P4_MACHINE_CLEAR: 1757ebccf1e3SJoseph Koshy /* only one bit is allowed to be set */ 1758ebccf1e3SJoseph Koshy if ((evmask & (evmask - 1)) != 0) 1759aa342b1fSJoseph Koshy return (-1); 1760ebccf1e3SJoseph Koshy if (evmask == 0) { 1761ebccf1e3SJoseph Koshy evmask = 0x1; /* 'CLEAR' */ 1762ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1763ebccf1e3SJoseph Koshy } 1764ebccf1e3SJoseph Koshy break; 1765ebccf1e3SJoseph Koshy default: 1766ebccf1e3SJoseph Koshy if (evmask == 0 && pmask) { 1767ebccf1e3SJoseph Koshy for (pm = pmask; pm->pm_name; pm++) 1768ebccf1e3SJoseph Koshy evmask |= pm->pm_value; 1769ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1770ebccf1e3SJoseph Koshy } 1771ebccf1e3SJoseph Koshy } 1772ebccf1e3SJoseph Koshy 1773f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 1774f263522aSJoseph Koshy P4_ESCR_TO_EVENT_MASK(evmask); 1775ebccf1e3SJoseph Koshy 1776aa342b1fSJoseph Koshy return (0); 1777ebccf1e3SJoseph Koshy } 1778ebccf1e3SJoseph Koshy 177986a65549SJoseph Koshy #endif 178086a65549SJoseph Koshy 178186a65549SJoseph Koshy #if defined(__i386__) 178286a65549SJoseph Koshy 1783ebccf1e3SJoseph Koshy /* 1784f263522aSJoseph Koshy * Pentium style PMCs 1785f263522aSJoseph Koshy */ 1786f263522aSJoseph Koshy 1787f263522aSJoseph Koshy static struct pmc_event_alias p5_aliases[] = { 17880b9b757dSJoseph Koshy EV_ALIAS("branches", "p5-taken-branches"), 1789f263522aSJoseph Koshy EV_ALIAS("cycles", "tsc"), 17900b9b757dSJoseph Koshy EV_ALIAS("dc-misses", "p5-data-read-miss-or-write-miss"), 17910b9b757dSJoseph Koshy EV_ALIAS("ic-misses", "p5-code-cache-miss"), 17920b9b757dSJoseph Koshy EV_ALIAS("instructions", "p5-instructions-executed"), 17930b9b757dSJoseph Koshy EV_ALIAS("interrupts", "p5-hardware-interrupts"), 17940b9b757dSJoseph Koshy EV_ALIAS("unhalted-cycles", 17950b9b757dSJoseph Koshy "p5-number-of-cycles-not-in-halt-state"), 1796f263522aSJoseph Koshy EV_ALIAS(NULL, NULL) 1797f263522aSJoseph Koshy }; 1798f263522aSJoseph Koshy 1799f263522aSJoseph Koshy static int 1800f263522aSJoseph Koshy p5_allocate_pmc(enum pmc_event pe, char *ctrspec, 1801f263522aSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 1802f263522aSJoseph Koshy { 1803aa342b1fSJoseph Koshy return (-1 || pe || ctrspec || pmc_config); /* shut up gcc */ 1804f263522aSJoseph Koshy } 1805f263522aSJoseph Koshy 1806f263522aSJoseph Koshy /* 1807ebccf1e3SJoseph Koshy * Pentium Pro style PMCs. These PMCs are found in Pentium II, Pentium III, 1808ebccf1e3SJoseph Koshy * and Pentium M CPUs. 1809ebccf1e3SJoseph Koshy */ 1810ebccf1e3SJoseph Koshy 1811ebccf1e3SJoseph Koshy static struct pmc_event_alias p6_aliases[] = { 1812ebccf1e3SJoseph Koshy EV_ALIAS("branches", "p6-br-inst-retired"), 1813ebccf1e3SJoseph Koshy EV_ALIAS("branch-mispredicts", "p6-br-miss-pred-retired"), 1814ebccf1e3SJoseph Koshy EV_ALIAS("cycles", "tsc"), 1815d56c5d4bSJoseph Koshy EV_ALIAS("dc-misses", "p6-dcu-lines-in"), 181673e2d811SJoseph Koshy EV_ALIAS("ic-misses", "p6-ifu-fetch-miss"), 1817ebccf1e3SJoseph Koshy EV_ALIAS("instructions", "p6-inst-retired"), 1818ebccf1e3SJoseph Koshy EV_ALIAS("interrupts", "p6-hw-int-rx"), 1819177a2f22SJoseph Koshy EV_ALIAS("unhalted-cycles", "p6-cpu-clk-unhalted"), 1820ebccf1e3SJoseph Koshy EV_ALIAS(NULL, NULL) 1821ebccf1e3SJoseph Koshy }; 1822ebccf1e3SJoseph Koshy 1823ebccf1e3SJoseph Koshy #define P6_KW_CMASK "cmask" 1824ebccf1e3SJoseph Koshy #define P6_KW_EDGE "edge" 1825ebccf1e3SJoseph Koshy #define P6_KW_INV "inv" 1826ebccf1e3SJoseph Koshy #define P6_KW_OS "os" 1827ebccf1e3SJoseph Koshy #define P6_KW_UMASK "umask" 1828ebccf1e3SJoseph Koshy #define P6_KW_USR "usr" 1829ebccf1e3SJoseph Koshy 1830ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mesi[] = { 1831ebccf1e3SJoseph Koshy PMCMASK(m, 0x01), 1832ebccf1e3SJoseph Koshy PMCMASK(e, 0x02), 1833ebccf1e3SJoseph Koshy PMCMASK(s, 0x04), 1834ebccf1e3SJoseph Koshy PMCMASK(i, 0x08), 1835ebccf1e3SJoseph Koshy NULLMASK 1836ebccf1e3SJoseph Koshy }; 1837ebccf1e3SJoseph Koshy 1838ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mesihw[] = { 1839ebccf1e3SJoseph Koshy PMCMASK(m, 0x01), 1840ebccf1e3SJoseph Koshy PMCMASK(e, 0x02), 1841ebccf1e3SJoseph Koshy PMCMASK(s, 0x04), 1842ebccf1e3SJoseph Koshy PMCMASK(i, 0x08), 1843ebccf1e3SJoseph Koshy PMCMASK(nonhw, 0x00), 1844ebccf1e3SJoseph Koshy PMCMASK(hw, 0x10), 1845ebccf1e3SJoseph Koshy PMCMASK(both, 0x30), 1846ebccf1e3SJoseph Koshy NULLMASK 1847ebccf1e3SJoseph Koshy }; 1848ebccf1e3SJoseph Koshy 1849ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_hw[] = { 1850ebccf1e3SJoseph Koshy PMCMASK(nonhw, 0x00), 1851ebccf1e3SJoseph Koshy PMCMASK(hw, 0x10), 1852ebccf1e3SJoseph Koshy PMCMASK(both, 0x30), 1853ebccf1e3SJoseph Koshy NULLMASK 1854ebccf1e3SJoseph Koshy }; 1855ebccf1e3SJoseph Koshy 1856ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_any[] = { 1857ebccf1e3SJoseph Koshy PMCMASK(self, 0x00), 1858ebccf1e3SJoseph Koshy PMCMASK(any, 0x20), 1859ebccf1e3SJoseph Koshy NULLMASK 1860ebccf1e3SJoseph Koshy }; 1861ebccf1e3SJoseph Koshy 1862ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_ekp[] = { 1863ebccf1e3SJoseph Koshy PMCMASK(nta, 0x00), 1864ebccf1e3SJoseph Koshy PMCMASK(t1, 0x01), 1865ebccf1e3SJoseph Koshy PMCMASK(t2, 0x02), 1866ebccf1e3SJoseph Koshy PMCMASK(wos, 0x03), 1867ebccf1e3SJoseph Koshy NULLMASK 1868ebccf1e3SJoseph Koshy }; 1869ebccf1e3SJoseph Koshy 1870ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_pps[] = { 1871ebccf1e3SJoseph Koshy PMCMASK(packed-and-scalar, 0x00), 1872ebccf1e3SJoseph Koshy PMCMASK(scalar, 0x01), 1873ebccf1e3SJoseph Koshy NULLMASK 1874ebccf1e3SJoseph Koshy }; 1875ebccf1e3SJoseph Koshy 1876ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mite[] = { 1877ebccf1e3SJoseph Koshy PMCMASK(packed-multiply, 0x01), 1878ebccf1e3SJoseph Koshy PMCMASK(packed-shift, 0x02), 1879ebccf1e3SJoseph Koshy PMCMASK(pack, 0x04), 1880ebccf1e3SJoseph Koshy PMCMASK(unpack, 0x08), 1881ebccf1e3SJoseph Koshy PMCMASK(packed-logical, 0x10), 1882ebccf1e3SJoseph Koshy PMCMASK(packed-arithmetic, 0x20), 1883ebccf1e3SJoseph Koshy NULLMASK 1884ebccf1e3SJoseph Koshy }; 1885ebccf1e3SJoseph Koshy 1886ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_fmt[] = { 1887ebccf1e3SJoseph Koshy PMCMASK(mmxtofp, 0x00), 1888ebccf1e3SJoseph Koshy PMCMASK(fptommx, 0x01), 1889ebccf1e3SJoseph Koshy NULLMASK 1890ebccf1e3SJoseph Koshy }; 1891ebccf1e3SJoseph Koshy 1892ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_sr[] = { 1893ebccf1e3SJoseph Koshy PMCMASK(es, 0x01), 1894ebccf1e3SJoseph Koshy PMCMASK(ds, 0x02), 1895ebccf1e3SJoseph Koshy PMCMASK(fs, 0x04), 1896ebccf1e3SJoseph Koshy PMCMASK(gs, 0x08), 1897ebccf1e3SJoseph Koshy NULLMASK 1898ebccf1e3SJoseph Koshy }; 1899ebccf1e3SJoseph Koshy 1900ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_eet[] = { 1901ebccf1e3SJoseph Koshy PMCMASK(all, 0x00), 1902ebccf1e3SJoseph Koshy PMCMASK(freq, 0x02), 1903ebccf1e3SJoseph Koshy NULLMASK 1904ebccf1e3SJoseph Koshy }; 1905ebccf1e3SJoseph Koshy 1906ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_efur[] = { 1907ebccf1e3SJoseph Koshy PMCMASK(all, 0x00), 1908ebccf1e3SJoseph Koshy PMCMASK(loadop, 0x01), 1909ebccf1e3SJoseph Koshy PMCMASK(stdsta, 0x02), 1910ebccf1e3SJoseph Koshy NULLMASK 1911ebccf1e3SJoseph Koshy }; 1912ebccf1e3SJoseph Koshy 1913ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_essir[] = { 1914ebccf1e3SJoseph Koshy PMCMASK(sse-packed-single, 0x00), 1915ebccf1e3SJoseph Koshy PMCMASK(sse-packed-single-scalar-single, 0x01), 1916ebccf1e3SJoseph Koshy PMCMASK(sse2-packed-double, 0x02), 1917ebccf1e3SJoseph Koshy PMCMASK(sse2-scalar-double, 0x03), 1918ebccf1e3SJoseph Koshy NULLMASK 1919ebccf1e3SJoseph Koshy }; 1920ebccf1e3SJoseph Koshy 1921ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_esscir[] = { 1922ebccf1e3SJoseph Koshy PMCMASK(sse-packed-single, 0x00), 1923ebccf1e3SJoseph Koshy PMCMASK(sse-scalar-single, 0x01), 1924ebccf1e3SJoseph Koshy PMCMASK(sse2-packed-double, 0x02), 1925ebccf1e3SJoseph Koshy PMCMASK(sse2-scalar-double, 0x03), 1926ebccf1e3SJoseph Koshy NULLMASK 1927ebccf1e3SJoseph Koshy }; 1928ebccf1e3SJoseph Koshy 1929ebccf1e3SJoseph Koshy /* P6 event parser */ 1930ebccf1e3SJoseph Koshy static int 1931ebccf1e3SJoseph Koshy p6_allocate_pmc(enum pmc_event pe, char *ctrspec, 1932ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 1933ebccf1e3SJoseph Koshy { 1934ebccf1e3SJoseph Koshy char *e, *p, *q; 1935ebccf1e3SJoseph Koshy uint32_t evmask; 1936ebccf1e3SJoseph Koshy int count, n; 1937ebccf1e3SJoseph Koshy const struct pmc_masks *pm, *pmask; 1938ebccf1e3SJoseph Koshy 1939789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1940f263522aSJoseph Koshy pmc_config->pm_md.pm_ppro.pm_ppro_config = 0; 1941ebccf1e3SJoseph Koshy 1942ebccf1e3SJoseph Koshy evmask = 0; 1943ebccf1e3SJoseph Koshy 1944ebccf1e3SJoseph Koshy #define P6MASKSET(M) pmask = p6_mask_ ## M 1945ebccf1e3SJoseph Koshy 1946ebccf1e3SJoseph Koshy switch(pe) { 1947ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_IFETCH: P6MASKSET(mesi); break; 1948ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_LD: P6MASKSET(mesi); break; 1949ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_ST: P6MASKSET(mesi); break; 1950ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_RQSTS: P6MASKSET(mesi); break; 1951ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_DRDY_CLOCKS: 1952ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_LOCK_CLOCKS: 1953ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BRD: 1954ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_RFO: 1955ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_WB: 1956ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_IFETCH: 1957ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_INVAL: 1958ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_PWR: 1959ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_P: 1960ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_IO: 1961ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_DEF: 1962ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BURST: 1963ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_ANY: 1964ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_MEM: 1965ebccf1e3SJoseph Koshy P6MASKSET(any); break; 1966ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED: 1967ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_MISS: 1968ebccf1e3SJoseph Koshy P6MASKSET(ekp); break; 1969ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_INST_RETIRED: 1970ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_COMP_INST_RET: 1971ebccf1e3SJoseph Koshy P6MASKSET(pps); break; 1972ebccf1e3SJoseph Koshy case PMC_EV_P6_MMX_INSTR_TYPE_EXEC: 1973ebccf1e3SJoseph Koshy P6MASKSET(mite); break; 1974ebccf1e3SJoseph Koshy case PMC_EV_P6_FP_MMX_TRANS: 1975ebccf1e3SJoseph Koshy P6MASKSET(fmt); break; 1976ebccf1e3SJoseph Koshy case PMC_EV_P6_SEG_RENAME_STALLS: 1977ebccf1e3SJoseph Koshy case PMC_EV_P6_SEG_REG_RENAMES: 1978ebccf1e3SJoseph Koshy P6MASKSET(sr); break; 1979ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_EST_TRANS: 1980ebccf1e3SJoseph Koshy P6MASKSET(eet); break; 1981ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_FUSED_UOPS_RET: 1982ebccf1e3SJoseph Koshy P6MASKSET(efur); break; 1983ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED: 1984ebccf1e3SJoseph Koshy P6MASKSET(essir); break; 1985ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED: 1986ebccf1e3SJoseph Koshy P6MASKSET(esscir); break; 1987ebccf1e3SJoseph Koshy default: 1988ebccf1e3SJoseph Koshy pmask = NULL; 1989ebccf1e3SJoseph Koshy break; 1990ebccf1e3SJoseph Koshy } 1991ebccf1e3SJoseph Koshy 1992ebccf1e3SJoseph Koshy /* Pentium M PMCs have a few events with different semantics */ 1993ebccf1e3SJoseph Koshy if (cpu_info.pm_cputype == PMC_CPU_INTEL_PM) { 1994ebccf1e3SJoseph Koshy if (pe == PMC_EV_P6_L2_LD || 1995ebccf1e3SJoseph Koshy pe == PMC_EV_P6_L2_LINES_IN || 1996ebccf1e3SJoseph Koshy pe == PMC_EV_P6_L2_LINES_OUT) 1997ebccf1e3SJoseph Koshy P6MASKSET(mesihw); 1998ebccf1e3SJoseph Koshy else if (pe == PMC_EV_P6_L2_M_LINES_OUTM) 1999ebccf1e3SJoseph Koshy P6MASKSET(hw); 2000ebccf1e3SJoseph Koshy } 2001ebccf1e3SJoseph Koshy 2002ebccf1e3SJoseph Koshy /* Parse additional modifiers if present */ 2003ebccf1e3SJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 2004ebccf1e3SJoseph Koshy if (KWPREFIXMATCH(p, P6_KW_CMASK "=")) { 2005ebccf1e3SJoseph Koshy q = strchr(p, '='); 2006ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 2007aa342b1fSJoseph Koshy return (-1); 2008ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 2009ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 2010aa342b1fSJoseph Koshy return (-1); 2011ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 2012f263522aSJoseph Koshy pmc_config->pm_md.pm_ppro.pm_ppro_config |= 2013f263522aSJoseph Koshy P6_EVSEL_TO_CMASK(count); 2014ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_EDGE)) { 2015ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 2016ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_INV)) { 2017ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 2018ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_OS)) { 2019ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2020ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, P6_KW_UMASK "=")) { 2021ebccf1e3SJoseph Koshy evmask = 0; 2022ebccf1e3SJoseph Koshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 2023aa342b1fSJoseph Koshy return (-1); 2024ebccf1e3SJoseph Koshy if ((pe == PMC_EV_P6_BUS_DRDY_CLOCKS || 2025ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_LOCK_CLOCKS || 2026ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_BRD || 2027ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_RFO || 2028ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_IFETCH || 2029ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_INVAL || 2030ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_PWR || 2031ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_DEF || 2032ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_BURST || 2033ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_ANY || 2034ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_MEM || 2035ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRANS_IO || 2036ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRANS_P || 2037ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRANS_WB || 2038ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_EST_TRANS || 2039ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_FUSED_UOPS_RET || 2040ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_COMP_INST_RET || 2041ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_INST_RETIRED || 2042ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_PREF_DISPATCHED || 2043ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_PREF_MISS || 2044ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED || 2045ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED || 2046ebccf1e3SJoseph Koshy pe == PMC_EV_P6_FP_MMX_TRANS) 2047aa342b1fSJoseph Koshy && (n > 1)) /* Only one mask keyword is allowed. */ 2048aa342b1fSJoseph Koshy return (-1); 2049ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2050ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_USR)) { 2051ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 2052ebccf1e3SJoseph Koshy } else 2053aa342b1fSJoseph Koshy return (-1); 2054ebccf1e3SJoseph Koshy } 2055ebccf1e3SJoseph Koshy 2056ebccf1e3SJoseph Koshy /* post processing */ 2057ebccf1e3SJoseph Koshy switch (pe) { 2058ebccf1e3SJoseph Koshy 2059ebccf1e3SJoseph Koshy /* 2060ebccf1e3SJoseph Koshy * The following events default to an evmask of 0 2061ebccf1e3SJoseph Koshy */ 2062ebccf1e3SJoseph Koshy 2063ebccf1e3SJoseph Koshy /* default => 'self' */ 2064ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_DRDY_CLOCKS: 2065ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_LOCK_CLOCKS: 2066ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BRD: 2067ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_RFO: 2068ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_WB: 2069ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_IFETCH: 2070ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_INVAL: 2071ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_PWR: 2072ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_P: 2073ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_IO: 2074ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_DEF: 2075ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BURST: 2076ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_ANY: 2077ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_MEM: 2078ebccf1e3SJoseph Koshy 2079ebccf1e3SJoseph Koshy /* default => 'nta' */ 2080ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED: 2081ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_MISS: 2082ebccf1e3SJoseph Koshy 2083ebccf1e3SJoseph Koshy /* default => 'packed and scalar' */ 2084ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_INST_RETIRED: 2085ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_COMP_INST_RET: 2086ebccf1e3SJoseph Koshy 2087ebccf1e3SJoseph Koshy /* default => 'mmx to fp transitions' */ 2088ebccf1e3SJoseph Koshy case PMC_EV_P6_FP_MMX_TRANS: 2089ebccf1e3SJoseph Koshy 2090ebccf1e3SJoseph Koshy /* default => 'SSE Packed Single' */ 2091ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED: 2092ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED: 2093ebccf1e3SJoseph Koshy 2094ebccf1e3SJoseph Koshy /* default => 'all fused micro-ops' */ 2095ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_FUSED_UOPS_RET: 2096ebccf1e3SJoseph Koshy 2097ebccf1e3SJoseph Koshy /* default => 'all transitions' */ 2098ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_EST_TRANS: 2099ebccf1e3SJoseph Koshy break; 2100ebccf1e3SJoseph Koshy 2101ebccf1e3SJoseph Koshy case PMC_EV_P6_MMX_UOPS_EXEC: 2102ebccf1e3SJoseph Koshy evmask = 0x0F; /* only value allowed */ 2103ebccf1e3SJoseph Koshy break; 2104ebccf1e3SJoseph Koshy 2105ebccf1e3SJoseph Koshy default: 2106ebccf1e3SJoseph Koshy /* 2107ebccf1e3SJoseph Koshy * For all other events, set the default event mask 2108ebccf1e3SJoseph Koshy * to a logical OR of all the allowed event mask bits. 2109ebccf1e3SJoseph Koshy */ 2110ebccf1e3SJoseph Koshy if (evmask == 0 && pmask) { 2111ebccf1e3SJoseph Koshy for (pm = pmask; pm->pm_name; pm++) 2112ebccf1e3SJoseph Koshy evmask |= pm->pm_value; 2113ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2114ebccf1e3SJoseph Koshy } 2115ebccf1e3SJoseph Koshy 2116ebccf1e3SJoseph Koshy break; 2117ebccf1e3SJoseph Koshy } 2118ebccf1e3SJoseph Koshy 2119ebccf1e3SJoseph Koshy if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) 2120f263522aSJoseph Koshy pmc_config->pm_md.pm_ppro.pm_ppro_config |= 2121f263522aSJoseph Koshy P6_EVSEL_TO_UMASK(evmask); 2122ebccf1e3SJoseph Koshy 2123aa342b1fSJoseph Koshy return (0); 2124ebccf1e3SJoseph Koshy } 2125ebccf1e3SJoseph Koshy 2126ebccf1e3SJoseph Koshy #endif 2127ebccf1e3SJoseph Koshy 2128789140c0SJoseph Koshy #if defined(__i386__) || defined(__amd64__) 2129789140c0SJoseph Koshy static int 2130789140c0SJoseph Koshy tsc_allocate_pmc(enum pmc_event pe, char *ctrspec, 2131789140c0SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 2132789140c0SJoseph Koshy { 2133789140c0SJoseph Koshy if (pe != PMC_EV_TSC_TSC) 2134789140c0SJoseph Koshy return (-1); 2135789140c0SJoseph Koshy 2136789140c0SJoseph Koshy /* TSC events must be unqualified. */ 2137789140c0SJoseph Koshy if (ctrspec && *ctrspec != '\0') 2138789140c0SJoseph Koshy return (-1); 2139789140c0SJoseph Koshy 2140789140c0SJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 2141789140c0SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_READ; 2142789140c0SJoseph Koshy 2143789140c0SJoseph Koshy return (0); 2144789140c0SJoseph Koshy } 2145789140c0SJoseph Koshy #endif 2146789140c0SJoseph Koshy 21470ce207d2SRui Paulo #if defined(__XSCALE__) 21480ce207d2SRui Paulo 21490ce207d2SRui Paulo static struct pmc_event_alias xscale_aliases[] = { 21500ce207d2SRui Paulo EV_ALIAS("branches", "BRANCH_RETIRED"), 21510ce207d2SRui Paulo EV_ALIAS("branch-mispredicts", "BRANCH_MISPRED"), 21520ce207d2SRui Paulo EV_ALIAS("dc-misses", "DC_MISS"), 21530ce207d2SRui Paulo EV_ALIAS("ic-misses", "IC_MISS"), 21540ce207d2SRui Paulo EV_ALIAS("instructions", "INSTR_RETIRED"), 21550ce207d2SRui Paulo EV_ALIAS(NULL, NULL) 21560ce207d2SRui Paulo }; 21570ce207d2SRui Paulo static int 21580ce207d2SRui Paulo xscale_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 21590ce207d2SRui Paulo struct pmc_op_pmcallocate *pmc_config __unused) 21600ce207d2SRui Paulo { 21610ce207d2SRui Paulo switch (pe) { 21620ce207d2SRui Paulo default: 21630ce207d2SRui Paulo break; 21640ce207d2SRui Paulo } 21650ce207d2SRui Paulo 21660ce207d2SRui Paulo return (0); 21670ce207d2SRui Paulo } 21680ce207d2SRui Paulo #endif 21690ce207d2SRui Paulo 2170660df75eSGeorge V. Neville-Neil #if defined(__mips__) 2171660df75eSGeorge V. Neville-Neil 2172660df75eSGeorge V. Neville-Neil static struct pmc_event_alias mips24k_aliases[] = { 2173660df75eSGeorge V. Neville-Neil EV_ALIAS("instructions", "INSTR_EXECUTED"), 2174660df75eSGeorge V. Neville-Neil EV_ALIAS("branches", "BRANCH_COMPLETED"), 2175660df75eSGeorge V. Neville-Neil EV_ALIAS("branch-mispredicts", "BRANCH_MISPRED"), 2176660df75eSGeorge V. Neville-Neil EV_ALIAS(NULL, NULL) 2177660df75eSGeorge V. Neville-Neil }; 2178660df75eSGeorge V. Neville-Neil 2179660df75eSGeorge V. Neville-Neil #define MIPS24K_KW_OS "os" 2180660df75eSGeorge V. Neville-Neil #define MIPS24K_KW_USR "usr" 2181660df75eSGeorge V. Neville-Neil #define MIPS24K_KW_ANYTHREAD "anythread" 2182660df75eSGeorge V. Neville-Neil 2183660df75eSGeorge V. Neville-Neil static int 2184660df75eSGeorge V. Neville-Neil mips24k_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 2185660df75eSGeorge V. Neville-Neil struct pmc_op_pmcallocate *pmc_config __unused) 2186660df75eSGeorge V. Neville-Neil { 2187660df75eSGeorge V. Neville-Neil char *p; 2188660df75eSGeorge V. Neville-Neil 2189660df75eSGeorge V. Neville-Neil (void) pe; 2190660df75eSGeorge V. Neville-Neil 2191660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2192660df75eSGeorge V. Neville-Neil 2193660df75eSGeorge V. Neville-Neil while ((p = strsep(&ctrspec, ",")) != NULL) { 2194660df75eSGeorge V. Neville-Neil if (KWMATCH(p, MIPS24K_KW_OS)) 2195660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2196660df75eSGeorge V. Neville-Neil else if (KWMATCH(p, MIPS24K_KW_USR)) 2197660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= PMC_CAP_USER; 2198660df75eSGeorge V. Neville-Neil else if (KWMATCH(p, MIPS24K_KW_ANYTHREAD)) 2199660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= (PMC_CAP_USER | PMC_CAP_SYSTEM); 2200660df75eSGeorge V. Neville-Neil else 2201660df75eSGeorge V. Neville-Neil return (-1); 2202660df75eSGeorge V. Neville-Neil } 2203660df75eSGeorge V. Neville-Neil 2204660df75eSGeorge V. Neville-Neil return (0); 2205660df75eSGeorge V. Neville-Neil } 2206660df75eSGeorge V. Neville-Neil #endif /* __mips__ */ 2207660df75eSGeorge V. Neville-Neil 2208660df75eSGeorge V. Neville-Neil 2209789140c0SJoseph Koshy /* 2210789140c0SJoseph Koshy * Match an event name `name' with its canonical form. 2211789140c0SJoseph Koshy * 22120cfab8ddSJoseph Koshy * Matches are case insensitive and spaces, periods, underscores and 22130cfab8ddSJoseph Koshy * hyphen characters are considered to match each other. 2214789140c0SJoseph Koshy * 2215789140c0SJoseph Koshy * Returns 1 for a match, 0 otherwise. 2216789140c0SJoseph Koshy */ 2217789140c0SJoseph Koshy 2218789140c0SJoseph Koshy static int 2219789140c0SJoseph Koshy pmc_match_event_name(const char *name, const char *canonicalname) 2220789140c0SJoseph Koshy { 2221789140c0SJoseph Koshy int cc, nc; 2222789140c0SJoseph Koshy const unsigned char *c, *n; 2223789140c0SJoseph Koshy 2224789140c0SJoseph Koshy c = (const unsigned char *) canonicalname; 2225789140c0SJoseph Koshy n = (const unsigned char *) name; 2226789140c0SJoseph Koshy 2227789140c0SJoseph Koshy for (; (nc = *n) && (cc = *c); n++, c++) { 2228789140c0SJoseph Koshy 22290cfab8ddSJoseph Koshy if ((nc == ' ' || nc == '_' || nc == '-' || nc == '.') && 22300cfab8ddSJoseph Koshy (cc == ' ' || cc == '_' || cc == '-' || cc == '.')) 2231789140c0SJoseph Koshy continue; 2232789140c0SJoseph Koshy 22330cfab8ddSJoseph Koshy if (toupper(nc) == toupper(cc)) 2234789140c0SJoseph Koshy continue; 2235789140c0SJoseph Koshy 22360cfab8ddSJoseph Koshy 2237789140c0SJoseph Koshy return (0); 2238789140c0SJoseph Koshy } 2239789140c0SJoseph Koshy 2240789140c0SJoseph Koshy if (*n == '\0' && *c == '\0') 2241789140c0SJoseph Koshy return (1); 2242789140c0SJoseph Koshy 2243789140c0SJoseph Koshy return (0); 2244789140c0SJoseph Koshy } 2245789140c0SJoseph Koshy 2246789140c0SJoseph Koshy /* 2247789140c0SJoseph Koshy * Match an event name against all the event named supported by a 2248789140c0SJoseph Koshy * PMC class. 2249789140c0SJoseph Koshy * 2250789140c0SJoseph Koshy * Returns an event descriptor pointer on match or NULL otherwise. 2251789140c0SJoseph Koshy */ 2252789140c0SJoseph Koshy static const struct pmc_event_descr * 2253789140c0SJoseph Koshy pmc_match_event_class(const char *name, 2254789140c0SJoseph Koshy const struct pmc_class_descr *pcd) 2255789140c0SJoseph Koshy { 2256789140c0SJoseph Koshy size_t n; 2257789140c0SJoseph Koshy const struct pmc_event_descr *ev; 2258789140c0SJoseph Koshy 2259789140c0SJoseph Koshy ev = pcd->pm_evc_event_table; 2260789140c0SJoseph Koshy for (n = 0; n < pcd->pm_evc_event_table_size; n++, ev++) 2261789140c0SJoseph Koshy if (pmc_match_event_name(name, ev->pm_ev_name)) 2262789140c0SJoseph Koshy return (ev); 2263789140c0SJoseph Koshy 2264789140c0SJoseph Koshy return (NULL); 2265789140c0SJoseph Koshy } 2266789140c0SJoseph Koshy 2267789140c0SJoseph Koshy static int 2268789140c0SJoseph Koshy pmc_mdep_is_compatible_class(enum pmc_class pc) 2269789140c0SJoseph Koshy { 2270789140c0SJoseph Koshy size_t n; 2271789140c0SJoseph Koshy 2272789140c0SJoseph Koshy for (n = 0; n < pmc_mdep_class_list_size; n++) 2273789140c0SJoseph Koshy if (pmc_mdep_class_list[n] == pc) 2274789140c0SJoseph Koshy return (1); 2275789140c0SJoseph Koshy return (0); 2276789140c0SJoseph Koshy } 2277789140c0SJoseph Koshy 2278ebccf1e3SJoseph Koshy /* 2279ebccf1e3SJoseph Koshy * API entry points 2280ebccf1e3SJoseph Koshy */ 2281ebccf1e3SJoseph Koshy 2282ebccf1e3SJoseph Koshy int 2283ebccf1e3SJoseph Koshy pmc_allocate(const char *ctrspec, enum pmc_mode mode, 2284ebccf1e3SJoseph Koshy uint32_t flags, int cpu, pmc_id_t *pmcid) 2285ebccf1e3SJoseph Koshy { 2286789140c0SJoseph Koshy size_t n; 2287ebccf1e3SJoseph Koshy int retval; 2288ebccf1e3SJoseph Koshy char *r, *spec_copy; 2289ebccf1e3SJoseph Koshy const char *ctrname; 2290789140c0SJoseph Koshy const struct pmc_event_descr *ev; 2291789140c0SJoseph Koshy const struct pmc_event_alias *alias; 2292ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate pmc_config; 2293789140c0SJoseph Koshy const struct pmc_class_descr *pcd; 2294ebccf1e3SJoseph Koshy 2295ebccf1e3SJoseph Koshy spec_copy = NULL; 2296ebccf1e3SJoseph Koshy retval = -1; 2297ebccf1e3SJoseph Koshy 2298ebccf1e3SJoseph Koshy if (mode != PMC_MODE_SS && mode != PMC_MODE_TS && 2299ebccf1e3SJoseph Koshy mode != PMC_MODE_SC && mode != PMC_MODE_TC) { 2300ebccf1e3SJoseph Koshy errno = EINVAL; 2301ebccf1e3SJoseph Koshy goto out; 2302ebccf1e3SJoseph Koshy } 2303ebccf1e3SJoseph Koshy 2304ebccf1e3SJoseph Koshy /* replace an event alias with the canonical event specifier */ 2305ebccf1e3SJoseph Koshy if (pmc_mdep_event_aliases) 2306789140c0SJoseph Koshy for (alias = pmc_mdep_event_aliases; alias->pm_alias; alias++) 2307789140c0SJoseph Koshy if (!strcasecmp(ctrspec, alias->pm_alias)) { 2308789140c0SJoseph Koshy spec_copy = strdup(alias->pm_spec); 2309ebccf1e3SJoseph Koshy break; 2310ebccf1e3SJoseph Koshy } 2311ebccf1e3SJoseph Koshy 2312ebccf1e3SJoseph Koshy if (spec_copy == NULL) 2313ebccf1e3SJoseph Koshy spec_copy = strdup(ctrspec); 2314ebccf1e3SJoseph Koshy 2315ebccf1e3SJoseph Koshy r = spec_copy; 2316ebccf1e3SJoseph Koshy ctrname = strsep(&r, ","); 2317ebccf1e3SJoseph Koshy 2318789140c0SJoseph Koshy /* 2319789140c0SJoseph Koshy * If a explicit class prefix was given by the user, restrict the 2320789140c0SJoseph Koshy * search for the event to the specified PMC class. 2321789140c0SJoseph Koshy */ 2322789140c0SJoseph Koshy ev = NULL; 23230cfab8ddSJoseph Koshy for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) { 23240cfab8ddSJoseph Koshy pcd = pmc_class_table[n]; 2325789140c0SJoseph Koshy if (pmc_mdep_is_compatible_class(pcd->pm_evc_class) && 2326789140c0SJoseph Koshy strncasecmp(ctrname, pcd->pm_evc_name, 2327789140c0SJoseph Koshy pcd->pm_evc_name_size) == 0) { 2328789140c0SJoseph Koshy if ((ev = pmc_match_event_class(ctrname + 2329789140c0SJoseph Koshy pcd->pm_evc_name_size, pcd)) == NULL) { 2330789140c0SJoseph Koshy errno = EINVAL; 2331789140c0SJoseph Koshy goto out; 2332789140c0SJoseph Koshy } 2333ebccf1e3SJoseph Koshy break; 2334789140c0SJoseph Koshy } 2335789140c0SJoseph Koshy } 2336ebccf1e3SJoseph Koshy 2337789140c0SJoseph Koshy /* 2338789140c0SJoseph Koshy * Otherwise, search for this event in all compatible PMC 2339789140c0SJoseph Koshy * classes. 2340789140c0SJoseph Koshy */ 23410cfab8ddSJoseph Koshy for (n = 0; ev == NULL && n < PMC_CLASS_TABLE_SIZE; n++) { 23420cfab8ddSJoseph Koshy pcd = pmc_class_table[n]; 2343789140c0SJoseph Koshy if (pmc_mdep_is_compatible_class(pcd->pm_evc_class)) 2344789140c0SJoseph Koshy ev = pmc_match_event_class(ctrname, pcd); 2345789140c0SJoseph Koshy } 2346789140c0SJoseph Koshy 2347789140c0SJoseph Koshy if (ev == NULL) { 2348ebccf1e3SJoseph Koshy errno = EINVAL; 2349ebccf1e3SJoseph Koshy goto out; 2350ebccf1e3SJoseph Koshy } 2351ebccf1e3SJoseph Koshy 2352ebccf1e3SJoseph Koshy bzero(&pmc_config, sizeof(pmc_config)); 2353789140c0SJoseph Koshy pmc_config.pm_ev = ev->pm_ev_code; 2354789140c0SJoseph Koshy pmc_config.pm_class = pcd->pm_evc_class; 2355ebccf1e3SJoseph Koshy pmc_config.pm_cpu = cpu; 2356ebccf1e3SJoseph Koshy pmc_config.pm_mode = mode; 2357ebccf1e3SJoseph Koshy pmc_config.pm_flags = flags; 2358ebccf1e3SJoseph Koshy 2359ebccf1e3SJoseph Koshy if (PMC_IS_SAMPLING_MODE(mode)) 2360ebccf1e3SJoseph Koshy pmc_config.pm_caps |= PMC_CAP_INTERRUPT; 2361ebccf1e3SJoseph Koshy 2362789140c0SJoseph Koshy if (pcd->pm_evc_allocate_pmc(ev->pm_ev_code, r, &pmc_config) < 0) { 2363ebccf1e3SJoseph Koshy errno = EINVAL; 2364ebccf1e3SJoseph Koshy goto out; 2365ebccf1e3SJoseph Koshy } 2366ebccf1e3SJoseph Koshy 2367ebccf1e3SJoseph Koshy if (PMC_CALL(PMCALLOCATE, &pmc_config) < 0) 2368ebccf1e3SJoseph Koshy goto out; 2369ebccf1e3SJoseph Koshy 2370ebccf1e3SJoseph Koshy *pmcid = pmc_config.pm_pmcid; 2371ebccf1e3SJoseph Koshy 2372ebccf1e3SJoseph Koshy retval = 0; 2373ebccf1e3SJoseph Koshy 2374ebccf1e3SJoseph Koshy out: 2375ebccf1e3SJoseph Koshy if (spec_copy) 2376ebccf1e3SJoseph Koshy free(spec_copy); 2377ebccf1e3SJoseph Koshy 2378aa342b1fSJoseph Koshy return (retval); 2379ebccf1e3SJoseph Koshy } 2380ebccf1e3SJoseph Koshy 2381ebccf1e3SJoseph Koshy int 2382ebccf1e3SJoseph Koshy pmc_attach(pmc_id_t pmc, pid_t pid) 2383ebccf1e3SJoseph Koshy { 2384ebccf1e3SJoseph Koshy struct pmc_op_pmcattach pmc_attach_args; 2385ebccf1e3SJoseph Koshy 2386ebccf1e3SJoseph Koshy pmc_attach_args.pm_pmc = pmc; 2387ebccf1e3SJoseph Koshy pmc_attach_args.pm_pid = pid; 2388ebccf1e3SJoseph Koshy 2389aa342b1fSJoseph Koshy return (PMC_CALL(PMCATTACH, &pmc_attach_args)); 2390ebccf1e3SJoseph Koshy } 2391ebccf1e3SJoseph Koshy 2392ebccf1e3SJoseph Koshy int 2393c5153e19SJoseph Koshy pmc_capabilities(pmc_id_t pmcid, uint32_t *caps) 2394c5153e19SJoseph Koshy { 2395c5153e19SJoseph Koshy unsigned int i; 2396c5153e19SJoseph Koshy enum pmc_class cl; 2397c5153e19SJoseph Koshy 2398c5153e19SJoseph Koshy cl = PMC_ID_TO_CLASS(pmcid); 2399c5153e19SJoseph Koshy for (i = 0; i < cpu_info.pm_nclass; i++) 2400c5153e19SJoseph Koshy if (cpu_info.pm_classes[i].pm_class == cl) { 2401c5153e19SJoseph Koshy *caps = cpu_info.pm_classes[i].pm_caps; 2402aa342b1fSJoseph Koshy return (0); 2403c5153e19SJoseph Koshy } 2404484202faSJoseph Koshy errno = EINVAL; 2405484202faSJoseph Koshy return (-1); 2406c5153e19SJoseph Koshy } 2407c5153e19SJoseph Koshy 2408f263522aSJoseph Koshy int 2409f263522aSJoseph Koshy pmc_configure_logfile(int fd) 2410ebccf1e3SJoseph Koshy { 2411f263522aSJoseph Koshy struct pmc_op_configurelog cla; 2412f263522aSJoseph Koshy 2413f263522aSJoseph Koshy cla.pm_logfd = fd; 2414f263522aSJoseph Koshy if (PMC_CALL(CONFIGURELOG, &cla) < 0) 2415aa342b1fSJoseph Koshy return (-1); 2416aa342b1fSJoseph Koshy return (0); 2417ebccf1e3SJoseph Koshy } 2418ebccf1e3SJoseph Koshy 2419f263522aSJoseph Koshy int 2420f263522aSJoseph Koshy pmc_cpuinfo(const struct pmc_cpuinfo **pci) 2421ebccf1e3SJoseph Koshy { 2422f263522aSJoseph Koshy if (pmc_syscall == -1) { 2423f263522aSJoseph Koshy errno = ENXIO; 2424aa342b1fSJoseph Koshy return (-1); 2425ebccf1e3SJoseph Koshy } 2426ebccf1e3SJoseph Koshy 24271455fcd3SJoseph Koshy *pci = &cpu_info; 2428aa342b1fSJoseph Koshy return (0); 2429ebccf1e3SJoseph Koshy } 2430ebccf1e3SJoseph Koshy 2431f263522aSJoseph Koshy int 2432f263522aSJoseph Koshy pmc_detach(pmc_id_t pmc, pid_t pid) 2433ebccf1e3SJoseph Koshy { 2434f263522aSJoseph Koshy struct pmc_op_pmcattach pmc_detach_args; 2435ebccf1e3SJoseph Koshy 2436f263522aSJoseph Koshy pmc_detach_args.pm_pmc = pmc; 2437f263522aSJoseph Koshy pmc_detach_args.pm_pid = pid; 2438aa342b1fSJoseph Koshy return (PMC_CALL(PMCDETACH, &pmc_detach_args)); 2439ebccf1e3SJoseph Koshy } 2440ebccf1e3SJoseph Koshy 2441f263522aSJoseph Koshy int 2442f263522aSJoseph Koshy pmc_disable(int cpu, int pmc) 2443ebccf1e3SJoseph Koshy { 2444f263522aSJoseph Koshy struct pmc_op_pmcadmin ssa; 2445ebccf1e3SJoseph Koshy 2446f263522aSJoseph Koshy ssa.pm_cpu = cpu; 2447f263522aSJoseph Koshy ssa.pm_pmc = pmc; 2448f263522aSJoseph Koshy ssa.pm_state = PMC_STATE_DISABLED; 2449aa342b1fSJoseph Koshy return (PMC_CALL(PMCADMIN, &ssa)); 2450ebccf1e3SJoseph Koshy } 2451ebccf1e3SJoseph Koshy 2452f263522aSJoseph Koshy int 2453f263522aSJoseph Koshy pmc_enable(int cpu, int pmc) 2454ebccf1e3SJoseph Koshy { 2455f263522aSJoseph Koshy struct pmc_op_pmcadmin ssa; 2456ebccf1e3SJoseph Koshy 2457f263522aSJoseph Koshy ssa.pm_cpu = cpu; 2458f263522aSJoseph Koshy ssa.pm_pmc = pmc; 2459f263522aSJoseph Koshy ssa.pm_state = PMC_STATE_FREE; 2460aa342b1fSJoseph Koshy return (PMC_CALL(PMCADMIN, &ssa)); 2461ebccf1e3SJoseph Koshy } 2462ebccf1e3SJoseph Koshy 2463ebccf1e3SJoseph Koshy /* 2464ebccf1e3SJoseph Koshy * Return a list of events known to a given PMC class. 'cl' is the 2465ebccf1e3SJoseph Koshy * PMC class identifier, 'eventnames' is the returned list of 'const 2466ebccf1e3SJoseph Koshy * char *' pointers pointing to the names of the events. 'nevents' is 2467ebccf1e3SJoseph Koshy * the number of event name pointers returned. 2468ebccf1e3SJoseph Koshy * 2469ebccf1e3SJoseph Koshy * The space for 'eventnames' is allocated using malloc(3). The caller 2470ebccf1e3SJoseph Koshy * is responsible for freeing this space when done. 2471ebccf1e3SJoseph Koshy */ 2472ebccf1e3SJoseph Koshy int 2473ebccf1e3SJoseph Koshy pmc_event_names_of_class(enum pmc_class cl, const char ***eventnames, 2474ebccf1e3SJoseph Koshy int *nevents) 2475ebccf1e3SJoseph Koshy { 2476ebccf1e3SJoseph Koshy int count; 2477ebccf1e3SJoseph Koshy const char **names; 2478ebccf1e3SJoseph Koshy const struct pmc_event_descr *ev; 2479ebccf1e3SJoseph Koshy 2480ebccf1e3SJoseph Koshy switch (cl) 2481ebccf1e3SJoseph Koshy { 24820cfab8ddSJoseph Koshy case PMC_CLASS_IAF: 24830cfab8ddSJoseph Koshy ev = iaf_event_table; 24840cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(iaf); 24850cfab8ddSJoseph Koshy break; 24860cfab8ddSJoseph Koshy case PMC_CLASS_IAP: 24870cfab8ddSJoseph Koshy /* 24880cfab8ddSJoseph Koshy * Return the most appropriate set of event name 24890cfab8ddSJoseph Koshy * spellings for the current CPU. 24900cfab8ddSJoseph Koshy */ 24910cfab8ddSJoseph Koshy switch (cpu_info.pm_cputype) { 24920cfab8ddSJoseph Koshy default: 24930cfab8ddSJoseph Koshy case PMC_CPU_INTEL_ATOM: 24940cfab8ddSJoseph Koshy ev = atom_event_table; 24950cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(atom); 24960cfab8ddSJoseph Koshy break; 24970cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE: 24980cfab8ddSJoseph Koshy ev = core_event_table; 24990cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(core); 25000cfab8ddSJoseph Koshy break; 25010cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE2: 2502b4d091f3SJoseph Koshy case PMC_CPU_INTEL_CORE2EXTREME: 25030cfab8ddSJoseph Koshy ev = core2_event_table; 25040cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(core2); 25050cfab8ddSJoseph Koshy break; 2506597979c4SJeff Roberson case PMC_CPU_INTEL_COREI7: 2507597979c4SJeff Roberson ev = corei7_event_table; 2508597979c4SJeff Roberson count = PMC_EVENT_TABLE_SIZE(corei7); 2509597979c4SJeff Roberson break; 25101fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 25111fa7f10bSFabien Thomas ev = westmere_event_table; 25121fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(westmere); 25131fa7f10bSFabien Thomas break; 25141fa7f10bSFabien Thomas } 25151fa7f10bSFabien Thomas break; 25161fa7f10bSFabien Thomas case PMC_CLASS_UCF: 25171fa7f10bSFabien Thomas ev = ucf_event_table; 25181fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(ucf); 25191fa7f10bSFabien Thomas break; 25201fa7f10bSFabien Thomas case PMC_CLASS_UCP: 25211fa7f10bSFabien Thomas /* 25221fa7f10bSFabien Thomas * Return the most appropriate set of event name 25231fa7f10bSFabien Thomas * spellings for the current CPU. 25241fa7f10bSFabien Thomas */ 25251fa7f10bSFabien Thomas switch (cpu_info.pm_cputype) { 25261fa7f10bSFabien Thomas default: 25271fa7f10bSFabien Thomas case PMC_CPU_INTEL_COREI7: 25281fa7f10bSFabien Thomas ev = corei7uc_event_table; 25291fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(corei7uc); 25301fa7f10bSFabien Thomas break; 25311fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 25321fa7f10bSFabien Thomas ev = westmereuc_event_table; 25331fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(westmereuc); 25341fa7f10bSFabien Thomas break; 25350cfab8ddSJoseph Koshy } 25360cfab8ddSJoseph Koshy break; 2537ebccf1e3SJoseph Koshy case PMC_CLASS_TSC: 2538789140c0SJoseph Koshy ev = tsc_event_table; 2539789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(tsc); 2540ebccf1e3SJoseph Koshy break; 2541ebccf1e3SJoseph Koshy case PMC_CLASS_K7: 2542789140c0SJoseph Koshy ev = k7_event_table; 2543789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(k7); 2544ebccf1e3SJoseph Koshy break; 2545ebccf1e3SJoseph Koshy case PMC_CLASS_K8: 2546789140c0SJoseph Koshy ev = k8_event_table; 2547789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(k8); 2548ebccf1e3SJoseph Koshy break; 2549ebccf1e3SJoseph Koshy case PMC_CLASS_P4: 2550789140c0SJoseph Koshy ev = p4_event_table; 2551789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p4); 2552789140c0SJoseph Koshy break; 2553789140c0SJoseph Koshy case PMC_CLASS_P5: 2554789140c0SJoseph Koshy ev = p5_event_table; 2555789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p5); 2556789140c0SJoseph Koshy break; 2557789140c0SJoseph Koshy case PMC_CLASS_P6: 2558789140c0SJoseph Koshy ev = p6_event_table; 2559789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p6); 2560ebccf1e3SJoseph Koshy break; 25610ce207d2SRui Paulo case PMC_CLASS_XSCALE: 25620ce207d2SRui Paulo ev = xscale_event_table; 25630ce207d2SRui Paulo count = PMC_EVENT_TABLE_SIZE(xscale); 25640ce207d2SRui Paulo break; 2565660df75eSGeorge V. Neville-Neil case PMC_CLASS_MIPS24K: 2566660df75eSGeorge V. Neville-Neil ev = mips24k_event_table; 2567660df75eSGeorge V. Neville-Neil count = PMC_EVENT_TABLE_SIZE(mips24k); 2568660df75eSGeorge V. Neville-Neil break; 2569ebccf1e3SJoseph Koshy default: 2570ebccf1e3SJoseph Koshy errno = EINVAL; 2571aa342b1fSJoseph Koshy return (-1); 2572ebccf1e3SJoseph Koshy } 2573ebccf1e3SJoseph Koshy 2574ebccf1e3SJoseph Koshy if ((names = malloc(count * sizeof(const char *))) == NULL) 2575aa342b1fSJoseph Koshy return (-1); 2576ebccf1e3SJoseph Koshy 2577ebccf1e3SJoseph Koshy *eventnames = names; 2578ebccf1e3SJoseph Koshy *nevents = count; 2579ebccf1e3SJoseph Koshy 2580ebccf1e3SJoseph Koshy for (;count--; ev++, names++) 2581ebccf1e3SJoseph Koshy *names = ev->pm_ev_name; 2582aa342b1fSJoseph Koshy return (0); 2583ebccf1e3SJoseph Koshy } 2584ebccf1e3SJoseph Koshy 2585f263522aSJoseph Koshy int 2586f263522aSJoseph Koshy pmc_flush_logfile(void) 2587f263522aSJoseph Koshy { 2588aa342b1fSJoseph Koshy return (PMC_CALL(FLUSHLOG,0)); 2589f263522aSJoseph Koshy } 2590ebccf1e3SJoseph Koshy 2591ebccf1e3SJoseph Koshy int 2592f263522aSJoseph Koshy pmc_get_driver_stats(struct pmc_driverstats *ds) 2593ebccf1e3SJoseph Koshy { 2594f263522aSJoseph Koshy struct pmc_op_getdriverstats gms; 2595f263522aSJoseph Koshy 2596f263522aSJoseph Koshy if (PMC_CALL(GETDRIVERSTATS, &gms) < 0) 2597aa342b1fSJoseph Koshy return (-1); 2598f263522aSJoseph Koshy 2599f263522aSJoseph Koshy /* copy out fields in the current userland<->library interface */ 2600f263522aSJoseph Koshy ds->pm_intr_ignored = gms.pm_intr_ignored; 2601f263522aSJoseph Koshy ds->pm_intr_processed = gms.pm_intr_processed; 2602f263522aSJoseph Koshy ds->pm_intr_bufferfull = gms.pm_intr_bufferfull; 2603f263522aSJoseph Koshy ds->pm_syscalls = gms.pm_syscalls; 2604f263522aSJoseph Koshy ds->pm_syscall_errors = gms.pm_syscall_errors; 2605f263522aSJoseph Koshy ds->pm_buffer_requests = gms.pm_buffer_requests; 2606f263522aSJoseph Koshy ds->pm_buffer_requests_failed = gms.pm_buffer_requests_failed; 2607f263522aSJoseph Koshy ds->pm_log_sweeps = gms.pm_log_sweeps; 2608aa342b1fSJoseph Koshy return (0); 2609f263522aSJoseph Koshy } 2610f263522aSJoseph Koshy 2611f263522aSJoseph Koshy int 2612f263522aSJoseph Koshy pmc_get_msr(pmc_id_t pmc, uint32_t *msr) 2613f263522aSJoseph Koshy { 2614f263522aSJoseph Koshy struct pmc_op_getmsr gm; 2615ebccf1e3SJoseph Koshy 2616ebccf1e3SJoseph Koshy gm.pm_pmcid = pmc; 2617f263522aSJoseph Koshy if (PMC_CALL(PMCGETMSR, &gm) < 0) 2618aa342b1fSJoseph Koshy return (-1); 2619ebccf1e3SJoseph Koshy *msr = gm.pm_msr; 2620aa342b1fSJoseph Koshy return (0); 2621ebccf1e3SJoseph Koshy } 2622ebccf1e3SJoseph Koshy 2623f263522aSJoseph Koshy int 2624f263522aSJoseph Koshy pmc_init(void) 2625f263522aSJoseph Koshy { 2626f263522aSJoseph Koshy int error, pmc_mod_id; 26271455fcd3SJoseph Koshy unsigned int n; 2628f263522aSJoseph Koshy uint32_t abi_version; 2629f263522aSJoseph Koshy struct module_stat pmc_modstat; 26301455fcd3SJoseph Koshy struct pmc_op_getcpuinfo op_cpu_info; 2631791f5d5bSJoseph Koshy #if defined(__amd64__) || defined(__i386__) 2632791f5d5bSJoseph Koshy int cpu_has_iaf_counters; 2633791f5d5bSJoseph Koshy unsigned int t; 2634791f5d5bSJoseph Koshy #endif 2635f263522aSJoseph Koshy 2636f263522aSJoseph Koshy if (pmc_syscall != -1) /* already inited */ 2637aa342b1fSJoseph Koshy return (0); 2638f263522aSJoseph Koshy 2639f263522aSJoseph Koshy /* retrieve the system call number from the KLD */ 2640f263522aSJoseph Koshy if ((pmc_mod_id = modfind(PMC_MODULE_NAME)) < 0) 2641aa342b1fSJoseph Koshy return (-1); 2642f263522aSJoseph Koshy 2643f263522aSJoseph Koshy pmc_modstat.version = sizeof(struct module_stat); 2644f263522aSJoseph Koshy if ((error = modstat(pmc_mod_id, &pmc_modstat)) < 0) 2645aa342b1fSJoseph Koshy return (-1); 2646f263522aSJoseph Koshy 2647f263522aSJoseph Koshy pmc_syscall = pmc_modstat.data.intval; 2648f263522aSJoseph Koshy 2649f263522aSJoseph Koshy /* check the kernel module's ABI against our compiled-in version */ 2650f263522aSJoseph Koshy abi_version = PMC_VERSION; 2651f263522aSJoseph Koshy if (PMC_CALL(GETMODULEVERSION, &abi_version) < 0) 2652f263522aSJoseph Koshy return (pmc_syscall = -1); 2653f263522aSJoseph Koshy 2654f263522aSJoseph Koshy /* ignore patch & minor numbers for the comparision */ 2655f263522aSJoseph Koshy if ((abi_version & 0xFF000000) != (PMC_VERSION & 0xFF000000)) { 2656f263522aSJoseph Koshy errno = EPROGMISMATCH; 2657f263522aSJoseph Koshy return (pmc_syscall = -1); 2658f263522aSJoseph Koshy } 2659f263522aSJoseph Koshy 26601455fcd3SJoseph Koshy if (PMC_CALL(GETCPUINFO, &op_cpu_info) < 0) 2661f263522aSJoseph Koshy return (pmc_syscall = -1); 2662f263522aSJoseph Koshy 26631455fcd3SJoseph Koshy cpu_info.pm_cputype = op_cpu_info.pm_cputype; 26641455fcd3SJoseph Koshy cpu_info.pm_ncpu = op_cpu_info.pm_ncpu; 26651455fcd3SJoseph Koshy cpu_info.pm_npmc = op_cpu_info.pm_npmc; 26661455fcd3SJoseph Koshy cpu_info.pm_nclass = op_cpu_info.pm_nclass; 26671455fcd3SJoseph Koshy for (n = 0; n < cpu_info.pm_nclass; n++) 26681455fcd3SJoseph Koshy cpu_info.pm_classes[n] = op_cpu_info.pm_classes[n]; 26691455fcd3SJoseph Koshy 26700cfab8ddSJoseph Koshy pmc_class_table = malloc(PMC_CLASS_TABLE_SIZE * 26710cfab8ddSJoseph Koshy sizeof(struct pmc_class_descr *)); 26720cfab8ddSJoseph Koshy 26730cfab8ddSJoseph Koshy if (pmc_class_table == NULL) 26740cfab8ddSJoseph Koshy return (-1); 26750cfab8ddSJoseph Koshy 2676791f5d5bSJoseph Koshy for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) 2677791f5d5bSJoseph Koshy pmc_class_table[n] = NULL; 26780cfab8ddSJoseph Koshy 26790cfab8ddSJoseph Koshy /* 26800cfab8ddSJoseph Koshy * Fill in the class table. 26810cfab8ddSJoseph Koshy */ 26820cfab8ddSJoseph Koshy n = 0; 26830cfab8ddSJoseph Koshy #if defined(__amd64__) || defined(__i386__) 26840cfab8ddSJoseph Koshy pmc_class_table[n++] = &tsc_class_table_descr; 2685791f5d5bSJoseph Koshy 2686791f5d5bSJoseph Koshy /* 2687791f5d5bSJoseph Koshy * Check if this CPU has fixed function counters. 2688791f5d5bSJoseph Koshy */ 2689791f5d5bSJoseph Koshy cpu_has_iaf_counters = 0; 2690791f5d5bSJoseph Koshy for (t = 0; t < cpu_info.pm_nclass; t++) 2691791f5d5bSJoseph Koshy if (cpu_info.pm_classes[t].pm_class == PMC_CLASS_IAF) 2692791f5d5bSJoseph Koshy cpu_has_iaf_counters = 1; 26930cfab8ddSJoseph Koshy #endif 26940cfab8ddSJoseph Koshy 2695789140c0SJoseph Koshy #define PMC_MDEP_INIT(C) do { \ 2696789140c0SJoseph Koshy pmc_mdep_event_aliases = C##_aliases; \ 2697789140c0SJoseph Koshy pmc_mdep_class_list = C##_pmc_classes; \ 2698789140c0SJoseph Koshy pmc_mdep_class_list_size = \ 2699789140c0SJoseph Koshy PMC_TABLE_SIZE(C##_pmc_classes); \ 2700789140c0SJoseph Koshy } while (0) 2701789140c0SJoseph Koshy 2702791f5d5bSJoseph Koshy #define PMC_MDEP_INIT_INTEL_V2(C) do { \ 2703791f5d5bSJoseph Koshy PMC_MDEP_INIT(C); \ 2704791f5d5bSJoseph Koshy if (cpu_has_iaf_counters) \ 2705791f5d5bSJoseph Koshy pmc_class_table[n++] = &iaf_class_table_descr; \ 2706791f5d5bSJoseph Koshy else \ 2707791f5d5bSJoseph Koshy pmc_mdep_event_aliases = \ 2708791f5d5bSJoseph Koshy C##_aliases_without_iaf; \ 2709791f5d5bSJoseph Koshy pmc_class_table[n] = &C##_class_table_descr; \ 2710791f5d5bSJoseph Koshy } while (0) 2711791f5d5bSJoseph Koshy 2712789140c0SJoseph Koshy /* Configure the event name parser. */ 2713f263522aSJoseph Koshy switch (cpu_info.pm_cputype) { 2714f263522aSJoseph Koshy #if defined(__i386__) 2715f263522aSJoseph Koshy case PMC_CPU_AMD_K7: 2716789140c0SJoseph Koshy PMC_MDEP_INIT(k7); 27170cfab8ddSJoseph Koshy pmc_class_table[n] = &k7_class_table_descr; 2718f263522aSJoseph Koshy break; 2719f263522aSJoseph Koshy case PMC_CPU_INTEL_P5: 2720789140c0SJoseph Koshy PMC_MDEP_INIT(p5); 27210cfab8ddSJoseph Koshy pmc_class_table[n] = &p5_class_table_descr; 2722f263522aSJoseph Koshy break; 2723f263522aSJoseph Koshy case PMC_CPU_INTEL_P6: /* P6 ... Pentium M CPUs have */ 2724f263522aSJoseph Koshy case PMC_CPU_INTEL_PII: /* similar PMCs. */ 2725f263522aSJoseph Koshy case PMC_CPU_INTEL_PIII: 2726f263522aSJoseph Koshy case PMC_CPU_INTEL_PM: 2727789140c0SJoseph Koshy PMC_MDEP_INIT(p6); 27280cfab8ddSJoseph Koshy pmc_class_table[n] = &p6_class_table_descr; 2729f263522aSJoseph Koshy break; 273086a65549SJoseph Koshy #endif 273186a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 2732f263522aSJoseph Koshy case PMC_CPU_AMD_K8: 2733789140c0SJoseph Koshy PMC_MDEP_INIT(k8); 27340cfab8ddSJoseph Koshy pmc_class_table[n] = &k8_class_table_descr; 27350cfab8ddSJoseph Koshy break; 27360cfab8ddSJoseph Koshy case PMC_CPU_INTEL_ATOM: 2737791f5d5bSJoseph Koshy PMC_MDEP_INIT_INTEL_V2(atom); 27380cfab8ddSJoseph Koshy break; 27390cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE: 27400cfab8ddSJoseph Koshy PMC_MDEP_INIT(core); 2741bc315bbdSJoseph Koshy pmc_class_table[n] = &core_class_table_descr; 27420cfab8ddSJoseph Koshy break; 27430cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE2: 2744b4d091f3SJoseph Koshy case PMC_CPU_INTEL_CORE2EXTREME: 2745791f5d5bSJoseph Koshy PMC_MDEP_INIT_INTEL_V2(core2); 2746789140c0SJoseph Koshy break; 2747597979c4SJeff Roberson case PMC_CPU_INTEL_COREI7: 27481fa7f10bSFabien Thomas pmc_class_table[n++] = &ucf_class_table_descr; 27491fa7f10bSFabien Thomas pmc_class_table[n++] = &corei7uc_class_table_descr; 2750791f5d5bSJoseph Koshy PMC_MDEP_INIT_INTEL_V2(corei7); 2751597979c4SJeff Roberson break; 27521fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 27531fa7f10bSFabien Thomas pmc_class_table[n++] = &ucf_class_table_descr; 27541fa7f10bSFabien Thomas pmc_class_table[n++] = &westmereuc_class_table_descr; 27551fa7f10bSFabien Thomas PMC_MDEP_INIT_INTEL_V2(westmere); 27561fa7f10bSFabien Thomas break; 2757789140c0SJoseph Koshy case PMC_CPU_INTEL_PIV: 2758789140c0SJoseph Koshy PMC_MDEP_INIT(p4); 27590cfab8ddSJoseph Koshy pmc_class_table[n] = &p4_class_table_descr; 2760f263522aSJoseph Koshy break; 2761ebccf1e3SJoseph Koshy #endif 27620ce207d2SRui Paulo #if defined(__XSCALE__) 27630ce207d2SRui Paulo case PMC_CPU_INTEL_XSCALE: 27640ce207d2SRui Paulo PMC_MDEP_INIT(xscale); 27650ce207d2SRui Paulo pmc_class_table[n] = &xscale_class_table_descr; 27660ce207d2SRui Paulo break; 27670ce207d2SRui Paulo #endif 2768660df75eSGeorge V. Neville-Neil #if defined(__mips__) 2769660df75eSGeorge V. Neville-Neil case PMC_CPU_MIPS_24K: 2770660df75eSGeorge V. Neville-Neil PMC_MDEP_INIT(mips24k); 2771660df75eSGeorge V. Neville-Neil pmc_class_table[n] = &mips24k_class_table_descr; 2772660df75eSGeorge V. Neville-Neil break; 2773660df75eSGeorge V. Neville-Neil #endif /* __mips__ */ 2774f263522aSJoseph Koshy default: 2775f263522aSJoseph Koshy /* 2776f263522aSJoseph Koshy * Some kind of CPU this version of the library knows nothing 2777f263522aSJoseph Koshy * about. This shouldn't happen since the abi version check 2778f263522aSJoseph Koshy * should have caught this. 2779f263522aSJoseph Koshy */ 2780f263522aSJoseph Koshy errno = ENXIO; 2781f263522aSJoseph Koshy return (pmc_syscall = -1); 2782f263522aSJoseph Koshy } 2783f263522aSJoseph Koshy 2784aa342b1fSJoseph Koshy return (0); 2785f263522aSJoseph Koshy } 2786f263522aSJoseph Koshy 2787f263522aSJoseph Koshy const char * 2788f263522aSJoseph Koshy pmc_name_of_capability(enum pmc_caps cap) 2789f263522aSJoseph Koshy { 2790f263522aSJoseph Koshy int i; 2791f263522aSJoseph Koshy 2792f263522aSJoseph Koshy /* 2793f263522aSJoseph Koshy * 'cap' should have a single bit set and should be in 2794f263522aSJoseph Koshy * range. 2795f263522aSJoseph Koshy */ 2796f263522aSJoseph Koshy if ((cap & (cap - 1)) || cap < PMC_CAP_FIRST || 2797f263522aSJoseph Koshy cap > PMC_CAP_LAST) { 2798f263522aSJoseph Koshy errno = EINVAL; 2799aa342b1fSJoseph Koshy return (NULL); 2800f263522aSJoseph Koshy } 2801f263522aSJoseph Koshy 2802f263522aSJoseph Koshy i = ffs(cap); 2803aa342b1fSJoseph Koshy return (pmc_capability_names[i - 1]); 2804f263522aSJoseph Koshy } 2805f263522aSJoseph Koshy 2806f263522aSJoseph Koshy const char * 2807f263522aSJoseph Koshy pmc_name_of_class(enum pmc_class pc) 2808f263522aSJoseph Koshy { 2809f263522aSJoseph Koshy if ((int) pc >= PMC_CLASS_FIRST && 2810f263522aSJoseph Koshy pc <= PMC_CLASS_LAST) 2811aa342b1fSJoseph Koshy return (pmc_class_names[pc]); 2812f263522aSJoseph Koshy 2813f263522aSJoseph Koshy errno = EINVAL; 2814aa342b1fSJoseph Koshy return (NULL); 2815f263522aSJoseph Koshy } 2816f263522aSJoseph Koshy 2817f263522aSJoseph Koshy const char * 2818f263522aSJoseph Koshy pmc_name_of_cputype(enum pmc_cputype cp) 2819f263522aSJoseph Koshy { 2820789140c0SJoseph Koshy size_t n; 2821789140c0SJoseph Koshy 2822789140c0SJoseph Koshy for (n = 0; n < PMC_TABLE_SIZE(pmc_cputype_names); n++) 2823789140c0SJoseph Koshy if (cp == pmc_cputype_names[n].pm_cputype) 2824789140c0SJoseph Koshy return (pmc_cputype_names[n].pm_name); 2825789140c0SJoseph Koshy 2826f263522aSJoseph Koshy errno = EINVAL; 2827aa342b1fSJoseph Koshy return (NULL); 2828f263522aSJoseph Koshy } 2829f263522aSJoseph Koshy 2830f263522aSJoseph Koshy const char * 2831f263522aSJoseph Koshy pmc_name_of_disposition(enum pmc_disp pd) 2832f263522aSJoseph Koshy { 2833f263522aSJoseph Koshy if ((int) pd >= PMC_DISP_FIRST && 2834f263522aSJoseph Koshy pd <= PMC_DISP_LAST) 2835aa342b1fSJoseph Koshy return (pmc_disposition_names[pd]); 2836f263522aSJoseph Koshy 2837f263522aSJoseph Koshy errno = EINVAL; 2838aa342b1fSJoseph Koshy return (NULL); 2839f263522aSJoseph Koshy } 2840f263522aSJoseph Koshy 2841f263522aSJoseph Koshy const char * 28420cfab8ddSJoseph Koshy _pmc_name_of_event(enum pmc_event pe, enum pmc_cputype cpu) 2843f263522aSJoseph Koshy { 2844789140c0SJoseph Koshy const struct pmc_event_descr *ev, *evfence; 2845789140c0SJoseph Koshy 2846789140c0SJoseph Koshy ev = evfence = NULL; 28470cfab8ddSJoseph Koshy if (pe >= PMC_EV_IAF_FIRST && pe <= PMC_EV_IAF_LAST) { 28480cfab8ddSJoseph Koshy ev = iaf_event_table; 28490cfab8ddSJoseph Koshy evfence = iaf_event_table + PMC_EVENT_TABLE_SIZE(iaf); 28500cfab8ddSJoseph Koshy } else if (pe >= PMC_EV_IAP_FIRST && pe <= PMC_EV_IAP_LAST) { 28510cfab8ddSJoseph Koshy switch (cpu) { 28520cfab8ddSJoseph Koshy case PMC_CPU_INTEL_ATOM: 28530cfab8ddSJoseph Koshy ev = atom_event_table; 28540cfab8ddSJoseph Koshy evfence = atom_event_table + PMC_EVENT_TABLE_SIZE(atom); 28550cfab8ddSJoseph Koshy break; 28560cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE: 28570cfab8ddSJoseph Koshy ev = core_event_table; 28580cfab8ddSJoseph Koshy evfence = core_event_table + PMC_EVENT_TABLE_SIZE(core); 28590cfab8ddSJoseph Koshy break; 28600cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE2: 2861b4d091f3SJoseph Koshy case PMC_CPU_INTEL_CORE2EXTREME: 28620cfab8ddSJoseph Koshy ev = core2_event_table; 28630cfab8ddSJoseph Koshy evfence = core2_event_table + PMC_EVENT_TABLE_SIZE(core2); 28640cfab8ddSJoseph Koshy break; 2865597979c4SJeff Roberson case PMC_CPU_INTEL_COREI7: 2866597979c4SJeff Roberson ev = corei7_event_table; 2867597979c4SJeff Roberson evfence = corei7_event_table + PMC_EVENT_TABLE_SIZE(corei7); 2868597979c4SJeff Roberson break; 28691fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 28701fa7f10bSFabien Thomas ev = westmere_event_table; 28711fa7f10bSFabien Thomas evfence = westmere_event_table + PMC_EVENT_TABLE_SIZE(westmere); 28721fa7f10bSFabien Thomas break; 28730cfab8ddSJoseph Koshy default: /* Unknown CPU type. */ 28740cfab8ddSJoseph Koshy break; 28750cfab8ddSJoseph Koshy } 28761fa7f10bSFabien Thomas } else if (pe >= PMC_EV_UCF_FIRST && pe <= PMC_EV_UCF_LAST) { 28771fa7f10bSFabien Thomas ev = ucf_event_table; 28781fa7f10bSFabien Thomas evfence = ucf_event_table + PMC_EVENT_TABLE_SIZE(ucf); 28791fa7f10bSFabien Thomas } else if (pe >= PMC_EV_UCP_FIRST && pe <= PMC_EV_UCP_LAST) { 28801fa7f10bSFabien Thomas switch (cpu) { 28811fa7f10bSFabien Thomas case PMC_CPU_INTEL_COREI7: 28821fa7f10bSFabien Thomas ev = corei7uc_event_table; 28831fa7f10bSFabien Thomas evfence = corei7uc_event_table + PMC_EVENT_TABLE_SIZE(corei7uc); 28841fa7f10bSFabien Thomas break; 28851fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 28861fa7f10bSFabien Thomas ev = westmereuc_event_table; 28871fa7f10bSFabien Thomas evfence = westmereuc_event_table + PMC_EVENT_TABLE_SIZE(westmereuc); 28881fa7f10bSFabien Thomas break; 28891fa7f10bSFabien Thomas default: /* Unknown CPU type. */ 28901fa7f10bSFabien Thomas break; 28911fa7f10bSFabien Thomas } 28921fa7f10bSFabien Thomas } else if (pe >= PMC_EV_K7_FIRST && pe <= PMC_EV_K7_LAST) { 2893789140c0SJoseph Koshy ev = k7_event_table; 2894789140c0SJoseph Koshy evfence = k7_event_table + PMC_EVENT_TABLE_SIZE(k7); 2895789140c0SJoseph Koshy } else if (pe >= PMC_EV_K8_FIRST && pe <= PMC_EV_K8_LAST) { 2896789140c0SJoseph Koshy ev = k8_event_table; 2897789140c0SJoseph Koshy evfence = k8_event_table + PMC_EVENT_TABLE_SIZE(k8); 2898789140c0SJoseph Koshy } else if (pe >= PMC_EV_P4_FIRST && pe <= PMC_EV_P4_LAST) { 2899789140c0SJoseph Koshy ev = p4_event_table; 2900789140c0SJoseph Koshy evfence = p4_event_table + PMC_EVENT_TABLE_SIZE(p4); 2901789140c0SJoseph Koshy } else if (pe >= PMC_EV_P5_FIRST && pe <= PMC_EV_P5_LAST) { 2902789140c0SJoseph Koshy ev = p5_event_table; 2903789140c0SJoseph Koshy evfence = p5_event_table + PMC_EVENT_TABLE_SIZE(p5); 2904789140c0SJoseph Koshy } else if (pe >= PMC_EV_P6_FIRST && pe <= PMC_EV_P6_LAST) { 2905789140c0SJoseph Koshy ev = p6_event_table; 2906789140c0SJoseph Koshy evfence = p6_event_table + PMC_EVENT_TABLE_SIZE(p6); 29070ce207d2SRui Paulo } else if (pe >= PMC_EV_XSCALE_FIRST && pe <= PMC_EV_XSCALE_LAST) { 29080ce207d2SRui Paulo ev = xscale_event_table; 29090ce207d2SRui Paulo evfence = xscale_event_table + PMC_EVENT_TABLE_SIZE(xscale); 2910660df75eSGeorge V. Neville-Neil } else if (pe >= PMC_EV_MIPS24K_FIRST && pe <= PMC_EV_MIPS24K_LAST) { 2911660df75eSGeorge V. Neville-Neil ev = mips24k_event_table; 2912660df75eSGeorge V. Neville-Neil evfence = mips24k_event_table + PMC_EVENT_TABLE_SIZE(mips24k 2913660df75eSGeorge V. Neville-Neil ); 2914789140c0SJoseph Koshy } else if (pe == PMC_EV_TSC_TSC) { 2915789140c0SJoseph Koshy ev = tsc_event_table; 2916789140c0SJoseph Koshy evfence = tsc_event_table + PMC_EVENT_TABLE_SIZE(tsc); 2917789140c0SJoseph Koshy } 2918789140c0SJoseph Koshy 2919789140c0SJoseph Koshy for (; ev != evfence; ev++) 2920789140c0SJoseph Koshy if (pe == ev->pm_ev_code) 2921789140c0SJoseph Koshy return (ev->pm_ev_name); 2922f263522aSJoseph Koshy 29230cfab8ddSJoseph Koshy return (NULL); 29240cfab8ddSJoseph Koshy } 29250cfab8ddSJoseph Koshy 29260cfab8ddSJoseph Koshy const char * 29270cfab8ddSJoseph Koshy pmc_name_of_event(enum pmc_event pe) 29280cfab8ddSJoseph Koshy { 29290cfab8ddSJoseph Koshy const char *n; 29300cfab8ddSJoseph Koshy 29310cfab8ddSJoseph Koshy if ((n = _pmc_name_of_event(pe, cpu_info.pm_cputype)) != NULL) 29320cfab8ddSJoseph Koshy return (n); 29330cfab8ddSJoseph Koshy 2934f263522aSJoseph Koshy errno = EINVAL; 2935aa342b1fSJoseph Koshy return (NULL); 2936f263522aSJoseph Koshy } 2937f263522aSJoseph Koshy 2938f263522aSJoseph Koshy const char * 2939f263522aSJoseph Koshy pmc_name_of_mode(enum pmc_mode pm) 2940f263522aSJoseph Koshy { 2941f263522aSJoseph Koshy if ((int) pm >= PMC_MODE_FIRST && 2942f263522aSJoseph Koshy pm <= PMC_MODE_LAST) 2943aa342b1fSJoseph Koshy return (pmc_mode_names[pm]); 2944f263522aSJoseph Koshy 2945f263522aSJoseph Koshy errno = EINVAL; 2946aa342b1fSJoseph Koshy return (NULL); 2947f263522aSJoseph Koshy } 2948f263522aSJoseph Koshy 2949f263522aSJoseph Koshy const char * 2950f263522aSJoseph Koshy pmc_name_of_state(enum pmc_state ps) 2951f263522aSJoseph Koshy { 2952f263522aSJoseph Koshy if ((int) ps >= PMC_STATE_FIRST && 2953f263522aSJoseph Koshy ps <= PMC_STATE_LAST) 2954aa342b1fSJoseph Koshy return (pmc_state_names[ps]); 2955f263522aSJoseph Koshy 2956f263522aSJoseph Koshy errno = EINVAL; 2957aa342b1fSJoseph Koshy return (NULL); 2958f263522aSJoseph Koshy } 2959f263522aSJoseph Koshy 2960f263522aSJoseph Koshy int 2961f263522aSJoseph Koshy pmc_ncpu(void) 2962f263522aSJoseph Koshy { 2963f263522aSJoseph Koshy if (pmc_syscall == -1) { 2964f263522aSJoseph Koshy errno = ENXIO; 2965aa342b1fSJoseph Koshy return (-1); 2966f263522aSJoseph Koshy } 2967f263522aSJoseph Koshy 2968aa342b1fSJoseph Koshy return (cpu_info.pm_ncpu); 2969f263522aSJoseph Koshy } 2970f263522aSJoseph Koshy 2971f263522aSJoseph Koshy int 2972f263522aSJoseph Koshy pmc_npmc(int cpu) 2973f263522aSJoseph Koshy { 2974f263522aSJoseph Koshy if (pmc_syscall == -1) { 2975f263522aSJoseph Koshy errno = ENXIO; 2976aa342b1fSJoseph Koshy return (-1); 2977f263522aSJoseph Koshy } 2978f263522aSJoseph Koshy 2979f263522aSJoseph Koshy if (cpu < 0 || cpu >= (int) cpu_info.pm_ncpu) { 2980f263522aSJoseph Koshy errno = EINVAL; 2981aa342b1fSJoseph Koshy return (-1); 2982f263522aSJoseph Koshy } 2983f263522aSJoseph Koshy 2984aa342b1fSJoseph Koshy return (cpu_info.pm_npmc); 2985f263522aSJoseph Koshy } 2986f263522aSJoseph Koshy 2987f263522aSJoseph Koshy int 2988f263522aSJoseph Koshy pmc_pmcinfo(int cpu, struct pmc_pmcinfo **ppmci) 2989f263522aSJoseph Koshy { 2990f263522aSJoseph Koshy int nbytes, npmc; 2991f263522aSJoseph Koshy struct pmc_op_getpmcinfo *pmci; 2992f263522aSJoseph Koshy 2993f263522aSJoseph Koshy if ((npmc = pmc_npmc(cpu)) < 0) 2994aa342b1fSJoseph Koshy return (-1); 2995f263522aSJoseph Koshy 2996f263522aSJoseph Koshy nbytes = sizeof(struct pmc_op_getpmcinfo) + 2997f263522aSJoseph Koshy npmc * sizeof(struct pmc_info); 2998f263522aSJoseph Koshy 2999f263522aSJoseph Koshy if ((pmci = calloc(1, nbytes)) == NULL) 3000aa342b1fSJoseph Koshy return (-1); 3001f263522aSJoseph Koshy 3002f263522aSJoseph Koshy pmci->pm_cpu = cpu; 3003f263522aSJoseph Koshy 3004f263522aSJoseph Koshy if (PMC_CALL(GETPMCINFO, pmci) < 0) { 3005f263522aSJoseph Koshy free(pmci); 3006aa342b1fSJoseph Koshy return (-1); 3007f263522aSJoseph Koshy } 3008f263522aSJoseph Koshy 3009f263522aSJoseph Koshy /* kernel<->library, library<->userland interfaces are identical */ 3010f263522aSJoseph Koshy *ppmci = (struct pmc_pmcinfo *) pmci; 3011aa342b1fSJoseph Koshy return (0); 3012f263522aSJoseph Koshy } 3013f263522aSJoseph Koshy 3014f263522aSJoseph Koshy int 3015f263522aSJoseph Koshy pmc_read(pmc_id_t pmc, pmc_value_t *value) 3016f263522aSJoseph Koshy { 3017f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_read_op; 3018f263522aSJoseph Koshy 3019f263522aSJoseph Koshy pmc_read_op.pm_pmcid = pmc; 3020f263522aSJoseph Koshy pmc_read_op.pm_flags = PMC_F_OLDVALUE; 3021f263522aSJoseph Koshy pmc_read_op.pm_value = -1; 3022f263522aSJoseph Koshy 3023f263522aSJoseph Koshy if (PMC_CALL(PMCRW, &pmc_read_op) < 0) 3024aa342b1fSJoseph Koshy return (-1); 3025f263522aSJoseph Koshy 3026f263522aSJoseph Koshy *value = pmc_read_op.pm_value; 3027aa342b1fSJoseph Koshy return (0); 3028f263522aSJoseph Koshy } 3029f263522aSJoseph Koshy 3030f263522aSJoseph Koshy int 3031f263522aSJoseph Koshy pmc_release(pmc_id_t pmc) 3032f263522aSJoseph Koshy { 3033f263522aSJoseph Koshy struct pmc_op_simple pmc_release_args; 3034f263522aSJoseph Koshy 3035f263522aSJoseph Koshy pmc_release_args.pm_pmcid = pmc; 3036aa342b1fSJoseph Koshy return (PMC_CALL(PMCRELEASE, &pmc_release_args)); 3037f263522aSJoseph Koshy } 3038f263522aSJoseph Koshy 3039f263522aSJoseph Koshy int 3040f263522aSJoseph Koshy pmc_rw(pmc_id_t pmc, pmc_value_t newvalue, pmc_value_t *oldvaluep) 3041f263522aSJoseph Koshy { 3042f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_rw_op; 3043f263522aSJoseph Koshy 3044f263522aSJoseph Koshy pmc_rw_op.pm_pmcid = pmc; 3045f263522aSJoseph Koshy pmc_rw_op.pm_flags = PMC_F_NEWVALUE | PMC_F_OLDVALUE; 3046f263522aSJoseph Koshy pmc_rw_op.pm_value = newvalue; 3047f263522aSJoseph Koshy 3048f263522aSJoseph Koshy if (PMC_CALL(PMCRW, &pmc_rw_op) < 0) 3049aa342b1fSJoseph Koshy return (-1); 3050f263522aSJoseph Koshy 3051f263522aSJoseph Koshy *oldvaluep = pmc_rw_op.pm_value; 3052aa342b1fSJoseph Koshy return (0); 3053f263522aSJoseph Koshy } 3054f263522aSJoseph Koshy 3055f263522aSJoseph Koshy int 3056f263522aSJoseph Koshy pmc_set(pmc_id_t pmc, pmc_value_t value) 3057f263522aSJoseph Koshy { 3058f263522aSJoseph Koshy struct pmc_op_pmcsetcount sc; 3059f263522aSJoseph Koshy 3060f263522aSJoseph Koshy sc.pm_pmcid = pmc; 3061f263522aSJoseph Koshy sc.pm_count = value; 3062f263522aSJoseph Koshy 3063f263522aSJoseph Koshy if (PMC_CALL(PMCSETCOUNT, &sc) < 0) 3064aa342b1fSJoseph Koshy return (-1); 3065aa342b1fSJoseph Koshy return (0); 3066f263522aSJoseph Koshy } 3067f263522aSJoseph Koshy 3068f263522aSJoseph Koshy int 3069f263522aSJoseph Koshy pmc_start(pmc_id_t pmc) 3070f263522aSJoseph Koshy { 3071f263522aSJoseph Koshy struct pmc_op_simple pmc_start_args; 3072f263522aSJoseph Koshy 3073f263522aSJoseph Koshy pmc_start_args.pm_pmcid = pmc; 3074aa342b1fSJoseph Koshy return (PMC_CALL(PMCSTART, &pmc_start_args)); 3075f263522aSJoseph Koshy } 3076f263522aSJoseph Koshy 3077f263522aSJoseph Koshy int 3078f263522aSJoseph Koshy pmc_stop(pmc_id_t pmc) 3079f263522aSJoseph Koshy { 3080f263522aSJoseph Koshy struct pmc_op_simple pmc_stop_args; 3081f263522aSJoseph Koshy 3082f263522aSJoseph Koshy pmc_stop_args.pm_pmcid = pmc; 3083aa342b1fSJoseph Koshy return (PMC_CALL(PMCSTOP, &pmc_stop_args)); 3084f263522aSJoseph Koshy } 3085f263522aSJoseph Koshy 3086f263522aSJoseph Koshy int 3087f263522aSJoseph Koshy pmc_width(pmc_id_t pmcid, uint32_t *width) 3088f263522aSJoseph Koshy { 3089f263522aSJoseph Koshy unsigned int i; 3090f263522aSJoseph Koshy enum pmc_class cl; 3091f263522aSJoseph Koshy 3092f263522aSJoseph Koshy cl = PMC_ID_TO_CLASS(pmcid); 3093f263522aSJoseph Koshy for (i = 0; i < cpu_info.pm_nclass; i++) 3094f263522aSJoseph Koshy if (cpu_info.pm_classes[i].pm_class == cl) { 3095f263522aSJoseph Koshy *width = cpu_info.pm_classes[i].pm_width; 3096aa342b1fSJoseph Koshy return (0); 3097f263522aSJoseph Koshy } 3098484202faSJoseph Koshy errno = EINVAL; 3099484202faSJoseph Koshy return (-1); 3100f263522aSJoseph Koshy } 3101f263522aSJoseph Koshy 3102f263522aSJoseph Koshy int 3103f263522aSJoseph Koshy pmc_write(pmc_id_t pmc, pmc_value_t value) 3104f263522aSJoseph Koshy { 3105f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_write_op; 3106f263522aSJoseph Koshy 3107f263522aSJoseph Koshy pmc_write_op.pm_pmcid = pmc; 3108f263522aSJoseph Koshy pmc_write_op.pm_flags = PMC_F_NEWVALUE; 3109f263522aSJoseph Koshy pmc_write_op.pm_value = value; 3110aa342b1fSJoseph Koshy return (PMC_CALL(PMCRW, &pmc_write_op)); 3111f263522aSJoseph Koshy } 3112f263522aSJoseph Koshy 3113f263522aSJoseph Koshy int 3114f263522aSJoseph Koshy pmc_writelog(uint32_t userdata) 3115f263522aSJoseph Koshy { 3116f263522aSJoseph Koshy struct pmc_op_writelog wl; 3117f263522aSJoseph Koshy 3118f263522aSJoseph Koshy wl.pm_userdata = userdata; 3119aa342b1fSJoseph Koshy return (PMC_CALL(WRITELOG, &wl)); 3120f263522aSJoseph Koshy } 3121