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 45ebccf1e3SJoseph Koshy /* Function prototypes */ 4604e9feb0SMarcel Moolenaar #if defined(__i386__) 47ebccf1e3SJoseph Koshy static int k7_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 48ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 49f263522aSJoseph Koshy #endif 5086a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 51f263522aSJoseph Koshy static int k8_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 52ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 5386a65549SJoseph Koshy static int p4_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 5486a65549SJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 55f263522aSJoseph Koshy #endif 56f263522aSJoseph Koshy #if defined(__i386__) 57ebccf1e3SJoseph Koshy static int p5_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 58ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 59f263522aSJoseph Koshy static int p6_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 60ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 61ebccf1e3SJoseph Koshy #endif 62789140c0SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 63789140c0SJoseph Koshy static int tsc_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 64789140c0SJoseph Koshy struct pmc_op_pmcallocate *_pmc_config); 65789140c0SJoseph Koshy #endif 66ebccf1e3SJoseph Koshy 67ebccf1e3SJoseph Koshy #define PMC_CALL(cmd, params) \ 68ebccf1e3SJoseph Koshy syscall(pmc_syscall, PMC_OP_##cmd, (params)) 69ebccf1e3SJoseph Koshy 70ebccf1e3SJoseph Koshy /* 71ebccf1e3SJoseph Koshy * Event aliases provide a way for the user to ask for generic events 72ebccf1e3SJoseph Koshy * like "cache-misses", or "instructions-retired". These aliases are 73ebccf1e3SJoseph Koshy * mapped to the appropriate canonical event descriptions using a 74ebccf1e3SJoseph Koshy * lookup table. 75ebccf1e3SJoseph Koshy */ 76ebccf1e3SJoseph Koshy struct pmc_event_alias { 77ebccf1e3SJoseph Koshy const char *pm_alias; 78ebccf1e3SJoseph Koshy const char *pm_spec; 79ebccf1e3SJoseph Koshy }; 80ebccf1e3SJoseph Koshy 81ebccf1e3SJoseph Koshy static const struct pmc_event_alias *pmc_mdep_event_aliases; 82ebccf1e3SJoseph Koshy 83ebccf1e3SJoseph Koshy /* 84789140c0SJoseph Koshy * The pmc_event_descr structure maps symbolic names known to the user 85ebccf1e3SJoseph Koshy * to integer codes used by the PMC KLD. 86ebccf1e3SJoseph Koshy */ 87ebccf1e3SJoseph Koshy struct pmc_event_descr { 88ebccf1e3SJoseph Koshy const char *pm_ev_name; 89ebccf1e3SJoseph Koshy enum pmc_event pm_ev_code; 90ebccf1e3SJoseph Koshy }; 91ebccf1e3SJoseph Koshy 92789140c0SJoseph Koshy /* 93789140c0SJoseph Koshy * The pmc_class_descr structure maps class name prefixes for 94789140c0SJoseph Koshy * event names to event tables and other PMC class data. 95789140c0SJoseph Koshy */ 96789140c0SJoseph Koshy struct pmc_class_descr { 97789140c0SJoseph Koshy const char *pm_evc_name; 98789140c0SJoseph Koshy size_t pm_evc_name_size; 99789140c0SJoseph Koshy enum pmc_class pm_evc_class; 100789140c0SJoseph Koshy const struct pmc_event_descr *pm_evc_event_table; 101789140c0SJoseph Koshy size_t pm_evc_event_table_size; 102789140c0SJoseph Koshy int (*pm_evc_allocate_pmc)(enum pmc_event _pe, 103789140c0SJoseph Koshy char *_ctrspec, struct pmc_op_pmcallocate *_pa); 104ebccf1e3SJoseph Koshy }; 105ebccf1e3SJoseph Koshy 106789140c0SJoseph Koshy #define PMC_TABLE_SIZE(N) (sizeof(N)/sizeof(N[0])) 107789140c0SJoseph Koshy #define PMC_EVENT_TABLE_SIZE(N) PMC_TABLE_SIZE(N##_event_table) 108789140c0SJoseph Koshy 109789140c0SJoseph Koshy #undef __PMC_EV 110789140c0SJoseph Koshy #define __PMC_EV(C,N) { #N, PMC_EV_ ## C ## _ ## N }, 111789140c0SJoseph Koshy 112789140c0SJoseph Koshy /* 113789140c0SJoseph Koshy * PMC_MDEP_TABLE(NAME, CLASS, ADDITIONAL_CLASSES...) 114789140c0SJoseph Koshy * 115789140c0SJoseph Koshy * Build an event descriptor table and a list of valid PMC classes. 116789140c0SJoseph Koshy */ 117789140c0SJoseph Koshy #define PMC_MDEP_TABLE(N,C,...) \ 118789140c0SJoseph Koshy static const struct pmc_event_descr N##_event_table[] = \ 119789140c0SJoseph Koshy { \ 120789140c0SJoseph Koshy __PMC_EV_##C() \ 121789140c0SJoseph Koshy }; \ 122789140c0SJoseph Koshy static const enum pmc_class N##_pmc_classes[] = { \ 123789140c0SJoseph Koshy PMC_CLASS_##C, __VA_ARGS__ \ 124789140c0SJoseph Koshy } 125789140c0SJoseph Koshy 126789140c0SJoseph Koshy PMC_MDEP_TABLE(k7, K7, PMC_CLASS_TSC); 127789140c0SJoseph Koshy PMC_MDEP_TABLE(k8, K8, PMC_CLASS_TSC); 128789140c0SJoseph Koshy PMC_MDEP_TABLE(p4, P4, PMC_CLASS_TSC); 129789140c0SJoseph Koshy PMC_MDEP_TABLE(p5, P5, PMC_CLASS_TSC); 130789140c0SJoseph Koshy PMC_MDEP_TABLE(p6, P6, PMC_CLASS_TSC); 131789140c0SJoseph Koshy 132789140c0SJoseph Koshy static const struct pmc_event_descr tsc_event_table[] = 133789140c0SJoseph Koshy { 134789140c0SJoseph Koshy __PMC_EV_TSC() 135789140c0SJoseph Koshy }; 136789140c0SJoseph Koshy 137789140c0SJoseph Koshy #undef PMC_CLASS_TABLE_DESC 138789140c0SJoseph Koshy #define PMC_CLASS_TABLE_DESC(N, C) { \ 139789140c0SJoseph Koshy .pm_evc_name = #N "-", \ 140789140c0SJoseph Koshy .pm_evc_name_size = sizeof(#N "-") - 1, \ 141789140c0SJoseph Koshy .pm_evc_class = PMC_CLASS_##C , \ 142789140c0SJoseph Koshy .pm_evc_event_table = N##_event_table , \ 143789140c0SJoseph Koshy .pm_evc_event_table_size = \ 144789140c0SJoseph Koshy PMC_EVENT_TABLE_SIZE(N), \ 145789140c0SJoseph Koshy .pm_evc_allocate_pmc = N##_allocate_pmc \ 146789140c0SJoseph Koshy } 147789140c0SJoseph Koshy 148789140c0SJoseph Koshy static const struct pmc_class_descr pmc_class_table[] = 149789140c0SJoseph Koshy { 150789140c0SJoseph Koshy #if defined(__i386__) 151789140c0SJoseph Koshy PMC_CLASS_TABLE_DESC(k7, K7), 152789140c0SJoseph Koshy #endif 153789140c0SJoseph Koshy #if defined(__i386__) || defined(__amd64__) 154789140c0SJoseph Koshy PMC_CLASS_TABLE_DESC(k8, K8), 155789140c0SJoseph Koshy PMC_CLASS_TABLE_DESC(p4, P4), 156789140c0SJoseph Koshy #endif 157789140c0SJoseph Koshy #if defined(__i386__) 158789140c0SJoseph Koshy PMC_CLASS_TABLE_DESC(p5, P5), 159789140c0SJoseph Koshy PMC_CLASS_TABLE_DESC(p6, P6), 160789140c0SJoseph Koshy #endif 161789140c0SJoseph Koshy #if defined(__i386__) || defined(__amd64__) 162789140c0SJoseph Koshy PMC_CLASS_TABLE_DESC(tsc, TSC) 163789140c0SJoseph Koshy #endif 164789140c0SJoseph Koshy }; 165789140c0SJoseph Koshy 166789140c0SJoseph Koshy static size_t pmc_event_class_table_size = 167789140c0SJoseph Koshy PMC_TABLE_SIZE(pmc_class_table); 168789140c0SJoseph Koshy 169789140c0SJoseph Koshy #undef PMC_CLASS_TABLE_DESC 170789140c0SJoseph Koshy 171789140c0SJoseph Koshy static const enum pmc_class *pmc_mdep_class_list; 172789140c0SJoseph Koshy static size_t pmc_mdep_class_list_size; 173789140c0SJoseph Koshy 174ebccf1e3SJoseph Koshy /* 175ebccf1e3SJoseph Koshy * Mapping tables, mapping enumeration values to human readable 176ebccf1e3SJoseph Koshy * strings. 177ebccf1e3SJoseph Koshy */ 178ebccf1e3SJoseph Koshy 179ebccf1e3SJoseph Koshy static const char * pmc_capability_names[] = { 180ebccf1e3SJoseph Koshy #undef __PMC_CAP 181ebccf1e3SJoseph Koshy #define __PMC_CAP(N,V,D) #N , 182ebccf1e3SJoseph Koshy __PMC_CAPS() 183ebccf1e3SJoseph Koshy }; 184ebccf1e3SJoseph Koshy 185ebccf1e3SJoseph Koshy static const char * pmc_class_names[] = { 186ebccf1e3SJoseph Koshy #undef __PMC_CLASS 187ebccf1e3SJoseph Koshy #define __PMC_CLASS(C) #C , 188ebccf1e3SJoseph Koshy __PMC_CLASSES() 189ebccf1e3SJoseph Koshy }; 190ebccf1e3SJoseph Koshy 191789140c0SJoseph Koshy struct pmc_cputype_map { 192789140c0SJoseph Koshy enum pmc_class pm_cputype; 193789140c0SJoseph Koshy const char *pm_name; 194789140c0SJoseph Koshy }; 195789140c0SJoseph Koshy 196789140c0SJoseph Koshy static const struct pmc_cputype_map pmc_cputype_names[] = { 197ebccf1e3SJoseph Koshy #undef __PMC_CPU 198789140c0SJoseph Koshy #define __PMC_CPU(S, V, D) { .pm_cputype = PMC_CPU_##S, .pm_name = #S } , 199ebccf1e3SJoseph Koshy __PMC_CPUS() 200ebccf1e3SJoseph Koshy }; 201ebccf1e3SJoseph Koshy 202ebccf1e3SJoseph Koshy static const char * pmc_disposition_names[] = { 203ebccf1e3SJoseph Koshy #undef __PMC_DISP 204ebccf1e3SJoseph Koshy #define __PMC_DISP(D) #D , 205ebccf1e3SJoseph Koshy __PMC_DISPOSITIONS() 206ebccf1e3SJoseph Koshy }; 207ebccf1e3SJoseph Koshy 208ebccf1e3SJoseph Koshy static const char * pmc_mode_names[] = { 209ebccf1e3SJoseph Koshy #undef __PMC_MODE 210ebccf1e3SJoseph Koshy #define __PMC_MODE(M,N) #M , 211ebccf1e3SJoseph Koshy __PMC_MODES() 212ebccf1e3SJoseph Koshy }; 213ebccf1e3SJoseph Koshy 214ebccf1e3SJoseph Koshy static const char * pmc_state_names[] = { 215ebccf1e3SJoseph Koshy #undef __PMC_STATE 216ebccf1e3SJoseph Koshy #define __PMC_STATE(S) #S , 217ebccf1e3SJoseph Koshy __PMC_STATES() 218ebccf1e3SJoseph Koshy }; 219ebccf1e3SJoseph Koshy 220ebccf1e3SJoseph Koshy static int pmc_syscall = -1; /* filled in by pmc_init() */ 221ebccf1e3SJoseph Koshy 2221455fcd3SJoseph Koshy static struct pmc_cpuinfo cpu_info; /* filled in by pmc_init() */ 2231455fcd3SJoseph Koshy 224ebccf1e3SJoseph Koshy /* Event masks for events */ 225ebccf1e3SJoseph Koshy struct pmc_masks { 226ebccf1e3SJoseph Koshy const char *pm_name; 227ebccf1e3SJoseph Koshy const uint32_t pm_value; 228ebccf1e3SJoseph Koshy }; 229ebccf1e3SJoseph Koshy #define PMCMASK(N,V) { .pm_name = #N, .pm_value = (V) } 230ebccf1e3SJoseph Koshy #define NULLMASK PMCMASK(NULL,0) 231ebccf1e3SJoseph Koshy 23286a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 233ebccf1e3SJoseph Koshy static int 234ebccf1e3SJoseph Koshy pmc_parse_mask(const struct pmc_masks *pmask, char *p, uint32_t *evmask) 235ebccf1e3SJoseph Koshy { 236ebccf1e3SJoseph Koshy const struct pmc_masks *pm; 237ebccf1e3SJoseph Koshy char *q, *r; 238ebccf1e3SJoseph Koshy int c; 239ebccf1e3SJoseph Koshy 240ebccf1e3SJoseph Koshy if (pmask == NULL) /* no mask keywords */ 241aa342b1fSJoseph Koshy return (-1); 242ebccf1e3SJoseph Koshy q = strchr(p, '='); /* skip '=' */ 243ebccf1e3SJoseph Koshy if (*++q == '\0') /* no more data */ 244aa342b1fSJoseph Koshy return (-1); 245ebccf1e3SJoseph Koshy c = 0; /* count of mask keywords seen */ 246ebccf1e3SJoseph Koshy while ((r = strsep(&q, "+")) != NULL) { 247789140c0SJoseph Koshy for (pm = pmask; pm->pm_name && strcasecmp(r, pm->pm_name); 248789140c0SJoseph Koshy pm++) 249ebccf1e3SJoseph Koshy ; 250ebccf1e3SJoseph Koshy if (pm->pm_name == NULL) /* not found */ 251aa342b1fSJoseph Koshy return (-1); 252ebccf1e3SJoseph Koshy *evmask |= pm->pm_value; 253ebccf1e3SJoseph Koshy c++; 254ebccf1e3SJoseph Koshy } 255aa342b1fSJoseph Koshy return (c); 256ebccf1e3SJoseph Koshy } 25704e9feb0SMarcel Moolenaar #endif 258ebccf1e3SJoseph Koshy 259ebccf1e3SJoseph Koshy #define KWMATCH(p,kw) (strcasecmp((p), (kw)) == 0) 260ebccf1e3SJoseph Koshy #define KWPREFIXMATCH(p,kw) (strncasecmp((p), (kw), sizeof((kw)) - 1) == 0) 261ebccf1e3SJoseph Koshy #define EV_ALIAS(N,S) { .pm_alias = N, .pm_spec = S } 262ebccf1e3SJoseph Koshy 26304e9feb0SMarcel Moolenaar #if defined(__i386__) 264ebccf1e3SJoseph Koshy 265ebccf1e3SJoseph Koshy /* 266ebccf1e3SJoseph Koshy * AMD K7 (Athlon) CPUs. 267ebccf1e3SJoseph Koshy */ 268ebccf1e3SJoseph Koshy 269ebccf1e3SJoseph Koshy static struct pmc_event_alias k7_aliases[] = { 270ebccf1e3SJoseph Koshy EV_ALIAS("branches", "k7-retired-branches"), 271ebccf1e3SJoseph Koshy EV_ALIAS("branch-mispredicts", "k7-retired-branches-mispredicted"), 272ebccf1e3SJoseph Koshy EV_ALIAS("cycles", "tsc"), 2736aa5a193SJoseph Koshy EV_ALIAS("dc-misses", "k7-dc-misses"), 274ebccf1e3SJoseph Koshy EV_ALIAS("ic-misses", "k7-ic-misses"), 275ebccf1e3SJoseph Koshy EV_ALIAS("instructions", "k7-retired-instructions"), 276ebccf1e3SJoseph Koshy EV_ALIAS("interrupts", "k7-hardware-interrupts"), 277ebccf1e3SJoseph Koshy EV_ALIAS(NULL, NULL) 278ebccf1e3SJoseph Koshy }; 279ebccf1e3SJoseph Koshy 280ebccf1e3SJoseph Koshy #define K7_KW_COUNT "count" 281ebccf1e3SJoseph Koshy #define K7_KW_EDGE "edge" 282ebccf1e3SJoseph Koshy #define K7_KW_INV "inv" 283ebccf1e3SJoseph Koshy #define K7_KW_OS "os" 284ebccf1e3SJoseph Koshy #define K7_KW_UNITMASK "unitmask" 285ebccf1e3SJoseph Koshy #define K7_KW_USR "usr" 286ebccf1e3SJoseph Koshy 287ebccf1e3SJoseph Koshy static int 288ebccf1e3SJoseph Koshy k7_allocate_pmc(enum pmc_event pe, char *ctrspec, 289ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 290ebccf1e3SJoseph Koshy { 291ebccf1e3SJoseph Koshy char *e, *p, *q; 292ebccf1e3SJoseph Koshy int c, has_unitmask; 293ebccf1e3SJoseph Koshy uint32_t count, unitmask; 294ebccf1e3SJoseph Koshy 295f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 296789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 297ebccf1e3SJoseph Koshy 298ebccf1e3SJoseph Koshy if (pe == PMC_EV_K7_DC_REFILLS_FROM_L2 || 299ebccf1e3SJoseph Koshy pe == PMC_EV_K7_DC_REFILLS_FROM_SYSTEM || 300ebccf1e3SJoseph Koshy pe == PMC_EV_K7_DC_WRITEBACKS) { 301ebccf1e3SJoseph Koshy has_unitmask = 1; 302f263522aSJoseph Koshy unitmask = AMD_PMC_UNITMASK_MOESI; 303ebccf1e3SJoseph Koshy } else 304ebccf1e3SJoseph Koshy unitmask = has_unitmask = 0; 305ebccf1e3SJoseph Koshy 306ebccf1e3SJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 307ebccf1e3SJoseph Koshy if (KWPREFIXMATCH(p, K7_KW_COUNT "=")) { 308ebccf1e3SJoseph Koshy q = strchr(p, '='); 309ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 310aa342b1fSJoseph Koshy return (-1); 311ebccf1e3SJoseph Koshy 312ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 313ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 314aa342b1fSJoseph Koshy return (-1); 315ebccf1e3SJoseph Koshy 316ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 317f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config |= 318f263522aSJoseph Koshy AMD_PMC_TO_COUNTER(count); 319ebccf1e3SJoseph Koshy 320ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_EDGE)) { 321ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 322ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_INV)) { 323ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 324ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_OS)) { 325ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 326ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, K7_KW_UNITMASK "=")) { 327ebccf1e3SJoseph Koshy if (has_unitmask == 0) 328aa342b1fSJoseph Koshy return (-1); 329ebccf1e3SJoseph Koshy unitmask = 0; 330ebccf1e3SJoseph Koshy q = strchr(p, '='); 331ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 332aa342b1fSJoseph Koshy return (-1); 333ebccf1e3SJoseph Koshy 334ebccf1e3SJoseph Koshy while ((c = tolower(*q++)) != 0) 335ebccf1e3SJoseph Koshy if (c == 'm') 336f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_M; 337ebccf1e3SJoseph Koshy else if (c == 'o') 338f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_O; 339ebccf1e3SJoseph Koshy else if (c == 'e') 340f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_E; 341ebccf1e3SJoseph Koshy else if (c == 's') 342f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_S; 343ebccf1e3SJoseph Koshy else if (c == 'i') 344f263522aSJoseph Koshy unitmask |= AMD_PMC_UNITMASK_I; 345ebccf1e3SJoseph Koshy else if (c == '+') 346ebccf1e3SJoseph Koshy continue; 347ebccf1e3SJoseph Koshy else 348aa342b1fSJoseph Koshy return (-1); 349ebccf1e3SJoseph Koshy 350ebccf1e3SJoseph Koshy if (unitmask == 0) 351aa342b1fSJoseph Koshy return (-1); 352ebccf1e3SJoseph Koshy 353ebccf1e3SJoseph Koshy } else if (KWMATCH(p, K7_KW_USR)) { 354ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 355ebccf1e3SJoseph Koshy } else 356aa342b1fSJoseph Koshy return (-1); 357ebccf1e3SJoseph Koshy } 358ebccf1e3SJoseph Koshy 359ebccf1e3SJoseph Koshy if (has_unitmask) { 360ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 361f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config |= 362f263522aSJoseph Koshy AMD_PMC_TO_UNITMASK(unitmask); 363ebccf1e3SJoseph Koshy } 364ebccf1e3SJoseph Koshy 365aa342b1fSJoseph Koshy return (0); 366ebccf1e3SJoseph Koshy 367ebccf1e3SJoseph Koshy } 368ebccf1e3SJoseph Koshy 369f263522aSJoseph Koshy #endif 370f263522aSJoseph Koshy 37186a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 372f263522aSJoseph Koshy 373f263522aSJoseph Koshy /* 374f263522aSJoseph Koshy * AMD K8 PMCs. 375f263522aSJoseph Koshy * 376f263522aSJoseph Koshy * These are very similar to AMD K7 PMCs, but support more kinds of 377f263522aSJoseph Koshy * events. 378f263522aSJoseph Koshy */ 379f263522aSJoseph Koshy 380f263522aSJoseph Koshy static struct pmc_event_alias k8_aliases[] = { 381f263522aSJoseph Koshy EV_ALIAS("branches", "k8-fr-retired-taken-branches"), 382f263522aSJoseph Koshy EV_ALIAS("branch-mispredicts", 383f263522aSJoseph Koshy "k8-fr-retired-taken-branches-mispredicted"), 384f263522aSJoseph Koshy EV_ALIAS("cycles", "tsc"), 385f263522aSJoseph Koshy EV_ALIAS("dc-misses", "k8-dc-miss"), 386f263522aSJoseph Koshy EV_ALIAS("ic-misses", "k8-ic-miss"), 387f263522aSJoseph Koshy EV_ALIAS("instructions", "k8-fr-retired-x86-instructions"), 388f263522aSJoseph Koshy EV_ALIAS("interrupts", "k8-fr-taken-hardware-interrupts"), 389177a2f22SJoseph Koshy EV_ALIAS("unhalted-cycles", "k8-bu-cpu-clk-unhalted"), 390f263522aSJoseph Koshy EV_ALIAS(NULL, NULL) 391f263522aSJoseph Koshy }; 392f263522aSJoseph Koshy 393f263522aSJoseph Koshy #define __K8MASK(N,V) PMCMASK(N,(1 << (V))) 394f263522aSJoseph Koshy 395f263522aSJoseph Koshy /* 396f263522aSJoseph Koshy * Parsing tables 397f263522aSJoseph Koshy */ 398f263522aSJoseph Koshy 399f263522aSJoseph Koshy /* fp dispatched fpu ops */ 400f263522aSJoseph Koshy static const struct pmc_masks k8_mask_fdfo[] = { 401f263522aSJoseph Koshy __K8MASK(add-pipe-excluding-junk-ops, 0), 402f263522aSJoseph Koshy __K8MASK(multiply-pipe-excluding-junk-ops, 1), 403f263522aSJoseph Koshy __K8MASK(store-pipe-excluding-junk-ops, 2), 404f263522aSJoseph Koshy __K8MASK(add-pipe-junk-ops, 3), 405f263522aSJoseph Koshy __K8MASK(multiply-pipe-junk-ops, 4), 406f263522aSJoseph Koshy __K8MASK(store-pipe-junk-ops, 5), 407f263522aSJoseph Koshy NULLMASK 408f263522aSJoseph Koshy }; 409f263522aSJoseph Koshy 410f263522aSJoseph Koshy /* ls segment register loads */ 411f263522aSJoseph Koshy static const struct pmc_masks k8_mask_lsrl[] = { 412f263522aSJoseph Koshy __K8MASK(es, 0), 413f263522aSJoseph Koshy __K8MASK(cs, 1), 414f263522aSJoseph Koshy __K8MASK(ss, 2), 415f263522aSJoseph Koshy __K8MASK(ds, 3), 416f263522aSJoseph Koshy __K8MASK(fs, 4), 417f263522aSJoseph Koshy __K8MASK(gs, 5), 418f263522aSJoseph Koshy __K8MASK(hs, 6), 419f263522aSJoseph Koshy NULLMASK 420f263522aSJoseph Koshy }; 421f263522aSJoseph Koshy 422f263522aSJoseph Koshy /* ls locked operation */ 423f263522aSJoseph Koshy static const struct pmc_masks k8_mask_llo[] = { 424f263522aSJoseph Koshy __K8MASK(locked-instructions, 0), 425f263522aSJoseph Koshy __K8MASK(cycles-in-request, 1), 426f263522aSJoseph Koshy __K8MASK(cycles-to-complete, 2), 427f263522aSJoseph Koshy NULLMASK 428f263522aSJoseph Koshy }; 429f263522aSJoseph Koshy 430f263522aSJoseph Koshy /* dc refill from {l2,system} and dc copyback */ 431f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dc[] = { 432f263522aSJoseph Koshy __K8MASK(invalid, 0), 433f263522aSJoseph Koshy __K8MASK(shared, 1), 434f263522aSJoseph Koshy __K8MASK(exclusive, 2), 435f263522aSJoseph Koshy __K8MASK(owner, 3), 436f263522aSJoseph Koshy __K8MASK(modified, 4), 437f263522aSJoseph Koshy NULLMASK 438f263522aSJoseph Koshy }; 439f263522aSJoseph Koshy 440f263522aSJoseph Koshy /* dc one bit ecc error */ 441f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dobee[] = { 442f263522aSJoseph Koshy __K8MASK(scrubber, 0), 443f263522aSJoseph Koshy __K8MASK(piggyback, 1), 444f263522aSJoseph Koshy NULLMASK 445f263522aSJoseph Koshy }; 446f263522aSJoseph Koshy 447f263522aSJoseph Koshy /* dc dispatched prefetch instructions */ 448f263522aSJoseph Koshy static const struct pmc_masks k8_mask_ddpi[] = { 449f263522aSJoseph Koshy __K8MASK(load, 0), 450f263522aSJoseph Koshy __K8MASK(store, 1), 451f263522aSJoseph Koshy __K8MASK(nta, 2), 452f263522aSJoseph Koshy NULLMASK 453f263522aSJoseph Koshy }; 454f263522aSJoseph Koshy 455f263522aSJoseph Koshy /* dc dcache accesses by locks */ 456f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dabl[] = { 457f263522aSJoseph Koshy __K8MASK(accesses, 0), 458f263522aSJoseph Koshy __K8MASK(misses, 1), 459f263522aSJoseph Koshy NULLMASK 460f263522aSJoseph Koshy }; 461f263522aSJoseph Koshy 462f263522aSJoseph Koshy /* bu internal l2 request */ 463f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bilr[] = { 464f263522aSJoseph Koshy __K8MASK(ic-fill, 0), 465f263522aSJoseph Koshy __K8MASK(dc-fill, 1), 466f263522aSJoseph Koshy __K8MASK(tlb-reload, 2), 467f263522aSJoseph Koshy __K8MASK(tag-snoop, 3), 468f263522aSJoseph Koshy __K8MASK(cancelled, 4), 469f263522aSJoseph Koshy NULLMASK 470f263522aSJoseph Koshy }; 471f263522aSJoseph Koshy 472f263522aSJoseph Koshy /* bu fill request l2 miss */ 473f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bfrlm[] = { 474f263522aSJoseph Koshy __K8MASK(ic-fill, 0), 475f263522aSJoseph Koshy __K8MASK(dc-fill, 1), 476f263522aSJoseph Koshy __K8MASK(tlb-reload, 2), 477f263522aSJoseph Koshy NULLMASK 478f263522aSJoseph Koshy }; 479f263522aSJoseph Koshy 480f263522aSJoseph Koshy /* bu fill into l2 */ 481f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bfil[] = { 482f263522aSJoseph Koshy __K8MASK(dirty-l2-victim, 0), 483f263522aSJoseph Koshy __K8MASK(victim-from-l2, 1), 484f263522aSJoseph Koshy NULLMASK 485f263522aSJoseph Koshy }; 486f263522aSJoseph Koshy 487f263522aSJoseph Koshy /* fr retired fpu instructions */ 488f263522aSJoseph Koshy static const struct pmc_masks k8_mask_frfi[] = { 489f263522aSJoseph Koshy __K8MASK(x87, 0), 490f263522aSJoseph Koshy __K8MASK(mmx-3dnow, 1), 491f263522aSJoseph Koshy __K8MASK(packed-sse-sse2, 2), 492f263522aSJoseph Koshy __K8MASK(scalar-sse-sse2, 3), 493f263522aSJoseph Koshy NULLMASK 494f263522aSJoseph Koshy }; 495f263522aSJoseph Koshy 496f263522aSJoseph Koshy /* fr retired fastpath double op instructions */ 497f263522aSJoseph Koshy static const struct pmc_masks k8_mask_frfdoi[] = { 498f263522aSJoseph Koshy __K8MASK(low-op-pos-0, 0), 499f263522aSJoseph Koshy __K8MASK(low-op-pos-1, 1), 500f263522aSJoseph Koshy __K8MASK(low-op-pos-2, 2), 501f263522aSJoseph Koshy NULLMASK 502f263522aSJoseph Koshy }; 503f263522aSJoseph Koshy 504f263522aSJoseph Koshy /* fr fpu exceptions */ 505f263522aSJoseph Koshy static const struct pmc_masks k8_mask_ffe[] = { 506f263522aSJoseph Koshy __K8MASK(x87-reclass-microfaults, 0), 507f263522aSJoseph Koshy __K8MASK(sse-retype-microfaults, 1), 508f263522aSJoseph Koshy __K8MASK(sse-reclass-microfaults, 2), 509f263522aSJoseph Koshy __K8MASK(sse-and-x87-microtraps, 3), 510f263522aSJoseph Koshy NULLMASK 511f263522aSJoseph Koshy }; 512f263522aSJoseph Koshy 513f263522aSJoseph Koshy /* nb memory controller page access event */ 514f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmcpae[] = { 515f263522aSJoseph Koshy __K8MASK(page-hit, 0), 516f263522aSJoseph Koshy __K8MASK(page-miss, 1), 517f263522aSJoseph Koshy __K8MASK(page-conflict, 2), 518f263522aSJoseph Koshy NULLMASK 519f263522aSJoseph Koshy }; 520f263522aSJoseph Koshy 521f263522aSJoseph Koshy /* nb memory controller turnaround */ 522f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmct[] = { 523f263522aSJoseph Koshy __K8MASK(dimm-turnaround, 0), 524f263522aSJoseph Koshy __K8MASK(read-to-write-turnaround, 1), 525f263522aSJoseph Koshy __K8MASK(write-to-read-turnaround, 2), 526f263522aSJoseph Koshy NULLMASK 527f263522aSJoseph Koshy }; 528f263522aSJoseph Koshy 529f263522aSJoseph Koshy /* nb memory controller bypass saturation */ 530f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmcbs[] = { 531f263522aSJoseph Koshy __K8MASK(memory-controller-hi-pri-bypass, 0), 532f263522aSJoseph Koshy __K8MASK(memory-controller-lo-pri-bypass, 1), 533f263522aSJoseph Koshy __K8MASK(dram-controller-interface-bypass, 2), 534f263522aSJoseph Koshy __K8MASK(dram-controller-queue-bypass, 3), 535f263522aSJoseph Koshy NULLMASK 536f263522aSJoseph Koshy }; 537f263522aSJoseph Koshy 538f263522aSJoseph Koshy /* nb sized commands */ 539f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nsc[] = { 540f263522aSJoseph Koshy __K8MASK(nonpostwrszbyte, 0), 541f263522aSJoseph Koshy __K8MASK(nonpostwrszdword, 1), 542f263522aSJoseph Koshy __K8MASK(postwrszbyte, 2), 543f263522aSJoseph Koshy __K8MASK(postwrszdword, 3), 544f263522aSJoseph Koshy __K8MASK(rdszbyte, 4), 545f263522aSJoseph Koshy __K8MASK(rdszdword, 5), 546f263522aSJoseph Koshy __K8MASK(rdmodwr, 6), 547f263522aSJoseph Koshy NULLMASK 548f263522aSJoseph Koshy }; 549f263522aSJoseph Koshy 550f263522aSJoseph Koshy /* nb probe result */ 551f263522aSJoseph Koshy static const struct pmc_masks k8_mask_npr[] = { 552f263522aSJoseph Koshy __K8MASK(probe-miss, 0), 553f263522aSJoseph Koshy __K8MASK(probe-hit, 1), 554f263522aSJoseph Koshy __K8MASK(probe-hit-dirty-no-memory-cancel, 2), 555f263522aSJoseph Koshy __K8MASK(probe-hit-dirty-with-memory-cancel, 3), 556f263522aSJoseph Koshy NULLMASK 557f263522aSJoseph Koshy }; 558f263522aSJoseph Koshy 559f263522aSJoseph Koshy /* nb hypertransport bus bandwidth */ 560f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nhbb[] = { /* HT bus bandwidth */ 561f263522aSJoseph Koshy __K8MASK(command, 0), 562f263522aSJoseph Koshy __K8MASK(data, 1), 563f263522aSJoseph Koshy __K8MASK(buffer-release, 2), 564f263522aSJoseph Koshy __K8MASK(nop, 3), 565f263522aSJoseph Koshy NULLMASK 566f263522aSJoseph Koshy }; 567f263522aSJoseph Koshy 568f263522aSJoseph Koshy #undef __K8MASK 569f263522aSJoseph Koshy 570f263522aSJoseph Koshy #define K8_KW_COUNT "count" 571f263522aSJoseph Koshy #define K8_KW_EDGE "edge" 572f263522aSJoseph Koshy #define K8_KW_INV "inv" 573f263522aSJoseph Koshy #define K8_KW_MASK "mask" 574f263522aSJoseph Koshy #define K8_KW_OS "os" 575f263522aSJoseph Koshy #define K8_KW_USR "usr" 576f263522aSJoseph Koshy 577f263522aSJoseph Koshy static int 578f263522aSJoseph Koshy k8_allocate_pmc(enum pmc_event pe, char *ctrspec, 579f263522aSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 580f263522aSJoseph Koshy { 581f263522aSJoseph Koshy char *e, *p, *q; 582f263522aSJoseph Koshy int n; 583f263522aSJoseph Koshy uint32_t count, evmask; 584f263522aSJoseph Koshy const struct pmc_masks *pm, *pmask; 585f263522aSJoseph Koshy 586789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 587f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 588f263522aSJoseph Koshy 589f263522aSJoseph Koshy pmask = NULL; 590f263522aSJoseph Koshy evmask = 0; 591f263522aSJoseph Koshy 592f263522aSJoseph Koshy #define __K8SETMASK(M) pmask = k8_mask_##M 593f263522aSJoseph Koshy 594f263522aSJoseph Koshy /* setup parsing tables */ 595f263522aSJoseph Koshy switch (pe) { 596f263522aSJoseph Koshy case PMC_EV_K8_FP_DISPATCHED_FPU_OPS: 597f263522aSJoseph Koshy __K8SETMASK(fdfo); 598f263522aSJoseph Koshy break; 599f263522aSJoseph Koshy case PMC_EV_K8_LS_SEGMENT_REGISTER_LOAD: 600f263522aSJoseph Koshy __K8SETMASK(lsrl); 601f263522aSJoseph Koshy break; 602f263522aSJoseph Koshy case PMC_EV_K8_LS_LOCKED_OPERATION: 603f263522aSJoseph Koshy __K8SETMASK(llo); 604f263522aSJoseph Koshy break; 605f263522aSJoseph Koshy case PMC_EV_K8_DC_REFILL_FROM_L2: 606f263522aSJoseph Koshy case PMC_EV_K8_DC_REFILL_FROM_SYSTEM: 607f263522aSJoseph Koshy case PMC_EV_K8_DC_COPYBACK: 608f263522aSJoseph Koshy __K8SETMASK(dc); 609f263522aSJoseph Koshy break; 610f263522aSJoseph Koshy case PMC_EV_K8_DC_ONE_BIT_ECC_ERROR: 611f263522aSJoseph Koshy __K8SETMASK(dobee); 612f263522aSJoseph Koshy break; 613f263522aSJoseph Koshy case PMC_EV_K8_DC_DISPATCHED_PREFETCH_INSTRUCTIONS: 614f263522aSJoseph Koshy __K8SETMASK(ddpi); 615f263522aSJoseph Koshy break; 616f263522aSJoseph Koshy case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS: 617f263522aSJoseph Koshy __K8SETMASK(dabl); 618f263522aSJoseph Koshy break; 619f263522aSJoseph Koshy case PMC_EV_K8_BU_INTERNAL_L2_REQUEST: 620f263522aSJoseph Koshy __K8SETMASK(bilr); 621f263522aSJoseph Koshy break; 622f263522aSJoseph Koshy case PMC_EV_K8_BU_FILL_REQUEST_L2_MISS: 623f263522aSJoseph Koshy __K8SETMASK(bfrlm); 624f263522aSJoseph Koshy break; 625f263522aSJoseph Koshy case PMC_EV_K8_BU_FILL_INTO_L2: 626f263522aSJoseph Koshy __K8SETMASK(bfil); 627f263522aSJoseph Koshy break; 628f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS: 629f263522aSJoseph Koshy __K8SETMASK(frfi); 630f263522aSJoseph Koshy break; 631f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS: 632f263522aSJoseph Koshy __K8SETMASK(frfdoi); 633f263522aSJoseph Koshy break; 634f263522aSJoseph Koshy case PMC_EV_K8_FR_FPU_EXCEPTIONS: 635f263522aSJoseph Koshy __K8SETMASK(ffe); 636f263522aSJoseph Koshy break; 637f263522aSJoseph Koshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_PAGE_ACCESS_EVENT: 638f263522aSJoseph Koshy __K8SETMASK(nmcpae); 639f263522aSJoseph Koshy break; 640f263522aSJoseph Koshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_TURNAROUND: 641f263522aSJoseph Koshy __K8SETMASK(nmct); 642f263522aSJoseph Koshy break; 643f263522aSJoseph Koshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_BYPASS_SATURATION: 644f263522aSJoseph Koshy __K8SETMASK(nmcbs); 645f263522aSJoseph Koshy break; 646f263522aSJoseph Koshy case PMC_EV_K8_NB_SIZED_COMMANDS: 647f263522aSJoseph Koshy __K8SETMASK(nsc); 648f263522aSJoseph Koshy break; 649f263522aSJoseph Koshy case PMC_EV_K8_NB_PROBE_RESULT: 650f263522aSJoseph Koshy __K8SETMASK(npr); 651f263522aSJoseph Koshy break; 652f263522aSJoseph Koshy case PMC_EV_K8_NB_HT_BUS0_BANDWIDTH: 653f263522aSJoseph Koshy case PMC_EV_K8_NB_HT_BUS1_BANDWIDTH: 654f263522aSJoseph Koshy case PMC_EV_K8_NB_HT_BUS2_BANDWIDTH: 655f263522aSJoseph Koshy __K8SETMASK(nhbb); 656f263522aSJoseph Koshy break; 657f263522aSJoseph Koshy 658f263522aSJoseph Koshy default: 659f263522aSJoseph Koshy break; /* no options defined */ 660f263522aSJoseph Koshy } 661f263522aSJoseph Koshy 662f263522aSJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 663f263522aSJoseph Koshy if (KWPREFIXMATCH(p, K8_KW_COUNT "=")) { 664f263522aSJoseph Koshy q = strchr(p, '='); 665f263522aSJoseph Koshy if (*++q == '\0') /* skip '=' */ 666aa342b1fSJoseph Koshy return (-1); 667f263522aSJoseph Koshy 668f263522aSJoseph Koshy count = strtol(q, &e, 0); 669f263522aSJoseph Koshy if (e == q || *e != '\0') 670aa342b1fSJoseph Koshy return (-1); 671f263522aSJoseph Koshy 672f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 673f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config |= 674f263522aSJoseph Koshy AMD_PMC_TO_COUNTER(count); 675f263522aSJoseph Koshy 676f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_EDGE)) { 677f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 678f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_INV)) { 679f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 680f263522aSJoseph Koshy } else if (KWPREFIXMATCH(p, K8_KW_MASK "=")) { 681f263522aSJoseph Koshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 682aa342b1fSJoseph Koshy return (-1); 683f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 684f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_OS)) { 685f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 686f263522aSJoseph Koshy } else if (KWMATCH(p, K8_KW_USR)) { 687f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 688f263522aSJoseph Koshy } else 689aa342b1fSJoseph Koshy return (-1); 690f263522aSJoseph Koshy } 691f263522aSJoseph Koshy 692f263522aSJoseph Koshy /* other post processing */ 693f263522aSJoseph Koshy switch (pe) { 694f263522aSJoseph Koshy case PMC_EV_K8_FP_DISPATCHED_FPU_OPS: 695f263522aSJoseph Koshy case PMC_EV_K8_FP_CYCLES_WITH_NO_FPU_OPS_RETIRED: 696f263522aSJoseph Koshy case PMC_EV_K8_FP_DISPATCHED_FPU_FAST_FLAG_OPS: 697f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS: 698f263522aSJoseph Koshy case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS: 699f263522aSJoseph Koshy case PMC_EV_K8_FR_FPU_EXCEPTIONS: 700f263522aSJoseph Koshy /* XXX only available in rev B and later */ 701f263522aSJoseph Koshy break; 702f263522aSJoseph Koshy case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS: 703f263522aSJoseph Koshy /* XXX only available in rev C and later */ 704f263522aSJoseph Koshy break; 705f263522aSJoseph Koshy case PMC_EV_K8_LS_LOCKED_OPERATION: 706f263522aSJoseph Koshy /* XXX CPU Rev A,B evmask is to be zero */ 707f263522aSJoseph Koshy if (evmask & (evmask - 1)) /* > 1 bit set */ 708aa342b1fSJoseph Koshy return (-1); 709f263522aSJoseph Koshy if (evmask == 0) { 710f263522aSJoseph Koshy evmask = 0x01; /* Rev C and later: #instrs */ 711f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 712f263522aSJoseph Koshy } 713f263522aSJoseph Koshy break; 714f263522aSJoseph Koshy default: 715f263522aSJoseph Koshy if (evmask == 0 && pmask != NULL) { 716f263522aSJoseph Koshy for (pm = pmask; pm->pm_name; pm++) 717f263522aSJoseph Koshy evmask |= pm->pm_value; 718f263522aSJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 719f263522aSJoseph Koshy } 720f263522aSJoseph Koshy } 721f263522aSJoseph Koshy 722f263522aSJoseph Koshy if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) 723f263522aSJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 724f263522aSJoseph Koshy AMD_PMC_TO_UNITMASK(evmask); 725f263522aSJoseph Koshy 726aa342b1fSJoseph Koshy return (0); 727f263522aSJoseph Koshy } 728f263522aSJoseph Koshy 729f263522aSJoseph Koshy #endif 730f263522aSJoseph Koshy 73186a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 732f263522aSJoseph Koshy 733ebccf1e3SJoseph Koshy /* 734ebccf1e3SJoseph Koshy * Intel P4 PMCs 735ebccf1e3SJoseph Koshy */ 736ebccf1e3SJoseph Koshy 737ebccf1e3SJoseph Koshy static struct pmc_event_alias p4_aliases[] = { 738d56c5d4bSJoseph Koshy EV_ALIAS("branches", "p4-branch-retired,mask=mmtp+mmtm"), 739d56c5d4bSJoseph Koshy EV_ALIAS("branch-mispredicts", "p4-mispred-branch-retired"), 740ebccf1e3SJoseph Koshy EV_ALIAS("cycles", "tsc"), 741d56c5d4bSJoseph Koshy EV_ALIAS("instructions", 742d56c5d4bSJoseph Koshy "p4-instr-retired,mask=nbogusntag+nbogustag"), 743177a2f22SJoseph Koshy EV_ALIAS("unhalted-cycles", "p4-global-power-events"), 744ebccf1e3SJoseph Koshy EV_ALIAS(NULL, NULL) 745ebccf1e3SJoseph Koshy }; 746ebccf1e3SJoseph Koshy 747ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE "active" 748ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_ANY "any" 749ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_BOTH "both" 750ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_NONE "none" 751ebccf1e3SJoseph Koshy #define P4_KW_ACTIVE_SINGLE "single" 752ebccf1e3SJoseph Koshy #define P4_KW_BUSREQTYPE "busreqtype" 753ebccf1e3SJoseph Koshy #define P4_KW_CASCADE "cascade" 754ebccf1e3SJoseph Koshy #define P4_KW_EDGE "edge" 755ebccf1e3SJoseph Koshy #define P4_KW_INV "complement" 756ebccf1e3SJoseph Koshy #define P4_KW_OS "os" 757ebccf1e3SJoseph Koshy #define P4_KW_MASK "mask" 758ebccf1e3SJoseph Koshy #define P4_KW_PRECISE "precise" 759ebccf1e3SJoseph Koshy #define P4_KW_TAG "tag" 760ebccf1e3SJoseph Koshy #define P4_KW_THRESHOLD "threshold" 761ebccf1e3SJoseph Koshy #define P4_KW_USR "usr" 762ebccf1e3SJoseph Koshy 763ebccf1e3SJoseph Koshy #define __P4MASK(N,V) PMCMASK(N, (1 << (V))) 764ebccf1e3SJoseph Koshy 765ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_tcdm[] = { /* tc deliver mode */ 766ebccf1e3SJoseph Koshy __P4MASK(dd, 0), 767ebccf1e3SJoseph Koshy __P4MASK(db, 1), 768ebccf1e3SJoseph Koshy __P4MASK(di, 2), 769ebccf1e3SJoseph Koshy __P4MASK(bd, 3), 770ebccf1e3SJoseph Koshy __P4MASK(bb, 4), 771ebccf1e3SJoseph Koshy __P4MASK(bi, 5), 772ebccf1e3SJoseph Koshy __P4MASK(id, 6), 773ebccf1e3SJoseph Koshy __P4MASK(ib, 7), 774ebccf1e3SJoseph Koshy NULLMASK 775ebccf1e3SJoseph Koshy }; 776ebccf1e3SJoseph Koshy 777ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_bfr[] = { /* bpu fetch request */ 778ebccf1e3SJoseph Koshy __P4MASK(tcmiss, 0), 779ebccf1e3SJoseph Koshy NULLMASK, 780ebccf1e3SJoseph Koshy }; 781ebccf1e3SJoseph Koshy 782ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ir[] = { /* itlb reference */ 783ebccf1e3SJoseph Koshy __P4MASK(hit, 0), 784ebccf1e3SJoseph Koshy __P4MASK(miss, 1), 785ebccf1e3SJoseph Koshy __P4MASK(hit-uc, 2), 786ebccf1e3SJoseph Koshy NULLMASK 787ebccf1e3SJoseph Koshy }; 788ebccf1e3SJoseph Koshy 789ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_memcan[] = { /* memory cancel */ 790ebccf1e3SJoseph Koshy __P4MASK(st-rb-full, 2), 791ebccf1e3SJoseph Koshy __P4MASK(64k-conf, 3), 792ebccf1e3SJoseph Koshy NULLMASK 793ebccf1e3SJoseph Koshy }; 794ebccf1e3SJoseph Koshy 795ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_memcomp[] = { /* memory complete */ 796ebccf1e3SJoseph Koshy __P4MASK(lsc, 0), 797ebccf1e3SJoseph Koshy __P4MASK(ssc, 1), 798ebccf1e3SJoseph Koshy NULLMASK 799ebccf1e3SJoseph Koshy }; 800ebccf1e3SJoseph Koshy 801ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_lpr[] = { /* load port replay */ 802ebccf1e3SJoseph Koshy __P4MASK(split-ld, 1), 803ebccf1e3SJoseph Koshy NULLMASK 804ebccf1e3SJoseph Koshy }; 805ebccf1e3SJoseph Koshy 806ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_spr[] = { /* store port replay */ 807ebccf1e3SJoseph Koshy __P4MASK(split-st, 1), 808ebccf1e3SJoseph Koshy NULLMASK 809ebccf1e3SJoseph Koshy }; 810ebccf1e3SJoseph Koshy 811ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_mlr[] = { /* mob load replay */ 812ebccf1e3SJoseph Koshy __P4MASK(no-sta, 1), 813ebccf1e3SJoseph Koshy __P4MASK(no-std, 3), 814ebccf1e3SJoseph Koshy __P4MASK(partial-data, 4), 815ebccf1e3SJoseph Koshy __P4MASK(unalgn-addr, 5), 816ebccf1e3SJoseph Koshy NULLMASK 817ebccf1e3SJoseph Koshy }; 818ebccf1e3SJoseph Koshy 819ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_pwt[] = { /* page walk type */ 820ebccf1e3SJoseph Koshy __P4MASK(dtmiss, 0), 821ebccf1e3SJoseph Koshy __P4MASK(itmiss, 1), 822ebccf1e3SJoseph Koshy NULLMASK 823ebccf1e3SJoseph Koshy }; 824ebccf1e3SJoseph Koshy 825ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_bcr[] = { /* bsq cache reference */ 826ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-hits, 0), 827ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-hite, 1), 828ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-hitm, 2), 829ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-hits, 3), 830ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-hite, 4), 831ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-hitm, 5), 832ebccf1e3SJoseph Koshy __P4MASK(rd-2ndl-miss, 8), 833ebccf1e3SJoseph Koshy __P4MASK(rd-3rdl-miss, 9), 834ebccf1e3SJoseph Koshy __P4MASK(wr-2ndl-miss, 10), 835ebccf1e3SJoseph Koshy NULLMASK 836ebccf1e3SJoseph Koshy }; 837ebccf1e3SJoseph Koshy 838ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ia[] = { /* ioq allocation */ 839ebccf1e3SJoseph Koshy __P4MASK(all-read, 5), 840ebccf1e3SJoseph Koshy __P4MASK(all-write, 6), 841ebccf1e3SJoseph Koshy __P4MASK(mem-uc, 7), 842ebccf1e3SJoseph Koshy __P4MASK(mem-wc, 8), 843ebccf1e3SJoseph Koshy __P4MASK(mem-wt, 9), 844ebccf1e3SJoseph Koshy __P4MASK(mem-wp, 10), 845ebccf1e3SJoseph Koshy __P4MASK(mem-wb, 11), 846ebccf1e3SJoseph Koshy __P4MASK(own, 13), 847ebccf1e3SJoseph Koshy __P4MASK(other, 14), 848ebccf1e3SJoseph Koshy __P4MASK(prefetch, 15), 849ebccf1e3SJoseph Koshy NULLMASK 850ebccf1e3SJoseph Koshy }; 851ebccf1e3SJoseph Koshy 852ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_iae[] = { /* ioq active entries */ 853ebccf1e3SJoseph Koshy __P4MASK(all-read, 5), 854ebccf1e3SJoseph Koshy __P4MASK(all-write, 6), 855ebccf1e3SJoseph Koshy __P4MASK(mem-uc, 7), 856ebccf1e3SJoseph Koshy __P4MASK(mem-wc, 8), 857ebccf1e3SJoseph Koshy __P4MASK(mem-wt, 9), 858ebccf1e3SJoseph Koshy __P4MASK(mem-wp, 10), 859ebccf1e3SJoseph Koshy __P4MASK(mem-wb, 11), 860ebccf1e3SJoseph Koshy __P4MASK(own, 13), 861ebccf1e3SJoseph Koshy __P4MASK(other, 14), 862ebccf1e3SJoseph Koshy __P4MASK(prefetch, 15), 863ebccf1e3SJoseph Koshy NULLMASK 864ebccf1e3SJoseph Koshy }; 865ebccf1e3SJoseph Koshy 866ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_fda[] = { /* fsb data activity */ 867ebccf1e3SJoseph Koshy __P4MASK(drdy-drv, 0), 868ebccf1e3SJoseph Koshy __P4MASK(drdy-own, 1), 869ebccf1e3SJoseph Koshy __P4MASK(drdy-other, 2), 870ebccf1e3SJoseph Koshy __P4MASK(dbsy-drv, 3), 871ebccf1e3SJoseph Koshy __P4MASK(dbsy-own, 4), 872ebccf1e3SJoseph Koshy __P4MASK(dbsy-other, 5), 873ebccf1e3SJoseph Koshy NULLMASK 874ebccf1e3SJoseph Koshy }; 875ebccf1e3SJoseph Koshy 876ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ba[] = { /* bsq allocation */ 877ebccf1e3SJoseph Koshy __P4MASK(req-type0, 0), 878ebccf1e3SJoseph Koshy __P4MASK(req-type1, 1), 879ebccf1e3SJoseph Koshy __P4MASK(req-len0, 2), 880ebccf1e3SJoseph Koshy __P4MASK(req-len1, 3), 881ebccf1e3SJoseph Koshy __P4MASK(req-io-type, 5), 882ebccf1e3SJoseph Koshy __P4MASK(req-lock-type, 6), 883ebccf1e3SJoseph Koshy __P4MASK(req-cache-type, 7), 884ebccf1e3SJoseph Koshy __P4MASK(req-split-type, 8), 885ebccf1e3SJoseph Koshy __P4MASK(req-dem-type, 9), 886ebccf1e3SJoseph Koshy __P4MASK(req-ord-type, 10), 887ebccf1e3SJoseph Koshy __P4MASK(mem-type0, 11), 888ebccf1e3SJoseph Koshy __P4MASK(mem-type1, 12), 889ebccf1e3SJoseph Koshy __P4MASK(mem-type2, 13), 890ebccf1e3SJoseph Koshy NULLMASK 891ebccf1e3SJoseph Koshy }; 892ebccf1e3SJoseph Koshy 893ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_sia[] = { /* sse input assist */ 894ebccf1e3SJoseph Koshy __P4MASK(all, 15), 895ebccf1e3SJoseph Koshy NULLMASK 896ebccf1e3SJoseph Koshy }; 897ebccf1e3SJoseph Koshy 898ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_psu[] = { /* packed sp uop */ 899ebccf1e3SJoseph Koshy __P4MASK(all, 15), 900ebccf1e3SJoseph Koshy NULLMASK 901ebccf1e3SJoseph Koshy }; 902ebccf1e3SJoseph Koshy 903ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_pdu[] = { /* packed dp uop */ 904ebccf1e3SJoseph Koshy __P4MASK(all, 15), 905ebccf1e3SJoseph Koshy NULLMASK 906ebccf1e3SJoseph Koshy }; 907ebccf1e3SJoseph Koshy 908ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ssu[] = { /* scalar sp uop */ 909ebccf1e3SJoseph Koshy __P4MASK(all, 15), 910ebccf1e3SJoseph Koshy NULLMASK 911ebccf1e3SJoseph Koshy }; 912ebccf1e3SJoseph Koshy 913ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_sdu[] = { /* scalar dp uop */ 914ebccf1e3SJoseph Koshy __P4MASK(all, 15), 915ebccf1e3SJoseph Koshy NULLMASK 916ebccf1e3SJoseph Koshy }; 917ebccf1e3SJoseph Koshy 918ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_64bmu[] = { /* 64 bit mmx uop */ 919ebccf1e3SJoseph Koshy __P4MASK(all, 15), 920ebccf1e3SJoseph Koshy NULLMASK 921ebccf1e3SJoseph Koshy }; 922ebccf1e3SJoseph Koshy 923ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_128bmu[] = { /* 128 bit mmx uop */ 924ebccf1e3SJoseph Koshy __P4MASK(all, 15), 925ebccf1e3SJoseph Koshy NULLMASK 926ebccf1e3SJoseph Koshy }; 927ebccf1e3SJoseph Koshy 928ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xfu[] = { /* X87 fp uop */ 929ebccf1e3SJoseph Koshy __P4MASK(all, 15), 930ebccf1e3SJoseph Koshy NULLMASK 931ebccf1e3SJoseph Koshy }; 932ebccf1e3SJoseph Koshy 933ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xsmu[] = { /* x87 simd moves uop */ 934ebccf1e3SJoseph Koshy __P4MASK(allp0, 3), 935ebccf1e3SJoseph Koshy __P4MASK(allp2, 4), 936ebccf1e3SJoseph Koshy NULLMASK 937ebccf1e3SJoseph Koshy }; 938ebccf1e3SJoseph Koshy 939ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_gpe[] = { /* global power events */ 940ebccf1e3SJoseph Koshy __P4MASK(running, 0), 941ebccf1e3SJoseph Koshy NULLMASK 942ebccf1e3SJoseph Koshy }; 943ebccf1e3SJoseph Koshy 944ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_tmx[] = { /* TC ms xfer */ 945ebccf1e3SJoseph Koshy __P4MASK(cisc, 0), 946ebccf1e3SJoseph Koshy NULLMASK 947ebccf1e3SJoseph Koshy }; 948ebccf1e3SJoseph Koshy 949ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_uqw[] = { /* uop queue writes */ 950ebccf1e3SJoseph Koshy __P4MASK(from-tc-build, 0), 951ebccf1e3SJoseph Koshy __P4MASK(from-tc-deliver, 1), 952ebccf1e3SJoseph Koshy __P4MASK(from-rom, 2), 953ebccf1e3SJoseph Koshy NULLMASK 954ebccf1e3SJoseph Koshy }; 955ebccf1e3SJoseph Koshy 956d56c5d4bSJoseph Koshy static const struct pmc_masks p4_mask_rmbt[] = { 957d56c5d4bSJoseph Koshy /* retired mispred branch type */ 958ebccf1e3SJoseph Koshy __P4MASK(conditional, 1), 959ebccf1e3SJoseph Koshy __P4MASK(call, 2), 960ebccf1e3SJoseph Koshy __P4MASK(return, 3), 961ebccf1e3SJoseph Koshy __P4MASK(indirect, 4), 962ebccf1e3SJoseph Koshy NULLMASK 963ebccf1e3SJoseph Koshy }; 964ebccf1e3SJoseph Koshy 965ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_rbt[] = { /* retired branch type */ 966ebccf1e3SJoseph Koshy __P4MASK(conditional, 1), 967ebccf1e3SJoseph Koshy __P4MASK(call, 2), 968ebccf1e3SJoseph Koshy __P4MASK(retired, 3), 969ebccf1e3SJoseph Koshy __P4MASK(indirect, 4), 970ebccf1e3SJoseph Koshy NULLMASK 971ebccf1e3SJoseph Koshy }; 972ebccf1e3SJoseph Koshy 973ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_rs[] = { /* resource stall */ 974ebccf1e3SJoseph Koshy __P4MASK(sbfull, 5), 975ebccf1e3SJoseph Koshy NULLMASK 976ebccf1e3SJoseph Koshy }; 977ebccf1e3SJoseph Koshy 978ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_wb[] = { /* WC buffer */ 979ebccf1e3SJoseph Koshy __P4MASK(wcb-evicts, 0), 980ebccf1e3SJoseph Koshy __P4MASK(wcb-full-evict, 1), 981ebccf1e3SJoseph Koshy NULLMASK 982ebccf1e3SJoseph Koshy }; 983ebccf1e3SJoseph Koshy 984ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_fee[] = { /* front end event */ 985ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 986ebccf1e3SJoseph Koshy __P4MASK(bogus, 1), 987ebccf1e3SJoseph Koshy NULLMASK 988ebccf1e3SJoseph Koshy }; 989ebccf1e3SJoseph Koshy 990ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ee[] = { /* execution event */ 991ebccf1e3SJoseph Koshy __P4MASK(nbogus0, 0), 992ebccf1e3SJoseph Koshy __P4MASK(nbogus1, 1), 993ebccf1e3SJoseph Koshy __P4MASK(nbogus2, 2), 994ebccf1e3SJoseph Koshy __P4MASK(nbogus3, 3), 995ebccf1e3SJoseph Koshy __P4MASK(bogus0, 4), 996ebccf1e3SJoseph Koshy __P4MASK(bogus1, 5), 997ebccf1e3SJoseph Koshy __P4MASK(bogus2, 6), 998ebccf1e3SJoseph Koshy __P4MASK(bogus3, 7), 999ebccf1e3SJoseph Koshy NULLMASK 1000ebccf1e3SJoseph Koshy }; 1001ebccf1e3SJoseph Koshy 1002ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_re[] = { /* replay event */ 1003ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1004ebccf1e3SJoseph Koshy __P4MASK(bogus, 1), 1005ebccf1e3SJoseph Koshy NULLMASK 1006ebccf1e3SJoseph Koshy }; 1007ebccf1e3SJoseph Koshy 1008ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_insret[] = { /* instr retired */ 1009ebccf1e3SJoseph Koshy __P4MASK(nbogusntag, 0), 1010ebccf1e3SJoseph Koshy __P4MASK(nbogustag, 1), 1011ebccf1e3SJoseph Koshy __P4MASK(bogusntag, 2), 1012ebccf1e3SJoseph Koshy __P4MASK(bogustag, 3), 1013ebccf1e3SJoseph Koshy NULLMASK 1014ebccf1e3SJoseph Koshy }; 1015ebccf1e3SJoseph Koshy 1016ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ur[] = { /* uops retired */ 1017ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1018ebccf1e3SJoseph Koshy __P4MASK(bogus, 1), 1019ebccf1e3SJoseph Koshy NULLMASK 1020ebccf1e3SJoseph Koshy }; 1021ebccf1e3SJoseph Koshy 1022ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ut[] = { /* uop type */ 1023ebccf1e3SJoseph Koshy __P4MASK(tagloads, 1), 1024ebccf1e3SJoseph Koshy __P4MASK(tagstores, 2), 1025ebccf1e3SJoseph Koshy NULLMASK 1026ebccf1e3SJoseph Koshy }; 1027ebccf1e3SJoseph Koshy 1028ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_br[] = { /* branch retired */ 1029ebccf1e3SJoseph Koshy __P4MASK(mmnp, 0), 1030ebccf1e3SJoseph Koshy __P4MASK(mmnm, 1), 1031ebccf1e3SJoseph Koshy __P4MASK(mmtp, 2), 1032ebccf1e3SJoseph Koshy __P4MASK(mmtm, 3), 1033ebccf1e3SJoseph Koshy NULLMASK 1034ebccf1e3SJoseph Koshy }; 1035ebccf1e3SJoseph Koshy 1036ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_mbr[] = { /* mispred branch retired */ 1037ebccf1e3SJoseph Koshy __P4MASK(nbogus, 0), 1038ebccf1e3SJoseph Koshy NULLMASK 1039ebccf1e3SJoseph Koshy }; 1040ebccf1e3SJoseph Koshy 1041ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xa[] = { /* x87 assist */ 1042ebccf1e3SJoseph Koshy __P4MASK(fpsu, 0), 1043ebccf1e3SJoseph Koshy __P4MASK(fpso, 1), 1044ebccf1e3SJoseph Koshy __P4MASK(poao, 2), 1045ebccf1e3SJoseph Koshy __P4MASK(poau, 3), 1046ebccf1e3SJoseph Koshy __P4MASK(prea, 4), 1047ebccf1e3SJoseph Koshy NULLMASK 1048ebccf1e3SJoseph Koshy }; 1049ebccf1e3SJoseph Koshy 1050ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_machclr[] = { /* machine clear */ 1051ebccf1e3SJoseph Koshy __P4MASK(clear, 0), 1052ebccf1e3SJoseph Koshy __P4MASK(moclear, 2), 1053ebccf1e3SJoseph Koshy __P4MASK(smclear, 3), 1054ebccf1e3SJoseph Koshy NULLMASK 1055ebccf1e3SJoseph Koshy }; 1056ebccf1e3SJoseph Koshy 1057ebccf1e3SJoseph Koshy /* P4 event parser */ 1058ebccf1e3SJoseph Koshy static int 1059ebccf1e3SJoseph Koshy p4_allocate_pmc(enum pmc_event pe, char *ctrspec, 1060ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 1061ebccf1e3SJoseph Koshy { 1062ebccf1e3SJoseph Koshy 1063ebccf1e3SJoseph Koshy char *e, *p, *q; 1064ebccf1e3SJoseph Koshy int count, has_tag, has_busreqtype, n; 1065ebccf1e3SJoseph Koshy uint32_t evmask, cccractivemask; 1066ebccf1e3SJoseph Koshy const struct pmc_masks *pm, *pmask; 1067ebccf1e3SJoseph Koshy 1068789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1069f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig = 1070f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 0; 1071ebccf1e3SJoseph Koshy 1072ebccf1e3SJoseph Koshy pmask = NULL; 1073ebccf1e3SJoseph Koshy evmask = 0; 1074ebccf1e3SJoseph Koshy cccractivemask = 0x3; 1075ebccf1e3SJoseph Koshy has_tag = has_busreqtype = 0; 1076ebccf1e3SJoseph Koshy 1077ebccf1e3SJoseph Koshy #define __P4SETMASK(M) do { \ 1078ebccf1e3SJoseph Koshy pmask = p4_mask_##M; \ 1079ebccf1e3SJoseph Koshy } while (0) 1080ebccf1e3SJoseph Koshy 1081ebccf1e3SJoseph Koshy switch (pe) { 1082ebccf1e3SJoseph Koshy case PMC_EV_P4_TC_DELIVER_MODE: 1083ebccf1e3SJoseph Koshy __P4SETMASK(tcdm); 1084ebccf1e3SJoseph Koshy break; 1085ebccf1e3SJoseph Koshy case PMC_EV_P4_BPU_FETCH_REQUEST: 1086ebccf1e3SJoseph Koshy __P4SETMASK(bfr); 1087ebccf1e3SJoseph Koshy break; 1088ebccf1e3SJoseph Koshy case PMC_EV_P4_ITLB_REFERENCE: 1089ebccf1e3SJoseph Koshy __P4SETMASK(ir); 1090ebccf1e3SJoseph Koshy break; 1091ebccf1e3SJoseph Koshy case PMC_EV_P4_MEMORY_CANCEL: 1092ebccf1e3SJoseph Koshy __P4SETMASK(memcan); 1093ebccf1e3SJoseph Koshy break; 1094ebccf1e3SJoseph Koshy case PMC_EV_P4_MEMORY_COMPLETE: 1095ebccf1e3SJoseph Koshy __P4SETMASK(memcomp); 1096ebccf1e3SJoseph Koshy break; 1097ebccf1e3SJoseph Koshy case PMC_EV_P4_LOAD_PORT_REPLAY: 1098ebccf1e3SJoseph Koshy __P4SETMASK(lpr); 1099ebccf1e3SJoseph Koshy break; 1100ebccf1e3SJoseph Koshy case PMC_EV_P4_STORE_PORT_REPLAY: 1101ebccf1e3SJoseph Koshy __P4SETMASK(spr); 1102ebccf1e3SJoseph Koshy break; 1103ebccf1e3SJoseph Koshy case PMC_EV_P4_MOB_LOAD_REPLAY: 1104ebccf1e3SJoseph Koshy __P4SETMASK(mlr); 1105ebccf1e3SJoseph Koshy break; 1106ebccf1e3SJoseph Koshy case PMC_EV_P4_PAGE_WALK_TYPE: 1107ebccf1e3SJoseph Koshy __P4SETMASK(pwt); 1108ebccf1e3SJoseph Koshy break; 1109ebccf1e3SJoseph Koshy case PMC_EV_P4_BSQ_CACHE_REFERENCE: 1110ebccf1e3SJoseph Koshy __P4SETMASK(bcr); 1111ebccf1e3SJoseph Koshy break; 1112ebccf1e3SJoseph Koshy case PMC_EV_P4_IOQ_ALLOCATION: 1113ebccf1e3SJoseph Koshy __P4SETMASK(ia); 1114ebccf1e3SJoseph Koshy has_busreqtype = 1; 1115ebccf1e3SJoseph Koshy break; 1116ebccf1e3SJoseph Koshy case PMC_EV_P4_IOQ_ACTIVE_ENTRIES: 1117ebccf1e3SJoseph Koshy __P4SETMASK(iae); 1118ebccf1e3SJoseph Koshy has_busreqtype = 1; 1119ebccf1e3SJoseph Koshy break; 1120ebccf1e3SJoseph Koshy case PMC_EV_P4_FSB_DATA_ACTIVITY: 1121ebccf1e3SJoseph Koshy __P4SETMASK(fda); 1122ebccf1e3SJoseph Koshy break; 1123ebccf1e3SJoseph Koshy case PMC_EV_P4_BSQ_ALLOCATION: 1124ebccf1e3SJoseph Koshy __P4SETMASK(ba); 1125ebccf1e3SJoseph Koshy break; 1126ebccf1e3SJoseph Koshy case PMC_EV_P4_SSE_INPUT_ASSIST: 1127ebccf1e3SJoseph Koshy __P4SETMASK(sia); 1128ebccf1e3SJoseph Koshy break; 1129ebccf1e3SJoseph Koshy case PMC_EV_P4_PACKED_SP_UOP: 1130ebccf1e3SJoseph Koshy __P4SETMASK(psu); 1131ebccf1e3SJoseph Koshy break; 1132ebccf1e3SJoseph Koshy case PMC_EV_P4_PACKED_DP_UOP: 1133ebccf1e3SJoseph Koshy __P4SETMASK(pdu); 1134ebccf1e3SJoseph Koshy break; 1135ebccf1e3SJoseph Koshy case PMC_EV_P4_SCALAR_SP_UOP: 1136ebccf1e3SJoseph Koshy __P4SETMASK(ssu); 1137ebccf1e3SJoseph Koshy break; 1138ebccf1e3SJoseph Koshy case PMC_EV_P4_SCALAR_DP_UOP: 1139ebccf1e3SJoseph Koshy __P4SETMASK(sdu); 1140ebccf1e3SJoseph Koshy break; 1141ebccf1e3SJoseph Koshy case PMC_EV_P4_64BIT_MMX_UOP: 1142ebccf1e3SJoseph Koshy __P4SETMASK(64bmu); 1143ebccf1e3SJoseph Koshy break; 1144ebccf1e3SJoseph Koshy case PMC_EV_P4_128BIT_MMX_UOP: 1145ebccf1e3SJoseph Koshy __P4SETMASK(128bmu); 1146ebccf1e3SJoseph Koshy break; 1147ebccf1e3SJoseph Koshy case PMC_EV_P4_X87_FP_UOP: 1148ebccf1e3SJoseph Koshy __P4SETMASK(xfu); 1149ebccf1e3SJoseph Koshy break; 1150ebccf1e3SJoseph Koshy case PMC_EV_P4_X87_SIMD_MOVES_UOP: 1151ebccf1e3SJoseph Koshy __P4SETMASK(xsmu); 1152ebccf1e3SJoseph Koshy break; 1153ebccf1e3SJoseph Koshy case PMC_EV_P4_GLOBAL_POWER_EVENTS: 1154ebccf1e3SJoseph Koshy __P4SETMASK(gpe); 1155ebccf1e3SJoseph Koshy break; 1156ebccf1e3SJoseph Koshy case PMC_EV_P4_TC_MS_XFER: 1157ebccf1e3SJoseph Koshy __P4SETMASK(tmx); 1158ebccf1e3SJoseph Koshy break; 1159ebccf1e3SJoseph Koshy case PMC_EV_P4_UOP_QUEUE_WRITES: 1160ebccf1e3SJoseph Koshy __P4SETMASK(uqw); 1161ebccf1e3SJoseph Koshy break; 1162ebccf1e3SJoseph Koshy case PMC_EV_P4_RETIRED_MISPRED_BRANCH_TYPE: 1163ebccf1e3SJoseph Koshy __P4SETMASK(rmbt); 1164ebccf1e3SJoseph Koshy break; 1165ebccf1e3SJoseph Koshy case PMC_EV_P4_RETIRED_BRANCH_TYPE: 1166ebccf1e3SJoseph Koshy __P4SETMASK(rbt); 1167ebccf1e3SJoseph Koshy break; 1168ebccf1e3SJoseph Koshy case PMC_EV_P4_RESOURCE_STALL: 1169ebccf1e3SJoseph Koshy __P4SETMASK(rs); 1170ebccf1e3SJoseph Koshy break; 1171ebccf1e3SJoseph Koshy case PMC_EV_P4_WC_BUFFER: 1172ebccf1e3SJoseph Koshy __P4SETMASK(wb); 1173ebccf1e3SJoseph Koshy break; 1174ebccf1e3SJoseph Koshy case PMC_EV_P4_BSQ_ACTIVE_ENTRIES: 1175ebccf1e3SJoseph Koshy case PMC_EV_P4_B2B_CYCLES: 1176ebccf1e3SJoseph Koshy case PMC_EV_P4_BNR: 1177ebccf1e3SJoseph Koshy case PMC_EV_P4_SNOOP: 1178ebccf1e3SJoseph Koshy case PMC_EV_P4_RESPONSE: 1179ebccf1e3SJoseph Koshy break; 1180ebccf1e3SJoseph Koshy case PMC_EV_P4_FRONT_END_EVENT: 1181ebccf1e3SJoseph Koshy __P4SETMASK(fee); 1182ebccf1e3SJoseph Koshy break; 1183ebccf1e3SJoseph Koshy case PMC_EV_P4_EXECUTION_EVENT: 1184ebccf1e3SJoseph Koshy __P4SETMASK(ee); 1185ebccf1e3SJoseph Koshy break; 1186ebccf1e3SJoseph Koshy case PMC_EV_P4_REPLAY_EVENT: 1187ebccf1e3SJoseph Koshy __P4SETMASK(re); 1188ebccf1e3SJoseph Koshy break; 1189ebccf1e3SJoseph Koshy case PMC_EV_P4_INSTR_RETIRED: 1190ebccf1e3SJoseph Koshy __P4SETMASK(insret); 1191ebccf1e3SJoseph Koshy break; 1192ebccf1e3SJoseph Koshy case PMC_EV_P4_UOPS_RETIRED: 1193ebccf1e3SJoseph Koshy __P4SETMASK(ur); 1194ebccf1e3SJoseph Koshy break; 1195ebccf1e3SJoseph Koshy case PMC_EV_P4_UOP_TYPE: 1196ebccf1e3SJoseph Koshy __P4SETMASK(ut); 1197ebccf1e3SJoseph Koshy break; 1198ebccf1e3SJoseph Koshy case PMC_EV_P4_BRANCH_RETIRED: 1199ebccf1e3SJoseph Koshy __P4SETMASK(br); 1200ebccf1e3SJoseph Koshy break; 1201ebccf1e3SJoseph Koshy case PMC_EV_P4_MISPRED_BRANCH_RETIRED: 1202ebccf1e3SJoseph Koshy __P4SETMASK(mbr); 1203ebccf1e3SJoseph Koshy break; 1204ebccf1e3SJoseph Koshy case PMC_EV_P4_X87_ASSIST: 1205ebccf1e3SJoseph Koshy __P4SETMASK(xa); 1206ebccf1e3SJoseph Koshy break; 1207ebccf1e3SJoseph Koshy case PMC_EV_P4_MACHINE_CLEAR: 1208ebccf1e3SJoseph Koshy __P4SETMASK(machclr); 1209ebccf1e3SJoseph Koshy break; 1210ebccf1e3SJoseph Koshy default: 1211aa342b1fSJoseph Koshy return (-1); 1212ebccf1e3SJoseph Koshy } 1213ebccf1e3SJoseph Koshy 1214ebccf1e3SJoseph Koshy /* process additional flags */ 1215ebccf1e3SJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 1216ebccf1e3SJoseph Koshy if (KWPREFIXMATCH(p, P4_KW_ACTIVE)) { 1217ebccf1e3SJoseph Koshy q = strchr(p, '='); 1218ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1219aa342b1fSJoseph Koshy return (-1); 1220ebccf1e3SJoseph Koshy 1221789140c0SJoseph Koshy if (strcasecmp(q, P4_KW_ACTIVE_NONE) == 0) 1222ebccf1e3SJoseph Koshy cccractivemask = 0x0; 1223789140c0SJoseph Koshy else if (strcasecmp(q, P4_KW_ACTIVE_SINGLE) == 0) 1224ebccf1e3SJoseph Koshy cccractivemask = 0x1; 1225789140c0SJoseph Koshy else if (strcasecmp(q, P4_KW_ACTIVE_BOTH) == 0) 1226ebccf1e3SJoseph Koshy cccractivemask = 0x2; 1227789140c0SJoseph Koshy else if (strcasecmp(q, P4_KW_ACTIVE_ANY) == 0) 1228ebccf1e3SJoseph Koshy cccractivemask = 0x3; 1229ebccf1e3SJoseph Koshy else 1230aa342b1fSJoseph Koshy return (-1); 1231ebccf1e3SJoseph Koshy 1232ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, P4_KW_BUSREQTYPE)) { 1233ebccf1e3SJoseph Koshy if (has_busreqtype == 0) 1234aa342b1fSJoseph Koshy return (-1); 1235ebccf1e3SJoseph Koshy 1236ebccf1e3SJoseph Koshy q = strchr(p, '='); 1237ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1238aa342b1fSJoseph Koshy return (-1); 1239ebccf1e3SJoseph Koshy 1240ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 1241ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 1242aa342b1fSJoseph Koshy return (-1); 1243ebccf1e3SJoseph Koshy evmask = (evmask & ~0x1F) | (count & 0x1F); 1244ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P4_KW_CASCADE)) 1245ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_CASCADE; 1246ebccf1e3SJoseph Koshy else if (KWMATCH(p, P4_KW_EDGE)) 1247ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1248ebccf1e3SJoseph Koshy else if (KWMATCH(p, P4_KW_INV)) 1249ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 1250ebccf1e3SJoseph Koshy else if (KWPREFIXMATCH(p, P4_KW_MASK "=")) { 1251ebccf1e3SJoseph Koshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 1252aa342b1fSJoseph Koshy return (-1); 1253ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1254ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P4_KW_OS)) 1255ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 1256ebccf1e3SJoseph Koshy else if (KWMATCH(p, P4_KW_PRECISE)) 1257ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_PRECISE; 1258ebccf1e3SJoseph Koshy else if (KWPREFIXMATCH(p, P4_KW_TAG "=")) { 1259ebccf1e3SJoseph Koshy if (has_tag == 0) 1260aa342b1fSJoseph Koshy return (-1); 1261ebccf1e3SJoseph Koshy 1262ebccf1e3SJoseph Koshy q = strchr(p, '='); 1263ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1264aa342b1fSJoseph Koshy return (-1); 1265ebccf1e3SJoseph Koshy 1266ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 1267ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 1268aa342b1fSJoseph Koshy return (-1); 1269ebccf1e3SJoseph Koshy 1270ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_TAGGING; 1271f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig |= 1272ebccf1e3SJoseph Koshy P4_ESCR_TO_TAG_VALUE(count); 1273ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, P4_KW_THRESHOLD "=")) { 1274ebccf1e3SJoseph Koshy q = strchr(p, '='); 1275ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1276aa342b1fSJoseph Koshy return (-1); 1277ebccf1e3SJoseph Koshy 1278ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 1279ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 1280aa342b1fSJoseph Koshy return (-1); 1281ebccf1e3SJoseph Koshy 1282ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 1283f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig &= 1284f263522aSJoseph Koshy ~P4_CCCR_THRESHOLD_MASK; 1285f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |= 1286f263522aSJoseph Koshy P4_CCCR_TO_THRESHOLD(count); 1287ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P4_KW_USR)) 1288ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 1289ebccf1e3SJoseph Koshy else 1290aa342b1fSJoseph Koshy return (-1); 1291ebccf1e3SJoseph Koshy } 1292ebccf1e3SJoseph Koshy 1293ebccf1e3SJoseph Koshy /* other post processing */ 1294ebccf1e3SJoseph Koshy if (pe == PMC_EV_P4_IOQ_ALLOCATION || 1295ebccf1e3SJoseph Koshy pe == PMC_EV_P4_FSB_DATA_ACTIVITY || 1296ebccf1e3SJoseph Koshy pe == PMC_EV_P4_BSQ_ALLOCATION) 1297ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1298ebccf1e3SJoseph Koshy 1299ebccf1e3SJoseph Koshy /* fill in thread activity mask */ 1300f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |= 1301ebccf1e3SJoseph Koshy P4_CCCR_TO_ACTIVE_THREAD(cccractivemask); 1302ebccf1e3SJoseph Koshy 1303ebccf1e3SJoseph Koshy if (evmask) 1304ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1305ebccf1e3SJoseph Koshy 1306ebccf1e3SJoseph Koshy switch (pe) { 1307ebccf1e3SJoseph Koshy case PMC_EV_P4_FSB_DATA_ACTIVITY: 1308ebccf1e3SJoseph Koshy if ((evmask & 0x06) == 0x06 || 1309ebccf1e3SJoseph Koshy (evmask & 0x18) == 0x18) 1310aa342b1fSJoseph Koshy return (-1); /* can't have own+other bits together */ 1311ebccf1e3SJoseph Koshy if (evmask == 0) /* default:drdy-{drv,own}+dbsy{drv,own} */ 1312ebccf1e3SJoseph Koshy evmask = 0x1D; 1313ebccf1e3SJoseph Koshy break; 1314ebccf1e3SJoseph Koshy case PMC_EV_P4_MACHINE_CLEAR: 1315ebccf1e3SJoseph Koshy /* only one bit is allowed to be set */ 1316ebccf1e3SJoseph Koshy if ((evmask & (evmask - 1)) != 0) 1317aa342b1fSJoseph Koshy return (-1); 1318ebccf1e3SJoseph Koshy if (evmask == 0) { 1319ebccf1e3SJoseph Koshy evmask = 0x1; /* 'CLEAR' */ 1320ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1321ebccf1e3SJoseph Koshy } 1322ebccf1e3SJoseph Koshy break; 1323ebccf1e3SJoseph Koshy default: 1324ebccf1e3SJoseph Koshy if (evmask == 0 && pmask) { 1325ebccf1e3SJoseph Koshy for (pm = pmask; pm->pm_name; pm++) 1326ebccf1e3SJoseph Koshy evmask |= pm->pm_value; 1327ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1328ebccf1e3SJoseph Koshy } 1329ebccf1e3SJoseph Koshy } 1330ebccf1e3SJoseph Koshy 1331f263522aSJoseph Koshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 1332f263522aSJoseph Koshy P4_ESCR_TO_EVENT_MASK(evmask); 1333ebccf1e3SJoseph Koshy 1334aa342b1fSJoseph Koshy return (0); 1335ebccf1e3SJoseph Koshy } 1336ebccf1e3SJoseph Koshy 133786a65549SJoseph Koshy #endif 133886a65549SJoseph Koshy 133986a65549SJoseph Koshy #if defined(__i386__) 134086a65549SJoseph Koshy 1341ebccf1e3SJoseph Koshy /* 1342f263522aSJoseph Koshy * Pentium style PMCs 1343f263522aSJoseph Koshy */ 1344f263522aSJoseph Koshy 1345f263522aSJoseph Koshy static struct pmc_event_alias p5_aliases[] = { 13460b9b757dSJoseph Koshy EV_ALIAS("branches", "p5-taken-branches"), 1347f263522aSJoseph Koshy EV_ALIAS("cycles", "tsc"), 13480b9b757dSJoseph Koshy EV_ALIAS("dc-misses", "p5-data-read-miss-or-write-miss"), 13490b9b757dSJoseph Koshy EV_ALIAS("ic-misses", "p5-code-cache-miss"), 13500b9b757dSJoseph Koshy EV_ALIAS("instructions", "p5-instructions-executed"), 13510b9b757dSJoseph Koshy EV_ALIAS("interrupts", "p5-hardware-interrupts"), 13520b9b757dSJoseph Koshy EV_ALIAS("unhalted-cycles", 13530b9b757dSJoseph Koshy "p5-number-of-cycles-not-in-halt-state"), 1354f263522aSJoseph Koshy EV_ALIAS(NULL, NULL) 1355f263522aSJoseph Koshy }; 1356f263522aSJoseph Koshy 1357f263522aSJoseph Koshy static int 1358f263522aSJoseph Koshy p5_allocate_pmc(enum pmc_event pe, char *ctrspec, 1359f263522aSJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 1360f263522aSJoseph Koshy { 1361aa342b1fSJoseph Koshy return (-1 || pe || ctrspec || pmc_config); /* shut up gcc */ 1362f263522aSJoseph Koshy } 1363f263522aSJoseph Koshy 1364f263522aSJoseph Koshy /* 1365ebccf1e3SJoseph Koshy * Pentium Pro style PMCs. These PMCs are found in Pentium II, Pentium III, 1366ebccf1e3SJoseph Koshy * and Pentium M CPUs. 1367ebccf1e3SJoseph Koshy */ 1368ebccf1e3SJoseph Koshy 1369ebccf1e3SJoseph Koshy static struct pmc_event_alias p6_aliases[] = { 1370ebccf1e3SJoseph Koshy EV_ALIAS("branches", "p6-br-inst-retired"), 1371ebccf1e3SJoseph Koshy EV_ALIAS("branch-mispredicts", "p6-br-miss-pred-retired"), 1372ebccf1e3SJoseph Koshy EV_ALIAS("cycles", "tsc"), 1373d56c5d4bSJoseph Koshy EV_ALIAS("dc-misses", "p6-dcu-lines-in"), 137473e2d811SJoseph Koshy EV_ALIAS("ic-misses", "p6-ifu-fetch-miss"), 1375ebccf1e3SJoseph Koshy EV_ALIAS("instructions", "p6-inst-retired"), 1376ebccf1e3SJoseph Koshy EV_ALIAS("interrupts", "p6-hw-int-rx"), 1377177a2f22SJoseph Koshy EV_ALIAS("unhalted-cycles", "p6-cpu-clk-unhalted"), 1378ebccf1e3SJoseph Koshy EV_ALIAS(NULL, NULL) 1379ebccf1e3SJoseph Koshy }; 1380ebccf1e3SJoseph Koshy 1381ebccf1e3SJoseph Koshy #define P6_KW_CMASK "cmask" 1382ebccf1e3SJoseph Koshy #define P6_KW_EDGE "edge" 1383ebccf1e3SJoseph Koshy #define P6_KW_INV "inv" 1384ebccf1e3SJoseph Koshy #define P6_KW_OS "os" 1385ebccf1e3SJoseph Koshy #define P6_KW_UMASK "umask" 1386ebccf1e3SJoseph Koshy #define P6_KW_USR "usr" 1387ebccf1e3SJoseph Koshy 1388ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mesi[] = { 1389ebccf1e3SJoseph Koshy PMCMASK(m, 0x01), 1390ebccf1e3SJoseph Koshy PMCMASK(e, 0x02), 1391ebccf1e3SJoseph Koshy PMCMASK(s, 0x04), 1392ebccf1e3SJoseph Koshy PMCMASK(i, 0x08), 1393ebccf1e3SJoseph Koshy NULLMASK 1394ebccf1e3SJoseph Koshy }; 1395ebccf1e3SJoseph Koshy 1396ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mesihw[] = { 1397ebccf1e3SJoseph Koshy PMCMASK(m, 0x01), 1398ebccf1e3SJoseph Koshy PMCMASK(e, 0x02), 1399ebccf1e3SJoseph Koshy PMCMASK(s, 0x04), 1400ebccf1e3SJoseph Koshy PMCMASK(i, 0x08), 1401ebccf1e3SJoseph Koshy PMCMASK(nonhw, 0x00), 1402ebccf1e3SJoseph Koshy PMCMASK(hw, 0x10), 1403ebccf1e3SJoseph Koshy PMCMASK(both, 0x30), 1404ebccf1e3SJoseph Koshy NULLMASK 1405ebccf1e3SJoseph Koshy }; 1406ebccf1e3SJoseph Koshy 1407ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_hw[] = { 1408ebccf1e3SJoseph Koshy PMCMASK(nonhw, 0x00), 1409ebccf1e3SJoseph Koshy PMCMASK(hw, 0x10), 1410ebccf1e3SJoseph Koshy PMCMASK(both, 0x30), 1411ebccf1e3SJoseph Koshy NULLMASK 1412ebccf1e3SJoseph Koshy }; 1413ebccf1e3SJoseph Koshy 1414ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_any[] = { 1415ebccf1e3SJoseph Koshy PMCMASK(self, 0x00), 1416ebccf1e3SJoseph Koshy PMCMASK(any, 0x20), 1417ebccf1e3SJoseph Koshy NULLMASK 1418ebccf1e3SJoseph Koshy }; 1419ebccf1e3SJoseph Koshy 1420ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_ekp[] = { 1421ebccf1e3SJoseph Koshy PMCMASK(nta, 0x00), 1422ebccf1e3SJoseph Koshy PMCMASK(t1, 0x01), 1423ebccf1e3SJoseph Koshy PMCMASK(t2, 0x02), 1424ebccf1e3SJoseph Koshy PMCMASK(wos, 0x03), 1425ebccf1e3SJoseph Koshy NULLMASK 1426ebccf1e3SJoseph Koshy }; 1427ebccf1e3SJoseph Koshy 1428ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_pps[] = { 1429ebccf1e3SJoseph Koshy PMCMASK(packed-and-scalar, 0x00), 1430ebccf1e3SJoseph Koshy PMCMASK(scalar, 0x01), 1431ebccf1e3SJoseph Koshy NULLMASK 1432ebccf1e3SJoseph Koshy }; 1433ebccf1e3SJoseph Koshy 1434ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mite[] = { 1435ebccf1e3SJoseph Koshy PMCMASK(packed-multiply, 0x01), 1436ebccf1e3SJoseph Koshy PMCMASK(packed-shift, 0x02), 1437ebccf1e3SJoseph Koshy PMCMASK(pack, 0x04), 1438ebccf1e3SJoseph Koshy PMCMASK(unpack, 0x08), 1439ebccf1e3SJoseph Koshy PMCMASK(packed-logical, 0x10), 1440ebccf1e3SJoseph Koshy PMCMASK(packed-arithmetic, 0x20), 1441ebccf1e3SJoseph Koshy NULLMASK 1442ebccf1e3SJoseph Koshy }; 1443ebccf1e3SJoseph Koshy 1444ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_fmt[] = { 1445ebccf1e3SJoseph Koshy PMCMASK(mmxtofp, 0x00), 1446ebccf1e3SJoseph Koshy PMCMASK(fptommx, 0x01), 1447ebccf1e3SJoseph Koshy NULLMASK 1448ebccf1e3SJoseph Koshy }; 1449ebccf1e3SJoseph Koshy 1450ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_sr[] = { 1451ebccf1e3SJoseph Koshy PMCMASK(es, 0x01), 1452ebccf1e3SJoseph Koshy PMCMASK(ds, 0x02), 1453ebccf1e3SJoseph Koshy PMCMASK(fs, 0x04), 1454ebccf1e3SJoseph Koshy PMCMASK(gs, 0x08), 1455ebccf1e3SJoseph Koshy NULLMASK 1456ebccf1e3SJoseph Koshy }; 1457ebccf1e3SJoseph Koshy 1458ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_eet[] = { 1459ebccf1e3SJoseph Koshy PMCMASK(all, 0x00), 1460ebccf1e3SJoseph Koshy PMCMASK(freq, 0x02), 1461ebccf1e3SJoseph Koshy NULLMASK 1462ebccf1e3SJoseph Koshy }; 1463ebccf1e3SJoseph Koshy 1464ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_efur[] = { 1465ebccf1e3SJoseph Koshy PMCMASK(all, 0x00), 1466ebccf1e3SJoseph Koshy PMCMASK(loadop, 0x01), 1467ebccf1e3SJoseph Koshy PMCMASK(stdsta, 0x02), 1468ebccf1e3SJoseph Koshy NULLMASK 1469ebccf1e3SJoseph Koshy }; 1470ebccf1e3SJoseph Koshy 1471ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_essir[] = { 1472ebccf1e3SJoseph Koshy PMCMASK(sse-packed-single, 0x00), 1473ebccf1e3SJoseph Koshy PMCMASK(sse-packed-single-scalar-single, 0x01), 1474ebccf1e3SJoseph Koshy PMCMASK(sse2-packed-double, 0x02), 1475ebccf1e3SJoseph Koshy PMCMASK(sse2-scalar-double, 0x03), 1476ebccf1e3SJoseph Koshy NULLMASK 1477ebccf1e3SJoseph Koshy }; 1478ebccf1e3SJoseph Koshy 1479ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_esscir[] = { 1480ebccf1e3SJoseph Koshy PMCMASK(sse-packed-single, 0x00), 1481ebccf1e3SJoseph Koshy PMCMASK(sse-scalar-single, 0x01), 1482ebccf1e3SJoseph Koshy PMCMASK(sse2-packed-double, 0x02), 1483ebccf1e3SJoseph Koshy PMCMASK(sse2-scalar-double, 0x03), 1484ebccf1e3SJoseph Koshy NULLMASK 1485ebccf1e3SJoseph Koshy }; 1486ebccf1e3SJoseph Koshy 1487ebccf1e3SJoseph Koshy /* P6 event parser */ 1488ebccf1e3SJoseph Koshy static int 1489ebccf1e3SJoseph Koshy p6_allocate_pmc(enum pmc_event pe, char *ctrspec, 1490ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 1491ebccf1e3SJoseph Koshy { 1492ebccf1e3SJoseph Koshy char *e, *p, *q; 1493ebccf1e3SJoseph Koshy uint32_t evmask; 1494ebccf1e3SJoseph Koshy int count, n; 1495ebccf1e3SJoseph Koshy const struct pmc_masks *pm, *pmask; 1496ebccf1e3SJoseph Koshy 1497789140c0SJoseph Koshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1498f263522aSJoseph Koshy pmc_config->pm_md.pm_ppro.pm_ppro_config = 0; 1499ebccf1e3SJoseph Koshy 1500ebccf1e3SJoseph Koshy evmask = 0; 1501ebccf1e3SJoseph Koshy 1502ebccf1e3SJoseph Koshy #define P6MASKSET(M) pmask = p6_mask_ ## M 1503ebccf1e3SJoseph Koshy 1504ebccf1e3SJoseph Koshy switch(pe) { 1505ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_IFETCH: P6MASKSET(mesi); break; 1506ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_LD: P6MASKSET(mesi); break; 1507ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_ST: P6MASKSET(mesi); break; 1508ebccf1e3SJoseph Koshy case PMC_EV_P6_L2_RQSTS: P6MASKSET(mesi); break; 1509ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_DRDY_CLOCKS: 1510ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_LOCK_CLOCKS: 1511ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BRD: 1512ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_RFO: 1513ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_WB: 1514ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_IFETCH: 1515ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_INVAL: 1516ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_PWR: 1517ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_P: 1518ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_IO: 1519ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_DEF: 1520ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BURST: 1521ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_ANY: 1522ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_MEM: 1523ebccf1e3SJoseph Koshy P6MASKSET(any); break; 1524ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED: 1525ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_MISS: 1526ebccf1e3SJoseph Koshy P6MASKSET(ekp); break; 1527ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_INST_RETIRED: 1528ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_COMP_INST_RET: 1529ebccf1e3SJoseph Koshy P6MASKSET(pps); break; 1530ebccf1e3SJoseph Koshy case PMC_EV_P6_MMX_INSTR_TYPE_EXEC: 1531ebccf1e3SJoseph Koshy P6MASKSET(mite); break; 1532ebccf1e3SJoseph Koshy case PMC_EV_P6_FP_MMX_TRANS: 1533ebccf1e3SJoseph Koshy P6MASKSET(fmt); break; 1534ebccf1e3SJoseph Koshy case PMC_EV_P6_SEG_RENAME_STALLS: 1535ebccf1e3SJoseph Koshy case PMC_EV_P6_SEG_REG_RENAMES: 1536ebccf1e3SJoseph Koshy P6MASKSET(sr); break; 1537ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_EST_TRANS: 1538ebccf1e3SJoseph Koshy P6MASKSET(eet); break; 1539ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_FUSED_UOPS_RET: 1540ebccf1e3SJoseph Koshy P6MASKSET(efur); break; 1541ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED: 1542ebccf1e3SJoseph Koshy P6MASKSET(essir); break; 1543ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED: 1544ebccf1e3SJoseph Koshy P6MASKSET(esscir); break; 1545ebccf1e3SJoseph Koshy default: 1546ebccf1e3SJoseph Koshy pmask = NULL; 1547ebccf1e3SJoseph Koshy break; 1548ebccf1e3SJoseph Koshy } 1549ebccf1e3SJoseph Koshy 1550ebccf1e3SJoseph Koshy /* Pentium M PMCs have a few events with different semantics */ 1551ebccf1e3SJoseph Koshy if (cpu_info.pm_cputype == PMC_CPU_INTEL_PM) { 1552ebccf1e3SJoseph Koshy if (pe == PMC_EV_P6_L2_LD || 1553ebccf1e3SJoseph Koshy pe == PMC_EV_P6_L2_LINES_IN || 1554ebccf1e3SJoseph Koshy pe == PMC_EV_P6_L2_LINES_OUT) 1555ebccf1e3SJoseph Koshy P6MASKSET(mesihw); 1556ebccf1e3SJoseph Koshy else if (pe == PMC_EV_P6_L2_M_LINES_OUTM) 1557ebccf1e3SJoseph Koshy P6MASKSET(hw); 1558ebccf1e3SJoseph Koshy } 1559ebccf1e3SJoseph Koshy 1560ebccf1e3SJoseph Koshy /* Parse additional modifiers if present */ 1561ebccf1e3SJoseph Koshy while ((p = strsep(&ctrspec, ",")) != NULL) { 1562ebccf1e3SJoseph Koshy if (KWPREFIXMATCH(p, P6_KW_CMASK "=")) { 1563ebccf1e3SJoseph Koshy q = strchr(p, '='); 1564ebccf1e3SJoseph Koshy if (*++q == '\0') /* skip '=' */ 1565aa342b1fSJoseph Koshy return (-1); 1566ebccf1e3SJoseph Koshy count = strtol(q, &e, 0); 1567ebccf1e3SJoseph Koshy if (e == q || *e != '\0') 1568aa342b1fSJoseph Koshy return (-1); 1569ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 1570f263522aSJoseph Koshy pmc_config->pm_md.pm_ppro.pm_ppro_config |= 1571f263522aSJoseph Koshy P6_EVSEL_TO_CMASK(count); 1572ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_EDGE)) { 1573ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1574ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_INV)) { 1575ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_INVERT; 1576ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_OS)) { 1577ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 1578ebccf1e3SJoseph Koshy } else if (KWPREFIXMATCH(p, P6_KW_UMASK "=")) { 1579ebccf1e3SJoseph Koshy evmask = 0; 1580ebccf1e3SJoseph Koshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 1581aa342b1fSJoseph Koshy return (-1); 1582ebccf1e3SJoseph Koshy if ((pe == PMC_EV_P6_BUS_DRDY_CLOCKS || 1583ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_LOCK_CLOCKS || 1584ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_BRD || 1585ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_RFO || 1586ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_IFETCH || 1587ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_INVAL || 1588ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_PWR || 1589ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_DEF || 1590ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_BURST || 1591ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_ANY || 1592ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRAN_MEM || 1593ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRANS_IO || 1594ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRANS_P || 1595ebccf1e3SJoseph Koshy pe == PMC_EV_P6_BUS_TRANS_WB || 1596ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_EST_TRANS || 1597ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_FUSED_UOPS_RET || 1598ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_COMP_INST_RET || 1599ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_INST_RETIRED || 1600ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_PREF_DISPATCHED || 1601ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_KNI_PREF_MISS || 1602ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED || 1603ebccf1e3SJoseph Koshy pe == PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED || 1604ebccf1e3SJoseph Koshy pe == PMC_EV_P6_FP_MMX_TRANS) 1605aa342b1fSJoseph Koshy && (n > 1)) /* Only one mask keyword is allowed. */ 1606aa342b1fSJoseph Koshy return (-1); 1607ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1608ebccf1e3SJoseph Koshy } else if (KWMATCH(p, P6_KW_USR)) { 1609ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_USER; 1610ebccf1e3SJoseph Koshy } else 1611aa342b1fSJoseph Koshy return (-1); 1612ebccf1e3SJoseph Koshy } 1613ebccf1e3SJoseph Koshy 1614ebccf1e3SJoseph Koshy /* post processing */ 1615ebccf1e3SJoseph Koshy switch (pe) { 1616ebccf1e3SJoseph Koshy 1617ebccf1e3SJoseph Koshy /* 1618ebccf1e3SJoseph Koshy * The following events default to an evmask of 0 1619ebccf1e3SJoseph Koshy */ 1620ebccf1e3SJoseph Koshy 1621ebccf1e3SJoseph Koshy /* default => 'self' */ 1622ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_DRDY_CLOCKS: 1623ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_LOCK_CLOCKS: 1624ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BRD: 1625ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_RFO: 1626ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_WB: 1627ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_IFETCH: 1628ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_INVAL: 1629ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_PWR: 1630ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_P: 1631ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRANS_IO: 1632ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_DEF: 1633ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_BURST: 1634ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_ANY: 1635ebccf1e3SJoseph Koshy case PMC_EV_P6_BUS_TRAN_MEM: 1636ebccf1e3SJoseph Koshy 1637ebccf1e3SJoseph Koshy /* default => 'nta' */ 1638ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED: 1639ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_PREF_MISS: 1640ebccf1e3SJoseph Koshy 1641ebccf1e3SJoseph Koshy /* default => 'packed and scalar' */ 1642ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_INST_RETIRED: 1643ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_KNI_COMP_INST_RET: 1644ebccf1e3SJoseph Koshy 1645ebccf1e3SJoseph Koshy /* default => 'mmx to fp transitions' */ 1646ebccf1e3SJoseph Koshy case PMC_EV_P6_FP_MMX_TRANS: 1647ebccf1e3SJoseph Koshy 1648ebccf1e3SJoseph Koshy /* default => 'SSE Packed Single' */ 1649ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED: 1650ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED: 1651ebccf1e3SJoseph Koshy 1652ebccf1e3SJoseph Koshy /* default => 'all fused micro-ops' */ 1653ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_FUSED_UOPS_RET: 1654ebccf1e3SJoseph Koshy 1655ebccf1e3SJoseph Koshy /* default => 'all transitions' */ 1656ebccf1e3SJoseph Koshy case PMC_EV_P6_EMON_EST_TRANS: 1657ebccf1e3SJoseph Koshy break; 1658ebccf1e3SJoseph Koshy 1659ebccf1e3SJoseph Koshy case PMC_EV_P6_MMX_UOPS_EXEC: 1660ebccf1e3SJoseph Koshy evmask = 0x0F; /* only value allowed */ 1661ebccf1e3SJoseph Koshy break; 1662ebccf1e3SJoseph Koshy 1663ebccf1e3SJoseph Koshy default: 1664ebccf1e3SJoseph Koshy /* 1665ebccf1e3SJoseph Koshy * For all other events, set the default event mask 1666ebccf1e3SJoseph Koshy * to a logical OR of all the allowed event mask bits. 1667ebccf1e3SJoseph Koshy */ 1668ebccf1e3SJoseph Koshy if (evmask == 0 && pmask) { 1669ebccf1e3SJoseph Koshy for (pm = pmask; pm->pm_name; pm++) 1670ebccf1e3SJoseph Koshy evmask |= pm->pm_value; 1671ebccf1e3SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1672ebccf1e3SJoseph Koshy } 1673ebccf1e3SJoseph Koshy 1674ebccf1e3SJoseph Koshy break; 1675ebccf1e3SJoseph Koshy } 1676ebccf1e3SJoseph Koshy 1677ebccf1e3SJoseph Koshy if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) 1678f263522aSJoseph Koshy pmc_config->pm_md.pm_ppro.pm_ppro_config |= 1679f263522aSJoseph Koshy P6_EVSEL_TO_UMASK(evmask); 1680ebccf1e3SJoseph Koshy 1681aa342b1fSJoseph Koshy return (0); 1682ebccf1e3SJoseph Koshy } 1683ebccf1e3SJoseph Koshy 1684ebccf1e3SJoseph Koshy #endif 1685ebccf1e3SJoseph Koshy 1686789140c0SJoseph Koshy #if defined(__i386__) || defined(__amd64__) 1687789140c0SJoseph Koshy static int 1688789140c0SJoseph Koshy tsc_allocate_pmc(enum pmc_event pe, char *ctrspec, 1689789140c0SJoseph Koshy struct pmc_op_pmcallocate *pmc_config) 1690789140c0SJoseph Koshy { 1691789140c0SJoseph Koshy if (pe != PMC_EV_TSC_TSC) 1692789140c0SJoseph Koshy return (-1); 1693789140c0SJoseph Koshy 1694789140c0SJoseph Koshy /* TSC events must be unqualified. */ 1695789140c0SJoseph Koshy if (ctrspec && *ctrspec != '\0') 1696789140c0SJoseph Koshy return (-1); 1697789140c0SJoseph Koshy 1698789140c0SJoseph Koshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 1699789140c0SJoseph Koshy pmc_config->pm_caps |= PMC_CAP_READ; 1700789140c0SJoseph Koshy 1701789140c0SJoseph Koshy return (0); 1702789140c0SJoseph Koshy } 1703789140c0SJoseph Koshy #endif 1704789140c0SJoseph Koshy 1705789140c0SJoseph Koshy /* 1706789140c0SJoseph Koshy * Match an event name `name' with its canonical form. 1707789140c0SJoseph Koshy * 1708789140c0SJoseph Koshy * Matches are case insensitive and spaces, underscores and hyphen 1709789140c0SJoseph Koshy * characters are considered to match each other. 1710789140c0SJoseph Koshy * 1711789140c0SJoseph Koshy * Returns 1 for a match, 0 otherwise. 1712789140c0SJoseph Koshy */ 1713789140c0SJoseph Koshy 1714789140c0SJoseph Koshy static int 1715789140c0SJoseph Koshy pmc_match_event_name(const char *name, const char *canonicalname) 1716789140c0SJoseph Koshy { 1717789140c0SJoseph Koshy int cc, nc; 1718789140c0SJoseph Koshy const unsigned char *c, *n; 1719789140c0SJoseph Koshy 1720789140c0SJoseph Koshy c = (const unsigned char *) canonicalname; 1721789140c0SJoseph Koshy n = (const unsigned char *) name; 1722789140c0SJoseph Koshy 1723789140c0SJoseph Koshy for (; (nc = *n) && (cc = *c); n++, c++) { 1724789140c0SJoseph Koshy 1725789140c0SJoseph Koshy if (toupper(nc) == cc) 1726789140c0SJoseph Koshy continue; 1727789140c0SJoseph Koshy 1728789140c0SJoseph Koshy if ((nc == ' ' || nc == '_' || nc == '-') && 1729789140c0SJoseph Koshy (cc == ' ' || cc == '_' || cc == '-')) 1730789140c0SJoseph Koshy continue; 1731789140c0SJoseph Koshy 1732789140c0SJoseph Koshy return (0); 1733789140c0SJoseph Koshy } 1734789140c0SJoseph Koshy 1735789140c0SJoseph Koshy if (*n == '\0' && *c == '\0') 1736789140c0SJoseph Koshy return (1); 1737789140c0SJoseph Koshy 1738789140c0SJoseph Koshy return (0); 1739789140c0SJoseph Koshy } 1740789140c0SJoseph Koshy 1741789140c0SJoseph Koshy /* 1742789140c0SJoseph Koshy * Match an event name against all the event named supported by a 1743789140c0SJoseph Koshy * PMC class. 1744789140c0SJoseph Koshy * 1745789140c0SJoseph Koshy * Returns an event descriptor pointer on match or NULL otherwise. 1746789140c0SJoseph Koshy */ 1747789140c0SJoseph Koshy static const struct pmc_event_descr * 1748789140c0SJoseph Koshy pmc_match_event_class(const char *name, 1749789140c0SJoseph Koshy const struct pmc_class_descr *pcd) 1750789140c0SJoseph Koshy { 1751789140c0SJoseph Koshy size_t n; 1752789140c0SJoseph Koshy const struct pmc_event_descr *ev; 1753789140c0SJoseph Koshy 1754789140c0SJoseph Koshy ev = pcd->pm_evc_event_table; 1755789140c0SJoseph Koshy for (n = 0; n < pcd->pm_evc_event_table_size; n++, ev++) 1756789140c0SJoseph Koshy if (pmc_match_event_name(name, ev->pm_ev_name)) 1757789140c0SJoseph Koshy return (ev); 1758789140c0SJoseph Koshy 1759789140c0SJoseph Koshy return (NULL); 1760789140c0SJoseph Koshy } 1761789140c0SJoseph Koshy 1762789140c0SJoseph Koshy static int 1763789140c0SJoseph Koshy pmc_mdep_is_compatible_class(enum pmc_class pc) 1764789140c0SJoseph Koshy { 1765789140c0SJoseph Koshy size_t n; 1766789140c0SJoseph Koshy 1767789140c0SJoseph Koshy for (n = 0; n < pmc_mdep_class_list_size; n++) 1768789140c0SJoseph Koshy if (pmc_mdep_class_list[n] == pc) 1769789140c0SJoseph Koshy return (1); 1770789140c0SJoseph Koshy return (0); 1771789140c0SJoseph Koshy } 1772789140c0SJoseph Koshy 1773ebccf1e3SJoseph Koshy /* 1774ebccf1e3SJoseph Koshy * API entry points 1775ebccf1e3SJoseph Koshy */ 1776ebccf1e3SJoseph Koshy 1777ebccf1e3SJoseph Koshy int 1778ebccf1e3SJoseph Koshy pmc_allocate(const char *ctrspec, enum pmc_mode mode, 1779ebccf1e3SJoseph Koshy uint32_t flags, int cpu, pmc_id_t *pmcid) 1780ebccf1e3SJoseph Koshy { 1781789140c0SJoseph Koshy size_t n; 1782ebccf1e3SJoseph Koshy int retval; 1783ebccf1e3SJoseph Koshy char *r, *spec_copy; 1784ebccf1e3SJoseph Koshy const char *ctrname; 1785789140c0SJoseph Koshy const struct pmc_event_descr *ev; 1786789140c0SJoseph Koshy const struct pmc_event_alias *alias; 1787ebccf1e3SJoseph Koshy struct pmc_op_pmcallocate pmc_config; 1788789140c0SJoseph Koshy const struct pmc_class_descr *pcd; 1789ebccf1e3SJoseph Koshy 1790ebccf1e3SJoseph Koshy spec_copy = NULL; 1791ebccf1e3SJoseph Koshy retval = -1; 1792ebccf1e3SJoseph Koshy 1793ebccf1e3SJoseph Koshy if (mode != PMC_MODE_SS && mode != PMC_MODE_TS && 1794ebccf1e3SJoseph Koshy mode != PMC_MODE_SC && mode != PMC_MODE_TC) { 1795ebccf1e3SJoseph Koshy errno = EINVAL; 1796ebccf1e3SJoseph Koshy goto out; 1797ebccf1e3SJoseph Koshy } 1798ebccf1e3SJoseph Koshy 1799ebccf1e3SJoseph Koshy /* replace an event alias with the canonical event specifier */ 1800ebccf1e3SJoseph Koshy if (pmc_mdep_event_aliases) 1801789140c0SJoseph Koshy for (alias = pmc_mdep_event_aliases; alias->pm_alias; alias++) 1802789140c0SJoseph Koshy if (!strcasecmp(ctrspec, alias->pm_alias)) { 1803789140c0SJoseph Koshy spec_copy = strdup(alias->pm_spec); 1804ebccf1e3SJoseph Koshy break; 1805ebccf1e3SJoseph Koshy } 1806ebccf1e3SJoseph Koshy 1807ebccf1e3SJoseph Koshy if (spec_copy == NULL) 1808ebccf1e3SJoseph Koshy spec_copy = strdup(ctrspec); 1809ebccf1e3SJoseph Koshy 1810ebccf1e3SJoseph Koshy r = spec_copy; 1811ebccf1e3SJoseph Koshy ctrname = strsep(&r, ","); 1812ebccf1e3SJoseph Koshy 1813789140c0SJoseph Koshy /* 1814789140c0SJoseph Koshy * If a explicit class prefix was given by the user, restrict the 1815789140c0SJoseph Koshy * search for the event to the specified PMC class. 1816789140c0SJoseph Koshy */ 1817789140c0SJoseph Koshy ev = NULL; 1818789140c0SJoseph Koshy for (n = 0; n < pmc_event_class_table_size; n++) { 1819789140c0SJoseph Koshy pcd = &pmc_class_table[n]; 1820789140c0SJoseph Koshy if (pmc_mdep_is_compatible_class(pcd->pm_evc_class) && 1821789140c0SJoseph Koshy strncasecmp(ctrname, pcd->pm_evc_name, 1822789140c0SJoseph Koshy pcd->pm_evc_name_size) == 0) { 1823789140c0SJoseph Koshy if ((ev = pmc_match_event_class(ctrname + 1824789140c0SJoseph Koshy pcd->pm_evc_name_size, pcd)) == NULL) { 1825789140c0SJoseph Koshy errno = EINVAL; 1826789140c0SJoseph Koshy goto out; 1827789140c0SJoseph Koshy } 1828ebccf1e3SJoseph Koshy break; 1829789140c0SJoseph Koshy } 1830789140c0SJoseph Koshy } 1831ebccf1e3SJoseph Koshy 1832789140c0SJoseph Koshy /* 1833789140c0SJoseph Koshy * Otherwise, search for this event in all compatible PMC 1834789140c0SJoseph Koshy * classes. 1835789140c0SJoseph Koshy */ 1836789140c0SJoseph Koshy for (n = 0; ev == NULL && n < pmc_event_class_table_size; n++) { 1837789140c0SJoseph Koshy pcd = &pmc_class_table[n]; 1838789140c0SJoseph Koshy if (pmc_mdep_is_compatible_class(pcd->pm_evc_class)) 1839789140c0SJoseph Koshy ev = pmc_match_event_class(ctrname, pcd); 1840789140c0SJoseph Koshy } 1841789140c0SJoseph Koshy 1842789140c0SJoseph Koshy if (ev == NULL) { 1843ebccf1e3SJoseph Koshy errno = EINVAL; 1844ebccf1e3SJoseph Koshy goto out; 1845ebccf1e3SJoseph Koshy } 1846ebccf1e3SJoseph Koshy 1847ebccf1e3SJoseph Koshy bzero(&pmc_config, sizeof(pmc_config)); 1848789140c0SJoseph Koshy pmc_config.pm_ev = ev->pm_ev_code; 1849789140c0SJoseph Koshy pmc_config.pm_class = pcd->pm_evc_class; 1850ebccf1e3SJoseph Koshy pmc_config.pm_cpu = cpu; 1851ebccf1e3SJoseph Koshy pmc_config.pm_mode = mode; 1852ebccf1e3SJoseph Koshy pmc_config.pm_flags = flags; 1853ebccf1e3SJoseph Koshy 1854ebccf1e3SJoseph Koshy if (PMC_IS_SAMPLING_MODE(mode)) 1855ebccf1e3SJoseph Koshy pmc_config.pm_caps |= PMC_CAP_INTERRUPT; 1856ebccf1e3SJoseph Koshy 1857789140c0SJoseph Koshy if (pcd->pm_evc_allocate_pmc(ev->pm_ev_code, r, &pmc_config) < 0) { 1858ebccf1e3SJoseph Koshy errno = EINVAL; 1859ebccf1e3SJoseph Koshy goto out; 1860ebccf1e3SJoseph Koshy } 1861ebccf1e3SJoseph Koshy 1862ebccf1e3SJoseph Koshy if (PMC_CALL(PMCALLOCATE, &pmc_config) < 0) 1863ebccf1e3SJoseph Koshy goto out; 1864ebccf1e3SJoseph Koshy 1865ebccf1e3SJoseph Koshy *pmcid = pmc_config.pm_pmcid; 1866ebccf1e3SJoseph Koshy 1867ebccf1e3SJoseph Koshy retval = 0; 1868ebccf1e3SJoseph Koshy 1869ebccf1e3SJoseph Koshy out: 1870ebccf1e3SJoseph Koshy if (spec_copy) 1871ebccf1e3SJoseph Koshy free(spec_copy); 1872ebccf1e3SJoseph Koshy 1873aa342b1fSJoseph Koshy return (retval); 1874ebccf1e3SJoseph Koshy } 1875ebccf1e3SJoseph Koshy 1876ebccf1e3SJoseph Koshy int 1877ebccf1e3SJoseph Koshy pmc_attach(pmc_id_t pmc, pid_t pid) 1878ebccf1e3SJoseph Koshy { 1879ebccf1e3SJoseph Koshy struct pmc_op_pmcattach pmc_attach_args; 1880ebccf1e3SJoseph Koshy 1881ebccf1e3SJoseph Koshy pmc_attach_args.pm_pmc = pmc; 1882ebccf1e3SJoseph Koshy pmc_attach_args.pm_pid = pid; 1883ebccf1e3SJoseph Koshy 1884aa342b1fSJoseph Koshy return (PMC_CALL(PMCATTACH, &pmc_attach_args)); 1885ebccf1e3SJoseph Koshy } 1886ebccf1e3SJoseph Koshy 1887ebccf1e3SJoseph Koshy int 1888c5153e19SJoseph Koshy pmc_capabilities(pmc_id_t pmcid, uint32_t *caps) 1889c5153e19SJoseph Koshy { 1890c5153e19SJoseph Koshy unsigned int i; 1891c5153e19SJoseph Koshy enum pmc_class cl; 1892c5153e19SJoseph Koshy 1893c5153e19SJoseph Koshy cl = PMC_ID_TO_CLASS(pmcid); 1894c5153e19SJoseph Koshy for (i = 0; i < cpu_info.pm_nclass; i++) 1895c5153e19SJoseph Koshy if (cpu_info.pm_classes[i].pm_class == cl) { 1896c5153e19SJoseph Koshy *caps = cpu_info.pm_classes[i].pm_caps; 1897aa342b1fSJoseph Koshy return (0); 1898c5153e19SJoseph Koshy } 1899484202faSJoseph Koshy errno = EINVAL; 1900484202faSJoseph Koshy return (-1); 1901c5153e19SJoseph Koshy } 1902c5153e19SJoseph Koshy 1903f263522aSJoseph Koshy int 1904f263522aSJoseph Koshy pmc_configure_logfile(int fd) 1905ebccf1e3SJoseph Koshy { 1906f263522aSJoseph Koshy struct pmc_op_configurelog cla; 1907f263522aSJoseph Koshy 1908f263522aSJoseph Koshy cla.pm_logfd = fd; 1909f263522aSJoseph Koshy if (PMC_CALL(CONFIGURELOG, &cla) < 0) 1910aa342b1fSJoseph Koshy return (-1); 1911aa342b1fSJoseph Koshy return (0); 1912ebccf1e3SJoseph Koshy } 1913ebccf1e3SJoseph Koshy 1914f263522aSJoseph Koshy int 1915f263522aSJoseph Koshy pmc_cpuinfo(const struct pmc_cpuinfo **pci) 1916ebccf1e3SJoseph Koshy { 1917f263522aSJoseph Koshy if (pmc_syscall == -1) { 1918f263522aSJoseph Koshy errno = ENXIO; 1919aa342b1fSJoseph Koshy return (-1); 1920ebccf1e3SJoseph Koshy } 1921ebccf1e3SJoseph Koshy 19221455fcd3SJoseph Koshy *pci = &cpu_info; 1923aa342b1fSJoseph Koshy return (0); 1924ebccf1e3SJoseph Koshy } 1925ebccf1e3SJoseph Koshy 1926f263522aSJoseph Koshy int 1927f263522aSJoseph Koshy pmc_detach(pmc_id_t pmc, pid_t pid) 1928ebccf1e3SJoseph Koshy { 1929f263522aSJoseph Koshy struct pmc_op_pmcattach pmc_detach_args; 1930ebccf1e3SJoseph Koshy 1931f263522aSJoseph Koshy pmc_detach_args.pm_pmc = pmc; 1932f263522aSJoseph Koshy pmc_detach_args.pm_pid = pid; 1933aa342b1fSJoseph Koshy return (PMC_CALL(PMCDETACH, &pmc_detach_args)); 1934ebccf1e3SJoseph Koshy } 1935ebccf1e3SJoseph Koshy 1936f263522aSJoseph Koshy int 1937f263522aSJoseph Koshy pmc_disable(int cpu, int pmc) 1938ebccf1e3SJoseph Koshy { 1939f263522aSJoseph Koshy struct pmc_op_pmcadmin ssa; 1940ebccf1e3SJoseph Koshy 1941f263522aSJoseph Koshy ssa.pm_cpu = cpu; 1942f263522aSJoseph Koshy ssa.pm_pmc = pmc; 1943f263522aSJoseph Koshy ssa.pm_state = PMC_STATE_DISABLED; 1944aa342b1fSJoseph Koshy return (PMC_CALL(PMCADMIN, &ssa)); 1945ebccf1e3SJoseph Koshy } 1946ebccf1e3SJoseph Koshy 1947f263522aSJoseph Koshy int 1948f263522aSJoseph Koshy pmc_enable(int cpu, int pmc) 1949ebccf1e3SJoseph Koshy { 1950f263522aSJoseph Koshy struct pmc_op_pmcadmin ssa; 1951ebccf1e3SJoseph Koshy 1952f263522aSJoseph Koshy ssa.pm_cpu = cpu; 1953f263522aSJoseph Koshy ssa.pm_pmc = pmc; 1954f263522aSJoseph Koshy ssa.pm_state = PMC_STATE_FREE; 1955aa342b1fSJoseph Koshy return (PMC_CALL(PMCADMIN, &ssa)); 1956ebccf1e3SJoseph Koshy } 1957ebccf1e3SJoseph Koshy 1958ebccf1e3SJoseph Koshy /* 1959ebccf1e3SJoseph Koshy * Return a list of events known to a given PMC class. 'cl' is the 1960ebccf1e3SJoseph Koshy * PMC class identifier, 'eventnames' is the returned list of 'const 1961ebccf1e3SJoseph Koshy * char *' pointers pointing to the names of the events. 'nevents' is 1962ebccf1e3SJoseph Koshy * the number of event name pointers returned. 1963ebccf1e3SJoseph Koshy * 1964ebccf1e3SJoseph Koshy * The space for 'eventnames' is allocated using malloc(3). The caller 1965ebccf1e3SJoseph Koshy * is responsible for freeing this space when done. 1966ebccf1e3SJoseph Koshy */ 1967ebccf1e3SJoseph Koshy int 1968ebccf1e3SJoseph Koshy pmc_event_names_of_class(enum pmc_class cl, const char ***eventnames, 1969ebccf1e3SJoseph Koshy int *nevents) 1970ebccf1e3SJoseph Koshy { 1971ebccf1e3SJoseph Koshy int count; 1972ebccf1e3SJoseph Koshy const char **names; 1973ebccf1e3SJoseph Koshy const struct pmc_event_descr *ev; 1974ebccf1e3SJoseph Koshy 1975ebccf1e3SJoseph Koshy switch (cl) 1976ebccf1e3SJoseph Koshy { 1977ebccf1e3SJoseph Koshy case PMC_CLASS_TSC: 1978789140c0SJoseph Koshy ev = tsc_event_table; 1979789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(tsc); 1980ebccf1e3SJoseph Koshy break; 1981ebccf1e3SJoseph Koshy case PMC_CLASS_K7: 1982789140c0SJoseph Koshy ev = k7_event_table; 1983789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(k7); 1984ebccf1e3SJoseph Koshy break; 1985ebccf1e3SJoseph Koshy case PMC_CLASS_K8: 1986789140c0SJoseph Koshy ev = k8_event_table; 1987789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(k8); 1988ebccf1e3SJoseph Koshy break; 1989ebccf1e3SJoseph Koshy case PMC_CLASS_P4: 1990789140c0SJoseph Koshy ev = p4_event_table; 1991789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p4); 1992789140c0SJoseph Koshy break; 1993789140c0SJoseph Koshy case PMC_CLASS_P5: 1994789140c0SJoseph Koshy ev = p5_event_table; 1995789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p5); 1996789140c0SJoseph Koshy break; 1997789140c0SJoseph Koshy case PMC_CLASS_P6: 1998789140c0SJoseph Koshy ev = p6_event_table; 1999789140c0SJoseph Koshy count = PMC_EVENT_TABLE_SIZE(p6); 2000ebccf1e3SJoseph Koshy break; 2001ebccf1e3SJoseph Koshy default: 2002ebccf1e3SJoseph Koshy errno = EINVAL; 2003aa342b1fSJoseph Koshy return (-1); 2004ebccf1e3SJoseph Koshy } 2005ebccf1e3SJoseph Koshy 2006ebccf1e3SJoseph Koshy if ((names = malloc(count * sizeof(const char *))) == NULL) 2007aa342b1fSJoseph Koshy return (-1); 2008ebccf1e3SJoseph Koshy 2009ebccf1e3SJoseph Koshy *eventnames = names; 2010ebccf1e3SJoseph Koshy *nevents = count; 2011ebccf1e3SJoseph Koshy 2012ebccf1e3SJoseph Koshy for (;count--; ev++, names++) 2013ebccf1e3SJoseph Koshy *names = ev->pm_ev_name; 2014aa342b1fSJoseph Koshy return (0); 2015ebccf1e3SJoseph Koshy } 2016ebccf1e3SJoseph Koshy 2017f263522aSJoseph Koshy int 2018f263522aSJoseph Koshy pmc_flush_logfile(void) 2019f263522aSJoseph Koshy { 2020aa342b1fSJoseph Koshy return (PMC_CALL(FLUSHLOG,0)); 2021f263522aSJoseph Koshy } 2022ebccf1e3SJoseph Koshy 2023ebccf1e3SJoseph Koshy int 2024f263522aSJoseph Koshy pmc_get_driver_stats(struct pmc_driverstats *ds) 2025ebccf1e3SJoseph Koshy { 2026f263522aSJoseph Koshy struct pmc_op_getdriverstats gms; 2027f263522aSJoseph Koshy 2028f263522aSJoseph Koshy if (PMC_CALL(GETDRIVERSTATS, &gms) < 0) 2029aa342b1fSJoseph Koshy return (-1); 2030f263522aSJoseph Koshy 2031f263522aSJoseph Koshy /* copy out fields in the current userland<->library interface */ 2032f263522aSJoseph Koshy ds->pm_intr_ignored = gms.pm_intr_ignored; 2033f263522aSJoseph Koshy ds->pm_intr_processed = gms.pm_intr_processed; 2034f263522aSJoseph Koshy ds->pm_intr_bufferfull = gms.pm_intr_bufferfull; 2035f263522aSJoseph Koshy ds->pm_syscalls = gms.pm_syscalls; 2036f263522aSJoseph Koshy ds->pm_syscall_errors = gms.pm_syscall_errors; 2037f263522aSJoseph Koshy ds->pm_buffer_requests = gms.pm_buffer_requests; 2038f263522aSJoseph Koshy ds->pm_buffer_requests_failed = gms.pm_buffer_requests_failed; 2039f263522aSJoseph Koshy ds->pm_log_sweeps = gms.pm_log_sweeps; 2040aa342b1fSJoseph Koshy return (0); 2041f263522aSJoseph Koshy } 2042f263522aSJoseph Koshy 2043f263522aSJoseph Koshy int 2044f263522aSJoseph Koshy pmc_get_msr(pmc_id_t pmc, uint32_t *msr) 2045f263522aSJoseph Koshy { 2046f263522aSJoseph Koshy struct pmc_op_getmsr gm; 2047ebccf1e3SJoseph Koshy 2048ebccf1e3SJoseph Koshy gm.pm_pmcid = pmc; 2049f263522aSJoseph Koshy if (PMC_CALL(PMCGETMSR, &gm) < 0) 2050aa342b1fSJoseph Koshy return (-1); 2051ebccf1e3SJoseph Koshy *msr = gm.pm_msr; 2052aa342b1fSJoseph Koshy return (0); 2053ebccf1e3SJoseph Koshy } 2054ebccf1e3SJoseph Koshy 2055f263522aSJoseph Koshy int 2056f263522aSJoseph Koshy pmc_init(void) 2057f263522aSJoseph Koshy { 2058f263522aSJoseph Koshy int error, pmc_mod_id; 20591455fcd3SJoseph Koshy unsigned int n; 2060f263522aSJoseph Koshy uint32_t abi_version; 2061f263522aSJoseph Koshy struct module_stat pmc_modstat; 20621455fcd3SJoseph Koshy struct pmc_op_getcpuinfo op_cpu_info; 2063f263522aSJoseph Koshy 2064f263522aSJoseph Koshy if (pmc_syscall != -1) /* already inited */ 2065aa342b1fSJoseph Koshy return (0); 2066f263522aSJoseph Koshy 2067f263522aSJoseph Koshy /* retrieve the system call number from the KLD */ 2068f263522aSJoseph Koshy if ((pmc_mod_id = modfind(PMC_MODULE_NAME)) < 0) 2069aa342b1fSJoseph Koshy return (-1); 2070f263522aSJoseph Koshy 2071f263522aSJoseph Koshy pmc_modstat.version = sizeof(struct module_stat); 2072f263522aSJoseph Koshy if ((error = modstat(pmc_mod_id, &pmc_modstat)) < 0) 2073aa342b1fSJoseph Koshy return (-1); 2074f263522aSJoseph Koshy 2075f263522aSJoseph Koshy pmc_syscall = pmc_modstat.data.intval; 2076f263522aSJoseph Koshy 2077f263522aSJoseph Koshy /* check the kernel module's ABI against our compiled-in version */ 2078f263522aSJoseph Koshy abi_version = PMC_VERSION; 2079f263522aSJoseph Koshy if (PMC_CALL(GETMODULEVERSION, &abi_version) < 0) 2080f263522aSJoseph Koshy return (pmc_syscall = -1); 2081f263522aSJoseph Koshy 2082f263522aSJoseph Koshy /* ignore patch & minor numbers for the comparision */ 2083f263522aSJoseph Koshy if ((abi_version & 0xFF000000) != (PMC_VERSION & 0xFF000000)) { 2084f263522aSJoseph Koshy errno = EPROGMISMATCH; 2085f263522aSJoseph Koshy return (pmc_syscall = -1); 2086f263522aSJoseph Koshy } 2087f263522aSJoseph Koshy 20881455fcd3SJoseph Koshy if (PMC_CALL(GETCPUINFO, &op_cpu_info) < 0) 2089f263522aSJoseph Koshy return (pmc_syscall = -1); 2090f263522aSJoseph Koshy 20911455fcd3SJoseph Koshy cpu_info.pm_cputype = op_cpu_info.pm_cputype; 20921455fcd3SJoseph Koshy cpu_info.pm_ncpu = op_cpu_info.pm_ncpu; 20931455fcd3SJoseph Koshy cpu_info.pm_npmc = op_cpu_info.pm_npmc; 20941455fcd3SJoseph Koshy cpu_info.pm_nclass = op_cpu_info.pm_nclass; 20951455fcd3SJoseph Koshy for (n = 0; n < cpu_info.pm_nclass; n++) 20961455fcd3SJoseph Koshy cpu_info.pm_classes[n] = op_cpu_info.pm_classes[n]; 20971455fcd3SJoseph Koshy 2098789140c0SJoseph Koshy #define PMC_MDEP_INIT(C) do { \ 2099789140c0SJoseph Koshy pmc_mdep_event_aliases = C##_aliases; \ 2100789140c0SJoseph Koshy pmc_mdep_class_list = C##_pmc_classes; \ 2101789140c0SJoseph Koshy pmc_mdep_class_list_size = \ 2102789140c0SJoseph Koshy PMC_TABLE_SIZE(C##_pmc_classes); \ 2103789140c0SJoseph Koshy } while (0) 2104789140c0SJoseph Koshy 2105789140c0SJoseph Koshy /* Configure the event name parser. */ 2106f263522aSJoseph Koshy switch (cpu_info.pm_cputype) { 2107f263522aSJoseph Koshy #if defined(__i386__) 2108f263522aSJoseph Koshy case PMC_CPU_AMD_K7: 2109789140c0SJoseph Koshy PMC_MDEP_INIT(k7); 2110f263522aSJoseph Koshy break; 2111f263522aSJoseph Koshy case PMC_CPU_INTEL_P5: 2112789140c0SJoseph Koshy PMC_MDEP_INIT(p5); 2113f263522aSJoseph Koshy break; 2114f263522aSJoseph Koshy case PMC_CPU_INTEL_P6: /* P6 ... Pentium M CPUs have */ 2115f263522aSJoseph Koshy case PMC_CPU_INTEL_PII: /* similar PMCs. */ 2116f263522aSJoseph Koshy case PMC_CPU_INTEL_PIII: 2117f263522aSJoseph Koshy case PMC_CPU_INTEL_PM: 2118789140c0SJoseph Koshy PMC_MDEP_INIT(p6); 2119f263522aSJoseph Koshy break; 212086a65549SJoseph Koshy #endif 212186a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__) 2122f263522aSJoseph Koshy case PMC_CPU_AMD_K8: 2123789140c0SJoseph Koshy PMC_MDEP_INIT(k8); 2124789140c0SJoseph Koshy break; 2125789140c0SJoseph Koshy case PMC_CPU_INTEL_PIV: 2126789140c0SJoseph Koshy PMC_MDEP_INIT(p4); 2127f263522aSJoseph Koshy break; 2128ebccf1e3SJoseph Koshy #endif 2129f263522aSJoseph Koshy 2130f263522aSJoseph Koshy default: 2131f263522aSJoseph Koshy /* 2132f263522aSJoseph Koshy * Some kind of CPU this version of the library knows nothing 2133f263522aSJoseph Koshy * about. This shouldn't happen since the abi version check 2134f263522aSJoseph Koshy * should have caught this. 2135f263522aSJoseph Koshy */ 2136f263522aSJoseph Koshy errno = ENXIO; 2137f263522aSJoseph Koshy return (pmc_syscall = -1); 2138f263522aSJoseph Koshy } 2139f263522aSJoseph Koshy 2140aa342b1fSJoseph Koshy return (0); 2141f263522aSJoseph Koshy } 2142f263522aSJoseph Koshy 2143f263522aSJoseph Koshy const char * 2144f263522aSJoseph Koshy pmc_name_of_capability(enum pmc_caps cap) 2145f263522aSJoseph Koshy { 2146f263522aSJoseph Koshy int i; 2147f263522aSJoseph Koshy 2148f263522aSJoseph Koshy /* 2149f263522aSJoseph Koshy * 'cap' should have a single bit set and should be in 2150f263522aSJoseph Koshy * range. 2151f263522aSJoseph Koshy */ 2152f263522aSJoseph Koshy if ((cap & (cap - 1)) || cap < PMC_CAP_FIRST || 2153f263522aSJoseph Koshy cap > PMC_CAP_LAST) { 2154f263522aSJoseph Koshy errno = EINVAL; 2155aa342b1fSJoseph Koshy return (NULL); 2156f263522aSJoseph Koshy } 2157f263522aSJoseph Koshy 2158f263522aSJoseph Koshy i = ffs(cap); 2159aa342b1fSJoseph Koshy return (pmc_capability_names[i - 1]); 2160f263522aSJoseph Koshy } 2161f263522aSJoseph Koshy 2162f263522aSJoseph Koshy const char * 2163f263522aSJoseph Koshy pmc_name_of_class(enum pmc_class pc) 2164f263522aSJoseph Koshy { 2165f263522aSJoseph Koshy if ((int) pc >= PMC_CLASS_FIRST && 2166f263522aSJoseph Koshy pc <= PMC_CLASS_LAST) 2167aa342b1fSJoseph Koshy return (pmc_class_names[pc]); 2168f263522aSJoseph Koshy 2169f263522aSJoseph Koshy errno = EINVAL; 2170aa342b1fSJoseph Koshy return (NULL); 2171f263522aSJoseph Koshy } 2172f263522aSJoseph Koshy 2173f263522aSJoseph Koshy const char * 2174f263522aSJoseph Koshy pmc_name_of_cputype(enum pmc_cputype cp) 2175f263522aSJoseph Koshy { 2176789140c0SJoseph Koshy size_t n; 2177789140c0SJoseph Koshy 2178789140c0SJoseph Koshy for (n = 0; n < PMC_TABLE_SIZE(pmc_cputype_names); n++) 2179789140c0SJoseph Koshy if (cp == pmc_cputype_names[n].pm_cputype) 2180789140c0SJoseph Koshy return (pmc_cputype_names[n].pm_name); 2181789140c0SJoseph Koshy 2182f263522aSJoseph Koshy errno = EINVAL; 2183aa342b1fSJoseph Koshy return (NULL); 2184f263522aSJoseph Koshy } 2185f263522aSJoseph Koshy 2186f263522aSJoseph Koshy const char * 2187f263522aSJoseph Koshy pmc_name_of_disposition(enum pmc_disp pd) 2188f263522aSJoseph Koshy { 2189f263522aSJoseph Koshy if ((int) pd >= PMC_DISP_FIRST && 2190f263522aSJoseph Koshy pd <= PMC_DISP_LAST) 2191aa342b1fSJoseph Koshy return (pmc_disposition_names[pd]); 2192f263522aSJoseph Koshy 2193f263522aSJoseph Koshy errno = EINVAL; 2194aa342b1fSJoseph Koshy return (NULL); 2195f263522aSJoseph Koshy } 2196f263522aSJoseph Koshy 2197f263522aSJoseph Koshy const char * 2198f263522aSJoseph Koshy pmc_name_of_event(enum pmc_event pe) 2199f263522aSJoseph Koshy { 2200789140c0SJoseph Koshy const struct pmc_event_descr *ev, *evfence; 2201789140c0SJoseph Koshy 2202789140c0SJoseph Koshy ev = evfence = NULL; 2203789140c0SJoseph Koshy if (pe >= PMC_EV_K7_FIRST && pe <= PMC_EV_K7_LAST) { 2204789140c0SJoseph Koshy ev = k7_event_table; 2205789140c0SJoseph Koshy evfence = k7_event_table + PMC_EVENT_TABLE_SIZE(k7); 2206789140c0SJoseph Koshy } else if (pe >= PMC_EV_K8_FIRST && pe <= PMC_EV_K8_LAST) { 2207789140c0SJoseph Koshy ev = k8_event_table; 2208789140c0SJoseph Koshy evfence = k8_event_table + PMC_EVENT_TABLE_SIZE(k8); 2209789140c0SJoseph Koshy } else if (pe >= PMC_EV_P4_FIRST && pe <= PMC_EV_P4_LAST) { 2210789140c0SJoseph Koshy ev = p4_event_table; 2211789140c0SJoseph Koshy evfence = p4_event_table + PMC_EVENT_TABLE_SIZE(p4); 2212789140c0SJoseph Koshy } else if (pe >= PMC_EV_P5_FIRST && pe <= PMC_EV_P5_LAST) { 2213789140c0SJoseph Koshy ev = p5_event_table; 2214789140c0SJoseph Koshy evfence = p5_event_table + PMC_EVENT_TABLE_SIZE(p5); 2215789140c0SJoseph Koshy } else if (pe >= PMC_EV_P6_FIRST && pe <= PMC_EV_P6_LAST) { 2216789140c0SJoseph Koshy ev = p6_event_table; 2217789140c0SJoseph Koshy evfence = p6_event_table + PMC_EVENT_TABLE_SIZE(p6); 2218789140c0SJoseph Koshy } else if (pe == PMC_EV_TSC_TSC) { 2219789140c0SJoseph Koshy ev = tsc_event_table; 2220789140c0SJoseph Koshy evfence = tsc_event_table + PMC_EVENT_TABLE_SIZE(tsc); 2221789140c0SJoseph Koshy } 2222789140c0SJoseph Koshy 2223789140c0SJoseph Koshy for (; ev != evfence; ev++) 2224789140c0SJoseph Koshy if (pe == ev->pm_ev_code) 2225789140c0SJoseph Koshy return (ev->pm_ev_name); 2226f263522aSJoseph Koshy 2227f263522aSJoseph Koshy errno = EINVAL; 2228aa342b1fSJoseph Koshy return (NULL); 2229f263522aSJoseph Koshy } 2230f263522aSJoseph Koshy 2231f263522aSJoseph Koshy const char * 2232f263522aSJoseph Koshy pmc_name_of_mode(enum pmc_mode pm) 2233f263522aSJoseph Koshy { 2234f263522aSJoseph Koshy if ((int) pm >= PMC_MODE_FIRST && 2235f263522aSJoseph Koshy pm <= PMC_MODE_LAST) 2236aa342b1fSJoseph Koshy return (pmc_mode_names[pm]); 2237f263522aSJoseph Koshy 2238f263522aSJoseph Koshy errno = EINVAL; 2239aa342b1fSJoseph Koshy return (NULL); 2240f263522aSJoseph Koshy } 2241f263522aSJoseph Koshy 2242f263522aSJoseph Koshy const char * 2243f263522aSJoseph Koshy pmc_name_of_state(enum pmc_state ps) 2244f263522aSJoseph Koshy { 2245f263522aSJoseph Koshy if ((int) ps >= PMC_STATE_FIRST && 2246f263522aSJoseph Koshy ps <= PMC_STATE_LAST) 2247aa342b1fSJoseph Koshy return (pmc_state_names[ps]); 2248f263522aSJoseph Koshy 2249f263522aSJoseph Koshy errno = EINVAL; 2250aa342b1fSJoseph Koshy return (NULL); 2251f263522aSJoseph Koshy } 2252f263522aSJoseph Koshy 2253f263522aSJoseph Koshy int 2254f263522aSJoseph Koshy pmc_ncpu(void) 2255f263522aSJoseph Koshy { 2256f263522aSJoseph Koshy if (pmc_syscall == -1) { 2257f263522aSJoseph Koshy errno = ENXIO; 2258aa342b1fSJoseph Koshy return (-1); 2259f263522aSJoseph Koshy } 2260f263522aSJoseph Koshy 2261aa342b1fSJoseph Koshy return (cpu_info.pm_ncpu); 2262f263522aSJoseph Koshy } 2263f263522aSJoseph Koshy 2264f263522aSJoseph Koshy int 2265f263522aSJoseph Koshy pmc_npmc(int cpu) 2266f263522aSJoseph Koshy { 2267f263522aSJoseph Koshy if (pmc_syscall == -1) { 2268f263522aSJoseph Koshy errno = ENXIO; 2269aa342b1fSJoseph Koshy return (-1); 2270f263522aSJoseph Koshy } 2271f263522aSJoseph Koshy 2272f263522aSJoseph Koshy if (cpu < 0 || cpu >= (int) cpu_info.pm_ncpu) { 2273f263522aSJoseph Koshy errno = EINVAL; 2274aa342b1fSJoseph Koshy return (-1); 2275f263522aSJoseph Koshy } 2276f263522aSJoseph Koshy 2277aa342b1fSJoseph Koshy return (cpu_info.pm_npmc); 2278f263522aSJoseph Koshy } 2279f263522aSJoseph Koshy 2280f263522aSJoseph Koshy int 2281f263522aSJoseph Koshy pmc_pmcinfo(int cpu, struct pmc_pmcinfo **ppmci) 2282f263522aSJoseph Koshy { 2283f263522aSJoseph Koshy int nbytes, npmc; 2284f263522aSJoseph Koshy struct pmc_op_getpmcinfo *pmci; 2285f263522aSJoseph Koshy 2286f263522aSJoseph Koshy if ((npmc = pmc_npmc(cpu)) < 0) 2287aa342b1fSJoseph Koshy return (-1); 2288f263522aSJoseph Koshy 2289f263522aSJoseph Koshy nbytes = sizeof(struct pmc_op_getpmcinfo) + 2290f263522aSJoseph Koshy npmc * sizeof(struct pmc_info); 2291f263522aSJoseph Koshy 2292f263522aSJoseph Koshy if ((pmci = calloc(1, nbytes)) == NULL) 2293aa342b1fSJoseph Koshy return (-1); 2294f263522aSJoseph Koshy 2295f263522aSJoseph Koshy pmci->pm_cpu = cpu; 2296f263522aSJoseph Koshy 2297f263522aSJoseph Koshy if (PMC_CALL(GETPMCINFO, pmci) < 0) { 2298f263522aSJoseph Koshy free(pmci); 2299aa342b1fSJoseph Koshy return (-1); 2300f263522aSJoseph Koshy } 2301f263522aSJoseph Koshy 2302f263522aSJoseph Koshy /* kernel<->library, library<->userland interfaces are identical */ 2303f263522aSJoseph Koshy *ppmci = (struct pmc_pmcinfo *) pmci; 2304aa342b1fSJoseph Koshy return (0); 2305f263522aSJoseph Koshy } 2306f263522aSJoseph Koshy 2307f263522aSJoseph Koshy int 2308f263522aSJoseph Koshy pmc_read(pmc_id_t pmc, pmc_value_t *value) 2309f263522aSJoseph Koshy { 2310f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_read_op; 2311f263522aSJoseph Koshy 2312f263522aSJoseph Koshy pmc_read_op.pm_pmcid = pmc; 2313f263522aSJoseph Koshy pmc_read_op.pm_flags = PMC_F_OLDVALUE; 2314f263522aSJoseph Koshy pmc_read_op.pm_value = -1; 2315f263522aSJoseph Koshy 2316f263522aSJoseph Koshy if (PMC_CALL(PMCRW, &pmc_read_op) < 0) 2317aa342b1fSJoseph Koshy return (-1); 2318f263522aSJoseph Koshy 2319f263522aSJoseph Koshy *value = pmc_read_op.pm_value; 2320aa342b1fSJoseph Koshy return (0); 2321f263522aSJoseph Koshy } 2322f263522aSJoseph Koshy 2323f263522aSJoseph Koshy int 2324f263522aSJoseph Koshy pmc_release(pmc_id_t pmc) 2325f263522aSJoseph Koshy { 2326f263522aSJoseph Koshy struct pmc_op_simple pmc_release_args; 2327f263522aSJoseph Koshy 2328f263522aSJoseph Koshy pmc_release_args.pm_pmcid = pmc; 2329aa342b1fSJoseph Koshy return (PMC_CALL(PMCRELEASE, &pmc_release_args)); 2330f263522aSJoseph Koshy } 2331f263522aSJoseph Koshy 2332f263522aSJoseph Koshy int 2333f263522aSJoseph Koshy pmc_rw(pmc_id_t pmc, pmc_value_t newvalue, pmc_value_t *oldvaluep) 2334f263522aSJoseph Koshy { 2335f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_rw_op; 2336f263522aSJoseph Koshy 2337f263522aSJoseph Koshy pmc_rw_op.pm_pmcid = pmc; 2338f263522aSJoseph Koshy pmc_rw_op.pm_flags = PMC_F_NEWVALUE | PMC_F_OLDVALUE; 2339f263522aSJoseph Koshy pmc_rw_op.pm_value = newvalue; 2340f263522aSJoseph Koshy 2341f263522aSJoseph Koshy if (PMC_CALL(PMCRW, &pmc_rw_op) < 0) 2342aa342b1fSJoseph Koshy return (-1); 2343f263522aSJoseph Koshy 2344f263522aSJoseph Koshy *oldvaluep = pmc_rw_op.pm_value; 2345aa342b1fSJoseph Koshy return (0); 2346f263522aSJoseph Koshy } 2347f263522aSJoseph Koshy 2348f263522aSJoseph Koshy int 2349f263522aSJoseph Koshy pmc_set(pmc_id_t pmc, pmc_value_t value) 2350f263522aSJoseph Koshy { 2351f263522aSJoseph Koshy struct pmc_op_pmcsetcount sc; 2352f263522aSJoseph Koshy 2353f263522aSJoseph Koshy sc.pm_pmcid = pmc; 2354f263522aSJoseph Koshy sc.pm_count = value; 2355f263522aSJoseph Koshy 2356f263522aSJoseph Koshy if (PMC_CALL(PMCSETCOUNT, &sc) < 0) 2357aa342b1fSJoseph Koshy return (-1); 2358aa342b1fSJoseph Koshy return (0); 2359f263522aSJoseph Koshy } 2360f263522aSJoseph Koshy 2361f263522aSJoseph Koshy int 2362f263522aSJoseph Koshy pmc_start(pmc_id_t pmc) 2363f263522aSJoseph Koshy { 2364f263522aSJoseph Koshy struct pmc_op_simple pmc_start_args; 2365f263522aSJoseph Koshy 2366f263522aSJoseph Koshy pmc_start_args.pm_pmcid = pmc; 2367aa342b1fSJoseph Koshy return (PMC_CALL(PMCSTART, &pmc_start_args)); 2368f263522aSJoseph Koshy } 2369f263522aSJoseph Koshy 2370f263522aSJoseph Koshy int 2371f263522aSJoseph Koshy pmc_stop(pmc_id_t pmc) 2372f263522aSJoseph Koshy { 2373f263522aSJoseph Koshy struct pmc_op_simple pmc_stop_args; 2374f263522aSJoseph Koshy 2375f263522aSJoseph Koshy pmc_stop_args.pm_pmcid = pmc; 2376aa342b1fSJoseph Koshy return (PMC_CALL(PMCSTOP, &pmc_stop_args)); 2377f263522aSJoseph Koshy } 2378f263522aSJoseph Koshy 2379f263522aSJoseph Koshy int 2380f263522aSJoseph Koshy pmc_width(pmc_id_t pmcid, uint32_t *width) 2381f263522aSJoseph Koshy { 2382f263522aSJoseph Koshy unsigned int i; 2383f263522aSJoseph Koshy enum pmc_class cl; 2384f263522aSJoseph Koshy 2385f263522aSJoseph Koshy cl = PMC_ID_TO_CLASS(pmcid); 2386f263522aSJoseph Koshy for (i = 0; i < cpu_info.pm_nclass; i++) 2387f263522aSJoseph Koshy if (cpu_info.pm_classes[i].pm_class == cl) { 2388f263522aSJoseph Koshy *width = cpu_info.pm_classes[i].pm_width; 2389aa342b1fSJoseph Koshy return (0); 2390f263522aSJoseph Koshy } 2391484202faSJoseph Koshy errno = EINVAL; 2392484202faSJoseph Koshy return (-1); 2393f263522aSJoseph Koshy } 2394f263522aSJoseph Koshy 2395f263522aSJoseph Koshy int 2396f263522aSJoseph Koshy pmc_write(pmc_id_t pmc, pmc_value_t value) 2397f263522aSJoseph Koshy { 2398f263522aSJoseph Koshy struct pmc_op_pmcrw pmc_write_op; 2399f263522aSJoseph Koshy 2400f263522aSJoseph Koshy pmc_write_op.pm_pmcid = pmc; 2401f263522aSJoseph Koshy pmc_write_op.pm_flags = PMC_F_NEWVALUE; 2402f263522aSJoseph Koshy pmc_write_op.pm_value = value; 2403aa342b1fSJoseph Koshy return (PMC_CALL(PMCRW, &pmc_write_op)); 2404f263522aSJoseph Koshy } 2405f263522aSJoseph Koshy 2406f263522aSJoseph Koshy int 2407f263522aSJoseph Koshy pmc_writelog(uint32_t userdata) 2408f263522aSJoseph Koshy { 2409f263522aSJoseph Koshy struct pmc_op_writelog wl; 2410f263522aSJoseph Koshy 2411f263522aSJoseph Koshy wl.pm_userdata = userdata; 2412aa342b1fSJoseph Koshy return (PMC_CALL(WRITELOG, &wl)); 2413f263522aSJoseph Koshy } 2414