libpmc.c revision 233335
1145256Sjkoshy/*- 2177107Sjkoshy * Copyright (c) 2003-2008 Joseph Koshy 3145256Sjkoshy * All rights reserved. 4145256Sjkoshy * 5145256Sjkoshy * Redistribution and use in source and binary forms, with or without 6145256Sjkoshy * modification, are permitted provided that the following conditions 7145256Sjkoshy * are met: 8145256Sjkoshy * 1. Redistributions of source code must retain the above copyright 9145256Sjkoshy * notice, this list of conditions and the following disclaimer. 10145256Sjkoshy * 2. Redistributions in binary form must reproduce the above copyright 11145256Sjkoshy * notice, this list of conditions and the following disclaimer in the 12145256Sjkoshy * documentation and/or other materials provided with the distribution. 13145256Sjkoshy * 14145256Sjkoshy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15145256Sjkoshy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16145256Sjkoshy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17145256Sjkoshy * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18145256Sjkoshy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19145256Sjkoshy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20145256Sjkoshy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21145256Sjkoshy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22145256Sjkoshy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23145256Sjkoshy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24145256Sjkoshy * SUCH DAMAGE. 25145256Sjkoshy */ 26145256Sjkoshy 27145256Sjkoshy#include <sys/cdefs.h> 28145256Sjkoshy__FBSDID("$FreeBSD: head/lib/libpmc/libpmc.c 233335 2012-03-23 00:10:21Z gonzo $"); 29145256Sjkoshy 30145256Sjkoshy#include <sys/types.h> 31145256Sjkoshy#include <sys/module.h> 32145256Sjkoshy#include <sys/pmc.h> 33145256Sjkoshy#include <sys/syscall.h> 34145256Sjkoshy 35145256Sjkoshy#include <ctype.h> 36145256Sjkoshy#include <errno.h> 37145256Sjkoshy#include <fcntl.h> 38145256Sjkoshy#include <pmc.h> 39145256Sjkoshy#include <stdio.h> 40145256Sjkoshy#include <stdlib.h> 41145256Sjkoshy#include <string.h> 42145256Sjkoshy#include <strings.h> 43145256Sjkoshy#include <unistd.h> 44145256Sjkoshy 45185363Sjkoshy#include "libpmcinternal.h" 46185363Sjkoshy 47145256Sjkoshy/* Function prototypes */ 48145340Smarcel#if defined(__i386__) 49145256Sjkoshystatic int k7_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 50145256Sjkoshy struct pmc_op_pmcallocate *_pmc_config); 51147191Sjkoshy#endif 52147759Sjkoshy#if defined(__amd64__) || defined(__i386__) 53185363Sjkoshystatic int iaf_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 54185363Sjkoshy struct pmc_op_pmcallocate *_pmc_config); 55185363Sjkoshystatic int iap_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 56185363Sjkoshy struct pmc_op_pmcallocate *_pmc_config); 57206089Sfabientstatic int ucf_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 58206089Sfabient struct pmc_op_pmcallocate *_pmc_config); 59206089Sfabientstatic int ucp_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 60206089Sfabient struct pmc_op_pmcallocate *_pmc_config); 61147191Sjkoshystatic int k8_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 62145256Sjkoshy struct pmc_op_pmcallocate *_pmc_config); 63147759Sjkoshystatic int p4_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 64147759Sjkoshy struct pmc_op_pmcallocate *_pmc_config); 65147191Sjkoshy#endif 66147191Sjkoshy#if defined(__i386__) 67145256Sjkoshystatic int p5_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 68145256Sjkoshy struct pmc_op_pmcallocate *_pmc_config); 69147191Sjkoshystatic int p6_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 70145256Sjkoshy struct pmc_op_pmcallocate *_pmc_config); 71145256Sjkoshy#endif 72183725Sjkoshy#if defined(__amd64__) || defined(__i386__) 73183725Sjkoshystatic int tsc_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 74183725Sjkoshy struct pmc_op_pmcallocate *_pmc_config); 75183725Sjkoshy#endif 76200928Srpaulo#if defined(__XSCALE__) 77200928Srpaulostatic int xscale_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 78200928Srpaulo struct pmc_op_pmcallocate *_pmc_config); 79200928Srpaulo#endif 80145256Sjkoshy 81204635Sgnn#if defined(__mips__) 82233320Sgonzostatic int mips_allocate_pmc(enum pmc_event _pe, char* ctrspec, 83204635Sgnn struct pmc_op_pmcallocate *_pmc_config); 84204635Sgnn#endif /* __mips__ */ 85204635Sgnn 86228869Sjhibbits#if defined(__powerpc__) 87228869Sjhibbitsstatic int ppc7450_allocate_pmc(enum pmc_event _pe, char* ctrspec, 88228869Sjhibbits struct pmc_op_pmcallocate *_pmc_config); 89228869Sjhibbits#endif /* __powerpc__ */ 90204635Sgnn 91145256Sjkoshy#define PMC_CALL(cmd, params) \ 92145256Sjkoshy syscall(pmc_syscall, PMC_OP_##cmd, (params)) 93145256Sjkoshy 94145256Sjkoshy/* 95145256Sjkoshy * Event aliases provide a way for the user to ask for generic events 96145256Sjkoshy * like "cache-misses", or "instructions-retired". These aliases are 97145256Sjkoshy * mapped to the appropriate canonical event descriptions using a 98145256Sjkoshy * lookup table. 99145256Sjkoshy */ 100145256Sjkoshystruct pmc_event_alias { 101145256Sjkoshy const char *pm_alias; 102145256Sjkoshy const char *pm_spec; 103145256Sjkoshy}; 104145256Sjkoshy 105145256Sjkoshystatic const struct pmc_event_alias *pmc_mdep_event_aliases; 106145256Sjkoshy 107145256Sjkoshy/* 108183725Sjkoshy * The pmc_event_descr structure maps symbolic names known to the user 109145256Sjkoshy * to integer codes used by the PMC KLD. 110145256Sjkoshy */ 111145256Sjkoshystruct pmc_event_descr { 112145256Sjkoshy const char *pm_ev_name; 113145256Sjkoshy enum pmc_event pm_ev_code; 114145256Sjkoshy}; 115145256Sjkoshy 116183725Sjkoshy/* 117183725Sjkoshy * The pmc_class_descr structure maps class name prefixes for 118183725Sjkoshy * event names to event tables and other PMC class data. 119183725Sjkoshy */ 120183725Sjkoshystruct pmc_class_descr { 121183725Sjkoshy const char *pm_evc_name; 122183725Sjkoshy size_t pm_evc_name_size; 123183725Sjkoshy enum pmc_class pm_evc_class; 124183725Sjkoshy const struct pmc_event_descr *pm_evc_event_table; 125183725Sjkoshy size_t pm_evc_event_table_size; 126183725Sjkoshy int (*pm_evc_allocate_pmc)(enum pmc_event _pe, 127183725Sjkoshy char *_ctrspec, struct pmc_op_pmcallocate *_pa); 128183725Sjkoshy}; 129183725Sjkoshy 130183725Sjkoshy#define PMC_TABLE_SIZE(N) (sizeof(N)/sizeof(N[0])) 131183725Sjkoshy#define PMC_EVENT_TABLE_SIZE(N) PMC_TABLE_SIZE(N##_event_table) 132183725Sjkoshy 133183725Sjkoshy#undef __PMC_EV 134183725Sjkoshy#define __PMC_EV(C,N) { #N, PMC_EV_ ## C ## _ ## N }, 135183725Sjkoshy 136183725Sjkoshy/* 137185363Sjkoshy * PMC_CLASSDEP_TABLE(NAME, CLASS) 138183725Sjkoshy * 139185363Sjkoshy * Define a table mapping event names and aliases to HWPMC event IDs. 140183725Sjkoshy */ 141185363Sjkoshy#define PMC_CLASSDEP_TABLE(N, C) \ 142183725Sjkoshy static const struct pmc_event_descr N##_event_table[] = \ 143183725Sjkoshy { \ 144183725Sjkoshy __PMC_EV_##C() \ 145185363Sjkoshy } 146185363Sjkoshy 147185363SjkoshyPMC_CLASSDEP_TABLE(iaf, IAF); 148185363SjkoshyPMC_CLASSDEP_TABLE(k7, K7); 149185363SjkoshyPMC_CLASSDEP_TABLE(k8, K8); 150185363SjkoshyPMC_CLASSDEP_TABLE(p4, P4); 151185363SjkoshyPMC_CLASSDEP_TABLE(p5, P5); 152185363SjkoshyPMC_CLASSDEP_TABLE(p6, P6); 153200928SrpauloPMC_CLASSDEP_TABLE(xscale, XSCALE); 154204635SgnnPMC_CLASSDEP_TABLE(mips24k, MIPS24K); 155233335SgonzoPMC_CLASSDEP_TABLE(octeon, OCTEON); 156206089SfabientPMC_CLASSDEP_TABLE(ucf, UCF); 157228869SjhibbitsPMC_CLASSDEP_TABLE(ppc7450, PPC7450); 158185363Sjkoshy 159185363Sjkoshy#undef __PMC_EV_ALIAS 160185363Sjkoshy#define __PMC_EV_ALIAS(N,CODE) { N, PMC_EV_##CODE }, 161185363Sjkoshy 162185363Sjkoshystatic const struct pmc_event_descr atom_event_table[] = 163185363Sjkoshy{ 164185363Sjkoshy __PMC_EV_ALIAS_ATOM() 165185363Sjkoshy}; 166185363Sjkoshy 167185363Sjkoshystatic const struct pmc_event_descr core_event_table[] = 168185363Sjkoshy{ 169185363Sjkoshy __PMC_EV_ALIAS_CORE() 170185363Sjkoshy}; 171185363Sjkoshy 172185363Sjkoshy 173185363Sjkoshystatic const struct pmc_event_descr core2_event_table[] = 174185363Sjkoshy{ 175185363Sjkoshy __PMC_EV_ALIAS_CORE2() 176185363Sjkoshy}; 177185363Sjkoshy 178187761Sjeffstatic const struct pmc_event_descr corei7_event_table[] = 179187761Sjeff{ 180187761Sjeff __PMC_EV_ALIAS_COREI7() 181187761Sjeff}; 182187761Sjeff 183232366Sdavidestatic const struct pmc_event_descr sandybridge_event_table[] = 184232366Sdavide{ 185232366Sdavide __PMC_EV_ALIAS_SANDYBRIDGE() 186232366Sdavide}; 187232366Sdavide 188206089Sfabientstatic const struct pmc_event_descr westmere_event_table[] = 189206089Sfabient{ 190206089Sfabient __PMC_EV_ALIAS_WESTMERE() 191206089Sfabient}; 192206089Sfabient 193206089Sfabientstatic const struct pmc_event_descr corei7uc_event_table[] = 194206089Sfabient{ 195206089Sfabient __PMC_EV_ALIAS_COREI7UC() 196206089Sfabient}; 197206089Sfabient 198232366Sdavidestatic const struct pmc_event_descr sandybridgeuc_event_table[] = 199232366Sdavide{ 200232366Sdavide __PMC_EV_ALIAS_SANDYBRIDGEUC() 201232366Sdavide}; 202232366Sdavide 203206089Sfabientstatic const struct pmc_event_descr westmereuc_event_table[] = 204206089Sfabient{ 205206089Sfabient __PMC_EV_ALIAS_WESTMEREUC() 206206089Sfabient}; 207206089Sfabient 208185363Sjkoshy/* 209185363Sjkoshy * PMC_MDEP_TABLE(NAME, PRIMARYCLASS, ADDITIONAL_CLASSES...) 210185363Sjkoshy * 211185363Sjkoshy * Map a CPU to the PMC classes it supports. 212185363Sjkoshy */ 213185363Sjkoshy#define PMC_MDEP_TABLE(N,C,...) \ 214183725Sjkoshy static const enum pmc_class N##_pmc_classes[] = { \ 215183725Sjkoshy PMC_CLASS_##C, __VA_ARGS__ \ 216183725Sjkoshy } 217183725Sjkoshy 218185363SjkoshyPMC_MDEP_TABLE(atom, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC); 219185363SjkoshyPMC_MDEP_TABLE(core, IAP, PMC_CLASS_TSC); 220185363SjkoshyPMC_MDEP_TABLE(core2, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC); 221206089SfabientPMC_MDEP_TABLE(corei7, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 222232366SdavidePMC_MDEP_TABLE(sandybridge, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 223206089SfabientPMC_MDEP_TABLE(westmere, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 224183725SjkoshyPMC_MDEP_TABLE(k7, K7, PMC_CLASS_TSC); 225183725SjkoshyPMC_MDEP_TABLE(k8, K8, PMC_CLASS_TSC); 226183725SjkoshyPMC_MDEP_TABLE(p4, P4, PMC_CLASS_TSC); 227183725SjkoshyPMC_MDEP_TABLE(p5, P5, PMC_CLASS_TSC); 228183725SjkoshyPMC_MDEP_TABLE(p6, P6, PMC_CLASS_TSC); 229200928SrpauloPMC_MDEP_TABLE(xscale, XSCALE, PMC_CLASS_XSCALE); 230204635SgnnPMC_MDEP_TABLE(mips24k, MIPS24K, PMC_CLASS_MIPS24K); 231233335SgonzoPMC_MDEP_TABLE(octeon, OCTEON, PMC_CLASS_OCTEON); 232228869SjhibbitsPMC_MDEP_TABLE(ppc7450, PPC7450, PMC_CLASS_PPC7450); 233183725Sjkoshy 234183725Sjkoshystatic const struct pmc_event_descr tsc_event_table[] = 235145256Sjkoshy{ 236183725Sjkoshy __PMC_EV_TSC() 237145256Sjkoshy}; 238145256Sjkoshy 239183725Sjkoshy#undef PMC_CLASS_TABLE_DESC 240185363Sjkoshy#define PMC_CLASS_TABLE_DESC(NAME, CLASS, EVENTS, ALLOCATOR) \ 241185363Sjkoshystatic const struct pmc_class_descr NAME##_class_table_descr = \ 242185363Sjkoshy { \ 243185363Sjkoshy .pm_evc_name = #CLASS "-", \ 244185363Sjkoshy .pm_evc_name_size = sizeof(#CLASS "-") - 1, \ 245185363Sjkoshy .pm_evc_class = PMC_CLASS_##CLASS , \ 246185363Sjkoshy .pm_evc_event_table = EVENTS##_event_table , \ 247183725Sjkoshy .pm_evc_event_table_size = \ 248185363Sjkoshy PMC_EVENT_TABLE_SIZE(EVENTS), \ 249185363Sjkoshy .pm_evc_allocate_pmc = ALLOCATOR##_allocate_pmc \ 250183725Sjkoshy } 251183725Sjkoshy 252185363Sjkoshy#if defined(__i386__) || defined(__amd64__) 253185363SjkoshyPMC_CLASS_TABLE_DESC(iaf, IAF, iaf, iaf); 254185363SjkoshyPMC_CLASS_TABLE_DESC(atom, IAP, atom, iap); 255185363SjkoshyPMC_CLASS_TABLE_DESC(core, IAP, core, iap); 256185363SjkoshyPMC_CLASS_TABLE_DESC(core2, IAP, core2, iap); 257187761SjeffPMC_CLASS_TABLE_DESC(corei7, IAP, corei7, iap); 258232366SdavidePMC_CLASS_TABLE_DESC(sandybridge, IAP, sandybridge, iap); 259206089SfabientPMC_CLASS_TABLE_DESC(westmere, IAP, westmere, iap); 260206089SfabientPMC_CLASS_TABLE_DESC(ucf, UCF, ucf, ucf); 261206089SfabientPMC_CLASS_TABLE_DESC(corei7uc, UCP, corei7uc, ucp); 262232366SdavidePMC_CLASS_TABLE_DESC(sandybridgeuc, UCP, sandybridgeuc, ucp); 263206089SfabientPMC_CLASS_TABLE_DESC(westmereuc, UCP, westmereuc, ucp); 264185363Sjkoshy#endif 265183725Sjkoshy#if defined(__i386__) 266185363SjkoshyPMC_CLASS_TABLE_DESC(k7, K7, k7, k7); 267183725Sjkoshy#endif 268183725Sjkoshy#if defined(__i386__) || defined(__amd64__) 269185363SjkoshyPMC_CLASS_TABLE_DESC(k8, K8, k8, k8); 270185363SjkoshyPMC_CLASS_TABLE_DESC(p4, P4, p4, p4); 271183725Sjkoshy#endif 272183725Sjkoshy#if defined(__i386__) 273185363SjkoshyPMC_CLASS_TABLE_DESC(p5, P5, p5, p5); 274185363SjkoshyPMC_CLASS_TABLE_DESC(p6, P6, p6, p6); 275183725Sjkoshy#endif 276183725Sjkoshy#if defined(__i386__) || defined(__amd64__) 277185363SjkoshyPMC_CLASS_TABLE_DESC(tsc, TSC, tsc, tsc); 278183725Sjkoshy#endif 279200928Srpaulo#if defined(__XSCALE__) 280200928SrpauloPMC_CLASS_TABLE_DESC(xscale, XSCALE, xscale, xscale); 281200928Srpaulo#endif 282183725Sjkoshy 283204635Sgnn#if defined(__mips__) 284233320SgonzoPMC_CLASS_TABLE_DESC(mips24k, MIPS24K, mips24k, mips); 285233335SgonzoPMC_CLASS_TABLE_DESC(octeon, OCTEON, octeon, mips); 286204635Sgnn#endif /* __mips__ */ 287204635Sgnn 288228869Sjhibbits#if defined(__powerpc__) 289228869SjhibbitsPMC_CLASS_TABLE_DESC(ppc7450, PPC7450, ppc7450, ppc7450); 290228869Sjhibbits#endif 291228869Sjhibbits 292183725Sjkoshy#undef PMC_CLASS_TABLE_DESC 293183725Sjkoshy 294185363Sjkoshystatic const struct pmc_class_descr **pmc_class_table; 295185363Sjkoshy#define PMC_CLASS_TABLE_SIZE cpu_info.pm_nclass 296185363Sjkoshy 297183725Sjkoshystatic const enum pmc_class *pmc_mdep_class_list; 298183725Sjkoshystatic size_t pmc_mdep_class_list_size; 299183725Sjkoshy 300145256Sjkoshy/* 301145256Sjkoshy * Mapping tables, mapping enumeration values to human readable 302145256Sjkoshy * strings. 303145256Sjkoshy */ 304145256Sjkoshy 305145256Sjkoshystatic const char * pmc_capability_names[] = { 306145256Sjkoshy#undef __PMC_CAP 307145256Sjkoshy#define __PMC_CAP(N,V,D) #N , 308145256Sjkoshy __PMC_CAPS() 309145256Sjkoshy}; 310145256Sjkoshy 311145256Sjkoshystatic const char * pmc_class_names[] = { 312145256Sjkoshy#undef __PMC_CLASS 313145256Sjkoshy#define __PMC_CLASS(C) #C , 314145256Sjkoshy __PMC_CLASSES() 315145256Sjkoshy}; 316145256Sjkoshy 317183725Sjkoshystruct pmc_cputype_map { 318228557Sdim enum pmc_cputype pm_cputype; 319183725Sjkoshy const char *pm_name; 320183725Sjkoshy}; 321183725Sjkoshy 322183725Sjkoshystatic const struct pmc_cputype_map pmc_cputype_names[] = { 323145256Sjkoshy#undef __PMC_CPU 324183725Sjkoshy#define __PMC_CPU(S, V, D) { .pm_cputype = PMC_CPU_##S, .pm_name = #S } , 325145256Sjkoshy __PMC_CPUS() 326145256Sjkoshy}; 327145256Sjkoshy 328145256Sjkoshystatic const char * pmc_disposition_names[] = { 329145256Sjkoshy#undef __PMC_DISP 330145256Sjkoshy#define __PMC_DISP(D) #D , 331145256Sjkoshy __PMC_DISPOSITIONS() 332145256Sjkoshy}; 333145256Sjkoshy 334145256Sjkoshystatic const char * pmc_mode_names[] = { 335145256Sjkoshy#undef __PMC_MODE 336145256Sjkoshy#define __PMC_MODE(M,N) #M , 337145256Sjkoshy __PMC_MODES() 338145256Sjkoshy}; 339145256Sjkoshy 340145256Sjkoshystatic const char * pmc_state_names[] = { 341145256Sjkoshy#undef __PMC_STATE 342145256Sjkoshy#define __PMC_STATE(S) #S , 343145256Sjkoshy __PMC_STATES() 344145256Sjkoshy}; 345145256Sjkoshy 346145256Sjkoshystatic int pmc_syscall = -1; /* filled in by pmc_init() */ 347145256Sjkoshy 348147219Sjkoshystatic struct pmc_cpuinfo cpu_info; /* filled in by pmc_init() */ 349145256Sjkoshy 350145256Sjkoshy/* Event masks for events */ 351145256Sjkoshystruct pmc_masks { 352145256Sjkoshy const char *pm_name; 353145256Sjkoshy const uint32_t pm_value; 354145256Sjkoshy}; 355145256Sjkoshy#define PMCMASK(N,V) { .pm_name = #N, .pm_value = (V) } 356206089Sfabient#define NULLMASK { .pm_name = NULL } 357145256Sjkoshy 358147759Sjkoshy#if defined(__amd64__) || defined(__i386__) 359145256Sjkoshystatic int 360145256Sjkoshypmc_parse_mask(const struct pmc_masks *pmask, char *p, uint32_t *evmask) 361145256Sjkoshy{ 362145256Sjkoshy const struct pmc_masks *pm; 363145256Sjkoshy char *q, *r; 364145256Sjkoshy int c; 365145256Sjkoshy 366145256Sjkoshy if (pmask == NULL) /* no mask keywords */ 367174406Sjkoshy return (-1); 368183107Sjkoshy q = strchr(p, '='); /* skip '=' */ 369145256Sjkoshy if (*++q == '\0') /* no more data */ 370174406Sjkoshy return (-1); 371145256Sjkoshy c = 0; /* count of mask keywords seen */ 372145256Sjkoshy while ((r = strsep(&q, "+")) != NULL) { 373183725Sjkoshy for (pm = pmask; pm->pm_name && strcasecmp(r, pm->pm_name); 374183725Sjkoshy pm++) 375145256Sjkoshy ; 376145256Sjkoshy if (pm->pm_name == NULL) /* not found */ 377174406Sjkoshy return (-1); 378145256Sjkoshy *evmask |= pm->pm_value; 379145256Sjkoshy c++; 380145256Sjkoshy } 381174406Sjkoshy return (c); 382145256Sjkoshy} 383145340Smarcel#endif 384145256Sjkoshy 385145256Sjkoshy#define KWMATCH(p,kw) (strcasecmp((p), (kw)) == 0) 386145256Sjkoshy#define KWPREFIXMATCH(p,kw) (strncasecmp((p), (kw), sizeof((kw)) - 1) == 0) 387145256Sjkoshy#define EV_ALIAS(N,S) { .pm_alias = N, .pm_spec = S } 388145256Sjkoshy 389145340Smarcel#if defined(__i386__) 390145256Sjkoshy 391145256Sjkoshy/* 392145256Sjkoshy * AMD K7 (Athlon) CPUs. 393145256Sjkoshy */ 394145256Sjkoshy 395145256Sjkoshystatic struct pmc_event_alias k7_aliases[] = { 396145351Sjkoshy EV_ALIAS("branches", "k7-retired-branches"), 397145351Sjkoshy EV_ALIAS("branch-mispredicts", "k7-retired-branches-mispredicted"), 398145351Sjkoshy EV_ALIAS("cycles", "tsc"), 399183075Sjkoshy EV_ALIAS("dc-misses", "k7-dc-misses"), 400145351Sjkoshy EV_ALIAS("ic-misses", "k7-ic-misses"), 401145351Sjkoshy EV_ALIAS("instructions", "k7-retired-instructions"), 402145351Sjkoshy EV_ALIAS("interrupts", "k7-hardware-interrupts"), 403145351Sjkoshy EV_ALIAS(NULL, NULL) 404145256Sjkoshy}; 405145256Sjkoshy 406145256Sjkoshy#define K7_KW_COUNT "count" 407145256Sjkoshy#define K7_KW_EDGE "edge" 408145256Sjkoshy#define K7_KW_INV "inv" 409145256Sjkoshy#define K7_KW_OS "os" 410145256Sjkoshy#define K7_KW_UNITMASK "unitmask" 411145256Sjkoshy#define K7_KW_USR "usr" 412145256Sjkoshy 413145256Sjkoshystatic int 414145256Sjkoshyk7_allocate_pmc(enum pmc_event pe, char *ctrspec, 415145256Sjkoshy struct pmc_op_pmcallocate *pmc_config) 416145256Sjkoshy{ 417183107Sjkoshy char *e, *p, *q; 418183107Sjkoshy int c, has_unitmask; 419145256Sjkoshy uint32_t count, unitmask; 420145256Sjkoshy 421147191Sjkoshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 422183725Sjkoshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 423145256Sjkoshy 424145256Sjkoshy if (pe == PMC_EV_K7_DC_REFILLS_FROM_L2 || 425145256Sjkoshy pe == PMC_EV_K7_DC_REFILLS_FROM_SYSTEM || 426145256Sjkoshy pe == PMC_EV_K7_DC_WRITEBACKS) { 427145256Sjkoshy has_unitmask = 1; 428147191Sjkoshy unitmask = AMD_PMC_UNITMASK_MOESI; 429145256Sjkoshy } else 430145256Sjkoshy unitmask = has_unitmask = 0; 431145256Sjkoshy 432145256Sjkoshy while ((p = strsep(&ctrspec, ",")) != NULL) { 433145256Sjkoshy if (KWPREFIXMATCH(p, K7_KW_COUNT "=")) { 434145256Sjkoshy q = strchr(p, '='); 435145256Sjkoshy if (*++q == '\0') /* skip '=' */ 436174406Sjkoshy return (-1); 437145256Sjkoshy 438145256Sjkoshy count = strtol(q, &e, 0); 439145256Sjkoshy if (e == q || *e != '\0') 440174406Sjkoshy return (-1); 441145256Sjkoshy 442145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 443147191Sjkoshy pmc_config->pm_md.pm_amd.pm_amd_config |= 444147191Sjkoshy AMD_PMC_TO_COUNTER(count); 445145256Sjkoshy 446145256Sjkoshy } else if (KWMATCH(p, K7_KW_EDGE)) { 447145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_EDGE; 448145256Sjkoshy } else if (KWMATCH(p, K7_KW_INV)) { 449145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_INVERT; 450145256Sjkoshy } else if (KWMATCH(p, K7_KW_OS)) { 451145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 452145256Sjkoshy } else if (KWPREFIXMATCH(p, K7_KW_UNITMASK "=")) { 453145256Sjkoshy if (has_unitmask == 0) 454174406Sjkoshy return (-1); 455145256Sjkoshy unitmask = 0; 456145256Sjkoshy q = strchr(p, '='); 457145256Sjkoshy if (*++q == '\0') /* skip '=' */ 458174406Sjkoshy return (-1); 459145256Sjkoshy 460145256Sjkoshy while ((c = tolower(*q++)) != 0) 461145256Sjkoshy if (c == 'm') 462147191Sjkoshy unitmask |= AMD_PMC_UNITMASK_M; 463145256Sjkoshy else if (c == 'o') 464147191Sjkoshy unitmask |= AMD_PMC_UNITMASK_O; 465145256Sjkoshy else if (c == 'e') 466147191Sjkoshy unitmask |= AMD_PMC_UNITMASK_E; 467145256Sjkoshy else if (c == 's') 468147191Sjkoshy unitmask |= AMD_PMC_UNITMASK_S; 469145256Sjkoshy else if (c == 'i') 470147191Sjkoshy unitmask |= AMD_PMC_UNITMASK_I; 471145256Sjkoshy else if (c == '+') 472145256Sjkoshy continue; 473145256Sjkoshy else 474174406Sjkoshy return (-1); 475145256Sjkoshy 476145256Sjkoshy if (unitmask == 0) 477174406Sjkoshy return (-1); 478145256Sjkoshy 479145256Sjkoshy } else if (KWMATCH(p, K7_KW_USR)) { 480145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_USER; 481145256Sjkoshy } else 482174406Sjkoshy return (-1); 483145256Sjkoshy } 484145256Sjkoshy 485145256Sjkoshy if (has_unitmask) { 486145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 487147191Sjkoshy pmc_config->pm_md.pm_amd.pm_amd_config |= 488147191Sjkoshy AMD_PMC_TO_UNITMASK(unitmask); 489145256Sjkoshy } 490145256Sjkoshy 491174406Sjkoshy return (0); 492145256Sjkoshy 493145256Sjkoshy} 494145256Sjkoshy 495147191Sjkoshy#endif 496147191Sjkoshy 497147759Sjkoshy#if defined(__amd64__) || defined(__i386__) 498147191Sjkoshy 499145256Sjkoshy/* 500185363Sjkoshy * Intel Core (Family 6, Model E) PMCs. 501185363Sjkoshy */ 502185363Sjkoshy 503185363Sjkoshystatic struct pmc_event_alias core_aliases[] = { 504185363Sjkoshy EV_ALIAS("branches", "iap-br-instr-ret"), 505185363Sjkoshy EV_ALIAS("branch-mispredicts", "iap-br-mispred-ret"), 506185363Sjkoshy EV_ALIAS("cycles", "tsc-tsc"), 507185363Sjkoshy EV_ALIAS("ic-misses", "iap-icache-misses"), 508185363Sjkoshy EV_ALIAS("instructions", "iap-instr-ret"), 509185363Sjkoshy EV_ALIAS("interrupts", "iap-core-hw-int-rx"), 510185363Sjkoshy EV_ALIAS("unhalted-cycles", "iap-unhalted-core-cycles"), 511185363Sjkoshy EV_ALIAS(NULL, NULL) 512185363Sjkoshy}; 513185363Sjkoshy 514185363Sjkoshy/* 515185363Sjkoshy * Intel Core2 (Family 6, Model F), Core2Extreme (Family 6, Model 17H) 516185363Sjkoshy * and Atom (Family 6, model 1CH) PMCs. 517198433Sjkoshy * 518198433Sjkoshy * We map aliases to events on the fixed-function counters if these 519198433Sjkoshy * are present. Note that not all CPUs in this family contain fixed-function 520198433Sjkoshy * counters. 521185363Sjkoshy */ 522185363Sjkoshy 523185363Sjkoshystatic struct pmc_event_alias core2_aliases[] = { 524185363Sjkoshy EV_ALIAS("branches", "iap-br-inst-retired.any"), 525185363Sjkoshy EV_ALIAS("branch-mispredicts", "iap-br-inst-retired.mispred"), 526185363Sjkoshy EV_ALIAS("cycles", "tsc-tsc"), 527185363Sjkoshy EV_ALIAS("ic-misses", "iap-l1i-misses"), 528185363Sjkoshy EV_ALIAS("instructions", "iaf-instr-retired.any"), 529185363Sjkoshy EV_ALIAS("interrupts", "iap-hw-int-rcv"), 530185363Sjkoshy EV_ALIAS("unhalted-cycles", "iaf-cpu-clk-unhalted.core"), 531185363Sjkoshy EV_ALIAS(NULL, NULL) 532185363Sjkoshy}; 533185363Sjkoshy 534198433Sjkoshystatic struct pmc_event_alias core2_aliases_without_iaf[] = { 535198433Sjkoshy EV_ALIAS("branches", "iap-br-inst-retired.any"), 536198433Sjkoshy EV_ALIAS("branch-mispredicts", "iap-br-inst-retired.mispred"), 537198433Sjkoshy EV_ALIAS("cycles", "tsc-tsc"), 538198433Sjkoshy EV_ALIAS("ic-misses", "iap-l1i-misses"), 539198433Sjkoshy EV_ALIAS("instructions", "iap-inst-retired.any_p"), 540198433Sjkoshy EV_ALIAS("interrupts", "iap-hw-int-rcv"), 541198433Sjkoshy EV_ALIAS("unhalted-cycles", "iap-cpu-clk-unhalted.core_p"), 542198433Sjkoshy EV_ALIAS(NULL, NULL) 543198433Sjkoshy}; 544198433Sjkoshy 545198433Sjkoshy#define atom_aliases core2_aliases 546198433Sjkoshy#define atom_aliases_without_iaf core2_aliases_without_iaf 547198433Sjkoshy#define corei7_aliases core2_aliases 548198433Sjkoshy#define corei7_aliases_without_iaf core2_aliases_without_iaf 549232366Sdavide#define sandybridge_aliases core2_aliases 550232366Sdavide#define sandybridge_aliases_without_iaf core2_aliases_without_iaf 551206089Sfabient#define westmere_aliases core2_aliases 552206089Sfabient#define westmere_aliases_without_iaf core2_aliases_without_iaf 553198433Sjkoshy 554185363Sjkoshy#define IAF_KW_OS "os" 555185363Sjkoshy#define IAF_KW_USR "usr" 556185363Sjkoshy#define IAF_KW_ANYTHREAD "anythread" 557185363Sjkoshy 558185363Sjkoshy/* 559185363Sjkoshy * Parse an event specifier for Intel fixed function counters. 560185363Sjkoshy */ 561185363Sjkoshystatic int 562185363Sjkoshyiaf_allocate_pmc(enum pmc_event pe, char *ctrspec, 563185363Sjkoshy struct pmc_op_pmcallocate *pmc_config) 564185363Sjkoshy{ 565185363Sjkoshy char *p; 566185363Sjkoshy 567185363Sjkoshy (void) pe; 568185363Sjkoshy 569185363Sjkoshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 570185363Sjkoshy pmc_config->pm_md.pm_iaf.pm_iaf_flags = 0; 571185363Sjkoshy 572185363Sjkoshy while ((p = strsep(&ctrspec, ",")) != NULL) { 573185363Sjkoshy if (KWMATCH(p, IAF_KW_OS)) 574185363Sjkoshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 575185363Sjkoshy else if (KWMATCH(p, IAF_KW_USR)) 576185363Sjkoshy pmc_config->pm_caps |= PMC_CAP_USER; 577185363Sjkoshy else if (KWMATCH(p, IAF_KW_ANYTHREAD)) 578185363Sjkoshy pmc_config->pm_md.pm_iaf.pm_iaf_flags |= IAF_ANY; 579185363Sjkoshy else 580185363Sjkoshy return (-1); 581185363Sjkoshy } 582185363Sjkoshy 583185363Sjkoshy return (0); 584185363Sjkoshy} 585185363Sjkoshy 586185363Sjkoshy/* 587185363Sjkoshy * Core/Core2 support. 588185363Sjkoshy */ 589185363Sjkoshy 590185363Sjkoshy#define IAP_KW_AGENT "agent" 591185363Sjkoshy#define IAP_KW_ANYTHREAD "anythread" 592185363Sjkoshy#define IAP_KW_CACHESTATE "cachestate" 593185363Sjkoshy#define IAP_KW_CMASK "cmask" 594185363Sjkoshy#define IAP_KW_CORE "core" 595185363Sjkoshy#define IAP_KW_EDGE "edge" 596185363Sjkoshy#define IAP_KW_INV "inv" 597185363Sjkoshy#define IAP_KW_OS "os" 598185363Sjkoshy#define IAP_KW_PREFETCH "prefetch" 599185363Sjkoshy#define IAP_KW_SNOOPRESPONSE "snoopresponse" 600185363Sjkoshy#define IAP_KW_SNOOPTYPE "snooptype" 601185363Sjkoshy#define IAP_KW_TRANSITION "trans" 602185363Sjkoshy#define IAP_KW_USR "usr" 603206089Sfabient#define IAP_KW_RSP "rsp" 604185363Sjkoshy 605185363Sjkoshystatic struct pmc_masks iap_core_mask[] = { 606185363Sjkoshy PMCMASK(all, (0x3 << 14)), 607185363Sjkoshy PMCMASK(this, (0x1 << 14)), 608185363Sjkoshy NULLMASK 609185363Sjkoshy}; 610185363Sjkoshy 611185363Sjkoshystatic struct pmc_masks iap_agent_mask[] = { 612185363Sjkoshy PMCMASK(this, 0), 613185363Sjkoshy PMCMASK(any, (0x1 << 13)), 614185363Sjkoshy NULLMASK 615185363Sjkoshy}; 616185363Sjkoshy 617185363Sjkoshystatic struct pmc_masks iap_prefetch_mask[] = { 618185363Sjkoshy PMCMASK(both, (0x3 << 12)), 619185363Sjkoshy PMCMASK(only, (0x1 << 12)), 620185363Sjkoshy PMCMASK(exclude, 0), 621185363Sjkoshy NULLMASK 622185363Sjkoshy}; 623185363Sjkoshy 624185363Sjkoshystatic struct pmc_masks iap_cachestate_mask[] = { 625185363Sjkoshy PMCMASK(i, (1 << 8)), 626185363Sjkoshy PMCMASK(s, (1 << 9)), 627185363Sjkoshy PMCMASK(e, (1 << 10)), 628185363Sjkoshy PMCMASK(m, (1 << 11)), 629185363Sjkoshy NULLMASK 630185363Sjkoshy}; 631185363Sjkoshy 632185363Sjkoshystatic struct pmc_masks iap_snoopresponse_mask[] = { 633185363Sjkoshy PMCMASK(clean, (1 << 8)), 634185363Sjkoshy PMCMASK(hit, (1 << 9)), 635185363Sjkoshy PMCMASK(hitm, (1 << 11)), 636185363Sjkoshy NULLMASK 637185363Sjkoshy}; 638185363Sjkoshy 639185363Sjkoshystatic struct pmc_masks iap_snooptype_mask[] = { 640185363Sjkoshy PMCMASK(cmp2s, (1 << 8)), 641185363Sjkoshy PMCMASK(cmp2i, (1 << 9)), 642185363Sjkoshy NULLMASK 643185363Sjkoshy}; 644185363Sjkoshy 645185363Sjkoshystatic struct pmc_masks iap_transition_mask[] = { 646185363Sjkoshy PMCMASK(any, 0x00), 647185363Sjkoshy PMCMASK(frequency, 0x10), 648185363Sjkoshy NULLMASK 649185363Sjkoshy}; 650185363Sjkoshy 651206089Sfabientstatic struct pmc_masks iap_rsp_mask[] = { 652206089Sfabient PMCMASK(DMND_DATA_RD, (1 << 0)), 653206089Sfabient PMCMASK(DMND_RFO, (1 << 1)), 654206089Sfabient PMCMASK(DMND_IFETCH, (1 << 2)), 655206089Sfabient PMCMASK(WB, (1 << 3)), 656206089Sfabient PMCMASK(PF_DATA_RD, (1 << 4)), 657206089Sfabient PMCMASK(PF_RFO, (1 << 5)), 658206089Sfabient PMCMASK(PF_IFETCH, (1 << 6)), 659206089Sfabient PMCMASK(OTHER, (1 << 7)), 660206089Sfabient PMCMASK(UNCORE_HIT, (1 << 8)), 661206089Sfabient PMCMASK(OTHER_CORE_HIT_SNP, (1 << 9)), 662206089Sfabient PMCMASK(OTHER_CORE_HITM, (1 << 10)), 663206089Sfabient PMCMASK(REMOTE_CACHE_FWD, (1 << 12)), 664206089Sfabient PMCMASK(REMOTE_DRAM, (1 << 13)), 665206089Sfabient PMCMASK(LOCAL_DRAM, (1 << 14)), 666206089Sfabient PMCMASK(NON_DRAM, (1 << 15)), 667206089Sfabient NULLMASK 668206089Sfabient}; 669206089Sfabient 670185363Sjkoshystatic int 671185363Sjkoshyiap_allocate_pmc(enum pmc_event pe, char *ctrspec, 672185363Sjkoshy struct pmc_op_pmcallocate *pmc_config) 673185363Sjkoshy{ 674185363Sjkoshy char *e, *p, *q; 675206089Sfabient uint32_t cachestate, evmask, rsp; 676185363Sjkoshy int count, n; 677185363Sjkoshy 678185363Sjkoshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE | 679185363Sjkoshy PMC_CAP_QUALIFIER); 680185363Sjkoshy pmc_config->pm_md.pm_iap.pm_iap_config = 0; 681185363Sjkoshy 682206089Sfabient cachestate = evmask = rsp = 0; 683185363Sjkoshy 684185363Sjkoshy /* Parse additional modifiers if present */ 685185363Sjkoshy while ((p = strsep(&ctrspec, ",")) != NULL) { 686185363Sjkoshy 687185363Sjkoshy n = 0; 688185363Sjkoshy if (KWPREFIXMATCH(p, IAP_KW_CMASK "=")) { 689185363Sjkoshy q = strchr(p, '='); 690185363Sjkoshy if (*++q == '\0') /* skip '=' */ 691185363Sjkoshy return (-1); 692185363Sjkoshy count = strtol(q, &e, 0); 693185363Sjkoshy if (e == q || *e != '\0') 694185363Sjkoshy return (-1); 695185363Sjkoshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 696185363Sjkoshy pmc_config->pm_md.pm_iap.pm_iap_config |= 697185363Sjkoshy IAP_CMASK(count); 698185363Sjkoshy } else if (KWMATCH(p, IAP_KW_EDGE)) { 699185363Sjkoshy pmc_config->pm_caps |= PMC_CAP_EDGE; 700185363Sjkoshy } else if (KWMATCH(p, IAP_KW_INV)) { 701185363Sjkoshy pmc_config->pm_caps |= PMC_CAP_INVERT; 702185363Sjkoshy } else if (KWMATCH(p, IAP_KW_OS)) { 703185363Sjkoshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 704185363Sjkoshy } else if (KWMATCH(p, IAP_KW_USR)) { 705185363Sjkoshy pmc_config->pm_caps |= PMC_CAP_USER; 706185363Sjkoshy } else if (KWMATCH(p, IAP_KW_ANYTHREAD)) { 707185363Sjkoshy pmc_config->pm_md.pm_iap.pm_iap_config |= IAP_ANY; 708193809Sjkoshy } else if (KWPREFIXMATCH(p, IAP_KW_CORE "=")) { 709185363Sjkoshy n = pmc_parse_mask(iap_core_mask, p, &evmask); 710185363Sjkoshy if (n != 1) 711185363Sjkoshy return (-1); 712193809Sjkoshy } else if (KWPREFIXMATCH(p, IAP_KW_AGENT "=")) { 713185363Sjkoshy n = pmc_parse_mask(iap_agent_mask, p, &evmask); 714185363Sjkoshy if (n != 1) 715185363Sjkoshy return (-1); 716193809Sjkoshy } else if (KWPREFIXMATCH(p, IAP_KW_PREFETCH "=")) { 717185363Sjkoshy n = pmc_parse_mask(iap_prefetch_mask, p, &evmask); 718185363Sjkoshy if (n != 1) 719185363Sjkoshy return (-1); 720193809Sjkoshy } else if (KWPREFIXMATCH(p, IAP_KW_CACHESTATE "=")) { 721185363Sjkoshy n = pmc_parse_mask(iap_cachestate_mask, p, &cachestate); 722185363Sjkoshy } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_CORE && 723193809Sjkoshy KWPREFIXMATCH(p, IAP_KW_TRANSITION "=")) { 724185363Sjkoshy n = pmc_parse_mask(iap_transition_mask, p, &evmask); 725185363Sjkoshy if (n != 1) 726185363Sjkoshy return (-1); 727185363Sjkoshy } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM || 728185585Sjkoshy cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2 || 729206089Sfabient cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2EXTREME) { 730193809Sjkoshy if (KWPREFIXMATCH(p, IAP_KW_SNOOPRESPONSE "=")) { 731185363Sjkoshy n = pmc_parse_mask(iap_snoopresponse_mask, p, 732185363Sjkoshy &evmask); 733193809Sjkoshy } else if (KWPREFIXMATCH(p, IAP_KW_SNOOPTYPE "=")) { 734185363Sjkoshy n = pmc_parse_mask(iap_snooptype_mask, p, 735185363Sjkoshy &evmask); 736185363Sjkoshy } else 737185363Sjkoshy return (-1); 738206089Sfabient } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_COREI7 || 739206089Sfabient cpu_info.pm_cputype == PMC_CPU_INTEL_WESTMERE) { 740206089Sfabient if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 741206089Sfabient n = pmc_parse_mask(iap_rsp_mask, p, &rsp); 742206089Sfabient } else 743206089Sfabient return (-1); 744185363Sjkoshy } else 745185363Sjkoshy return (-1); 746185363Sjkoshy 747185363Sjkoshy if (n < 0) /* Parsing failed. */ 748185363Sjkoshy return (-1); 749185363Sjkoshy } 750185363Sjkoshy 751185363Sjkoshy pmc_config->pm_md.pm_iap.pm_iap_config |= evmask; 752185363Sjkoshy 753185363Sjkoshy /* 754185363Sjkoshy * If the event requires a 'cachestate' qualifier but was not 755185363Sjkoshy * specified by the user, use a sensible default. 756185363Sjkoshy */ 757185363Sjkoshy switch (pe) { 758185363Sjkoshy case PMC_EV_IAP_EVENT_28H: /* Core, Core2, Atom */ 759185363Sjkoshy case PMC_EV_IAP_EVENT_29H: /* Core, Core2, Atom */ 760185363Sjkoshy case PMC_EV_IAP_EVENT_2AH: /* Core, Core2, Atom */ 761185363Sjkoshy case PMC_EV_IAP_EVENT_2BH: /* Atom, Core2 */ 762185363Sjkoshy case PMC_EV_IAP_EVENT_2EH: /* Core, Core2, Atom */ 763185363Sjkoshy case PMC_EV_IAP_EVENT_30H: /* Core, Core2, Atom */ 764185363Sjkoshy case PMC_EV_IAP_EVENT_32H: /* Core */ 765185363Sjkoshy case PMC_EV_IAP_EVENT_40H: /* Core */ 766185363Sjkoshy case PMC_EV_IAP_EVENT_41H: /* Core */ 767185363Sjkoshy case PMC_EV_IAP_EVENT_42H: /* Core, Core2, Atom */ 768185363Sjkoshy if (cachestate == 0) 769185363Sjkoshy cachestate = (0xF << 8); 770207482Srstone break; 771207482Srstone case PMC_EV_IAP_EVENT_77H: /* Atom */ 772207482Srstone /* IAP_EVENT_77H only accepts a cachestate qualifier on the 773207482Srstone * Atom processor 774207482Srstone */ 775207482Srstone if(cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM && cachestate == 0) 776207482Srstone cachestate = (0xF << 8); 777207482Srstone break; 778185363Sjkoshy default: 779185363Sjkoshy break; 780185363Sjkoshy } 781185363Sjkoshy 782185363Sjkoshy pmc_config->pm_md.pm_iap.pm_iap_config |= cachestate; 783206089Sfabient pmc_config->pm_md.pm_iap.pm_iap_rsp = rsp; 784185363Sjkoshy 785185363Sjkoshy return (0); 786185363Sjkoshy} 787185363Sjkoshy 788185363Sjkoshy/* 789206089Sfabient * Intel Uncore. 790206089Sfabient */ 791206089Sfabient 792206089Sfabientstatic int 793206089Sfabientucf_allocate_pmc(enum pmc_event pe, char *ctrspec, 794206089Sfabient struct pmc_op_pmcallocate *pmc_config) 795206089Sfabient{ 796206089Sfabient (void) pe; 797206089Sfabient (void) ctrspec; 798206089Sfabient 799206089Sfabient pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 800206089Sfabient pmc_config->pm_md.pm_ucf.pm_ucf_flags = 0; 801206089Sfabient 802206089Sfabient return (0); 803206089Sfabient} 804206089Sfabient 805206089Sfabient#define UCP_KW_CMASK "cmask" 806206089Sfabient#define UCP_KW_EDGE "edge" 807206089Sfabient#define UCP_KW_INV "inv" 808206089Sfabient 809206089Sfabientstatic int 810206089Sfabientucp_allocate_pmc(enum pmc_event pe, char *ctrspec, 811206089Sfabient struct pmc_op_pmcallocate *pmc_config) 812206089Sfabient{ 813206089Sfabient char *e, *p, *q; 814206089Sfabient int count, n; 815206089Sfabient 816206089Sfabient (void) pe; 817206089Sfabient 818206089Sfabient pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE | 819206089Sfabient PMC_CAP_QUALIFIER); 820206089Sfabient pmc_config->pm_md.pm_ucp.pm_ucp_config = 0; 821206089Sfabient 822206089Sfabient /* Parse additional modifiers if present */ 823206089Sfabient while ((p = strsep(&ctrspec, ",")) != NULL) { 824206089Sfabient 825206089Sfabient n = 0; 826206089Sfabient if (KWPREFIXMATCH(p, UCP_KW_CMASK "=")) { 827206089Sfabient q = strchr(p, '='); 828206089Sfabient if (*++q == '\0') /* skip '=' */ 829206089Sfabient return (-1); 830206089Sfabient count = strtol(q, &e, 0); 831206089Sfabient if (e == q || *e != '\0') 832206089Sfabient return (-1); 833206089Sfabient pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 834206089Sfabient pmc_config->pm_md.pm_ucp.pm_ucp_config |= 835206089Sfabient UCP_CMASK(count); 836206089Sfabient } else if (KWMATCH(p, UCP_KW_EDGE)) { 837206089Sfabient pmc_config->pm_caps |= PMC_CAP_EDGE; 838206089Sfabient } else if (KWMATCH(p, UCP_KW_INV)) { 839206089Sfabient pmc_config->pm_caps |= PMC_CAP_INVERT; 840206089Sfabient } else 841206089Sfabient return (-1); 842206089Sfabient 843206089Sfabient if (n < 0) /* Parsing failed. */ 844206089Sfabient return (-1); 845206089Sfabient } 846206089Sfabient 847206089Sfabient return (0); 848206089Sfabient} 849206089Sfabient 850206089Sfabient/* 851147191Sjkoshy * AMD K8 PMCs. 852147191Sjkoshy * 853147191Sjkoshy * These are very similar to AMD K7 PMCs, but support more kinds of 854147191Sjkoshy * events. 855147191Sjkoshy */ 856147191Sjkoshy 857147191Sjkoshystatic struct pmc_event_alias k8_aliases[] = { 858147191Sjkoshy EV_ALIAS("branches", "k8-fr-retired-taken-branches"), 859147191Sjkoshy EV_ALIAS("branch-mispredicts", 860147191Sjkoshy "k8-fr-retired-taken-branches-mispredicted"), 861147191Sjkoshy EV_ALIAS("cycles", "tsc"), 862147191Sjkoshy EV_ALIAS("dc-misses", "k8-dc-miss"), 863147191Sjkoshy EV_ALIAS("ic-misses", "k8-ic-miss"), 864183107Sjkoshy EV_ALIAS("instructions", "k8-fr-retired-x86-instructions"), 865147191Sjkoshy EV_ALIAS("interrupts", "k8-fr-taken-hardware-interrupts"), 866155998Sjkoshy EV_ALIAS("unhalted-cycles", "k8-bu-cpu-clk-unhalted"), 867147191Sjkoshy EV_ALIAS(NULL, NULL) 868147191Sjkoshy}; 869147191Sjkoshy 870147191Sjkoshy#define __K8MASK(N,V) PMCMASK(N,(1 << (V))) 871147191Sjkoshy 872147191Sjkoshy/* 873147191Sjkoshy * Parsing tables 874147191Sjkoshy */ 875147191Sjkoshy 876147191Sjkoshy/* fp dispatched fpu ops */ 877147191Sjkoshystatic const struct pmc_masks k8_mask_fdfo[] = { 878147191Sjkoshy __K8MASK(add-pipe-excluding-junk-ops, 0), 879147191Sjkoshy __K8MASK(multiply-pipe-excluding-junk-ops, 1), 880147191Sjkoshy __K8MASK(store-pipe-excluding-junk-ops, 2), 881147191Sjkoshy __K8MASK(add-pipe-junk-ops, 3), 882147191Sjkoshy __K8MASK(multiply-pipe-junk-ops, 4), 883147191Sjkoshy __K8MASK(store-pipe-junk-ops, 5), 884147191Sjkoshy NULLMASK 885147191Sjkoshy}; 886147191Sjkoshy 887147191Sjkoshy/* ls segment register loads */ 888147191Sjkoshystatic const struct pmc_masks k8_mask_lsrl[] = { 889147191Sjkoshy __K8MASK(es, 0), 890147191Sjkoshy __K8MASK(cs, 1), 891147191Sjkoshy __K8MASK(ss, 2), 892147191Sjkoshy __K8MASK(ds, 3), 893147191Sjkoshy __K8MASK(fs, 4), 894147191Sjkoshy __K8MASK(gs, 5), 895147191Sjkoshy __K8MASK(hs, 6), 896147191Sjkoshy NULLMASK 897147191Sjkoshy}; 898147191Sjkoshy 899147191Sjkoshy/* ls locked operation */ 900147191Sjkoshystatic const struct pmc_masks k8_mask_llo[] = { 901147191Sjkoshy __K8MASK(locked-instructions, 0), 902147191Sjkoshy __K8MASK(cycles-in-request, 1), 903147191Sjkoshy __K8MASK(cycles-to-complete, 2), 904147191Sjkoshy NULLMASK 905147191Sjkoshy}; 906147191Sjkoshy 907147191Sjkoshy/* dc refill from {l2,system} and dc copyback */ 908147191Sjkoshystatic const struct pmc_masks k8_mask_dc[] = { 909147191Sjkoshy __K8MASK(invalid, 0), 910147191Sjkoshy __K8MASK(shared, 1), 911147191Sjkoshy __K8MASK(exclusive, 2), 912147191Sjkoshy __K8MASK(owner, 3), 913147191Sjkoshy __K8MASK(modified, 4), 914147191Sjkoshy NULLMASK 915147191Sjkoshy}; 916147191Sjkoshy 917147191Sjkoshy/* dc one bit ecc error */ 918147191Sjkoshystatic const struct pmc_masks k8_mask_dobee[] = { 919147191Sjkoshy __K8MASK(scrubber, 0), 920147191Sjkoshy __K8MASK(piggyback, 1), 921147191Sjkoshy NULLMASK 922147191Sjkoshy}; 923147191Sjkoshy 924147191Sjkoshy/* dc dispatched prefetch instructions */ 925147191Sjkoshystatic const struct pmc_masks k8_mask_ddpi[] = { 926147191Sjkoshy __K8MASK(load, 0), 927147191Sjkoshy __K8MASK(store, 1), 928147191Sjkoshy __K8MASK(nta, 2), 929147191Sjkoshy NULLMASK 930147191Sjkoshy}; 931147191Sjkoshy 932147191Sjkoshy/* dc dcache accesses by locks */ 933147191Sjkoshystatic const struct pmc_masks k8_mask_dabl[] = { 934147191Sjkoshy __K8MASK(accesses, 0), 935147191Sjkoshy __K8MASK(misses, 1), 936147191Sjkoshy NULLMASK 937147191Sjkoshy}; 938147191Sjkoshy 939147191Sjkoshy/* bu internal l2 request */ 940147191Sjkoshystatic const struct pmc_masks k8_mask_bilr[] = { 941147191Sjkoshy __K8MASK(ic-fill, 0), 942147191Sjkoshy __K8MASK(dc-fill, 1), 943147191Sjkoshy __K8MASK(tlb-reload, 2), 944147191Sjkoshy __K8MASK(tag-snoop, 3), 945147191Sjkoshy __K8MASK(cancelled, 4), 946147191Sjkoshy NULLMASK 947147191Sjkoshy}; 948147191Sjkoshy 949147191Sjkoshy/* bu fill request l2 miss */ 950147191Sjkoshystatic const struct pmc_masks k8_mask_bfrlm[] = { 951147191Sjkoshy __K8MASK(ic-fill, 0), 952147191Sjkoshy __K8MASK(dc-fill, 1), 953147191Sjkoshy __K8MASK(tlb-reload, 2), 954147191Sjkoshy NULLMASK 955147191Sjkoshy}; 956147191Sjkoshy 957147191Sjkoshy/* bu fill into l2 */ 958147191Sjkoshystatic const struct pmc_masks k8_mask_bfil[] = { 959147191Sjkoshy __K8MASK(dirty-l2-victim, 0), 960147191Sjkoshy __K8MASK(victim-from-l2, 1), 961147191Sjkoshy NULLMASK 962147191Sjkoshy}; 963147191Sjkoshy 964147191Sjkoshy/* fr retired fpu instructions */ 965147191Sjkoshystatic const struct pmc_masks k8_mask_frfi[] = { 966147191Sjkoshy __K8MASK(x87, 0), 967147191Sjkoshy __K8MASK(mmx-3dnow, 1), 968147191Sjkoshy __K8MASK(packed-sse-sse2, 2), 969147191Sjkoshy __K8MASK(scalar-sse-sse2, 3), 970147191Sjkoshy NULLMASK 971147191Sjkoshy}; 972147191Sjkoshy 973147191Sjkoshy/* fr retired fastpath double op instructions */ 974147191Sjkoshystatic const struct pmc_masks k8_mask_frfdoi[] = { 975147191Sjkoshy __K8MASK(low-op-pos-0, 0), 976147191Sjkoshy __K8MASK(low-op-pos-1, 1), 977147191Sjkoshy __K8MASK(low-op-pos-2, 2), 978147191Sjkoshy NULLMASK 979147191Sjkoshy}; 980147191Sjkoshy 981147191Sjkoshy/* fr fpu exceptions */ 982147191Sjkoshystatic const struct pmc_masks k8_mask_ffe[] = { 983147191Sjkoshy __K8MASK(x87-reclass-microfaults, 0), 984147191Sjkoshy __K8MASK(sse-retype-microfaults, 1), 985147191Sjkoshy __K8MASK(sse-reclass-microfaults, 2), 986147191Sjkoshy __K8MASK(sse-and-x87-microtraps, 3), 987147191Sjkoshy NULLMASK 988147191Sjkoshy}; 989147191Sjkoshy 990147191Sjkoshy/* nb memory controller page access event */ 991147191Sjkoshystatic const struct pmc_masks k8_mask_nmcpae[] = { 992147191Sjkoshy __K8MASK(page-hit, 0), 993147191Sjkoshy __K8MASK(page-miss, 1), 994147191Sjkoshy __K8MASK(page-conflict, 2), 995147191Sjkoshy NULLMASK 996147191Sjkoshy}; 997147191Sjkoshy 998147191Sjkoshy/* nb memory controller turnaround */ 999147191Sjkoshystatic const struct pmc_masks k8_mask_nmct[] = { 1000147191Sjkoshy __K8MASK(dimm-turnaround, 0), 1001147191Sjkoshy __K8MASK(read-to-write-turnaround, 1), 1002147191Sjkoshy __K8MASK(write-to-read-turnaround, 2), 1003147191Sjkoshy NULLMASK 1004147191Sjkoshy}; 1005147191Sjkoshy 1006147191Sjkoshy/* nb memory controller bypass saturation */ 1007147191Sjkoshystatic const struct pmc_masks k8_mask_nmcbs[] = { 1008147191Sjkoshy __K8MASK(memory-controller-hi-pri-bypass, 0), 1009147191Sjkoshy __K8MASK(memory-controller-lo-pri-bypass, 1), 1010147191Sjkoshy __K8MASK(dram-controller-interface-bypass, 2), 1011147191Sjkoshy __K8MASK(dram-controller-queue-bypass, 3), 1012147191Sjkoshy NULLMASK 1013147191Sjkoshy}; 1014147191Sjkoshy 1015147191Sjkoshy/* nb sized commands */ 1016147191Sjkoshystatic const struct pmc_masks k8_mask_nsc[] = { 1017147191Sjkoshy __K8MASK(nonpostwrszbyte, 0), 1018147191Sjkoshy __K8MASK(nonpostwrszdword, 1), 1019147191Sjkoshy __K8MASK(postwrszbyte, 2), 1020147191Sjkoshy __K8MASK(postwrszdword, 3), 1021147191Sjkoshy __K8MASK(rdszbyte, 4), 1022147191Sjkoshy __K8MASK(rdszdword, 5), 1023147191Sjkoshy __K8MASK(rdmodwr, 6), 1024147191Sjkoshy NULLMASK 1025147191Sjkoshy}; 1026147191Sjkoshy 1027147191Sjkoshy/* nb probe result */ 1028147191Sjkoshystatic const struct pmc_masks k8_mask_npr[] = { 1029147191Sjkoshy __K8MASK(probe-miss, 0), 1030147191Sjkoshy __K8MASK(probe-hit, 1), 1031147191Sjkoshy __K8MASK(probe-hit-dirty-no-memory-cancel, 2), 1032147191Sjkoshy __K8MASK(probe-hit-dirty-with-memory-cancel, 3), 1033147191Sjkoshy NULLMASK 1034147191Sjkoshy}; 1035147191Sjkoshy 1036147191Sjkoshy/* nb hypertransport bus bandwidth */ 1037147191Sjkoshystatic const struct pmc_masks k8_mask_nhbb[] = { /* HT bus bandwidth */ 1038147191Sjkoshy __K8MASK(command, 0), 1039183107Sjkoshy __K8MASK(data, 1), 1040147191Sjkoshy __K8MASK(buffer-release, 2), 1041147191Sjkoshy __K8MASK(nop, 3), 1042147191Sjkoshy NULLMASK 1043147191Sjkoshy}; 1044147191Sjkoshy 1045147191Sjkoshy#undef __K8MASK 1046147191Sjkoshy 1047147191Sjkoshy#define K8_KW_COUNT "count" 1048147191Sjkoshy#define K8_KW_EDGE "edge" 1049147191Sjkoshy#define K8_KW_INV "inv" 1050147191Sjkoshy#define K8_KW_MASK "mask" 1051147191Sjkoshy#define K8_KW_OS "os" 1052147191Sjkoshy#define K8_KW_USR "usr" 1053147191Sjkoshy 1054147191Sjkoshystatic int 1055147191Sjkoshyk8_allocate_pmc(enum pmc_event pe, char *ctrspec, 1056147191Sjkoshy struct pmc_op_pmcallocate *pmc_config) 1057147191Sjkoshy{ 1058183107Sjkoshy char *e, *p, *q; 1059183107Sjkoshy int n; 1060147191Sjkoshy uint32_t count, evmask; 1061147191Sjkoshy const struct pmc_masks *pm, *pmask; 1062147191Sjkoshy 1063183725Sjkoshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1064147191Sjkoshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 1065147191Sjkoshy 1066147191Sjkoshy pmask = NULL; 1067147191Sjkoshy evmask = 0; 1068147191Sjkoshy 1069147191Sjkoshy#define __K8SETMASK(M) pmask = k8_mask_##M 1070147191Sjkoshy 1071147191Sjkoshy /* setup parsing tables */ 1072147191Sjkoshy switch (pe) { 1073147191Sjkoshy case PMC_EV_K8_FP_DISPATCHED_FPU_OPS: 1074147191Sjkoshy __K8SETMASK(fdfo); 1075147191Sjkoshy break; 1076147191Sjkoshy case PMC_EV_K8_LS_SEGMENT_REGISTER_LOAD: 1077147191Sjkoshy __K8SETMASK(lsrl); 1078147191Sjkoshy break; 1079147191Sjkoshy case PMC_EV_K8_LS_LOCKED_OPERATION: 1080147191Sjkoshy __K8SETMASK(llo); 1081147191Sjkoshy break; 1082147191Sjkoshy case PMC_EV_K8_DC_REFILL_FROM_L2: 1083147191Sjkoshy case PMC_EV_K8_DC_REFILL_FROM_SYSTEM: 1084147191Sjkoshy case PMC_EV_K8_DC_COPYBACK: 1085147191Sjkoshy __K8SETMASK(dc); 1086147191Sjkoshy break; 1087147191Sjkoshy case PMC_EV_K8_DC_ONE_BIT_ECC_ERROR: 1088147191Sjkoshy __K8SETMASK(dobee); 1089147191Sjkoshy break; 1090147191Sjkoshy case PMC_EV_K8_DC_DISPATCHED_PREFETCH_INSTRUCTIONS: 1091147191Sjkoshy __K8SETMASK(ddpi); 1092147191Sjkoshy break; 1093147191Sjkoshy case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS: 1094147191Sjkoshy __K8SETMASK(dabl); 1095147191Sjkoshy break; 1096147191Sjkoshy case PMC_EV_K8_BU_INTERNAL_L2_REQUEST: 1097147191Sjkoshy __K8SETMASK(bilr); 1098147191Sjkoshy break; 1099147191Sjkoshy case PMC_EV_K8_BU_FILL_REQUEST_L2_MISS: 1100147191Sjkoshy __K8SETMASK(bfrlm); 1101147191Sjkoshy break; 1102147191Sjkoshy case PMC_EV_K8_BU_FILL_INTO_L2: 1103147191Sjkoshy __K8SETMASK(bfil); 1104147191Sjkoshy break; 1105147191Sjkoshy case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS: 1106147191Sjkoshy __K8SETMASK(frfi); 1107147191Sjkoshy break; 1108147191Sjkoshy case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS: 1109147191Sjkoshy __K8SETMASK(frfdoi); 1110147191Sjkoshy break; 1111147191Sjkoshy case PMC_EV_K8_FR_FPU_EXCEPTIONS: 1112147191Sjkoshy __K8SETMASK(ffe); 1113147191Sjkoshy break; 1114147191Sjkoshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_PAGE_ACCESS_EVENT: 1115147191Sjkoshy __K8SETMASK(nmcpae); 1116147191Sjkoshy break; 1117147191Sjkoshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_TURNAROUND: 1118147191Sjkoshy __K8SETMASK(nmct); 1119147191Sjkoshy break; 1120147191Sjkoshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_BYPASS_SATURATION: 1121147191Sjkoshy __K8SETMASK(nmcbs); 1122147191Sjkoshy break; 1123147191Sjkoshy case PMC_EV_K8_NB_SIZED_COMMANDS: 1124147191Sjkoshy __K8SETMASK(nsc); 1125147191Sjkoshy break; 1126147191Sjkoshy case PMC_EV_K8_NB_PROBE_RESULT: 1127147191Sjkoshy __K8SETMASK(npr); 1128147191Sjkoshy break; 1129147191Sjkoshy case PMC_EV_K8_NB_HT_BUS0_BANDWIDTH: 1130147191Sjkoshy case PMC_EV_K8_NB_HT_BUS1_BANDWIDTH: 1131147191Sjkoshy case PMC_EV_K8_NB_HT_BUS2_BANDWIDTH: 1132147191Sjkoshy __K8SETMASK(nhbb); 1133147191Sjkoshy break; 1134147191Sjkoshy 1135147191Sjkoshy default: 1136147191Sjkoshy break; /* no options defined */ 1137147191Sjkoshy } 1138147191Sjkoshy 1139147191Sjkoshy while ((p = strsep(&ctrspec, ",")) != NULL) { 1140147191Sjkoshy if (KWPREFIXMATCH(p, K8_KW_COUNT "=")) { 1141147191Sjkoshy q = strchr(p, '='); 1142147191Sjkoshy if (*++q == '\0') /* skip '=' */ 1143174406Sjkoshy return (-1); 1144147191Sjkoshy 1145147191Sjkoshy count = strtol(q, &e, 0); 1146147191Sjkoshy if (e == q || *e != '\0') 1147174406Sjkoshy return (-1); 1148147191Sjkoshy 1149147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 1150147191Sjkoshy pmc_config->pm_md.pm_amd.pm_amd_config |= 1151147191Sjkoshy AMD_PMC_TO_COUNTER(count); 1152147191Sjkoshy 1153147191Sjkoshy } else if (KWMATCH(p, K8_KW_EDGE)) { 1154147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1155147191Sjkoshy } else if (KWMATCH(p, K8_KW_INV)) { 1156147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_INVERT; 1157147191Sjkoshy } else if (KWPREFIXMATCH(p, K8_KW_MASK "=")) { 1158147191Sjkoshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 1159174406Sjkoshy return (-1); 1160147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1161147191Sjkoshy } else if (KWMATCH(p, K8_KW_OS)) { 1162147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 1163147191Sjkoshy } else if (KWMATCH(p, K8_KW_USR)) { 1164147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_USER; 1165147191Sjkoshy } else 1166174406Sjkoshy return (-1); 1167147191Sjkoshy } 1168147191Sjkoshy 1169147191Sjkoshy /* other post processing */ 1170147191Sjkoshy switch (pe) { 1171147191Sjkoshy case PMC_EV_K8_FP_DISPATCHED_FPU_OPS: 1172147191Sjkoshy case PMC_EV_K8_FP_CYCLES_WITH_NO_FPU_OPS_RETIRED: 1173147191Sjkoshy case PMC_EV_K8_FP_DISPATCHED_FPU_FAST_FLAG_OPS: 1174147191Sjkoshy case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS: 1175147191Sjkoshy case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS: 1176147191Sjkoshy case PMC_EV_K8_FR_FPU_EXCEPTIONS: 1177147191Sjkoshy /* XXX only available in rev B and later */ 1178147191Sjkoshy break; 1179147191Sjkoshy case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS: 1180147191Sjkoshy /* XXX only available in rev C and later */ 1181147191Sjkoshy break; 1182147191Sjkoshy case PMC_EV_K8_LS_LOCKED_OPERATION: 1183147191Sjkoshy /* XXX CPU Rev A,B evmask is to be zero */ 1184147191Sjkoshy if (evmask & (evmask - 1)) /* > 1 bit set */ 1185174406Sjkoshy return (-1); 1186147191Sjkoshy if (evmask == 0) { 1187147191Sjkoshy evmask = 0x01; /* Rev C and later: #instrs */ 1188147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1189147191Sjkoshy } 1190147191Sjkoshy break; 1191147191Sjkoshy default: 1192147191Sjkoshy if (evmask == 0 && pmask != NULL) { 1193147191Sjkoshy for (pm = pmask; pm->pm_name; pm++) 1194147191Sjkoshy evmask |= pm->pm_value; 1195147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1196147191Sjkoshy } 1197147191Sjkoshy } 1198147191Sjkoshy 1199147191Sjkoshy if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) 1200147191Sjkoshy pmc_config->pm_md.pm_amd.pm_amd_config = 1201147191Sjkoshy AMD_PMC_TO_UNITMASK(evmask); 1202147191Sjkoshy 1203174406Sjkoshy return (0); 1204147191Sjkoshy} 1205147191Sjkoshy 1206147191Sjkoshy#endif 1207147191Sjkoshy 1208147759Sjkoshy#if defined(__amd64__) || defined(__i386__) 1209147191Sjkoshy 1210147191Sjkoshy/* 1211145256Sjkoshy * Intel P4 PMCs 1212145256Sjkoshy */ 1213145256Sjkoshy 1214145256Sjkoshystatic struct pmc_event_alias p4_aliases[] = { 1215145351Sjkoshy EV_ALIAS("branches", "p4-branch-retired,mask=mmtp+mmtm"), 1216145351Sjkoshy EV_ALIAS("branch-mispredicts", "p4-mispred-branch-retired"), 1217145351Sjkoshy EV_ALIAS("cycles", "tsc"), 1218145351Sjkoshy EV_ALIAS("instructions", 1219145351Sjkoshy "p4-instr-retired,mask=nbogusntag+nbogustag"), 1220155998Sjkoshy EV_ALIAS("unhalted-cycles", "p4-global-power-events"), 1221145256Sjkoshy EV_ALIAS(NULL, NULL) 1222145256Sjkoshy}; 1223145256Sjkoshy 1224145256Sjkoshy#define P4_KW_ACTIVE "active" 1225145256Sjkoshy#define P4_KW_ACTIVE_ANY "any" 1226145256Sjkoshy#define P4_KW_ACTIVE_BOTH "both" 1227145256Sjkoshy#define P4_KW_ACTIVE_NONE "none" 1228145256Sjkoshy#define P4_KW_ACTIVE_SINGLE "single" 1229145256Sjkoshy#define P4_KW_BUSREQTYPE "busreqtype" 1230145256Sjkoshy#define P4_KW_CASCADE "cascade" 1231145256Sjkoshy#define P4_KW_EDGE "edge" 1232145256Sjkoshy#define P4_KW_INV "complement" 1233145256Sjkoshy#define P4_KW_OS "os" 1234145256Sjkoshy#define P4_KW_MASK "mask" 1235145256Sjkoshy#define P4_KW_PRECISE "precise" 1236145256Sjkoshy#define P4_KW_TAG "tag" 1237145256Sjkoshy#define P4_KW_THRESHOLD "threshold" 1238145256Sjkoshy#define P4_KW_USR "usr" 1239145256Sjkoshy 1240145256Sjkoshy#define __P4MASK(N,V) PMCMASK(N, (1 << (V))) 1241145256Sjkoshy 1242145256Sjkoshystatic const struct pmc_masks p4_mask_tcdm[] = { /* tc deliver mode */ 1243145256Sjkoshy __P4MASK(dd, 0), 1244145256Sjkoshy __P4MASK(db, 1), 1245145256Sjkoshy __P4MASK(di, 2), 1246145256Sjkoshy __P4MASK(bd, 3), 1247145256Sjkoshy __P4MASK(bb, 4), 1248145256Sjkoshy __P4MASK(bi, 5), 1249145256Sjkoshy __P4MASK(id, 6), 1250145256Sjkoshy __P4MASK(ib, 7), 1251145256Sjkoshy NULLMASK 1252145256Sjkoshy}; 1253145256Sjkoshy 1254145256Sjkoshystatic const struct pmc_masks p4_mask_bfr[] = { /* bpu fetch request */ 1255145256Sjkoshy __P4MASK(tcmiss, 0), 1256145256Sjkoshy NULLMASK, 1257145256Sjkoshy}; 1258145256Sjkoshy 1259145256Sjkoshystatic const struct pmc_masks p4_mask_ir[] = { /* itlb reference */ 1260145256Sjkoshy __P4MASK(hit, 0), 1261145256Sjkoshy __P4MASK(miss, 1), 1262145256Sjkoshy __P4MASK(hit-uc, 2), 1263145256Sjkoshy NULLMASK 1264145256Sjkoshy}; 1265145256Sjkoshy 1266145256Sjkoshystatic const struct pmc_masks p4_mask_memcan[] = { /* memory cancel */ 1267145256Sjkoshy __P4MASK(st-rb-full, 2), 1268145256Sjkoshy __P4MASK(64k-conf, 3), 1269145256Sjkoshy NULLMASK 1270145256Sjkoshy}; 1271145256Sjkoshy 1272145256Sjkoshystatic const struct pmc_masks p4_mask_memcomp[] = { /* memory complete */ 1273145256Sjkoshy __P4MASK(lsc, 0), 1274145256Sjkoshy __P4MASK(ssc, 1), 1275145256Sjkoshy NULLMASK 1276145256Sjkoshy}; 1277145256Sjkoshy 1278145256Sjkoshystatic const struct pmc_masks p4_mask_lpr[] = { /* load port replay */ 1279145256Sjkoshy __P4MASK(split-ld, 1), 1280145256Sjkoshy NULLMASK 1281145256Sjkoshy}; 1282145256Sjkoshy 1283145256Sjkoshystatic const struct pmc_masks p4_mask_spr[] = { /* store port replay */ 1284145256Sjkoshy __P4MASK(split-st, 1), 1285145256Sjkoshy NULLMASK 1286145256Sjkoshy}; 1287145256Sjkoshy 1288145256Sjkoshystatic const struct pmc_masks p4_mask_mlr[] = { /* mob load replay */ 1289145256Sjkoshy __P4MASK(no-sta, 1), 1290145256Sjkoshy __P4MASK(no-std, 3), 1291145256Sjkoshy __P4MASK(partial-data, 4), 1292145256Sjkoshy __P4MASK(unalgn-addr, 5), 1293145256Sjkoshy NULLMASK 1294145256Sjkoshy}; 1295145256Sjkoshy 1296145256Sjkoshystatic const struct pmc_masks p4_mask_pwt[] = { /* page walk type */ 1297145256Sjkoshy __P4MASK(dtmiss, 0), 1298145256Sjkoshy __P4MASK(itmiss, 1), 1299145256Sjkoshy NULLMASK 1300145256Sjkoshy}; 1301145256Sjkoshy 1302145256Sjkoshystatic const struct pmc_masks p4_mask_bcr[] = { /* bsq cache reference */ 1303145256Sjkoshy __P4MASK(rd-2ndl-hits, 0), 1304145256Sjkoshy __P4MASK(rd-2ndl-hite, 1), 1305145256Sjkoshy __P4MASK(rd-2ndl-hitm, 2), 1306145256Sjkoshy __P4MASK(rd-3rdl-hits, 3), 1307145256Sjkoshy __P4MASK(rd-3rdl-hite, 4), 1308145256Sjkoshy __P4MASK(rd-3rdl-hitm, 5), 1309145256Sjkoshy __P4MASK(rd-2ndl-miss, 8), 1310145256Sjkoshy __P4MASK(rd-3rdl-miss, 9), 1311145256Sjkoshy __P4MASK(wr-2ndl-miss, 10), 1312145256Sjkoshy NULLMASK 1313145256Sjkoshy}; 1314145256Sjkoshy 1315145256Sjkoshystatic const struct pmc_masks p4_mask_ia[] = { /* ioq allocation */ 1316145256Sjkoshy __P4MASK(all-read, 5), 1317145256Sjkoshy __P4MASK(all-write, 6), 1318145256Sjkoshy __P4MASK(mem-uc, 7), 1319145256Sjkoshy __P4MASK(mem-wc, 8), 1320145256Sjkoshy __P4MASK(mem-wt, 9), 1321145256Sjkoshy __P4MASK(mem-wp, 10), 1322145256Sjkoshy __P4MASK(mem-wb, 11), 1323145256Sjkoshy __P4MASK(own, 13), 1324145256Sjkoshy __P4MASK(other, 14), 1325145256Sjkoshy __P4MASK(prefetch, 15), 1326145256Sjkoshy NULLMASK 1327145256Sjkoshy}; 1328145256Sjkoshy 1329145256Sjkoshystatic const struct pmc_masks p4_mask_iae[] = { /* ioq active entries */ 1330145256Sjkoshy __P4MASK(all-read, 5), 1331145256Sjkoshy __P4MASK(all-write, 6), 1332145256Sjkoshy __P4MASK(mem-uc, 7), 1333145256Sjkoshy __P4MASK(mem-wc, 8), 1334145256Sjkoshy __P4MASK(mem-wt, 9), 1335145256Sjkoshy __P4MASK(mem-wp, 10), 1336145256Sjkoshy __P4MASK(mem-wb, 11), 1337145256Sjkoshy __P4MASK(own, 13), 1338145256Sjkoshy __P4MASK(other, 14), 1339145256Sjkoshy __P4MASK(prefetch, 15), 1340145256Sjkoshy NULLMASK 1341145256Sjkoshy}; 1342145256Sjkoshy 1343145256Sjkoshystatic const struct pmc_masks p4_mask_fda[] = { /* fsb data activity */ 1344145256Sjkoshy __P4MASK(drdy-drv, 0), 1345145256Sjkoshy __P4MASK(drdy-own, 1), 1346145256Sjkoshy __P4MASK(drdy-other, 2), 1347145256Sjkoshy __P4MASK(dbsy-drv, 3), 1348145256Sjkoshy __P4MASK(dbsy-own, 4), 1349145256Sjkoshy __P4MASK(dbsy-other, 5), 1350145256Sjkoshy NULLMASK 1351145256Sjkoshy}; 1352145256Sjkoshy 1353145256Sjkoshystatic const struct pmc_masks p4_mask_ba[] = { /* bsq allocation */ 1354145256Sjkoshy __P4MASK(req-type0, 0), 1355145256Sjkoshy __P4MASK(req-type1, 1), 1356145256Sjkoshy __P4MASK(req-len0, 2), 1357145256Sjkoshy __P4MASK(req-len1, 3), 1358145256Sjkoshy __P4MASK(req-io-type, 5), 1359145256Sjkoshy __P4MASK(req-lock-type, 6), 1360145256Sjkoshy __P4MASK(req-cache-type, 7), 1361145256Sjkoshy __P4MASK(req-split-type, 8), 1362145256Sjkoshy __P4MASK(req-dem-type, 9), 1363145256Sjkoshy __P4MASK(req-ord-type, 10), 1364145256Sjkoshy __P4MASK(mem-type0, 11), 1365145256Sjkoshy __P4MASK(mem-type1, 12), 1366145256Sjkoshy __P4MASK(mem-type2, 13), 1367145256Sjkoshy NULLMASK 1368145256Sjkoshy}; 1369145256Sjkoshy 1370145256Sjkoshystatic const struct pmc_masks p4_mask_sia[] = { /* sse input assist */ 1371145256Sjkoshy __P4MASK(all, 15), 1372145256Sjkoshy NULLMASK 1373145256Sjkoshy}; 1374145256Sjkoshy 1375145256Sjkoshystatic const struct pmc_masks p4_mask_psu[] = { /* packed sp uop */ 1376145256Sjkoshy __P4MASK(all, 15), 1377145256Sjkoshy NULLMASK 1378145256Sjkoshy}; 1379145256Sjkoshy 1380145256Sjkoshystatic const struct pmc_masks p4_mask_pdu[] = { /* packed dp uop */ 1381145256Sjkoshy __P4MASK(all, 15), 1382145256Sjkoshy NULLMASK 1383145256Sjkoshy}; 1384145256Sjkoshy 1385145256Sjkoshystatic const struct pmc_masks p4_mask_ssu[] = { /* scalar sp uop */ 1386145256Sjkoshy __P4MASK(all, 15), 1387145256Sjkoshy NULLMASK 1388145256Sjkoshy}; 1389145256Sjkoshy 1390145256Sjkoshystatic const struct pmc_masks p4_mask_sdu[] = { /* scalar dp uop */ 1391145256Sjkoshy __P4MASK(all, 15), 1392145256Sjkoshy NULLMASK 1393145256Sjkoshy}; 1394145256Sjkoshy 1395145256Sjkoshystatic const struct pmc_masks p4_mask_64bmu[] = { /* 64 bit mmx uop */ 1396145256Sjkoshy __P4MASK(all, 15), 1397145256Sjkoshy NULLMASK 1398145256Sjkoshy}; 1399145256Sjkoshy 1400145256Sjkoshystatic const struct pmc_masks p4_mask_128bmu[] = { /* 128 bit mmx uop */ 1401145256Sjkoshy __P4MASK(all, 15), 1402145256Sjkoshy NULLMASK 1403145256Sjkoshy}; 1404145256Sjkoshy 1405145256Sjkoshystatic const struct pmc_masks p4_mask_xfu[] = { /* X87 fp uop */ 1406145256Sjkoshy __P4MASK(all, 15), 1407145256Sjkoshy NULLMASK 1408145256Sjkoshy}; 1409145256Sjkoshy 1410145256Sjkoshystatic const struct pmc_masks p4_mask_xsmu[] = { /* x87 simd moves uop */ 1411145256Sjkoshy __P4MASK(allp0, 3), 1412145256Sjkoshy __P4MASK(allp2, 4), 1413145256Sjkoshy NULLMASK 1414145256Sjkoshy}; 1415145256Sjkoshy 1416145256Sjkoshystatic const struct pmc_masks p4_mask_gpe[] = { /* global power events */ 1417145256Sjkoshy __P4MASK(running, 0), 1418145256Sjkoshy NULLMASK 1419145256Sjkoshy}; 1420145256Sjkoshy 1421145256Sjkoshystatic const struct pmc_masks p4_mask_tmx[] = { /* TC ms xfer */ 1422145256Sjkoshy __P4MASK(cisc, 0), 1423145256Sjkoshy NULLMASK 1424145256Sjkoshy}; 1425145256Sjkoshy 1426145256Sjkoshystatic const struct pmc_masks p4_mask_uqw[] = { /* uop queue writes */ 1427145256Sjkoshy __P4MASK(from-tc-build, 0), 1428145256Sjkoshy __P4MASK(from-tc-deliver, 1), 1429145256Sjkoshy __P4MASK(from-rom, 2), 1430145256Sjkoshy NULLMASK 1431145256Sjkoshy}; 1432145256Sjkoshy 1433145351Sjkoshystatic const struct pmc_masks p4_mask_rmbt[] = { 1434145351Sjkoshy /* retired mispred branch type */ 1435145256Sjkoshy __P4MASK(conditional, 1), 1436145256Sjkoshy __P4MASK(call, 2), 1437145256Sjkoshy __P4MASK(return, 3), 1438145256Sjkoshy __P4MASK(indirect, 4), 1439145256Sjkoshy NULLMASK 1440145256Sjkoshy}; 1441145256Sjkoshy 1442145256Sjkoshystatic const struct pmc_masks p4_mask_rbt[] = { /* retired branch type */ 1443145256Sjkoshy __P4MASK(conditional, 1), 1444145256Sjkoshy __P4MASK(call, 2), 1445145256Sjkoshy __P4MASK(retired, 3), 1446145256Sjkoshy __P4MASK(indirect, 4), 1447145256Sjkoshy NULLMASK 1448145256Sjkoshy}; 1449145256Sjkoshy 1450145256Sjkoshystatic const struct pmc_masks p4_mask_rs[] = { /* resource stall */ 1451145256Sjkoshy __P4MASK(sbfull, 5), 1452145256Sjkoshy NULLMASK 1453145256Sjkoshy}; 1454145256Sjkoshy 1455145256Sjkoshystatic const struct pmc_masks p4_mask_wb[] = { /* WC buffer */ 1456145256Sjkoshy __P4MASK(wcb-evicts, 0), 1457145256Sjkoshy __P4MASK(wcb-full-evict, 1), 1458145256Sjkoshy NULLMASK 1459145256Sjkoshy}; 1460145256Sjkoshy 1461145256Sjkoshystatic const struct pmc_masks p4_mask_fee[] = { /* front end event */ 1462145256Sjkoshy __P4MASK(nbogus, 0), 1463145256Sjkoshy __P4MASK(bogus, 1), 1464145256Sjkoshy NULLMASK 1465145256Sjkoshy}; 1466145256Sjkoshy 1467145256Sjkoshystatic const struct pmc_masks p4_mask_ee[] = { /* execution event */ 1468145256Sjkoshy __P4MASK(nbogus0, 0), 1469145256Sjkoshy __P4MASK(nbogus1, 1), 1470145256Sjkoshy __P4MASK(nbogus2, 2), 1471145256Sjkoshy __P4MASK(nbogus3, 3), 1472145256Sjkoshy __P4MASK(bogus0, 4), 1473145256Sjkoshy __P4MASK(bogus1, 5), 1474145256Sjkoshy __P4MASK(bogus2, 6), 1475145256Sjkoshy __P4MASK(bogus3, 7), 1476145256Sjkoshy NULLMASK 1477145256Sjkoshy}; 1478145256Sjkoshy 1479145256Sjkoshystatic const struct pmc_masks p4_mask_re[] = { /* replay event */ 1480145256Sjkoshy __P4MASK(nbogus, 0), 1481145256Sjkoshy __P4MASK(bogus, 1), 1482145256Sjkoshy NULLMASK 1483145256Sjkoshy}; 1484145256Sjkoshy 1485145256Sjkoshystatic const struct pmc_masks p4_mask_insret[] = { /* instr retired */ 1486145256Sjkoshy __P4MASK(nbogusntag, 0), 1487145256Sjkoshy __P4MASK(nbogustag, 1), 1488145256Sjkoshy __P4MASK(bogusntag, 2), 1489145256Sjkoshy __P4MASK(bogustag, 3), 1490145256Sjkoshy NULLMASK 1491145256Sjkoshy}; 1492145256Sjkoshy 1493145256Sjkoshystatic const struct pmc_masks p4_mask_ur[] = { /* uops retired */ 1494145256Sjkoshy __P4MASK(nbogus, 0), 1495145256Sjkoshy __P4MASK(bogus, 1), 1496145256Sjkoshy NULLMASK 1497145256Sjkoshy}; 1498145256Sjkoshy 1499145256Sjkoshystatic const struct pmc_masks p4_mask_ut[] = { /* uop type */ 1500145256Sjkoshy __P4MASK(tagloads, 1), 1501145256Sjkoshy __P4MASK(tagstores, 2), 1502145256Sjkoshy NULLMASK 1503145256Sjkoshy}; 1504145256Sjkoshy 1505145256Sjkoshystatic const struct pmc_masks p4_mask_br[] = { /* branch retired */ 1506145256Sjkoshy __P4MASK(mmnp, 0), 1507145256Sjkoshy __P4MASK(mmnm, 1), 1508145256Sjkoshy __P4MASK(mmtp, 2), 1509145256Sjkoshy __P4MASK(mmtm, 3), 1510145256Sjkoshy NULLMASK 1511145256Sjkoshy}; 1512145256Sjkoshy 1513145256Sjkoshystatic const struct pmc_masks p4_mask_mbr[] = { /* mispred branch retired */ 1514145256Sjkoshy __P4MASK(nbogus, 0), 1515145256Sjkoshy NULLMASK 1516145256Sjkoshy}; 1517145256Sjkoshy 1518145256Sjkoshystatic const struct pmc_masks p4_mask_xa[] = { /* x87 assist */ 1519145256Sjkoshy __P4MASK(fpsu, 0), 1520145256Sjkoshy __P4MASK(fpso, 1), 1521145256Sjkoshy __P4MASK(poao, 2), 1522145256Sjkoshy __P4MASK(poau, 3), 1523145256Sjkoshy __P4MASK(prea, 4), 1524145256Sjkoshy NULLMASK 1525145256Sjkoshy}; 1526145256Sjkoshy 1527145256Sjkoshystatic const struct pmc_masks p4_mask_machclr[] = { /* machine clear */ 1528145256Sjkoshy __P4MASK(clear, 0), 1529145256Sjkoshy __P4MASK(moclear, 2), 1530145256Sjkoshy __P4MASK(smclear, 3), 1531145256Sjkoshy NULLMASK 1532145256Sjkoshy}; 1533145256Sjkoshy 1534145256Sjkoshy/* P4 event parser */ 1535145256Sjkoshystatic int 1536145256Sjkoshyp4_allocate_pmc(enum pmc_event pe, char *ctrspec, 1537145256Sjkoshy struct pmc_op_pmcallocate *pmc_config) 1538145256Sjkoshy{ 1539145256Sjkoshy 1540145256Sjkoshy char *e, *p, *q; 1541145256Sjkoshy int count, has_tag, has_busreqtype, n; 1542145256Sjkoshy uint32_t evmask, cccractivemask; 1543145256Sjkoshy const struct pmc_masks *pm, *pmask; 1544145256Sjkoshy 1545183725Sjkoshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1546147191Sjkoshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig = 1547147191Sjkoshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 0; 1548145256Sjkoshy 1549145256Sjkoshy pmask = NULL; 1550145256Sjkoshy evmask = 0; 1551145256Sjkoshy cccractivemask = 0x3; 1552145256Sjkoshy has_tag = has_busreqtype = 0; 1553145256Sjkoshy 1554145256Sjkoshy#define __P4SETMASK(M) do { \ 1555183107Sjkoshy pmask = p4_mask_##M; \ 1556145256Sjkoshy} while (0) 1557145256Sjkoshy 1558145256Sjkoshy switch (pe) { 1559145256Sjkoshy case PMC_EV_P4_TC_DELIVER_MODE: 1560145256Sjkoshy __P4SETMASK(tcdm); 1561145256Sjkoshy break; 1562145256Sjkoshy case PMC_EV_P4_BPU_FETCH_REQUEST: 1563145256Sjkoshy __P4SETMASK(bfr); 1564145256Sjkoshy break; 1565145256Sjkoshy case PMC_EV_P4_ITLB_REFERENCE: 1566145256Sjkoshy __P4SETMASK(ir); 1567145256Sjkoshy break; 1568145256Sjkoshy case PMC_EV_P4_MEMORY_CANCEL: 1569145256Sjkoshy __P4SETMASK(memcan); 1570145256Sjkoshy break; 1571145256Sjkoshy case PMC_EV_P4_MEMORY_COMPLETE: 1572145256Sjkoshy __P4SETMASK(memcomp); 1573145256Sjkoshy break; 1574145256Sjkoshy case PMC_EV_P4_LOAD_PORT_REPLAY: 1575145256Sjkoshy __P4SETMASK(lpr); 1576145256Sjkoshy break; 1577145256Sjkoshy case PMC_EV_P4_STORE_PORT_REPLAY: 1578145256Sjkoshy __P4SETMASK(spr); 1579145256Sjkoshy break; 1580145256Sjkoshy case PMC_EV_P4_MOB_LOAD_REPLAY: 1581145256Sjkoshy __P4SETMASK(mlr); 1582145256Sjkoshy break; 1583145256Sjkoshy case PMC_EV_P4_PAGE_WALK_TYPE: 1584145256Sjkoshy __P4SETMASK(pwt); 1585145256Sjkoshy break; 1586145256Sjkoshy case PMC_EV_P4_BSQ_CACHE_REFERENCE: 1587145256Sjkoshy __P4SETMASK(bcr); 1588145256Sjkoshy break; 1589145256Sjkoshy case PMC_EV_P4_IOQ_ALLOCATION: 1590145256Sjkoshy __P4SETMASK(ia); 1591145256Sjkoshy has_busreqtype = 1; 1592145256Sjkoshy break; 1593145256Sjkoshy case PMC_EV_P4_IOQ_ACTIVE_ENTRIES: 1594145256Sjkoshy __P4SETMASK(iae); 1595145256Sjkoshy has_busreqtype = 1; 1596145256Sjkoshy break; 1597145256Sjkoshy case PMC_EV_P4_FSB_DATA_ACTIVITY: 1598145256Sjkoshy __P4SETMASK(fda); 1599145256Sjkoshy break; 1600145256Sjkoshy case PMC_EV_P4_BSQ_ALLOCATION: 1601145256Sjkoshy __P4SETMASK(ba); 1602145256Sjkoshy break; 1603145256Sjkoshy case PMC_EV_P4_SSE_INPUT_ASSIST: 1604145256Sjkoshy __P4SETMASK(sia); 1605145256Sjkoshy break; 1606145256Sjkoshy case PMC_EV_P4_PACKED_SP_UOP: 1607145256Sjkoshy __P4SETMASK(psu); 1608145256Sjkoshy break; 1609145256Sjkoshy case PMC_EV_P4_PACKED_DP_UOP: 1610145256Sjkoshy __P4SETMASK(pdu); 1611145256Sjkoshy break; 1612145256Sjkoshy case PMC_EV_P4_SCALAR_SP_UOP: 1613145256Sjkoshy __P4SETMASK(ssu); 1614145256Sjkoshy break; 1615145256Sjkoshy case PMC_EV_P4_SCALAR_DP_UOP: 1616145256Sjkoshy __P4SETMASK(sdu); 1617145256Sjkoshy break; 1618145256Sjkoshy case PMC_EV_P4_64BIT_MMX_UOP: 1619145256Sjkoshy __P4SETMASK(64bmu); 1620145256Sjkoshy break; 1621145256Sjkoshy case PMC_EV_P4_128BIT_MMX_UOP: 1622145256Sjkoshy __P4SETMASK(128bmu); 1623145256Sjkoshy break; 1624145256Sjkoshy case PMC_EV_P4_X87_FP_UOP: 1625145256Sjkoshy __P4SETMASK(xfu); 1626145256Sjkoshy break; 1627145256Sjkoshy case PMC_EV_P4_X87_SIMD_MOVES_UOP: 1628145256Sjkoshy __P4SETMASK(xsmu); 1629145256Sjkoshy break; 1630145256Sjkoshy case PMC_EV_P4_GLOBAL_POWER_EVENTS: 1631145256Sjkoshy __P4SETMASK(gpe); 1632145256Sjkoshy break; 1633145256Sjkoshy case PMC_EV_P4_TC_MS_XFER: 1634145256Sjkoshy __P4SETMASK(tmx); 1635145256Sjkoshy break; 1636145256Sjkoshy case PMC_EV_P4_UOP_QUEUE_WRITES: 1637145256Sjkoshy __P4SETMASK(uqw); 1638145256Sjkoshy break; 1639145256Sjkoshy case PMC_EV_P4_RETIRED_MISPRED_BRANCH_TYPE: 1640145256Sjkoshy __P4SETMASK(rmbt); 1641145256Sjkoshy break; 1642145256Sjkoshy case PMC_EV_P4_RETIRED_BRANCH_TYPE: 1643145256Sjkoshy __P4SETMASK(rbt); 1644145256Sjkoshy break; 1645145256Sjkoshy case PMC_EV_P4_RESOURCE_STALL: 1646145256Sjkoshy __P4SETMASK(rs); 1647145256Sjkoshy break; 1648145256Sjkoshy case PMC_EV_P4_WC_BUFFER: 1649145256Sjkoshy __P4SETMASK(wb); 1650145256Sjkoshy break; 1651145256Sjkoshy case PMC_EV_P4_BSQ_ACTIVE_ENTRIES: 1652145256Sjkoshy case PMC_EV_P4_B2B_CYCLES: 1653145256Sjkoshy case PMC_EV_P4_BNR: 1654145256Sjkoshy case PMC_EV_P4_SNOOP: 1655145256Sjkoshy case PMC_EV_P4_RESPONSE: 1656145256Sjkoshy break; 1657145256Sjkoshy case PMC_EV_P4_FRONT_END_EVENT: 1658145256Sjkoshy __P4SETMASK(fee); 1659145256Sjkoshy break; 1660145256Sjkoshy case PMC_EV_P4_EXECUTION_EVENT: 1661145256Sjkoshy __P4SETMASK(ee); 1662145256Sjkoshy break; 1663145256Sjkoshy case PMC_EV_P4_REPLAY_EVENT: 1664145256Sjkoshy __P4SETMASK(re); 1665145256Sjkoshy break; 1666145256Sjkoshy case PMC_EV_P4_INSTR_RETIRED: 1667145256Sjkoshy __P4SETMASK(insret); 1668145256Sjkoshy break; 1669145256Sjkoshy case PMC_EV_P4_UOPS_RETIRED: 1670145256Sjkoshy __P4SETMASK(ur); 1671145256Sjkoshy break; 1672145256Sjkoshy case PMC_EV_P4_UOP_TYPE: 1673145256Sjkoshy __P4SETMASK(ut); 1674145256Sjkoshy break; 1675145256Sjkoshy case PMC_EV_P4_BRANCH_RETIRED: 1676145256Sjkoshy __P4SETMASK(br); 1677145256Sjkoshy break; 1678145256Sjkoshy case PMC_EV_P4_MISPRED_BRANCH_RETIRED: 1679145256Sjkoshy __P4SETMASK(mbr); 1680145256Sjkoshy break; 1681145256Sjkoshy case PMC_EV_P4_X87_ASSIST: 1682145256Sjkoshy __P4SETMASK(xa); 1683145256Sjkoshy break; 1684145256Sjkoshy case PMC_EV_P4_MACHINE_CLEAR: 1685145256Sjkoshy __P4SETMASK(machclr); 1686145256Sjkoshy break; 1687145256Sjkoshy default: 1688174406Sjkoshy return (-1); 1689145256Sjkoshy } 1690145256Sjkoshy 1691145256Sjkoshy /* process additional flags */ 1692145256Sjkoshy while ((p = strsep(&ctrspec, ",")) != NULL) { 1693145256Sjkoshy if (KWPREFIXMATCH(p, P4_KW_ACTIVE)) { 1694145256Sjkoshy q = strchr(p, '='); 1695145256Sjkoshy if (*++q == '\0') /* skip '=' */ 1696174406Sjkoshy return (-1); 1697145256Sjkoshy 1698183725Sjkoshy if (strcasecmp(q, P4_KW_ACTIVE_NONE) == 0) 1699145256Sjkoshy cccractivemask = 0x0; 1700183725Sjkoshy else if (strcasecmp(q, P4_KW_ACTIVE_SINGLE) == 0) 1701145256Sjkoshy cccractivemask = 0x1; 1702183725Sjkoshy else if (strcasecmp(q, P4_KW_ACTIVE_BOTH) == 0) 1703145256Sjkoshy cccractivemask = 0x2; 1704183725Sjkoshy else if (strcasecmp(q, P4_KW_ACTIVE_ANY) == 0) 1705145256Sjkoshy cccractivemask = 0x3; 1706145256Sjkoshy else 1707174406Sjkoshy return (-1); 1708145256Sjkoshy 1709145256Sjkoshy } else if (KWPREFIXMATCH(p, P4_KW_BUSREQTYPE)) { 1710145256Sjkoshy if (has_busreqtype == 0) 1711174406Sjkoshy return (-1); 1712145256Sjkoshy 1713145256Sjkoshy q = strchr(p, '='); 1714145256Sjkoshy if (*++q == '\0') /* skip '=' */ 1715174406Sjkoshy return (-1); 1716145256Sjkoshy 1717145256Sjkoshy count = strtol(q, &e, 0); 1718145256Sjkoshy if (e == q || *e != '\0') 1719174406Sjkoshy return (-1); 1720145256Sjkoshy evmask = (evmask & ~0x1F) | (count & 0x1F); 1721145256Sjkoshy } else if (KWMATCH(p, P4_KW_CASCADE)) 1722145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_CASCADE; 1723145256Sjkoshy else if (KWMATCH(p, P4_KW_EDGE)) 1724145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1725145256Sjkoshy else if (KWMATCH(p, P4_KW_INV)) 1726145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_INVERT; 1727145256Sjkoshy else if (KWPREFIXMATCH(p, P4_KW_MASK "=")) { 1728145256Sjkoshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 1729174406Sjkoshy return (-1); 1730145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1731145256Sjkoshy } else if (KWMATCH(p, P4_KW_OS)) 1732145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 1733145256Sjkoshy else if (KWMATCH(p, P4_KW_PRECISE)) 1734145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_PRECISE; 1735145256Sjkoshy else if (KWPREFIXMATCH(p, P4_KW_TAG "=")) { 1736145256Sjkoshy if (has_tag == 0) 1737174406Sjkoshy return (-1); 1738145256Sjkoshy 1739145256Sjkoshy q = strchr(p, '='); 1740145256Sjkoshy if (*++q == '\0') /* skip '=' */ 1741174406Sjkoshy return (-1); 1742145256Sjkoshy 1743145256Sjkoshy count = strtol(q, &e, 0); 1744145256Sjkoshy if (e == q || *e != '\0') 1745174406Sjkoshy return (-1); 1746145256Sjkoshy 1747145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_TAGGING; 1748147191Sjkoshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig |= 1749145256Sjkoshy P4_ESCR_TO_TAG_VALUE(count); 1750145256Sjkoshy } else if (KWPREFIXMATCH(p, P4_KW_THRESHOLD "=")) { 1751145256Sjkoshy q = strchr(p, '='); 1752145256Sjkoshy if (*++q == '\0') /* skip '=' */ 1753174406Sjkoshy return (-1); 1754145256Sjkoshy 1755145256Sjkoshy count = strtol(q, &e, 0); 1756145256Sjkoshy if (e == q || *e != '\0') 1757174406Sjkoshy return (-1); 1758145256Sjkoshy 1759145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 1760147191Sjkoshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig &= 1761147191Sjkoshy ~P4_CCCR_THRESHOLD_MASK; 1762147191Sjkoshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |= 1763147191Sjkoshy P4_CCCR_TO_THRESHOLD(count); 1764145256Sjkoshy } else if (KWMATCH(p, P4_KW_USR)) 1765145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_USER; 1766145256Sjkoshy else 1767174406Sjkoshy return (-1); 1768145256Sjkoshy } 1769145256Sjkoshy 1770145256Sjkoshy /* other post processing */ 1771145256Sjkoshy if (pe == PMC_EV_P4_IOQ_ALLOCATION || 1772145256Sjkoshy pe == PMC_EV_P4_FSB_DATA_ACTIVITY || 1773145256Sjkoshy pe == PMC_EV_P4_BSQ_ALLOCATION) 1774145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1775145256Sjkoshy 1776145256Sjkoshy /* fill in thread activity mask */ 1777147191Sjkoshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |= 1778145256Sjkoshy P4_CCCR_TO_ACTIVE_THREAD(cccractivemask); 1779145256Sjkoshy 1780145256Sjkoshy if (evmask) 1781145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1782145256Sjkoshy 1783145256Sjkoshy switch (pe) { 1784145256Sjkoshy case PMC_EV_P4_FSB_DATA_ACTIVITY: 1785145256Sjkoshy if ((evmask & 0x06) == 0x06 || 1786145256Sjkoshy (evmask & 0x18) == 0x18) 1787174406Sjkoshy return (-1); /* can't have own+other bits together */ 1788145256Sjkoshy if (evmask == 0) /* default:drdy-{drv,own}+dbsy{drv,own} */ 1789145256Sjkoshy evmask = 0x1D; 1790145256Sjkoshy break; 1791145256Sjkoshy case PMC_EV_P4_MACHINE_CLEAR: 1792145256Sjkoshy /* only one bit is allowed to be set */ 1793145256Sjkoshy if ((evmask & (evmask - 1)) != 0) 1794174406Sjkoshy return (-1); 1795145256Sjkoshy if (evmask == 0) { 1796183107Sjkoshy evmask = 0x1; /* 'CLEAR' */ 1797145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1798145256Sjkoshy } 1799145256Sjkoshy break; 1800145256Sjkoshy default: 1801145256Sjkoshy if (evmask == 0 && pmask) { 1802145256Sjkoshy for (pm = pmask; pm->pm_name; pm++) 1803145256Sjkoshy evmask |= pm->pm_value; 1804145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1805145256Sjkoshy } 1806145256Sjkoshy } 1807145256Sjkoshy 1808147191Sjkoshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 1809147191Sjkoshy P4_ESCR_TO_EVENT_MASK(evmask); 1810145256Sjkoshy 1811174406Sjkoshy return (0); 1812145256Sjkoshy} 1813145256Sjkoshy 1814147759Sjkoshy#endif 1815147759Sjkoshy 1816147759Sjkoshy#if defined(__i386__) 1817147759Sjkoshy 1818145256Sjkoshy/* 1819147191Sjkoshy * Pentium style PMCs 1820147191Sjkoshy */ 1821147191Sjkoshy 1822147191Sjkoshystatic struct pmc_event_alias p5_aliases[] = { 1823183105Sjkoshy EV_ALIAS("branches", "p5-taken-branches"), 1824183105Sjkoshy EV_ALIAS("cycles", "tsc"), 1825183105Sjkoshy EV_ALIAS("dc-misses", "p5-data-read-miss-or-write-miss"), 1826183105Sjkoshy EV_ALIAS("ic-misses", "p5-code-cache-miss"), 1827183105Sjkoshy EV_ALIAS("instructions", "p5-instructions-executed"), 1828183105Sjkoshy EV_ALIAS("interrupts", "p5-hardware-interrupts"), 1829183105Sjkoshy EV_ALIAS("unhalted-cycles", 1830183105Sjkoshy "p5-number-of-cycles-not-in-halt-state"), 1831147191Sjkoshy EV_ALIAS(NULL, NULL) 1832147191Sjkoshy}; 1833147191Sjkoshy 1834147191Sjkoshystatic int 1835147191Sjkoshyp5_allocate_pmc(enum pmc_event pe, char *ctrspec, 1836147191Sjkoshy struct pmc_op_pmcallocate *pmc_config) 1837147191Sjkoshy{ 1838174406Sjkoshy return (-1 || pe || ctrspec || pmc_config); /* shut up gcc */ 1839147191Sjkoshy} 1840147191Sjkoshy 1841147191Sjkoshy/* 1842145256Sjkoshy * Pentium Pro style PMCs. These PMCs are found in Pentium II, Pentium III, 1843145256Sjkoshy * and Pentium M CPUs. 1844145256Sjkoshy */ 1845145256Sjkoshy 1846145256Sjkoshystatic struct pmc_event_alias p6_aliases[] = { 1847145351Sjkoshy EV_ALIAS("branches", "p6-br-inst-retired"), 1848145351Sjkoshy EV_ALIAS("branch-mispredicts", "p6-br-miss-pred-retired"), 1849145351Sjkoshy EV_ALIAS("cycles", "tsc"), 1850145351Sjkoshy EV_ALIAS("dc-misses", "p6-dcu-lines-in"), 1851168612Sjkoshy EV_ALIAS("ic-misses", "p6-ifu-fetch-miss"), 1852145351Sjkoshy EV_ALIAS("instructions", "p6-inst-retired"), 1853145351Sjkoshy EV_ALIAS("interrupts", "p6-hw-int-rx"), 1854155998Sjkoshy EV_ALIAS("unhalted-cycles", "p6-cpu-clk-unhalted"), 1855145351Sjkoshy EV_ALIAS(NULL, NULL) 1856145256Sjkoshy}; 1857145256Sjkoshy 1858145256Sjkoshy#define P6_KW_CMASK "cmask" 1859145256Sjkoshy#define P6_KW_EDGE "edge" 1860145256Sjkoshy#define P6_KW_INV "inv" 1861145256Sjkoshy#define P6_KW_OS "os" 1862145256Sjkoshy#define P6_KW_UMASK "umask" 1863145256Sjkoshy#define P6_KW_USR "usr" 1864145256Sjkoshy 1865145256Sjkoshystatic struct pmc_masks p6_mask_mesi[] = { 1866145256Sjkoshy PMCMASK(m, 0x01), 1867145256Sjkoshy PMCMASK(e, 0x02), 1868145256Sjkoshy PMCMASK(s, 0x04), 1869145256Sjkoshy PMCMASK(i, 0x08), 1870145256Sjkoshy NULLMASK 1871145256Sjkoshy}; 1872145256Sjkoshy 1873145256Sjkoshystatic struct pmc_masks p6_mask_mesihw[] = { 1874145256Sjkoshy PMCMASK(m, 0x01), 1875145256Sjkoshy PMCMASK(e, 0x02), 1876145256Sjkoshy PMCMASK(s, 0x04), 1877145256Sjkoshy PMCMASK(i, 0x08), 1878145256Sjkoshy PMCMASK(nonhw, 0x00), 1879145256Sjkoshy PMCMASK(hw, 0x10), 1880145256Sjkoshy PMCMASK(both, 0x30), 1881145256Sjkoshy NULLMASK 1882145256Sjkoshy}; 1883145256Sjkoshy 1884145256Sjkoshystatic struct pmc_masks p6_mask_hw[] = { 1885145256Sjkoshy PMCMASK(nonhw, 0x00), 1886145256Sjkoshy PMCMASK(hw, 0x10), 1887145256Sjkoshy PMCMASK(both, 0x30), 1888145256Sjkoshy NULLMASK 1889145256Sjkoshy}; 1890145256Sjkoshy 1891145256Sjkoshystatic struct pmc_masks p6_mask_any[] = { 1892145256Sjkoshy PMCMASK(self, 0x00), 1893145256Sjkoshy PMCMASK(any, 0x20), 1894145256Sjkoshy NULLMASK 1895145256Sjkoshy}; 1896145256Sjkoshy 1897145256Sjkoshystatic struct pmc_masks p6_mask_ekp[] = { 1898145256Sjkoshy PMCMASK(nta, 0x00), 1899145256Sjkoshy PMCMASK(t1, 0x01), 1900145256Sjkoshy PMCMASK(t2, 0x02), 1901145256Sjkoshy PMCMASK(wos, 0x03), 1902145256Sjkoshy NULLMASK 1903145256Sjkoshy}; 1904145256Sjkoshy 1905145256Sjkoshystatic struct pmc_masks p6_mask_pps[] = { 1906145256Sjkoshy PMCMASK(packed-and-scalar, 0x00), 1907145256Sjkoshy PMCMASK(scalar, 0x01), 1908145256Sjkoshy NULLMASK 1909145256Sjkoshy}; 1910145256Sjkoshy 1911145256Sjkoshystatic struct pmc_masks p6_mask_mite[] = { 1912145256Sjkoshy PMCMASK(packed-multiply, 0x01), 1913145256Sjkoshy PMCMASK(packed-shift, 0x02), 1914145256Sjkoshy PMCMASK(pack, 0x04), 1915145256Sjkoshy PMCMASK(unpack, 0x08), 1916145256Sjkoshy PMCMASK(packed-logical, 0x10), 1917145256Sjkoshy PMCMASK(packed-arithmetic, 0x20), 1918145256Sjkoshy NULLMASK 1919145256Sjkoshy}; 1920145256Sjkoshy 1921145256Sjkoshystatic struct pmc_masks p6_mask_fmt[] = { 1922145256Sjkoshy PMCMASK(mmxtofp, 0x00), 1923145256Sjkoshy PMCMASK(fptommx, 0x01), 1924145256Sjkoshy NULLMASK 1925145256Sjkoshy}; 1926145256Sjkoshy 1927145256Sjkoshystatic struct pmc_masks p6_mask_sr[] = { 1928145256Sjkoshy PMCMASK(es, 0x01), 1929145256Sjkoshy PMCMASK(ds, 0x02), 1930145256Sjkoshy PMCMASK(fs, 0x04), 1931145256Sjkoshy PMCMASK(gs, 0x08), 1932145256Sjkoshy NULLMASK 1933145256Sjkoshy}; 1934145256Sjkoshy 1935145256Sjkoshystatic struct pmc_masks p6_mask_eet[] = { 1936145256Sjkoshy PMCMASK(all, 0x00), 1937145256Sjkoshy PMCMASK(freq, 0x02), 1938145256Sjkoshy NULLMASK 1939145256Sjkoshy}; 1940145256Sjkoshy 1941145256Sjkoshystatic struct pmc_masks p6_mask_efur[] = { 1942145256Sjkoshy PMCMASK(all, 0x00), 1943145256Sjkoshy PMCMASK(loadop, 0x01), 1944145256Sjkoshy PMCMASK(stdsta, 0x02), 1945145256Sjkoshy NULLMASK 1946145256Sjkoshy}; 1947145256Sjkoshy 1948145256Sjkoshystatic struct pmc_masks p6_mask_essir[] = { 1949145256Sjkoshy PMCMASK(sse-packed-single, 0x00), 1950145256Sjkoshy PMCMASK(sse-packed-single-scalar-single, 0x01), 1951145256Sjkoshy PMCMASK(sse2-packed-double, 0x02), 1952145256Sjkoshy PMCMASK(sse2-scalar-double, 0x03), 1953145256Sjkoshy NULLMASK 1954145256Sjkoshy}; 1955145256Sjkoshy 1956145256Sjkoshystatic struct pmc_masks p6_mask_esscir[] = { 1957145256Sjkoshy PMCMASK(sse-packed-single, 0x00), 1958145256Sjkoshy PMCMASK(sse-scalar-single, 0x01), 1959145256Sjkoshy PMCMASK(sse2-packed-double, 0x02), 1960145256Sjkoshy PMCMASK(sse2-scalar-double, 0x03), 1961145256Sjkoshy NULLMASK 1962145256Sjkoshy}; 1963145256Sjkoshy 1964145256Sjkoshy/* P6 event parser */ 1965145256Sjkoshystatic int 1966145256Sjkoshyp6_allocate_pmc(enum pmc_event pe, char *ctrspec, 1967145256Sjkoshy struct pmc_op_pmcallocate *pmc_config) 1968145256Sjkoshy{ 1969145256Sjkoshy char *e, *p, *q; 1970145256Sjkoshy uint32_t evmask; 1971145256Sjkoshy int count, n; 1972145256Sjkoshy const struct pmc_masks *pm, *pmask; 1973145256Sjkoshy 1974183725Sjkoshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1975147191Sjkoshy pmc_config->pm_md.pm_ppro.pm_ppro_config = 0; 1976145256Sjkoshy 1977145256Sjkoshy evmask = 0; 1978145256Sjkoshy 1979145256Sjkoshy#define P6MASKSET(M) pmask = p6_mask_ ## M 1980145256Sjkoshy 1981145256Sjkoshy switch(pe) { 1982183107Sjkoshy case PMC_EV_P6_L2_IFETCH: P6MASKSET(mesi); break; 1983145256Sjkoshy case PMC_EV_P6_L2_LD: P6MASKSET(mesi); break; 1984145256Sjkoshy case PMC_EV_P6_L2_ST: P6MASKSET(mesi); break; 1985145256Sjkoshy case PMC_EV_P6_L2_RQSTS: P6MASKSET(mesi); break; 1986145256Sjkoshy case PMC_EV_P6_BUS_DRDY_CLOCKS: 1987145256Sjkoshy case PMC_EV_P6_BUS_LOCK_CLOCKS: 1988145256Sjkoshy case PMC_EV_P6_BUS_TRAN_BRD: 1989145256Sjkoshy case PMC_EV_P6_BUS_TRAN_RFO: 1990145256Sjkoshy case PMC_EV_P6_BUS_TRANS_WB: 1991145256Sjkoshy case PMC_EV_P6_BUS_TRAN_IFETCH: 1992145256Sjkoshy case PMC_EV_P6_BUS_TRAN_INVAL: 1993145256Sjkoshy case PMC_EV_P6_BUS_TRAN_PWR: 1994145256Sjkoshy case PMC_EV_P6_BUS_TRANS_P: 1995145256Sjkoshy case PMC_EV_P6_BUS_TRANS_IO: 1996145256Sjkoshy case PMC_EV_P6_BUS_TRAN_DEF: 1997145256Sjkoshy case PMC_EV_P6_BUS_TRAN_BURST: 1998145256Sjkoshy case PMC_EV_P6_BUS_TRAN_ANY: 1999145256Sjkoshy case PMC_EV_P6_BUS_TRAN_MEM: 2000145256Sjkoshy P6MASKSET(any); break; 2001145256Sjkoshy case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED: 2002145256Sjkoshy case PMC_EV_P6_EMON_KNI_PREF_MISS: 2003145256Sjkoshy P6MASKSET(ekp); break; 2004145256Sjkoshy case PMC_EV_P6_EMON_KNI_INST_RETIRED: 2005145256Sjkoshy case PMC_EV_P6_EMON_KNI_COMP_INST_RET: 2006145256Sjkoshy P6MASKSET(pps); break; 2007145256Sjkoshy case PMC_EV_P6_MMX_INSTR_TYPE_EXEC: 2008145256Sjkoshy P6MASKSET(mite); break; 2009145256Sjkoshy case PMC_EV_P6_FP_MMX_TRANS: 2010145256Sjkoshy P6MASKSET(fmt); break; 2011145256Sjkoshy case PMC_EV_P6_SEG_RENAME_STALLS: 2012145256Sjkoshy case PMC_EV_P6_SEG_REG_RENAMES: 2013145256Sjkoshy P6MASKSET(sr); break; 2014145256Sjkoshy case PMC_EV_P6_EMON_EST_TRANS: 2015145256Sjkoshy P6MASKSET(eet); break; 2016145256Sjkoshy case PMC_EV_P6_EMON_FUSED_UOPS_RET: 2017145256Sjkoshy P6MASKSET(efur); break; 2018145256Sjkoshy case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED: 2019145256Sjkoshy P6MASKSET(essir); break; 2020145256Sjkoshy case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED: 2021145256Sjkoshy P6MASKSET(esscir); break; 2022145256Sjkoshy default: 2023145256Sjkoshy pmask = NULL; 2024145256Sjkoshy break; 2025145256Sjkoshy } 2026145256Sjkoshy 2027145256Sjkoshy /* Pentium M PMCs have a few events with different semantics */ 2028145256Sjkoshy if (cpu_info.pm_cputype == PMC_CPU_INTEL_PM) { 2029145256Sjkoshy if (pe == PMC_EV_P6_L2_LD || 2030145256Sjkoshy pe == PMC_EV_P6_L2_LINES_IN || 2031145256Sjkoshy pe == PMC_EV_P6_L2_LINES_OUT) 2032145256Sjkoshy P6MASKSET(mesihw); 2033145256Sjkoshy else if (pe == PMC_EV_P6_L2_M_LINES_OUTM) 2034145256Sjkoshy P6MASKSET(hw); 2035145256Sjkoshy } 2036145256Sjkoshy 2037145256Sjkoshy /* Parse additional modifiers if present */ 2038145256Sjkoshy while ((p = strsep(&ctrspec, ",")) != NULL) { 2039145256Sjkoshy if (KWPREFIXMATCH(p, P6_KW_CMASK "=")) { 2040145256Sjkoshy q = strchr(p, '='); 2041145256Sjkoshy if (*++q == '\0') /* skip '=' */ 2042174406Sjkoshy return (-1); 2043145256Sjkoshy count = strtol(q, &e, 0); 2044145256Sjkoshy if (e == q || *e != '\0') 2045174406Sjkoshy return (-1); 2046145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 2047147191Sjkoshy pmc_config->pm_md.pm_ppro.pm_ppro_config |= 2048147191Sjkoshy P6_EVSEL_TO_CMASK(count); 2049145256Sjkoshy } else if (KWMATCH(p, P6_KW_EDGE)) { 2050145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_EDGE; 2051145256Sjkoshy } else if (KWMATCH(p, P6_KW_INV)) { 2052145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_INVERT; 2053145256Sjkoshy } else if (KWMATCH(p, P6_KW_OS)) { 2054145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2055145256Sjkoshy } else if (KWPREFIXMATCH(p, P6_KW_UMASK "=")) { 2056145256Sjkoshy evmask = 0; 2057145256Sjkoshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 2058174406Sjkoshy return (-1); 2059145256Sjkoshy if ((pe == PMC_EV_P6_BUS_DRDY_CLOCKS || 2060145256Sjkoshy pe == PMC_EV_P6_BUS_LOCK_CLOCKS || 2061145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_BRD || 2062145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_RFO || 2063145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_IFETCH || 2064145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_INVAL || 2065145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_PWR || 2066145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_DEF || 2067145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_BURST || 2068145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_ANY || 2069145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_MEM || 2070145256Sjkoshy pe == PMC_EV_P6_BUS_TRANS_IO || 2071145256Sjkoshy pe == PMC_EV_P6_BUS_TRANS_P || 2072145256Sjkoshy pe == PMC_EV_P6_BUS_TRANS_WB || 2073145256Sjkoshy pe == PMC_EV_P6_EMON_EST_TRANS || 2074145256Sjkoshy pe == PMC_EV_P6_EMON_FUSED_UOPS_RET || 2075145256Sjkoshy pe == PMC_EV_P6_EMON_KNI_COMP_INST_RET || 2076145256Sjkoshy pe == PMC_EV_P6_EMON_KNI_INST_RETIRED || 2077145256Sjkoshy pe == PMC_EV_P6_EMON_KNI_PREF_DISPATCHED || 2078145256Sjkoshy pe == PMC_EV_P6_EMON_KNI_PREF_MISS || 2079145256Sjkoshy pe == PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED || 2080145256Sjkoshy pe == PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED || 2081145256Sjkoshy pe == PMC_EV_P6_FP_MMX_TRANS) 2082174406Sjkoshy && (n > 1)) /* Only one mask keyword is allowed. */ 2083174406Sjkoshy return (-1); 2084145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2085145256Sjkoshy } else if (KWMATCH(p, P6_KW_USR)) { 2086145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_USER; 2087145256Sjkoshy } else 2088174406Sjkoshy return (-1); 2089145256Sjkoshy } 2090145256Sjkoshy 2091145256Sjkoshy /* post processing */ 2092145256Sjkoshy switch (pe) { 2093145256Sjkoshy 2094145256Sjkoshy /* 2095145256Sjkoshy * The following events default to an evmask of 0 2096145256Sjkoshy */ 2097145256Sjkoshy 2098145256Sjkoshy /* default => 'self' */ 2099145256Sjkoshy case PMC_EV_P6_BUS_DRDY_CLOCKS: 2100145256Sjkoshy case PMC_EV_P6_BUS_LOCK_CLOCKS: 2101145256Sjkoshy case PMC_EV_P6_BUS_TRAN_BRD: 2102145256Sjkoshy case PMC_EV_P6_BUS_TRAN_RFO: 2103145256Sjkoshy case PMC_EV_P6_BUS_TRANS_WB: 2104145256Sjkoshy case PMC_EV_P6_BUS_TRAN_IFETCH: 2105145256Sjkoshy case PMC_EV_P6_BUS_TRAN_INVAL: 2106145256Sjkoshy case PMC_EV_P6_BUS_TRAN_PWR: 2107145256Sjkoshy case PMC_EV_P6_BUS_TRANS_P: 2108145256Sjkoshy case PMC_EV_P6_BUS_TRANS_IO: 2109145256Sjkoshy case PMC_EV_P6_BUS_TRAN_DEF: 2110145256Sjkoshy case PMC_EV_P6_BUS_TRAN_BURST: 2111145256Sjkoshy case PMC_EV_P6_BUS_TRAN_ANY: 2112145256Sjkoshy case PMC_EV_P6_BUS_TRAN_MEM: 2113145256Sjkoshy 2114145256Sjkoshy /* default => 'nta' */ 2115145256Sjkoshy case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED: 2116145256Sjkoshy case PMC_EV_P6_EMON_KNI_PREF_MISS: 2117145256Sjkoshy 2118145256Sjkoshy /* default => 'packed and scalar' */ 2119145256Sjkoshy case PMC_EV_P6_EMON_KNI_INST_RETIRED: 2120145256Sjkoshy case PMC_EV_P6_EMON_KNI_COMP_INST_RET: 2121145256Sjkoshy 2122145256Sjkoshy /* default => 'mmx to fp transitions' */ 2123145256Sjkoshy case PMC_EV_P6_FP_MMX_TRANS: 2124145256Sjkoshy 2125145256Sjkoshy /* default => 'SSE Packed Single' */ 2126145256Sjkoshy case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED: 2127145256Sjkoshy case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED: 2128145256Sjkoshy 2129145256Sjkoshy /* default => 'all fused micro-ops' */ 2130145256Sjkoshy case PMC_EV_P6_EMON_FUSED_UOPS_RET: 2131145256Sjkoshy 2132145256Sjkoshy /* default => 'all transitions' */ 2133145256Sjkoshy case PMC_EV_P6_EMON_EST_TRANS: 2134145256Sjkoshy break; 2135145256Sjkoshy 2136145256Sjkoshy case PMC_EV_P6_MMX_UOPS_EXEC: 2137145256Sjkoshy evmask = 0x0F; /* only value allowed */ 2138145256Sjkoshy break; 2139145256Sjkoshy 2140145256Sjkoshy default: 2141145256Sjkoshy /* 2142145256Sjkoshy * For all other events, set the default event mask 2143145256Sjkoshy * to a logical OR of all the allowed event mask bits. 2144145256Sjkoshy */ 2145145256Sjkoshy if (evmask == 0 && pmask) { 2146145256Sjkoshy for (pm = pmask; pm->pm_name; pm++) 2147145256Sjkoshy evmask |= pm->pm_value; 2148145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2149145256Sjkoshy } 2150145256Sjkoshy 2151145256Sjkoshy break; 2152145256Sjkoshy } 2153145256Sjkoshy 2154145256Sjkoshy if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) 2155147191Sjkoshy pmc_config->pm_md.pm_ppro.pm_ppro_config |= 2156147191Sjkoshy P6_EVSEL_TO_UMASK(evmask); 2157145256Sjkoshy 2158174406Sjkoshy return (0); 2159145256Sjkoshy} 2160145256Sjkoshy 2161147191Sjkoshy#endif 2162147191Sjkoshy 2163183725Sjkoshy#if defined(__i386__) || defined(__amd64__) 2164183725Sjkoshystatic int 2165183725Sjkoshytsc_allocate_pmc(enum pmc_event pe, char *ctrspec, 2166183725Sjkoshy struct pmc_op_pmcallocate *pmc_config) 2167183725Sjkoshy{ 2168183725Sjkoshy if (pe != PMC_EV_TSC_TSC) 2169183725Sjkoshy return (-1); 2170183725Sjkoshy 2171183725Sjkoshy /* TSC events must be unqualified. */ 2172183725Sjkoshy if (ctrspec && *ctrspec != '\0') 2173183725Sjkoshy return (-1); 2174183725Sjkoshy 2175183725Sjkoshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 2176183725Sjkoshy pmc_config->pm_caps |= PMC_CAP_READ; 2177183725Sjkoshy 2178183725Sjkoshy return (0); 2179183725Sjkoshy} 2180183725Sjkoshy#endif 2181183725Sjkoshy 2182200928Srpaulo#if defined(__XSCALE__) 2183200928Srpaulo 2184200928Srpaulostatic struct pmc_event_alias xscale_aliases[] = { 2185200928Srpaulo EV_ALIAS("branches", "BRANCH_RETIRED"), 2186200928Srpaulo EV_ALIAS("branch-mispredicts", "BRANCH_MISPRED"), 2187200928Srpaulo EV_ALIAS("dc-misses", "DC_MISS"), 2188200928Srpaulo EV_ALIAS("ic-misses", "IC_MISS"), 2189200928Srpaulo EV_ALIAS("instructions", "INSTR_RETIRED"), 2190200928Srpaulo EV_ALIAS(NULL, NULL) 2191200928Srpaulo}; 2192200928Srpaulostatic int 2193200928Srpauloxscale_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 2194200928Srpaulo struct pmc_op_pmcallocate *pmc_config __unused) 2195200928Srpaulo{ 2196200928Srpaulo switch (pe) { 2197200928Srpaulo default: 2198200928Srpaulo break; 2199200928Srpaulo } 2200200928Srpaulo 2201200928Srpaulo return (0); 2202200928Srpaulo} 2203200928Srpaulo#endif 2204200928Srpaulo 2205204635Sgnn#if defined(__mips__) 2206204635Sgnn 2207204635Sgnnstatic struct pmc_event_alias mips24k_aliases[] = { 2208204635Sgnn EV_ALIAS("instructions", "INSTR_EXECUTED"), 2209204635Sgnn EV_ALIAS("branches", "BRANCH_COMPLETED"), 2210204635Sgnn EV_ALIAS("branch-mispredicts", "BRANCH_MISPRED"), 2211204635Sgnn EV_ALIAS(NULL, NULL) 2212204635Sgnn}; 2213204635Sgnn 2214233335Sgonzostatic struct pmc_event_alias octeon_aliases[] = { 2215233335Sgonzo EV_ALIAS("instructions", "RET"), 2216233335Sgonzo EV_ALIAS("branches", "BR"), 2217233335Sgonzo EV_ALIAS("branch-mispredicts", "BRMIS"), 2218233335Sgonzo EV_ALIAS(NULL, NULL) 2219233335Sgonzo}; 2220233335Sgonzo 2221233320Sgonzo#define MIPS_KW_OS "os" 2222233320Sgonzo#define MIPS_KW_USR "usr" 2223233320Sgonzo#define MIPS_KW_ANYTHREAD "anythread" 2224204635Sgnn 2225204635Sgnnstatic int 2226233320Sgonzomips_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 2227204635Sgnn struct pmc_op_pmcallocate *pmc_config __unused) 2228204635Sgnn{ 2229204635Sgnn char *p; 2230204635Sgnn 2231204635Sgnn (void) pe; 2232204635Sgnn 2233204635Sgnn pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2234204635Sgnn 2235204635Sgnn while ((p = strsep(&ctrspec, ",")) != NULL) { 2236233320Sgonzo if (KWMATCH(p, MIPS_KW_OS)) 2237204635Sgnn pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2238233320Sgonzo else if (KWMATCH(p, MIPS_KW_USR)) 2239204635Sgnn pmc_config->pm_caps |= PMC_CAP_USER; 2240233320Sgonzo else if (KWMATCH(p, MIPS_KW_ANYTHREAD)) 2241204635Sgnn pmc_config->pm_caps |= (PMC_CAP_USER | PMC_CAP_SYSTEM); 2242204635Sgnn else 2243204635Sgnn return (-1); 2244204635Sgnn } 2245204635Sgnn 2246204635Sgnn return (0); 2247204635Sgnn} 2248233320Sgonzo 2249204635Sgnn#endif /* __mips__ */ 2250204635Sgnn 2251228869Sjhibbits#if defined(__powerpc__) 2252204635Sgnn 2253228869Sjhibbitsstatic struct pmc_event_alias ppc7450_aliases[] = { 2254228869Sjhibbits EV_ALIAS("instructions", "INSTR_COMPLETED"), 2255228869Sjhibbits EV_ALIAS("branches", "BRANCHES_COMPLETED"), 2256228869Sjhibbits EV_ALIAS("branch-mispredicts", "MISPREDICTED_BRANCHES"), 2257228869Sjhibbits EV_ALIAS(NULL, NULL) 2258228869Sjhibbits}; 2259228869Sjhibbits 2260228869Sjhibbits#define PPC7450_KW_OS "os" 2261228869Sjhibbits#define PPC7450_KW_USR "usr" 2262228869Sjhibbits#define PPC7450_KW_ANYTHREAD "anythread" 2263228869Sjhibbits 2264228869Sjhibbitsstatic int 2265228869Sjhibbitsppc7450_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 2266228869Sjhibbits struct pmc_op_pmcallocate *pmc_config __unused) 2267228869Sjhibbits{ 2268228869Sjhibbits char *p; 2269228869Sjhibbits 2270228869Sjhibbits (void) pe; 2271228869Sjhibbits 2272228869Sjhibbits pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2273228869Sjhibbits 2274228869Sjhibbits while ((p = strsep(&ctrspec, ",")) != NULL) { 2275228869Sjhibbits if (KWMATCH(p, PPC7450_KW_OS)) 2276228869Sjhibbits pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2277228869Sjhibbits else if (KWMATCH(p, PPC7450_KW_USR)) 2278228869Sjhibbits pmc_config->pm_caps |= PMC_CAP_USER; 2279228869Sjhibbits else if (KWMATCH(p, PPC7450_KW_ANYTHREAD)) 2280228869Sjhibbits pmc_config->pm_caps |= (PMC_CAP_USER | PMC_CAP_SYSTEM); 2281228869Sjhibbits else 2282228869Sjhibbits return (-1); 2283228869Sjhibbits } 2284228869Sjhibbits 2285228869Sjhibbits return (0); 2286228869Sjhibbits} 2287228869Sjhibbits#endif /* __powerpc__ */ 2288228869Sjhibbits 2289228869Sjhibbits 2290145256Sjkoshy/* 2291183725Sjkoshy * Match an event name `name' with its canonical form. 2292183725Sjkoshy * 2293185363Sjkoshy * Matches are case insensitive and spaces, periods, underscores and 2294185363Sjkoshy * hyphen characters are considered to match each other. 2295185363Sjkoshy * 2296183725Sjkoshy * Returns 1 for a match, 0 otherwise. 2297183725Sjkoshy */ 2298183725Sjkoshy 2299183725Sjkoshystatic int 2300183725Sjkoshypmc_match_event_name(const char *name, const char *canonicalname) 2301183725Sjkoshy{ 2302183725Sjkoshy int cc, nc; 2303183725Sjkoshy const unsigned char *c, *n; 2304183725Sjkoshy 2305183725Sjkoshy c = (const unsigned char *) canonicalname; 2306183725Sjkoshy n = (const unsigned char *) name; 2307183725Sjkoshy 2308183725Sjkoshy for (; (nc = *n) && (cc = *c); n++, c++) { 2309183725Sjkoshy 2310185363Sjkoshy if ((nc == ' ' || nc == '_' || nc == '-' || nc == '.') && 2311185363Sjkoshy (cc == ' ' || cc == '_' || cc == '-' || cc == '.')) 2312183725Sjkoshy continue; 2313183725Sjkoshy 2314185363Sjkoshy if (toupper(nc) == toupper(cc)) 2315183725Sjkoshy continue; 2316183725Sjkoshy 2317185363Sjkoshy 2318183725Sjkoshy return (0); 2319183725Sjkoshy } 2320183725Sjkoshy 2321183725Sjkoshy if (*n == '\0' && *c == '\0') 2322183725Sjkoshy return (1); 2323183725Sjkoshy 2324183725Sjkoshy return (0); 2325183725Sjkoshy} 2326183725Sjkoshy 2327183725Sjkoshy/* 2328183725Sjkoshy * Match an event name against all the event named supported by a 2329183725Sjkoshy * PMC class. 2330183725Sjkoshy * 2331183725Sjkoshy * Returns an event descriptor pointer on match or NULL otherwise. 2332183725Sjkoshy */ 2333183725Sjkoshystatic const struct pmc_event_descr * 2334183725Sjkoshypmc_match_event_class(const char *name, 2335183725Sjkoshy const struct pmc_class_descr *pcd) 2336183725Sjkoshy{ 2337183725Sjkoshy size_t n; 2338183725Sjkoshy const struct pmc_event_descr *ev; 2339185363Sjkoshy 2340183725Sjkoshy ev = pcd->pm_evc_event_table; 2341183725Sjkoshy for (n = 0; n < pcd->pm_evc_event_table_size; n++, ev++) 2342183725Sjkoshy if (pmc_match_event_name(name, ev->pm_ev_name)) 2343183725Sjkoshy return (ev); 2344183725Sjkoshy 2345183725Sjkoshy return (NULL); 2346183725Sjkoshy} 2347183725Sjkoshy 2348183725Sjkoshystatic int 2349183725Sjkoshypmc_mdep_is_compatible_class(enum pmc_class pc) 2350183725Sjkoshy{ 2351183725Sjkoshy size_t n; 2352183725Sjkoshy 2353183725Sjkoshy for (n = 0; n < pmc_mdep_class_list_size; n++) 2354183725Sjkoshy if (pmc_mdep_class_list[n] == pc) 2355183725Sjkoshy return (1); 2356183725Sjkoshy return (0); 2357183725Sjkoshy} 2358183725Sjkoshy 2359183725Sjkoshy/* 2360147191Sjkoshy * API entry points 2361145256Sjkoshy */ 2362145256Sjkoshy 2363147191Sjkoshyint 2364147191Sjkoshypmc_allocate(const char *ctrspec, enum pmc_mode mode, 2365147191Sjkoshy uint32_t flags, int cpu, pmc_id_t *pmcid) 2366145256Sjkoshy{ 2367183725Sjkoshy size_t n; 2368147191Sjkoshy int retval; 2369147191Sjkoshy char *r, *spec_copy; 2370147191Sjkoshy const char *ctrname; 2371183725Sjkoshy const struct pmc_event_descr *ev; 2372183725Sjkoshy const struct pmc_event_alias *alias; 2373147191Sjkoshy struct pmc_op_pmcallocate pmc_config; 2374183725Sjkoshy const struct pmc_class_descr *pcd; 2375145256Sjkoshy 2376147191Sjkoshy spec_copy = NULL; 2377147191Sjkoshy retval = -1; 2378145256Sjkoshy 2379147191Sjkoshy if (mode != PMC_MODE_SS && mode != PMC_MODE_TS && 2380147191Sjkoshy mode != PMC_MODE_SC && mode != PMC_MODE_TC) { 2381147191Sjkoshy errno = EINVAL; 2382147191Sjkoshy goto out; 2383147191Sjkoshy } 2384145256Sjkoshy 2385147191Sjkoshy /* replace an event alias with the canonical event specifier */ 2386147191Sjkoshy if (pmc_mdep_event_aliases) 2387183725Sjkoshy for (alias = pmc_mdep_event_aliases; alias->pm_alias; alias++) 2388183725Sjkoshy if (!strcasecmp(ctrspec, alias->pm_alias)) { 2389183725Sjkoshy spec_copy = strdup(alias->pm_spec); 2390147191Sjkoshy break; 2391147191Sjkoshy } 2392145256Sjkoshy 2393147191Sjkoshy if (spec_copy == NULL) 2394147191Sjkoshy spec_copy = strdup(ctrspec); 2395145256Sjkoshy 2396147191Sjkoshy r = spec_copy; 2397147191Sjkoshy ctrname = strsep(&r, ","); 2398145256Sjkoshy 2399183725Sjkoshy /* 2400183725Sjkoshy * If a explicit class prefix was given by the user, restrict the 2401183725Sjkoshy * search for the event to the specified PMC class. 2402183725Sjkoshy */ 2403183725Sjkoshy ev = NULL; 2404185363Sjkoshy for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) { 2405185363Sjkoshy pcd = pmc_class_table[n]; 2406183725Sjkoshy if (pmc_mdep_is_compatible_class(pcd->pm_evc_class) && 2407183725Sjkoshy strncasecmp(ctrname, pcd->pm_evc_name, 2408183725Sjkoshy pcd->pm_evc_name_size) == 0) { 2409183725Sjkoshy if ((ev = pmc_match_event_class(ctrname + 2410183725Sjkoshy pcd->pm_evc_name_size, pcd)) == NULL) { 2411183725Sjkoshy errno = EINVAL; 2412183725Sjkoshy goto out; 2413183725Sjkoshy } 2414147191Sjkoshy break; 2415183725Sjkoshy } 2416183725Sjkoshy } 2417145256Sjkoshy 2418183725Sjkoshy /* 2419183725Sjkoshy * Otherwise, search for this event in all compatible PMC 2420183725Sjkoshy * classes. 2421183725Sjkoshy */ 2422185363Sjkoshy for (n = 0; ev == NULL && n < PMC_CLASS_TABLE_SIZE; n++) { 2423185363Sjkoshy pcd = pmc_class_table[n]; 2424183725Sjkoshy if (pmc_mdep_is_compatible_class(pcd->pm_evc_class)) 2425183725Sjkoshy ev = pmc_match_event_class(ctrname, pcd); 2426183725Sjkoshy } 2427183725Sjkoshy 2428183725Sjkoshy if (ev == NULL) { 2429147191Sjkoshy errno = EINVAL; 2430147191Sjkoshy goto out; 2431147191Sjkoshy } 2432145256Sjkoshy 2433147191Sjkoshy bzero(&pmc_config, sizeof(pmc_config)); 2434183725Sjkoshy pmc_config.pm_ev = ev->pm_ev_code; 2435183725Sjkoshy pmc_config.pm_class = pcd->pm_evc_class; 2436147191Sjkoshy pmc_config.pm_cpu = cpu; 2437147191Sjkoshy pmc_config.pm_mode = mode; 2438147191Sjkoshy pmc_config.pm_flags = flags; 2439145256Sjkoshy 2440147191Sjkoshy if (PMC_IS_SAMPLING_MODE(mode)) 2441147191Sjkoshy pmc_config.pm_caps |= PMC_CAP_INTERRUPT; 2442145256Sjkoshy 2443183725Sjkoshy if (pcd->pm_evc_allocate_pmc(ev->pm_ev_code, r, &pmc_config) < 0) { 2444147191Sjkoshy errno = EINVAL; 2445147191Sjkoshy goto out; 2446147191Sjkoshy } 2447145256Sjkoshy 2448147191Sjkoshy if (PMC_CALL(PMCALLOCATE, &pmc_config) < 0) 2449147191Sjkoshy goto out; 2450145256Sjkoshy 2451147191Sjkoshy *pmcid = pmc_config.pm_pmcid; 2452145256Sjkoshy 2453147191Sjkoshy retval = 0; 2454145256Sjkoshy 2455147191Sjkoshy out: 2456147191Sjkoshy if (spec_copy) 2457147191Sjkoshy free(spec_copy); 2458145256Sjkoshy 2459174406Sjkoshy return (retval); 2460147191Sjkoshy} 2461145256Sjkoshy 2462147191Sjkoshyint 2463147191Sjkoshypmc_attach(pmc_id_t pmc, pid_t pid) 2464147191Sjkoshy{ 2465147191Sjkoshy struct pmc_op_pmcattach pmc_attach_args; 2466145256Sjkoshy 2467147191Sjkoshy pmc_attach_args.pm_pmc = pmc; 2468147191Sjkoshy pmc_attach_args.pm_pid = pid; 2469145256Sjkoshy 2470174406Sjkoshy return (PMC_CALL(PMCATTACH, &pmc_attach_args)); 2471147191Sjkoshy} 2472145256Sjkoshy 2473147191Sjkoshyint 2474147191Sjkoshypmc_capabilities(pmc_id_t pmcid, uint32_t *caps) 2475147191Sjkoshy{ 2476147191Sjkoshy unsigned int i; 2477147191Sjkoshy enum pmc_class cl; 2478145256Sjkoshy 2479147191Sjkoshy cl = PMC_ID_TO_CLASS(pmcid); 2480147191Sjkoshy for (i = 0; i < cpu_info.pm_nclass; i++) 2481147191Sjkoshy if (cpu_info.pm_classes[i].pm_class == cl) { 2482147191Sjkoshy *caps = cpu_info.pm_classes[i].pm_caps; 2483174406Sjkoshy return (0); 2484147191Sjkoshy } 2485177107Sjkoshy errno = EINVAL; 2486177107Sjkoshy return (-1); 2487147191Sjkoshy} 2488145256Sjkoshy 2489147191Sjkoshyint 2490147191Sjkoshypmc_configure_logfile(int fd) 2491147191Sjkoshy{ 2492147191Sjkoshy struct pmc_op_configurelog cla; 2493145256Sjkoshy 2494147191Sjkoshy cla.pm_logfd = fd; 2495147191Sjkoshy if (PMC_CALL(CONFIGURELOG, &cla) < 0) 2496174406Sjkoshy return (-1); 2497174406Sjkoshy return (0); 2498147191Sjkoshy} 2499145256Sjkoshy 2500147191Sjkoshyint 2501147191Sjkoshypmc_cpuinfo(const struct pmc_cpuinfo **pci) 2502147191Sjkoshy{ 2503147191Sjkoshy if (pmc_syscall == -1) { 2504147191Sjkoshy errno = ENXIO; 2505174406Sjkoshy return (-1); 2506147191Sjkoshy } 2507145256Sjkoshy 2508147219Sjkoshy *pci = &cpu_info; 2509174406Sjkoshy return (0); 2510147191Sjkoshy} 2511145256Sjkoshy 2512147191Sjkoshyint 2513147191Sjkoshypmc_detach(pmc_id_t pmc, pid_t pid) 2514147191Sjkoshy{ 2515147191Sjkoshy struct pmc_op_pmcattach pmc_detach_args; 2516145256Sjkoshy 2517147191Sjkoshy pmc_detach_args.pm_pmc = pmc; 2518147191Sjkoshy pmc_detach_args.pm_pid = pid; 2519174406Sjkoshy return (PMC_CALL(PMCDETACH, &pmc_detach_args)); 2520147191Sjkoshy} 2521147191Sjkoshy 2522147191Sjkoshyint 2523147191Sjkoshypmc_disable(int cpu, int pmc) 2524145256Sjkoshy{ 2525147191Sjkoshy struct pmc_op_pmcadmin ssa; 2526145256Sjkoshy 2527147191Sjkoshy ssa.pm_cpu = cpu; 2528147191Sjkoshy ssa.pm_pmc = pmc; 2529147191Sjkoshy ssa.pm_state = PMC_STATE_DISABLED; 2530174406Sjkoshy return (PMC_CALL(PMCADMIN, &ssa)); 2531147191Sjkoshy} 2532145256Sjkoshy 2533147191Sjkoshyint 2534147191Sjkoshypmc_enable(int cpu, int pmc) 2535147191Sjkoshy{ 2536147191Sjkoshy struct pmc_op_pmcadmin ssa; 2537145256Sjkoshy 2538147191Sjkoshy ssa.pm_cpu = cpu; 2539147191Sjkoshy ssa.pm_pmc = pmc; 2540147191Sjkoshy ssa.pm_state = PMC_STATE_FREE; 2541174406Sjkoshy return (PMC_CALL(PMCADMIN, &ssa)); 2542147191Sjkoshy} 2543145256Sjkoshy 2544147191Sjkoshy/* 2545147191Sjkoshy * Return a list of events known to a given PMC class. 'cl' is the 2546147191Sjkoshy * PMC class identifier, 'eventnames' is the returned list of 'const 2547147191Sjkoshy * char *' pointers pointing to the names of the events. 'nevents' is 2548147191Sjkoshy * the number of event name pointers returned. 2549147191Sjkoshy * 2550147191Sjkoshy * The space for 'eventnames' is allocated using malloc(3). The caller 2551147191Sjkoshy * is responsible for freeing this space when done. 2552147191Sjkoshy */ 2553147191Sjkoshyint 2554147191Sjkoshypmc_event_names_of_class(enum pmc_class cl, const char ***eventnames, 2555147191Sjkoshy int *nevents) 2556147191Sjkoshy{ 2557147191Sjkoshy int count; 2558147191Sjkoshy const char **names; 2559147191Sjkoshy const struct pmc_event_descr *ev; 2560147191Sjkoshy 2561147191Sjkoshy switch (cl) 2562147191Sjkoshy { 2563185363Sjkoshy case PMC_CLASS_IAF: 2564185363Sjkoshy ev = iaf_event_table; 2565185363Sjkoshy count = PMC_EVENT_TABLE_SIZE(iaf); 2566185363Sjkoshy break; 2567185363Sjkoshy case PMC_CLASS_IAP: 2568185363Sjkoshy /* 2569185363Sjkoshy * Return the most appropriate set of event name 2570185363Sjkoshy * spellings for the current CPU. 2571185363Sjkoshy */ 2572185363Sjkoshy switch (cpu_info.pm_cputype) { 2573185363Sjkoshy default: 2574185363Sjkoshy case PMC_CPU_INTEL_ATOM: 2575185363Sjkoshy ev = atom_event_table; 2576185363Sjkoshy count = PMC_EVENT_TABLE_SIZE(atom); 2577185363Sjkoshy break; 2578185363Sjkoshy case PMC_CPU_INTEL_CORE: 2579185363Sjkoshy ev = core_event_table; 2580185363Sjkoshy count = PMC_EVENT_TABLE_SIZE(core); 2581185363Sjkoshy break; 2582185363Sjkoshy case PMC_CPU_INTEL_CORE2: 2583185585Sjkoshy case PMC_CPU_INTEL_CORE2EXTREME: 2584185363Sjkoshy ev = core2_event_table; 2585185363Sjkoshy count = PMC_EVENT_TABLE_SIZE(core2); 2586185363Sjkoshy break; 2587187761Sjeff case PMC_CPU_INTEL_COREI7: 2588187761Sjeff ev = corei7_event_table; 2589187761Sjeff count = PMC_EVENT_TABLE_SIZE(corei7); 2590187761Sjeff break; 2591232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 2592232366Sdavide ev = sandybridge_event_table; 2593232366Sdavide count = PMC_EVENT_TABLE_SIZE(sandybridge); 2594232366Sdavide break; 2595206089Sfabient case PMC_CPU_INTEL_WESTMERE: 2596206089Sfabient ev = westmere_event_table; 2597206089Sfabient count = PMC_EVENT_TABLE_SIZE(westmere); 2598206089Sfabient break; 2599185363Sjkoshy } 2600185363Sjkoshy break; 2601206089Sfabient case PMC_CLASS_UCF: 2602206089Sfabient ev = ucf_event_table; 2603206089Sfabient count = PMC_EVENT_TABLE_SIZE(ucf); 2604206089Sfabient break; 2605206089Sfabient case PMC_CLASS_UCP: 2606206089Sfabient /* 2607206089Sfabient * Return the most appropriate set of event name 2608206089Sfabient * spellings for the current CPU. 2609206089Sfabient */ 2610206089Sfabient switch (cpu_info.pm_cputype) { 2611206089Sfabient default: 2612206089Sfabient case PMC_CPU_INTEL_COREI7: 2613206089Sfabient ev = corei7uc_event_table; 2614206089Sfabient count = PMC_EVENT_TABLE_SIZE(corei7uc); 2615206089Sfabient break; 2616232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 2617232366Sdavide ev = sandybridgeuc_event_table; 2618232366Sdavide count = PMC_EVENT_TABLE_SIZE(sandybridgeuc); 2619232366Sdavide break; 2620206089Sfabient case PMC_CPU_INTEL_WESTMERE: 2621206089Sfabient ev = westmereuc_event_table; 2622206089Sfabient count = PMC_EVENT_TABLE_SIZE(westmereuc); 2623206089Sfabient break; 2624206089Sfabient } 2625206089Sfabient break; 2626147191Sjkoshy case PMC_CLASS_TSC: 2627183725Sjkoshy ev = tsc_event_table; 2628183725Sjkoshy count = PMC_EVENT_TABLE_SIZE(tsc); 2629145256Sjkoshy break; 2630147191Sjkoshy case PMC_CLASS_K7: 2631183725Sjkoshy ev = k7_event_table; 2632183725Sjkoshy count = PMC_EVENT_TABLE_SIZE(k7); 2633145256Sjkoshy break; 2634147191Sjkoshy case PMC_CLASS_K8: 2635183725Sjkoshy ev = k8_event_table; 2636183725Sjkoshy count = PMC_EVENT_TABLE_SIZE(k8); 2637145256Sjkoshy break; 2638183725Sjkoshy case PMC_CLASS_P4: 2639183725Sjkoshy ev = p4_event_table; 2640183725Sjkoshy count = PMC_EVENT_TABLE_SIZE(p4); 2641183725Sjkoshy break; 2642147191Sjkoshy case PMC_CLASS_P5: 2643183725Sjkoshy ev = p5_event_table; 2644183725Sjkoshy count = PMC_EVENT_TABLE_SIZE(p5); 2645145256Sjkoshy break; 2646147191Sjkoshy case PMC_CLASS_P6: 2647183725Sjkoshy ev = p6_event_table; 2648183725Sjkoshy count = PMC_EVENT_TABLE_SIZE(p6); 2649145256Sjkoshy break; 2650200928Srpaulo case PMC_CLASS_XSCALE: 2651200928Srpaulo ev = xscale_event_table; 2652200928Srpaulo count = PMC_EVENT_TABLE_SIZE(xscale); 2653200928Srpaulo break; 2654204635Sgnn case PMC_CLASS_MIPS24K: 2655204635Sgnn ev = mips24k_event_table; 2656204635Sgnn count = PMC_EVENT_TABLE_SIZE(mips24k); 2657204635Sgnn break; 2658233335Sgonzo case PMC_CLASS_OCTEON: 2659233335Sgonzo ev = octeon_event_table; 2660233335Sgonzo count = PMC_EVENT_TABLE_SIZE(octeon); 2661233335Sgonzo break; 2662228869Sjhibbits case PMC_CLASS_PPC7450: 2663228869Sjhibbits ev = ppc7450_event_table; 2664228869Sjhibbits count = PMC_EVENT_TABLE_SIZE(ppc7450); 2665228869Sjhibbits break; 2666145256Sjkoshy default: 2667147191Sjkoshy errno = EINVAL; 2668174406Sjkoshy return (-1); 2669145256Sjkoshy } 2670145256Sjkoshy 2671147191Sjkoshy if ((names = malloc(count * sizeof(const char *))) == NULL) 2672174406Sjkoshy return (-1); 2673145256Sjkoshy 2674147191Sjkoshy *eventnames = names; 2675147191Sjkoshy *nevents = count; 2676145256Sjkoshy 2677147191Sjkoshy for (;count--; ev++, names++) 2678147191Sjkoshy *names = ev->pm_ev_name; 2679174406Sjkoshy return (0); 2680147191Sjkoshy} 2681145256Sjkoshy 2682147191Sjkoshyint 2683147191Sjkoshypmc_flush_logfile(void) 2684147191Sjkoshy{ 2685174406Sjkoshy return (PMC_CALL(FLUSHLOG,0)); 2686147191Sjkoshy} 2687145256Sjkoshy 2688147191Sjkoshyint 2689226514Sfabientpmc_close_logfile(void) 2690226514Sfabient{ 2691226514Sfabient return (PMC_CALL(CLOSELOG,0)); 2692226514Sfabient} 2693226514Sfabient 2694226514Sfabientint 2695147191Sjkoshypmc_get_driver_stats(struct pmc_driverstats *ds) 2696147191Sjkoshy{ 2697147191Sjkoshy struct pmc_op_getdriverstats gms; 2698145256Sjkoshy 2699147191Sjkoshy if (PMC_CALL(GETDRIVERSTATS, &gms) < 0) 2700174406Sjkoshy return (-1); 2701145256Sjkoshy 2702147191Sjkoshy /* copy out fields in the current userland<->library interface */ 2703147191Sjkoshy ds->pm_intr_ignored = gms.pm_intr_ignored; 2704147191Sjkoshy ds->pm_intr_processed = gms.pm_intr_processed; 2705147191Sjkoshy ds->pm_intr_bufferfull = gms.pm_intr_bufferfull; 2706147191Sjkoshy ds->pm_syscalls = gms.pm_syscalls; 2707147191Sjkoshy ds->pm_syscall_errors = gms.pm_syscall_errors; 2708147191Sjkoshy ds->pm_buffer_requests = gms.pm_buffer_requests; 2709147191Sjkoshy ds->pm_buffer_requests_failed = gms.pm_buffer_requests_failed; 2710147191Sjkoshy ds->pm_log_sweeps = gms.pm_log_sweeps; 2711174406Sjkoshy return (0); 2712147191Sjkoshy} 2713145256Sjkoshy 2714147191Sjkoshyint 2715147191Sjkoshypmc_get_msr(pmc_id_t pmc, uint32_t *msr) 2716147191Sjkoshy{ 2717147191Sjkoshy struct pmc_op_getmsr gm; 2718147191Sjkoshy 2719147191Sjkoshy gm.pm_pmcid = pmc; 2720147191Sjkoshy if (PMC_CALL(PMCGETMSR, &gm) < 0) 2721174406Sjkoshy return (-1); 2722147191Sjkoshy *msr = gm.pm_msr; 2723174406Sjkoshy return (0); 2724145256Sjkoshy} 2725145256Sjkoshy 2726145256Sjkoshyint 2727145256Sjkoshypmc_init(void) 2728145256Sjkoshy{ 2729145256Sjkoshy int error, pmc_mod_id; 2730147219Sjkoshy unsigned int n; 2731145256Sjkoshy uint32_t abi_version; 2732145256Sjkoshy struct module_stat pmc_modstat; 2733147219Sjkoshy struct pmc_op_getcpuinfo op_cpu_info; 2734198433Sjkoshy#if defined(__amd64__) || defined(__i386__) 2735198433Sjkoshy int cpu_has_iaf_counters; 2736198433Sjkoshy unsigned int t; 2737198433Sjkoshy#endif 2738145256Sjkoshy 2739145256Sjkoshy if (pmc_syscall != -1) /* already inited */ 2740174406Sjkoshy return (0); 2741145256Sjkoshy 2742145256Sjkoshy /* retrieve the system call number from the KLD */ 2743145256Sjkoshy if ((pmc_mod_id = modfind(PMC_MODULE_NAME)) < 0) 2744174406Sjkoshy return (-1); 2745145256Sjkoshy 2746145256Sjkoshy pmc_modstat.version = sizeof(struct module_stat); 2747145256Sjkoshy if ((error = modstat(pmc_mod_id, &pmc_modstat)) < 0) 2748174406Sjkoshy return (-1); 2749145256Sjkoshy 2750145256Sjkoshy pmc_syscall = pmc_modstat.data.intval; 2751145256Sjkoshy 2752147191Sjkoshy /* check the kernel module's ABI against our compiled-in version */ 2753147191Sjkoshy abi_version = PMC_VERSION; 2754145256Sjkoshy if (PMC_CALL(GETMODULEVERSION, &abi_version) < 0) 2755145256Sjkoshy return (pmc_syscall = -1); 2756145256Sjkoshy 2757147191Sjkoshy /* ignore patch & minor numbers for the comparision */ 2758147191Sjkoshy if ((abi_version & 0xFF000000) != (PMC_VERSION & 0xFF000000)) { 2759145256Sjkoshy errno = EPROGMISMATCH; 2760145256Sjkoshy return (pmc_syscall = -1); 2761145256Sjkoshy } 2762145256Sjkoshy 2763147219Sjkoshy if (PMC_CALL(GETCPUINFO, &op_cpu_info) < 0) 2764145256Sjkoshy return (pmc_syscall = -1); 2765145256Sjkoshy 2766147219Sjkoshy cpu_info.pm_cputype = op_cpu_info.pm_cputype; 2767147219Sjkoshy cpu_info.pm_ncpu = op_cpu_info.pm_ncpu; 2768147219Sjkoshy cpu_info.pm_npmc = op_cpu_info.pm_npmc; 2769147219Sjkoshy cpu_info.pm_nclass = op_cpu_info.pm_nclass; 2770147219Sjkoshy for (n = 0; n < cpu_info.pm_nclass; n++) 2771147219Sjkoshy cpu_info.pm_classes[n] = op_cpu_info.pm_classes[n]; 2772147219Sjkoshy 2773185363Sjkoshy pmc_class_table = malloc(PMC_CLASS_TABLE_SIZE * 2774185363Sjkoshy sizeof(struct pmc_class_descr *)); 2775185363Sjkoshy 2776185363Sjkoshy if (pmc_class_table == NULL) 2777185363Sjkoshy return (-1); 2778185363Sjkoshy 2779198433Sjkoshy for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) 2780198433Sjkoshy pmc_class_table[n] = NULL; 2781185363Sjkoshy 2782185363Sjkoshy /* 2783185363Sjkoshy * Fill in the class table. 2784185363Sjkoshy */ 2785185363Sjkoshy n = 0; 2786185363Sjkoshy#if defined(__amd64__) || defined(__i386__) 2787185363Sjkoshy pmc_class_table[n++] = &tsc_class_table_descr; 2788198433Sjkoshy 2789198433Sjkoshy /* 2790198433Sjkoshy * Check if this CPU has fixed function counters. 2791198433Sjkoshy */ 2792198433Sjkoshy cpu_has_iaf_counters = 0; 2793198433Sjkoshy for (t = 0; t < cpu_info.pm_nclass; t++) 2794212224Sfabient if (cpu_info.pm_classes[t].pm_class == PMC_CLASS_IAF && 2795212224Sfabient cpu_info.pm_classes[t].pm_num > 0) 2796198433Sjkoshy cpu_has_iaf_counters = 1; 2797185363Sjkoshy#endif 2798185363Sjkoshy 2799183725Sjkoshy#define PMC_MDEP_INIT(C) do { \ 2800183725Sjkoshy pmc_mdep_event_aliases = C##_aliases; \ 2801183725Sjkoshy pmc_mdep_class_list = C##_pmc_classes; \ 2802183725Sjkoshy pmc_mdep_class_list_size = \ 2803183725Sjkoshy PMC_TABLE_SIZE(C##_pmc_classes); \ 2804183725Sjkoshy } while (0) 2805183725Sjkoshy 2806198433Sjkoshy#define PMC_MDEP_INIT_INTEL_V2(C) do { \ 2807198433Sjkoshy PMC_MDEP_INIT(C); \ 2808212224Sfabient pmc_class_table[n++] = &iaf_class_table_descr; \ 2809212224Sfabient if (!cpu_has_iaf_counters) \ 2810198433Sjkoshy pmc_mdep_event_aliases = \ 2811198433Sjkoshy C##_aliases_without_iaf; \ 2812198433Sjkoshy pmc_class_table[n] = &C##_class_table_descr; \ 2813198433Sjkoshy } while (0) 2814198433Sjkoshy 2815183725Sjkoshy /* Configure the event name parser. */ 2816145256Sjkoshy switch (cpu_info.pm_cputype) { 2817145340Smarcel#if defined(__i386__) 2818145256Sjkoshy case PMC_CPU_AMD_K7: 2819183725Sjkoshy PMC_MDEP_INIT(k7); 2820185363Sjkoshy pmc_class_table[n] = &k7_class_table_descr; 2821145256Sjkoshy break; 2822145256Sjkoshy case PMC_CPU_INTEL_P5: 2823183725Sjkoshy PMC_MDEP_INIT(p5); 2824185363Sjkoshy pmc_class_table[n] = &p5_class_table_descr; 2825145256Sjkoshy break; 2826145256Sjkoshy case PMC_CPU_INTEL_P6: /* P6 ... Pentium M CPUs have */ 2827145256Sjkoshy case PMC_CPU_INTEL_PII: /* similar PMCs. */ 2828145256Sjkoshy case PMC_CPU_INTEL_PIII: 2829145256Sjkoshy case PMC_CPU_INTEL_PM: 2830183725Sjkoshy PMC_MDEP_INIT(p6); 2831185363Sjkoshy pmc_class_table[n] = &p6_class_table_descr; 2832145256Sjkoshy break; 2833147759Sjkoshy#endif 2834147759Sjkoshy#if defined(__amd64__) || defined(__i386__) 2835183725Sjkoshy case PMC_CPU_AMD_K8: 2836183725Sjkoshy PMC_MDEP_INIT(k8); 2837185363Sjkoshy pmc_class_table[n] = &k8_class_table_descr; 2838183725Sjkoshy break; 2839185363Sjkoshy case PMC_CPU_INTEL_ATOM: 2840198433Sjkoshy PMC_MDEP_INIT_INTEL_V2(atom); 2841185363Sjkoshy break; 2842185363Sjkoshy case PMC_CPU_INTEL_CORE: 2843185363Sjkoshy PMC_MDEP_INIT(core); 2844202157Sjkoshy pmc_class_table[n] = &core_class_table_descr; 2845185363Sjkoshy break; 2846185363Sjkoshy case PMC_CPU_INTEL_CORE2: 2847185585Sjkoshy case PMC_CPU_INTEL_CORE2EXTREME: 2848198433Sjkoshy PMC_MDEP_INIT_INTEL_V2(core2); 2849185363Sjkoshy break; 2850187761Sjeff case PMC_CPU_INTEL_COREI7: 2851206089Sfabient pmc_class_table[n++] = &ucf_class_table_descr; 2852206089Sfabient pmc_class_table[n++] = &corei7uc_class_table_descr; 2853198433Sjkoshy PMC_MDEP_INIT_INTEL_V2(corei7); 2854187761Sjeff break; 2855232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 2856232366Sdavide pmc_class_table[n++] = &ucf_class_table_descr; 2857232366Sdavide pmc_class_table[n++] = &sandybridgeuc_class_table_descr; 2858232366Sdavide PMC_MDEP_INIT_INTEL_V2(sandybridge); 2859232366Sdavide break; 2860206089Sfabient case PMC_CPU_INTEL_WESTMERE: 2861206089Sfabient pmc_class_table[n++] = &ucf_class_table_descr; 2862206089Sfabient pmc_class_table[n++] = &westmereuc_class_table_descr; 2863206089Sfabient PMC_MDEP_INIT_INTEL_V2(westmere); 2864206089Sfabient break; 2865145256Sjkoshy case PMC_CPU_INTEL_PIV: 2866183725Sjkoshy PMC_MDEP_INIT(p4); 2867185363Sjkoshy pmc_class_table[n] = &p4_class_table_descr; 2868145256Sjkoshy break; 2869145256Sjkoshy#endif 2870200928Srpaulo#if defined(__XSCALE__) 2871200928Srpaulo case PMC_CPU_INTEL_XSCALE: 2872200928Srpaulo PMC_MDEP_INIT(xscale); 2873200928Srpaulo pmc_class_table[n] = &xscale_class_table_descr; 2874200928Srpaulo break; 2875200928Srpaulo#endif 2876204635Sgnn#if defined(__mips__) 2877204635Sgnn case PMC_CPU_MIPS_24K: 2878204635Sgnn PMC_MDEP_INIT(mips24k); 2879204635Sgnn pmc_class_table[n] = &mips24k_class_table_descr; 2880204635Sgnn break; 2881233335Sgonzo case PMC_CPU_MIPS_OCTEON: 2882233335Sgonzo PMC_MDEP_INIT(octeon); 2883233335Sgonzo pmc_class_table[n] = &octeon_class_table_descr; 2884233335Sgonzo break; 2885204635Sgnn#endif /* __mips__ */ 2886228869Sjhibbits#if defined(__powerpc__) 2887228869Sjhibbits case PMC_CPU_PPC_7450: 2888228869Sjhibbits PMC_MDEP_INIT(ppc7450); 2889228869Sjhibbits pmc_class_table[n] = &ppc7450_class_table_descr; 2890228869Sjhibbits break; 2891228869Sjhibbits#endif 2892145256Sjkoshy default: 2893145256Sjkoshy /* 2894145256Sjkoshy * Some kind of CPU this version of the library knows nothing 2895145256Sjkoshy * about. This shouldn't happen since the abi version check 2896145256Sjkoshy * should have caught this. 2897145256Sjkoshy */ 2898145256Sjkoshy errno = ENXIO; 2899145256Sjkoshy return (pmc_syscall = -1); 2900145256Sjkoshy } 2901145256Sjkoshy 2902174406Sjkoshy return (0); 2903145256Sjkoshy} 2904145256Sjkoshy 2905147191Sjkoshyconst char * 2906147191Sjkoshypmc_name_of_capability(enum pmc_caps cap) 2907145256Sjkoshy{ 2908147191Sjkoshy int i; 2909145256Sjkoshy 2910147191Sjkoshy /* 2911147191Sjkoshy * 'cap' should have a single bit set and should be in 2912147191Sjkoshy * range. 2913147191Sjkoshy */ 2914147191Sjkoshy if ((cap & (cap - 1)) || cap < PMC_CAP_FIRST || 2915147191Sjkoshy cap > PMC_CAP_LAST) { 2916145256Sjkoshy errno = EINVAL; 2917174406Sjkoshy return (NULL); 2918145256Sjkoshy } 2919145256Sjkoshy 2920147191Sjkoshy i = ffs(cap); 2921174406Sjkoshy return (pmc_capability_names[i - 1]); 2922147191Sjkoshy} 2923145256Sjkoshy 2924147191Sjkoshyconst char * 2925147191Sjkoshypmc_name_of_class(enum pmc_class pc) 2926147191Sjkoshy{ 2927147191Sjkoshy if ((int) pc >= PMC_CLASS_FIRST && 2928147191Sjkoshy pc <= PMC_CLASS_LAST) 2929174406Sjkoshy return (pmc_class_names[pc]); 2930145256Sjkoshy 2931147191Sjkoshy errno = EINVAL; 2932174406Sjkoshy return (NULL); 2933147191Sjkoshy} 2934145256Sjkoshy 2935147191Sjkoshyconst char * 2936147191Sjkoshypmc_name_of_cputype(enum pmc_cputype cp) 2937147191Sjkoshy{ 2938183725Sjkoshy size_t n; 2939183725Sjkoshy 2940183725Sjkoshy for (n = 0; n < PMC_TABLE_SIZE(pmc_cputype_names); n++) 2941183725Sjkoshy if (cp == pmc_cputype_names[n].pm_cputype) 2942183725Sjkoshy return (pmc_cputype_names[n].pm_name); 2943183725Sjkoshy 2944147191Sjkoshy errno = EINVAL; 2945174406Sjkoshy return (NULL); 2946147191Sjkoshy} 2947145256Sjkoshy 2948147191Sjkoshyconst char * 2949147191Sjkoshypmc_name_of_disposition(enum pmc_disp pd) 2950147191Sjkoshy{ 2951147191Sjkoshy if ((int) pd >= PMC_DISP_FIRST && 2952147191Sjkoshy pd <= PMC_DISP_LAST) 2953174406Sjkoshy return (pmc_disposition_names[pd]); 2954145256Sjkoshy 2955147191Sjkoshy errno = EINVAL; 2956174406Sjkoshy return (NULL); 2957147191Sjkoshy} 2958145256Sjkoshy 2959147191Sjkoshyconst char * 2960185363Sjkoshy_pmc_name_of_event(enum pmc_event pe, enum pmc_cputype cpu) 2961147191Sjkoshy{ 2962183725Sjkoshy const struct pmc_event_descr *ev, *evfence; 2963145256Sjkoshy 2964183725Sjkoshy ev = evfence = NULL; 2965185363Sjkoshy if (pe >= PMC_EV_IAF_FIRST && pe <= PMC_EV_IAF_LAST) { 2966185363Sjkoshy ev = iaf_event_table; 2967185363Sjkoshy evfence = iaf_event_table + PMC_EVENT_TABLE_SIZE(iaf); 2968185363Sjkoshy } else if (pe >= PMC_EV_IAP_FIRST && pe <= PMC_EV_IAP_LAST) { 2969185363Sjkoshy switch (cpu) { 2970185363Sjkoshy case PMC_CPU_INTEL_ATOM: 2971185363Sjkoshy ev = atom_event_table; 2972185363Sjkoshy evfence = atom_event_table + PMC_EVENT_TABLE_SIZE(atom); 2973185363Sjkoshy break; 2974185363Sjkoshy case PMC_CPU_INTEL_CORE: 2975185363Sjkoshy ev = core_event_table; 2976185363Sjkoshy evfence = core_event_table + PMC_EVENT_TABLE_SIZE(core); 2977185363Sjkoshy break; 2978185363Sjkoshy case PMC_CPU_INTEL_CORE2: 2979185585Sjkoshy case PMC_CPU_INTEL_CORE2EXTREME: 2980185363Sjkoshy ev = core2_event_table; 2981185363Sjkoshy evfence = core2_event_table + PMC_EVENT_TABLE_SIZE(core2); 2982185363Sjkoshy break; 2983187761Sjeff case PMC_CPU_INTEL_COREI7: 2984187761Sjeff ev = corei7_event_table; 2985187761Sjeff evfence = corei7_event_table + PMC_EVENT_TABLE_SIZE(corei7); 2986187761Sjeff break; 2987232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 2988232366Sdavide ev = sandybridge_event_table; 2989232366Sdavide evfence = sandybridge_event_table + PMC_EVENT_TABLE_SIZE(sandybridge); 2990232366Sdavide break; 2991206089Sfabient case PMC_CPU_INTEL_WESTMERE: 2992206089Sfabient ev = westmere_event_table; 2993206089Sfabient evfence = westmere_event_table + PMC_EVENT_TABLE_SIZE(westmere); 2994206089Sfabient break; 2995185363Sjkoshy default: /* Unknown CPU type. */ 2996185363Sjkoshy break; 2997185363Sjkoshy } 2998206089Sfabient } else if (pe >= PMC_EV_UCF_FIRST && pe <= PMC_EV_UCF_LAST) { 2999206089Sfabient ev = ucf_event_table; 3000206089Sfabient evfence = ucf_event_table + PMC_EVENT_TABLE_SIZE(ucf); 3001206089Sfabient } else if (pe >= PMC_EV_UCP_FIRST && pe <= PMC_EV_UCP_LAST) { 3002206089Sfabient switch (cpu) { 3003206089Sfabient case PMC_CPU_INTEL_COREI7: 3004206089Sfabient ev = corei7uc_event_table; 3005206089Sfabient evfence = corei7uc_event_table + PMC_EVENT_TABLE_SIZE(corei7uc); 3006206089Sfabient break; 3007232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 3008232366Sdavide ev = sandybridgeuc_event_table; 3009232366Sdavide evfence = sandybridgeuc_event_table + PMC_EVENT_TABLE_SIZE(sandybridgeuc); 3010232366Sdavide break; 3011206089Sfabient case PMC_CPU_INTEL_WESTMERE: 3012206089Sfabient ev = westmereuc_event_table; 3013206089Sfabient evfence = westmereuc_event_table + PMC_EVENT_TABLE_SIZE(westmereuc); 3014206089Sfabient break; 3015206089Sfabient default: /* Unknown CPU type. */ 3016206089Sfabient break; 3017206089Sfabient } 3018206089Sfabient } else if (pe >= PMC_EV_K7_FIRST && pe <= PMC_EV_K7_LAST) { 3019183725Sjkoshy ev = k7_event_table; 3020183725Sjkoshy evfence = k7_event_table + PMC_EVENT_TABLE_SIZE(k7); 3021183725Sjkoshy } else if (pe >= PMC_EV_K8_FIRST && pe <= PMC_EV_K8_LAST) { 3022183725Sjkoshy ev = k8_event_table; 3023183725Sjkoshy evfence = k8_event_table + PMC_EVENT_TABLE_SIZE(k8); 3024183725Sjkoshy } else if (pe >= PMC_EV_P4_FIRST && pe <= PMC_EV_P4_LAST) { 3025183725Sjkoshy ev = p4_event_table; 3026183725Sjkoshy evfence = p4_event_table + PMC_EVENT_TABLE_SIZE(p4); 3027183725Sjkoshy } else if (pe >= PMC_EV_P5_FIRST && pe <= PMC_EV_P5_LAST) { 3028183725Sjkoshy ev = p5_event_table; 3029183725Sjkoshy evfence = p5_event_table + PMC_EVENT_TABLE_SIZE(p5); 3030183725Sjkoshy } else if (pe >= PMC_EV_P6_FIRST && pe <= PMC_EV_P6_LAST) { 3031183725Sjkoshy ev = p6_event_table; 3032183725Sjkoshy evfence = p6_event_table + PMC_EVENT_TABLE_SIZE(p6); 3033200928Srpaulo } else if (pe >= PMC_EV_XSCALE_FIRST && pe <= PMC_EV_XSCALE_LAST) { 3034200928Srpaulo ev = xscale_event_table; 3035200928Srpaulo evfence = xscale_event_table + PMC_EVENT_TABLE_SIZE(xscale); 3036204635Sgnn } else if (pe >= PMC_EV_MIPS24K_FIRST && pe <= PMC_EV_MIPS24K_LAST) { 3037204635Sgnn ev = mips24k_event_table; 3038204635Sgnn evfence = mips24k_event_table + PMC_EVENT_TABLE_SIZE(mips24k 3039204635Sgnn); 3040233335Sgonzo } else if (pe >= PMC_EV_OCTEON_FIRST && pe <= PMC_EV_OCTEON_LAST) { 3041233335Sgonzo ev = octeon_event_table; 3042233335Sgonzo evfence = octeon_event_table + PMC_EVENT_TABLE_SIZE(octeon); 3043228869Sjhibbits } else if (pe >= PMC_EV_PPC7450_FIRST && pe <= PMC_EV_PPC7450_LAST) { 3044228869Sjhibbits ev = ppc7450_event_table; 3045228869Sjhibbits evfence = ppc7450_event_table + PMC_EVENT_TABLE_SIZE(ppc7450 3046228869Sjhibbits); 3047183725Sjkoshy } else if (pe == PMC_EV_TSC_TSC) { 3048183725Sjkoshy ev = tsc_event_table; 3049183725Sjkoshy evfence = tsc_event_table + PMC_EVENT_TABLE_SIZE(tsc); 3050183725Sjkoshy } 3051183725Sjkoshy 3052183725Sjkoshy for (; ev != evfence; ev++) 3053183725Sjkoshy if (pe == ev->pm_ev_code) 3054183725Sjkoshy return (ev->pm_ev_name); 3055183725Sjkoshy 3056185363Sjkoshy return (NULL); 3057185363Sjkoshy} 3058185363Sjkoshy 3059185363Sjkoshyconst char * 3060185363Sjkoshypmc_name_of_event(enum pmc_event pe) 3061185363Sjkoshy{ 3062185363Sjkoshy const char *n; 3063185363Sjkoshy 3064185363Sjkoshy if ((n = _pmc_name_of_event(pe, cpu_info.pm_cputype)) != NULL) 3065185363Sjkoshy return (n); 3066185363Sjkoshy 3067147191Sjkoshy errno = EINVAL; 3068174406Sjkoshy return (NULL); 3069147191Sjkoshy} 3070145256Sjkoshy 3071147191Sjkoshyconst char * 3072147191Sjkoshypmc_name_of_mode(enum pmc_mode pm) 3073147191Sjkoshy{ 3074147191Sjkoshy if ((int) pm >= PMC_MODE_FIRST && 3075147191Sjkoshy pm <= PMC_MODE_LAST) 3076174406Sjkoshy return (pmc_mode_names[pm]); 3077145256Sjkoshy 3078147191Sjkoshy errno = EINVAL; 3079174406Sjkoshy return (NULL); 3080147191Sjkoshy} 3081145256Sjkoshy 3082147191Sjkoshyconst char * 3083147191Sjkoshypmc_name_of_state(enum pmc_state ps) 3084147191Sjkoshy{ 3085147191Sjkoshy if ((int) ps >= PMC_STATE_FIRST && 3086147191Sjkoshy ps <= PMC_STATE_LAST) 3087174406Sjkoshy return (pmc_state_names[ps]); 3088145256Sjkoshy 3089147191Sjkoshy errno = EINVAL; 3090174406Sjkoshy return (NULL); 3091145256Sjkoshy} 3092145256Sjkoshy 3093145256Sjkoshyint 3094147191Sjkoshypmc_ncpu(void) 3095145256Sjkoshy{ 3096147191Sjkoshy if (pmc_syscall == -1) { 3097147191Sjkoshy errno = ENXIO; 3098174406Sjkoshy return (-1); 3099147191Sjkoshy } 3100145256Sjkoshy 3101174406Sjkoshy return (cpu_info.pm_ncpu); 3102145256Sjkoshy} 3103145256Sjkoshy 3104145256Sjkoshyint 3105147191Sjkoshypmc_npmc(int cpu) 3106145256Sjkoshy{ 3107147191Sjkoshy if (pmc_syscall == -1) { 3108147191Sjkoshy errno = ENXIO; 3109174406Sjkoshy return (-1); 3110147191Sjkoshy } 3111145256Sjkoshy 3112147191Sjkoshy if (cpu < 0 || cpu >= (int) cpu_info.pm_ncpu) { 3113147191Sjkoshy errno = EINVAL; 3114174406Sjkoshy return (-1); 3115147191Sjkoshy } 3116145256Sjkoshy 3117174406Sjkoshy return (cpu_info.pm_npmc); 3118145256Sjkoshy} 3119145256Sjkoshy 3120145256Sjkoshyint 3121147191Sjkoshypmc_pmcinfo(int cpu, struct pmc_pmcinfo **ppmci) 3122145256Sjkoshy{ 3123147191Sjkoshy int nbytes, npmc; 3124147191Sjkoshy struct pmc_op_getpmcinfo *pmci; 3125145256Sjkoshy 3126147191Sjkoshy if ((npmc = pmc_npmc(cpu)) < 0) 3127174406Sjkoshy return (-1); 3128145256Sjkoshy 3129147191Sjkoshy nbytes = sizeof(struct pmc_op_getpmcinfo) + 3130147191Sjkoshy npmc * sizeof(struct pmc_info); 3131145256Sjkoshy 3132147191Sjkoshy if ((pmci = calloc(1, nbytes)) == NULL) 3133174406Sjkoshy return (-1); 3134145256Sjkoshy 3135147191Sjkoshy pmci->pm_cpu = cpu; 3136145256Sjkoshy 3137147191Sjkoshy if (PMC_CALL(GETPMCINFO, pmci) < 0) { 3138147191Sjkoshy free(pmci); 3139174406Sjkoshy return (-1); 3140147191Sjkoshy } 3141145256Sjkoshy 3142147191Sjkoshy /* kernel<->library, library<->userland interfaces are identical */ 3143147191Sjkoshy *ppmci = (struct pmc_pmcinfo *) pmci; 3144174406Sjkoshy return (0); 3145145256Sjkoshy} 3146145256Sjkoshy 3147145256Sjkoshyint 3148145256Sjkoshypmc_read(pmc_id_t pmc, pmc_value_t *value) 3149145256Sjkoshy{ 3150145256Sjkoshy struct pmc_op_pmcrw pmc_read_op; 3151145256Sjkoshy 3152145256Sjkoshy pmc_read_op.pm_pmcid = pmc; 3153145256Sjkoshy pmc_read_op.pm_flags = PMC_F_OLDVALUE; 3154145256Sjkoshy pmc_read_op.pm_value = -1; 3155145256Sjkoshy 3156145256Sjkoshy if (PMC_CALL(PMCRW, &pmc_read_op) < 0) 3157174406Sjkoshy return (-1); 3158145256Sjkoshy 3159145256Sjkoshy *value = pmc_read_op.pm_value; 3160174406Sjkoshy return (0); 3161145256Sjkoshy} 3162145256Sjkoshy 3163145256Sjkoshyint 3164147191Sjkoshypmc_release(pmc_id_t pmc) 3165145256Sjkoshy{ 3166147191Sjkoshy struct pmc_op_simple pmc_release_args; 3167145256Sjkoshy 3168147191Sjkoshy pmc_release_args.pm_pmcid = pmc; 3169174406Sjkoshy return (PMC_CALL(PMCRELEASE, &pmc_release_args)); 3170145256Sjkoshy} 3171145256Sjkoshy 3172145256Sjkoshyint 3173145256Sjkoshypmc_rw(pmc_id_t pmc, pmc_value_t newvalue, pmc_value_t *oldvaluep) 3174145256Sjkoshy{ 3175145256Sjkoshy struct pmc_op_pmcrw pmc_rw_op; 3176145256Sjkoshy 3177145256Sjkoshy pmc_rw_op.pm_pmcid = pmc; 3178145256Sjkoshy pmc_rw_op.pm_flags = PMC_F_NEWVALUE | PMC_F_OLDVALUE; 3179145256Sjkoshy pmc_rw_op.pm_value = newvalue; 3180145256Sjkoshy 3181145256Sjkoshy if (PMC_CALL(PMCRW, &pmc_rw_op) < 0) 3182174406Sjkoshy return (-1); 3183145256Sjkoshy 3184145256Sjkoshy *oldvaluep = pmc_rw_op.pm_value; 3185174406Sjkoshy return (0); 3186145256Sjkoshy} 3187145256Sjkoshy 3188145256Sjkoshyint 3189145256Sjkoshypmc_set(pmc_id_t pmc, pmc_value_t value) 3190145256Sjkoshy{ 3191145256Sjkoshy struct pmc_op_pmcsetcount sc; 3192145256Sjkoshy 3193145256Sjkoshy sc.pm_pmcid = pmc; 3194145256Sjkoshy sc.pm_count = value; 3195145256Sjkoshy 3196145256Sjkoshy if (PMC_CALL(PMCSETCOUNT, &sc) < 0) 3197174406Sjkoshy return (-1); 3198174406Sjkoshy return (0); 3199145256Sjkoshy} 3200145256Sjkoshy 3201145256Sjkoshyint 3202147191Sjkoshypmc_start(pmc_id_t pmc) 3203145256Sjkoshy{ 3204147191Sjkoshy struct pmc_op_simple pmc_start_args; 3205145256Sjkoshy 3206147191Sjkoshy pmc_start_args.pm_pmcid = pmc; 3207174406Sjkoshy return (PMC_CALL(PMCSTART, &pmc_start_args)); 3208145256Sjkoshy} 3209145256Sjkoshy 3210145256Sjkoshyint 3211147191Sjkoshypmc_stop(pmc_id_t pmc) 3212145256Sjkoshy{ 3213147191Sjkoshy struct pmc_op_simple pmc_stop_args; 3214145256Sjkoshy 3215147191Sjkoshy pmc_stop_args.pm_pmcid = pmc; 3216174406Sjkoshy return (PMC_CALL(PMCSTOP, &pmc_stop_args)); 3217145256Sjkoshy} 3218145256Sjkoshy 3219145256Sjkoshyint 3220145774Sjkoshypmc_width(pmc_id_t pmcid, uint32_t *width) 3221145774Sjkoshy{ 3222145774Sjkoshy unsigned int i; 3223145774Sjkoshy enum pmc_class cl; 3224145774Sjkoshy 3225145774Sjkoshy cl = PMC_ID_TO_CLASS(pmcid); 3226145774Sjkoshy for (i = 0; i < cpu_info.pm_nclass; i++) 3227145774Sjkoshy if (cpu_info.pm_classes[i].pm_class == cl) { 3228145774Sjkoshy *width = cpu_info.pm_classes[i].pm_width; 3229174406Sjkoshy return (0); 3230145774Sjkoshy } 3231177107Sjkoshy errno = EINVAL; 3232177107Sjkoshy return (-1); 3233145774Sjkoshy} 3234145774Sjkoshy 3235145774Sjkoshyint 3236147191Sjkoshypmc_write(pmc_id_t pmc, pmc_value_t value) 3237145774Sjkoshy{ 3238147191Sjkoshy struct pmc_op_pmcrw pmc_write_op; 3239145774Sjkoshy 3240147191Sjkoshy pmc_write_op.pm_pmcid = pmc; 3241147191Sjkoshy pmc_write_op.pm_flags = PMC_F_NEWVALUE; 3242147191Sjkoshy pmc_write_op.pm_value = value; 3243174406Sjkoshy return (PMC_CALL(PMCRW, &pmc_write_op)); 3244145256Sjkoshy} 3245145256Sjkoshy 3246145256Sjkoshyint 3247147191Sjkoshypmc_writelog(uint32_t userdata) 3248145256Sjkoshy{ 3249147191Sjkoshy struct pmc_op_writelog wl; 3250145256Sjkoshy 3251147191Sjkoshy wl.pm_userdata = userdata; 3252174406Sjkoshy return (PMC_CALL(WRITELOG, &wl)); 3253145256Sjkoshy} 3254