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 if (cachestate == 0) 7410cfab8ddSJoseph Koshy cachestate = (0xF << 8); 742aa1b887bSRyan Stone break; 743aa1b887bSRyan Stone case PMC_EV_IAP_EVENT_77H: /* Atom */ 744aa1b887bSRyan Stone /* IAP_EVENT_77H only accepts a cachestate qualifier on the 745aa1b887bSRyan Stone * Atom processor 746aa1b887bSRyan Stone */ 747aa1b887bSRyan Stone if(cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM && cachestate == 0) 748aa1b887bSRyan Stone cachestate = (0xF << 8); 749aa1b887bSRyan Stone break; 7500cfab8ddSJoseph Koshy default: 7510cfab8ddSJoseph Koshy break; 7520cfab8ddSJoseph Koshy } 7530cfab8ddSJoseph Koshy 7540cfab8ddSJoseph Koshy pmc_config->pm_md.pm_iap.pm_iap_config |= cachestate; 7551fa7f10bSFabien Thomas pmc_config->pm_md.pm_iap.pm_iap_rsp = rsp; 7561fa7f10bSFabien Thomas 7571fa7f10bSFabien Thomas return (0); 7581fa7f10bSFabien Thomas } 7591fa7f10bSFabien Thomas 7601fa7f10bSFabien Thomas /* 7611fa7f10bSFabien Thomas * Intel Uncore. 7621fa7f10bSFabien Thomas */ 7631fa7f10bSFabien Thomas 7641fa7f10bSFabien Thomas static int 7651fa7f10bSFabien Thomas ucf_allocate_pmc(enum pmc_event pe, char *ctrspec, 7661fa7f10bSFabien Thomas struct pmc_op_pmcallocate *pmc_config) 7671fa7f10bSFabien Thomas { 7681fa7f10bSFabien Thomas (void) pe; 7691fa7f10bSFabien Thomas (void) ctrspec; 7701fa7f10bSFabien Thomas 7711fa7f10bSFabien Thomas pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 7721fa7f10bSFabien Thomas pmc_config->pm_md.pm_ucf.pm_ucf_flags = 0; 7731fa7f10bSFabien Thomas 7741fa7f10bSFabien Thomas return (0); 7751fa7f10bSFabien Thomas } 7761fa7f10bSFabien Thomas 7771fa7f10bSFabien Thomas #define UCP_KW_CMASK "cmask" 7781fa7f10bSFabien Thomas #define UCP_KW_EDGE "edge" 7791fa7f10bSFabien Thomas #define UCP_KW_INV "inv" 7801fa7f10bSFabien Thomas 7811fa7f10bSFabien Thomas static int 7821fa7f10bSFabien Thomas ucp_allocate_pmc(enum pmc_event pe, char *ctrspec, 7831fa7f10bSFabien Thomas struct pmc_op_pmcallocate *pmc_config) 7841fa7f10bSFabien Thomas { 7851fa7f10bSFabien Thomas char *e, *p, *q; 7861fa7f10bSFabien Thomas int count, n; 7871fa7f10bSFabien Thomas 7881fa7f10bSFabien Thomas (void) pe; 7891fa7f10bSFabien Thomas 7901fa7f10bSFabien Thomas pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE | 7911fa7f10bSFabien Thomas PMC_CAP_QUALIFIER); 7921fa7f10bSFabien Thomas pmc_config->pm_md.pm_ucp.pm_ucp_config = 0; 7931fa7f10bSFabien Thomas 7941fa7f10bSFabien Thomas /* Parse additional modifiers if present */ 7951fa7f10bSFabien Thomas while ((p = strsep(&ctrspec, ",")) != NULL) { 7961fa7f10bSFabien Thomas 7971fa7f10bSFabien Thomas n = 0; 7981fa7f10bSFabien Thomas if (KWPREFIXMATCH(p, UCP_KW_CMASK "=")) { 7991fa7f10bSFabien Thomas q = strchr(p, '='); 8001fa7f10bSFabien Thomas if (*++q == '\0') /* skip '=' */ 8011fa7f10bSFabien Thomas return (-1); 8021fa7f10bSFabien Thomas count = strtol(q, &e, 0); 8031fa7f10bSFabien Thomas if (e == q || *e != '\0') 8041fa7f10bSFabien Thomas return (-1); 8051fa7f10bSFabien Thomas pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 8061fa7f10bSFabien Thomas pmc_config->pm_md.pm_ucp.pm_ucp_config |= 8071fa7f10bSFabien Thomas UCP_CMASK(count); 8081fa7f10bSFabien Thomas } else if (KWMATCH(p, UCP_KW_EDGE)) { 8091fa7f10bSFabien Thomas pmc_config->pm_caps |= PMC_CAP_EDGE; 8101fa7f10bSFabien Thomas } else if (KWMATCH(p, UCP_KW_INV)) { 8111fa7f10bSFabien Thomas pmc_config->pm_caps |= PMC_CAP_INVERT; 8121fa7f10bSFabien Thomas } else 8131fa7f10bSFabien Thomas return (-1); 8141fa7f10bSFabien Thomas 8151fa7f10bSFabien Thomas if (n < 0) /* Parsing failed. */ 8161fa7f10bSFabien Thomas return (-1); 8171fa7f10bSFabien Thomas } 8180cfab8ddSJoseph Koshy 8190cfab8ddSJoseph Koshy return (0); 8200cfab8ddSJoseph Koshy } 8210cfab8ddSJoseph Koshy 8220cfab8ddSJoseph Koshy /* 823f263522aSJoseph Koshy * AMD K8 PMCs. 824f263522aSJoseph Koshy * 825f263522aSJoseph Koshy * These are very similar to AMD K7 PMCs, but support more kinds of 826f263522aSJoseph Koshy * events. 827f263522aSJoseph Koshy */ 828f263522aSJoseph Koshy 829f263522aSJoseph Koshy static struct pmc_event_alias k8_aliases[] = { 830f263522aSJoseph Koshy EV_ALIAS("branches", "k8-fr-retired-taken-branches"), 831f263522aSJoseph Koshy EV_ALIAS("branch-mispredicts", 832f263522aSJoseph Koshy "k8-fr-retired-taken-branches-mispredicted"), 833f263522aSJoseph Koshy EV_ALIAS("cycles", "tsc"), 834f263522aSJoseph Koshy EV_ALIAS("dc-misses", "k8-dc-miss"), 835f263522aSJoseph Koshy EV_ALIAS("ic-misses", "k8-ic-miss"), 836f263522aSJoseph Koshy EV_ALIAS("instructions", "k8-fr-retired-x86-instructions"), 837f263522aSJoseph Koshy EV_ALIAS("interrupts", "k8-fr-taken-hardware-interrupts"), 838177a2f22SJoseph Koshy EV_ALIAS("unhalted-cycles", "k8-bu-cpu-clk-unhalted"), 839f263522aSJoseph Koshy EV_ALIAS(NULL, NULL) 840f263522aSJoseph Koshy }; 841f263522aSJoseph Koshy 842f263522aSJoseph Koshy #define __K8MASK(N,V) PMCMASK(N,(1 << (V))) 843f263522aSJoseph Koshy 844f263522aSJoseph Koshy /* 845f263522aSJoseph Koshy * Parsing tables 846f263522aSJoseph Koshy */ 847f263522aSJoseph Koshy 848f263522aSJoseph Koshy /* fp dispatched fpu ops */ 849f263522aSJoseph Koshy static const struct pmc_masks k8_mask_fdfo[] = { 850f263522aSJoseph Koshy __K8MASK(add-pipe-excluding-junk-ops, 0), 851f263522aSJoseph Koshy __K8MASK(multiply-pipe-excluding-junk-ops, 1), 852f263522aSJoseph Koshy __K8MASK(store-pipe-excluding-junk-ops, 2), 853f263522aSJoseph Koshy __K8MASK(add-pipe-junk-ops, 3), 854f263522aSJoseph Koshy __K8MASK(multiply-pipe-junk-ops, 4), 855f263522aSJoseph Koshy __K8MASK(store-pipe-junk-ops, 5), 856f263522aSJoseph Koshy NULLMASK 857f263522aSJoseph Koshy }; 858f263522aSJoseph Koshy 859f263522aSJoseph Koshy /* ls segment register loads */ 860f263522aSJoseph Koshy static const struct pmc_masks k8_mask_lsrl[] = { 861f263522aSJoseph Koshy __K8MASK(es, 0), 862f263522aSJoseph Koshy __K8MASK(cs, 1), 863f263522aSJoseph Koshy __K8MASK(ss, 2), 864f263522aSJoseph Koshy __K8MASK(ds, 3), 865f263522aSJoseph Koshy __K8MASK(fs, 4), 866f263522aSJoseph Koshy __K8MASK(gs, 5), 867f263522aSJoseph Koshy __K8MASK(hs, 6), 868f263522aSJoseph Koshy NULLMASK 869f263522aSJoseph Koshy }; 870f263522aSJoseph Koshy 871f263522aSJoseph Koshy /* ls locked operation */ 872f263522aSJoseph Koshy static const struct pmc_masks k8_mask_llo[] = { 873f263522aSJoseph Koshy __K8MASK(locked-instructions, 0), 874f263522aSJoseph Koshy __K8MASK(cycles-in-request, 1), 875f263522aSJoseph Koshy __K8MASK(cycles-to-complete, 2), 876f263522aSJoseph Koshy NULLMASK 877f263522aSJoseph Koshy }; 878f263522aSJoseph Koshy 879f263522aSJoseph Koshy /* dc refill from {l2,system} and dc copyback */ 880f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dc[] = { 881f263522aSJoseph Koshy __K8MASK(invalid, 0), 882f263522aSJoseph Koshy __K8MASK(shared, 1), 883f263522aSJoseph Koshy __K8MASK(exclusive, 2), 884f263522aSJoseph Koshy __K8MASK(owner, 3), 885f263522aSJoseph Koshy __K8MASK(modified, 4), 886f263522aSJoseph Koshy NULLMASK 887f263522aSJoseph Koshy }; 888f263522aSJoseph Koshy 889f263522aSJoseph Koshy /* dc one bit ecc error */ 890f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dobee[] = { 891f263522aSJoseph Koshy __K8MASK(scrubber, 0), 892f263522aSJoseph Koshy __K8MASK(piggyback, 1), 893f263522aSJoseph Koshy NULLMASK 894f263522aSJoseph Koshy }; 895f263522aSJoseph Koshy 896f263522aSJoseph Koshy /* dc dispatched prefetch instructions */ 897f263522aSJoseph Koshy static const struct pmc_masks k8_mask_ddpi[] = { 898f263522aSJoseph Koshy __K8MASK(load, 0), 899f263522aSJoseph Koshy __K8MASK(store, 1), 900f263522aSJoseph Koshy __K8MASK(nta, 2), 901f263522aSJoseph Koshy NULLMASK 902f263522aSJoseph Koshy }; 903f263522aSJoseph Koshy 904f263522aSJoseph Koshy /* dc dcache accesses by locks */ 905f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dabl[] = { 906f263522aSJoseph Koshy __K8MASK(accesses, 0), 907f263522aSJoseph Koshy __K8MASK(misses, 1), 908f263522aSJoseph Koshy NULLMASK 909f263522aSJoseph Koshy }; 910f263522aSJoseph Koshy 911f263522aSJoseph Koshy /* bu internal l2 request */ 912f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bilr[] = { 913f263522aSJoseph Koshy __K8MASK(ic-fill, 0), 914f263522aSJoseph Koshy __K8MASK(dc-fill, 1), 915f263522aSJoseph Koshy __K8MASK(tlb-reload, 2), 916f263522aSJoseph Koshy __K8MASK(tag-snoop, 3), 917f263522aSJoseph Koshy __K8MASK(cancelled, 4), 918f263522aSJoseph Koshy NULLMASK 919f263522aSJoseph Koshy }; 920f263522aSJoseph Koshy 921f263522aSJoseph Koshy /* bu fill request l2 miss */ 922f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bfrlm[] = { 923f263522aSJoseph Koshy __K8MASK(ic-fill, 0), 924f263522aSJoseph Koshy __K8MASK(dc-fill, 1), 925f263522aSJoseph Koshy __K8MASK(tlb-reload, 2), 926f263522aSJoseph Koshy NULLMASK 927f263522aSJoseph Koshy }; 928f263522aSJoseph Koshy 929f263522aSJoseph Koshy /* bu fill into l2 */ 930f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bfil[] = { 931f263522aSJoseph Koshy __K8MASK(dirty-l2-victim, 0), 932f263522aSJoseph Koshy __K8MASK(victim-from-l2, 1), 933f263522aSJoseph Koshy NULLMASK 934f263522aSJoseph Koshy }; 935f263522aSJoseph Koshy 936f263522aSJoseph Koshy /* fr retired fpu instructions */ 937f263522aSJoseph Koshy static const struct pmc_masks k8_mask_frfi[] = { 938f263522aSJoseph Koshy __K8MASK(x87, 0), 939f263522aSJoseph Koshy __K8MASK(mmx-3dnow, 1), 940f263522aSJoseph Koshy __K8MASK(packed-sse-sse2, 2), 941f263522aSJoseph Koshy __K8MASK(scalar-sse-sse2, 3), 942f263522aSJoseph Koshy NULLMASK 943f263522aSJoseph Koshy }; 944f263522aSJoseph Koshy 945f263522aSJoseph Koshy /* fr retired fastpath double op instructions */ 946f263522aSJoseph Koshy static const struct pmc_masks k8_mask_frfdoi[] = { 947f263522aSJoseph Koshy __K8MASK(low-op-pos-0, 0), 948f263522aSJoseph Koshy __K8MASK(low-op-pos-1, 1), 949f263522aSJoseph Koshy __K8MASK(low-op-pos-2, 2), 950f263522aSJoseph Koshy NULLMASK 951f263522aSJoseph Koshy }; 952f263522aSJoseph Koshy 953f263522aSJoseph Koshy /* fr fpu exceptions */ 954f263522aSJoseph Koshy static const struct pmc_masks k8_mask_ffe[] = { 955f263522aSJoseph Koshy __K8MASK(x87-reclass-microfaults, 0), 956f263522aSJoseph Koshy __K8MASK(sse-retype-microfaults, 1), 957f263522aSJoseph Koshy __K8MASK(sse-reclass-microfaults, 2), 958f263522aSJoseph Koshy __K8MASK(sse-and-x87-microtraps, 3), 959f263522aSJoseph Koshy NULLMASK 960f263522aSJoseph Koshy }; 961f263522aSJoseph Koshy 962f263522aSJoseph Koshy /* nb memory controller page access event */ 963f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmcpae[] = { 964f263522aSJoseph Koshy __K8MASK(page-hit, 0), 965f263522aSJoseph Koshy __K8MASK(page-miss, 1), 966f263522aSJoseph Koshy __K8MASK(page-conflict, 2), 967f263522aSJoseph Koshy NULLMASK 968f263522aSJoseph Koshy }; 969f263522aSJoseph Koshy 970f263522aSJoseph Koshy /* nb memory controller turnaround */ 971f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmct[] = { 972f263522aSJoseph Koshy __K8MASK(dimm-turnaround, 0), 973f263522aSJoseph Koshy __K8MASK(read-to-write-turnaround, 1), 974f263522aSJoseph Koshy __K8MASK(write-to-read-turnaround, 2), 975f263522aSJoseph Koshy NULLMASK 976f263522aSJoseph Koshy }; 977f263522aSJoseph Koshy 978f263522aSJoseph Koshy /* nb memory controller bypass saturation */ 979f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmcbs[] = { 980f263522aSJoseph Koshy __K8MASK(memory-controller-hi-pri-bypass, 0), 981f263522aSJoseph Koshy __K8MASK(memory-controller-lo-pri-bypass, 1), 982f263522aSJoseph Koshy __K8MASK(dram-controller-interface-bypass, 2), 983f263522aSJoseph Koshy __K8MASK(dram-controller-queue-bypass, 3), 984f263522aSJoseph Koshy NULLMASK 985f263522aSJoseph Koshy }; 986f263522aSJoseph Koshy 987f263522aSJoseph Koshy /* nb sized commands */ 988f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nsc[] = { 989f263522aSJoseph Koshy __K8MASK(nonpostwrszbyte, 0), 990f263522aSJoseph Koshy __K8MASK(nonpostwrszdword, 1), 991f263522aSJoseph Koshy __K8MASK(postwrszbyte, 2), 992f263522aSJoseph Koshy __K8MASK(postwrszdword, 3), 993f263522aSJoseph Koshy __K8MASK(rdszbyte, 4), 994f263522aSJoseph Koshy __K8MASK(rdszdword, 5), 995f263522aSJoseph Koshy __K8MASK(rdmodwr, 6), 996f263522aSJoseph Koshy NULLMASK 997f263522aSJoseph Koshy }; 998f263522aSJoseph Koshy 999f263522aSJoseph Koshy /* nb probe result */ 1000f263522aSJoseph Koshy static const struct pmc_masks k8_mask_npr[] = { 1001f263522aSJoseph Koshy __K8MASK(probe-miss, 0), 1002f263522aSJoseph Koshy __K8MASK(probe-hit, 1), 1003f263522aSJoseph Koshy __K8MASK(probe-hit-dirty-no-memory-cancel, 2), 1004f263522aSJoseph Koshy __K8MASK(probe-hit-dirty-with-memory-cancel, 3), 1005f263522aSJoseph Koshy NULLMASK 1006f263522aSJoseph Koshy }; 1007f263522aSJoseph Koshy 1008f263522aSJoseph Koshy /* nb hypertransport bus bandwidth */ 1009f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nhbb[] = { /* HT bus bandwidth */ 1010f263522aSJoseph Koshy __K8MASK(command, 0), 1011f263522aSJoseph Koshy __K8MASK(data, 1), 1012f263522aSJoseph Koshy __K8MASK(buffer-release, 2), 1013f263522aSJoseph Koshy __K8MASK(nop, 3), 1014f263522aSJoseph Koshy NULLMASK 1015f263522aSJoseph Koshy }; 1016f263522aSJoseph Koshy 1017f263522aSJoseph Koshy #undef __K8MASK 1018f263522aSJoseph Koshy 1019f263522aSJoseph Koshy #define K8_KW_COUNT "count" 1020f263522aSJoseph Koshy #define K8_KW_EDGE "edge" 1021f263522aSJoseph Koshy #define K8_KW_INV "inv" 1022f263522aSJoseph Koshy #define K8_KW_MASK "mask" 1023f263522aSJoseph Koshy #define K8_KW_OS "os" 1024f263522aSJoseph Koshy #define K8_KW_USR "usr" 1025f263522aSJoseph Koshy 1026f263522aSJoseph Koshy static int 1027f263522aSJoseph Koshy k8_allocate_pmc(enum pmc_event pe, char *ctrspec, 1028f263522aSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 1029f263522aSJoseph Koshy { 1030f263522aSJoseph Koshy char *e, *p, *q; 1031f263522aSJoseph Koshy int n; 1032f263522aSJoseph Koshy uint32_t count, evmask; 1033f263522aSJoseph Koshy const struct pmc_masks *pm, *pmask; 1034f263522aSJoseph Koshy 1035789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1036f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 1037f263522aSJoseph Koshy 1038f263522aSJoseph Koshy pmask = NULL; 1039f263522aSJoseph Koshy evmask = 0; 1040f263522aSJoseph Koshy 1041f263522aSJoseph Koshy #define __K8SETMASK(M) pmask = k8_mask_##M 1042f263522aSJoseph Koshy 1043f263522aSJoseph Koshy /* setup parsing tables */ 1044f263522aSJoseph Koshy switch (pe) { 1045f263522aSJoseph Koshy case PMC_EV_K8_FP_DISPATCHED_FPU_OPS: 1046f263522aSJoseph Koshy __K8SETMASK(fdfo); 1047f263522aSJoseph Koshy break; 1048f263522aSJoseph Koshy case PMC_EV_K8_LS_SEGMENT_REGISTER_LOAD: 1049f263522aSJoseph Koshy __K8SETMASK(lsrl); 1050f263522aSJoseph Koshy break; 1051f263522aSJoseph Koshy case PMC_EV_K8_LS_LOCKED_OPERATION: 1052f263522aSJoseph Koshy __K8SETMASK(llo); 1053f263522aSJoseph Koshy break; 1054f263522aSJoseph Koshy case PMC_EV_K8_DC_REFILL_FROM_L2: 1055f263522aSJoseph Koshy case PMC_EV_K8_DC_REFILL_FROM_SYSTEM: 1056f263522aSJoseph Koshy case PMC_EV_K8_DC_COPYBACK: 1057f263522aSJoseph Koshy __K8SETMASK(dc); 1058f263522aSJoseph Koshy break; 1059f263522aSJoseph Koshy case PMC_EV_K8_DC_ONE_BIT_ECC_ERROR: 1060f263522aSJoseph Koshy __K8SETMASK(dobee); 1061f263522aSJoseph Koshy break; 1062f263522aSJoseph Koshy case PMC_EV_K8_DC_DISPATCHED_PREFETCH_INSTRUCTIONS: 1063f263522aSJoseph Koshy __K8SETMASK(ddpi); 1064f263522aSJoseph Koshy break; 1065f263522aSJoseph Koshy case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS: 1066f263522aSJoseph Koshy __K8SETMASK(dabl); 1067f263522aSJoseph Koshy break; 1068f263522aSJoseph Koshy case PMC_EV_K8_BU_INTERNAL_L2_REQUEST: 1069f263522aSJoseph Koshy __K8SETMASK(bilr); 1070f263522aSJoseph Koshy break; 1071f263522aSJoseph Koshy case PMC_EV_K8_BU_FILL_REQUEST_L2_MISS: 1072f263522aSJoseph Koshy __K8SETMASK(bfrlm); 1073f263522aSJoseph Koshy break; 1074f263522aSJoseph Koshy case PMC_EV_K8_BU_FILL_INTO_L2: 1075f263522aSJoseph Koshy __K8SETMASK(bfil); 1076f263522aSJoseph Koshy break; 1077f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS: 1078f263522aSJoseph Koshy __K8SETMASK(frfi); 1079f263522aSJoseph Koshy break; 1080f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS: 1081f263522aSJoseph Koshy __K8SETMASK(frfdoi); 1082f263522aSJoseph Koshy break; 1083f263522aSJoseph Koshy case PMC_EV_K8_FR_FPU_EXCEPTIONS: 1084f263522aSJoseph Koshy __K8SETMASK(ffe); 1085f263522aSJoseph Koshy break; 1086f263522aSJoseph Koshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_PAGE_ACCESS_EVENT: 1087f263522aSJoseph Koshy __K8SETMASK(nmcpae); 1088f263522aSJoseph Koshy break; 1089f263522aSJoseph Koshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_TURNAROUND: 1090f263522aSJoseph Koshy __K8SETMASK(nmct); 1091f263522aSJoseph Koshy break; 1092f263522aSJoseph Koshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_BYPASS_SATURATION: 1093f263522aSJoseph Koshy __K8SETMASK(nmcbs); 1094f263522aSJoseph Koshy break; 1095f263522aSJoseph Koshy case PMC_EV_K8_NB_SIZED_COMMANDS: 1096f263522aSJoseph Koshy __K8SETMASK(nsc); 1097f263522aSJoseph Koshy break; 1098f263522aSJoseph Koshy case PMC_EV_K8_NB_PROBE_RESULT: 1099f263522aSJoseph Koshy __K8SETMASK(npr); 1100f263522aSJoseph Koshy break; 1101f263522aSJoseph Koshy case PMC_EV_K8_NB_HT_BUS0_BANDWIDTH: 1102f263522aSJoseph Koshy case PMC_EV_K8_NB_HT_BUS1_BANDWIDTH: 1103f263522aSJoseph Koshy case PMC_EV_K8_NB_HT_BUS2_BANDWIDTH: 1104f263522aSJoseph Koshy __K8SETMASK(nhbb); 1105f263522aSJoseph Koshy break; 1106f263522aSJoseph Koshy 1107f263522aSJoseph Koshy default: 1108f263522aSJoseph Koshy break; /* no options defined */ 1109f263522aSJoseph Koshy } 1110f263522aSJoseph Koshy 1111f263522aSJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 1112f263522aSJoseph Koshy if (KWPREFIXMATCH(p, K8_KW_COUNT "=")) { 1113f263522aSJoseph Koshy q = strchr(p, '='); 1114f263522aSJoseph Koshy if (*++q == '\0') /* skip '=' */ 1115aa342b1fSJoseph Koshy return (-1); 1116f263522aSJoseph Koshy 1117f263522aSJoseph Koshy count = strtol(q, &e, 0); 1118f263522aSJoseph Koshy if (e == q || *e != '\0') 1119aa342b1fSJoseph Koshy return (-1); 1120f263522aSJoseph Koshy 1121f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 1122f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config |= 1123f263522aSJoseph Koshy AMD_PMC_TO_COUNTER(count); 1124f263522aSJoseph Koshy 1125f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_EDGE)) { 1126f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1127f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_INV)) { 1128f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 1129f263522aSJoseph Koshy } else if (KWPREFIXMATCH(p, K8_KW_MASK "=")) { 1130f263522aSJoseph Koshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 1131aa342b1fSJoseph Koshy return (-1); 1132f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1133f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_OS)) { 1134f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 1135f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_USR)) { 1136f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 1137f263522aSJoseph Koshy } else 1138aa342b1fSJoseph Koshy return (-1); 1139f263522aSJoseph Koshy } 1140f263522aSJoseph Koshy 1141f263522aSJoseph Koshy /* other post processing */ 1142f263522aSJoseph Koshy switch (pe) { 1143f263522aSJoseph Koshy case PMC_EV_K8_FP_DISPATCHED_FPU_OPS: 1144f263522aSJoseph Koshy case PMC_EV_K8_FP_CYCLES_WITH_NO_FPU_OPS_RETIRED: 1145f263522aSJoseph Koshy case PMC_EV_K8_FP_DISPATCHED_FPU_FAST_FLAG_OPS: 1146f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS: 1147f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS: 1148f263522aSJoseph Koshy case PMC_EV_K8_FR_FPU_EXCEPTIONS: 1149f263522aSJoseph Koshy /* XXX only available in rev B and later */ 1150f263522aSJoseph Koshy break; 1151f263522aSJoseph Koshy case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS: 1152f263522aSJoseph Koshy /* XXX only available in rev C and later */ 1153f263522aSJoseph Koshy break; 1154f263522aSJoseph Koshy case PMC_EV_K8_LS_LOCKED_OPERATION: 1155f263522aSJoseph Koshy /* XXX CPU Rev A,B evmask is to be zero */ 1156f263522aSJoseph Koshy if (evmask & (evmask - 1)) /* > 1 bit set */ 1157aa342b1fSJoseph Koshy return (-1); 1158f263522aSJoseph Koshy if (evmask == 0) { 1159f263522aSJoseph Koshy evmask = 0x01; /* Rev C and later: #instrs */ 1160f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1161f263522aSJoseph Koshy } 1162f263522aSJoseph Koshy break; 1163f263522aSJoseph Koshy default: 1164f263522aSJoseph Koshy if (evmask == 0 && pmask != NULL) { 1165f263522aSJoseph Koshy for (pm = pmask; pm->pm_name; pm++) 1166f263522aSJoseph Koshy evmask |= pm->pm_value; 1167f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1168f263522aSJoseph Koshy } 1169f263522aSJoseph Koshy } 1170f263522aSJoseph Koshy 1171f263522aSJoseph Koshy if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) 1172f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 1173f263522aSJoseph Koshy AMD_PMC_TO_UNITMASK(evmask); 1174f263522aSJoseph Koshy 1175aa342b1fSJoseph Koshy return (0); 1176f263522aSJoseph Koshy } 1177f263522aSJoseph Koshy 1178f263522aSJoseph Koshy #endif 1179f263522aSJoseph Koshy 118086a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 1181f263522aSJoseph Koshy 1182ebccf1e3SJoseph Koshy /* 1183ebccf1e3SJoseph Koshy * Intel P4 PMCs 1184ebccf1e3SJoseph Koshy */ 1185ebccf1e3SJoseph Koshy 1186ebccf1e3SJoseph Koshy static struct pmc_event_alias p4_aliases[] = { 1187d56c5d4bSJoseph Koshy EV_ALIAS("branches", "p4-branch-retired,mask=mmtp+mmtm"), 1188d56c5d4bSJoseph Koshy EV_ALIAS("branch-mispredicts", "p4-mispred-branch-retired"), 1189ebccf1e3SJoseph Koshy EV_ALIAS("cycles", "tsc"), 1190d56c5d4bSJoseph Koshy EV_ALIAS("instructions", 1191d56c5d4bSJoseph Koshy "p4-instr-retired,mask=nbogusntag+nbogustag"), 1192177a2f22SJoseph Koshy EV_ALIAS("unhalted-cycles", "p4-global-power-events"), 1193ebccf1e3SJoseph Koshy EV_ALIAS(NULL, NULL) 1194ebccf1e3SJoseph Koshy }; 1195ebccf1e3SJoseph Koshy 1196ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE "active" 1197ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_ANY "any" 1198ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_BOTH "both" 1199ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_NONE "none" 1200ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_SINGLE "single" 1201ebccf1e3SJoseph Koshy #define P4_KW_BUSREQTYPE "busreqtype" 1202ebccf1e3SJoseph Koshy #define P4_KW_CASCADE "cascade" 1203ebccf1e3SJoseph Koshy #define P4_KW_EDGE "edge" 1204ebccf1e3SJoseph Koshy #define P4_KW_INV "complement" 1205ebccf1e3SJoseph Koshy #define P4_KW_OS "os" 1206ebccf1e3SJoseph Koshy #define P4_KW_MASK "mask" 1207ebccf1e3SJoseph Koshy #define P4_KW_PRECISE "precise" 1208ebccf1e3SJoseph Koshy #define P4_KW_TAG "tag" 1209ebccf1e3SJoseph Koshy #define P4_KW_THRESHOLD "threshold" 1210ebccf1e3SJoseph Koshy #define P4_KW_USR "usr" 1211ebccf1e3SJoseph Koshy 1212ebccf1e3SJoseph Koshy #define __P4MASK(N,V) PMCMASK(N, (1 << (V))) 1213ebccf1e3SJoseph Koshy 1214ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_tcdm[] = { /* tc deliver mode */ 1215ebccf1e3SJoseph Koshy __P4MASK(dd, 0), 1216ebccf1e3SJoseph Koshy __P4MASK(db, 1), 1217ebccf1e3SJoseph Koshy __P4MASK(di, 2), 1218ebccf1e3SJoseph Koshy __P4MASK(bd, 3), 1219ebccf1e3SJoseph Koshy __P4MASK(bb, 4), 1220ebccf1e3SJoseph Koshy __P4MASK(bi, 5), 1221ebccf1e3SJoseph Koshy __P4MASK(id, 6), 1222ebccf1e3SJoseph Koshy __P4MASK(ib, 7), 1223ebccf1e3SJoseph Koshy NULLMASK 1224ebccf1e3SJoseph Koshy }; 1225ebccf1e3SJoseph Koshy 1226ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_bfr[] = { /* bpu fetch request */ 1227ebccf1e3SJoseph Koshy __P4MASK(tcmiss, 0), 1228ebccf1e3SJoseph Koshy NULLMASK, 1229ebccf1e3SJoseph Koshy }; 1230ebccf1e3SJoseph Koshy 1231ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ir[] = { /* itlb reference */ 1232ebccf1e3SJoseph Koshy __P4MASK(hit, 0), 1233ebccf1e3SJoseph Koshy __P4MASK(miss, 1), 1234ebccf1e3SJoseph Koshy __P4MASK(hit-uc, 2), 1235ebccf1e3SJoseph Koshy NULLMASK 1236ebccf1e3SJoseph Koshy }; 1237ebccf1e3SJoseph Koshy 1238ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_memcan[] = { /* memory cancel */ 1239ebccf1e3SJoseph Koshy __P4MASK(st-rb-full, 2), 1240ebccf1e3SJoseph Koshy __P4MASK(64k-conf, 3), 1241ebccf1e3SJoseph Koshy NULLMASK 1242ebccf1e3SJoseph Koshy }; 1243ebccf1e3SJoseph Koshy 1244ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_memcomp[] = { /* memory complete */ 1245ebccf1e3SJoseph Koshy __P4MASK(lsc, 0), 1246ebccf1e3SJoseph Koshy __P4MASK(ssc, 1), 1247ebccf1e3SJoseph Koshy NULLMASK 1248ebccf1e3SJoseph Koshy }; 1249ebccf1e3SJoseph Koshy 1250ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_lpr[] = { /* load port replay */ 1251ebccf1e3SJoseph Koshy __P4MASK(split-ld, 1), 1252ebccf1e3SJoseph Koshy NULLMASK 1253ebccf1e3SJoseph Koshy }; 1254ebccf1e3SJoseph Koshy 1255ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_spr[] = { /* store port replay */ 1256ebccf1e3SJoseph Koshy __P4MASK(split-st, 1), 1257ebccf1e3SJoseph Koshy NULLMASK 1258ebccf1e3SJoseph Koshy }; 1259ebccf1e3SJoseph Koshy 1260ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_mlr[] = { /* mob load replay */ 1261ebccf1e3SJoseph Koshy __P4MASK(no-sta, 1), 1262ebccf1e3SJoseph Koshy __P4MASK(no-std, 3), 1263ebccf1e3SJoseph Koshy __P4MASK(partial-data, 4), 1264ebccf1e3SJoseph Koshy __P4MASK(unalgn-addr, 5), 1265ebccf1e3SJoseph Koshy NULLMASK 1266ebccf1e3SJoseph Koshy }; 1267ebccf1e3SJoseph Koshy 1268ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_pwt[] = { /* page walk type */ 1269ebccf1e3SJoseph Koshy __P4MASK(dtmiss, 0), 1270ebccf1e3SJoseph Koshy __P4MASK(itmiss, 1), 1271ebccf1e3SJoseph Koshy NULLMASK 1272ebccf1e3SJoseph Koshy }; 1273ebccf1e3SJoseph Koshy 1274ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_bcr[] = { /* bsq cache reference */ 1275ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-hits, 0), 1276ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-hite, 1), 1277ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-hitm, 2), 1278ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-hits, 3), 1279ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-hite, 4), 1280ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-hitm, 5), 1281ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-miss, 8), 1282ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-miss, 9), 1283ebccf1e3SJoseph Koshy __P4MASK(wr-2ndl-miss, 10), 1284ebccf1e3SJoseph Koshy NULLMASK 1285ebccf1e3SJoseph Koshy }; 1286ebccf1e3SJoseph Koshy 1287ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ia[] = { /* ioq allocation */ 1288ebccf1e3SJoseph Koshy __P4MASK(all-read, 5), 1289ebccf1e3SJoseph Koshy __P4MASK(all-write, 6), 1290ebccf1e3SJoseph Koshy __P4MASK(mem-uc, 7), 1291ebccf1e3SJoseph Koshy __P4MASK(mem-wc, 8), 1292ebccf1e3SJoseph Koshy __P4MASK(mem-wt, 9), 1293ebccf1e3SJoseph Koshy __P4MASK(mem-wp, 10), 1294ebccf1e3SJoseph Koshy __P4MASK(mem-wb, 11), 1295ebccf1e3SJoseph Koshy __P4MASK(own, 13), 1296ebccf1e3SJoseph Koshy __P4MASK(other, 14), 1297ebccf1e3SJoseph Koshy __P4MASK(prefetch, 15), 1298ebccf1e3SJoseph Koshy NULLMASK 1299ebccf1e3SJoseph Koshy }; 1300ebccf1e3SJoseph Koshy 1301ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_iae[] = { /* ioq active entries */ 1302ebccf1e3SJoseph Koshy __P4MASK(all-read, 5), 1303ebccf1e3SJoseph Koshy __P4MASK(all-write, 6), 1304ebccf1e3SJoseph Koshy __P4MASK(mem-uc, 7), 1305ebccf1e3SJoseph Koshy __P4MASK(mem-wc, 8), 1306ebccf1e3SJoseph Koshy __P4MASK(mem-wt, 9), 1307ebccf1e3SJoseph Koshy __P4MASK(mem-wp, 10), 1308ebccf1e3SJoseph Koshy __P4MASK(mem-wb, 11), 1309ebccf1e3SJoseph Koshy __P4MASK(own, 13), 1310ebccf1e3SJoseph Koshy __P4MASK(other, 14), 1311ebccf1e3SJoseph Koshy __P4MASK(prefetch, 15), 1312ebccf1e3SJoseph Koshy NULLMASK 1313ebccf1e3SJoseph Koshy }; 1314ebccf1e3SJoseph Koshy 1315ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_fda[] = { /* fsb data activity */ 1316ebccf1e3SJoseph Koshy __P4MASK(drdy-drv, 0), 1317ebccf1e3SJoseph Koshy __P4MASK(drdy-own, 1), 1318ebccf1e3SJoseph Koshy __P4MASK(drdy-other, 2), 1319ebccf1e3SJoseph Koshy __P4MASK(dbsy-drv, 3), 1320ebccf1e3SJoseph Koshy __P4MASK(dbsy-own, 4), 1321ebccf1e3SJoseph Koshy __P4MASK(dbsy-other, 5), 1322ebccf1e3SJoseph Koshy NULLMASK 1323ebccf1e3SJoseph Koshy }; 1324ebccf1e3SJoseph Koshy 1325ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ba[] = { /* bsq allocation */ 1326ebccf1e3SJoseph Koshy __P4MASK(req-type0, 0), 1327ebccf1e3SJoseph Koshy __P4MASK(req-type1, 1), 1328ebccf1e3SJoseph Koshy __P4MASK(req-len0, 2), 1329ebccf1e3SJoseph Koshy __P4MASK(req-len1, 3), 1330ebccf1e3SJoseph Koshy __P4MASK(req-io-type, 5), 1331ebccf1e3SJoseph Koshy __P4MASK(req-lock-type, 6), 1332ebccf1e3SJoseph Koshy __P4MASK(req-cache-type, 7), 1333ebccf1e3SJoseph Koshy __P4MASK(req-split-type, 8), 1334ebccf1e3SJoseph Koshy __P4MASK(req-dem-type, 9), 1335ebccf1e3SJoseph Koshy __P4MASK(req-ord-type, 10), 1336ebccf1e3SJoseph Koshy __P4MASK(mem-type0, 11), 1337ebccf1e3SJoseph Koshy __P4MASK(mem-type1, 12), 1338ebccf1e3SJoseph Koshy __P4MASK(mem-type2, 13), 1339ebccf1e3SJoseph Koshy NULLMASK 1340ebccf1e3SJoseph Koshy }; 1341ebccf1e3SJoseph Koshy 1342ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_sia[] = { /* sse input assist */ 1343ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1344ebccf1e3SJoseph Koshy NULLMASK 1345ebccf1e3SJoseph Koshy }; 1346ebccf1e3SJoseph Koshy 1347ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_psu[] = { /* packed sp uop */ 1348ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1349ebccf1e3SJoseph Koshy NULLMASK 1350ebccf1e3SJoseph Koshy }; 1351ebccf1e3SJoseph Koshy 1352ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_pdu[] = { /* packed dp uop */ 1353ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1354ebccf1e3SJoseph Koshy NULLMASK 1355ebccf1e3SJoseph Koshy }; 1356ebccf1e3SJoseph Koshy 1357ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ssu[] = { /* scalar sp uop */ 1358ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1359ebccf1e3SJoseph Koshy NULLMASK 1360ebccf1e3SJoseph Koshy }; 1361ebccf1e3SJoseph Koshy 1362ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_sdu[] = { /* scalar dp uop */ 1363ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1364ebccf1e3SJoseph Koshy NULLMASK 1365ebccf1e3SJoseph Koshy }; 1366ebccf1e3SJoseph Koshy 1367ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_64bmu[] = { /* 64 bit mmx uop */ 1368ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1369ebccf1e3SJoseph Koshy NULLMASK 1370ebccf1e3SJoseph Koshy }; 1371ebccf1e3SJoseph Koshy 1372ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_128bmu[] = { /* 128 bit mmx uop */ 1373ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1374ebccf1e3SJoseph Koshy NULLMASK 1375ebccf1e3SJoseph Koshy }; 1376ebccf1e3SJoseph Koshy 1377ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xfu[] = { /* X87 fp uop */ 1378ebccf1e3SJoseph Koshy __P4MASK(all, 15), 1379ebccf1e3SJoseph Koshy NULLMASK 1380ebccf1e3SJoseph Koshy }; 1381ebccf1e3SJoseph Koshy 1382ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xsmu[] = { /* x87 simd moves uop */ 1383ebccf1e3SJoseph Koshy __P4MASK(allp0, 3), 1384ebccf1e3SJoseph Koshy __P4MASK(allp2, 4), 1385ebccf1e3SJoseph Koshy NULLMASK 1386ebccf1e3SJoseph Koshy }; 1387ebccf1e3SJoseph Koshy 1388ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_gpe[] = { /* global power events */ 1389ebccf1e3SJoseph Koshy __P4MASK(running, 0), 1390ebccf1e3SJoseph Koshy NULLMASK 1391ebccf1e3SJoseph Koshy }; 1392ebccf1e3SJoseph Koshy 1393ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_tmx[] = { /* TC ms xfer */ 1394ebccf1e3SJoseph Koshy __P4MASK(cisc, 0), 1395ebccf1e3SJoseph Koshy NULLMASK 1396ebccf1e3SJoseph Koshy }; 1397ebccf1e3SJoseph Koshy 1398ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_uqw[] = { /* uop queue writes */ 1399ebccf1e3SJoseph Koshy __P4MASK(from-tc-build, 0), 1400ebccf1e3SJoseph Koshy __P4MASK(from-tc-deliver, 1), 1401ebccf1e3SJoseph Koshy __P4MASK(from-rom, 2), 1402ebccf1e3SJoseph Koshy NULLMASK 1403ebccf1e3SJoseph Koshy }; 1404ebccf1e3SJoseph Koshy 1405d56c5d4bSJoseph Koshy static const struct pmc_masks p4_mask_rmbt[] = { 1406d56c5d4bSJoseph Koshy /* retired mispred branch type */ 1407ebccf1e3SJoseph Koshy __P4MASK(conditional, 1), 1408ebccf1e3SJoseph Koshy __P4MASK(call, 2), 1409ebccf1e3SJoseph Koshy __P4MASK(return, 3), 1410ebccf1e3SJoseph Koshy __P4MASK(indirect, 4), 1411ebccf1e3SJoseph Koshy NULLMASK 1412ebccf1e3SJoseph Koshy }; 1413ebccf1e3SJoseph Koshy 1414ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_rbt[] = { /* retired branch type */ 1415ebccf1e3SJoseph Koshy __P4MASK(conditional, 1), 1416ebccf1e3SJoseph Koshy __P4MASK(call, 2), 1417ebccf1e3SJoseph Koshy __P4MASK(retired, 3), 1418ebccf1e3SJoseph Koshy __P4MASK(indirect, 4), 1419ebccf1e3SJoseph Koshy NULLMASK 1420ebccf1e3SJoseph Koshy }; 1421ebccf1e3SJoseph Koshy 1422ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_rs[] = { /* resource stall */ 1423ebccf1e3SJoseph Koshy __P4MASK(sbfull, 5), 1424ebccf1e3SJoseph Koshy NULLMASK 1425ebccf1e3SJoseph Koshy }; 1426ebccf1e3SJoseph Koshy 1427ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_wb[] = { /* WC buffer */ 1428ebccf1e3SJoseph Koshy __P4MASK(wcb-evicts, 0), 1429ebccf1e3SJoseph Koshy __P4MASK(wcb-full-evict, 1), 1430ebccf1e3SJoseph Koshy NULLMASK 1431ebccf1e3SJoseph Koshy }; 1432ebccf1e3SJoseph Koshy 1433ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_fee[] = { /* front end event */ 1434ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1435ebccf1e3SJoseph Koshy __P4MASK(bogus, 1), 1436ebccf1e3SJoseph Koshy NULLMASK 1437ebccf1e3SJoseph Koshy }; 1438ebccf1e3SJoseph Koshy 1439ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ee[] = { /* execution event */ 1440ebccf1e3SJoseph Koshy __P4MASK(nbogus0, 0), 1441ebccf1e3SJoseph Koshy __P4MASK(nbogus1, 1), 1442ebccf1e3SJoseph Koshy __P4MASK(nbogus2, 2), 1443ebccf1e3SJoseph Koshy __P4MASK(nbogus3, 3), 1444ebccf1e3SJoseph Koshy __P4MASK(bogus0, 4), 1445ebccf1e3SJoseph Koshy __P4MASK(bogus1, 5), 1446ebccf1e3SJoseph Koshy __P4MASK(bogus2, 6), 1447ebccf1e3SJoseph Koshy __P4MASK(bogus3, 7), 1448ebccf1e3SJoseph Koshy NULLMASK 1449ebccf1e3SJoseph Koshy }; 1450ebccf1e3SJoseph Koshy 1451ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_re[] = { /* replay event */ 1452ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1453ebccf1e3SJoseph Koshy __P4MASK(bogus, 1), 1454ebccf1e3SJoseph Koshy NULLMASK 1455ebccf1e3SJoseph Koshy }; 1456ebccf1e3SJoseph Koshy 1457ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_insret[] = { /* instr retired */ 1458ebccf1e3SJoseph Koshy __P4MASK(nbogusntag, 0), 1459ebccf1e3SJoseph Koshy __P4MASK(nbogustag, 1), 1460ebccf1e3SJoseph Koshy __P4MASK(bogusntag, 2), 1461ebccf1e3SJoseph Koshy __P4MASK(bogustag, 3), 1462ebccf1e3SJoseph Koshy NULLMASK 1463ebccf1e3SJoseph Koshy }; 1464ebccf1e3SJoseph Koshy 1465ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ur[] = { /* uops retired */ 1466ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1467ebccf1e3SJoseph Koshy __P4MASK(bogus, 1), 1468ebccf1e3SJoseph Koshy NULLMASK 1469ebccf1e3SJoseph Koshy }; 1470ebccf1e3SJoseph Koshy 1471ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ut[] = { /* uop type */ 1472ebccf1e3SJoseph Koshy __P4MASK(tagloads, 1), 1473ebccf1e3SJoseph Koshy __P4MASK(tagstores, 2), 1474ebccf1e3SJoseph Koshy NULLMASK 1475ebccf1e3SJoseph Koshy }; 1476ebccf1e3SJoseph Koshy 1477ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_br[] = { /* branch retired */ 1478ebccf1e3SJoseph Koshy __P4MASK(mmnp, 0), 1479ebccf1e3SJoseph Koshy __P4MASK(mmnm, 1), 1480ebccf1e3SJoseph Koshy __P4MASK(mmtp, 2), 1481ebccf1e3SJoseph Koshy __P4MASK(mmtm, 3), 1482ebccf1e3SJoseph Koshy NULLMASK 1483ebccf1e3SJoseph Koshy }; 1484ebccf1e3SJoseph Koshy 1485ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_mbr[] = { /* mispred branch retired */ 1486ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1487ebccf1e3SJoseph Koshy NULLMASK 1488ebccf1e3SJoseph Koshy }; 1489ebccf1e3SJoseph Koshy 1490ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xa[] = { /* x87 assist */ 1491ebccf1e3SJoseph Koshy __P4MASK(fpsu, 0), 1492ebccf1e3SJoseph Koshy __P4MASK(fpso, 1), 1493ebccf1e3SJoseph Koshy __P4MASK(poao, 2), 1494ebccf1e3SJoseph Koshy __P4MASK(poau, 3), 1495ebccf1e3SJoseph Koshy __P4MASK(prea, 4), 1496ebccf1e3SJoseph Koshy NULLMASK 1497ebccf1e3SJoseph Koshy }; 1498ebccf1e3SJoseph Koshy 1499ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_machclr[] = { /* machine clear */ 1500ebccf1e3SJoseph Koshy __P4MASK(clear, 0), 1501ebccf1e3SJoseph Koshy __P4MASK(moclear, 2), 1502ebccf1e3SJoseph Koshy __P4MASK(smclear, 3), 1503ebccf1e3SJoseph Koshy NULLMASK 1504ebccf1e3SJoseph Koshy }; 1505ebccf1e3SJoseph Koshy 1506ebccf1e3SJoseph Koshy /* P4 event parser */ 1507ebccf1e3SJoseph Koshy static int 1508ebccf1e3SJoseph Koshy p4_allocate_pmc(enum pmc_event pe, char *ctrspec, 1509ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 1510ebccf1e3SJoseph Koshy { 1511ebccf1e3SJoseph Koshy 1512ebccf1e3SJoseph Koshy char *e, *p, *q; 1513ebccf1e3SJoseph Koshy int count, has_tag, has_busreqtype, n; 1514ebccf1e3SJoseph Koshy uint32_t evmask, cccractivemask; 1515ebccf1e3SJoseph Koshy const struct pmc_masks *pm, *pmask; 1516ebccf1e3SJoseph Koshy 1517789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1518f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig = 1519f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 0; 1520ebccf1e3SJoseph Koshy 1521ebccf1e3SJoseph Koshy pmask = NULL; 1522ebccf1e3SJoseph Koshy evmask = 0; 1523ebccf1e3SJoseph Koshy cccractivemask = 0x3; 1524ebccf1e3SJoseph Koshy has_tag = has_busreqtype = 0; 1525ebccf1e3SJoseph Koshy 1526ebccf1e3SJoseph Koshy #define __P4SETMASK(M) do { \ 1527ebccf1e3SJoseph Koshy pmask = p4_mask_##M; \ 1528ebccf1e3SJoseph Koshy } while (0) 1529ebccf1e3SJoseph Koshy 1530ebccf1e3SJoseph Koshy switch (pe) { 1531ebccf1e3SJoseph Koshy case PMC_EV_P4_TC_DELIVER_MODE: 1532ebccf1e3SJoseph Koshy __P4SETMASK(tcdm); 1533ebccf1e3SJoseph Koshy break; 1534ebccf1e3SJoseph Koshy case PMC_EV_P4_BPU_FETCH_REQUEST: 1535ebccf1e3SJoseph Koshy __P4SETMASK(bfr); 1536ebccf1e3SJoseph Koshy break; 1537ebccf1e3SJoseph Koshy case PMC_EV_P4_ITLB_REFERENCE: 1538ebccf1e3SJoseph Koshy __P4SETMASK(ir); 1539ebccf1e3SJoseph Koshy break; 1540ebccf1e3SJoseph Koshy case PMC_EV_P4_MEMORY_CANCEL: 1541ebccf1e3SJoseph Koshy __P4SETMASK(memcan); 1542ebccf1e3SJoseph Koshy break; 1543ebccf1e3SJoseph Koshy case PMC_EV_P4_MEMORY_COMPLETE: 1544ebccf1e3SJoseph Koshy __P4SETMASK(memcomp); 1545ebccf1e3SJoseph Koshy break; 1546ebccf1e3SJoseph Koshy case PMC_EV_P4_LOAD_PORT_REPLAY: 1547ebccf1e3SJoseph Koshy __P4SETMASK(lpr); 1548ebccf1e3SJoseph Koshy break; 1549ebccf1e3SJoseph Koshy case PMC_EV_P4_STORE_PORT_REPLAY: 1550ebccf1e3SJoseph Koshy __P4SETMASK(spr); 1551ebccf1e3SJoseph Koshy break; 1552ebccf1e3SJoseph Koshy case PMC_EV_P4_MOB_LOAD_REPLAY: 1553ebccf1e3SJoseph Koshy __P4SETMASK(mlr); 1554ebccf1e3SJoseph Koshy break; 1555ebccf1e3SJoseph Koshy case PMC_EV_P4_PAGE_WALK_TYPE: 1556ebccf1e3SJoseph Koshy __P4SETMASK(pwt); 1557ebccf1e3SJoseph Koshy break; 1558ebccf1e3SJoseph Koshy case PMC_EV_P4_BSQ_CACHE_REFERENCE: 1559ebccf1e3SJoseph Koshy __P4SETMASK(bcr); 1560ebccf1e3SJoseph Koshy break; 1561ebccf1e3SJoseph Koshy case PMC_EV_P4_IOQ_ALLOCATION: 1562ebccf1e3SJoseph Koshy __P4SETMASK(ia); 1563ebccf1e3SJoseph Koshy has_busreqtype = 1; 1564ebccf1e3SJoseph Koshy break; 1565ebccf1e3SJoseph Koshy case PMC_EV_P4_IOQ_ACTIVE_ENTRIES: 1566ebccf1e3SJoseph Koshy __P4SETMASK(iae); 1567ebccf1e3SJoseph Koshy has_busreqtype = 1; 1568ebccf1e3SJoseph Koshy break; 1569ebccf1e3SJoseph Koshy case PMC_EV_P4_FSB_DATA_ACTIVITY: 1570ebccf1e3SJoseph Koshy __P4SETMASK(fda); 1571ebccf1e3SJoseph Koshy break; 1572ebccf1e3SJoseph Koshy case PMC_EV_P4_BSQ_ALLOCATION: 1573ebccf1e3SJoseph Koshy __P4SETMASK(ba); 1574ebccf1e3SJoseph Koshy break; 1575ebccf1e3SJoseph Koshy case PMC_EV_P4_SSE_INPUT_ASSIST: 1576ebccf1e3SJoseph Koshy __P4SETMASK(sia); 1577ebccf1e3SJoseph Koshy break; 1578ebccf1e3SJoseph Koshy case PMC_EV_P4_PACKED_SP_UOP: 1579ebccf1e3SJoseph Koshy __P4SETMASK(psu); 1580ebccf1e3SJoseph Koshy break; 1581ebccf1e3SJoseph Koshy case PMC_EV_P4_PACKED_DP_UOP: 1582ebccf1e3SJoseph Koshy __P4SETMASK(pdu); 1583ebccf1e3SJoseph Koshy break; 1584ebccf1e3SJoseph Koshy case PMC_EV_P4_SCALAR_SP_UOP: 1585ebccf1e3SJoseph Koshy __P4SETMASK(ssu); 1586ebccf1e3SJoseph Koshy break; 1587ebccf1e3SJoseph Koshy case PMC_EV_P4_SCALAR_DP_UOP: 1588ebccf1e3SJoseph Koshy __P4SETMASK(sdu); 1589ebccf1e3SJoseph Koshy break; 1590ebccf1e3SJoseph Koshy case PMC_EV_P4_64BIT_MMX_UOP: 1591ebccf1e3SJoseph Koshy __P4SETMASK(64bmu); 1592ebccf1e3SJoseph Koshy break; 1593ebccf1e3SJoseph Koshy case PMC_EV_P4_128BIT_MMX_UOP: 1594ebccf1e3SJoseph Koshy __P4SETMASK(128bmu); 1595ebccf1e3SJoseph Koshy break; 1596ebccf1e3SJoseph Koshy case PMC_EV_P4_X87_FP_UOP: 1597ebccf1e3SJoseph Koshy __P4SETMASK(xfu); 1598ebccf1e3SJoseph Koshy break; 1599ebccf1e3SJoseph Koshy case PMC_EV_P4_X87_SIMD_MOVES_UOP: 1600ebccf1e3SJoseph Koshy __P4SETMASK(xsmu); 1601ebccf1e3SJoseph Koshy break; 1602ebccf1e3SJoseph Koshy case PMC_EV_P4_GLOBAL_POWER_EVENTS: 1603ebccf1e3SJoseph Koshy __P4SETMASK(gpe); 1604ebccf1e3SJoseph Koshy break; 1605ebccf1e3SJoseph Koshy case PMC_EV_P4_TC_MS_XFER: 1606ebccf1e3SJoseph Koshy __P4SETMASK(tmx); 1607ebccf1e3SJoseph Koshy break; 1608ebccf1e3SJoseph Koshy case PMC_EV_P4_UOP_QUEUE_WRITES: 1609ebccf1e3SJoseph Koshy __P4SETMASK(uqw); 1610ebccf1e3SJoseph Koshy break; 1611ebccf1e3SJoseph Koshy case PMC_EV_P4_RETIRED_MISPRED_BRANCH_TYPE: 1612ebccf1e3SJoseph Koshy __P4SETMASK(rmbt); 1613ebccf1e3SJoseph Koshy break; 1614ebccf1e3SJoseph Koshy case PMC_EV_P4_RETIRED_BRANCH_TYPE: 1615ebccf1e3SJoseph Koshy __P4SETMASK(rbt); 1616ebccf1e3SJoseph Koshy break; 1617ebccf1e3SJoseph Koshy case PMC_EV_P4_RESOURCE_STALL: 1618ebccf1e3SJoseph Koshy __P4SETMASK(rs); 1619ebccf1e3SJoseph Koshy break; 1620ebccf1e3SJoseph Koshy case PMC_EV_P4_WC_BUFFER: 1621ebccf1e3SJoseph Koshy __P4SETMASK(wb); 1622ebccf1e3SJoseph Koshy break; 1623ebccf1e3SJoseph Koshy case PMC_EV_P4_BSQ_ACTIVE_ENTRIES: 1624ebccf1e3SJoseph Koshy case PMC_EV_P4_B2B_CYCLES: 1625ebccf1e3SJoseph Koshy case PMC_EV_P4_BNR: 1626ebccf1e3SJoseph Koshy case PMC_EV_P4_SNOOP: 1627ebccf1e3SJoseph Koshy case PMC_EV_P4_RESPONSE: 1628ebccf1e3SJoseph Koshy break; 1629ebccf1e3SJoseph Koshy case PMC_EV_P4_FRONT_END_EVENT: 1630ebccf1e3SJoseph Koshy __P4SETMASK(fee); 1631ebccf1e3SJoseph Koshy break; 1632ebccf1e3SJoseph Koshy case PMC_EV_P4_EXECUTION_EVENT: 1633ebccf1e3SJoseph Koshy __P4SETMASK(ee); 1634ebccf1e3SJoseph Koshy break; 1635ebccf1e3SJoseph Koshy case PMC_EV_P4_REPLAY_EVENT: 1636ebccf1e3SJoseph Koshy __P4SETMASK(re); 1637ebccf1e3SJoseph Koshy break; 1638ebccf1e3SJoseph Koshy case PMC_EV_P4_INSTR_RETIRED: 1639ebccf1e3SJoseph Koshy __P4SETMASK(insret); 1640ebccf1e3SJoseph Koshy break; 1641ebccf1e3SJoseph Koshy case PMC_EV_P4_UOPS_RETIRED: 1642ebccf1e3SJoseph Koshy __P4SETMASK(ur); 1643ebccf1e3SJoseph Koshy break; 1644ebccf1e3SJoseph Koshy case PMC_EV_P4_UOP_TYPE: 1645ebccf1e3SJoseph Koshy __P4SETMASK(ut); 1646ebccf1e3SJoseph Koshy break; 1647ebccf1e3SJoseph Koshy case PMC_EV_P4_BRANCH_RETIRED: 1648ebccf1e3SJoseph Koshy __P4SETMASK(br); 1649ebccf1e3SJoseph Koshy break; 1650ebccf1e3SJoseph Koshy case PMC_EV_P4_MISPRED_BRANCH_RETIRED: 1651ebccf1e3SJoseph Koshy __P4SETMASK(mbr); 1652ebccf1e3SJoseph Koshy break; 1653ebccf1e3SJoseph Koshy case PMC_EV_P4_X87_ASSIST: 1654ebccf1e3SJoseph Koshy __P4SETMASK(xa); 1655ebccf1e3SJoseph Koshy break; 1656ebccf1e3SJoseph Koshy case PMC_EV_P4_MACHINE_CLEAR: 1657ebccf1e3SJoseph Koshy __P4SETMASK(machclr); 1658ebccf1e3SJoseph Koshy break; 1659ebccf1e3SJoseph Koshy default: 1660aa342b1fSJoseph Koshy return (-1); 1661ebccf1e3SJoseph Koshy } 1662ebccf1e3SJoseph Koshy 1663ebccf1e3SJoseph Koshy /* process additional flags */ 1664ebccf1e3SJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 1665ebccf1e3SJoseph Koshy if (KWPREFIXMATCH(p, P4_KW_ACTIVE)) { 1666ebccf1e3SJoseph Koshy q = strchr(p, '='); 1667ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1668aa342b1fSJoseph Koshy return (-1); 1669ebccf1e3SJoseph Koshy 1670789140c0SJoseph Koshy if (strcasecmp(q, P4_KW_ACTIVE_NONE) == 0) 1671ebccf1e3SJoseph Koshy cccractivemask = 0x0; 1672789140c0SJoseph Koshy else if (strcasecmp(q, P4_KW_ACTIVE_SINGLE) == 0) 1673ebccf1e3SJoseph Koshy cccractivemask = 0x1; 1674789140c0SJoseph Koshy else if (strcasecmp(q, P4_KW_ACTIVE_BOTH) == 0) 1675ebccf1e3SJoseph Koshy cccractivemask = 0x2; 1676789140c0SJoseph Koshy else if (strcasecmp(q, P4_KW_ACTIVE_ANY) == 0) 1677ebccf1e3SJoseph Koshy cccractivemask = 0x3; 1678ebccf1e3SJoseph Koshy else 1679aa342b1fSJoseph Koshy return (-1); 1680ebccf1e3SJoseph Koshy 1681ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, P4_KW_BUSREQTYPE)) { 1682ebccf1e3SJoseph Koshy if (has_busreqtype == 0) 1683aa342b1fSJoseph Koshy return (-1); 1684ebccf1e3SJoseph Koshy 1685ebccf1e3SJoseph Koshy q = strchr(p, '='); 1686ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1687aa342b1fSJoseph Koshy return (-1); 1688ebccf1e3SJoseph Koshy 1689ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 1690ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 1691aa342b1fSJoseph Koshy return (-1); 1692ebccf1e3SJoseph Koshy evmask = (evmask & ~0x1F) | (count & 0x1F); 1693ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P4_KW_CASCADE)) 1694ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_CASCADE; 1695ebccf1e3SJoseph Koshy else if (KWMATCH(p, P4_KW_EDGE)) 1696ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1697ebccf1e3SJoseph Koshy else if (KWMATCH(p, P4_KW_INV)) 1698ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 1699ebccf1e3SJoseph Koshy else if (KWPREFIXMATCH(p, P4_KW_MASK "=")) { 1700ebccf1e3SJoseph Koshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 1701aa342b1fSJoseph Koshy return (-1); 1702ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1703ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P4_KW_OS)) 1704ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 1705ebccf1e3SJoseph Koshy else if (KWMATCH(p, P4_KW_PRECISE)) 1706ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_PRECISE; 1707ebccf1e3SJoseph Koshy else if (KWPREFIXMATCH(p, P4_KW_TAG "=")) { 1708ebccf1e3SJoseph Koshy if (has_tag == 0) 1709aa342b1fSJoseph Koshy return (-1); 1710ebccf1e3SJoseph Koshy 1711ebccf1e3SJoseph Koshy q = strchr(p, '='); 1712ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1713aa342b1fSJoseph Koshy return (-1); 1714ebccf1e3SJoseph Koshy 1715ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 1716ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 1717aa342b1fSJoseph Koshy return (-1); 1718ebccf1e3SJoseph Koshy 1719ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_TAGGING; 1720f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig |= 1721ebccf1e3SJoseph Koshy P4_ESCR_TO_TAG_VALUE(count); 1722ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, P4_KW_THRESHOLD "=")) { 1723ebccf1e3SJoseph Koshy q = strchr(p, '='); 1724ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1725aa342b1fSJoseph Koshy return (-1); 1726ebccf1e3SJoseph Koshy 1727ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 1728ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 1729aa342b1fSJoseph Koshy return (-1); 1730ebccf1e3SJoseph Koshy 1731ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 1732f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig &= 1733f263522aSJoseph Koshy ~P4_CCCR_THRESHOLD_MASK; 1734f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |= 1735f263522aSJoseph Koshy P4_CCCR_TO_THRESHOLD(count); 1736ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P4_KW_USR)) 1737ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 1738ebccf1e3SJoseph Koshy else 1739aa342b1fSJoseph Koshy return (-1); 1740ebccf1e3SJoseph Koshy } 1741ebccf1e3SJoseph Koshy 1742ebccf1e3SJoseph Koshy /* other post processing */ 1743ebccf1e3SJoseph Koshy if (pe == PMC_EV_P4_IOQ_ALLOCATION || 1744ebccf1e3SJoseph Koshy pe == PMC_EV_P4_FSB_DATA_ACTIVITY || 1745ebccf1e3SJoseph Koshy pe == PMC_EV_P4_BSQ_ALLOCATION) 1746ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1747ebccf1e3SJoseph Koshy 1748ebccf1e3SJoseph Koshy /* fill in thread activity mask */ 1749f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |= 1750ebccf1e3SJoseph Koshy P4_CCCR_TO_ACTIVE_THREAD(cccractivemask); 1751ebccf1e3SJoseph Koshy 1752ebccf1e3SJoseph Koshy if (evmask) 1753ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1754ebccf1e3SJoseph Koshy 1755ebccf1e3SJoseph Koshy switch (pe) { 1756ebccf1e3SJoseph Koshy case PMC_EV_P4_FSB_DATA_ACTIVITY: 1757ebccf1e3SJoseph Koshy if ((evmask & 0x06) == 0x06 || 1758ebccf1e3SJoseph Koshy (evmask & 0x18) == 0x18) 1759aa342b1fSJoseph Koshy return (-1); /* can't have own+other bits together */ 1760ebccf1e3SJoseph Koshy if (evmask == 0) /* default:drdy-{drv,own}+dbsy{drv,own} */ 1761ebccf1e3SJoseph Koshy evmask = 0x1D; 1762ebccf1e3SJoseph Koshy break; 1763ebccf1e3SJoseph Koshy case PMC_EV_P4_MACHINE_CLEAR: 1764ebccf1e3SJoseph Koshy /* only one bit is allowed to be set */ 1765ebccf1e3SJoseph Koshy if ((evmask & (evmask - 1)) != 0) 1766aa342b1fSJoseph Koshy return (-1); 1767ebccf1e3SJoseph Koshy if (evmask == 0) { 1768ebccf1e3SJoseph Koshy evmask = 0x1; /* 'CLEAR' */ 1769ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1770ebccf1e3SJoseph Koshy } 1771ebccf1e3SJoseph Koshy break; 1772ebccf1e3SJoseph Koshy default: 1773ebccf1e3SJoseph Koshy if (evmask == 0 && pmask) { 1774ebccf1e3SJoseph Koshy for (pm = pmask; pm->pm_name; pm++) 1775ebccf1e3SJoseph Koshy evmask |= pm->pm_value; 1776ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1777ebccf1e3SJoseph Koshy } 1778ebccf1e3SJoseph Koshy } 1779ebccf1e3SJoseph Koshy 1780f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 1781f263522aSJoseph Koshy P4_ESCR_TO_EVENT_MASK(evmask); 1782ebccf1e3SJoseph Koshy 1783aa342b1fSJoseph Koshy return (0); 1784ebccf1e3SJoseph Koshy } 1785ebccf1e3SJoseph Koshy 178686a65549SJoseph Koshy #endif 178786a65549SJoseph Koshy 178886a65549SJoseph Koshy #if defined(__i386__) 178986a65549SJoseph Koshy 1790ebccf1e3SJoseph Koshy /* 1791f263522aSJoseph Koshy * Pentium style PMCs 1792f263522aSJoseph Koshy */ 1793f263522aSJoseph Koshy 1794f263522aSJoseph Koshy static struct pmc_event_alias p5_aliases[] = { 17950b9b757dSJoseph Koshy EV_ALIAS("branches", "p5-taken-branches"), 1796f263522aSJoseph Koshy EV_ALIAS("cycles", "tsc"), 17970b9b757dSJoseph Koshy EV_ALIAS("dc-misses", "p5-data-read-miss-or-write-miss"), 17980b9b757dSJoseph Koshy EV_ALIAS("ic-misses", "p5-code-cache-miss"), 17990b9b757dSJoseph Koshy EV_ALIAS("instructions", "p5-instructions-executed"), 18000b9b757dSJoseph Koshy EV_ALIAS("interrupts", "p5-hardware-interrupts"), 18010b9b757dSJoseph Koshy EV_ALIAS("unhalted-cycles", 18020b9b757dSJoseph Koshy "p5-number-of-cycles-not-in-halt-state"), 1803f263522aSJoseph Koshy EV_ALIAS(NULL, NULL) 1804f263522aSJoseph Koshy }; 1805f263522aSJoseph Koshy 1806f263522aSJoseph Koshy static int 1807f263522aSJoseph Koshy p5_allocate_pmc(enum pmc_event pe, char *ctrspec, 1808f263522aSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 1809f263522aSJoseph Koshy { 1810aa342b1fSJoseph Koshy return (-1 || pe || ctrspec || pmc_config); /* shut up gcc */ 1811f263522aSJoseph Koshy } 1812f263522aSJoseph Koshy 1813f263522aSJoseph Koshy /* 1814ebccf1e3SJoseph Koshy * Pentium Pro style PMCs. These PMCs are found in Pentium II, Pentium III, 1815ebccf1e3SJoseph Koshy * and Pentium M CPUs. 1816ebccf1e3SJoseph Koshy */ 1817ebccf1e3SJoseph Koshy 1818ebccf1e3SJoseph Koshy static struct pmc_event_alias p6_aliases[] = { 1819ebccf1e3SJoseph Koshy EV_ALIAS("branches", "p6-br-inst-retired"), 1820ebccf1e3SJoseph Koshy EV_ALIAS("branch-mispredicts", "p6-br-miss-pred-retired"), 1821ebccf1e3SJoseph Koshy EV_ALIAS("cycles", "tsc"), 1822d56c5d4bSJoseph Koshy EV_ALIAS("dc-misses", "p6-dcu-lines-in"), 182373e2d811SJoseph Koshy EV_ALIAS("ic-misses", "p6-ifu-fetch-miss"), 1824ebccf1e3SJoseph Koshy EV_ALIAS("instructions", "p6-inst-retired"), 1825ebccf1e3SJoseph Koshy EV_ALIAS("interrupts", "p6-hw-int-rx"), 1826177a2f22SJoseph Koshy EV_ALIAS("unhalted-cycles", "p6-cpu-clk-unhalted"), 1827ebccf1e3SJoseph Koshy EV_ALIAS(NULL, NULL) 1828ebccf1e3SJoseph Koshy }; 1829ebccf1e3SJoseph Koshy 1830ebccf1e3SJoseph Koshy #define P6_KW_CMASK "cmask" 1831ebccf1e3SJoseph Koshy #define P6_KW_EDGE "edge" 1832ebccf1e3SJoseph Koshy #define P6_KW_INV "inv" 1833ebccf1e3SJoseph Koshy #define P6_KW_OS "os" 1834ebccf1e3SJoseph Koshy #define P6_KW_UMASK "umask" 1835ebccf1e3SJoseph Koshy #define P6_KW_USR "usr" 1836ebccf1e3SJoseph Koshy 1837ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mesi[] = { 1838ebccf1e3SJoseph Koshy PMCMASK(m, 0x01), 1839ebccf1e3SJoseph Koshy PMCMASK(e, 0x02), 1840ebccf1e3SJoseph Koshy PMCMASK(s, 0x04), 1841ebccf1e3SJoseph Koshy PMCMASK(i, 0x08), 1842ebccf1e3SJoseph Koshy NULLMASK 1843ebccf1e3SJoseph Koshy }; 1844ebccf1e3SJoseph Koshy 1845ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mesihw[] = { 1846ebccf1e3SJoseph Koshy PMCMASK(m, 0x01), 1847ebccf1e3SJoseph Koshy PMCMASK(e, 0x02), 1848ebccf1e3SJoseph Koshy PMCMASK(s, 0x04), 1849ebccf1e3SJoseph Koshy PMCMASK(i, 0x08), 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_hw[] = { 1857ebccf1e3SJoseph Koshy PMCMASK(nonhw, 0x00), 1858ebccf1e3SJoseph Koshy PMCMASK(hw, 0x10), 1859ebccf1e3SJoseph Koshy PMCMASK(both, 0x30), 1860ebccf1e3SJoseph Koshy NULLMASK 1861ebccf1e3SJoseph Koshy }; 1862ebccf1e3SJoseph Koshy 1863ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_any[] = { 1864ebccf1e3SJoseph Koshy PMCMASK(self, 0x00), 1865ebccf1e3SJoseph Koshy PMCMASK(any, 0x20), 1866ebccf1e3SJoseph Koshy NULLMASK 1867ebccf1e3SJoseph Koshy }; 1868ebccf1e3SJoseph Koshy 1869ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_ekp[] = { 1870ebccf1e3SJoseph Koshy PMCMASK(nta, 0x00), 1871ebccf1e3SJoseph Koshy PMCMASK(t1, 0x01), 1872ebccf1e3SJoseph Koshy PMCMASK(t2, 0x02), 1873ebccf1e3SJoseph Koshy PMCMASK(wos, 0x03), 1874ebccf1e3SJoseph Koshy NULLMASK 1875ebccf1e3SJoseph Koshy }; 1876ebccf1e3SJoseph Koshy 1877ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_pps[] = { 1878ebccf1e3SJoseph Koshy PMCMASK(packed-and-scalar, 0x00), 1879ebccf1e3SJoseph Koshy PMCMASK(scalar, 0x01), 1880ebccf1e3SJoseph Koshy NULLMASK 1881ebccf1e3SJoseph Koshy }; 1882ebccf1e3SJoseph Koshy 1883ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mite[] = { 1884ebccf1e3SJoseph Koshy PMCMASK(packed-multiply, 0x01), 1885ebccf1e3SJoseph Koshy PMCMASK(packed-shift, 0x02), 1886ebccf1e3SJoseph Koshy PMCMASK(pack, 0x04), 1887ebccf1e3SJoseph Koshy PMCMASK(unpack, 0x08), 1888ebccf1e3SJoseph Koshy PMCMASK(packed-logical, 0x10), 1889ebccf1e3SJoseph Koshy PMCMASK(packed-arithmetic, 0x20), 1890ebccf1e3SJoseph Koshy NULLMASK 1891ebccf1e3SJoseph Koshy }; 1892ebccf1e3SJoseph Koshy 1893ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_fmt[] = { 1894ebccf1e3SJoseph Koshy PMCMASK(mmxtofp, 0x00), 1895ebccf1e3SJoseph Koshy PMCMASK(fptommx, 0x01), 1896ebccf1e3SJoseph Koshy NULLMASK 1897ebccf1e3SJoseph Koshy }; 1898ebccf1e3SJoseph Koshy 1899ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_sr[] = { 1900ebccf1e3SJoseph Koshy PMCMASK(es, 0x01), 1901ebccf1e3SJoseph Koshy PMCMASK(ds, 0x02), 1902ebccf1e3SJoseph Koshy PMCMASK(fs, 0x04), 1903ebccf1e3SJoseph Koshy PMCMASK(gs, 0x08), 1904ebccf1e3SJoseph Koshy NULLMASK 1905ebccf1e3SJoseph Koshy }; 1906ebccf1e3SJoseph Koshy 1907ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_eet[] = { 1908ebccf1e3SJoseph Koshy PMCMASK(all, 0x00), 1909ebccf1e3SJoseph Koshy PMCMASK(freq, 0x02), 1910ebccf1e3SJoseph Koshy NULLMASK 1911ebccf1e3SJoseph Koshy }; 1912ebccf1e3SJoseph Koshy 1913ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_efur[] = { 1914ebccf1e3SJoseph Koshy PMCMASK(all, 0x00), 1915ebccf1e3SJoseph Koshy PMCMASK(loadop, 0x01), 1916ebccf1e3SJoseph Koshy PMCMASK(stdsta, 0x02), 1917ebccf1e3SJoseph Koshy NULLMASK 1918ebccf1e3SJoseph Koshy }; 1919ebccf1e3SJoseph Koshy 1920ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_essir[] = { 1921ebccf1e3SJoseph Koshy PMCMASK(sse-packed-single, 0x00), 1922ebccf1e3SJoseph Koshy PMCMASK(sse-packed-single-scalar-single, 0x01), 1923ebccf1e3SJoseph Koshy PMCMASK(sse2-packed-double, 0x02), 1924ebccf1e3SJoseph Koshy PMCMASK(sse2-scalar-double, 0x03), 1925ebccf1e3SJoseph Koshy NULLMASK 1926ebccf1e3SJoseph Koshy }; 1927ebccf1e3SJoseph Koshy 1928ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_esscir[] = { 1929ebccf1e3SJoseph Koshy PMCMASK(sse-packed-single, 0x00), 1930ebccf1e3SJoseph Koshy PMCMASK(sse-scalar-single, 0x01), 1931ebccf1e3SJoseph Koshy PMCMASK(sse2-packed-double, 0x02), 1932ebccf1e3SJoseph Koshy PMCMASK(sse2-scalar-double, 0x03), 1933ebccf1e3SJoseph Koshy NULLMASK 1934ebccf1e3SJoseph Koshy }; 1935ebccf1e3SJoseph Koshy 1936ebccf1e3SJoseph Koshy /* P6 event parser */ 1937ebccf1e3SJoseph Koshy static int 1938ebccf1e3SJoseph Koshy p6_allocate_pmc(enum pmc_event pe, char *ctrspec, 1939ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 1940ebccf1e3SJoseph Koshy { 1941ebccf1e3SJoseph Koshy char *e, *p, *q; 1942ebccf1e3SJoseph Koshy uint32_t evmask; 1943ebccf1e3SJoseph Koshy int count, n; 1944ebccf1e3SJoseph Koshy const struct pmc_masks *pm, *pmask; 1945ebccf1e3SJoseph Koshy 1946789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1947f263522aSJoseph Koshy pmc_config->pm_md.pm_ppro.pm_ppro_config = 0; 1948ebccf1e3SJoseph Koshy 1949ebccf1e3SJoseph Koshy evmask = 0; 1950ebccf1e3SJoseph Koshy 1951ebccf1e3SJoseph Koshy #define P6MASKSET(M) pmask = p6_mask_ ## M 1952ebccf1e3SJoseph Koshy 1953ebccf1e3SJoseph Koshy switch(pe) { 1954ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_IFETCH: P6MASKSET(mesi); break; 1955ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_LD: P6MASKSET(mesi); break; 1956ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_ST: P6MASKSET(mesi); break; 1957ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_RQSTS: P6MASKSET(mesi); break; 1958ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_DRDY_CLOCKS: 1959ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_LOCK_CLOCKS: 1960ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BRD: 1961ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_RFO: 1962ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_WB: 1963ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_IFETCH: 1964ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_INVAL: 1965ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_PWR: 1966ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_P: 1967ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_IO: 1968ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_DEF: 1969ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BURST: 1970ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_ANY: 1971ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_MEM: 1972ebccf1e3SJoseph Koshy P6MASKSET(any); break; 1973ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED: 1974ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_MISS: 1975ebccf1e3SJoseph Koshy P6MASKSET(ekp); break; 1976ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_INST_RETIRED: 1977ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_COMP_INST_RET: 1978ebccf1e3SJoseph Koshy P6MASKSET(pps); break; 1979ebccf1e3SJoseph Koshy case PMC_EV_P6_MMX_INSTR_TYPE_EXEC: 1980ebccf1e3SJoseph Koshy P6MASKSET(mite); break; 1981ebccf1e3SJoseph Koshy case PMC_EV_P6_FP_MMX_TRANS: 1982ebccf1e3SJoseph Koshy P6MASKSET(fmt); break; 1983ebccf1e3SJoseph Koshy case PMC_EV_P6_SEG_RENAME_STALLS: 1984ebccf1e3SJoseph Koshy case PMC_EV_P6_SEG_REG_RENAMES: 1985ebccf1e3SJoseph Koshy P6MASKSET(sr); break; 1986ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_EST_TRANS: 1987ebccf1e3SJoseph Koshy P6MASKSET(eet); break; 1988ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_FUSED_UOPS_RET: 1989ebccf1e3SJoseph Koshy P6MASKSET(efur); break; 1990ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED: 1991ebccf1e3SJoseph Koshy P6MASKSET(essir); break; 1992ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED: 1993ebccf1e3SJoseph Koshy P6MASKSET(esscir); break; 1994ebccf1e3SJoseph Koshy default: 1995ebccf1e3SJoseph Koshy pmask = NULL; 1996ebccf1e3SJoseph Koshy break; 1997ebccf1e3SJoseph Koshy } 1998ebccf1e3SJoseph Koshy 1999ebccf1e3SJoseph Koshy /* Pentium M PMCs have a few events with different semantics */ 2000ebccf1e3SJoseph Koshy if (cpu_info.pm_cputype == PMC_CPU_INTEL_PM) { 2001ebccf1e3SJoseph Koshy if (pe == PMC_EV_P6_L2_LD || 2002ebccf1e3SJoseph Koshy pe == PMC_EV_P6_L2_LINES_IN || 2003ebccf1e3SJoseph Koshy pe == PMC_EV_P6_L2_LINES_OUT) 2004ebccf1e3SJoseph Koshy P6MASKSET(mesihw); 2005ebccf1e3SJoseph Koshy else if (pe == PMC_EV_P6_L2_M_LINES_OUTM) 2006ebccf1e3SJoseph Koshy P6MASKSET(hw); 2007ebccf1e3SJoseph Koshy } 2008ebccf1e3SJoseph Koshy 2009ebccf1e3SJoseph Koshy /* Parse additional modifiers if present */ 2010ebccf1e3SJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 2011ebccf1e3SJoseph Koshy if (KWPREFIXMATCH(p, P6_KW_CMASK "=")) { 2012ebccf1e3SJoseph Koshy q = strchr(p, '='); 2013ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 2014aa342b1fSJoseph Koshy return (-1); 2015ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 2016ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 2017aa342b1fSJoseph Koshy return (-1); 2018ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 2019f263522aSJoseph Koshy pmc_config->pm_md.pm_ppro.pm_ppro_config |= 2020f263522aSJoseph Koshy P6_EVSEL_TO_CMASK(count); 2021ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_EDGE)) { 2022ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 2023ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_INV)) { 2024ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 2025ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_OS)) { 2026ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2027ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, P6_KW_UMASK "=")) { 2028ebccf1e3SJoseph Koshy evmask = 0; 2029ebccf1e3SJoseph Koshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 2030aa342b1fSJoseph Koshy return (-1); 2031ebccf1e3SJoseph Koshy if ((pe == PMC_EV_P6_BUS_DRDY_CLOCKS || 2032ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_LOCK_CLOCKS || 2033ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_BRD || 2034ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_RFO || 2035ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_IFETCH || 2036ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_INVAL || 2037ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_PWR || 2038ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_DEF || 2039ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_BURST || 2040ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_ANY || 2041ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_MEM || 2042ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRANS_IO || 2043ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRANS_P || 2044ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRANS_WB || 2045ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_EST_TRANS || 2046ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_FUSED_UOPS_RET || 2047ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_COMP_INST_RET || 2048ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_INST_RETIRED || 2049ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_PREF_DISPATCHED || 2050ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_PREF_MISS || 2051ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED || 2052ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED || 2053ebccf1e3SJoseph Koshy pe == PMC_EV_P6_FP_MMX_TRANS) 2054aa342b1fSJoseph Koshy && (n > 1)) /* Only one mask keyword is allowed. */ 2055aa342b1fSJoseph Koshy return (-1); 2056ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2057ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_USR)) { 2058ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 2059ebccf1e3SJoseph Koshy } else 2060aa342b1fSJoseph Koshy return (-1); 2061ebccf1e3SJoseph Koshy } 2062ebccf1e3SJoseph Koshy 2063ebccf1e3SJoseph Koshy /* post processing */ 2064ebccf1e3SJoseph Koshy switch (pe) { 2065ebccf1e3SJoseph Koshy 2066ebccf1e3SJoseph Koshy /* 2067ebccf1e3SJoseph Koshy * The following events default to an evmask of 0 2068ebccf1e3SJoseph Koshy */ 2069ebccf1e3SJoseph Koshy 2070ebccf1e3SJoseph Koshy /* default => 'self' */ 2071ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_DRDY_CLOCKS: 2072ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_LOCK_CLOCKS: 2073ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BRD: 2074ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_RFO: 2075ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_WB: 2076ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_IFETCH: 2077ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_INVAL: 2078ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_PWR: 2079ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_P: 2080ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_IO: 2081ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_DEF: 2082ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BURST: 2083ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_ANY: 2084ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_MEM: 2085ebccf1e3SJoseph Koshy 2086ebccf1e3SJoseph Koshy /* default => 'nta' */ 2087ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED: 2088ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_MISS: 2089ebccf1e3SJoseph Koshy 2090ebccf1e3SJoseph Koshy /* default => 'packed and scalar' */ 2091ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_INST_RETIRED: 2092ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_COMP_INST_RET: 2093ebccf1e3SJoseph Koshy 2094ebccf1e3SJoseph Koshy /* default => 'mmx to fp transitions' */ 2095ebccf1e3SJoseph Koshy case PMC_EV_P6_FP_MMX_TRANS: 2096ebccf1e3SJoseph Koshy 2097ebccf1e3SJoseph Koshy /* default => 'SSE Packed Single' */ 2098ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED: 2099ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED: 2100ebccf1e3SJoseph Koshy 2101ebccf1e3SJoseph Koshy /* default => 'all fused micro-ops' */ 2102ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_FUSED_UOPS_RET: 2103ebccf1e3SJoseph Koshy 2104ebccf1e3SJoseph Koshy /* default => 'all transitions' */ 2105ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_EST_TRANS: 2106ebccf1e3SJoseph Koshy break; 2107ebccf1e3SJoseph Koshy 2108ebccf1e3SJoseph Koshy case PMC_EV_P6_MMX_UOPS_EXEC: 2109ebccf1e3SJoseph Koshy evmask = 0x0F; /* only value allowed */ 2110ebccf1e3SJoseph Koshy break; 2111ebccf1e3SJoseph Koshy 2112ebccf1e3SJoseph Koshy default: 2113ebccf1e3SJoseph Koshy /* 2114ebccf1e3SJoseph Koshy * For all other events, set the default event mask 2115ebccf1e3SJoseph Koshy * to a logical OR of all the allowed event mask bits. 2116ebccf1e3SJoseph Koshy */ 2117ebccf1e3SJoseph Koshy if (evmask == 0 && pmask) { 2118ebccf1e3SJoseph Koshy for (pm = pmask; pm->pm_name; pm++) 2119ebccf1e3SJoseph Koshy evmask |= pm->pm_value; 2120ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2121ebccf1e3SJoseph Koshy } 2122ebccf1e3SJoseph Koshy 2123ebccf1e3SJoseph Koshy break; 2124ebccf1e3SJoseph Koshy } 2125ebccf1e3SJoseph Koshy 2126ebccf1e3SJoseph Koshy if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) 2127f263522aSJoseph Koshy pmc_config->pm_md.pm_ppro.pm_ppro_config |= 2128f263522aSJoseph Koshy P6_EVSEL_TO_UMASK(evmask); 2129ebccf1e3SJoseph Koshy 2130aa342b1fSJoseph Koshy return (0); 2131ebccf1e3SJoseph Koshy } 2132ebccf1e3SJoseph Koshy 2133ebccf1e3SJoseph Koshy #endif 2134ebccf1e3SJoseph Koshy 2135789140c0SJoseph Koshy #if defined(__i386__) || defined(__amd64__) 2136789140c0SJoseph Koshy static int 2137789140c0SJoseph Koshy tsc_allocate_pmc(enum pmc_event pe, char *ctrspec, 2138789140c0SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 2139789140c0SJoseph Koshy { 2140789140c0SJoseph Koshy if (pe != PMC_EV_TSC_TSC) 2141789140c0SJoseph Koshy return (-1); 2142789140c0SJoseph Koshy 2143789140c0SJoseph Koshy /* TSC events must be unqualified. */ 2144789140c0SJoseph Koshy if (ctrspec && *ctrspec != '\0') 2145789140c0SJoseph Koshy return (-1); 2146789140c0SJoseph Koshy 2147789140c0SJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 2148789140c0SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_READ; 2149789140c0SJoseph Koshy 2150789140c0SJoseph Koshy return (0); 2151789140c0SJoseph Koshy } 2152789140c0SJoseph Koshy #endif 2153789140c0SJoseph Koshy 21540ce207d2SRui Paulo #if defined(__XSCALE__) 21550ce207d2SRui Paulo 21560ce207d2SRui Paulo static struct pmc_event_alias xscale_aliases[] = { 21570ce207d2SRui Paulo EV_ALIAS("branches", "BRANCH_RETIRED"), 21580ce207d2SRui Paulo EV_ALIAS("branch-mispredicts", "BRANCH_MISPRED"), 21590ce207d2SRui Paulo EV_ALIAS("dc-misses", "DC_MISS"), 21600ce207d2SRui Paulo EV_ALIAS("ic-misses", "IC_MISS"), 21610ce207d2SRui Paulo EV_ALIAS("instructions", "INSTR_RETIRED"), 21620ce207d2SRui Paulo EV_ALIAS(NULL, NULL) 21630ce207d2SRui Paulo }; 21640ce207d2SRui Paulo static int 21650ce207d2SRui Paulo xscale_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 21660ce207d2SRui Paulo struct pmc_op_pmcallocate *pmc_config __unused) 21670ce207d2SRui Paulo { 21680ce207d2SRui Paulo switch (pe) { 21690ce207d2SRui Paulo default: 21700ce207d2SRui Paulo break; 21710ce207d2SRui Paulo } 21720ce207d2SRui Paulo 21730ce207d2SRui Paulo return (0); 21740ce207d2SRui Paulo } 21750ce207d2SRui Paulo #endif 21760ce207d2SRui Paulo 2177660df75eSGeorge V. Neville-Neil #if defined(__mips__) 2178660df75eSGeorge V. Neville-Neil 2179660df75eSGeorge V. Neville-Neil static struct pmc_event_alias mips24k_aliases[] = { 2180660df75eSGeorge V. Neville-Neil EV_ALIAS("instructions", "INSTR_EXECUTED"), 2181660df75eSGeorge V. Neville-Neil EV_ALIAS("branches", "BRANCH_COMPLETED"), 2182660df75eSGeorge V. Neville-Neil EV_ALIAS("branch-mispredicts", "BRANCH_MISPRED"), 2183660df75eSGeorge V. Neville-Neil EV_ALIAS(NULL, NULL) 2184660df75eSGeorge V. Neville-Neil }; 2185660df75eSGeorge V. Neville-Neil 2186660df75eSGeorge V. Neville-Neil #define MIPS24K_KW_OS "os" 2187660df75eSGeorge V. Neville-Neil #define MIPS24K_KW_USR "usr" 2188660df75eSGeorge V. Neville-Neil #define MIPS24K_KW_ANYTHREAD "anythread" 2189660df75eSGeorge V. Neville-Neil 2190660df75eSGeorge V. Neville-Neil static int 2191660df75eSGeorge V. Neville-Neil mips24k_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 2192660df75eSGeorge V. Neville-Neil struct pmc_op_pmcallocate *pmc_config __unused) 2193660df75eSGeorge V. Neville-Neil { 2194660df75eSGeorge V. Neville-Neil char *p; 2195660df75eSGeorge V. Neville-Neil 2196660df75eSGeorge V. Neville-Neil (void) pe; 2197660df75eSGeorge V. Neville-Neil 2198660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2199660df75eSGeorge V. Neville-Neil 2200660df75eSGeorge V. Neville-Neil while ((p = strsep(&ctrspec, ",")) != NULL) { 2201660df75eSGeorge V. Neville-Neil if (KWMATCH(p, MIPS24K_KW_OS)) 2202660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2203660df75eSGeorge V. Neville-Neil else if (KWMATCH(p, MIPS24K_KW_USR)) 2204660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= PMC_CAP_USER; 2205660df75eSGeorge V. Neville-Neil else if (KWMATCH(p, MIPS24K_KW_ANYTHREAD)) 2206660df75eSGeorge V. Neville-Neil pmc_config->pm_caps |= (PMC_CAP_USER | PMC_CAP_SYSTEM); 2207660df75eSGeorge V. Neville-Neil else 2208660df75eSGeorge V. Neville-Neil return (-1); 2209660df75eSGeorge V. Neville-Neil } 2210660df75eSGeorge V. Neville-Neil 2211660df75eSGeorge V. Neville-Neil return (0); 2212660df75eSGeorge V. Neville-Neil } 2213660df75eSGeorge V. Neville-Neil #endif /* __mips__ */ 2214660df75eSGeorge V. Neville-Neil 2215660df75eSGeorge V. Neville-Neil 2216789140c0SJoseph Koshy /* 2217789140c0SJoseph Koshy * Match an event name `name' with its canonical form. 2218789140c0SJoseph Koshy * 22190cfab8ddSJoseph Koshy * Matches are case insensitive and spaces, periods, underscores and 22200cfab8ddSJoseph Koshy * hyphen characters are considered to match each other. 2221789140c0SJoseph Koshy * 2222789140c0SJoseph Koshy * Returns 1 for a match, 0 otherwise. 2223789140c0SJoseph Koshy */ 2224789140c0SJoseph Koshy 2225789140c0SJoseph Koshy static int 2226789140c0SJoseph Koshy pmc_match_event_name(const char *name, const char *canonicalname) 2227789140c0SJoseph Koshy { 2228789140c0SJoseph Koshy int cc, nc; 2229789140c0SJoseph Koshy const unsigned char *c, *n; 2230789140c0SJoseph Koshy 2231789140c0SJoseph Koshy c = (const unsigned char *) canonicalname; 2232789140c0SJoseph Koshy n = (const unsigned char *) name; 2233789140c0SJoseph Koshy 2234789140c0SJoseph Koshy for (; (nc = *n) && (cc = *c); n++, c++) { 2235789140c0SJoseph Koshy 22360cfab8ddSJoseph Koshy if ((nc == ' ' || nc == '_' || nc == '-' || nc == '.') && 22370cfab8ddSJoseph Koshy (cc == ' ' || cc == '_' || cc == '-' || cc == '.')) 2238789140c0SJoseph Koshy continue; 2239789140c0SJoseph Koshy 22400cfab8ddSJoseph Koshy if (toupper(nc) == toupper(cc)) 2241789140c0SJoseph Koshy continue; 2242789140c0SJoseph Koshy 22430cfab8ddSJoseph Koshy 2244789140c0SJoseph Koshy return (0); 2245789140c0SJoseph Koshy } 2246789140c0SJoseph Koshy 2247789140c0SJoseph Koshy if (*n == '\0' && *c == '\0') 2248789140c0SJoseph Koshy return (1); 2249789140c0SJoseph Koshy 2250789140c0SJoseph Koshy return (0); 2251789140c0SJoseph Koshy } 2252789140c0SJoseph Koshy 2253789140c0SJoseph Koshy /* 2254789140c0SJoseph Koshy * Match an event name against all the event named supported by a 2255789140c0SJoseph Koshy * PMC class. 2256789140c0SJoseph Koshy * 2257789140c0SJoseph Koshy * Returns an event descriptor pointer on match or NULL otherwise. 2258789140c0SJoseph Koshy */ 2259789140c0SJoseph Koshy static const struct pmc_event_descr * 2260789140c0SJoseph Koshy pmc_match_event_class(const char *name, 2261789140c0SJoseph Koshy const struct pmc_class_descr *pcd) 2262789140c0SJoseph Koshy { 2263789140c0SJoseph Koshy size_t n; 2264789140c0SJoseph Koshy const struct pmc_event_descr *ev; 2265789140c0SJoseph Koshy 2266789140c0SJoseph Koshy ev = pcd->pm_evc_event_table; 2267789140c0SJoseph Koshy for (n = 0; n < pcd->pm_evc_event_table_size; n++, ev++) 2268789140c0SJoseph Koshy if (pmc_match_event_name(name, ev->pm_ev_name)) 2269789140c0SJoseph Koshy return (ev); 2270789140c0SJoseph Koshy 2271789140c0SJoseph Koshy return (NULL); 2272789140c0SJoseph Koshy } 2273789140c0SJoseph Koshy 2274789140c0SJoseph Koshy static int 2275789140c0SJoseph Koshy pmc_mdep_is_compatible_class(enum pmc_class pc) 2276789140c0SJoseph Koshy { 2277789140c0SJoseph Koshy size_t n; 2278789140c0SJoseph Koshy 2279789140c0SJoseph Koshy for (n = 0; n < pmc_mdep_class_list_size; n++) 2280789140c0SJoseph Koshy if (pmc_mdep_class_list[n] == pc) 2281789140c0SJoseph Koshy return (1); 2282789140c0SJoseph Koshy return (0); 2283789140c0SJoseph Koshy } 2284789140c0SJoseph Koshy 2285ebccf1e3SJoseph Koshy /* 2286ebccf1e3SJoseph Koshy * API entry points 2287ebccf1e3SJoseph Koshy */ 2288ebccf1e3SJoseph Koshy 2289ebccf1e3SJoseph Koshy int 2290ebccf1e3SJoseph Koshy pmc_allocate(const char *ctrspec, enum pmc_mode mode, 2291ebccf1e3SJoseph Koshy uint32_t flags, int cpu, pmc_id_t *pmcid) 2292ebccf1e3SJoseph Koshy { 2293789140c0SJoseph Koshy size_t n; 2294ebccf1e3SJoseph Koshy int retval; 2295ebccf1e3SJoseph Koshy char *r, *spec_copy; 2296ebccf1e3SJoseph Koshy const char *ctrname; 2297789140c0SJoseph Koshy const struct pmc_event_descr *ev; 2298789140c0SJoseph Koshy const struct pmc_event_alias *alias; 2299ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate pmc_config; 2300789140c0SJoseph Koshy const struct pmc_class_descr *pcd; 2301ebccf1e3SJoseph Koshy 2302ebccf1e3SJoseph Koshy spec_copy = NULL; 2303ebccf1e3SJoseph Koshy retval = -1; 2304ebccf1e3SJoseph Koshy 2305ebccf1e3SJoseph Koshy if (mode != PMC_MODE_SS && mode != PMC_MODE_TS && 2306ebccf1e3SJoseph Koshy mode != PMC_MODE_SC && mode != PMC_MODE_TC) { 2307ebccf1e3SJoseph Koshy errno = EINVAL; 2308ebccf1e3SJoseph Koshy goto out; 2309ebccf1e3SJoseph Koshy } 2310ebccf1e3SJoseph Koshy 2311ebccf1e3SJoseph Koshy /* replace an event alias with the canonical event specifier */ 2312ebccf1e3SJoseph Koshy if (pmc_mdep_event_aliases) 2313789140c0SJoseph Koshy for (alias = pmc_mdep_event_aliases; alias->pm_alias; alias++) 2314789140c0SJoseph Koshy if (!strcasecmp(ctrspec, alias->pm_alias)) { 2315789140c0SJoseph Koshy spec_copy = strdup(alias->pm_spec); 2316ebccf1e3SJoseph Koshy break; 2317ebccf1e3SJoseph Koshy } 2318ebccf1e3SJoseph Koshy 2319ebccf1e3SJoseph Koshy if (spec_copy == NULL) 2320ebccf1e3SJoseph Koshy spec_copy = strdup(ctrspec); 2321ebccf1e3SJoseph Koshy 2322ebccf1e3SJoseph Koshy r = spec_copy; 2323ebccf1e3SJoseph Koshy ctrname = strsep(&r, ","); 2324ebccf1e3SJoseph Koshy 2325789140c0SJoseph Koshy /* 2326789140c0SJoseph Koshy * If a explicit class prefix was given by the user, restrict the 2327789140c0SJoseph Koshy * search for the event to the specified PMC class. 2328789140c0SJoseph Koshy */ 2329789140c0SJoseph Koshy ev = NULL; 23300cfab8ddSJoseph Koshy for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) { 23310cfab8ddSJoseph Koshy pcd = pmc_class_table[n]; 2332789140c0SJoseph Koshy if (pmc_mdep_is_compatible_class(pcd->pm_evc_class) && 2333789140c0SJoseph Koshy strncasecmp(ctrname, pcd->pm_evc_name, 2334789140c0SJoseph Koshy pcd->pm_evc_name_size) == 0) { 2335789140c0SJoseph Koshy if ((ev = pmc_match_event_class(ctrname + 2336789140c0SJoseph Koshy pcd->pm_evc_name_size, pcd)) == NULL) { 2337789140c0SJoseph Koshy errno = EINVAL; 2338789140c0SJoseph Koshy goto out; 2339789140c0SJoseph Koshy } 2340ebccf1e3SJoseph Koshy break; 2341789140c0SJoseph Koshy } 2342789140c0SJoseph Koshy } 2343ebccf1e3SJoseph Koshy 2344789140c0SJoseph Koshy /* 2345789140c0SJoseph Koshy * Otherwise, search for this event in all compatible PMC 2346789140c0SJoseph Koshy * classes. 2347789140c0SJoseph Koshy */ 23480cfab8ddSJoseph Koshy for (n = 0; ev == NULL && n < PMC_CLASS_TABLE_SIZE; n++) { 23490cfab8ddSJoseph Koshy pcd = pmc_class_table[n]; 2350789140c0SJoseph Koshy if (pmc_mdep_is_compatible_class(pcd->pm_evc_class)) 2351789140c0SJoseph Koshy ev = pmc_match_event_class(ctrname, pcd); 2352789140c0SJoseph Koshy } 2353789140c0SJoseph Koshy 2354789140c0SJoseph Koshy if (ev == NULL) { 2355ebccf1e3SJoseph Koshy errno = EINVAL; 2356ebccf1e3SJoseph Koshy goto out; 2357ebccf1e3SJoseph Koshy } 2358ebccf1e3SJoseph Koshy 2359ebccf1e3SJoseph Koshy bzero(&pmc_config, sizeof(pmc_config)); 2360789140c0SJoseph Koshy pmc_config.pm_ev = ev->pm_ev_code; 2361789140c0SJoseph Koshy pmc_config.pm_class = pcd->pm_evc_class; 2362ebccf1e3SJoseph Koshy pmc_config.pm_cpu = cpu; 2363ebccf1e3SJoseph Koshy pmc_config.pm_mode = mode; 2364ebccf1e3SJoseph Koshy pmc_config.pm_flags = flags; 2365ebccf1e3SJoseph Koshy 2366ebccf1e3SJoseph Koshy if (PMC_IS_SAMPLING_MODE(mode)) 2367ebccf1e3SJoseph Koshy pmc_config.pm_caps |= PMC_CAP_INTERRUPT; 2368ebccf1e3SJoseph Koshy 2369789140c0SJoseph Koshy if (pcd->pm_evc_allocate_pmc(ev->pm_ev_code, r, &pmc_config) < 0) { 2370ebccf1e3SJoseph Koshy errno = EINVAL; 2371ebccf1e3SJoseph Koshy goto out; 2372ebccf1e3SJoseph Koshy } 2373ebccf1e3SJoseph Koshy 2374ebccf1e3SJoseph Koshy if (PMC_CALL(PMCALLOCATE, &pmc_config) < 0) 2375ebccf1e3SJoseph Koshy goto out; 2376ebccf1e3SJoseph Koshy 2377ebccf1e3SJoseph Koshy *pmcid = pmc_config.pm_pmcid; 2378ebccf1e3SJoseph Koshy 2379ebccf1e3SJoseph Koshy retval = 0; 2380ebccf1e3SJoseph Koshy 2381ebccf1e3SJoseph Koshy out: 2382ebccf1e3SJoseph Koshy if (spec_copy) 2383ebccf1e3SJoseph Koshy free(spec_copy); 2384ebccf1e3SJoseph Koshy 2385aa342b1fSJoseph Koshy return (retval); 2386ebccf1e3SJoseph Koshy } 2387ebccf1e3SJoseph Koshy 2388ebccf1e3SJoseph Koshy int 2389ebccf1e3SJoseph Koshy pmc_attach(pmc_id_t pmc, pid_t pid) 2390ebccf1e3SJoseph Koshy { 2391ebccf1e3SJoseph Koshy struct pmc_op_pmcattach pmc_attach_args; 2392ebccf1e3SJoseph Koshy 2393ebccf1e3SJoseph Koshy pmc_attach_args.pm_pmc = pmc; 2394ebccf1e3SJoseph Koshy pmc_attach_args.pm_pid = pid; 2395ebccf1e3SJoseph Koshy 2396aa342b1fSJoseph Koshy return (PMC_CALL(PMCATTACH, &pmc_attach_args)); 2397ebccf1e3SJoseph Koshy } 2398ebccf1e3SJoseph Koshy 2399ebccf1e3SJoseph Koshy int 2400c5153e19SJoseph Koshy pmc_capabilities(pmc_id_t pmcid, uint32_t *caps) 2401c5153e19SJoseph Koshy { 2402c5153e19SJoseph Koshy unsigned int i; 2403c5153e19SJoseph Koshy enum pmc_class cl; 2404c5153e19SJoseph Koshy 2405c5153e19SJoseph Koshy cl = PMC_ID_TO_CLASS(pmcid); 2406c5153e19SJoseph Koshy for (i = 0; i < cpu_info.pm_nclass; i++) 2407c5153e19SJoseph Koshy if (cpu_info.pm_classes[i].pm_class == cl) { 2408c5153e19SJoseph Koshy *caps = cpu_info.pm_classes[i].pm_caps; 2409aa342b1fSJoseph Koshy return (0); 2410c5153e19SJoseph Koshy } 2411484202faSJoseph Koshy errno = EINVAL; 2412484202faSJoseph Koshy return (-1); 2413c5153e19SJoseph Koshy } 2414c5153e19SJoseph Koshy 2415f263522aSJoseph Koshy int 2416f263522aSJoseph Koshy pmc_configure_logfile(int fd) 2417ebccf1e3SJoseph Koshy { 2418f263522aSJoseph Koshy struct pmc_op_configurelog cla; 2419f263522aSJoseph Koshy 2420f263522aSJoseph Koshy cla.pm_logfd = fd; 2421f263522aSJoseph Koshy if (PMC_CALL(CONFIGURELOG, &cla) < 0) 2422aa342b1fSJoseph Koshy return (-1); 2423aa342b1fSJoseph Koshy return (0); 2424ebccf1e3SJoseph Koshy } 2425ebccf1e3SJoseph Koshy 2426f263522aSJoseph Koshy int 2427f263522aSJoseph Koshy pmc_cpuinfo(const struct pmc_cpuinfo **pci) 2428ebccf1e3SJoseph Koshy { 2429f263522aSJoseph Koshy if (pmc_syscall == -1) { 2430f263522aSJoseph Koshy errno = ENXIO; 2431aa342b1fSJoseph Koshy return (-1); 2432ebccf1e3SJoseph Koshy } 2433ebccf1e3SJoseph Koshy 24341455fcd3SJoseph Koshy *pci = &cpu_info; 2435aa342b1fSJoseph Koshy return (0); 2436ebccf1e3SJoseph Koshy } 2437ebccf1e3SJoseph Koshy 2438f263522aSJoseph Koshy int 2439f263522aSJoseph Koshy pmc_detach(pmc_id_t pmc, pid_t pid) 2440ebccf1e3SJoseph Koshy { 2441f263522aSJoseph Koshy struct pmc_op_pmcattach pmc_detach_args; 2442ebccf1e3SJoseph Koshy 2443f263522aSJoseph Koshy pmc_detach_args.pm_pmc = pmc; 2444f263522aSJoseph Koshy pmc_detach_args.pm_pid = pid; 2445aa342b1fSJoseph Koshy return (PMC_CALL(PMCDETACH, &pmc_detach_args)); 2446ebccf1e3SJoseph Koshy } 2447ebccf1e3SJoseph Koshy 2448f263522aSJoseph Koshy int 2449f263522aSJoseph Koshy pmc_disable(int cpu, int pmc) 2450ebccf1e3SJoseph Koshy { 2451f263522aSJoseph Koshy struct pmc_op_pmcadmin ssa; 2452ebccf1e3SJoseph Koshy 2453f263522aSJoseph Koshy ssa.pm_cpu = cpu; 2454f263522aSJoseph Koshy ssa.pm_pmc = pmc; 2455f263522aSJoseph Koshy ssa.pm_state = PMC_STATE_DISABLED; 2456aa342b1fSJoseph Koshy return (PMC_CALL(PMCADMIN, &ssa)); 2457ebccf1e3SJoseph Koshy } 2458ebccf1e3SJoseph Koshy 2459f263522aSJoseph Koshy int 2460f263522aSJoseph Koshy pmc_enable(int cpu, int pmc) 2461ebccf1e3SJoseph Koshy { 2462f263522aSJoseph Koshy struct pmc_op_pmcadmin ssa; 2463ebccf1e3SJoseph Koshy 2464f263522aSJoseph Koshy ssa.pm_cpu = cpu; 2465f263522aSJoseph Koshy ssa.pm_pmc = pmc; 2466f263522aSJoseph Koshy ssa.pm_state = PMC_STATE_FREE; 2467aa342b1fSJoseph Koshy return (PMC_CALL(PMCADMIN, &ssa)); 2468ebccf1e3SJoseph Koshy } 2469ebccf1e3SJoseph Koshy 2470ebccf1e3SJoseph Koshy /* 2471ebccf1e3SJoseph Koshy * Return a list of events known to a given PMC class. 'cl' is the 2472ebccf1e3SJoseph Koshy * PMC class identifier, 'eventnames' is the returned list of 'const 2473ebccf1e3SJoseph Koshy * char *' pointers pointing to the names of the events. 'nevents' is 2474ebccf1e3SJoseph Koshy * the number of event name pointers returned. 2475ebccf1e3SJoseph Koshy * 2476ebccf1e3SJoseph Koshy * The space for 'eventnames' is allocated using malloc(3). The caller 2477ebccf1e3SJoseph Koshy * is responsible for freeing this space when done. 2478ebccf1e3SJoseph Koshy */ 2479ebccf1e3SJoseph Koshy int 2480ebccf1e3SJoseph Koshy pmc_event_names_of_class(enum pmc_class cl, const char ***eventnames, 2481ebccf1e3SJoseph Koshy int *nevents) 2482ebccf1e3SJoseph Koshy { 2483ebccf1e3SJoseph Koshy int count; 2484ebccf1e3SJoseph Koshy const char **names; 2485ebccf1e3SJoseph Koshy const struct pmc_event_descr *ev; 2486ebccf1e3SJoseph Koshy 2487ebccf1e3SJoseph Koshy switch (cl) 2488ebccf1e3SJoseph Koshy { 24890cfab8ddSJoseph Koshy case PMC_CLASS_IAF: 24900cfab8ddSJoseph Koshy ev = iaf_event_table; 24910cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(iaf); 24920cfab8ddSJoseph Koshy break; 24930cfab8ddSJoseph Koshy case PMC_CLASS_IAP: 24940cfab8ddSJoseph Koshy /* 24950cfab8ddSJoseph Koshy * Return the most appropriate set of event name 24960cfab8ddSJoseph Koshy * spellings for the current CPU. 24970cfab8ddSJoseph Koshy */ 24980cfab8ddSJoseph Koshy switch (cpu_info.pm_cputype) { 24990cfab8ddSJoseph Koshy default: 25000cfab8ddSJoseph Koshy case PMC_CPU_INTEL_ATOM: 25010cfab8ddSJoseph Koshy ev = atom_event_table; 25020cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(atom); 25030cfab8ddSJoseph Koshy break; 25040cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE: 25050cfab8ddSJoseph Koshy ev = core_event_table; 25060cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(core); 25070cfab8ddSJoseph Koshy break; 25080cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE2: 2509b4d091f3SJoseph Koshy case PMC_CPU_INTEL_CORE2EXTREME: 25100cfab8ddSJoseph Koshy ev = core2_event_table; 25110cfab8ddSJoseph Koshy count = PMC_EVENT_TABLE_SIZE(core2); 25120cfab8ddSJoseph Koshy break; 2513597979c4SJeff Roberson case PMC_CPU_INTEL_COREI7: 2514597979c4SJeff Roberson ev = corei7_event_table; 2515597979c4SJeff Roberson count = PMC_EVENT_TABLE_SIZE(corei7); 2516597979c4SJeff Roberson break; 25171fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 25181fa7f10bSFabien Thomas ev = westmere_event_table; 25191fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(westmere); 25201fa7f10bSFabien Thomas break; 25211fa7f10bSFabien Thomas } 25221fa7f10bSFabien Thomas break; 25231fa7f10bSFabien Thomas case PMC_CLASS_UCF: 25241fa7f10bSFabien Thomas ev = ucf_event_table; 25251fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(ucf); 25261fa7f10bSFabien Thomas break; 25271fa7f10bSFabien Thomas case PMC_CLASS_UCP: 25281fa7f10bSFabien Thomas /* 25291fa7f10bSFabien Thomas * Return the most appropriate set of event name 25301fa7f10bSFabien Thomas * spellings for the current CPU. 25311fa7f10bSFabien Thomas */ 25321fa7f10bSFabien Thomas switch (cpu_info.pm_cputype) { 25331fa7f10bSFabien Thomas default: 25341fa7f10bSFabien Thomas case PMC_CPU_INTEL_COREI7: 25351fa7f10bSFabien Thomas ev = corei7uc_event_table; 25361fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(corei7uc); 25371fa7f10bSFabien Thomas break; 25381fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 25391fa7f10bSFabien Thomas ev = westmereuc_event_table; 25401fa7f10bSFabien Thomas count = PMC_EVENT_TABLE_SIZE(westmereuc); 25411fa7f10bSFabien Thomas break; 25420cfab8ddSJoseph Koshy } 25430cfab8ddSJoseph Koshy break; 2544ebccf1e3SJoseph Koshy case PMC_CLASS_TSC: 2545789140c0SJoseph Koshy ev = tsc_event_table; 2546789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(tsc); 2547ebccf1e3SJoseph Koshy break; 2548ebccf1e3SJoseph Koshy case PMC_CLASS_K7: 2549789140c0SJoseph Koshy ev = k7_event_table; 2550789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(k7); 2551ebccf1e3SJoseph Koshy break; 2552ebccf1e3SJoseph Koshy case PMC_CLASS_K8: 2553789140c0SJoseph Koshy ev = k8_event_table; 2554789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(k8); 2555ebccf1e3SJoseph Koshy break; 2556ebccf1e3SJoseph Koshy case PMC_CLASS_P4: 2557789140c0SJoseph Koshy ev = p4_event_table; 2558789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p4); 2559789140c0SJoseph Koshy break; 2560789140c0SJoseph Koshy case PMC_CLASS_P5: 2561789140c0SJoseph Koshy ev = p5_event_table; 2562789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p5); 2563789140c0SJoseph Koshy break; 2564789140c0SJoseph Koshy case PMC_CLASS_P6: 2565789140c0SJoseph Koshy ev = p6_event_table; 2566789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p6); 2567ebccf1e3SJoseph Koshy break; 25680ce207d2SRui Paulo case PMC_CLASS_XSCALE: 25690ce207d2SRui Paulo ev = xscale_event_table; 25700ce207d2SRui Paulo count = PMC_EVENT_TABLE_SIZE(xscale); 25710ce207d2SRui Paulo break; 2572660df75eSGeorge V. Neville-Neil case PMC_CLASS_MIPS24K: 2573660df75eSGeorge V. Neville-Neil ev = mips24k_event_table; 2574660df75eSGeorge V. Neville-Neil count = PMC_EVENT_TABLE_SIZE(mips24k); 2575660df75eSGeorge V. Neville-Neil break; 2576ebccf1e3SJoseph Koshy default: 2577ebccf1e3SJoseph Koshy errno = EINVAL; 2578aa342b1fSJoseph Koshy return (-1); 2579ebccf1e3SJoseph Koshy } 2580ebccf1e3SJoseph Koshy 2581ebccf1e3SJoseph Koshy if ((names = malloc(count * sizeof(const char *))) == NULL) 2582aa342b1fSJoseph Koshy return (-1); 2583ebccf1e3SJoseph Koshy 2584ebccf1e3SJoseph Koshy *eventnames = names; 2585ebccf1e3SJoseph Koshy *nevents = count; 2586ebccf1e3SJoseph Koshy 2587ebccf1e3SJoseph Koshy for (;count--; ev++, names++) 2588ebccf1e3SJoseph Koshy *names = ev->pm_ev_name; 2589aa342b1fSJoseph Koshy return (0); 2590ebccf1e3SJoseph Koshy } 2591ebccf1e3SJoseph Koshy 2592f263522aSJoseph Koshy int 2593f263522aSJoseph Koshy pmc_flush_logfile(void) 2594f263522aSJoseph Koshy { 2595aa342b1fSJoseph Koshy return (PMC_CALL(FLUSHLOG,0)); 2596f263522aSJoseph Koshy } 2597ebccf1e3SJoseph Koshy 2598ebccf1e3SJoseph Koshy int 2599*dceed24aSFabien Thomas pmc_close_logfile(void) 2600*dceed24aSFabien Thomas { 2601*dceed24aSFabien Thomas return (PMC_CALL(CLOSELOG,0)); 2602*dceed24aSFabien Thomas } 2603*dceed24aSFabien Thomas 2604*dceed24aSFabien Thomas int 2605f263522aSJoseph Koshy pmc_get_driver_stats(struct pmc_driverstats *ds) 2606ebccf1e3SJoseph Koshy { 2607f263522aSJoseph Koshy struct pmc_op_getdriverstats gms; 2608f263522aSJoseph Koshy 2609f263522aSJoseph Koshy if (PMC_CALL(GETDRIVERSTATS, &gms) < 0) 2610aa342b1fSJoseph Koshy return (-1); 2611f263522aSJoseph Koshy 2612f263522aSJoseph Koshy /* copy out fields in the current userland<->library interface */ 2613f263522aSJoseph Koshy ds->pm_intr_ignored = gms.pm_intr_ignored; 2614f263522aSJoseph Koshy ds->pm_intr_processed = gms.pm_intr_processed; 2615f263522aSJoseph Koshy ds->pm_intr_bufferfull = gms.pm_intr_bufferfull; 2616f263522aSJoseph Koshy ds->pm_syscalls = gms.pm_syscalls; 2617f263522aSJoseph Koshy ds->pm_syscall_errors = gms.pm_syscall_errors; 2618f263522aSJoseph Koshy ds->pm_buffer_requests = gms.pm_buffer_requests; 2619f263522aSJoseph Koshy ds->pm_buffer_requests_failed = gms.pm_buffer_requests_failed; 2620f263522aSJoseph Koshy ds->pm_log_sweeps = gms.pm_log_sweeps; 2621aa342b1fSJoseph Koshy return (0); 2622f263522aSJoseph Koshy } 2623f263522aSJoseph Koshy 2624f263522aSJoseph Koshy int 2625f263522aSJoseph Koshy pmc_get_msr(pmc_id_t pmc, uint32_t *msr) 2626f263522aSJoseph Koshy { 2627f263522aSJoseph Koshy struct pmc_op_getmsr gm; 2628ebccf1e3SJoseph Koshy 2629ebccf1e3SJoseph Koshy gm.pm_pmcid = pmc; 2630f263522aSJoseph Koshy if (PMC_CALL(PMCGETMSR, &gm) < 0) 2631aa342b1fSJoseph Koshy return (-1); 2632ebccf1e3SJoseph Koshy *msr = gm.pm_msr; 2633aa342b1fSJoseph Koshy return (0); 2634ebccf1e3SJoseph Koshy } 2635ebccf1e3SJoseph Koshy 2636f263522aSJoseph Koshy int 2637f263522aSJoseph Koshy pmc_init(void) 2638f263522aSJoseph Koshy { 2639f263522aSJoseph Koshy int error, pmc_mod_id; 26401455fcd3SJoseph Koshy unsigned int n; 2641f263522aSJoseph Koshy uint32_t abi_version; 2642f263522aSJoseph Koshy struct module_stat pmc_modstat; 26431455fcd3SJoseph Koshy struct pmc_op_getcpuinfo op_cpu_info; 2644791f5d5bSJoseph Koshy #if defined(__amd64__) || defined(__i386__) 2645791f5d5bSJoseph Koshy int cpu_has_iaf_counters; 2646791f5d5bSJoseph Koshy unsigned int t; 2647791f5d5bSJoseph Koshy #endif 2648f263522aSJoseph Koshy 2649f263522aSJoseph Koshy if (pmc_syscall != -1) /* already inited */ 2650aa342b1fSJoseph Koshy return (0); 2651f263522aSJoseph Koshy 2652f263522aSJoseph Koshy /* retrieve the system call number from the KLD */ 2653f263522aSJoseph Koshy if ((pmc_mod_id = modfind(PMC_MODULE_NAME)) < 0) 2654aa342b1fSJoseph Koshy return (-1); 2655f263522aSJoseph Koshy 2656f263522aSJoseph Koshy pmc_modstat.version = sizeof(struct module_stat); 2657f263522aSJoseph Koshy if ((error = modstat(pmc_mod_id, &pmc_modstat)) < 0) 2658aa342b1fSJoseph Koshy return (-1); 2659f263522aSJoseph Koshy 2660f263522aSJoseph Koshy pmc_syscall = pmc_modstat.data.intval; 2661f263522aSJoseph Koshy 2662f263522aSJoseph Koshy /* check the kernel module's ABI against our compiled-in version */ 2663f263522aSJoseph Koshy abi_version = PMC_VERSION; 2664f263522aSJoseph Koshy if (PMC_CALL(GETMODULEVERSION, &abi_version) < 0) 2665f263522aSJoseph Koshy return (pmc_syscall = -1); 2666f263522aSJoseph Koshy 2667f263522aSJoseph Koshy /* ignore patch & minor numbers for the comparision */ 2668f263522aSJoseph Koshy if ((abi_version & 0xFF000000) != (PMC_VERSION & 0xFF000000)) { 2669f263522aSJoseph Koshy errno = EPROGMISMATCH; 2670f263522aSJoseph Koshy return (pmc_syscall = -1); 2671f263522aSJoseph Koshy } 2672f263522aSJoseph Koshy 26731455fcd3SJoseph Koshy if (PMC_CALL(GETCPUINFO, &op_cpu_info) < 0) 2674f263522aSJoseph Koshy return (pmc_syscall = -1); 2675f263522aSJoseph Koshy 26761455fcd3SJoseph Koshy cpu_info.pm_cputype = op_cpu_info.pm_cputype; 26771455fcd3SJoseph Koshy cpu_info.pm_ncpu = op_cpu_info.pm_ncpu; 26781455fcd3SJoseph Koshy cpu_info.pm_npmc = op_cpu_info.pm_npmc; 26791455fcd3SJoseph Koshy cpu_info.pm_nclass = op_cpu_info.pm_nclass; 26801455fcd3SJoseph Koshy for (n = 0; n < cpu_info.pm_nclass; n++) 26811455fcd3SJoseph Koshy cpu_info.pm_classes[n] = op_cpu_info.pm_classes[n]; 26821455fcd3SJoseph Koshy 26830cfab8ddSJoseph Koshy pmc_class_table = malloc(PMC_CLASS_TABLE_SIZE * 26840cfab8ddSJoseph Koshy sizeof(struct pmc_class_descr *)); 26850cfab8ddSJoseph Koshy 26860cfab8ddSJoseph Koshy if (pmc_class_table == NULL) 26870cfab8ddSJoseph Koshy return (-1); 26880cfab8ddSJoseph Koshy 2689791f5d5bSJoseph Koshy for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) 2690791f5d5bSJoseph Koshy pmc_class_table[n] = NULL; 26910cfab8ddSJoseph Koshy 26920cfab8ddSJoseph Koshy /* 26930cfab8ddSJoseph Koshy * Fill in the class table. 26940cfab8ddSJoseph Koshy */ 26950cfab8ddSJoseph Koshy n = 0; 26960cfab8ddSJoseph Koshy #if defined(__amd64__) || defined(__i386__) 26970cfab8ddSJoseph Koshy pmc_class_table[n++] = &tsc_class_table_descr; 2698791f5d5bSJoseph Koshy 2699791f5d5bSJoseph Koshy /* 2700791f5d5bSJoseph Koshy * Check if this CPU has fixed function counters. 2701791f5d5bSJoseph Koshy */ 2702791f5d5bSJoseph Koshy cpu_has_iaf_counters = 0; 2703791f5d5bSJoseph Koshy for (t = 0; t < cpu_info.pm_nclass; t++) 27042aef9dd6SFabien Thomas if (cpu_info.pm_classes[t].pm_class == PMC_CLASS_IAF && 27052aef9dd6SFabien Thomas cpu_info.pm_classes[t].pm_num > 0) 2706791f5d5bSJoseph Koshy cpu_has_iaf_counters = 1; 27070cfab8ddSJoseph Koshy #endif 27080cfab8ddSJoseph Koshy 2709789140c0SJoseph Koshy #define PMC_MDEP_INIT(C) do { \ 2710789140c0SJoseph Koshy pmc_mdep_event_aliases = C##_aliases; \ 2711789140c0SJoseph Koshy pmc_mdep_class_list = C##_pmc_classes; \ 2712789140c0SJoseph Koshy pmc_mdep_class_list_size = \ 2713789140c0SJoseph Koshy PMC_TABLE_SIZE(C##_pmc_classes); \ 2714789140c0SJoseph Koshy } while (0) 2715789140c0SJoseph Koshy 2716791f5d5bSJoseph Koshy #define PMC_MDEP_INIT_INTEL_V2(C) do { \ 2717791f5d5bSJoseph Koshy PMC_MDEP_INIT(C); \ 2718791f5d5bSJoseph Koshy pmc_class_table[n++] = &iaf_class_table_descr; \ 27192aef9dd6SFabien Thomas if (!cpu_has_iaf_counters) \ 2720791f5d5bSJoseph Koshy pmc_mdep_event_aliases = \ 2721791f5d5bSJoseph Koshy C##_aliases_without_iaf; \ 2722791f5d5bSJoseph Koshy pmc_class_table[n] = &C##_class_table_descr; \ 2723791f5d5bSJoseph Koshy } while (0) 2724791f5d5bSJoseph Koshy 2725789140c0SJoseph Koshy /* Configure the event name parser. */ 2726f263522aSJoseph Koshy switch (cpu_info.pm_cputype) { 2727f263522aSJoseph Koshy #if defined(__i386__) 2728f263522aSJoseph Koshy case PMC_CPU_AMD_K7: 2729789140c0SJoseph Koshy PMC_MDEP_INIT(k7); 27300cfab8ddSJoseph Koshy pmc_class_table[n] = &k7_class_table_descr; 2731f263522aSJoseph Koshy break; 2732f263522aSJoseph Koshy case PMC_CPU_INTEL_P5: 2733789140c0SJoseph Koshy PMC_MDEP_INIT(p5); 27340cfab8ddSJoseph Koshy pmc_class_table[n] = &p5_class_table_descr; 2735f263522aSJoseph Koshy break; 2736f263522aSJoseph Koshy case PMC_CPU_INTEL_P6: /* P6 ... Pentium M CPUs have */ 2737f263522aSJoseph Koshy case PMC_CPU_INTEL_PII: /* similar PMCs. */ 2738f263522aSJoseph Koshy case PMC_CPU_INTEL_PIII: 2739f263522aSJoseph Koshy case PMC_CPU_INTEL_PM: 2740789140c0SJoseph Koshy PMC_MDEP_INIT(p6); 27410cfab8ddSJoseph Koshy pmc_class_table[n] = &p6_class_table_descr; 2742f263522aSJoseph Koshy break; 274386a65549SJoseph Koshy #endif 274486a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 2745f263522aSJoseph Koshy case PMC_CPU_AMD_K8: 2746789140c0SJoseph Koshy PMC_MDEP_INIT(k8); 27470cfab8ddSJoseph Koshy pmc_class_table[n] = &k8_class_table_descr; 27480cfab8ddSJoseph Koshy break; 27490cfab8ddSJoseph Koshy case PMC_CPU_INTEL_ATOM: 2750791f5d5bSJoseph Koshy PMC_MDEP_INIT_INTEL_V2(atom); 27510cfab8ddSJoseph Koshy break; 27520cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE: 27530cfab8ddSJoseph Koshy PMC_MDEP_INIT(core); 2754bc315bbdSJoseph Koshy pmc_class_table[n] = &core_class_table_descr; 27550cfab8ddSJoseph Koshy break; 27560cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE2: 2757b4d091f3SJoseph Koshy case PMC_CPU_INTEL_CORE2EXTREME: 2758791f5d5bSJoseph Koshy PMC_MDEP_INIT_INTEL_V2(core2); 2759789140c0SJoseph Koshy break; 2760597979c4SJeff Roberson case PMC_CPU_INTEL_COREI7: 27611fa7f10bSFabien Thomas pmc_class_table[n++] = &ucf_class_table_descr; 27621fa7f10bSFabien Thomas pmc_class_table[n++] = &corei7uc_class_table_descr; 2763791f5d5bSJoseph Koshy PMC_MDEP_INIT_INTEL_V2(corei7); 2764597979c4SJeff Roberson break; 27651fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 27661fa7f10bSFabien Thomas pmc_class_table[n++] = &ucf_class_table_descr; 27671fa7f10bSFabien Thomas pmc_class_table[n++] = &westmereuc_class_table_descr; 27681fa7f10bSFabien Thomas PMC_MDEP_INIT_INTEL_V2(westmere); 27691fa7f10bSFabien Thomas break; 2770789140c0SJoseph Koshy case PMC_CPU_INTEL_PIV: 2771789140c0SJoseph Koshy PMC_MDEP_INIT(p4); 27720cfab8ddSJoseph Koshy pmc_class_table[n] = &p4_class_table_descr; 2773f263522aSJoseph Koshy break; 2774ebccf1e3SJoseph Koshy #endif 27750ce207d2SRui Paulo #if defined(__XSCALE__) 27760ce207d2SRui Paulo case PMC_CPU_INTEL_XSCALE: 27770ce207d2SRui Paulo PMC_MDEP_INIT(xscale); 27780ce207d2SRui Paulo pmc_class_table[n] = &xscale_class_table_descr; 27790ce207d2SRui Paulo break; 27800ce207d2SRui Paulo #endif 2781660df75eSGeorge V. Neville-Neil #if defined(__mips__) 2782660df75eSGeorge V. Neville-Neil case PMC_CPU_MIPS_24K: 2783660df75eSGeorge V. Neville-Neil PMC_MDEP_INIT(mips24k); 2784660df75eSGeorge V. Neville-Neil pmc_class_table[n] = &mips24k_class_table_descr; 2785660df75eSGeorge V. Neville-Neil break; 2786660df75eSGeorge V. Neville-Neil #endif /* __mips__ */ 2787f263522aSJoseph Koshy default: 2788f263522aSJoseph Koshy /* 2789f263522aSJoseph Koshy * Some kind of CPU this version of the library knows nothing 2790f263522aSJoseph Koshy * about. This shouldn't happen since the abi version check 2791f263522aSJoseph Koshy * should have caught this. 2792f263522aSJoseph Koshy */ 2793f263522aSJoseph Koshy errno = ENXIO; 2794f263522aSJoseph Koshy return (pmc_syscall = -1); 2795f263522aSJoseph Koshy } 2796f263522aSJoseph Koshy 2797aa342b1fSJoseph Koshy return (0); 2798f263522aSJoseph Koshy } 2799f263522aSJoseph Koshy 2800f263522aSJoseph Koshy const char * 2801f263522aSJoseph Koshy pmc_name_of_capability(enum pmc_caps cap) 2802f263522aSJoseph Koshy { 2803f263522aSJoseph Koshy int i; 2804f263522aSJoseph Koshy 2805f263522aSJoseph Koshy /* 2806f263522aSJoseph Koshy * 'cap' should have a single bit set and should be in 2807f263522aSJoseph Koshy * range. 2808f263522aSJoseph Koshy */ 2809f263522aSJoseph Koshy if ((cap & (cap - 1)) || cap < PMC_CAP_FIRST || 2810f263522aSJoseph Koshy cap > PMC_CAP_LAST) { 2811f263522aSJoseph Koshy errno = EINVAL; 2812aa342b1fSJoseph Koshy return (NULL); 2813f263522aSJoseph Koshy } 2814f263522aSJoseph Koshy 2815f263522aSJoseph Koshy i = ffs(cap); 2816aa342b1fSJoseph Koshy return (pmc_capability_names[i - 1]); 2817f263522aSJoseph Koshy } 2818f263522aSJoseph Koshy 2819f263522aSJoseph Koshy const char * 2820f263522aSJoseph Koshy pmc_name_of_class(enum pmc_class pc) 2821f263522aSJoseph Koshy { 2822f263522aSJoseph Koshy if ((int) pc >= PMC_CLASS_FIRST && 2823f263522aSJoseph Koshy pc <= PMC_CLASS_LAST) 2824aa342b1fSJoseph Koshy return (pmc_class_names[pc]); 2825f263522aSJoseph Koshy 2826f263522aSJoseph Koshy errno = EINVAL; 2827aa342b1fSJoseph Koshy return (NULL); 2828f263522aSJoseph Koshy } 2829f263522aSJoseph Koshy 2830f263522aSJoseph Koshy const char * 2831f263522aSJoseph Koshy pmc_name_of_cputype(enum pmc_cputype cp) 2832f263522aSJoseph Koshy { 2833789140c0SJoseph Koshy size_t n; 2834789140c0SJoseph Koshy 2835789140c0SJoseph Koshy for (n = 0; n < PMC_TABLE_SIZE(pmc_cputype_names); n++) 2836789140c0SJoseph Koshy if (cp == pmc_cputype_names[n].pm_cputype) 2837789140c0SJoseph Koshy return (pmc_cputype_names[n].pm_name); 2838789140c0SJoseph Koshy 2839f263522aSJoseph Koshy errno = EINVAL; 2840aa342b1fSJoseph Koshy return (NULL); 2841f263522aSJoseph Koshy } 2842f263522aSJoseph Koshy 2843f263522aSJoseph Koshy const char * 2844f263522aSJoseph Koshy pmc_name_of_disposition(enum pmc_disp pd) 2845f263522aSJoseph Koshy { 2846f263522aSJoseph Koshy if ((int) pd >= PMC_DISP_FIRST && 2847f263522aSJoseph Koshy pd <= PMC_DISP_LAST) 2848aa342b1fSJoseph Koshy return (pmc_disposition_names[pd]); 2849f263522aSJoseph Koshy 2850f263522aSJoseph Koshy errno = EINVAL; 2851aa342b1fSJoseph Koshy return (NULL); 2852f263522aSJoseph Koshy } 2853f263522aSJoseph Koshy 2854f263522aSJoseph Koshy const char * 28550cfab8ddSJoseph Koshy _pmc_name_of_event(enum pmc_event pe, enum pmc_cputype cpu) 2856f263522aSJoseph Koshy { 2857789140c0SJoseph Koshy const struct pmc_event_descr *ev, *evfence; 2858789140c0SJoseph Koshy 2859789140c0SJoseph Koshy ev = evfence = NULL; 28600cfab8ddSJoseph Koshy if (pe >= PMC_EV_IAF_FIRST && pe <= PMC_EV_IAF_LAST) { 28610cfab8ddSJoseph Koshy ev = iaf_event_table; 28620cfab8ddSJoseph Koshy evfence = iaf_event_table + PMC_EVENT_TABLE_SIZE(iaf); 28630cfab8ddSJoseph Koshy } else if (pe >= PMC_EV_IAP_FIRST && pe <= PMC_EV_IAP_LAST) { 28640cfab8ddSJoseph Koshy switch (cpu) { 28650cfab8ddSJoseph Koshy case PMC_CPU_INTEL_ATOM: 28660cfab8ddSJoseph Koshy ev = atom_event_table; 28670cfab8ddSJoseph Koshy evfence = atom_event_table + PMC_EVENT_TABLE_SIZE(atom); 28680cfab8ddSJoseph Koshy break; 28690cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE: 28700cfab8ddSJoseph Koshy ev = core_event_table; 28710cfab8ddSJoseph Koshy evfence = core_event_table + PMC_EVENT_TABLE_SIZE(core); 28720cfab8ddSJoseph Koshy break; 28730cfab8ddSJoseph Koshy case PMC_CPU_INTEL_CORE2: 2874b4d091f3SJoseph Koshy case PMC_CPU_INTEL_CORE2EXTREME: 28750cfab8ddSJoseph Koshy ev = core2_event_table; 28760cfab8ddSJoseph Koshy evfence = core2_event_table + PMC_EVENT_TABLE_SIZE(core2); 28770cfab8ddSJoseph Koshy break; 2878597979c4SJeff Roberson case PMC_CPU_INTEL_COREI7: 2879597979c4SJeff Roberson ev = corei7_event_table; 2880597979c4SJeff Roberson evfence = corei7_event_table + PMC_EVENT_TABLE_SIZE(corei7); 2881597979c4SJeff Roberson break; 28821fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 28831fa7f10bSFabien Thomas ev = westmere_event_table; 28841fa7f10bSFabien Thomas evfence = westmere_event_table + PMC_EVENT_TABLE_SIZE(westmere); 28851fa7f10bSFabien Thomas break; 28860cfab8ddSJoseph Koshy default: /* Unknown CPU type. */ 28870cfab8ddSJoseph Koshy break; 28880cfab8ddSJoseph Koshy } 28891fa7f10bSFabien Thomas } else if (pe >= PMC_EV_UCF_FIRST && pe <= PMC_EV_UCF_LAST) { 28901fa7f10bSFabien Thomas ev = ucf_event_table; 28911fa7f10bSFabien Thomas evfence = ucf_event_table + PMC_EVENT_TABLE_SIZE(ucf); 28921fa7f10bSFabien Thomas } else if (pe >= PMC_EV_UCP_FIRST && pe <= PMC_EV_UCP_LAST) { 28931fa7f10bSFabien Thomas switch (cpu) { 28941fa7f10bSFabien Thomas case PMC_CPU_INTEL_COREI7: 28951fa7f10bSFabien Thomas ev = corei7uc_event_table; 28961fa7f10bSFabien Thomas evfence = corei7uc_event_table + PMC_EVENT_TABLE_SIZE(corei7uc); 28971fa7f10bSFabien Thomas break; 28981fa7f10bSFabien Thomas case PMC_CPU_INTEL_WESTMERE: 28991fa7f10bSFabien Thomas ev = westmereuc_event_table; 29001fa7f10bSFabien Thomas evfence = westmereuc_event_table + PMC_EVENT_TABLE_SIZE(westmereuc); 29011fa7f10bSFabien Thomas break; 29021fa7f10bSFabien Thomas default: /* Unknown CPU type. */ 29031fa7f10bSFabien Thomas break; 29041fa7f10bSFabien Thomas } 29051fa7f10bSFabien Thomas } else if (pe >= PMC_EV_K7_FIRST && pe <= PMC_EV_K7_LAST) { 2906789140c0SJoseph Koshy ev = k7_event_table; 2907789140c0SJoseph Koshy evfence = k7_event_table + PMC_EVENT_TABLE_SIZE(k7); 2908789140c0SJoseph Koshy } else if (pe >= PMC_EV_K8_FIRST && pe <= PMC_EV_K8_LAST) { 2909789140c0SJoseph Koshy ev = k8_event_table; 2910789140c0SJoseph Koshy evfence = k8_event_table + PMC_EVENT_TABLE_SIZE(k8); 2911789140c0SJoseph Koshy } else if (pe >= PMC_EV_P4_FIRST && pe <= PMC_EV_P4_LAST) { 2912789140c0SJoseph Koshy ev = p4_event_table; 2913789140c0SJoseph Koshy evfence = p4_event_table + PMC_EVENT_TABLE_SIZE(p4); 2914789140c0SJoseph Koshy } else if (pe >= PMC_EV_P5_FIRST && pe <= PMC_EV_P5_LAST) { 2915789140c0SJoseph Koshy ev = p5_event_table; 2916789140c0SJoseph Koshy evfence = p5_event_table + PMC_EVENT_TABLE_SIZE(p5); 2917789140c0SJoseph Koshy } else if (pe >= PMC_EV_P6_FIRST && pe <= PMC_EV_P6_LAST) { 2918789140c0SJoseph Koshy ev = p6_event_table; 2919789140c0SJoseph Koshy evfence = p6_event_table + PMC_EVENT_TABLE_SIZE(p6); 29200ce207d2SRui Paulo } else if (pe >= PMC_EV_XSCALE_FIRST && pe <= PMC_EV_XSCALE_LAST) { 29210ce207d2SRui Paulo ev = xscale_event_table; 29220ce207d2SRui Paulo evfence = xscale_event_table + PMC_EVENT_TABLE_SIZE(xscale); 2923660df75eSGeorge V. Neville-Neil } else if (pe >= PMC_EV_MIPS24K_FIRST && pe <= PMC_EV_MIPS24K_LAST) { 2924660df75eSGeorge V. Neville-Neil ev = mips24k_event_table; 2925660df75eSGeorge V. Neville-Neil evfence = mips24k_event_table + PMC_EVENT_TABLE_SIZE(mips24k 2926660df75eSGeorge V. Neville-Neil ); 2927789140c0SJoseph Koshy } else if (pe == PMC_EV_TSC_TSC) { 2928789140c0SJoseph Koshy ev = tsc_event_table; 2929789140c0SJoseph Koshy evfence = tsc_event_table + PMC_EVENT_TABLE_SIZE(tsc); 2930789140c0SJoseph Koshy } 2931789140c0SJoseph Koshy 2932789140c0SJoseph Koshy for (; ev != evfence; ev++) 2933789140c0SJoseph Koshy if (pe == ev->pm_ev_code) 2934789140c0SJoseph Koshy return (ev->pm_ev_name); 2935f263522aSJoseph Koshy 29360cfab8ddSJoseph Koshy return (NULL); 29370cfab8ddSJoseph Koshy } 29380cfab8ddSJoseph Koshy 29390cfab8ddSJoseph Koshy const char * 29400cfab8ddSJoseph Koshy pmc_name_of_event(enum pmc_event pe) 29410cfab8ddSJoseph Koshy { 29420cfab8ddSJoseph Koshy const char *n; 29430cfab8ddSJoseph Koshy 29440cfab8ddSJoseph Koshy if ((n = _pmc_name_of_event(pe, cpu_info.pm_cputype)) != NULL) 29450cfab8ddSJoseph Koshy return (n); 29460cfab8ddSJoseph Koshy 2947f263522aSJoseph Koshy errno = EINVAL; 2948aa342b1fSJoseph Koshy return (NULL); 2949f263522aSJoseph Koshy } 2950f263522aSJoseph Koshy 2951f263522aSJoseph Koshy const char * 2952f263522aSJoseph Koshy pmc_name_of_mode(enum pmc_mode pm) 2953f263522aSJoseph Koshy { 2954f263522aSJoseph Koshy if ((int) pm >= PMC_MODE_FIRST && 2955f263522aSJoseph Koshy pm <= PMC_MODE_LAST) 2956aa342b1fSJoseph Koshy return (pmc_mode_names[pm]); 2957f263522aSJoseph Koshy 2958f263522aSJoseph Koshy errno = EINVAL; 2959aa342b1fSJoseph Koshy return (NULL); 2960f263522aSJoseph Koshy } 2961f263522aSJoseph Koshy 2962f263522aSJoseph Koshy const char * 2963f263522aSJoseph Koshy pmc_name_of_state(enum pmc_state ps) 2964f263522aSJoseph Koshy { 2965f263522aSJoseph Koshy if ((int) ps >= PMC_STATE_FIRST && 2966f263522aSJoseph Koshy ps <= PMC_STATE_LAST) 2967aa342b1fSJoseph Koshy return (pmc_state_names[ps]); 2968f263522aSJoseph Koshy 2969f263522aSJoseph Koshy errno = EINVAL; 2970aa342b1fSJoseph Koshy return (NULL); 2971f263522aSJoseph Koshy } 2972f263522aSJoseph Koshy 2973f263522aSJoseph Koshy int 2974f263522aSJoseph Koshy pmc_ncpu(void) 2975f263522aSJoseph Koshy { 2976f263522aSJoseph Koshy if (pmc_syscall == -1) { 2977f263522aSJoseph Koshy errno = ENXIO; 2978aa342b1fSJoseph Koshy return (-1); 2979f263522aSJoseph Koshy } 2980f263522aSJoseph Koshy 2981aa342b1fSJoseph Koshy return (cpu_info.pm_ncpu); 2982f263522aSJoseph Koshy } 2983f263522aSJoseph Koshy 2984f263522aSJoseph Koshy int 2985f263522aSJoseph Koshy pmc_npmc(int cpu) 2986f263522aSJoseph Koshy { 2987f263522aSJoseph Koshy if (pmc_syscall == -1) { 2988f263522aSJoseph Koshy errno = ENXIO; 2989aa342b1fSJoseph Koshy return (-1); 2990f263522aSJoseph Koshy } 2991f263522aSJoseph Koshy 2992f263522aSJoseph Koshy if (cpu < 0 || cpu >= (int) cpu_info.pm_ncpu) { 2993f263522aSJoseph Koshy errno = EINVAL; 2994aa342b1fSJoseph Koshy return (-1); 2995f263522aSJoseph Koshy } 2996f263522aSJoseph Koshy 2997aa342b1fSJoseph Koshy return (cpu_info.pm_npmc); 2998f263522aSJoseph Koshy } 2999f263522aSJoseph Koshy 3000f263522aSJoseph Koshy int 3001f263522aSJoseph Koshy pmc_pmcinfo(int cpu, struct pmc_pmcinfo **ppmci) 3002f263522aSJoseph Koshy { 3003f263522aSJoseph Koshy int nbytes, npmc; 3004f263522aSJoseph Koshy struct pmc_op_getpmcinfo *pmci; 3005f263522aSJoseph Koshy 3006f263522aSJoseph Koshy if ((npmc = pmc_npmc(cpu)) < 0) 3007aa342b1fSJoseph Koshy return (-1); 3008f263522aSJoseph Koshy 3009f263522aSJoseph Koshy nbytes = sizeof(struct pmc_op_getpmcinfo) + 3010f263522aSJoseph Koshy npmc * sizeof(struct pmc_info); 3011f263522aSJoseph Koshy 3012f263522aSJoseph Koshy if ((pmci = calloc(1, nbytes)) == NULL) 3013aa342b1fSJoseph Koshy return (-1); 3014f263522aSJoseph Koshy 3015f263522aSJoseph Koshy pmci->pm_cpu = cpu; 3016f263522aSJoseph Koshy 3017f263522aSJoseph Koshy if (PMC_CALL(GETPMCINFO, pmci) < 0) { 3018f263522aSJoseph Koshy free(pmci); 3019aa342b1fSJoseph Koshy return (-1); 3020f263522aSJoseph Koshy } 3021f263522aSJoseph Koshy 3022f263522aSJoseph Koshy /* kernel<->library, library<->userland interfaces are identical */ 3023f263522aSJoseph Koshy *ppmci = (struct pmc_pmcinfo *) pmci; 3024aa342b1fSJoseph Koshy return (0); 3025f263522aSJoseph Koshy } 3026f263522aSJoseph Koshy 3027f263522aSJoseph Koshy int 3028f263522aSJoseph Koshy pmc_read(pmc_id_t pmc, pmc_value_t *value) 3029f263522aSJoseph Koshy { 3030f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_read_op; 3031f263522aSJoseph Koshy 3032f263522aSJoseph Koshy pmc_read_op.pm_pmcid = pmc; 3033f263522aSJoseph Koshy pmc_read_op.pm_flags = PMC_F_OLDVALUE; 3034f263522aSJoseph Koshy pmc_read_op.pm_value = -1; 3035f263522aSJoseph Koshy 3036f263522aSJoseph Koshy if (PMC_CALL(PMCRW, &pmc_read_op) < 0) 3037aa342b1fSJoseph Koshy return (-1); 3038f263522aSJoseph Koshy 3039f263522aSJoseph Koshy *value = pmc_read_op.pm_value; 3040aa342b1fSJoseph Koshy return (0); 3041f263522aSJoseph Koshy } 3042f263522aSJoseph Koshy 3043f263522aSJoseph Koshy int 3044f263522aSJoseph Koshy pmc_release(pmc_id_t pmc) 3045f263522aSJoseph Koshy { 3046f263522aSJoseph Koshy struct pmc_op_simple pmc_release_args; 3047f263522aSJoseph Koshy 3048f263522aSJoseph Koshy pmc_release_args.pm_pmcid = pmc; 3049aa342b1fSJoseph Koshy return (PMC_CALL(PMCRELEASE, &pmc_release_args)); 3050f263522aSJoseph Koshy } 3051f263522aSJoseph Koshy 3052f263522aSJoseph Koshy int 3053f263522aSJoseph Koshy pmc_rw(pmc_id_t pmc, pmc_value_t newvalue, pmc_value_t *oldvaluep) 3054f263522aSJoseph Koshy { 3055f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_rw_op; 3056f263522aSJoseph Koshy 3057f263522aSJoseph Koshy pmc_rw_op.pm_pmcid = pmc; 3058f263522aSJoseph Koshy pmc_rw_op.pm_flags = PMC_F_NEWVALUE | PMC_F_OLDVALUE; 3059f263522aSJoseph Koshy pmc_rw_op.pm_value = newvalue; 3060f263522aSJoseph Koshy 3061f263522aSJoseph Koshy if (PMC_CALL(PMCRW, &pmc_rw_op) < 0) 3062aa342b1fSJoseph Koshy return (-1); 3063f263522aSJoseph Koshy 3064f263522aSJoseph Koshy *oldvaluep = pmc_rw_op.pm_value; 3065aa342b1fSJoseph Koshy return (0); 3066f263522aSJoseph Koshy } 3067f263522aSJoseph Koshy 3068f263522aSJoseph Koshy int 3069f263522aSJoseph Koshy pmc_set(pmc_id_t pmc, pmc_value_t value) 3070f263522aSJoseph Koshy { 3071f263522aSJoseph Koshy struct pmc_op_pmcsetcount sc; 3072f263522aSJoseph Koshy 3073f263522aSJoseph Koshy sc.pm_pmcid = pmc; 3074f263522aSJoseph Koshy sc.pm_count = value; 3075f263522aSJoseph Koshy 3076f263522aSJoseph Koshy if (PMC_CALL(PMCSETCOUNT, &sc) < 0) 3077aa342b1fSJoseph Koshy return (-1); 3078aa342b1fSJoseph Koshy return (0); 3079f263522aSJoseph Koshy } 3080f263522aSJoseph Koshy 3081f263522aSJoseph Koshy int 3082f263522aSJoseph Koshy pmc_start(pmc_id_t pmc) 3083f263522aSJoseph Koshy { 3084f263522aSJoseph Koshy struct pmc_op_simple pmc_start_args; 3085f263522aSJoseph Koshy 3086f263522aSJoseph Koshy pmc_start_args.pm_pmcid = pmc; 3087aa342b1fSJoseph Koshy return (PMC_CALL(PMCSTART, &pmc_start_args)); 3088f263522aSJoseph Koshy } 3089f263522aSJoseph Koshy 3090f263522aSJoseph Koshy int 3091f263522aSJoseph Koshy pmc_stop(pmc_id_t pmc) 3092f263522aSJoseph Koshy { 3093f263522aSJoseph Koshy struct pmc_op_simple pmc_stop_args; 3094f263522aSJoseph Koshy 3095f263522aSJoseph Koshy pmc_stop_args.pm_pmcid = pmc; 3096aa342b1fSJoseph Koshy return (PMC_CALL(PMCSTOP, &pmc_stop_args)); 3097f263522aSJoseph Koshy } 3098f263522aSJoseph Koshy 3099f263522aSJoseph Koshy int 3100f263522aSJoseph Koshy pmc_width(pmc_id_t pmcid, uint32_t *width) 3101f263522aSJoseph Koshy { 3102f263522aSJoseph Koshy unsigned int i; 3103f263522aSJoseph Koshy enum pmc_class cl; 3104f263522aSJoseph Koshy 3105f263522aSJoseph Koshy cl = PMC_ID_TO_CLASS(pmcid); 3106f263522aSJoseph Koshy for (i = 0; i < cpu_info.pm_nclass; i++) 3107f263522aSJoseph Koshy if (cpu_info.pm_classes[i].pm_class == cl) { 3108f263522aSJoseph Koshy *width = cpu_info.pm_classes[i].pm_width; 3109aa342b1fSJoseph Koshy return (0); 3110f263522aSJoseph Koshy } 3111484202faSJoseph Koshy errno = EINVAL; 3112484202faSJoseph Koshy return (-1); 3113f263522aSJoseph Koshy } 3114f263522aSJoseph Koshy 3115f263522aSJoseph Koshy int 3116f263522aSJoseph Koshy pmc_write(pmc_id_t pmc, pmc_value_t value) 3117f263522aSJoseph Koshy { 3118f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_write_op; 3119f263522aSJoseph Koshy 3120f263522aSJoseph Koshy pmc_write_op.pm_pmcid = pmc; 3121f263522aSJoseph Koshy pmc_write_op.pm_flags = PMC_F_NEWVALUE; 3122f263522aSJoseph Koshy pmc_write_op.pm_value = value; 3123aa342b1fSJoseph Koshy return (PMC_CALL(PMCRW, &pmc_write_op)); 3124f263522aSJoseph Koshy } 3125f263522aSJoseph Koshy 3126f263522aSJoseph Koshy int 3127f263522aSJoseph Koshy pmc_writelog(uint32_t userdata) 3128f263522aSJoseph Koshy { 3129f263522aSJoseph Koshy struct pmc_op_writelog wl; 3130f263522aSJoseph Koshy 3131f263522aSJoseph Koshy wl.pm_userdata = userdata; 3132aa342b1fSJoseph Koshy return (PMC_CALL(WRITELOG, &wl)); 3133f263522aSJoseph Koshy } 3134