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$"); 29145256Sjkoshy 30145256Sjkoshy#include <sys/types.h> 31263122Sjhibbits#include <sys/param.h> 32145256Sjkoshy#include <sys/module.h> 33145256Sjkoshy#include <sys/pmc.h> 34145256Sjkoshy#include <sys/syscall.h> 35145256Sjkoshy 36145256Sjkoshy#include <ctype.h> 37145256Sjkoshy#include <errno.h> 38145256Sjkoshy#include <fcntl.h> 39145256Sjkoshy#include <pmc.h> 40145256Sjkoshy#include <stdio.h> 41145256Sjkoshy#include <stdlib.h> 42145256Sjkoshy#include <string.h> 43145256Sjkoshy#include <strings.h> 44145256Sjkoshy#include <unistd.h> 45145256Sjkoshy 46185363Sjkoshy#include "libpmcinternal.h" 47185363Sjkoshy 48145256Sjkoshy/* Function prototypes */ 49145340Smarcel#if defined(__i386__) 50145256Sjkoshystatic int k7_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 51145256Sjkoshy struct pmc_op_pmcallocate *_pmc_config); 52147191Sjkoshy#endif 53147759Sjkoshy#if defined(__amd64__) || defined(__i386__) 54185363Sjkoshystatic int iaf_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 55185363Sjkoshy struct pmc_op_pmcallocate *_pmc_config); 56185363Sjkoshystatic int iap_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 57185363Sjkoshy struct pmc_op_pmcallocate *_pmc_config); 58206089Sfabientstatic int ucf_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 59206089Sfabient struct pmc_op_pmcallocate *_pmc_config); 60206089Sfabientstatic int ucp_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 61206089Sfabient struct pmc_op_pmcallocate *_pmc_config); 62147191Sjkoshystatic int k8_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 63145256Sjkoshy struct pmc_op_pmcallocate *_pmc_config); 64147759Sjkoshystatic int p4_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 65147759Sjkoshy struct pmc_op_pmcallocate *_pmc_config); 66147191Sjkoshy#endif 67147191Sjkoshy#if defined(__i386__) 68145256Sjkoshystatic int p5_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 69145256Sjkoshy struct pmc_op_pmcallocate *_pmc_config); 70147191Sjkoshystatic int p6_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 71145256Sjkoshy struct pmc_op_pmcallocate *_pmc_config); 72145256Sjkoshy#endif 73183725Sjkoshy#if defined(__amd64__) || defined(__i386__) 74183725Sjkoshystatic int tsc_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 75183725Sjkoshy struct pmc_op_pmcallocate *_pmc_config); 76183725Sjkoshy#endif 77200928Srpaulo#if defined(__XSCALE__) 78200928Srpaulostatic int xscale_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 79200928Srpaulo struct pmc_op_pmcallocate *_pmc_config); 80200928Srpaulo#endif 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__ */ 85233628Sfabientstatic int soft_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 86233628Sfabient struct pmc_op_pmcallocate *_pmc_config); 87204635Sgnn 88228869Sjhibbits#if defined(__powerpc__) 89263122Sjhibbitsstatic int powerpc_allocate_pmc(enum pmc_event _pe, char* ctrspec, 90228869Sjhibbits struct pmc_op_pmcallocate *_pmc_config); 91228869Sjhibbits#endif /* __powerpc__ */ 92204635Sgnn 93145256Sjkoshy#define PMC_CALL(cmd, params) \ 94145256Sjkoshy syscall(pmc_syscall, PMC_OP_##cmd, (params)) 95145256Sjkoshy 96145256Sjkoshy/* 97145256Sjkoshy * Event aliases provide a way for the user to ask for generic events 98145256Sjkoshy * like "cache-misses", or "instructions-retired". These aliases are 99145256Sjkoshy * mapped to the appropriate canonical event descriptions using a 100145256Sjkoshy * lookup table. 101145256Sjkoshy */ 102145256Sjkoshystruct pmc_event_alias { 103145256Sjkoshy const char *pm_alias; 104145256Sjkoshy const char *pm_spec; 105145256Sjkoshy}; 106145256Sjkoshy 107145256Sjkoshystatic const struct pmc_event_alias *pmc_mdep_event_aliases; 108145256Sjkoshy 109145256Sjkoshy/* 110183725Sjkoshy * The pmc_event_descr structure maps symbolic names known to the user 111145256Sjkoshy * to integer codes used by the PMC KLD. 112145256Sjkoshy */ 113145256Sjkoshystruct pmc_event_descr { 114145256Sjkoshy const char *pm_ev_name; 115145256Sjkoshy enum pmc_event pm_ev_code; 116145256Sjkoshy}; 117145256Sjkoshy 118183725Sjkoshy/* 119183725Sjkoshy * The pmc_class_descr structure maps class name prefixes for 120183725Sjkoshy * event names to event tables and other PMC class data. 121183725Sjkoshy */ 122183725Sjkoshystruct pmc_class_descr { 123183725Sjkoshy const char *pm_evc_name; 124183725Sjkoshy size_t pm_evc_name_size; 125183725Sjkoshy enum pmc_class pm_evc_class; 126183725Sjkoshy const struct pmc_event_descr *pm_evc_event_table; 127183725Sjkoshy size_t pm_evc_event_table_size; 128183725Sjkoshy int (*pm_evc_allocate_pmc)(enum pmc_event _pe, 129183725Sjkoshy char *_ctrspec, struct pmc_op_pmcallocate *_pa); 130183725Sjkoshy}; 131183725Sjkoshy 132183725Sjkoshy#define PMC_TABLE_SIZE(N) (sizeof(N)/sizeof(N[0])) 133183725Sjkoshy#define PMC_EVENT_TABLE_SIZE(N) PMC_TABLE_SIZE(N##_event_table) 134183725Sjkoshy 135183725Sjkoshy#undef __PMC_EV 136183725Sjkoshy#define __PMC_EV(C,N) { #N, PMC_EV_ ## C ## _ ## N }, 137183725Sjkoshy 138183725Sjkoshy/* 139185363Sjkoshy * PMC_CLASSDEP_TABLE(NAME, CLASS) 140183725Sjkoshy * 141185363Sjkoshy * Define a table mapping event names and aliases to HWPMC event IDs. 142183725Sjkoshy */ 143185363Sjkoshy#define PMC_CLASSDEP_TABLE(N, C) \ 144183725Sjkoshy static const struct pmc_event_descr N##_event_table[] = \ 145183725Sjkoshy { \ 146183725Sjkoshy __PMC_EV_##C() \ 147185363Sjkoshy } 148185363Sjkoshy 149185363SjkoshyPMC_CLASSDEP_TABLE(iaf, IAF); 150185363SjkoshyPMC_CLASSDEP_TABLE(k7, K7); 151185363SjkoshyPMC_CLASSDEP_TABLE(k8, K8); 152185363SjkoshyPMC_CLASSDEP_TABLE(p4, P4); 153185363SjkoshyPMC_CLASSDEP_TABLE(p5, P5); 154185363SjkoshyPMC_CLASSDEP_TABLE(p6, P6); 155200928SrpauloPMC_CLASSDEP_TABLE(xscale, XSCALE); 156204635SgnnPMC_CLASSDEP_TABLE(mips24k, MIPS24K); 157233335SgonzoPMC_CLASSDEP_TABLE(octeon, OCTEON); 158206089SfabientPMC_CLASSDEP_TABLE(ucf, UCF); 159228869SjhibbitsPMC_CLASSDEP_TABLE(ppc7450, PPC7450); 160263122SjhibbitsPMC_CLASSDEP_TABLE(ppc970, PPC970); 161185363Sjkoshy 162233628Sfabientstatic struct pmc_event_descr soft_event_table[PMC_EV_DYN_COUNT]; 163233628Sfabient 164185363Sjkoshy#undef __PMC_EV_ALIAS 165185363Sjkoshy#define __PMC_EV_ALIAS(N,CODE) { N, PMC_EV_##CODE }, 166185363Sjkoshy 167185363Sjkoshystatic const struct pmc_event_descr atom_event_table[] = 168185363Sjkoshy{ 169185363Sjkoshy __PMC_EV_ALIAS_ATOM() 170185363Sjkoshy}; 171185363Sjkoshy 172266911Shirenstatic const struct pmc_event_descr atom_silvermont_event_table[] = 173266911Shiren{ 174266911Shiren __PMC_EV_ALIAS_ATOM_SILVERMONT() 175266911Shiren}; 176266911Shiren 177185363Sjkoshystatic const struct pmc_event_descr core_event_table[] = 178185363Sjkoshy{ 179185363Sjkoshy __PMC_EV_ALIAS_CORE() 180185363Sjkoshy}; 181185363Sjkoshy 182185363Sjkoshy 183185363Sjkoshystatic const struct pmc_event_descr core2_event_table[] = 184185363Sjkoshy{ 185185363Sjkoshy __PMC_EV_ALIAS_CORE2() 186185363Sjkoshy}; 187185363Sjkoshy 188187761Sjeffstatic const struct pmc_event_descr corei7_event_table[] = 189187761Sjeff{ 190187761Sjeff __PMC_EV_ALIAS_COREI7() 191187761Sjeff}; 192187761Sjeff 193267602Skibstatic const struct pmc_event_descr nehalem_ex_event_table[] = 194267602Skib{ 195267602Skib __PMC_EV_ALIAS_COREI7() 196267602Skib}; 197267602Skib 198248842Ssbrunostatic const struct pmc_event_descr haswell_event_table[] = 199248842Ssbruno{ 200248842Ssbruno __PMC_EV_ALIAS_HASWELL() 201248842Ssbruno}; 202248842Ssbruno 203240164Sfabientstatic const struct pmc_event_descr ivybridge_event_table[] = 204240164Sfabient{ 205240164Sfabient __PMC_EV_ALIAS_IVYBRIDGE() 206240164Sfabient}; 207240164Sfabient 208246166Ssbrunostatic const struct pmc_event_descr ivybridge_xeon_event_table[] = 209246166Ssbruno{ 210246166Ssbruno __PMC_EV_ALIAS_IVYBRIDGE_XEON() 211246166Ssbruno}; 212246166Ssbruno 213232366Sdavidestatic const struct pmc_event_descr sandybridge_event_table[] = 214232366Sdavide{ 215232366Sdavide __PMC_EV_ALIAS_SANDYBRIDGE() 216232366Sdavide}; 217232366Sdavide 218241738Ssbrunostatic const struct pmc_event_descr sandybridge_xeon_event_table[] = 219241738Ssbruno{ 220241738Ssbruno __PMC_EV_ALIAS_SANDYBRIDGE_XEON() 221241738Ssbruno}; 222241738Ssbruno 223206089Sfabientstatic const struct pmc_event_descr westmere_event_table[] = 224206089Sfabient{ 225206089Sfabient __PMC_EV_ALIAS_WESTMERE() 226206089Sfabient}; 227206089Sfabient 228267602Skibstatic const struct pmc_event_descr westmere_ex_event_table[] = 229267602Skib{ 230267602Skib __PMC_EV_ALIAS_WESTMERE() 231267602Skib}; 232267602Skib 233206089Sfabientstatic const struct pmc_event_descr corei7uc_event_table[] = 234206089Sfabient{ 235206089Sfabient __PMC_EV_ALIAS_COREI7UC() 236206089Sfabient}; 237206089Sfabient 238248842Ssbrunostatic const struct pmc_event_descr haswelluc_event_table[] = 239248842Ssbruno{ 240248842Ssbruno __PMC_EV_ALIAS_HASWELLUC() 241248842Ssbruno}; 242248842Ssbruno 243232366Sdavidestatic const struct pmc_event_descr sandybridgeuc_event_table[] = 244232366Sdavide{ 245232366Sdavide __PMC_EV_ALIAS_SANDYBRIDGEUC() 246232366Sdavide}; 247232366Sdavide 248206089Sfabientstatic const struct pmc_event_descr westmereuc_event_table[] = 249206089Sfabient{ 250206089Sfabient __PMC_EV_ALIAS_WESTMEREUC() 251206089Sfabient}; 252206089Sfabient 253185363Sjkoshy/* 254185363Sjkoshy * PMC_MDEP_TABLE(NAME, PRIMARYCLASS, ADDITIONAL_CLASSES...) 255185363Sjkoshy * 256185363Sjkoshy * Map a CPU to the PMC classes it supports. 257185363Sjkoshy */ 258185363Sjkoshy#define PMC_MDEP_TABLE(N,C,...) \ 259183725Sjkoshy static const enum pmc_class N##_pmc_classes[] = { \ 260183725Sjkoshy PMC_CLASS_##C, __VA_ARGS__ \ 261183725Sjkoshy } 262183725Sjkoshy 263233628SfabientPMC_MDEP_TABLE(atom, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 264266911ShirenPMC_MDEP_TABLE(atom_silvermont, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 265233628SfabientPMC_MDEP_TABLE(core, IAP, PMC_CLASS_SOFT, PMC_CLASS_TSC); 266233628SfabientPMC_MDEP_TABLE(core2, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 267233628SfabientPMC_MDEP_TABLE(corei7, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 268267602SkibPMC_MDEP_TABLE(nehalem_ex, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 269248842SsbrunoPMC_MDEP_TABLE(haswell, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 270240164SfabientPMC_MDEP_TABLE(ivybridge, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 271246166SsbrunoPMC_MDEP_TABLE(ivybridge_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 272233628SfabientPMC_MDEP_TABLE(sandybridge, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 273241738SsbrunoPMC_MDEP_TABLE(sandybridge_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 274233628SfabientPMC_MDEP_TABLE(westmere, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 275267602SkibPMC_MDEP_TABLE(westmere_ex, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 276233628SfabientPMC_MDEP_TABLE(k7, K7, PMC_CLASS_SOFT, PMC_CLASS_TSC); 277233628SfabientPMC_MDEP_TABLE(k8, K8, PMC_CLASS_SOFT, PMC_CLASS_TSC); 278233628SfabientPMC_MDEP_TABLE(p4, P4, PMC_CLASS_SOFT, PMC_CLASS_TSC); 279233628SfabientPMC_MDEP_TABLE(p5, P5, PMC_CLASS_SOFT, PMC_CLASS_TSC); 280233628SfabientPMC_MDEP_TABLE(p6, P6, PMC_CLASS_SOFT, PMC_CLASS_TSC); 281233628SfabientPMC_MDEP_TABLE(xscale, XSCALE, PMC_CLASS_SOFT, PMC_CLASS_XSCALE); 282233628SfabientPMC_MDEP_TABLE(mips24k, MIPS24K, PMC_CLASS_SOFT, PMC_CLASS_MIPS24K); 283233628SfabientPMC_MDEP_TABLE(octeon, OCTEON, PMC_CLASS_SOFT, PMC_CLASS_OCTEON); 284233628SfabientPMC_MDEP_TABLE(ppc7450, PPC7450, PMC_CLASS_SOFT, PMC_CLASS_PPC7450); 285263122SjhibbitsPMC_MDEP_TABLE(ppc970, PPC970, PMC_CLASS_SOFT, PMC_CLASS_PPC970); 286233628SfabientPMC_MDEP_TABLE(generic, SOFT, PMC_CLASS_SOFT); 287183725Sjkoshy 288183725Sjkoshystatic const struct pmc_event_descr tsc_event_table[] = 289145256Sjkoshy{ 290183725Sjkoshy __PMC_EV_TSC() 291145256Sjkoshy}; 292145256Sjkoshy 293183725Sjkoshy#undef PMC_CLASS_TABLE_DESC 294185363Sjkoshy#define PMC_CLASS_TABLE_DESC(NAME, CLASS, EVENTS, ALLOCATOR) \ 295185363Sjkoshystatic const struct pmc_class_descr NAME##_class_table_descr = \ 296185363Sjkoshy { \ 297185363Sjkoshy .pm_evc_name = #CLASS "-", \ 298185363Sjkoshy .pm_evc_name_size = sizeof(#CLASS "-") - 1, \ 299185363Sjkoshy .pm_evc_class = PMC_CLASS_##CLASS , \ 300185363Sjkoshy .pm_evc_event_table = EVENTS##_event_table , \ 301183725Sjkoshy .pm_evc_event_table_size = \ 302185363Sjkoshy PMC_EVENT_TABLE_SIZE(EVENTS), \ 303185363Sjkoshy .pm_evc_allocate_pmc = ALLOCATOR##_allocate_pmc \ 304183725Sjkoshy } 305183725Sjkoshy 306185363Sjkoshy#if defined(__i386__) || defined(__amd64__) 307185363SjkoshyPMC_CLASS_TABLE_DESC(iaf, IAF, iaf, iaf); 308185363SjkoshyPMC_CLASS_TABLE_DESC(atom, IAP, atom, iap); 309266911ShirenPMC_CLASS_TABLE_DESC(atom_silvermont, IAP, atom_silvermont, iap); 310185363SjkoshyPMC_CLASS_TABLE_DESC(core, IAP, core, iap); 311185363SjkoshyPMC_CLASS_TABLE_DESC(core2, IAP, core2, iap); 312187761SjeffPMC_CLASS_TABLE_DESC(corei7, IAP, corei7, iap); 313267602SkibPMC_CLASS_TABLE_DESC(nehalem_ex, IAP, nehalem_ex, iap); 314248842SsbrunoPMC_CLASS_TABLE_DESC(haswell, IAP, haswell, iap); 315240164SfabientPMC_CLASS_TABLE_DESC(ivybridge, IAP, ivybridge, iap); 316246166SsbrunoPMC_CLASS_TABLE_DESC(ivybridge_xeon, IAP, ivybridge_xeon, iap); 317232366SdavidePMC_CLASS_TABLE_DESC(sandybridge, IAP, sandybridge, iap); 318241738SsbrunoPMC_CLASS_TABLE_DESC(sandybridge_xeon, IAP, sandybridge_xeon, iap); 319206089SfabientPMC_CLASS_TABLE_DESC(westmere, IAP, westmere, iap); 320267602SkibPMC_CLASS_TABLE_DESC(westmere_ex, IAP, westmere_ex, iap); 321206089SfabientPMC_CLASS_TABLE_DESC(ucf, UCF, ucf, ucf); 322206089SfabientPMC_CLASS_TABLE_DESC(corei7uc, UCP, corei7uc, ucp); 323248842SsbrunoPMC_CLASS_TABLE_DESC(haswelluc, UCP, haswelluc, ucp); 324232366SdavidePMC_CLASS_TABLE_DESC(sandybridgeuc, UCP, sandybridgeuc, ucp); 325206089SfabientPMC_CLASS_TABLE_DESC(westmereuc, UCP, westmereuc, ucp); 326185363Sjkoshy#endif 327183725Sjkoshy#if defined(__i386__) 328185363SjkoshyPMC_CLASS_TABLE_DESC(k7, K7, k7, k7); 329183725Sjkoshy#endif 330183725Sjkoshy#if defined(__i386__) || defined(__amd64__) 331185363SjkoshyPMC_CLASS_TABLE_DESC(k8, K8, k8, k8); 332185363SjkoshyPMC_CLASS_TABLE_DESC(p4, P4, p4, p4); 333183725Sjkoshy#endif 334183725Sjkoshy#if defined(__i386__) 335185363SjkoshyPMC_CLASS_TABLE_DESC(p5, P5, p5, p5); 336185363SjkoshyPMC_CLASS_TABLE_DESC(p6, P6, p6, p6); 337183725Sjkoshy#endif 338183725Sjkoshy#if defined(__i386__) || defined(__amd64__) 339185363SjkoshyPMC_CLASS_TABLE_DESC(tsc, TSC, tsc, tsc); 340183725Sjkoshy#endif 341200928Srpaulo#if defined(__XSCALE__) 342200928SrpauloPMC_CLASS_TABLE_DESC(xscale, XSCALE, xscale, xscale); 343200928Srpaulo#endif 344204635Sgnn#if defined(__mips__) 345233320SgonzoPMC_CLASS_TABLE_DESC(mips24k, MIPS24K, mips24k, mips); 346233335SgonzoPMC_CLASS_TABLE_DESC(octeon, OCTEON, octeon, mips); 347204635Sgnn#endif /* __mips__ */ 348228869Sjhibbits#if defined(__powerpc__) 349263122SjhibbitsPMC_CLASS_TABLE_DESC(ppc7450, PPC7450, ppc7450, powerpc); 350263122SjhibbitsPMC_CLASS_TABLE_DESC(ppc970, PPC970, ppc970, powerpc); 351228869Sjhibbits#endif 352228869Sjhibbits 353233628Sfabientstatic struct pmc_class_descr soft_class_table_descr = 354233628Sfabient{ 355233628Sfabient .pm_evc_name = "SOFT-", 356233628Sfabient .pm_evc_name_size = sizeof("SOFT-") - 1, 357233628Sfabient .pm_evc_class = PMC_CLASS_SOFT, 358233628Sfabient .pm_evc_event_table = NULL, 359233628Sfabient .pm_evc_event_table_size = 0, 360233628Sfabient .pm_evc_allocate_pmc = soft_allocate_pmc 361233628Sfabient}; 362233628Sfabient 363183725Sjkoshy#undef PMC_CLASS_TABLE_DESC 364183725Sjkoshy 365185363Sjkoshystatic const struct pmc_class_descr **pmc_class_table; 366185363Sjkoshy#define PMC_CLASS_TABLE_SIZE cpu_info.pm_nclass 367185363Sjkoshy 368183725Sjkoshystatic const enum pmc_class *pmc_mdep_class_list; 369183725Sjkoshystatic size_t pmc_mdep_class_list_size; 370183725Sjkoshy 371145256Sjkoshy/* 372145256Sjkoshy * Mapping tables, mapping enumeration values to human readable 373145256Sjkoshy * strings. 374145256Sjkoshy */ 375145256Sjkoshy 376145256Sjkoshystatic const char * pmc_capability_names[] = { 377145256Sjkoshy#undef __PMC_CAP 378145256Sjkoshy#define __PMC_CAP(N,V,D) #N , 379145256Sjkoshy __PMC_CAPS() 380145256Sjkoshy}; 381145256Sjkoshy 382145256Sjkoshystatic const char * pmc_class_names[] = { 383145256Sjkoshy#undef __PMC_CLASS 384145256Sjkoshy#define __PMC_CLASS(C) #C , 385145256Sjkoshy __PMC_CLASSES() 386145256Sjkoshy}; 387145256Sjkoshy 388183725Sjkoshystruct pmc_cputype_map { 389228557Sdim enum pmc_cputype pm_cputype; 390183725Sjkoshy const char *pm_name; 391183725Sjkoshy}; 392183725Sjkoshy 393183725Sjkoshystatic const struct pmc_cputype_map pmc_cputype_names[] = { 394145256Sjkoshy#undef __PMC_CPU 395183725Sjkoshy#define __PMC_CPU(S, V, D) { .pm_cputype = PMC_CPU_##S, .pm_name = #S } , 396145256Sjkoshy __PMC_CPUS() 397145256Sjkoshy}; 398145256Sjkoshy 399145256Sjkoshystatic const char * pmc_disposition_names[] = { 400145256Sjkoshy#undef __PMC_DISP 401145256Sjkoshy#define __PMC_DISP(D) #D , 402145256Sjkoshy __PMC_DISPOSITIONS() 403145256Sjkoshy}; 404145256Sjkoshy 405145256Sjkoshystatic const char * pmc_mode_names[] = { 406145256Sjkoshy#undef __PMC_MODE 407145256Sjkoshy#define __PMC_MODE(M,N) #M , 408145256Sjkoshy __PMC_MODES() 409145256Sjkoshy}; 410145256Sjkoshy 411145256Sjkoshystatic const char * pmc_state_names[] = { 412145256Sjkoshy#undef __PMC_STATE 413145256Sjkoshy#define __PMC_STATE(S) #S , 414145256Sjkoshy __PMC_STATES() 415145256Sjkoshy}; 416145256Sjkoshy 417233628Sfabient/* 418233628Sfabient * Filled in by pmc_init(). 419233628Sfabient */ 420233628Sfabientstatic int pmc_syscall = -1; 421233628Sfabientstatic struct pmc_cpuinfo cpu_info; 422233628Sfabientstatic struct pmc_op_getdyneventinfo soft_event_info; 423145256Sjkoshy 424145256Sjkoshy/* Event masks for events */ 425145256Sjkoshystruct pmc_masks { 426145256Sjkoshy const char *pm_name; 427240164Sfabient const uint64_t pm_value; 428145256Sjkoshy}; 429145256Sjkoshy#define PMCMASK(N,V) { .pm_name = #N, .pm_value = (V) } 430206089Sfabient#define NULLMASK { .pm_name = NULL } 431145256Sjkoshy 432147759Sjkoshy#if defined(__amd64__) || defined(__i386__) 433145256Sjkoshystatic int 434240164Sfabientpmc_parse_mask(const struct pmc_masks *pmask, char *p, uint64_t *evmask) 435145256Sjkoshy{ 436145256Sjkoshy const struct pmc_masks *pm; 437145256Sjkoshy char *q, *r; 438145256Sjkoshy int c; 439145256Sjkoshy 440145256Sjkoshy if (pmask == NULL) /* no mask keywords */ 441174406Sjkoshy return (-1); 442183107Sjkoshy q = strchr(p, '='); /* skip '=' */ 443145256Sjkoshy if (*++q == '\0') /* no more data */ 444174406Sjkoshy return (-1); 445145256Sjkoshy c = 0; /* count of mask keywords seen */ 446145256Sjkoshy while ((r = strsep(&q, "+")) != NULL) { 447183725Sjkoshy for (pm = pmask; pm->pm_name && strcasecmp(r, pm->pm_name); 448183725Sjkoshy pm++) 449145256Sjkoshy ; 450145256Sjkoshy if (pm->pm_name == NULL) /* not found */ 451174406Sjkoshy return (-1); 452145256Sjkoshy *evmask |= pm->pm_value; 453145256Sjkoshy c++; 454145256Sjkoshy } 455174406Sjkoshy return (c); 456145256Sjkoshy} 457145340Smarcel#endif 458145256Sjkoshy 459145256Sjkoshy#define KWMATCH(p,kw) (strcasecmp((p), (kw)) == 0) 460145256Sjkoshy#define KWPREFIXMATCH(p,kw) (strncasecmp((p), (kw), sizeof((kw)) - 1) == 0) 461145256Sjkoshy#define EV_ALIAS(N,S) { .pm_alias = N, .pm_spec = S } 462145256Sjkoshy 463145340Smarcel#if defined(__i386__) 464145256Sjkoshy 465145256Sjkoshy/* 466145256Sjkoshy * AMD K7 (Athlon) CPUs. 467145256Sjkoshy */ 468145256Sjkoshy 469145256Sjkoshystatic struct pmc_event_alias k7_aliases[] = { 470145351Sjkoshy EV_ALIAS("branches", "k7-retired-branches"), 471145351Sjkoshy EV_ALIAS("branch-mispredicts", "k7-retired-branches-mispredicted"), 472145351Sjkoshy EV_ALIAS("cycles", "tsc"), 473183075Sjkoshy EV_ALIAS("dc-misses", "k7-dc-misses"), 474145351Sjkoshy EV_ALIAS("ic-misses", "k7-ic-misses"), 475145351Sjkoshy EV_ALIAS("instructions", "k7-retired-instructions"), 476145351Sjkoshy EV_ALIAS("interrupts", "k7-hardware-interrupts"), 477145351Sjkoshy EV_ALIAS(NULL, NULL) 478145256Sjkoshy}; 479145256Sjkoshy 480145256Sjkoshy#define K7_KW_COUNT "count" 481145256Sjkoshy#define K7_KW_EDGE "edge" 482145256Sjkoshy#define K7_KW_INV "inv" 483145256Sjkoshy#define K7_KW_OS "os" 484145256Sjkoshy#define K7_KW_UNITMASK "unitmask" 485145256Sjkoshy#define K7_KW_USR "usr" 486145256Sjkoshy 487145256Sjkoshystatic int 488145256Sjkoshyk7_allocate_pmc(enum pmc_event pe, char *ctrspec, 489145256Sjkoshy struct pmc_op_pmcallocate *pmc_config) 490145256Sjkoshy{ 491183107Sjkoshy char *e, *p, *q; 492183107Sjkoshy int c, has_unitmask; 493145256Sjkoshy uint32_t count, unitmask; 494145256Sjkoshy 495147191Sjkoshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 496183725Sjkoshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 497145256Sjkoshy 498145256Sjkoshy if (pe == PMC_EV_K7_DC_REFILLS_FROM_L2 || 499145256Sjkoshy pe == PMC_EV_K7_DC_REFILLS_FROM_SYSTEM || 500145256Sjkoshy pe == PMC_EV_K7_DC_WRITEBACKS) { 501145256Sjkoshy has_unitmask = 1; 502147191Sjkoshy unitmask = AMD_PMC_UNITMASK_MOESI; 503145256Sjkoshy } else 504145256Sjkoshy unitmask = has_unitmask = 0; 505145256Sjkoshy 506145256Sjkoshy while ((p = strsep(&ctrspec, ",")) != NULL) { 507145256Sjkoshy if (KWPREFIXMATCH(p, K7_KW_COUNT "=")) { 508145256Sjkoshy q = strchr(p, '='); 509145256Sjkoshy if (*++q == '\0') /* skip '=' */ 510174406Sjkoshy return (-1); 511145256Sjkoshy 512145256Sjkoshy count = strtol(q, &e, 0); 513145256Sjkoshy if (e == q || *e != '\0') 514174406Sjkoshy return (-1); 515145256Sjkoshy 516145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 517147191Sjkoshy pmc_config->pm_md.pm_amd.pm_amd_config |= 518147191Sjkoshy AMD_PMC_TO_COUNTER(count); 519145256Sjkoshy 520145256Sjkoshy } else if (KWMATCH(p, K7_KW_EDGE)) { 521145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_EDGE; 522145256Sjkoshy } else if (KWMATCH(p, K7_KW_INV)) { 523145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_INVERT; 524145256Sjkoshy } else if (KWMATCH(p, K7_KW_OS)) { 525145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 526145256Sjkoshy } else if (KWPREFIXMATCH(p, K7_KW_UNITMASK "=")) { 527145256Sjkoshy if (has_unitmask == 0) 528174406Sjkoshy return (-1); 529145256Sjkoshy unitmask = 0; 530145256Sjkoshy q = strchr(p, '='); 531145256Sjkoshy if (*++q == '\0') /* skip '=' */ 532174406Sjkoshy return (-1); 533145256Sjkoshy 534145256Sjkoshy while ((c = tolower(*q++)) != 0) 535145256Sjkoshy if (c == 'm') 536147191Sjkoshy unitmask |= AMD_PMC_UNITMASK_M; 537145256Sjkoshy else if (c == 'o') 538147191Sjkoshy unitmask |= AMD_PMC_UNITMASK_O; 539145256Sjkoshy else if (c == 'e') 540147191Sjkoshy unitmask |= AMD_PMC_UNITMASK_E; 541145256Sjkoshy else if (c == 's') 542147191Sjkoshy unitmask |= AMD_PMC_UNITMASK_S; 543145256Sjkoshy else if (c == 'i') 544147191Sjkoshy unitmask |= AMD_PMC_UNITMASK_I; 545145256Sjkoshy else if (c == '+') 546145256Sjkoshy continue; 547145256Sjkoshy else 548174406Sjkoshy return (-1); 549145256Sjkoshy 550145256Sjkoshy if (unitmask == 0) 551174406Sjkoshy return (-1); 552145256Sjkoshy 553145256Sjkoshy } else if (KWMATCH(p, K7_KW_USR)) { 554145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_USER; 555145256Sjkoshy } else 556174406Sjkoshy return (-1); 557145256Sjkoshy } 558145256Sjkoshy 559145256Sjkoshy if (has_unitmask) { 560145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 561147191Sjkoshy pmc_config->pm_md.pm_amd.pm_amd_config |= 562147191Sjkoshy AMD_PMC_TO_UNITMASK(unitmask); 563145256Sjkoshy } 564145256Sjkoshy 565174406Sjkoshy return (0); 566145256Sjkoshy 567145256Sjkoshy} 568145256Sjkoshy 569147191Sjkoshy#endif 570147191Sjkoshy 571147759Sjkoshy#if defined(__amd64__) || defined(__i386__) 572147191Sjkoshy 573145256Sjkoshy/* 574185363Sjkoshy * Intel Core (Family 6, Model E) PMCs. 575185363Sjkoshy */ 576185363Sjkoshy 577185363Sjkoshystatic struct pmc_event_alias core_aliases[] = { 578185363Sjkoshy EV_ALIAS("branches", "iap-br-instr-ret"), 579185363Sjkoshy EV_ALIAS("branch-mispredicts", "iap-br-mispred-ret"), 580185363Sjkoshy EV_ALIAS("cycles", "tsc-tsc"), 581185363Sjkoshy EV_ALIAS("ic-misses", "iap-icache-misses"), 582185363Sjkoshy EV_ALIAS("instructions", "iap-instr-ret"), 583185363Sjkoshy EV_ALIAS("interrupts", "iap-core-hw-int-rx"), 584185363Sjkoshy EV_ALIAS("unhalted-cycles", "iap-unhalted-core-cycles"), 585185363Sjkoshy EV_ALIAS(NULL, NULL) 586185363Sjkoshy}; 587185363Sjkoshy 588185363Sjkoshy/* 589185363Sjkoshy * Intel Core2 (Family 6, Model F), Core2Extreme (Family 6, Model 17H) 590185363Sjkoshy * and Atom (Family 6, model 1CH) PMCs. 591198433Sjkoshy * 592198433Sjkoshy * We map aliases to events on the fixed-function counters if these 593198433Sjkoshy * are present. Note that not all CPUs in this family contain fixed-function 594198433Sjkoshy * counters. 595185363Sjkoshy */ 596185363Sjkoshy 597185363Sjkoshystatic struct pmc_event_alias core2_aliases[] = { 598185363Sjkoshy EV_ALIAS("branches", "iap-br-inst-retired.any"), 599185363Sjkoshy EV_ALIAS("branch-mispredicts", "iap-br-inst-retired.mispred"), 600185363Sjkoshy EV_ALIAS("cycles", "tsc-tsc"), 601185363Sjkoshy EV_ALIAS("ic-misses", "iap-l1i-misses"), 602185363Sjkoshy EV_ALIAS("instructions", "iaf-instr-retired.any"), 603185363Sjkoshy EV_ALIAS("interrupts", "iap-hw-int-rcv"), 604185363Sjkoshy EV_ALIAS("unhalted-cycles", "iaf-cpu-clk-unhalted.core"), 605185363Sjkoshy EV_ALIAS(NULL, NULL) 606185363Sjkoshy}; 607185363Sjkoshy 608198433Sjkoshystatic struct pmc_event_alias core2_aliases_without_iaf[] = { 609198433Sjkoshy EV_ALIAS("branches", "iap-br-inst-retired.any"), 610198433Sjkoshy EV_ALIAS("branch-mispredicts", "iap-br-inst-retired.mispred"), 611198433Sjkoshy EV_ALIAS("cycles", "tsc-tsc"), 612198433Sjkoshy EV_ALIAS("ic-misses", "iap-l1i-misses"), 613198433Sjkoshy EV_ALIAS("instructions", "iap-inst-retired.any_p"), 614198433Sjkoshy EV_ALIAS("interrupts", "iap-hw-int-rcv"), 615198433Sjkoshy EV_ALIAS("unhalted-cycles", "iap-cpu-clk-unhalted.core_p"), 616198433Sjkoshy EV_ALIAS(NULL, NULL) 617198433Sjkoshy}; 618198433Sjkoshy 619198433Sjkoshy#define atom_aliases core2_aliases 620198433Sjkoshy#define atom_aliases_without_iaf core2_aliases_without_iaf 621266911Shiren#define atom_silvermont_aliases core2_aliases 622266911Shiren#define atom_silvermont_aliases_without_iaf core2_aliases_without_iaf 623198433Sjkoshy#define corei7_aliases core2_aliases 624198433Sjkoshy#define corei7_aliases_without_iaf core2_aliases_without_iaf 625267602Skib#define nehalem_ex_aliases core2_aliases 626267602Skib#define nehalem_ex_aliases_without_iaf core2_aliases_without_iaf 627248842Ssbruno#define haswell_aliases core2_aliases 628248842Ssbruno#define haswell_aliases_without_iaf core2_aliases_without_iaf 629240164Sfabient#define ivybridge_aliases core2_aliases 630240164Sfabient#define ivybridge_aliases_without_iaf core2_aliases_without_iaf 631246166Ssbruno#define ivybridge_xeon_aliases core2_aliases 632246166Ssbruno#define ivybridge_xeon_aliases_without_iaf core2_aliases_without_iaf 633232366Sdavide#define sandybridge_aliases core2_aliases 634232366Sdavide#define sandybridge_aliases_without_iaf core2_aliases_without_iaf 635241738Ssbruno#define sandybridge_xeon_aliases core2_aliases 636241738Ssbruno#define sandybridge_xeon_aliases_without_iaf core2_aliases_without_iaf 637206089Sfabient#define westmere_aliases core2_aliases 638206089Sfabient#define westmere_aliases_without_iaf core2_aliases_without_iaf 639267602Skib#define westmere_ex_aliases core2_aliases 640267602Skib#define westmere_ex_aliases_without_iaf core2_aliases_without_iaf 641198433Sjkoshy 642185363Sjkoshy#define IAF_KW_OS "os" 643185363Sjkoshy#define IAF_KW_USR "usr" 644185363Sjkoshy#define IAF_KW_ANYTHREAD "anythread" 645185363Sjkoshy 646185363Sjkoshy/* 647185363Sjkoshy * Parse an event specifier for Intel fixed function counters. 648185363Sjkoshy */ 649185363Sjkoshystatic int 650185363Sjkoshyiaf_allocate_pmc(enum pmc_event pe, char *ctrspec, 651185363Sjkoshy struct pmc_op_pmcallocate *pmc_config) 652185363Sjkoshy{ 653185363Sjkoshy char *p; 654185363Sjkoshy 655185363Sjkoshy (void) pe; 656185363Sjkoshy 657185363Sjkoshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 658185363Sjkoshy pmc_config->pm_md.pm_iaf.pm_iaf_flags = 0; 659185363Sjkoshy 660185363Sjkoshy while ((p = strsep(&ctrspec, ",")) != NULL) { 661185363Sjkoshy if (KWMATCH(p, IAF_KW_OS)) 662185363Sjkoshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 663185363Sjkoshy else if (KWMATCH(p, IAF_KW_USR)) 664185363Sjkoshy pmc_config->pm_caps |= PMC_CAP_USER; 665185363Sjkoshy else if (KWMATCH(p, IAF_KW_ANYTHREAD)) 666185363Sjkoshy pmc_config->pm_md.pm_iaf.pm_iaf_flags |= IAF_ANY; 667185363Sjkoshy else 668185363Sjkoshy return (-1); 669185363Sjkoshy } 670185363Sjkoshy 671185363Sjkoshy return (0); 672185363Sjkoshy} 673185363Sjkoshy 674185363Sjkoshy/* 675185363Sjkoshy * Core/Core2 support. 676185363Sjkoshy */ 677185363Sjkoshy 678185363Sjkoshy#define IAP_KW_AGENT "agent" 679185363Sjkoshy#define IAP_KW_ANYTHREAD "anythread" 680185363Sjkoshy#define IAP_KW_CACHESTATE "cachestate" 681185363Sjkoshy#define IAP_KW_CMASK "cmask" 682185363Sjkoshy#define IAP_KW_CORE "core" 683185363Sjkoshy#define IAP_KW_EDGE "edge" 684185363Sjkoshy#define IAP_KW_INV "inv" 685185363Sjkoshy#define IAP_KW_OS "os" 686185363Sjkoshy#define IAP_KW_PREFETCH "prefetch" 687185363Sjkoshy#define IAP_KW_SNOOPRESPONSE "snoopresponse" 688185363Sjkoshy#define IAP_KW_SNOOPTYPE "snooptype" 689185363Sjkoshy#define IAP_KW_TRANSITION "trans" 690185363Sjkoshy#define IAP_KW_USR "usr" 691206089Sfabient#define IAP_KW_RSP "rsp" 692185363Sjkoshy 693185363Sjkoshystatic struct pmc_masks iap_core_mask[] = { 694185363Sjkoshy PMCMASK(all, (0x3 << 14)), 695185363Sjkoshy PMCMASK(this, (0x1 << 14)), 696185363Sjkoshy NULLMASK 697185363Sjkoshy}; 698185363Sjkoshy 699185363Sjkoshystatic struct pmc_masks iap_agent_mask[] = { 700185363Sjkoshy PMCMASK(this, 0), 701185363Sjkoshy PMCMASK(any, (0x1 << 13)), 702185363Sjkoshy NULLMASK 703185363Sjkoshy}; 704185363Sjkoshy 705185363Sjkoshystatic struct pmc_masks iap_prefetch_mask[] = { 706185363Sjkoshy PMCMASK(both, (0x3 << 12)), 707185363Sjkoshy PMCMASK(only, (0x1 << 12)), 708185363Sjkoshy PMCMASK(exclude, 0), 709185363Sjkoshy NULLMASK 710185363Sjkoshy}; 711185363Sjkoshy 712185363Sjkoshystatic struct pmc_masks iap_cachestate_mask[] = { 713185363Sjkoshy PMCMASK(i, (1 << 8)), 714185363Sjkoshy PMCMASK(s, (1 << 9)), 715185363Sjkoshy PMCMASK(e, (1 << 10)), 716185363Sjkoshy PMCMASK(m, (1 << 11)), 717185363Sjkoshy NULLMASK 718185363Sjkoshy}; 719185363Sjkoshy 720185363Sjkoshystatic struct pmc_masks iap_snoopresponse_mask[] = { 721185363Sjkoshy PMCMASK(clean, (1 << 8)), 722185363Sjkoshy PMCMASK(hit, (1 << 9)), 723185363Sjkoshy PMCMASK(hitm, (1 << 11)), 724185363Sjkoshy NULLMASK 725185363Sjkoshy}; 726185363Sjkoshy 727185363Sjkoshystatic struct pmc_masks iap_snooptype_mask[] = { 728185363Sjkoshy PMCMASK(cmp2s, (1 << 8)), 729185363Sjkoshy PMCMASK(cmp2i, (1 << 9)), 730185363Sjkoshy NULLMASK 731185363Sjkoshy}; 732185363Sjkoshy 733185363Sjkoshystatic struct pmc_masks iap_transition_mask[] = { 734185363Sjkoshy PMCMASK(any, 0x00), 735185363Sjkoshy PMCMASK(frequency, 0x10), 736185363Sjkoshy NULLMASK 737185363Sjkoshy}; 738185363Sjkoshy 739240164Sfabientstatic struct pmc_masks iap_rsp_mask_i7_wm[] = { 740206089Sfabient PMCMASK(DMND_DATA_RD, (1 << 0)), 741206089Sfabient PMCMASK(DMND_RFO, (1 << 1)), 742206089Sfabient PMCMASK(DMND_IFETCH, (1 << 2)), 743206089Sfabient PMCMASK(WB, (1 << 3)), 744206089Sfabient PMCMASK(PF_DATA_RD, (1 << 4)), 745206089Sfabient PMCMASK(PF_RFO, (1 << 5)), 746206089Sfabient PMCMASK(PF_IFETCH, (1 << 6)), 747206089Sfabient PMCMASK(OTHER, (1 << 7)), 748206089Sfabient PMCMASK(UNCORE_HIT, (1 << 8)), 749206089Sfabient PMCMASK(OTHER_CORE_HIT_SNP, (1 << 9)), 750206089Sfabient PMCMASK(OTHER_CORE_HITM, (1 << 10)), 751206089Sfabient PMCMASK(REMOTE_CACHE_FWD, (1 << 12)), 752206089Sfabient PMCMASK(REMOTE_DRAM, (1 << 13)), 753206089Sfabient PMCMASK(LOCAL_DRAM, (1 << 14)), 754206089Sfabient PMCMASK(NON_DRAM, (1 << 15)), 755206089Sfabient NULLMASK 756206089Sfabient}; 757206089Sfabient 758241738Ssbrunostatic struct pmc_masks iap_rsp_mask_sb_sbx_ib[] = { 759240164Sfabient PMCMASK(REQ_DMND_DATA_RD, (1ULL << 0)), 760240164Sfabient PMCMASK(REQ_DMND_RFO, (1ULL << 1)), 761240164Sfabient PMCMASK(REQ_DMND_IFETCH, (1ULL << 2)), 762240164Sfabient PMCMASK(REQ_WB, (1ULL << 3)), 763240164Sfabient PMCMASK(REQ_PF_DATA_RD, (1ULL << 4)), 764240164Sfabient PMCMASK(REQ_PF_RFO, (1ULL << 5)), 765240164Sfabient PMCMASK(REQ_PF_IFETCH, (1ULL << 6)), 766240164Sfabient PMCMASK(REQ_PF_LLC_DATA_RD, (1ULL << 7)), 767240164Sfabient PMCMASK(REQ_PF_LLC_RFO, (1ULL << 8)), 768240164Sfabient PMCMASK(REQ_PF_LLC_IFETCH, (1ULL << 9)), 769240164Sfabient PMCMASK(REQ_BUS_LOCKS, (1ULL << 10)), 770240164Sfabient PMCMASK(REQ_STRM_ST, (1ULL << 11)), 771240164Sfabient PMCMASK(REQ_OTHER, (1ULL << 15)), 772240164Sfabient PMCMASK(RES_ANY, (1ULL << 16)), 773240164Sfabient PMCMASK(RES_SUPPLIER_SUPP, (1ULL << 17)), 774240164Sfabient PMCMASK(RES_SUPPLIER_LLC_HITM, (1ULL << 18)), 775240164Sfabient PMCMASK(RES_SUPPLIER_LLC_HITE, (1ULL << 19)), 776240164Sfabient PMCMASK(RES_SUPPLIER_LLC_HITS, (1ULL << 20)), 777240164Sfabient PMCMASK(RES_SUPPLIER_LLC_HITF, (1ULL << 21)), 778240164Sfabient PMCMASK(RES_SUPPLIER_LOCAL, (1ULL << 22)), 779241974Ssbruno PMCMASK(RES_SNOOP_SNP_NONE, (1ULL << 31)), 780240164Sfabient PMCMASK(RES_SNOOP_SNP_NO_NEEDED,(1ULL << 32)), 781240164Sfabient PMCMASK(RES_SNOOP_SNP_MISS, (1ULL << 33)), 782240164Sfabient PMCMASK(RES_SNOOP_HIT_NO_FWD, (1ULL << 34)), 783240164Sfabient PMCMASK(RES_SNOOP_HIT_FWD, (1ULL << 35)), 784240164Sfabient PMCMASK(RES_SNOOP_HITM, (1ULL << 36)), 785240164Sfabient PMCMASK(RES_NON_DRAM, (1ULL << 37)), 786240164Sfabient NULLMASK 787240164Sfabient}; 788240164Sfabient 789248842Ssbrunostatic struct pmc_masks iap_rsp_mask_haswell[] = { 790248842Ssbruno PMCMASK(REQ_DMND_DATA_RD, (1ULL << 0)), 791248842Ssbruno PMCMASK(REQ_DMND_RFO, (1ULL << 1)), 792248842Ssbruno PMCMASK(REQ_DMND_IFETCH, (1ULL << 2)), 793248842Ssbruno PMCMASK(REQ_PF_DATA_RD, (1ULL << 4)), 794248842Ssbruno PMCMASK(REQ_PF_RFO, (1ULL << 5)), 795248842Ssbruno PMCMASK(REQ_PF_IFETCH, (1ULL << 6)), 796248842Ssbruno PMCMASK(REQ_OTHER, (1ULL << 15)), 797248842Ssbruno PMCMASK(RES_ANY, (1ULL << 16)), 798248842Ssbruno PMCMASK(RES_SUPPLIER_SUPP, (1ULL << 17)), 799248842Ssbruno PMCMASK(RES_SUPPLIER_LLC_HITM, (1ULL << 18)), 800248842Ssbruno PMCMASK(RES_SUPPLIER_LLC_HITE, (1ULL << 19)), 801248842Ssbruno PMCMASK(RES_SUPPLIER_LLC_HITS, (1ULL << 20)), 802248842Ssbruno PMCMASK(RES_SUPPLIER_LLC_HITF, (1ULL << 21)), 803248842Ssbruno PMCMASK(RES_SUPPLIER_LOCAL, (1ULL << 22)), 804248842Ssbruno PMCMASK(RES_SNOOP_SNP_NONE, (1ULL << 31)), 805248842Ssbruno PMCMASK(RES_SNOOP_SNP_NO_NEEDED,(1ULL << 32)), 806248842Ssbruno PMCMASK(RES_SNOOP_SNP_MISS, (1ULL << 33)), 807248842Ssbruno PMCMASK(RES_SNOOP_HIT_NO_FWD, (1ULL << 34)), 808248842Ssbruno PMCMASK(RES_SNOOP_HIT_FWD, (1ULL << 35)), 809248842Ssbruno PMCMASK(RES_SNOOP_HITM, (1ULL << 36)), 810248842Ssbruno PMCMASK(RES_NON_DRAM, (1ULL << 37)), 811248842Ssbruno NULLMASK 812248842Ssbruno}; 813248842Ssbruno 814185363Sjkoshystatic int 815185363Sjkoshyiap_allocate_pmc(enum pmc_event pe, char *ctrspec, 816185363Sjkoshy struct pmc_op_pmcallocate *pmc_config) 817185363Sjkoshy{ 818185363Sjkoshy char *e, *p, *q; 819240164Sfabient uint64_t cachestate, evmask, rsp; 820185363Sjkoshy int count, n; 821185363Sjkoshy 822185363Sjkoshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE | 823185363Sjkoshy PMC_CAP_QUALIFIER); 824185363Sjkoshy pmc_config->pm_md.pm_iap.pm_iap_config = 0; 825185363Sjkoshy 826206089Sfabient cachestate = evmask = rsp = 0; 827185363Sjkoshy 828185363Sjkoshy /* Parse additional modifiers if present */ 829185363Sjkoshy while ((p = strsep(&ctrspec, ",")) != NULL) { 830185363Sjkoshy 831185363Sjkoshy n = 0; 832185363Sjkoshy if (KWPREFIXMATCH(p, IAP_KW_CMASK "=")) { 833185363Sjkoshy q = strchr(p, '='); 834185363Sjkoshy if (*++q == '\0') /* skip '=' */ 835185363Sjkoshy return (-1); 836185363Sjkoshy count = strtol(q, &e, 0); 837185363Sjkoshy if (e == q || *e != '\0') 838185363Sjkoshy return (-1); 839185363Sjkoshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 840185363Sjkoshy pmc_config->pm_md.pm_iap.pm_iap_config |= 841185363Sjkoshy IAP_CMASK(count); 842185363Sjkoshy } else if (KWMATCH(p, IAP_KW_EDGE)) { 843185363Sjkoshy pmc_config->pm_caps |= PMC_CAP_EDGE; 844185363Sjkoshy } else if (KWMATCH(p, IAP_KW_INV)) { 845185363Sjkoshy pmc_config->pm_caps |= PMC_CAP_INVERT; 846185363Sjkoshy } else if (KWMATCH(p, IAP_KW_OS)) { 847185363Sjkoshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 848185363Sjkoshy } else if (KWMATCH(p, IAP_KW_USR)) { 849185363Sjkoshy pmc_config->pm_caps |= PMC_CAP_USER; 850185363Sjkoshy } else if (KWMATCH(p, IAP_KW_ANYTHREAD)) { 851185363Sjkoshy pmc_config->pm_md.pm_iap.pm_iap_config |= IAP_ANY; 852193809Sjkoshy } else if (KWPREFIXMATCH(p, IAP_KW_CORE "=")) { 853185363Sjkoshy n = pmc_parse_mask(iap_core_mask, p, &evmask); 854185363Sjkoshy if (n != 1) 855185363Sjkoshy return (-1); 856193809Sjkoshy } else if (KWPREFIXMATCH(p, IAP_KW_AGENT "=")) { 857185363Sjkoshy n = pmc_parse_mask(iap_agent_mask, p, &evmask); 858185363Sjkoshy if (n != 1) 859185363Sjkoshy return (-1); 860193809Sjkoshy } else if (KWPREFIXMATCH(p, IAP_KW_PREFETCH "=")) { 861185363Sjkoshy n = pmc_parse_mask(iap_prefetch_mask, p, &evmask); 862185363Sjkoshy if (n != 1) 863185363Sjkoshy return (-1); 864193809Sjkoshy } else if (KWPREFIXMATCH(p, IAP_KW_CACHESTATE "=")) { 865185363Sjkoshy n = pmc_parse_mask(iap_cachestate_mask, p, &cachestate); 866185363Sjkoshy } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_CORE && 867193809Sjkoshy KWPREFIXMATCH(p, IAP_KW_TRANSITION "=")) { 868185363Sjkoshy n = pmc_parse_mask(iap_transition_mask, p, &evmask); 869185363Sjkoshy if (n != 1) 870185363Sjkoshy return (-1); 871185363Sjkoshy } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM || 872266911Shiren cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM_SILVERMONT || 873185585Sjkoshy cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2 || 874206089Sfabient cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2EXTREME) { 875193809Sjkoshy if (KWPREFIXMATCH(p, IAP_KW_SNOOPRESPONSE "=")) { 876185363Sjkoshy n = pmc_parse_mask(iap_snoopresponse_mask, p, 877185363Sjkoshy &evmask); 878193809Sjkoshy } else if (KWPREFIXMATCH(p, IAP_KW_SNOOPTYPE "=")) { 879185363Sjkoshy n = pmc_parse_mask(iap_snooptype_mask, p, 880185363Sjkoshy &evmask); 881185363Sjkoshy } else 882185363Sjkoshy return (-1); 883206089Sfabient } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_COREI7 || 884267602Skib cpu_info.pm_cputype == PMC_CPU_INTEL_WESTMERE || 885267602Skib cpu_info.pm_cputype == PMC_CPU_INTEL_NEHALEM_EX || 886267602Skib cpu_info.pm_cputype == PMC_CPU_INTEL_WESTMERE_EX) { 887206089Sfabient if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 888240164Sfabient n = pmc_parse_mask(iap_rsp_mask_i7_wm, p, &rsp); 889206089Sfabient } else 890206089Sfabient return (-1); 891240164Sfabient } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_SANDYBRIDGE || 892241738Ssbruno cpu_info.pm_cputype == PMC_CPU_INTEL_SANDYBRIDGE_XEON || 893246166Ssbruno cpu_info.pm_cputype == PMC_CPU_INTEL_IVYBRIDGE || 894246166Ssbruno cpu_info.pm_cputype == PMC_CPU_INTEL_IVYBRIDGE_XEON ) { 895240164Sfabient if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 896241738Ssbruno n = pmc_parse_mask(iap_rsp_mask_sb_sbx_ib, p, &rsp); 897240164Sfabient } else 898240164Sfabient return (-1); 899248842Ssbruno } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_HASWELL) { 900248842Ssbruno if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 901248842Ssbruno n = pmc_parse_mask(iap_rsp_mask_haswell, p, &rsp); 902248842Ssbruno } else 903248842Ssbruno return (-1); 904185363Sjkoshy } else 905185363Sjkoshy return (-1); 906185363Sjkoshy 907185363Sjkoshy if (n < 0) /* Parsing failed. */ 908185363Sjkoshy return (-1); 909185363Sjkoshy } 910185363Sjkoshy 911185363Sjkoshy pmc_config->pm_md.pm_iap.pm_iap_config |= evmask; 912185363Sjkoshy 913185363Sjkoshy /* 914185363Sjkoshy * If the event requires a 'cachestate' qualifier but was not 915185363Sjkoshy * specified by the user, use a sensible default. 916185363Sjkoshy */ 917185363Sjkoshy switch (pe) { 918185363Sjkoshy case PMC_EV_IAP_EVENT_28H: /* Core, Core2, Atom */ 919185363Sjkoshy case PMC_EV_IAP_EVENT_29H: /* Core, Core2, Atom */ 920185363Sjkoshy case PMC_EV_IAP_EVENT_2AH: /* Core, Core2, Atom */ 921185363Sjkoshy case PMC_EV_IAP_EVENT_2BH: /* Atom, Core2 */ 922185363Sjkoshy case PMC_EV_IAP_EVENT_2EH: /* Core, Core2, Atom */ 923185363Sjkoshy case PMC_EV_IAP_EVENT_30H: /* Core, Core2, Atom */ 924185363Sjkoshy case PMC_EV_IAP_EVENT_32H: /* Core */ 925185363Sjkoshy case PMC_EV_IAP_EVENT_40H: /* Core */ 926185363Sjkoshy case PMC_EV_IAP_EVENT_41H: /* Core */ 927185363Sjkoshy case PMC_EV_IAP_EVENT_42H: /* Core, Core2, Atom */ 928185363Sjkoshy if (cachestate == 0) 929185363Sjkoshy cachestate = (0xF << 8); 930207482Srstone break; 931207482Srstone case PMC_EV_IAP_EVENT_77H: /* Atom */ 932207482Srstone /* IAP_EVENT_77H only accepts a cachestate qualifier on the 933207482Srstone * Atom processor 934207482Srstone */ 935207482Srstone if(cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM && cachestate == 0) 936207482Srstone cachestate = (0xF << 8); 937207482Srstone break; 938185363Sjkoshy default: 939185363Sjkoshy break; 940185363Sjkoshy } 941185363Sjkoshy 942185363Sjkoshy pmc_config->pm_md.pm_iap.pm_iap_config |= cachestate; 943206089Sfabient pmc_config->pm_md.pm_iap.pm_iap_rsp = rsp; 944185363Sjkoshy 945185363Sjkoshy return (0); 946185363Sjkoshy} 947185363Sjkoshy 948185363Sjkoshy/* 949206089Sfabient * Intel Uncore. 950206089Sfabient */ 951206089Sfabient 952206089Sfabientstatic int 953206089Sfabientucf_allocate_pmc(enum pmc_event pe, char *ctrspec, 954206089Sfabient struct pmc_op_pmcallocate *pmc_config) 955206089Sfabient{ 956206089Sfabient (void) pe; 957206089Sfabient (void) ctrspec; 958206089Sfabient 959206089Sfabient pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 960206089Sfabient pmc_config->pm_md.pm_ucf.pm_ucf_flags = 0; 961206089Sfabient 962206089Sfabient return (0); 963206089Sfabient} 964206089Sfabient 965206089Sfabient#define UCP_KW_CMASK "cmask" 966206089Sfabient#define UCP_KW_EDGE "edge" 967206089Sfabient#define UCP_KW_INV "inv" 968206089Sfabient 969206089Sfabientstatic int 970206089Sfabientucp_allocate_pmc(enum pmc_event pe, char *ctrspec, 971206089Sfabient struct pmc_op_pmcallocate *pmc_config) 972206089Sfabient{ 973206089Sfabient char *e, *p, *q; 974206089Sfabient int count, n; 975206089Sfabient 976206089Sfabient (void) pe; 977206089Sfabient 978206089Sfabient pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE | 979206089Sfabient PMC_CAP_QUALIFIER); 980206089Sfabient pmc_config->pm_md.pm_ucp.pm_ucp_config = 0; 981206089Sfabient 982206089Sfabient /* Parse additional modifiers if present */ 983206089Sfabient while ((p = strsep(&ctrspec, ",")) != NULL) { 984206089Sfabient 985206089Sfabient n = 0; 986206089Sfabient if (KWPREFIXMATCH(p, UCP_KW_CMASK "=")) { 987206089Sfabient q = strchr(p, '='); 988206089Sfabient if (*++q == '\0') /* skip '=' */ 989206089Sfabient return (-1); 990206089Sfabient count = strtol(q, &e, 0); 991206089Sfabient if (e == q || *e != '\0') 992206089Sfabient return (-1); 993206089Sfabient pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 994206089Sfabient pmc_config->pm_md.pm_ucp.pm_ucp_config |= 995206089Sfabient UCP_CMASK(count); 996206089Sfabient } else if (KWMATCH(p, UCP_KW_EDGE)) { 997206089Sfabient pmc_config->pm_caps |= PMC_CAP_EDGE; 998206089Sfabient } else if (KWMATCH(p, UCP_KW_INV)) { 999206089Sfabient pmc_config->pm_caps |= PMC_CAP_INVERT; 1000206089Sfabient } else 1001206089Sfabient return (-1); 1002206089Sfabient 1003206089Sfabient if (n < 0) /* Parsing failed. */ 1004206089Sfabient return (-1); 1005206089Sfabient } 1006206089Sfabient 1007206089Sfabient return (0); 1008206089Sfabient} 1009206089Sfabient 1010206089Sfabient/* 1011147191Sjkoshy * AMD K8 PMCs. 1012147191Sjkoshy * 1013147191Sjkoshy * These are very similar to AMD K7 PMCs, but support more kinds of 1014147191Sjkoshy * events. 1015147191Sjkoshy */ 1016147191Sjkoshy 1017147191Sjkoshystatic struct pmc_event_alias k8_aliases[] = { 1018147191Sjkoshy EV_ALIAS("branches", "k8-fr-retired-taken-branches"), 1019147191Sjkoshy EV_ALIAS("branch-mispredicts", 1020147191Sjkoshy "k8-fr-retired-taken-branches-mispredicted"), 1021147191Sjkoshy EV_ALIAS("cycles", "tsc"), 1022147191Sjkoshy EV_ALIAS("dc-misses", "k8-dc-miss"), 1023147191Sjkoshy EV_ALIAS("ic-misses", "k8-ic-miss"), 1024183107Sjkoshy EV_ALIAS("instructions", "k8-fr-retired-x86-instructions"), 1025147191Sjkoshy EV_ALIAS("interrupts", "k8-fr-taken-hardware-interrupts"), 1026155998Sjkoshy EV_ALIAS("unhalted-cycles", "k8-bu-cpu-clk-unhalted"), 1027147191Sjkoshy EV_ALIAS(NULL, NULL) 1028147191Sjkoshy}; 1029147191Sjkoshy 1030147191Sjkoshy#define __K8MASK(N,V) PMCMASK(N,(1 << (V))) 1031147191Sjkoshy 1032147191Sjkoshy/* 1033147191Sjkoshy * Parsing tables 1034147191Sjkoshy */ 1035147191Sjkoshy 1036147191Sjkoshy/* fp dispatched fpu ops */ 1037147191Sjkoshystatic const struct pmc_masks k8_mask_fdfo[] = { 1038147191Sjkoshy __K8MASK(add-pipe-excluding-junk-ops, 0), 1039147191Sjkoshy __K8MASK(multiply-pipe-excluding-junk-ops, 1), 1040147191Sjkoshy __K8MASK(store-pipe-excluding-junk-ops, 2), 1041147191Sjkoshy __K8MASK(add-pipe-junk-ops, 3), 1042147191Sjkoshy __K8MASK(multiply-pipe-junk-ops, 4), 1043147191Sjkoshy __K8MASK(store-pipe-junk-ops, 5), 1044147191Sjkoshy NULLMASK 1045147191Sjkoshy}; 1046147191Sjkoshy 1047147191Sjkoshy/* ls segment register loads */ 1048147191Sjkoshystatic const struct pmc_masks k8_mask_lsrl[] = { 1049147191Sjkoshy __K8MASK(es, 0), 1050147191Sjkoshy __K8MASK(cs, 1), 1051147191Sjkoshy __K8MASK(ss, 2), 1052147191Sjkoshy __K8MASK(ds, 3), 1053147191Sjkoshy __K8MASK(fs, 4), 1054147191Sjkoshy __K8MASK(gs, 5), 1055147191Sjkoshy __K8MASK(hs, 6), 1056147191Sjkoshy NULLMASK 1057147191Sjkoshy}; 1058147191Sjkoshy 1059147191Sjkoshy/* ls locked operation */ 1060147191Sjkoshystatic const struct pmc_masks k8_mask_llo[] = { 1061147191Sjkoshy __K8MASK(locked-instructions, 0), 1062147191Sjkoshy __K8MASK(cycles-in-request, 1), 1063147191Sjkoshy __K8MASK(cycles-to-complete, 2), 1064147191Sjkoshy NULLMASK 1065147191Sjkoshy}; 1066147191Sjkoshy 1067147191Sjkoshy/* dc refill from {l2,system} and dc copyback */ 1068147191Sjkoshystatic const struct pmc_masks k8_mask_dc[] = { 1069147191Sjkoshy __K8MASK(invalid, 0), 1070147191Sjkoshy __K8MASK(shared, 1), 1071147191Sjkoshy __K8MASK(exclusive, 2), 1072147191Sjkoshy __K8MASK(owner, 3), 1073147191Sjkoshy __K8MASK(modified, 4), 1074147191Sjkoshy NULLMASK 1075147191Sjkoshy}; 1076147191Sjkoshy 1077147191Sjkoshy/* dc one bit ecc error */ 1078147191Sjkoshystatic const struct pmc_masks k8_mask_dobee[] = { 1079147191Sjkoshy __K8MASK(scrubber, 0), 1080147191Sjkoshy __K8MASK(piggyback, 1), 1081147191Sjkoshy NULLMASK 1082147191Sjkoshy}; 1083147191Sjkoshy 1084147191Sjkoshy/* dc dispatched prefetch instructions */ 1085147191Sjkoshystatic const struct pmc_masks k8_mask_ddpi[] = { 1086147191Sjkoshy __K8MASK(load, 0), 1087147191Sjkoshy __K8MASK(store, 1), 1088147191Sjkoshy __K8MASK(nta, 2), 1089147191Sjkoshy NULLMASK 1090147191Sjkoshy}; 1091147191Sjkoshy 1092147191Sjkoshy/* dc dcache accesses by locks */ 1093147191Sjkoshystatic const struct pmc_masks k8_mask_dabl[] = { 1094147191Sjkoshy __K8MASK(accesses, 0), 1095147191Sjkoshy __K8MASK(misses, 1), 1096147191Sjkoshy NULLMASK 1097147191Sjkoshy}; 1098147191Sjkoshy 1099147191Sjkoshy/* bu internal l2 request */ 1100147191Sjkoshystatic const struct pmc_masks k8_mask_bilr[] = { 1101147191Sjkoshy __K8MASK(ic-fill, 0), 1102147191Sjkoshy __K8MASK(dc-fill, 1), 1103147191Sjkoshy __K8MASK(tlb-reload, 2), 1104147191Sjkoshy __K8MASK(tag-snoop, 3), 1105147191Sjkoshy __K8MASK(cancelled, 4), 1106147191Sjkoshy NULLMASK 1107147191Sjkoshy}; 1108147191Sjkoshy 1109147191Sjkoshy/* bu fill request l2 miss */ 1110147191Sjkoshystatic const struct pmc_masks k8_mask_bfrlm[] = { 1111147191Sjkoshy __K8MASK(ic-fill, 0), 1112147191Sjkoshy __K8MASK(dc-fill, 1), 1113147191Sjkoshy __K8MASK(tlb-reload, 2), 1114147191Sjkoshy NULLMASK 1115147191Sjkoshy}; 1116147191Sjkoshy 1117147191Sjkoshy/* bu fill into l2 */ 1118147191Sjkoshystatic const struct pmc_masks k8_mask_bfil[] = { 1119147191Sjkoshy __K8MASK(dirty-l2-victim, 0), 1120147191Sjkoshy __K8MASK(victim-from-l2, 1), 1121147191Sjkoshy NULLMASK 1122147191Sjkoshy}; 1123147191Sjkoshy 1124147191Sjkoshy/* fr retired fpu instructions */ 1125147191Sjkoshystatic const struct pmc_masks k8_mask_frfi[] = { 1126147191Sjkoshy __K8MASK(x87, 0), 1127147191Sjkoshy __K8MASK(mmx-3dnow, 1), 1128147191Sjkoshy __K8MASK(packed-sse-sse2, 2), 1129147191Sjkoshy __K8MASK(scalar-sse-sse2, 3), 1130147191Sjkoshy NULLMASK 1131147191Sjkoshy}; 1132147191Sjkoshy 1133147191Sjkoshy/* fr retired fastpath double op instructions */ 1134147191Sjkoshystatic const struct pmc_masks k8_mask_frfdoi[] = { 1135147191Sjkoshy __K8MASK(low-op-pos-0, 0), 1136147191Sjkoshy __K8MASK(low-op-pos-1, 1), 1137147191Sjkoshy __K8MASK(low-op-pos-2, 2), 1138147191Sjkoshy NULLMASK 1139147191Sjkoshy}; 1140147191Sjkoshy 1141147191Sjkoshy/* fr fpu exceptions */ 1142147191Sjkoshystatic const struct pmc_masks k8_mask_ffe[] = { 1143147191Sjkoshy __K8MASK(x87-reclass-microfaults, 0), 1144147191Sjkoshy __K8MASK(sse-retype-microfaults, 1), 1145147191Sjkoshy __K8MASK(sse-reclass-microfaults, 2), 1146147191Sjkoshy __K8MASK(sse-and-x87-microtraps, 3), 1147147191Sjkoshy NULLMASK 1148147191Sjkoshy}; 1149147191Sjkoshy 1150147191Sjkoshy/* nb memory controller page access event */ 1151147191Sjkoshystatic const struct pmc_masks k8_mask_nmcpae[] = { 1152147191Sjkoshy __K8MASK(page-hit, 0), 1153147191Sjkoshy __K8MASK(page-miss, 1), 1154147191Sjkoshy __K8MASK(page-conflict, 2), 1155147191Sjkoshy NULLMASK 1156147191Sjkoshy}; 1157147191Sjkoshy 1158147191Sjkoshy/* nb memory controller turnaround */ 1159147191Sjkoshystatic const struct pmc_masks k8_mask_nmct[] = { 1160147191Sjkoshy __K8MASK(dimm-turnaround, 0), 1161147191Sjkoshy __K8MASK(read-to-write-turnaround, 1), 1162147191Sjkoshy __K8MASK(write-to-read-turnaround, 2), 1163147191Sjkoshy NULLMASK 1164147191Sjkoshy}; 1165147191Sjkoshy 1166147191Sjkoshy/* nb memory controller bypass saturation */ 1167147191Sjkoshystatic const struct pmc_masks k8_mask_nmcbs[] = { 1168147191Sjkoshy __K8MASK(memory-controller-hi-pri-bypass, 0), 1169147191Sjkoshy __K8MASK(memory-controller-lo-pri-bypass, 1), 1170147191Sjkoshy __K8MASK(dram-controller-interface-bypass, 2), 1171147191Sjkoshy __K8MASK(dram-controller-queue-bypass, 3), 1172147191Sjkoshy NULLMASK 1173147191Sjkoshy}; 1174147191Sjkoshy 1175147191Sjkoshy/* nb sized commands */ 1176147191Sjkoshystatic const struct pmc_masks k8_mask_nsc[] = { 1177147191Sjkoshy __K8MASK(nonpostwrszbyte, 0), 1178147191Sjkoshy __K8MASK(nonpostwrszdword, 1), 1179147191Sjkoshy __K8MASK(postwrszbyte, 2), 1180147191Sjkoshy __K8MASK(postwrszdword, 3), 1181147191Sjkoshy __K8MASK(rdszbyte, 4), 1182147191Sjkoshy __K8MASK(rdszdword, 5), 1183147191Sjkoshy __K8MASK(rdmodwr, 6), 1184147191Sjkoshy NULLMASK 1185147191Sjkoshy}; 1186147191Sjkoshy 1187147191Sjkoshy/* nb probe result */ 1188147191Sjkoshystatic const struct pmc_masks k8_mask_npr[] = { 1189147191Sjkoshy __K8MASK(probe-miss, 0), 1190147191Sjkoshy __K8MASK(probe-hit, 1), 1191147191Sjkoshy __K8MASK(probe-hit-dirty-no-memory-cancel, 2), 1192147191Sjkoshy __K8MASK(probe-hit-dirty-with-memory-cancel, 3), 1193147191Sjkoshy NULLMASK 1194147191Sjkoshy}; 1195147191Sjkoshy 1196147191Sjkoshy/* nb hypertransport bus bandwidth */ 1197147191Sjkoshystatic const struct pmc_masks k8_mask_nhbb[] = { /* HT bus bandwidth */ 1198147191Sjkoshy __K8MASK(command, 0), 1199183107Sjkoshy __K8MASK(data, 1), 1200147191Sjkoshy __K8MASK(buffer-release, 2), 1201147191Sjkoshy __K8MASK(nop, 3), 1202147191Sjkoshy NULLMASK 1203147191Sjkoshy}; 1204147191Sjkoshy 1205147191Sjkoshy#undef __K8MASK 1206147191Sjkoshy 1207147191Sjkoshy#define K8_KW_COUNT "count" 1208147191Sjkoshy#define K8_KW_EDGE "edge" 1209147191Sjkoshy#define K8_KW_INV "inv" 1210147191Sjkoshy#define K8_KW_MASK "mask" 1211147191Sjkoshy#define K8_KW_OS "os" 1212147191Sjkoshy#define K8_KW_USR "usr" 1213147191Sjkoshy 1214147191Sjkoshystatic int 1215147191Sjkoshyk8_allocate_pmc(enum pmc_event pe, char *ctrspec, 1216147191Sjkoshy struct pmc_op_pmcallocate *pmc_config) 1217147191Sjkoshy{ 1218183107Sjkoshy char *e, *p, *q; 1219183107Sjkoshy int n; 1220240164Sfabient uint32_t count; 1221240164Sfabient uint64_t evmask; 1222147191Sjkoshy const struct pmc_masks *pm, *pmask; 1223147191Sjkoshy 1224183725Sjkoshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1225147191Sjkoshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 1226147191Sjkoshy 1227147191Sjkoshy pmask = NULL; 1228147191Sjkoshy evmask = 0; 1229147191Sjkoshy 1230147191Sjkoshy#define __K8SETMASK(M) pmask = k8_mask_##M 1231147191Sjkoshy 1232147191Sjkoshy /* setup parsing tables */ 1233147191Sjkoshy switch (pe) { 1234147191Sjkoshy case PMC_EV_K8_FP_DISPATCHED_FPU_OPS: 1235147191Sjkoshy __K8SETMASK(fdfo); 1236147191Sjkoshy break; 1237147191Sjkoshy case PMC_EV_K8_LS_SEGMENT_REGISTER_LOAD: 1238147191Sjkoshy __K8SETMASK(lsrl); 1239147191Sjkoshy break; 1240147191Sjkoshy case PMC_EV_K8_LS_LOCKED_OPERATION: 1241147191Sjkoshy __K8SETMASK(llo); 1242147191Sjkoshy break; 1243147191Sjkoshy case PMC_EV_K8_DC_REFILL_FROM_L2: 1244147191Sjkoshy case PMC_EV_K8_DC_REFILL_FROM_SYSTEM: 1245147191Sjkoshy case PMC_EV_K8_DC_COPYBACK: 1246147191Sjkoshy __K8SETMASK(dc); 1247147191Sjkoshy break; 1248147191Sjkoshy case PMC_EV_K8_DC_ONE_BIT_ECC_ERROR: 1249147191Sjkoshy __K8SETMASK(dobee); 1250147191Sjkoshy break; 1251147191Sjkoshy case PMC_EV_K8_DC_DISPATCHED_PREFETCH_INSTRUCTIONS: 1252147191Sjkoshy __K8SETMASK(ddpi); 1253147191Sjkoshy break; 1254147191Sjkoshy case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS: 1255147191Sjkoshy __K8SETMASK(dabl); 1256147191Sjkoshy break; 1257147191Sjkoshy case PMC_EV_K8_BU_INTERNAL_L2_REQUEST: 1258147191Sjkoshy __K8SETMASK(bilr); 1259147191Sjkoshy break; 1260147191Sjkoshy case PMC_EV_K8_BU_FILL_REQUEST_L2_MISS: 1261147191Sjkoshy __K8SETMASK(bfrlm); 1262147191Sjkoshy break; 1263147191Sjkoshy case PMC_EV_K8_BU_FILL_INTO_L2: 1264147191Sjkoshy __K8SETMASK(bfil); 1265147191Sjkoshy break; 1266147191Sjkoshy case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS: 1267147191Sjkoshy __K8SETMASK(frfi); 1268147191Sjkoshy break; 1269147191Sjkoshy case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS: 1270147191Sjkoshy __K8SETMASK(frfdoi); 1271147191Sjkoshy break; 1272147191Sjkoshy case PMC_EV_K8_FR_FPU_EXCEPTIONS: 1273147191Sjkoshy __K8SETMASK(ffe); 1274147191Sjkoshy break; 1275147191Sjkoshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_PAGE_ACCESS_EVENT: 1276147191Sjkoshy __K8SETMASK(nmcpae); 1277147191Sjkoshy break; 1278147191Sjkoshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_TURNAROUND: 1279147191Sjkoshy __K8SETMASK(nmct); 1280147191Sjkoshy break; 1281147191Sjkoshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_BYPASS_SATURATION: 1282147191Sjkoshy __K8SETMASK(nmcbs); 1283147191Sjkoshy break; 1284147191Sjkoshy case PMC_EV_K8_NB_SIZED_COMMANDS: 1285147191Sjkoshy __K8SETMASK(nsc); 1286147191Sjkoshy break; 1287147191Sjkoshy case PMC_EV_K8_NB_PROBE_RESULT: 1288147191Sjkoshy __K8SETMASK(npr); 1289147191Sjkoshy break; 1290147191Sjkoshy case PMC_EV_K8_NB_HT_BUS0_BANDWIDTH: 1291147191Sjkoshy case PMC_EV_K8_NB_HT_BUS1_BANDWIDTH: 1292147191Sjkoshy case PMC_EV_K8_NB_HT_BUS2_BANDWIDTH: 1293147191Sjkoshy __K8SETMASK(nhbb); 1294147191Sjkoshy break; 1295147191Sjkoshy 1296147191Sjkoshy default: 1297147191Sjkoshy break; /* no options defined */ 1298147191Sjkoshy } 1299147191Sjkoshy 1300147191Sjkoshy while ((p = strsep(&ctrspec, ",")) != NULL) { 1301147191Sjkoshy if (KWPREFIXMATCH(p, K8_KW_COUNT "=")) { 1302147191Sjkoshy q = strchr(p, '='); 1303147191Sjkoshy if (*++q == '\0') /* skip '=' */ 1304174406Sjkoshy return (-1); 1305147191Sjkoshy 1306147191Sjkoshy count = strtol(q, &e, 0); 1307147191Sjkoshy if (e == q || *e != '\0') 1308174406Sjkoshy return (-1); 1309147191Sjkoshy 1310147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 1311147191Sjkoshy pmc_config->pm_md.pm_amd.pm_amd_config |= 1312147191Sjkoshy AMD_PMC_TO_COUNTER(count); 1313147191Sjkoshy 1314147191Sjkoshy } else if (KWMATCH(p, K8_KW_EDGE)) { 1315147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1316147191Sjkoshy } else if (KWMATCH(p, K8_KW_INV)) { 1317147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_INVERT; 1318147191Sjkoshy } else if (KWPREFIXMATCH(p, K8_KW_MASK "=")) { 1319147191Sjkoshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 1320174406Sjkoshy return (-1); 1321147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1322147191Sjkoshy } else if (KWMATCH(p, K8_KW_OS)) { 1323147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 1324147191Sjkoshy } else if (KWMATCH(p, K8_KW_USR)) { 1325147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_USER; 1326147191Sjkoshy } else 1327174406Sjkoshy return (-1); 1328147191Sjkoshy } 1329147191Sjkoshy 1330147191Sjkoshy /* other post processing */ 1331147191Sjkoshy switch (pe) { 1332147191Sjkoshy case PMC_EV_K8_FP_DISPATCHED_FPU_OPS: 1333147191Sjkoshy case PMC_EV_K8_FP_CYCLES_WITH_NO_FPU_OPS_RETIRED: 1334147191Sjkoshy case PMC_EV_K8_FP_DISPATCHED_FPU_FAST_FLAG_OPS: 1335147191Sjkoshy case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS: 1336147191Sjkoshy case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS: 1337147191Sjkoshy case PMC_EV_K8_FR_FPU_EXCEPTIONS: 1338147191Sjkoshy /* XXX only available in rev B and later */ 1339147191Sjkoshy break; 1340147191Sjkoshy case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS: 1341147191Sjkoshy /* XXX only available in rev C and later */ 1342147191Sjkoshy break; 1343147191Sjkoshy case PMC_EV_K8_LS_LOCKED_OPERATION: 1344147191Sjkoshy /* XXX CPU Rev A,B evmask is to be zero */ 1345147191Sjkoshy if (evmask & (evmask - 1)) /* > 1 bit set */ 1346174406Sjkoshy return (-1); 1347147191Sjkoshy if (evmask == 0) { 1348147191Sjkoshy evmask = 0x01; /* Rev C and later: #instrs */ 1349147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1350147191Sjkoshy } 1351147191Sjkoshy break; 1352147191Sjkoshy default: 1353147191Sjkoshy if (evmask == 0 && pmask != NULL) { 1354147191Sjkoshy for (pm = pmask; pm->pm_name; pm++) 1355147191Sjkoshy evmask |= pm->pm_value; 1356147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1357147191Sjkoshy } 1358147191Sjkoshy } 1359147191Sjkoshy 1360147191Sjkoshy if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) 1361147191Sjkoshy pmc_config->pm_md.pm_amd.pm_amd_config = 1362147191Sjkoshy AMD_PMC_TO_UNITMASK(evmask); 1363147191Sjkoshy 1364174406Sjkoshy return (0); 1365147191Sjkoshy} 1366147191Sjkoshy 1367147191Sjkoshy#endif 1368147191Sjkoshy 1369147759Sjkoshy#if defined(__amd64__) || defined(__i386__) 1370147191Sjkoshy 1371147191Sjkoshy/* 1372145256Sjkoshy * Intel P4 PMCs 1373145256Sjkoshy */ 1374145256Sjkoshy 1375145256Sjkoshystatic struct pmc_event_alias p4_aliases[] = { 1376145351Sjkoshy EV_ALIAS("branches", "p4-branch-retired,mask=mmtp+mmtm"), 1377145351Sjkoshy EV_ALIAS("branch-mispredicts", "p4-mispred-branch-retired"), 1378145351Sjkoshy EV_ALIAS("cycles", "tsc"), 1379145351Sjkoshy EV_ALIAS("instructions", 1380145351Sjkoshy "p4-instr-retired,mask=nbogusntag+nbogustag"), 1381155998Sjkoshy EV_ALIAS("unhalted-cycles", "p4-global-power-events"), 1382145256Sjkoshy EV_ALIAS(NULL, NULL) 1383145256Sjkoshy}; 1384145256Sjkoshy 1385145256Sjkoshy#define P4_KW_ACTIVE "active" 1386145256Sjkoshy#define P4_KW_ACTIVE_ANY "any" 1387145256Sjkoshy#define P4_KW_ACTIVE_BOTH "both" 1388145256Sjkoshy#define P4_KW_ACTIVE_NONE "none" 1389145256Sjkoshy#define P4_KW_ACTIVE_SINGLE "single" 1390145256Sjkoshy#define P4_KW_BUSREQTYPE "busreqtype" 1391145256Sjkoshy#define P4_KW_CASCADE "cascade" 1392145256Sjkoshy#define P4_KW_EDGE "edge" 1393145256Sjkoshy#define P4_KW_INV "complement" 1394145256Sjkoshy#define P4_KW_OS "os" 1395145256Sjkoshy#define P4_KW_MASK "mask" 1396145256Sjkoshy#define P4_KW_PRECISE "precise" 1397145256Sjkoshy#define P4_KW_TAG "tag" 1398145256Sjkoshy#define P4_KW_THRESHOLD "threshold" 1399145256Sjkoshy#define P4_KW_USR "usr" 1400145256Sjkoshy 1401145256Sjkoshy#define __P4MASK(N,V) PMCMASK(N, (1 << (V))) 1402145256Sjkoshy 1403145256Sjkoshystatic const struct pmc_masks p4_mask_tcdm[] = { /* tc deliver mode */ 1404145256Sjkoshy __P4MASK(dd, 0), 1405145256Sjkoshy __P4MASK(db, 1), 1406145256Sjkoshy __P4MASK(di, 2), 1407145256Sjkoshy __P4MASK(bd, 3), 1408145256Sjkoshy __P4MASK(bb, 4), 1409145256Sjkoshy __P4MASK(bi, 5), 1410145256Sjkoshy __P4MASK(id, 6), 1411145256Sjkoshy __P4MASK(ib, 7), 1412145256Sjkoshy NULLMASK 1413145256Sjkoshy}; 1414145256Sjkoshy 1415145256Sjkoshystatic const struct pmc_masks p4_mask_bfr[] = { /* bpu fetch request */ 1416145256Sjkoshy __P4MASK(tcmiss, 0), 1417145256Sjkoshy NULLMASK, 1418145256Sjkoshy}; 1419145256Sjkoshy 1420145256Sjkoshystatic const struct pmc_masks p4_mask_ir[] = { /* itlb reference */ 1421145256Sjkoshy __P4MASK(hit, 0), 1422145256Sjkoshy __P4MASK(miss, 1), 1423145256Sjkoshy __P4MASK(hit-uc, 2), 1424145256Sjkoshy NULLMASK 1425145256Sjkoshy}; 1426145256Sjkoshy 1427145256Sjkoshystatic const struct pmc_masks p4_mask_memcan[] = { /* memory cancel */ 1428145256Sjkoshy __P4MASK(st-rb-full, 2), 1429145256Sjkoshy __P4MASK(64k-conf, 3), 1430145256Sjkoshy NULLMASK 1431145256Sjkoshy}; 1432145256Sjkoshy 1433145256Sjkoshystatic const struct pmc_masks p4_mask_memcomp[] = { /* memory complete */ 1434145256Sjkoshy __P4MASK(lsc, 0), 1435145256Sjkoshy __P4MASK(ssc, 1), 1436145256Sjkoshy NULLMASK 1437145256Sjkoshy}; 1438145256Sjkoshy 1439145256Sjkoshystatic const struct pmc_masks p4_mask_lpr[] = { /* load port replay */ 1440145256Sjkoshy __P4MASK(split-ld, 1), 1441145256Sjkoshy NULLMASK 1442145256Sjkoshy}; 1443145256Sjkoshy 1444145256Sjkoshystatic const struct pmc_masks p4_mask_spr[] = { /* store port replay */ 1445145256Sjkoshy __P4MASK(split-st, 1), 1446145256Sjkoshy NULLMASK 1447145256Sjkoshy}; 1448145256Sjkoshy 1449145256Sjkoshystatic const struct pmc_masks p4_mask_mlr[] = { /* mob load replay */ 1450145256Sjkoshy __P4MASK(no-sta, 1), 1451145256Sjkoshy __P4MASK(no-std, 3), 1452145256Sjkoshy __P4MASK(partial-data, 4), 1453145256Sjkoshy __P4MASK(unalgn-addr, 5), 1454145256Sjkoshy NULLMASK 1455145256Sjkoshy}; 1456145256Sjkoshy 1457145256Sjkoshystatic const struct pmc_masks p4_mask_pwt[] = { /* page walk type */ 1458145256Sjkoshy __P4MASK(dtmiss, 0), 1459145256Sjkoshy __P4MASK(itmiss, 1), 1460145256Sjkoshy NULLMASK 1461145256Sjkoshy}; 1462145256Sjkoshy 1463145256Sjkoshystatic const struct pmc_masks p4_mask_bcr[] = { /* bsq cache reference */ 1464145256Sjkoshy __P4MASK(rd-2ndl-hits, 0), 1465145256Sjkoshy __P4MASK(rd-2ndl-hite, 1), 1466145256Sjkoshy __P4MASK(rd-2ndl-hitm, 2), 1467145256Sjkoshy __P4MASK(rd-3rdl-hits, 3), 1468145256Sjkoshy __P4MASK(rd-3rdl-hite, 4), 1469145256Sjkoshy __P4MASK(rd-3rdl-hitm, 5), 1470145256Sjkoshy __P4MASK(rd-2ndl-miss, 8), 1471145256Sjkoshy __P4MASK(rd-3rdl-miss, 9), 1472145256Sjkoshy __P4MASK(wr-2ndl-miss, 10), 1473145256Sjkoshy NULLMASK 1474145256Sjkoshy}; 1475145256Sjkoshy 1476145256Sjkoshystatic const struct pmc_masks p4_mask_ia[] = { /* ioq allocation */ 1477145256Sjkoshy __P4MASK(all-read, 5), 1478145256Sjkoshy __P4MASK(all-write, 6), 1479145256Sjkoshy __P4MASK(mem-uc, 7), 1480145256Sjkoshy __P4MASK(mem-wc, 8), 1481145256Sjkoshy __P4MASK(mem-wt, 9), 1482145256Sjkoshy __P4MASK(mem-wp, 10), 1483145256Sjkoshy __P4MASK(mem-wb, 11), 1484145256Sjkoshy __P4MASK(own, 13), 1485145256Sjkoshy __P4MASK(other, 14), 1486145256Sjkoshy __P4MASK(prefetch, 15), 1487145256Sjkoshy NULLMASK 1488145256Sjkoshy}; 1489145256Sjkoshy 1490145256Sjkoshystatic const struct pmc_masks p4_mask_iae[] = { /* ioq active entries */ 1491145256Sjkoshy __P4MASK(all-read, 5), 1492145256Sjkoshy __P4MASK(all-write, 6), 1493145256Sjkoshy __P4MASK(mem-uc, 7), 1494145256Sjkoshy __P4MASK(mem-wc, 8), 1495145256Sjkoshy __P4MASK(mem-wt, 9), 1496145256Sjkoshy __P4MASK(mem-wp, 10), 1497145256Sjkoshy __P4MASK(mem-wb, 11), 1498145256Sjkoshy __P4MASK(own, 13), 1499145256Sjkoshy __P4MASK(other, 14), 1500145256Sjkoshy __P4MASK(prefetch, 15), 1501145256Sjkoshy NULLMASK 1502145256Sjkoshy}; 1503145256Sjkoshy 1504145256Sjkoshystatic const struct pmc_masks p4_mask_fda[] = { /* fsb data activity */ 1505145256Sjkoshy __P4MASK(drdy-drv, 0), 1506145256Sjkoshy __P4MASK(drdy-own, 1), 1507145256Sjkoshy __P4MASK(drdy-other, 2), 1508145256Sjkoshy __P4MASK(dbsy-drv, 3), 1509145256Sjkoshy __P4MASK(dbsy-own, 4), 1510145256Sjkoshy __P4MASK(dbsy-other, 5), 1511145256Sjkoshy NULLMASK 1512145256Sjkoshy}; 1513145256Sjkoshy 1514145256Sjkoshystatic const struct pmc_masks p4_mask_ba[] = { /* bsq allocation */ 1515145256Sjkoshy __P4MASK(req-type0, 0), 1516145256Sjkoshy __P4MASK(req-type1, 1), 1517145256Sjkoshy __P4MASK(req-len0, 2), 1518145256Sjkoshy __P4MASK(req-len1, 3), 1519145256Sjkoshy __P4MASK(req-io-type, 5), 1520145256Sjkoshy __P4MASK(req-lock-type, 6), 1521145256Sjkoshy __P4MASK(req-cache-type, 7), 1522145256Sjkoshy __P4MASK(req-split-type, 8), 1523145256Sjkoshy __P4MASK(req-dem-type, 9), 1524145256Sjkoshy __P4MASK(req-ord-type, 10), 1525145256Sjkoshy __P4MASK(mem-type0, 11), 1526145256Sjkoshy __P4MASK(mem-type1, 12), 1527145256Sjkoshy __P4MASK(mem-type2, 13), 1528145256Sjkoshy NULLMASK 1529145256Sjkoshy}; 1530145256Sjkoshy 1531145256Sjkoshystatic const struct pmc_masks p4_mask_sia[] = { /* sse input assist */ 1532145256Sjkoshy __P4MASK(all, 15), 1533145256Sjkoshy NULLMASK 1534145256Sjkoshy}; 1535145256Sjkoshy 1536145256Sjkoshystatic const struct pmc_masks p4_mask_psu[] = { /* packed sp uop */ 1537145256Sjkoshy __P4MASK(all, 15), 1538145256Sjkoshy NULLMASK 1539145256Sjkoshy}; 1540145256Sjkoshy 1541145256Sjkoshystatic const struct pmc_masks p4_mask_pdu[] = { /* packed dp uop */ 1542145256Sjkoshy __P4MASK(all, 15), 1543145256Sjkoshy NULLMASK 1544145256Sjkoshy}; 1545145256Sjkoshy 1546145256Sjkoshystatic const struct pmc_masks p4_mask_ssu[] = { /* scalar sp uop */ 1547145256Sjkoshy __P4MASK(all, 15), 1548145256Sjkoshy NULLMASK 1549145256Sjkoshy}; 1550145256Sjkoshy 1551145256Sjkoshystatic const struct pmc_masks p4_mask_sdu[] = { /* scalar dp uop */ 1552145256Sjkoshy __P4MASK(all, 15), 1553145256Sjkoshy NULLMASK 1554145256Sjkoshy}; 1555145256Sjkoshy 1556145256Sjkoshystatic const struct pmc_masks p4_mask_64bmu[] = { /* 64 bit mmx uop */ 1557145256Sjkoshy __P4MASK(all, 15), 1558145256Sjkoshy NULLMASK 1559145256Sjkoshy}; 1560145256Sjkoshy 1561145256Sjkoshystatic const struct pmc_masks p4_mask_128bmu[] = { /* 128 bit mmx uop */ 1562145256Sjkoshy __P4MASK(all, 15), 1563145256Sjkoshy NULLMASK 1564145256Sjkoshy}; 1565145256Sjkoshy 1566145256Sjkoshystatic const struct pmc_masks p4_mask_xfu[] = { /* X87 fp uop */ 1567145256Sjkoshy __P4MASK(all, 15), 1568145256Sjkoshy NULLMASK 1569145256Sjkoshy}; 1570145256Sjkoshy 1571145256Sjkoshystatic const struct pmc_masks p4_mask_xsmu[] = { /* x87 simd moves uop */ 1572145256Sjkoshy __P4MASK(allp0, 3), 1573145256Sjkoshy __P4MASK(allp2, 4), 1574145256Sjkoshy NULLMASK 1575145256Sjkoshy}; 1576145256Sjkoshy 1577145256Sjkoshystatic const struct pmc_masks p4_mask_gpe[] = { /* global power events */ 1578145256Sjkoshy __P4MASK(running, 0), 1579145256Sjkoshy NULLMASK 1580145256Sjkoshy}; 1581145256Sjkoshy 1582145256Sjkoshystatic const struct pmc_masks p4_mask_tmx[] = { /* TC ms xfer */ 1583145256Sjkoshy __P4MASK(cisc, 0), 1584145256Sjkoshy NULLMASK 1585145256Sjkoshy}; 1586145256Sjkoshy 1587145256Sjkoshystatic const struct pmc_masks p4_mask_uqw[] = { /* uop queue writes */ 1588145256Sjkoshy __P4MASK(from-tc-build, 0), 1589145256Sjkoshy __P4MASK(from-tc-deliver, 1), 1590145256Sjkoshy __P4MASK(from-rom, 2), 1591145256Sjkoshy NULLMASK 1592145256Sjkoshy}; 1593145256Sjkoshy 1594145351Sjkoshystatic const struct pmc_masks p4_mask_rmbt[] = { 1595145351Sjkoshy /* retired mispred branch type */ 1596145256Sjkoshy __P4MASK(conditional, 1), 1597145256Sjkoshy __P4MASK(call, 2), 1598145256Sjkoshy __P4MASK(return, 3), 1599145256Sjkoshy __P4MASK(indirect, 4), 1600145256Sjkoshy NULLMASK 1601145256Sjkoshy}; 1602145256Sjkoshy 1603145256Sjkoshystatic const struct pmc_masks p4_mask_rbt[] = { /* retired branch type */ 1604145256Sjkoshy __P4MASK(conditional, 1), 1605145256Sjkoshy __P4MASK(call, 2), 1606145256Sjkoshy __P4MASK(retired, 3), 1607145256Sjkoshy __P4MASK(indirect, 4), 1608145256Sjkoshy NULLMASK 1609145256Sjkoshy}; 1610145256Sjkoshy 1611145256Sjkoshystatic const struct pmc_masks p4_mask_rs[] = { /* resource stall */ 1612145256Sjkoshy __P4MASK(sbfull, 5), 1613145256Sjkoshy NULLMASK 1614145256Sjkoshy}; 1615145256Sjkoshy 1616145256Sjkoshystatic const struct pmc_masks p4_mask_wb[] = { /* WC buffer */ 1617145256Sjkoshy __P4MASK(wcb-evicts, 0), 1618145256Sjkoshy __P4MASK(wcb-full-evict, 1), 1619145256Sjkoshy NULLMASK 1620145256Sjkoshy}; 1621145256Sjkoshy 1622145256Sjkoshystatic const struct pmc_masks p4_mask_fee[] = { /* front end event */ 1623145256Sjkoshy __P4MASK(nbogus, 0), 1624145256Sjkoshy __P4MASK(bogus, 1), 1625145256Sjkoshy NULLMASK 1626145256Sjkoshy}; 1627145256Sjkoshy 1628145256Sjkoshystatic const struct pmc_masks p4_mask_ee[] = { /* execution event */ 1629145256Sjkoshy __P4MASK(nbogus0, 0), 1630145256Sjkoshy __P4MASK(nbogus1, 1), 1631145256Sjkoshy __P4MASK(nbogus2, 2), 1632145256Sjkoshy __P4MASK(nbogus3, 3), 1633145256Sjkoshy __P4MASK(bogus0, 4), 1634145256Sjkoshy __P4MASK(bogus1, 5), 1635145256Sjkoshy __P4MASK(bogus2, 6), 1636145256Sjkoshy __P4MASK(bogus3, 7), 1637145256Sjkoshy NULLMASK 1638145256Sjkoshy}; 1639145256Sjkoshy 1640145256Sjkoshystatic const struct pmc_masks p4_mask_re[] = { /* replay event */ 1641145256Sjkoshy __P4MASK(nbogus, 0), 1642145256Sjkoshy __P4MASK(bogus, 1), 1643145256Sjkoshy NULLMASK 1644145256Sjkoshy}; 1645145256Sjkoshy 1646145256Sjkoshystatic const struct pmc_masks p4_mask_insret[] = { /* instr retired */ 1647145256Sjkoshy __P4MASK(nbogusntag, 0), 1648145256Sjkoshy __P4MASK(nbogustag, 1), 1649145256Sjkoshy __P4MASK(bogusntag, 2), 1650145256Sjkoshy __P4MASK(bogustag, 3), 1651145256Sjkoshy NULLMASK 1652145256Sjkoshy}; 1653145256Sjkoshy 1654145256Sjkoshystatic const struct pmc_masks p4_mask_ur[] = { /* uops retired */ 1655145256Sjkoshy __P4MASK(nbogus, 0), 1656145256Sjkoshy __P4MASK(bogus, 1), 1657145256Sjkoshy NULLMASK 1658145256Sjkoshy}; 1659145256Sjkoshy 1660145256Sjkoshystatic const struct pmc_masks p4_mask_ut[] = { /* uop type */ 1661145256Sjkoshy __P4MASK(tagloads, 1), 1662145256Sjkoshy __P4MASK(tagstores, 2), 1663145256Sjkoshy NULLMASK 1664145256Sjkoshy}; 1665145256Sjkoshy 1666145256Sjkoshystatic const struct pmc_masks p4_mask_br[] = { /* branch retired */ 1667145256Sjkoshy __P4MASK(mmnp, 0), 1668145256Sjkoshy __P4MASK(mmnm, 1), 1669145256Sjkoshy __P4MASK(mmtp, 2), 1670145256Sjkoshy __P4MASK(mmtm, 3), 1671145256Sjkoshy NULLMASK 1672145256Sjkoshy}; 1673145256Sjkoshy 1674145256Sjkoshystatic const struct pmc_masks p4_mask_mbr[] = { /* mispred branch retired */ 1675145256Sjkoshy __P4MASK(nbogus, 0), 1676145256Sjkoshy NULLMASK 1677145256Sjkoshy}; 1678145256Sjkoshy 1679145256Sjkoshystatic const struct pmc_masks p4_mask_xa[] = { /* x87 assist */ 1680145256Sjkoshy __P4MASK(fpsu, 0), 1681145256Sjkoshy __P4MASK(fpso, 1), 1682145256Sjkoshy __P4MASK(poao, 2), 1683145256Sjkoshy __P4MASK(poau, 3), 1684145256Sjkoshy __P4MASK(prea, 4), 1685145256Sjkoshy NULLMASK 1686145256Sjkoshy}; 1687145256Sjkoshy 1688145256Sjkoshystatic const struct pmc_masks p4_mask_machclr[] = { /* machine clear */ 1689145256Sjkoshy __P4MASK(clear, 0), 1690145256Sjkoshy __P4MASK(moclear, 2), 1691145256Sjkoshy __P4MASK(smclear, 3), 1692145256Sjkoshy NULLMASK 1693145256Sjkoshy}; 1694145256Sjkoshy 1695145256Sjkoshy/* P4 event parser */ 1696145256Sjkoshystatic int 1697145256Sjkoshyp4_allocate_pmc(enum pmc_event pe, char *ctrspec, 1698145256Sjkoshy struct pmc_op_pmcallocate *pmc_config) 1699145256Sjkoshy{ 1700145256Sjkoshy 1701145256Sjkoshy char *e, *p, *q; 1702145256Sjkoshy int count, has_tag, has_busreqtype, n; 1703240164Sfabient uint32_t cccractivemask; 1704240164Sfabient uint64_t evmask; 1705145256Sjkoshy const struct pmc_masks *pm, *pmask; 1706145256Sjkoshy 1707183725Sjkoshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1708147191Sjkoshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig = 1709147191Sjkoshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 0; 1710145256Sjkoshy 1711145256Sjkoshy pmask = NULL; 1712145256Sjkoshy evmask = 0; 1713145256Sjkoshy cccractivemask = 0x3; 1714145256Sjkoshy has_tag = has_busreqtype = 0; 1715145256Sjkoshy 1716145256Sjkoshy#define __P4SETMASK(M) do { \ 1717183107Sjkoshy pmask = p4_mask_##M; \ 1718145256Sjkoshy} while (0) 1719145256Sjkoshy 1720145256Sjkoshy switch (pe) { 1721145256Sjkoshy case PMC_EV_P4_TC_DELIVER_MODE: 1722145256Sjkoshy __P4SETMASK(tcdm); 1723145256Sjkoshy break; 1724145256Sjkoshy case PMC_EV_P4_BPU_FETCH_REQUEST: 1725145256Sjkoshy __P4SETMASK(bfr); 1726145256Sjkoshy break; 1727145256Sjkoshy case PMC_EV_P4_ITLB_REFERENCE: 1728145256Sjkoshy __P4SETMASK(ir); 1729145256Sjkoshy break; 1730145256Sjkoshy case PMC_EV_P4_MEMORY_CANCEL: 1731145256Sjkoshy __P4SETMASK(memcan); 1732145256Sjkoshy break; 1733145256Sjkoshy case PMC_EV_P4_MEMORY_COMPLETE: 1734145256Sjkoshy __P4SETMASK(memcomp); 1735145256Sjkoshy break; 1736145256Sjkoshy case PMC_EV_P4_LOAD_PORT_REPLAY: 1737145256Sjkoshy __P4SETMASK(lpr); 1738145256Sjkoshy break; 1739145256Sjkoshy case PMC_EV_P4_STORE_PORT_REPLAY: 1740145256Sjkoshy __P4SETMASK(spr); 1741145256Sjkoshy break; 1742145256Sjkoshy case PMC_EV_P4_MOB_LOAD_REPLAY: 1743145256Sjkoshy __P4SETMASK(mlr); 1744145256Sjkoshy break; 1745145256Sjkoshy case PMC_EV_P4_PAGE_WALK_TYPE: 1746145256Sjkoshy __P4SETMASK(pwt); 1747145256Sjkoshy break; 1748145256Sjkoshy case PMC_EV_P4_BSQ_CACHE_REFERENCE: 1749145256Sjkoshy __P4SETMASK(bcr); 1750145256Sjkoshy break; 1751145256Sjkoshy case PMC_EV_P4_IOQ_ALLOCATION: 1752145256Sjkoshy __P4SETMASK(ia); 1753145256Sjkoshy has_busreqtype = 1; 1754145256Sjkoshy break; 1755145256Sjkoshy case PMC_EV_P4_IOQ_ACTIVE_ENTRIES: 1756145256Sjkoshy __P4SETMASK(iae); 1757145256Sjkoshy has_busreqtype = 1; 1758145256Sjkoshy break; 1759145256Sjkoshy case PMC_EV_P4_FSB_DATA_ACTIVITY: 1760145256Sjkoshy __P4SETMASK(fda); 1761145256Sjkoshy break; 1762145256Sjkoshy case PMC_EV_P4_BSQ_ALLOCATION: 1763145256Sjkoshy __P4SETMASK(ba); 1764145256Sjkoshy break; 1765145256Sjkoshy case PMC_EV_P4_SSE_INPUT_ASSIST: 1766145256Sjkoshy __P4SETMASK(sia); 1767145256Sjkoshy break; 1768145256Sjkoshy case PMC_EV_P4_PACKED_SP_UOP: 1769145256Sjkoshy __P4SETMASK(psu); 1770145256Sjkoshy break; 1771145256Sjkoshy case PMC_EV_P4_PACKED_DP_UOP: 1772145256Sjkoshy __P4SETMASK(pdu); 1773145256Sjkoshy break; 1774145256Sjkoshy case PMC_EV_P4_SCALAR_SP_UOP: 1775145256Sjkoshy __P4SETMASK(ssu); 1776145256Sjkoshy break; 1777145256Sjkoshy case PMC_EV_P4_SCALAR_DP_UOP: 1778145256Sjkoshy __P4SETMASK(sdu); 1779145256Sjkoshy break; 1780145256Sjkoshy case PMC_EV_P4_64BIT_MMX_UOP: 1781145256Sjkoshy __P4SETMASK(64bmu); 1782145256Sjkoshy break; 1783145256Sjkoshy case PMC_EV_P4_128BIT_MMX_UOP: 1784145256Sjkoshy __P4SETMASK(128bmu); 1785145256Sjkoshy break; 1786145256Sjkoshy case PMC_EV_P4_X87_FP_UOP: 1787145256Sjkoshy __P4SETMASK(xfu); 1788145256Sjkoshy break; 1789145256Sjkoshy case PMC_EV_P4_X87_SIMD_MOVES_UOP: 1790145256Sjkoshy __P4SETMASK(xsmu); 1791145256Sjkoshy break; 1792145256Sjkoshy case PMC_EV_P4_GLOBAL_POWER_EVENTS: 1793145256Sjkoshy __P4SETMASK(gpe); 1794145256Sjkoshy break; 1795145256Sjkoshy case PMC_EV_P4_TC_MS_XFER: 1796145256Sjkoshy __P4SETMASK(tmx); 1797145256Sjkoshy break; 1798145256Sjkoshy case PMC_EV_P4_UOP_QUEUE_WRITES: 1799145256Sjkoshy __P4SETMASK(uqw); 1800145256Sjkoshy break; 1801145256Sjkoshy case PMC_EV_P4_RETIRED_MISPRED_BRANCH_TYPE: 1802145256Sjkoshy __P4SETMASK(rmbt); 1803145256Sjkoshy break; 1804145256Sjkoshy case PMC_EV_P4_RETIRED_BRANCH_TYPE: 1805145256Sjkoshy __P4SETMASK(rbt); 1806145256Sjkoshy break; 1807145256Sjkoshy case PMC_EV_P4_RESOURCE_STALL: 1808145256Sjkoshy __P4SETMASK(rs); 1809145256Sjkoshy break; 1810145256Sjkoshy case PMC_EV_P4_WC_BUFFER: 1811145256Sjkoshy __P4SETMASK(wb); 1812145256Sjkoshy break; 1813145256Sjkoshy case PMC_EV_P4_BSQ_ACTIVE_ENTRIES: 1814145256Sjkoshy case PMC_EV_P4_B2B_CYCLES: 1815145256Sjkoshy case PMC_EV_P4_BNR: 1816145256Sjkoshy case PMC_EV_P4_SNOOP: 1817145256Sjkoshy case PMC_EV_P4_RESPONSE: 1818145256Sjkoshy break; 1819145256Sjkoshy case PMC_EV_P4_FRONT_END_EVENT: 1820145256Sjkoshy __P4SETMASK(fee); 1821145256Sjkoshy break; 1822145256Sjkoshy case PMC_EV_P4_EXECUTION_EVENT: 1823145256Sjkoshy __P4SETMASK(ee); 1824145256Sjkoshy break; 1825145256Sjkoshy case PMC_EV_P4_REPLAY_EVENT: 1826145256Sjkoshy __P4SETMASK(re); 1827145256Sjkoshy break; 1828145256Sjkoshy case PMC_EV_P4_INSTR_RETIRED: 1829145256Sjkoshy __P4SETMASK(insret); 1830145256Sjkoshy break; 1831145256Sjkoshy case PMC_EV_P4_UOPS_RETIRED: 1832145256Sjkoshy __P4SETMASK(ur); 1833145256Sjkoshy break; 1834145256Sjkoshy case PMC_EV_P4_UOP_TYPE: 1835145256Sjkoshy __P4SETMASK(ut); 1836145256Sjkoshy break; 1837145256Sjkoshy case PMC_EV_P4_BRANCH_RETIRED: 1838145256Sjkoshy __P4SETMASK(br); 1839145256Sjkoshy break; 1840145256Sjkoshy case PMC_EV_P4_MISPRED_BRANCH_RETIRED: 1841145256Sjkoshy __P4SETMASK(mbr); 1842145256Sjkoshy break; 1843145256Sjkoshy case PMC_EV_P4_X87_ASSIST: 1844145256Sjkoshy __P4SETMASK(xa); 1845145256Sjkoshy break; 1846145256Sjkoshy case PMC_EV_P4_MACHINE_CLEAR: 1847145256Sjkoshy __P4SETMASK(machclr); 1848145256Sjkoshy break; 1849145256Sjkoshy default: 1850174406Sjkoshy return (-1); 1851145256Sjkoshy } 1852145256Sjkoshy 1853145256Sjkoshy /* process additional flags */ 1854145256Sjkoshy while ((p = strsep(&ctrspec, ",")) != NULL) { 1855145256Sjkoshy if (KWPREFIXMATCH(p, P4_KW_ACTIVE)) { 1856145256Sjkoshy q = strchr(p, '='); 1857145256Sjkoshy if (*++q == '\0') /* skip '=' */ 1858174406Sjkoshy return (-1); 1859145256Sjkoshy 1860183725Sjkoshy if (strcasecmp(q, P4_KW_ACTIVE_NONE) == 0) 1861145256Sjkoshy cccractivemask = 0x0; 1862183725Sjkoshy else if (strcasecmp(q, P4_KW_ACTIVE_SINGLE) == 0) 1863145256Sjkoshy cccractivemask = 0x1; 1864183725Sjkoshy else if (strcasecmp(q, P4_KW_ACTIVE_BOTH) == 0) 1865145256Sjkoshy cccractivemask = 0x2; 1866183725Sjkoshy else if (strcasecmp(q, P4_KW_ACTIVE_ANY) == 0) 1867145256Sjkoshy cccractivemask = 0x3; 1868145256Sjkoshy else 1869174406Sjkoshy return (-1); 1870145256Sjkoshy 1871145256Sjkoshy } else if (KWPREFIXMATCH(p, P4_KW_BUSREQTYPE)) { 1872145256Sjkoshy if (has_busreqtype == 0) 1873174406Sjkoshy return (-1); 1874145256Sjkoshy 1875145256Sjkoshy q = strchr(p, '='); 1876145256Sjkoshy if (*++q == '\0') /* skip '=' */ 1877174406Sjkoshy return (-1); 1878145256Sjkoshy 1879145256Sjkoshy count = strtol(q, &e, 0); 1880145256Sjkoshy if (e == q || *e != '\0') 1881174406Sjkoshy return (-1); 1882145256Sjkoshy evmask = (evmask & ~0x1F) | (count & 0x1F); 1883145256Sjkoshy } else if (KWMATCH(p, P4_KW_CASCADE)) 1884145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_CASCADE; 1885145256Sjkoshy else if (KWMATCH(p, P4_KW_EDGE)) 1886145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1887145256Sjkoshy else if (KWMATCH(p, P4_KW_INV)) 1888145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_INVERT; 1889145256Sjkoshy else if (KWPREFIXMATCH(p, P4_KW_MASK "=")) { 1890145256Sjkoshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 1891174406Sjkoshy return (-1); 1892145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1893145256Sjkoshy } else if (KWMATCH(p, P4_KW_OS)) 1894145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 1895145256Sjkoshy else if (KWMATCH(p, P4_KW_PRECISE)) 1896145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_PRECISE; 1897145256Sjkoshy else if (KWPREFIXMATCH(p, P4_KW_TAG "=")) { 1898145256Sjkoshy if (has_tag == 0) 1899174406Sjkoshy return (-1); 1900145256Sjkoshy 1901145256Sjkoshy q = strchr(p, '='); 1902145256Sjkoshy if (*++q == '\0') /* skip '=' */ 1903174406Sjkoshy return (-1); 1904145256Sjkoshy 1905145256Sjkoshy count = strtol(q, &e, 0); 1906145256Sjkoshy if (e == q || *e != '\0') 1907174406Sjkoshy return (-1); 1908145256Sjkoshy 1909145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_TAGGING; 1910147191Sjkoshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig |= 1911145256Sjkoshy P4_ESCR_TO_TAG_VALUE(count); 1912145256Sjkoshy } else if (KWPREFIXMATCH(p, P4_KW_THRESHOLD "=")) { 1913145256Sjkoshy q = strchr(p, '='); 1914145256Sjkoshy if (*++q == '\0') /* skip '=' */ 1915174406Sjkoshy return (-1); 1916145256Sjkoshy 1917145256Sjkoshy count = strtol(q, &e, 0); 1918145256Sjkoshy if (e == q || *e != '\0') 1919174406Sjkoshy return (-1); 1920145256Sjkoshy 1921145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 1922147191Sjkoshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig &= 1923147191Sjkoshy ~P4_CCCR_THRESHOLD_MASK; 1924147191Sjkoshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |= 1925147191Sjkoshy P4_CCCR_TO_THRESHOLD(count); 1926145256Sjkoshy } else if (KWMATCH(p, P4_KW_USR)) 1927145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_USER; 1928145256Sjkoshy else 1929174406Sjkoshy return (-1); 1930145256Sjkoshy } 1931145256Sjkoshy 1932145256Sjkoshy /* other post processing */ 1933145256Sjkoshy if (pe == PMC_EV_P4_IOQ_ALLOCATION || 1934145256Sjkoshy pe == PMC_EV_P4_FSB_DATA_ACTIVITY || 1935145256Sjkoshy pe == PMC_EV_P4_BSQ_ALLOCATION) 1936145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1937145256Sjkoshy 1938145256Sjkoshy /* fill in thread activity mask */ 1939147191Sjkoshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |= 1940145256Sjkoshy P4_CCCR_TO_ACTIVE_THREAD(cccractivemask); 1941145256Sjkoshy 1942145256Sjkoshy if (evmask) 1943145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1944145256Sjkoshy 1945145256Sjkoshy switch (pe) { 1946145256Sjkoshy case PMC_EV_P4_FSB_DATA_ACTIVITY: 1947145256Sjkoshy if ((evmask & 0x06) == 0x06 || 1948145256Sjkoshy (evmask & 0x18) == 0x18) 1949174406Sjkoshy return (-1); /* can't have own+other bits together */ 1950145256Sjkoshy if (evmask == 0) /* default:drdy-{drv,own}+dbsy{drv,own} */ 1951145256Sjkoshy evmask = 0x1D; 1952145256Sjkoshy break; 1953145256Sjkoshy case PMC_EV_P4_MACHINE_CLEAR: 1954145256Sjkoshy /* only one bit is allowed to be set */ 1955145256Sjkoshy if ((evmask & (evmask - 1)) != 0) 1956174406Sjkoshy return (-1); 1957145256Sjkoshy if (evmask == 0) { 1958183107Sjkoshy evmask = 0x1; /* 'CLEAR' */ 1959145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1960145256Sjkoshy } 1961145256Sjkoshy break; 1962145256Sjkoshy default: 1963145256Sjkoshy if (evmask == 0 && pmask) { 1964145256Sjkoshy for (pm = pmask; pm->pm_name; pm++) 1965145256Sjkoshy evmask |= pm->pm_value; 1966145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1967145256Sjkoshy } 1968145256Sjkoshy } 1969145256Sjkoshy 1970147191Sjkoshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 1971147191Sjkoshy P4_ESCR_TO_EVENT_MASK(evmask); 1972145256Sjkoshy 1973174406Sjkoshy return (0); 1974145256Sjkoshy} 1975145256Sjkoshy 1976147759Sjkoshy#endif 1977147759Sjkoshy 1978147759Sjkoshy#if defined(__i386__) 1979147759Sjkoshy 1980145256Sjkoshy/* 1981147191Sjkoshy * Pentium style PMCs 1982147191Sjkoshy */ 1983147191Sjkoshy 1984147191Sjkoshystatic struct pmc_event_alias p5_aliases[] = { 1985183105Sjkoshy EV_ALIAS("branches", "p5-taken-branches"), 1986183105Sjkoshy EV_ALIAS("cycles", "tsc"), 1987183105Sjkoshy EV_ALIAS("dc-misses", "p5-data-read-miss-or-write-miss"), 1988183105Sjkoshy EV_ALIAS("ic-misses", "p5-code-cache-miss"), 1989183105Sjkoshy EV_ALIAS("instructions", "p5-instructions-executed"), 1990183105Sjkoshy EV_ALIAS("interrupts", "p5-hardware-interrupts"), 1991183105Sjkoshy EV_ALIAS("unhalted-cycles", 1992183105Sjkoshy "p5-number-of-cycles-not-in-halt-state"), 1993147191Sjkoshy EV_ALIAS(NULL, NULL) 1994147191Sjkoshy}; 1995147191Sjkoshy 1996147191Sjkoshystatic int 1997147191Sjkoshyp5_allocate_pmc(enum pmc_event pe, char *ctrspec, 1998147191Sjkoshy struct pmc_op_pmcallocate *pmc_config) 1999147191Sjkoshy{ 2000174406Sjkoshy return (-1 || pe || ctrspec || pmc_config); /* shut up gcc */ 2001147191Sjkoshy} 2002147191Sjkoshy 2003147191Sjkoshy/* 2004145256Sjkoshy * Pentium Pro style PMCs. These PMCs are found in Pentium II, Pentium III, 2005145256Sjkoshy * and Pentium M CPUs. 2006145256Sjkoshy */ 2007145256Sjkoshy 2008145256Sjkoshystatic struct pmc_event_alias p6_aliases[] = { 2009145351Sjkoshy EV_ALIAS("branches", "p6-br-inst-retired"), 2010145351Sjkoshy EV_ALIAS("branch-mispredicts", "p6-br-miss-pred-retired"), 2011145351Sjkoshy EV_ALIAS("cycles", "tsc"), 2012145351Sjkoshy EV_ALIAS("dc-misses", "p6-dcu-lines-in"), 2013168612Sjkoshy EV_ALIAS("ic-misses", "p6-ifu-fetch-miss"), 2014145351Sjkoshy EV_ALIAS("instructions", "p6-inst-retired"), 2015145351Sjkoshy EV_ALIAS("interrupts", "p6-hw-int-rx"), 2016155998Sjkoshy EV_ALIAS("unhalted-cycles", "p6-cpu-clk-unhalted"), 2017145351Sjkoshy EV_ALIAS(NULL, NULL) 2018145256Sjkoshy}; 2019145256Sjkoshy 2020145256Sjkoshy#define P6_KW_CMASK "cmask" 2021145256Sjkoshy#define P6_KW_EDGE "edge" 2022145256Sjkoshy#define P6_KW_INV "inv" 2023145256Sjkoshy#define P6_KW_OS "os" 2024145256Sjkoshy#define P6_KW_UMASK "umask" 2025145256Sjkoshy#define P6_KW_USR "usr" 2026145256Sjkoshy 2027145256Sjkoshystatic struct pmc_masks p6_mask_mesi[] = { 2028145256Sjkoshy PMCMASK(m, 0x01), 2029145256Sjkoshy PMCMASK(e, 0x02), 2030145256Sjkoshy PMCMASK(s, 0x04), 2031145256Sjkoshy PMCMASK(i, 0x08), 2032145256Sjkoshy NULLMASK 2033145256Sjkoshy}; 2034145256Sjkoshy 2035145256Sjkoshystatic struct pmc_masks p6_mask_mesihw[] = { 2036145256Sjkoshy PMCMASK(m, 0x01), 2037145256Sjkoshy PMCMASK(e, 0x02), 2038145256Sjkoshy PMCMASK(s, 0x04), 2039145256Sjkoshy PMCMASK(i, 0x08), 2040145256Sjkoshy PMCMASK(nonhw, 0x00), 2041145256Sjkoshy PMCMASK(hw, 0x10), 2042145256Sjkoshy PMCMASK(both, 0x30), 2043145256Sjkoshy NULLMASK 2044145256Sjkoshy}; 2045145256Sjkoshy 2046145256Sjkoshystatic struct pmc_masks p6_mask_hw[] = { 2047145256Sjkoshy PMCMASK(nonhw, 0x00), 2048145256Sjkoshy PMCMASK(hw, 0x10), 2049145256Sjkoshy PMCMASK(both, 0x30), 2050145256Sjkoshy NULLMASK 2051145256Sjkoshy}; 2052145256Sjkoshy 2053145256Sjkoshystatic struct pmc_masks p6_mask_any[] = { 2054145256Sjkoshy PMCMASK(self, 0x00), 2055145256Sjkoshy PMCMASK(any, 0x20), 2056145256Sjkoshy NULLMASK 2057145256Sjkoshy}; 2058145256Sjkoshy 2059145256Sjkoshystatic struct pmc_masks p6_mask_ekp[] = { 2060145256Sjkoshy PMCMASK(nta, 0x00), 2061145256Sjkoshy PMCMASK(t1, 0x01), 2062145256Sjkoshy PMCMASK(t2, 0x02), 2063145256Sjkoshy PMCMASK(wos, 0x03), 2064145256Sjkoshy NULLMASK 2065145256Sjkoshy}; 2066145256Sjkoshy 2067145256Sjkoshystatic struct pmc_masks p6_mask_pps[] = { 2068145256Sjkoshy PMCMASK(packed-and-scalar, 0x00), 2069145256Sjkoshy PMCMASK(scalar, 0x01), 2070145256Sjkoshy NULLMASK 2071145256Sjkoshy}; 2072145256Sjkoshy 2073145256Sjkoshystatic struct pmc_masks p6_mask_mite[] = { 2074145256Sjkoshy PMCMASK(packed-multiply, 0x01), 2075145256Sjkoshy PMCMASK(packed-shift, 0x02), 2076145256Sjkoshy PMCMASK(pack, 0x04), 2077145256Sjkoshy PMCMASK(unpack, 0x08), 2078145256Sjkoshy PMCMASK(packed-logical, 0x10), 2079145256Sjkoshy PMCMASK(packed-arithmetic, 0x20), 2080145256Sjkoshy NULLMASK 2081145256Sjkoshy}; 2082145256Sjkoshy 2083145256Sjkoshystatic struct pmc_masks p6_mask_fmt[] = { 2084145256Sjkoshy PMCMASK(mmxtofp, 0x00), 2085145256Sjkoshy PMCMASK(fptommx, 0x01), 2086145256Sjkoshy NULLMASK 2087145256Sjkoshy}; 2088145256Sjkoshy 2089145256Sjkoshystatic struct pmc_masks p6_mask_sr[] = { 2090145256Sjkoshy PMCMASK(es, 0x01), 2091145256Sjkoshy PMCMASK(ds, 0x02), 2092145256Sjkoshy PMCMASK(fs, 0x04), 2093145256Sjkoshy PMCMASK(gs, 0x08), 2094145256Sjkoshy NULLMASK 2095145256Sjkoshy}; 2096145256Sjkoshy 2097145256Sjkoshystatic struct pmc_masks p6_mask_eet[] = { 2098145256Sjkoshy PMCMASK(all, 0x00), 2099145256Sjkoshy PMCMASK(freq, 0x02), 2100145256Sjkoshy NULLMASK 2101145256Sjkoshy}; 2102145256Sjkoshy 2103145256Sjkoshystatic struct pmc_masks p6_mask_efur[] = { 2104145256Sjkoshy PMCMASK(all, 0x00), 2105145256Sjkoshy PMCMASK(loadop, 0x01), 2106145256Sjkoshy PMCMASK(stdsta, 0x02), 2107145256Sjkoshy NULLMASK 2108145256Sjkoshy}; 2109145256Sjkoshy 2110145256Sjkoshystatic struct pmc_masks p6_mask_essir[] = { 2111145256Sjkoshy PMCMASK(sse-packed-single, 0x00), 2112145256Sjkoshy PMCMASK(sse-packed-single-scalar-single, 0x01), 2113145256Sjkoshy PMCMASK(sse2-packed-double, 0x02), 2114145256Sjkoshy PMCMASK(sse2-scalar-double, 0x03), 2115145256Sjkoshy NULLMASK 2116145256Sjkoshy}; 2117145256Sjkoshy 2118145256Sjkoshystatic struct pmc_masks p6_mask_esscir[] = { 2119145256Sjkoshy PMCMASK(sse-packed-single, 0x00), 2120145256Sjkoshy PMCMASK(sse-scalar-single, 0x01), 2121145256Sjkoshy PMCMASK(sse2-packed-double, 0x02), 2122145256Sjkoshy PMCMASK(sse2-scalar-double, 0x03), 2123145256Sjkoshy NULLMASK 2124145256Sjkoshy}; 2125145256Sjkoshy 2126145256Sjkoshy/* P6 event parser */ 2127145256Sjkoshystatic int 2128145256Sjkoshyp6_allocate_pmc(enum pmc_event pe, char *ctrspec, 2129145256Sjkoshy struct pmc_op_pmcallocate *pmc_config) 2130145256Sjkoshy{ 2131145256Sjkoshy char *e, *p, *q; 2132240164Sfabient uint64_t evmask; 2133145256Sjkoshy int count, n; 2134145256Sjkoshy const struct pmc_masks *pm, *pmask; 2135145256Sjkoshy 2136183725Sjkoshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2137147191Sjkoshy pmc_config->pm_md.pm_ppro.pm_ppro_config = 0; 2138145256Sjkoshy 2139145256Sjkoshy evmask = 0; 2140145256Sjkoshy 2141145256Sjkoshy#define P6MASKSET(M) pmask = p6_mask_ ## M 2142145256Sjkoshy 2143145256Sjkoshy switch(pe) { 2144183107Sjkoshy case PMC_EV_P6_L2_IFETCH: P6MASKSET(mesi); break; 2145145256Sjkoshy case PMC_EV_P6_L2_LD: P6MASKSET(mesi); break; 2146145256Sjkoshy case PMC_EV_P6_L2_ST: P6MASKSET(mesi); break; 2147145256Sjkoshy case PMC_EV_P6_L2_RQSTS: P6MASKSET(mesi); break; 2148145256Sjkoshy case PMC_EV_P6_BUS_DRDY_CLOCKS: 2149145256Sjkoshy case PMC_EV_P6_BUS_LOCK_CLOCKS: 2150145256Sjkoshy case PMC_EV_P6_BUS_TRAN_BRD: 2151145256Sjkoshy case PMC_EV_P6_BUS_TRAN_RFO: 2152145256Sjkoshy case PMC_EV_P6_BUS_TRANS_WB: 2153145256Sjkoshy case PMC_EV_P6_BUS_TRAN_IFETCH: 2154145256Sjkoshy case PMC_EV_P6_BUS_TRAN_INVAL: 2155145256Sjkoshy case PMC_EV_P6_BUS_TRAN_PWR: 2156145256Sjkoshy case PMC_EV_P6_BUS_TRANS_P: 2157145256Sjkoshy case PMC_EV_P6_BUS_TRANS_IO: 2158145256Sjkoshy case PMC_EV_P6_BUS_TRAN_DEF: 2159145256Sjkoshy case PMC_EV_P6_BUS_TRAN_BURST: 2160145256Sjkoshy case PMC_EV_P6_BUS_TRAN_ANY: 2161145256Sjkoshy case PMC_EV_P6_BUS_TRAN_MEM: 2162145256Sjkoshy P6MASKSET(any); break; 2163145256Sjkoshy case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED: 2164145256Sjkoshy case PMC_EV_P6_EMON_KNI_PREF_MISS: 2165145256Sjkoshy P6MASKSET(ekp); break; 2166145256Sjkoshy case PMC_EV_P6_EMON_KNI_INST_RETIRED: 2167145256Sjkoshy case PMC_EV_P6_EMON_KNI_COMP_INST_RET: 2168145256Sjkoshy P6MASKSET(pps); break; 2169145256Sjkoshy case PMC_EV_P6_MMX_INSTR_TYPE_EXEC: 2170145256Sjkoshy P6MASKSET(mite); break; 2171145256Sjkoshy case PMC_EV_P6_FP_MMX_TRANS: 2172145256Sjkoshy P6MASKSET(fmt); break; 2173145256Sjkoshy case PMC_EV_P6_SEG_RENAME_STALLS: 2174145256Sjkoshy case PMC_EV_P6_SEG_REG_RENAMES: 2175145256Sjkoshy P6MASKSET(sr); break; 2176145256Sjkoshy case PMC_EV_P6_EMON_EST_TRANS: 2177145256Sjkoshy P6MASKSET(eet); break; 2178145256Sjkoshy case PMC_EV_P6_EMON_FUSED_UOPS_RET: 2179145256Sjkoshy P6MASKSET(efur); break; 2180145256Sjkoshy case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED: 2181145256Sjkoshy P6MASKSET(essir); break; 2182145256Sjkoshy case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED: 2183145256Sjkoshy P6MASKSET(esscir); break; 2184145256Sjkoshy default: 2185145256Sjkoshy pmask = NULL; 2186145256Sjkoshy break; 2187145256Sjkoshy } 2188145256Sjkoshy 2189145256Sjkoshy /* Pentium M PMCs have a few events with different semantics */ 2190145256Sjkoshy if (cpu_info.pm_cputype == PMC_CPU_INTEL_PM) { 2191145256Sjkoshy if (pe == PMC_EV_P6_L2_LD || 2192145256Sjkoshy pe == PMC_EV_P6_L2_LINES_IN || 2193145256Sjkoshy pe == PMC_EV_P6_L2_LINES_OUT) 2194145256Sjkoshy P6MASKSET(mesihw); 2195145256Sjkoshy else if (pe == PMC_EV_P6_L2_M_LINES_OUTM) 2196145256Sjkoshy P6MASKSET(hw); 2197145256Sjkoshy } 2198145256Sjkoshy 2199145256Sjkoshy /* Parse additional modifiers if present */ 2200145256Sjkoshy while ((p = strsep(&ctrspec, ",")) != NULL) { 2201145256Sjkoshy if (KWPREFIXMATCH(p, P6_KW_CMASK "=")) { 2202145256Sjkoshy q = strchr(p, '='); 2203145256Sjkoshy if (*++q == '\0') /* skip '=' */ 2204174406Sjkoshy return (-1); 2205145256Sjkoshy count = strtol(q, &e, 0); 2206145256Sjkoshy if (e == q || *e != '\0') 2207174406Sjkoshy return (-1); 2208145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 2209147191Sjkoshy pmc_config->pm_md.pm_ppro.pm_ppro_config |= 2210147191Sjkoshy P6_EVSEL_TO_CMASK(count); 2211145256Sjkoshy } else if (KWMATCH(p, P6_KW_EDGE)) { 2212145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_EDGE; 2213145256Sjkoshy } else if (KWMATCH(p, P6_KW_INV)) { 2214145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_INVERT; 2215145256Sjkoshy } else if (KWMATCH(p, P6_KW_OS)) { 2216145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2217145256Sjkoshy } else if (KWPREFIXMATCH(p, P6_KW_UMASK "=")) { 2218145256Sjkoshy evmask = 0; 2219145256Sjkoshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 2220174406Sjkoshy return (-1); 2221145256Sjkoshy if ((pe == PMC_EV_P6_BUS_DRDY_CLOCKS || 2222145256Sjkoshy pe == PMC_EV_P6_BUS_LOCK_CLOCKS || 2223145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_BRD || 2224145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_RFO || 2225145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_IFETCH || 2226145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_INVAL || 2227145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_PWR || 2228145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_DEF || 2229145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_BURST || 2230145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_ANY || 2231145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_MEM || 2232145256Sjkoshy pe == PMC_EV_P6_BUS_TRANS_IO || 2233145256Sjkoshy pe == PMC_EV_P6_BUS_TRANS_P || 2234145256Sjkoshy pe == PMC_EV_P6_BUS_TRANS_WB || 2235145256Sjkoshy pe == PMC_EV_P6_EMON_EST_TRANS || 2236145256Sjkoshy pe == PMC_EV_P6_EMON_FUSED_UOPS_RET || 2237145256Sjkoshy pe == PMC_EV_P6_EMON_KNI_COMP_INST_RET || 2238145256Sjkoshy pe == PMC_EV_P6_EMON_KNI_INST_RETIRED || 2239145256Sjkoshy pe == PMC_EV_P6_EMON_KNI_PREF_DISPATCHED || 2240145256Sjkoshy pe == PMC_EV_P6_EMON_KNI_PREF_MISS || 2241145256Sjkoshy pe == PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED || 2242145256Sjkoshy pe == PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED || 2243145256Sjkoshy pe == PMC_EV_P6_FP_MMX_TRANS) 2244174406Sjkoshy && (n > 1)) /* Only one mask keyword is allowed. */ 2245174406Sjkoshy return (-1); 2246145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2247145256Sjkoshy } else if (KWMATCH(p, P6_KW_USR)) { 2248145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_USER; 2249145256Sjkoshy } else 2250174406Sjkoshy return (-1); 2251145256Sjkoshy } 2252145256Sjkoshy 2253145256Sjkoshy /* post processing */ 2254145256Sjkoshy switch (pe) { 2255145256Sjkoshy 2256145256Sjkoshy /* 2257145256Sjkoshy * The following events default to an evmask of 0 2258145256Sjkoshy */ 2259145256Sjkoshy 2260145256Sjkoshy /* default => 'self' */ 2261145256Sjkoshy case PMC_EV_P6_BUS_DRDY_CLOCKS: 2262145256Sjkoshy case PMC_EV_P6_BUS_LOCK_CLOCKS: 2263145256Sjkoshy case PMC_EV_P6_BUS_TRAN_BRD: 2264145256Sjkoshy case PMC_EV_P6_BUS_TRAN_RFO: 2265145256Sjkoshy case PMC_EV_P6_BUS_TRANS_WB: 2266145256Sjkoshy case PMC_EV_P6_BUS_TRAN_IFETCH: 2267145256Sjkoshy case PMC_EV_P6_BUS_TRAN_INVAL: 2268145256Sjkoshy case PMC_EV_P6_BUS_TRAN_PWR: 2269145256Sjkoshy case PMC_EV_P6_BUS_TRANS_P: 2270145256Sjkoshy case PMC_EV_P6_BUS_TRANS_IO: 2271145256Sjkoshy case PMC_EV_P6_BUS_TRAN_DEF: 2272145256Sjkoshy case PMC_EV_P6_BUS_TRAN_BURST: 2273145256Sjkoshy case PMC_EV_P6_BUS_TRAN_ANY: 2274145256Sjkoshy case PMC_EV_P6_BUS_TRAN_MEM: 2275145256Sjkoshy 2276145256Sjkoshy /* default => 'nta' */ 2277145256Sjkoshy case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED: 2278145256Sjkoshy case PMC_EV_P6_EMON_KNI_PREF_MISS: 2279145256Sjkoshy 2280145256Sjkoshy /* default => 'packed and scalar' */ 2281145256Sjkoshy case PMC_EV_P6_EMON_KNI_INST_RETIRED: 2282145256Sjkoshy case PMC_EV_P6_EMON_KNI_COMP_INST_RET: 2283145256Sjkoshy 2284145256Sjkoshy /* default => 'mmx to fp transitions' */ 2285145256Sjkoshy case PMC_EV_P6_FP_MMX_TRANS: 2286145256Sjkoshy 2287145256Sjkoshy /* default => 'SSE Packed Single' */ 2288145256Sjkoshy case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED: 2289145256Sjkoshy case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED: 2290145256Sjkoshy 2291145256Sjkoshy /* default => 'all fused micro-ops' */ 2292145256Sjkoshy case PMC_EV_P6_EMON_FUSED_UOPS_RET: 2293145256Sjkoshy 2294145256Sjkoshy /* default => 'all transitions' */ 2295145256Sjkoshy case PMC_EV_P6_EMON_EST_TRANS: 2296145256Sjkoshy break; 2297145256Sjkoshy 2298145256Sjkoshy case PMC_EV_P6_MMX_UOPS_EXEC: 2299145256Sjkoshy evmask = 0x0F; /* only value allowed */ 2300145256Sjkoshy break; 2301145256Sjkoshy 2302145256Sjkoshy default: 2303145256Sjkoshy /* 2304145256Sjkoshy * For all other events, set the default event mask 2305145256Sjkoshy * to a logical OR of all the allowed event mask bits. 2306145256Sjkoshy */ 2307145256Sjkoshy if (evmask == 0 && pmask) { 2308145256Sjkoshy for (pm = pmask; pm->pm_name; pm++) 2309145256Sjkoshy evmask |= pm->pm_value; 2310145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2311145256Sjkoshy } 2312145256Sjkoshy 2313145256Sjkoshy break; 2314145256Sjkoshy } 2315145256Sjkoshy 2316145256Sjkoshy if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) 2317147191Sjkoshy pmc_config->pm_md.pm_ppro.pm_ppro_config |= 2318147191Sjkoshy P6_EVSEL_TO_UMASK(evmask); 2319145256Sjkoshy 2320174406Sjkoshy return (0); 2321145256Sjkoshy} 2322145256Sjkoshy 2323147191Sjkoshy#endif 2324147191Sjkoshy 2325183725Sjkoshy#if defined(__i386__) || defined(__amd64__) 2326183725Sjkoshystatic int 2327183725Sjkoshytsc_allocate_pmc(enum pmc_event pe, char *ctrspec, 2328183725Sjkoshy struct pmc_op_pmcallocate *pmc_config) 2329183725Sjkoshy{ 2330183725Sjkoshy if (pe != PMC_EV_TSC_TSC) 2331183725Sjkoshy return (-1); 2332183725Sjkoshy 2333183725Sjkoshy /* TSC events must be unqualified. */ 2334183725Sjkoshy if (ctrspec && *ctrspec != '\0') 2335183725Sjkoshy return (-1); 2336183725Sjkoshy 2337183725Sjkoshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 2338183725Sjkoshy pmc_config->pm_caps |= PMC_CAP_READ; 2339183725Sjkoshy 2340183725Sjkoshy return (0); 2341183725Sjkoshy} 2342183725Sjkoshy#endif 2343183725Sjkoshy 2344233628Sfabientstatic struct pmc_event_alias generic_aliases[] = { 2345233628Sfabient EV_ALIAS("instructions", "SOFT-CLOCK.HARD"), 2346233628Sfabient EV_ALIAS(NULL, NULL) 2347233628Sfabient}; 2348233628Sfabient 2349233628Sfabientstatic int 2350233628Sfabientsoft_allocate_pmc(enum pmc_event pe, char *ctrspec, 2351233628Sfabient struct pmc_op_pmcallocate *pmc_config) 2352233628Sfabient{ 2353233628Sfabient (void)ctrspec; 2354233628Sfabient (void)pmc_config; 2355233628Sfabient 2356242622Sdim if ((int)pe < PMC_EV_SOFT_FIRST || (int)pe > PMC_EV_SOFT_LAST) 2357233628Sfabient return (-1); 2358233628Sfabient 2359233628Sfabient pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2360233628Sfabient return (0); 2361233628Sfabient} 2362233628Sfabient 2363200928Srpaulo#if defined(__XSCALE__) 2364200928Srpaulo 2365200928Srpaulostatic struct pmc_event_alias xscale_aliases[] = { 2366200928Srpaulo EV_ALIAS("branches", "BRANCH_RETIRED"), 2367200928Srpaulo EV_ALIAS("branch-mispredicts", "BRANCH_MISPRED"), 2368200928Srpaulo EV_ALIAS("dc-misses", "DC_MISS"), 2369200928Srpaulo EV_ALIAS("ic-misses", "IC_MISS"), 2370200928Srpaulo EV_ALIAS("instructions", "INSTR_RETIRED"), 2371200928Srpaulo EV_ALIAS(NULL, NULL) 2372200928Srpaulo}; 2373200928Srpaulostatic int 2374200928Srpauloxscale_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 2375200928Srpaulo struct pmc_op_pmcallocate *pmc_config __unused) 2376200928Srpaulo{ 2377200928Srpaulo switch (pe) { 2378200928Srpaulo default: 2379200928Srpaulo break; 2380200928Srpaulo } 2381200928Srpaulo 2382200928Srpaulo return (0); 2383200928Srpaulo} 2384200928Srpaulo#endif 2385200928Srpaulo 2386204635Sgnn#if defined(__mips__) 2387204635Sgnn 2388204635Sgnnstatic struct pmc_event_alias mips24k_aliases[] = { 2389204635Sgnn EV_ALIAS("instructions", "INSTR_EXECUTED"), 2390204635Sgnn EV_ALIAS("branches", "BRANCH_COMPLETED"), 2391204635Sgnn EV_ALIAS("branch-mispredicts", "BRANCH_MISPRED"), 2392204635Sgnn EV_ALIAS(NULL, NULL) 2393204635Sgnn}; 2394204635Sgnn 2395233335Sgonzostatic struct pmc_event_alias octeon_aliases[] = { 2396233335Sgonzo EV_ALIAS("instructions", "RET"), 2397233335Sgonzo EV_ALIAS("branches", "BR"), 2398233335Sgonzo EV_ALIAS("branch-mispredicts", "BRMIS"), 2399233335Sgonzo EV_ALIAS(NULL, NULL) 2400233335Sgonzo}; 2401233335Sgonzo 2402233320Sgonzo#define MIPS_KW_OS "os" 2403233320Sgonzo#define MIPS_KW_USR "usr" 2404233320Sgonzo#define MIPS_KW_ANYTHREAD "anythread" 2405204635Sgnn 2406204635Sgnnstatic int 2407233320Sgonzomips_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 2408204635Sgnn struct pmc_op_pmcallocate *pmc_config __unused) 2409204635Sgnn{ 2410204635Sgnn char *p; 2411204635Sgnn 2412204635Sgnn (void) pe; 2413204635Sgnn 2414204635Sgnn pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2415204635Sgnn 2416204635Sgnn while ((p = strsep(&ctrspec, ",")) != NULL) { 2417233320Sgonzo if (KWMATCH(p, MIPS_KW_OS)) 2418204635Sgnn pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2419233320Sgonzo else if (KWMATCH(p, MIPS_KW_USR)) 2420204635Sgnn pmc_config->pm_caps |= PMC_CAP_USER; 2421233320Sgonzo else if (KWMATCH(p, MIPS_KW_ANYTHREAD)) 2422204635Sgnn pmc_config->pm_caps |= (PMC_CAP_USER | PMC_CAP_SYSTEM); 2423204635Sgnn else 2424204635Sgnn return (-1); 2425204635Sgnn } 2426204635Sgnn 2427204635Sgnn return (0); 2428204635Sgnn} 2429233320Sgonzo 2430204635Sgnn#endif /* __mips__ */ 2431204635Sgnn 2432228869Sjhibbits#if defined(__powerpc__) 2433204635Sgnn 2434228869Sjhibbitsstatic struct pmc_event_alias ppc7450_aliases[] = { 2435228869Sjhibbits EV_ALIAS("instructions", "INSTR_COMPLETED"), 2436228869Sjhibbits EV_ALIAS("branches", "BRANCHES_COMPLETED"), 2437228869Sjhibbits EV_ALIAS("branch-mispredicts", "MISPREDICTED_BRANCHES"), 2438228869Sjhibbits EV_ALIAS(NULL, NULL) 2439228869Sjhibbits}; 2440228869Sjhibbits 2441263122Sjhibbitsstatic struct pmc_event_alias ppc970_aliases[] = { 2442263122Sjhibbits EV_ALIAS("instructions", "INSTR_COMPLETED"), 2443263122Sjhibbits EV_ALIAS("cycles", "CYCLES"), 2444263122Sjhibbits EV_ALIAS(NULL, NULL) 2445263122Sjhibbits}; 2446228869Sjhibbits 2447263122Sjhibbits#define POWERPC_KW_OS "os" 2448263122Sjhibbits#define POWERPC_KW_USR "usr" 2449263122Sjhibbits#define POWERPC_KW_ANYTHREAD "anythread" 2450263122Sjhibbits 2451228869Sjhibbitsstatic int 2452263122Sjhibbitspowerpc_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 2453263122Sjhibbits struct pmc_op_pmcallocate *pmc_config __unused) 2454228869Sjhibbits{ 2455228869Sjhibbits char *p; 2456228869Sjhibbits 2457228869Sjhibbits (void) pe; 2458228869Sjhibbits 2459228869Sjhibbits pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2460228869Sjhibbits 2461228869Sjhibbits while ((p = strsep(&ctrspec, ",")) != NULL) { 2462263122Sjhibbits if (KWMATCH(p, POWERPC_KW_OS)) 2463228869Sjhibbits pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2464263122Sjhibbits else if (KWMATCH(p, POWERPC_KW_USR)) 2465228869Sjhibbits pmc_config->pm_caps |= PMC_CAP_USER; 2466263122Sjhibbits else if (KWMATCH(p, POWERPC_KW_ANYTHREAD)) 2467228869Sjhibbits pmc_config->pm_caps |= (PMC_CAP_USER | PMC_CAP_SYSTEM); 2468228869Sjhibbits else 2469228869Sjhibbits return (-1); 2470228869Sjhibbits } 2471228869Sjhibbits 2472228869Sjhibbits return (0); 2473228869Sjhibbits} 2474263122Sjhibbits 2475228869Sjhibbits#endif /* __powerpc__ */ 2476228869Sjhibbits 2477228869Sjhibbits 2478145256Sjkoshy/* 2479183725Sjkoshy * Match an event name `name' with its canonical form. 2480183725Sjkoshy * 2481185363Sjkoshy * Matches are case insensitive and spaces, periods, underscores and 2482185363Sjkoshy * hyphen characters are considered to match each other. 2483185363Sjkoshy * 2484183725Sjkoshy * Returns 1 for a match, 0 otherwise. 2485183725Sjkoshy */ 2486183725Sjkoshy 2487183725Sjkoshystatic int 2488183725Sjkoshypmc_match_event_name(const char *name, const char *canonicalname) 2489183725Sjkoshy{ 2490183725Sjkoshy int cc, nc; 2491183725Sjkoshy const unsigned char *c, *n; 2492183725Sjkoshy 2493183725Sjkoshy c = (const unsigned char *) canonicalname; 2494183725Sjkoshy n = (const unsigned char *) name; 2495183725Sjkoshy 2496183725Sjkoshy for (; (nc = *n) && (cc = *c); n++, c++) { 2497183725Sjkoshy 2498185363Sjkoshy if ((nc == ' ' || nc == '_' || nc == '-' || nc == '.') && 2499185363Sjkoshy (cc == ' ' || cc == '_' || cc == '-' || cc == '.')) 2500183725Sjkoshy continue; 2501183725Sjkoshy 2502185363Sjkoshy if (toupper(nc) == toupper(cc)) 2503183725Sjkoshy continue; 2504183725Sjkoshy 2505185363Sjkoshy 2506183725Sjkoshy return (0); 2507183725Sjkoshy } 2508183725Sjkoshy 2509183725Sjkoshy if (*n == '\0' && *c == '\0') 2510183725Sjkoshy return (1); 2511183725Sjkoshy 2512183725Sjkoshy return (0); 2513183725Sjkoshy} 2514183725Sjkoshy 2515183725Sjkoshy/* 2516183725Sjkoshy * Match an event name against all the event named supported by a 2517183725Sjkoshy * PMC class. 2518183725Sjkoshy * 2519183725Sjkoshy * Returns an event descriptor pointer on match or NULL otherwise. 2520183725Sjkoshy */ 2521183725Sjkoshystatic const struct pmc_event_descr * 2522183725Sjkoshypmc_match_event_class(const char *name, 2523183725Sjkoshy const struct pmc_class_descr *pcd) 2524183725Sjkoshy{ 2525183725Sjkoshy size_t n; 2526183725Sjkoshy const struct pmc_event_descr *ev; 2527185363Sjkoshy 2528183725Sjkoshy ev = pcd->pm_evc_event_table; 2529183725Sjkoshy for (n = 0; n < pcd->pm_evc_event_table_size; n++, ev++) 2530183725Sjkoshy if (pmc_match_event_name(name, ev->pm_ev_name)) 2531183725Sjkoshy return (ev); 2532183725Sjkoshy 2533183725Sjkoshy return (NULL); 2534183725Sjkoshy} 2535183725Sjkoshy 2536183725Sjkoshystatic int 2537183725Sjkoshypmc_mdep_is_compatible_class(enum pmc_class pc) 2538183725Sjkoshy{ 2539183725Sjkoshy size_t n; 2540183725Sjkoshy 2541183725Sjkoshy for (n = 0; n < pmc_mdep_class_list_size; n++) 2542183725Sjkoshy if (pmc_mdep_class_list[n] == pc) 2543183725Sjkoshy return (1); 2544183725Sjkoshy return (0); 2545183725Sjkoshy} 2546183725Sjkoshy 2547183725Sjkoshy/* 2548147191Sjkoshy * API entry points 2549145256Sjkoshy */ 2550145256Sjkoshy 2551147191Sjkoshyint 2552147191Sjkoshypmc_allocate(const char *ctrspec, enum pmc_mode mode, 2553147191Sjkoshy uint32_t flags, int cpu, pmc_id_t *pmcid) 2554145256Sjkoshy{ 2555183725Sjkoshy size_t n; 2556147191Sjkoshy int retval; 2557147191Sjkoshy char *r, *spec_copy; 2558147191Sjkoshy const char *ctrname; 2559183725Sjkoshy const struct pmc_event_descr *ev; 2560183725Sjkoshy const struct pmc_event_alias *alias; 2561147191Sjkoshy struct pmc_op_pmcallocate pmc_config; 2562183725Sjkoshy const struct pmc_class_descr *pcd; 2563145256Sjkoshy 2564147191Sjkoshy spec_copy = NULL; 2565147191Sjkoshy retval = -1; 2566145256Sjkoshy 2567147191Sjkoshy if (mode != PMC_MODE_SS && mode != PMC_MODE_TS && 2568147191Sjkoshy mode != PMC_MODE_SC && mode != PMC_MODE_TC) { 2569147191Sjkoshy errno = EINVAL; 2570147191Sjkoshy goto out; 2571147191Sjkoshy } 2572145256Sjkoshy 2573147191Sjkoshy /* replace an event alias with the canonical event specifier */ 2574147191Sjkoshy if (pmc_mdep_event_aliases) 2575183725Sjkoshy for (alias = pmc_mdep_event_aliases; alias->pm_alias; alias++) 2576183725Sjkoshy if (!strcasecmp(ctrspec, alias->pm_alias)) { 2577183725Sjkoshy spec_copy = strdup(alias->pm_spec); 2578147191Sjkoshy break; 2579147191Sjkoshy } 2580145256Sjkoshy 2581147191Sjkoshy if (spec_copy == NULL) 2582147191Sjkoshy spec_copy = strdup(ctrspec); 2583145256Sjkoshy 2584147191Sjkoshy r = spec_copy; 2585147191Sjkoshy ctrname = strsep(&r, ","); 2586145256Sjkoshy 2587183725Sjkoshy /* 2588183725Sjkoshy * If a explicit class prefix was given by the user, restrict the 2589183725Sjkoshy * search for the event to the specified PMC class. 2590183725Sjkoshy */ 2591183725Sjkoshy ev = NULL; 2592185363Sjkoshy for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) { 2593185363Sjkoshy pcd = pmc_class_table[n]; 2594183725Sjkoshy if (pmc_mdep_is_compatible_class(pcd->pm_evc_class) && 2595183725Sjkoshy strncasecmp(ctrname, pcd->pm_evc_name, 2596183725Sjkoshy pcd->pm_evc_name_size) == 0) { 2597183725Sjkoshy if ((ev = pmc_match_event_class(ctrname + 2598183725Sjkoshy pcd->pm_evc_name_size, pcd)) == NULL) { 2599183725Sjkoshy errno = EINVAL; 2600183725Sjkoshy goto out; 2601183725Sjkoshy } 2602147191Sjkoshy break; 2603183725Sjkoshy } 2604183725Sjkoshy } 2605145256Sjkoshy 2606183725Sjkoshy /* 2607183725Sjkoshy * Otherwise, search for this event in all compatible PMC 2608183725Sjkoshy * classes. 2609183725Sjkoshy */ 2610185363Sjkoshy for (n = 0; ev == NULL && n < PMC_CLASS_TABLE_SIZE; n++) { 2611185363Sjkoshy pcd = pmc_class_table[n]; 2612183725Sjkoshy if (pmc_mdep_is_compatible_class(pcd->pm_evc_class)) 2613183725Sjkoshy ev = pmc_match_event_class(ctrname, pcd); 2614183725Sjkoshy } 2615183725Sjkoshy 2616183725Sjkoshy if (ev == NULL) { 2617147191Sjkoshy errno = EINVAL; 2618147191Sjkoshy goto out; 2619147191Sjkoshy } 2620145256Sjkoshy 2621147191Sjkoshy bzero(&pmc_config, sizeof(pmc_config)); 2622183725Sjkoshy pmc_config.pm_ev = ev->pm_ev_code; 2623183725Sjkoshy pmc_config.pm_class = pcd->pm_evc_class; 2624147191Sjkoshy pmc_config.pm_cpu = cpu; 2625147191Sjkoshy pmc_config.pm_mode = mode; 2626147191Sjkoshy pmc_config.pm_flags = flags; 2627145256Sjkoshy 2628147191Sjkoshy if (PMC_IS_SAMPLING_MODE(mode)) 2629147191Sjkoshy pmc_config.pm_caps |= PMC_CAP_INTERRUPT; 2630145256Sjkoshy 2631183725Sjkoshy if (pcd->pm_evc_allocate_pmc(ev->pm_ev_code, r, &pmc_config) < 0) { 2632147191Sjkoshy errno = EINVAL; 2633147191Sjkoshy goto out; 2634147191Sjkoshy } 2635145256Sjkoshy 2636147191Sjkoshy if (PMC_CALL(PMCALLOCATE, &pmc_config) < 0) 2637147191Sjkoshy goto out; 2638145256Sjkoshy 2639147191Sjkoshy *pmcid = pmc_config.pm_pmcid; 2640145256Sjkoshy 2641147191Sjkoshy retval = 0; 2642145256Sjkoshy 2643147191Sjkoshy out: 2644147191Sjkoshy if (spec_copy) 2645147191Sjkoshy free(spec_copy); 2646145256Sjkoshy 2647174406Sjkoshy return (retval); 2648147191Sjkoshy} 2649145256Sjkoshy 2650147191Sjkoshyint 2651147191Sjkoshypmc_attach(pmc_id_t pmc, pid_t pid) 2652147191Sjkoshy{ 2653147191Sjkoshy struct pmc_op_pmcattach pmc_attach_args; 2654145256Sjkoshy 2655147191Sjkoshy pmc_attach_args.pm_pmc = pmc; 2656147191Sjkoshy pmc_attach_args.pm_pid = pid; 2657145256Sjkoshy 2658174406Sjkoshy return (PMC_CALL(PMCATTACH, &pmc_attach_args)); 2659147191Sjkoshy} 2660145256Sjkoshy 2661147191Sjkoshyint 2662147191Sjkoshypmc_capabilities(pmc_id_t pmcid, uint32_t *caps) 2663147191Sjkoshy{ 2664147191Sjkoshy unsigned int i; 2665147191Sjkoshy enum pmc_class cl; 2666145256Sjkoshy 2667147191Sjkoshy cl = PMC_ID_TO_CLASS(pmcid); 2668147191Sjkoshy for (i = 0; i < cpu_info.pm_nclass; i++) 2669147191Sjkoshy if (cpu_info.pm_classes[i].pm_class == cl) { 2670147191Sjkoshy *caps = cpu_info.pm_classes[i].pm_caps; 2671174406Sjkoshy return (0); 2672147191Sjkoshy } 2673177107Sjkoshy errno = EINVAL; 2674177107Sjkoshy return (-1); 2675147191Sjkoshy} 2676145256Sjkoshy 2677147191Sjkoshyint 2678147191Sjkoshypmc_configure_logfile(int fd) 2679147191Sjkoshy{ 2680147191Sjkoshy struct pmc_op_configurelog cla; 2681145256Sjkoshy 2682147191Sjkoshy cla.pm_logfd = fd; 2683147191Sjkoshy if (PMC_CALL(CONFIGURELOG, &cla) < 0) 2684174406Sjkoshy return (-1); 2685174406Sjkoshy return (0); 2686147191Sjkoshy} 2687145256Sjkoshy 2688147191Sjkoshyint 2689147191Sjkoshypmc_cpuinfo(const struct pmc_cpuinfo **pci) 2690147191Sjkoshy{ 2691147191Sjkoshy if (pmc_syscall == -1) { 2692147191Sjkoshy errno = ENXIO; 2693174406Sjkoshy return (-1); 2694147191Sjkoshy } 2695145256Sjkoshy 2696147219Sjkoshy *pci = &cpu_info; 2697174406Sjkoshy return (0); 2698147191Sjkoshy} 2699145256Sjkoshy 2700147191Sjkoshyint 2701147191Sjkoshypmc_detach(pmc_id_t pmc, pid_t pid) 2702147191Sjkoshy{ 2703147191Sjkoshy struct pmc_op_pmcattach pmc_detach_args; 2704145256Sjkoshy 2705147191Sjkoshy pmc_detach_args.pm_pmc = pmc; 2706147191Sjkoshy pmc_detach_args.pm_pid = pid; 2707174406Sjkoshy return (PMC_CALL(PMCDETACH, &pmc_detach_args)); 2708147191Sjkoshy} 2709147191Sjkoshy 2710147191Sjkoshyint 2711147191Sjkoshypmc_disable(int cpu, int pmc) 2712145256Sjkoshy{ 2713147191Sjkoshy struct pmc_op_pmcadmin ssa; 2714145256Sjkoshy 2715147191Sjkoshy ssa.pm_cpu = cpu; 2716147191Sjkoshy ssa.pm_pmc = pmc; 2717147191Sjkoshy ssa.pm_state = PMC_STATE_DISABLED; 2718174406Sjkoshy return (PMC_CALL(PMCADMIN, &ssa)); 2719147191Sjkoshy} 2720145256Sjkoshy 2721147191Sjkoshyint 2722147191Sjkoshypmc_enable(int cpu, int pmc) 2723147191Sjkoshy{ 2724147191Sjkoshy struct pmc_op_pmcadmin ssa; 2725145256Sjkoshy 2726147191Sjkoshy ssa.pm_cpu = cpu; 2727147191Sjkoshy ssa.pm_pmc = pmc; 2728147191Sjkoshy ssa.pm_state = PMC_STATE_FREE; 2729174406Sjkoshy return (PMC_CALL(PMCADMIN, &ssa)); 2730147191Sjkoshy} 2731145256Sjkoshy 2732147191Sjkoshy/* 2733147191Sjkoshy * Return a list of events known to a given PMC class. 'cl' is the 2734147191Sjkoshy * PMC class identifier, 'eventnames' is the returned list of 'const 2735147191Sjkoshy * char *' pointers pointing to the names of the events. 'nevents' is 2736147191Sjkoshy * the number of event name pointers returned. 2737147191Sjkoshy * 2738147191Sjkoshy * The space for 'eventnames' is allocated using malloc(3). The caller 2739147191Sjkoshy * is responsible for freeing this space when done. 2740147191Sjkoshy */ 2741147191Sjkoshyint 2742147191Sjkoshypmc_event_names_of_class(enum pmc_class cl, const char ***eventnames, 2743147191Sjkoshy int *nevents) 2744147191Sjkoshy{ 2745147191Sjkoshy int count; 2746147191Sjkoshy const char **names; 2747147191Sjkoshy const struct pmc_event_descr *ev; 2748147191Sjkoshy 2749147191Sjkoshy switch (cl) 2750147191Sjkoshy { 2751185363Sjkoshy case PMC_CLASS_IAF: 2752185363Sjkoshy ev = iaf_event_table; 2753185363Sjkoshy count = PMC_EVENT_TABLE_SIZE(iaf); 2754185363Sjkoshy break; 2755185363Sjkoshy case PMC_CLASS_IAP: 2756185363Sjkoshy /* 2757185363Sjkoshy * Return the most appropriate set of event name 2758185363Sjkoshy * spellings for the current CPU. 2759185363Sjkoshy */ 2760185363Sjkoshy switch (cpu_info.pm_cputype) { 2761185363Sjkoshy default: 2762185363Sjkoshy case PMC_CPU_INTEL_ATOM: 2763185363Sjkoshy ev = atom_event_table; 2764185363Sjkoshy count = PMC_EVENT_TABLE_SIZE(atom); 2765185363Sjkoshy break; 2766266911Shiren case PMC_CPU_INTEL_ATOM_SILVERMONT: 2767266911Shiren ev = atom_silvermont_event_table; 2768266911Shiren count = PMC_EVENT_TABLE_SIZE(atom_silvermont); 2769266911Shiren break; 2770185363Sjkoshy case PMC_CPU_INTEL_CORE: 2771185363Sjkoshy ev = core_event_table; 2772185363Sjkoshy count = PMC_EVENT_TABLE_SIZE(core); 2773185363Sjkoshy break; 2774185363Sjkoshy case PMC_CPU_INTEL_CORE2: 2775185585Sjkoshy case PMC_CPU_INTEL_CORE2EXTREME: 2776185363Sjkoshy ev = core2_event_table; 2777185363Sjkoshy count = PMC_EVENT_TABLE_SIZE(core2); 2778185363Sjkoshy break; 2779187761Sjeff case PMC_CPU_INTEL_COREI7: 2780187761Sjeff ev = corei7_event_table; 2781187761Sjeff count = PMC_EVENT_TABLE_SIZE(corei7); 2782187761Sjeff break; 2783267602Skib case PMC_CPU_INTEL_NEHALEM_EX: 2784267602Skib ev = nehalem_ex_event_table; 2785267602Skib count = PMC_EVENT_TABLE_SIZE(nehalem_ex); 2786267602Skib break; 2787248842Ssbruno case PMC_CPU_INTEL_HASWELL: 2788248842Ssbruno ev = haswell_event_table; 2789248842Ssbruno count = PMC_EVENT_TABLE_SIZE(haswell); 2790248842Ssbruno break; 2791240164Sfabient case PMC_CPU_INTEL_IVYBRIDGE: 2792240164Sfabient ev = ivybridge_event_table; 2793240164Sfabient count = PMC_EVENT_TABLE_SIZE(ivybridge); 2794240164Sfabient break; 2795246166Ssbruno case PMC_CPU_INTEL_IVYBRIDGE_XEON: 2796246166Ssbruno ev = ivybridge_xeon_event_table; 2797246166Ssbruno count = PMC_EVENT_TABLE_SIZE(ivybridge_xeon); 2798246166Ssbruno break; 2799232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 2800232366Sdavide ev = sandybridge_event_table; 2801232366Sdavide count = PMC_EVENT_TABLE_SIZE(sandybridge); 2802232366Sdavide break; 2803241738Ssbruno case PMC_CPU_INTEL_SANDYBRIDGE_XEON: 2804241738Ssbruno ev = sandybridge_xeon_event_table; 2805241738Ssbruno count = PMC_EVENT_TABLE_SIZE(sandybridge_xeon); 2806241738Ssbruno break; 2807206089Sfabient case PMC_CPU_INTEL_WESTMERE: 2808206089Sfabient ev = westmere_event_table; 2809206089Sfabient count = PMC_EVENT_TABLE_SIZE(westmere); 2810206089Sfabient break; 2811267602Skib case PMC_CPU_INTEL_WESTMERE_EX: 2812267602Skib ev = westmere_ex_event_table; 2813267602Skib count = PMC_EVENT_TABLE_SIZE(westmere_ex); 2814267602Skib break; 2815185363Sjkoshy } 2816185363Sjkoshy break; 2817206089Sfabient case PMC_CLASS_UCF: 2818206089Sfabient ev = ucf_event_table; 2819206089Sfabient count = PMC_EVENT_TABLE_SIZE(ucf); 2820206089Sfabient break; 2821206089Sfabient case PMC_CLASS_UCP: 2822206089Sfabient /* 2823206089Sfabient * Return the most appropriate set of event name 2824206089Sfabient * spellings for the current CPU. 2825206089Sfabient */ 2826206089Sfabient switch (cpu_info.pm_cputype) { 2827206089Sfabient default: 2828206089Sfabient case PMC_CPU_INTEL_COREI7: 2829206089Sfabient ev = corei7uc_event_table; 2830206089Sfabient count = PMC_EVENT_TABLE_SIZE(corei7uc); 2831206089Sfabient break; 2832248842Ssbruno case PMC_CPU_INTEL_HASWELL: 2833248842Ssbruno ev = haswelluc_event_table; 2834248842Ssbruno count = PMC_EVENT_TABLE_SIZE(haswelluc); 2835248842Ssbruno break; 2836232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 2837232366Sdavide ev = sandybridgeuc_event_table; 2838232366Sdavide count = PMC_EVENT_TABLE_SIZE(sandybridgeuc); 2839232366Sdavide break; 2840206089Sfabient case PMC_CPU_INTEL_WESTMERE: 2841206089Sfabient ev = westmereuc_event_table; 2842206089Sfabient count = PMC_EVENT_TABLE_SIZE(westmereuc); 2843206089Sfabient break; 2844206089Sfabient } 2845206089Sfabient break; 2846147191Sjkoshy case PMC_CLASS_TSC: 2847183725Sjkoshy ev = tsc_event_table; 2848183725Sjkoshy count = PMC_EVENT_TABLE_SIZE(tsc); 2849145256Sjkoshy break; 2850147191Sjkoshy case PMC_CLASS_K7: 2851183725Sjkoshy ev = k7_event_table; 2852183725Sjkoshy count = PMC_EVENT_TABLE_SIZE(k7); 2853145256Sjkoshy break; 2854147191Sjkoshy case PMC_CLASS_K8: 2855183725Sjkoshy ev = k8_event_table; 2856183725Sjkoshy count = PMC_EVENT_TABLE_SIZE(k8); 2857145256Sjkoshy break; 2858183725Sjkoshy case PMC_CLASS_P4: 2859183725Sjkoshy ev = p4_event_table; 2860183725Sjkoshy count = PMC_EVENT_TABLE_SIZE(p4); 2861183725Sjkoshy break; 2862147191Sjkoshy case PMC_CLASS_P5: 2863183725Sjkoshy ev = p5_event_table; 2864183725Sjkoshy count = PMC_EVENT_TABLE_SIZE(p5); 2865145256Sjkoshy break; 2866147191Sjkoshy case PMC_CLASS_P6: 2867183725Sjkoshy ev = p6_event_table; 2868183725Sjkoshy count = PMC_EVENT_TABLE_SIZE(p6); 2869145256Sjkoshy break; 2870200928Srpaulo case PMC_CLASS_XSCALE: 2871200928Srpaulo ev = xscale_event_table; 2872200928Srpaulo count = PMC_EVENT_TABLE_SIZE(xscale); 2873200928Srpaulo break; 2874204635Sgnn case PMC_CLASS_MIPS24K: 2875204635Sgnn ev = mips24k_event_table; 2876204635Sgnn count = PMC_EVENT_TABLE_SIZE(mips24k); 2877204635Sgnn break; 2878233335Sgonzo case PMC_CLASS_OCTEON: 2879233335Sgonzo ev = octeon_event_table; 2880233335Sgonzo count = PMC_EVENT_TABLE_SIZE(octeon); 2881233335Sgonzo break; 2882228869Sjhibbits case PMC_CLASS_PPC7450: 2883228869Sjhibbits ev = ppc7450_event_table; 2884228869Sjhibbits count = PMC_EVENT_TABLE_SIZE(ppc7450); 2885228869Sjhibbits break; 2886263122Sjhibbits case PMC_CLASS_PPC970: 2887263122Sjhibbits ev = ppc970_event_table; 2888263122Sjhibbits count = PMC_EVENT_TABLE_SIZE(ppc970); 2889263122Sjhibbits break; 2890233628Sfabient case PMC_CLASS_SOFT: 2891233628Sfabient ev = soft_event_table; 2892233628Sfabient count = soft_event_info.pm_nevent; 2893233628Sfabient break; 2894145256Sjkoshy default: 2895147191Sjkoshy errno = EINVAL; 2896174406Sjkoshy return (-1); 2897145256Sjkoshy } 2898145256Sjkoshy 2899147191Sjkoshy if ((names = malloc(count * sizeof(const char *))) == NULL) 2900174406Sjkoshy return (-1); 2901145256Sjkoshy 2902147191Sjkoshy *eventnames = names; 2903147191Sjkoshy *nevents = count; 2904145256Sjkoshy 2905147191Sjkoshy for (;count--; ev++, names++) 2906147191Sjkoshy *names = ev->pm_ev_name; 2907233628Sfabient 2908174406Sjkoshy return (0); 2909147191Sjkoshy} 2910145256Sjkoshy 2911147191Sjkoshyint 2912147191Sjkoshypmc_flush_logfile(void) 2913147191Sjkoshy{ 2914174406Sjkoshy return (PMC_CALL(FLUSHLOG,0)); 2915147191Sjkoshy} 2916145256Sjkoshy 2917147191Sjkoshyint 2918226514Sfabientpmc_close_logfile(void) 2919226514Sfabient{ 2920226514Sfabient return (PMC_CALL(CLOSELOG,0)); 2921226514Sfabient} 2922226514Sfabient 2923226514Sfabientint 2924147191Sjkoshypmc_get_driver_stats(struct pmc_driverstats *ds) 2925147191Sjkoshy{ 2926147191Sjkoshy struct pmc_op_getdriverstats gms; 2927145256Sjkoshy 2928147191Sjkoshy if (PMC_CALL(GETDRIVERSTATS, &gms) < 0) 2929174406Sjkoshy return (-1); 2930145256Sjkoshy 2931147191Sjkoshy /* copy out fields in the current userland<->library interface */ 2932147191Sjkoshy ds->pm_intr_ignored = gms.pm_intr_ignored; 2933147191Sjkoshy ds->pm_intr_processed = gms.pm_intr_processed; 2934147191Sjkoshy ds->pm_intr_bufferfull = gms.pm_intr_bufferfull; 2935147191Sjkoshy ds->pm_syscalls = gms.pm_syscalls; 2936147191Sjkoshy ds->pm_syscall_errors = gms.pm_syscall_errors; 2937147191Sjkoshy ds->pm_buffer_requests = gms.pm_buffer_requests; 2938147191Sjkoshy ds->pm_buffer_requests_failed = gms.pm_buffer_requests_failed; 2939147191Sjkoshy ds->pm_log_sweeps = gms.pm_log_sweeps; 2940174406Sjkoshy return (0); 2941147191Sjkoshy} 2942145256Sjkoshy 2943147191Sjkoshyint 2944147191Sjkoshypmc_get_msr(pmc_id_t pmc, uint32_t *msr) 2945147191Sjkoshy{ 2946147191Sjkoshy struct pmc_op_getmsr gm; 2947147191Sjkoshy 2948147191Sjkoshy gm.pm_pmcid = pmc; 2949147191Sjkoshy if (PMC_CALL(PMCGETMSR, &gm) < 0) 2950174406Sjkoshy return (-1); 2951147191Sjkoshy *msr = gm.pm_msr; 2952174406Sjkoshy return (0); 2953145256Sjkoshy} 2954145256Sjkoshy 2955145256Sjkoshyint 2956145256Sjkoshypmc_init(void) 2957145256Sjkoshy{ 2958145256Sjkoshy int error, pmc_mod_id; 2959147219Sjkoshy unsigned int n; 2960145256Sjkoshy uint32_t abi_version; 2961145256Sjkoshy struct module_stat pmc_modstat; 2962147219Sjkoshy struct pmc_op_getcpuinfo op_cpu_info; 2963198433Sjkoshy#if defined(__amd64__) || defined(__i386__) 2964198433Sjkoshy int cpu_has_iaf_counters; 2965198433Sjkoshy unsigned int t; 2966198433Sjkoshy#endif 2967145256Sjkoshy 2968145256Sjkoshy if (pmc_syscall != -1) /* already inited */ 2969174406Sjkoshy return (0); 2970145256Sjkoshy 2971145256Sjkoshy /* retrieve the system call number from the KLD */ 2972145256Sjkoshy if ((pmc_mod_id = modfind(PMC_MODULE_NAME)) < 0) 2973174406Sjkoshy return (-1); 2974145256Sjkoshy 2975145256Sjkoshy pmc_modstat.version = sizeof(struct module_stat); 2976145256Sjkoshy if ((error = modstat(pmc_mod_id, &pmc_modstat)) < 0) 2977174406Sjkoshy return (-1); 2978145256Sjkoshy 2979145256Sjkoshy pmc_syscall = pmc_modstat.data.intval; 2980145256Sjkoshy 2981147191Sjkoshy /* check the kernel module's ABI against our compiled-in version */ 2982147191Sjkoshy abi_version = PMC_VERSION; 2983145256Sjkoshy if (PMC_CALL(GETMODULEVERSION, &abi_version) < 0) 2984145256Sjkoshy return (pmc_syscall = -1); 2985145256Sjkoshy 2986147191Sjkoshy /* ignore patch & minor numbers for the comparision */ 2987147191Sjkoshy if ((abi_version & 0xFF000000) != (PMC_VERSION & 0xFF000000)) { 2988145256Sjkoshy errno = EPROGMISMATCH; 2989145256Sjkoshy return (pmc_syscall = -1); 2990145256Sjkoshy } 2991145256Sjkoshy 2992147219Sjkoshy if (PMC_CALL(GETCPUINFO, &op_cpu_info) < 0) 2993145256Sjkoshy return (pmc_syscall = -1); 2994145256Sjkoshy 2995147219Sjkoshy cpu_info.pm_cputype = op_cpu_info.pm_cputype; 2996147219Sjkoshy cpu_info.pm_ncpu = op_cpu_info.pm_ncpu; 2997147219Sjkoshy cpu_info.pm_npmc = op_cpu_info.pm_npmc; 2998147219Sjkoshy cpu_info.pm_nclass = op_cpu_info.pm_nclass; 2999147219Sjkoshy for (n = 0; n < cpu_info.pm_nclass; n++) 3000147219Sjkoshy cpu_info.pm_classes[n] = op_cpu_info.pm_classes[n]; 3001147219Sjkoshy 3002185363Sjkoshy pmc_class_table = malloc(PMC_CLASS_TABLE_SIZE * 3003185363Sjkoshy sizeof(struct pmc_class_descr *)); 3004185363Sjkoshy 3005185363Sjkoshy if (pmc_class_table == NULL) 3006185363Sjkoshy return (-1); 3007185363Sjkoshy 3008198433Sjkoshy for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) 3009198433Sjkoshy pmc_class_table[n] = NULL; 3010185363Sjkoshy 3011185363Sjkoshy /* 3012233628Sfabient * Get soft events list. 3013233628Sfabient */ 3014233628Sfabient soft_event_info.pm_class = PMC_CLASS_SOFT; 3015233628Sfabient if (PMC_CALL(GETDYNEVENTINFO, &soft_event_info) < 0) 3016233628Sfabient return (pmc_syscall = -1); 3017233628Sfabient 3018233628Sfabient /* Map soft events to static list. */ 3019233628Sfabient for (n = 0; n < soft_event_info.pm_nevent; n++) { 3020233628Sfabient soft_event_table[n].pm_ev_name = 3021233628Sfabient soft_event_info.pm_events[n].pm_ev_name; 3022233628Sfabient soft_event_table[n].pm_ev_code = 3023233628Sfabient soft_event_info.pm_events[n].pm_ev_code; 3024233628Sfabient } 3025233628Sfabient soft_class_table_descr.pm_evc_event_table_size = \ 3026233628Sfabient soft_event_info.pm_nevent; 3027233628Sfabient soft_class_table_descr.pm_evc_event_table = \ 3028233628Sfabient soft_event_table; 3029233628Sfabient 3030233628Sfabient /* 3031185363Sjkoshy * Fill in the class table. 3032185363Sjkoshy */ 3033185363Sjkoshy n = 0; 3034233628Sfabient 3035233628Sfabient /* Fill soft events information. */ 3036233628Sfabient pmc_class_table[n++] = &soft_class_table_descr; 3037185363Sjkoshy#if defined(__amd64__) || defined(__i386__) 3038233628Sfabient if (cpu_info.pm_cputype != PMC_CPU_GENERIC) 3039233628Sfabient pmc_class_table[n++] = &tsc_class_table_descr; 3040198433Sjkoshy 3041198433Sjkoshy /* 3042198433Sjkoshy * Check if this CPU has fixed function counters. 3043198433Sjkoshy */ 3044198433Sjkoshy cpu_has_iaf_counters = 0; 3045198433Sjkoshy for (t = 0; t < cpu_info.pm_nclass; t++) 3046212224Sfabient if (cpu_info.pm_classes[t].pm_class == PMC_CLASS_IAF && 3047212224Sfabient cpu_info.pm_classes[t].pm_num > 0) 3048198433Sjkoshy cpu_has_iaf_counters = 1; 3049185363Sjkoshy#endif 3050185363Sjkoshy 3051183725Sjkoshy#define PMC_MDEP_INIT(C) do { \ 3052183725Sjkoshy pmc_mdep_event_aliases = C##_aliases; \ 3053183725Sjkoshy pmc_mdep_class_list = C##_pmc_classes; \ 3054183725Sjkoshy pmc_mdep_class_list_size = \ 3055183725Sjkoshy PMC_TABLE_SIZE(C##_pmc_classes); \ 3056183725Sjkoshy } while (0) 3057183725Sjkoshy 3058198433Sjkoshy#define PMC_MDEP_INIT_INTEL_V2(C) do { \ 3059198433Sjkoshy PMC_MDEP_INIT(C); \ 3060212224Sfabient pmc_class_table[n++] = &iaf_class_table_descr; \ 3061212224Sfabient if (!cpu_has_iaf_counters) \ 3062198433Sjkoshy pmc_mdep_event_aliases = \ 3063198433Sjkoshy C##_aliases_without_iaf; \ 3064198433Sjkoshy pmc_class_table[n] = &C##_class_table_descr; \ 3065198433Sjkoshy } while (0) 3066198433Sjkoshy 3067183725Sjkoshy /* Configure the event name parser. */ 3068145256Sjkoshy switch (cpu_info.pm_cputype) { 3069145340Smarcel#if defined(__i386__) 3070145256Sjkoshy case PMC_CPU_AMD_K7: 3071183725Sjkoshy PMC_MDEP_INIT(k7); 3072185363Sjkoshy pmc_class_table[n] = &k7_class_table_descr; 3073145256Sjkoshy break; 3074145256Sjkoshy case PMC_CPU_INTEL_P5: 3075183725Sjkoshy PMC_MDEP_INIT(p5); 3076185363Sjkoshy pmc_class_table[n] = &p5_class_table_descr; 3077145256Sjkoshy break; 3078145256Sjkoshy case PMC_CPU_INTEL_P6: /* P6 ... Pentium M CPUs have */ 3079145256Sjkoshy case PMC_CPU_INTEL_PII: /* similar PMCs. */ 3080145256Sjkoshy case PMC_CPU_INTEL_PIII: 3081145256Sjkoshy case PMC_CPU_INTEL_PM: 3082183725Sjkoshy PMC_MDEP_INIT(p6); 3083185363Sjkoshy pmc_class_table[n] = &p6_class_table_descr; 3084145256Sjkoshy break; 3085147759Sjkoshy#endif 3086147759Sjkoshy#if defined(__amd64__) || defined(__i386__) 3087183725Sjkoshy case PMC_CPU_AMD_K8: 3088183725Sjkoshy PMC_MDEP_INIT(k8); 3089185363Sjkoshy pmc_class_table[n] = &k8_class_table_descr; 3090183725Sjkoshy break; 3091185363Sjkoshy case PMC_CPU_INTEL_ATOM: 3092198433Sjkoshy PMC_MDEP_INIT_INTEL_V2(atom); 3093185363Sjkoshy break; 3094266911Shiren case PMC_CPU_INTEL_ATOM_SILVERMONT: 3095266911Shiren PMC_MDEP_INIT_INTEL_V2(atom_silvermont); 3096266911Shiren break; 3097185363Sjkoshy case PMC_CPU_INTEL_CORE: 3098185363Sjkoshy PMC_MDEP_INIT(core); 3099202157Sjkoshy pmc_class_table[n] = &core_class_table_descr; 3100185363Sjkoshy break; 3101185363Sjkoshy case PMC_CPU_INTEL_CORE2: 3102185585Sjkoshy case PMC_CPU_INTEL_CORE2EXTREME: 3103198433Sjkoshy PMC_MDEP_INIT_INTEL_V2(core2); 3104185363Sjkoshy break; 3105187761Sjeff case PMC_CPU_INTEL_COREI7: 3106206089Sfabient pmc_class_table[n++] = &ucf_class_table_descr; 3107206089Sfabient pmc_class_table[n++] = &corei7uc_class_table_descr; 3108198433Sjkoshy PMC_MDEP_INIT_INTEL_V2(corei7); 3109187761Sjeff break; 3110267602Skib case PMC_CPU_INTEL_NEHALEM_EX: 3111267602Skib PMC_MDEP_INIT_INTEL_V2(nehalem_ex); 3112267602Skib break; 3113248842Ssbruno case PMC_CPU_INTEL_HASWELL: 3114248842Ssbruno pmc_class_table[n++] = &ucf_class_table_descr; 3115248842Ssbruno pmc_class_table[n++] = &haswelluc_class_table_descr; 3116248842Ssbruno PMC_MDEP_INIT_INTEL_V2(haswell); 3117248842Ssbruno break; 3118240164Sfabient case PMC_CPU_INTEL_IVYBRIDGE: 3119240164Sfabient PMC_MDEP_INIT_INTEL_V2(ivybridge); 3120240164Sfabient break; 3121246166Ssbruno case PMC_CPU_INTEL_IVYBRIDGE_XEON: 3122246166Ssbruno PMC_MDEP_INIT_INTEL_V2(ivybridge_xeon); 3123246166Ssbruno break; 3124232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 3125232366Sdavide pmc_class_table[n++] = &ucf_class_table_descr; 3126232366Sdavide pmc_class_table[n++] = &sandybridgeuc_class_table_descr; 3127232366Sdavide PMC_MDEP_INIT_INTEL_V2(sandybridge); 3128232366Sdavide break; 3129241738Ssbruno case PMC_CPU_INTEL_SANDYBRIDGE_XEON: 3130241738Ssbruno PMC_MDEP_INIT_INTEL_V2(sandybridge_xeon); 3131241738Ssbruno break; 3132206089Sfabient case PMC_CPU_INTEL_WESTMERE: 3133206089Sfabient pmc_class_table[n++] = &ucf_class_table_descr; 3134206089Sfabient pmc_class_table[n++] = &westmereuc_class_table_descr; 3135206089Sfabient PMC_MDEP_INIT_INTEL_V2(westmere); 3136206089Sfabient break; 3137267602Skib case PMC_CPU_INTEL_WESTMERE_EX: 3138267602Skib PMC_MDEP_INIT_INTEL_V2(westmere_ex); 3139267602Skib break; 3140145256Sjkoshy case PMC_CPU_INTEL_PIV: 3141183725Sjkoshy PMC_MDEP_INIT(p4); 3142185363Sjkoshy pmc_class_table[n] = &p4_class_table_descr; 3143145256Sjkoshy break; 3144145256Sjkoshy#endif 3145233628Sfabient case PMC_CPU_GENERIC: 3146233628Sfabient PMC_MDEP_INIT(generic); 3147233628Sfabient break; 3148200928Srpaulo#if defined(__XSCALE__) 3149200928Srpaulo case PMC_CPU_INTEL_XSCALE: 3150200928Srpaulo PMC_MDEP_INIT(xscale); 3151200928Srpaulo pmc_class_table[n] = &xscale_class_table_descr; 3152200928Srpaulo break; 3153200928Srpaulo#endif 3154204635Sgnn#if defined(__mips__) 3155204635Sgnn case PMC_CPU_MIPS_24K: 3156204635Sgnn PMC_MDEP_INIT(mips24k); 3157204635Sgnn pmc_class_table[n] = &mips24k_class_table_descr; 3158204635Sgnn break; 3159233335Sgonzo case PMC_CPU_MIPS_OCTEON: 3160233335Sgonzo PMC_MDEP_INIT(octeon); 3161233335Sgonzo pmc_class_table[n] = &octeon_class_table_descr; 3162233335Sgonzo break; 3163204635Sgnn#endif /* __mips__ */ 3164228869Sjhibbits#if defined(__powerpc__) 3165228869Sjhibbits case PMC_CPU_PPC_7450: 3166228869Sjhibbits PMC_MDEP_INIT(ppc7450); 3167228869Sjhibbits pmc_class_table[n] = &ppc7450_class_table_descr; 3168228869Sjhibbits break; 3169263122Sjhibbits case PMC_CPU_PPC_970: 3170263122Sjhibbits PMC_MDEP_INIT(ppc970); 3171263122Sjhibbits pmc_class_table[n] = &ppc970_class_table_descr; 3172263122Sjhibbits break; 3173228869Sjhibbits#endif 3174145256Sjkoshy default: 3175145256Sjkoshy /* 3176145256Sjkoshy * Some kind of CPU this version of the library knows nothing 3177145256Sjkoshy * about. This shouldn't happen since the abi version check 3178145256Sjkoshy * should have caught this. 3179145256Sjkoshy */ 3180145256Sjkoshy errno = ENXIO; 3181145256Sjkoshy return (pmc_syscall = -1); 3182145256Sjkoshy } 3183145256Sjkoshy 3184174406Sjkoshy return (0); 3185145256Sjkoshy} 3186145256Sjkoshy 3187147191Sjkoshyconst char * 3188147191Sjkoshypmc_name_of_capability(enum pmc_caps cap) 3189145256Sjkoshy{ 3190147191Sjkoshy int i; 3191145256Sjkoshy 3192147191Sjkoshy /* 3193147191Sjkoshy * 'cap' should have a single bit set and should be in 3194147191Sjkoshy * range. 3195147191Sjkoshy */ 3196147191Sjkoshy if ((cap & (cap - 1)) || cap < PMC_CAP_FIRST || 3197147191Sjkoshy cap > PMC_CAP_LAST) { 3198145256Sjkoshy errno = EINVAL; 3199174406Sjkoshy return (NULL); 3200145256Sjkoshy } 3201145256Sjkoshy 3202147191Sjkoshy i = ffs(cap); 3203174406Sjkoshy return (pmc_capability_names[i - 1]); 3204147191Sjkoshy} 3205145256Sjkoshy 3206147191Sjkoshyconst char * 3207147191Sjkoshypmc_name_of_class(enum pmc_class pc) 3208147191Sjkoshy{ 3209147191Sjkoshy if ((int) pc >= PMC_CLASS_FIRST && 3210147191Sjkoshy pc <= PMC_CLASS_LAST) 3211174406Sjkoshy return (pmc_class_names[pc]); 3212145256Sjkoshy 3213147191Sjkoshy errno = EINVAL; 3214174406Sjkoshy return (NULL); 3215147191Sjkoshy} 3216145256Sjkoshy 3217147191Sjkoshyconst char * 3218147191Sjkoshypmc_name_of_cputype(enum pmc_cputype cp) 3219147191Sjkoshy{ 3220183725Sjkoshy size_t n; 3221183725Sjkoshy 3222183725Sjkoshy for (n = 0; n < PMC_TABLE_SIZE(pmc_cputype_names); n++) 3223183725Sjkoshy if (cp == pmc_cputype_names[n].pm_cputype) 3224183725Sjkoshy return (pmc_cputype_names[n].pm_name); 3225183725Sjkoshy 3226147191Sjkoshy errno = EINVAL; 3227174406Sjkoshy return (NULL); 3228147191Sjkoshy} 3229145256Sjkoshy 3230147191Sjkoshyconst char * 3231147191Sjkoshypmc_name_of_disposition(enum pmc_disp pd) 3232147191Sjkoshy{ 3233147191Sjkoshy if ((int) pd >= PMC_DISP_FIRST && 3234147191Sjkoshy pd <= PMC_DISP_LAST) 3235174406Sjkoshy return (pmc_disposition_names[pd]); 3236145256Sjkoshy 3237147191Sjkoshy errno = EINVAL; 3238174406Sjkoshy return (NULL); 3239147191Sjkoshy} 3240145256Sjkoshy 3241147191Sjkoshyconst char * 3242185363Sjkoshy_pmc_name_of_event(enum pmc_event pe, enum pmc_cputype cpu) 3243147191Sjkoshy{ 3244183725Sjkoshy const struct pmc_event_descr *ev, *evfence; 3245145256Sjkoshy 3246183725Sjkoshy ev = evfence = NULL; 3247185363Sjkoshy if (pe >= PMC_EV_IAF_FIRST && pe <= PMC_EV_IAF_LAST) { 3248185363Sjkoshy ev = iaf_event_table; 3249185363Sjkoshy evfence = iaf_event_table + PMC_EVENT_TABLE_SIZE(iaf); 3250185363Sjkoshy } else if (pe >= PMC_EV_IAP_FIRST && pe <= PMC_EV_IAP_LAST) { 3251185363Sjkoshy switch (cpu) { 3252185363Sjkoshy case PMC_CPU_INTEL_ATOM: 3253185363Sjkoshy ev = atom_event_table; 3254185363Sjkoshy evfence = atom_event_table + PMC_EVENT_TABLE_SIZE(atom); 3255185363Sjkoshy break; 3256266911Shiren case PMC_CPU_INTEL_ATOM_SILVERMONT: 3257266911Shiren ev = atom_silvermont_event_table; 3258266911Shiren evfence = atom_silvermont_event_table + 3259266911Shiren PMC_EVENT_TABLE_SIZE(atom_silvermont); 3260266911Shiren break; 3261185363Sjkoshy case PMC_CPU_INTEL_CORE: 3262185363Sjkoshy ev = core_event_table; 3263185363Sjkoshy evfence = core_event_table + PMC_EVENT_TABLE_SIZE(core); 3264185363Sjkoshy break; 3265185363Sjkoshy case PMC_CPU_INTEL_CORE2: 3266185585Sjkoshy case PMC_CPU_INTEL_CORE2EXTREME: 3267185363Sjkoshy ev = core2_event_table; 3268185363Sjkoshy evfence = core2_event_table + PMC_EVENT_TABLE_SIZE(core2); 3269185363Sjkoshy break; 3270187761Sjeff case PMC_CPU_INTEL_COREI7: 3271187761Sjeff ev = corei7_event_table; 3272187761Sjeff evfence = corei7_event_table + PMC_EVENT_TABLE_SIZE(corei7); 3273187761Sjeff break; 3274267602Skib case PMC_CPU_INTEL_NEHALEM_EX: 3275267602Skib ev = nehalem_ex_event_table; 3276267602Skib evfence = nehalem_ex_event_table + 3277267602Skib PMC_EVENT_TABLE_SIZE(nehalem_ex); 3278267602Skib break; 3279248842Ssbruno case PMC_CPU_INTEL_HASWELL: 3280248842Ssbruno ev = haswell_event_table; 3281248842Ssbruno evfence = haswell_event_table + PMC_EVENT_TABLE_SIZE(haswell); 3282248842Ssbruno break; 3283240164Sfabient case PMC_CPU_INTEL_IVYBRIDGE: 3284240164Sfabient ev = ivybridge_event_table; 3285240164Sfabient evfence = ivybridge_event_table + PMC_EVENT_TABLE_SIZE(ivybridge); 3286240164Sfabient break; 3287246166Ssbruno case PMC_CPU_INTEL_IVYBRIDGE_XEON: 3288246166Ssbruno ev = ivybridge_xeon_event_table; 3289246166Ssbruno evfence = ivybridge_xeon_event_table + PMC_EVENT_TABLE_SIZE(ivybridge_xeon); 3290246166Ssbruno break; 3291232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 3292232366Sdavide ev = sandybridge_event_table; 3293232366Sdavide evfence = sandybridge_event_table + PMC_EVENT_TABLE_SIZE(sandybridge); 3294232366Sdavide break; 3295241738Ssbruno case PMC_CPU_INTEL_SANDYBRIDGE_XEON: 3296241738Ssbruno ev = sandybridge_xeon_event_table; 3297241738Ssbruno evfence = sandybridge_xeon_event_table + PMC_EVENT_TABLE_SIZE(sandybridge_xeon); 3298241738Ssbruno break; 3299206089Sfabient case PMC_CPU_INTEL_WESTMERE: 3300206089Sfabient ev = westmere_event_table; 3301206089Sfabient evfence = westmere_event_table + PMC_EVENT_TABLE_SIZE(westmere); 3302206089Sfabient break; 3303267602Skib case PMC_CPU_INTEL_WESTMERE_EX: 3304267602Skib ev = westmere_ex_event_table; 3305267602Skib evfence = westmere_ex_event_table + 3306267602Skib PMC_EVENT_TABLE_SIZE(westmere_ex); 3307267602Skib break; 3308185363Sjkoshy default: /* Unknown CPU type. */ 3309185363Sjkoshy break; 3310185363Sjkoshy } 3311206089Sfabient } else if (pe >= PMC_EV_UCF_FIRST && pe <= PMC_EV_UCF_LAST) { 3312206089Sfabient ev = ucf_event_table; 3313206089Sfabient evfence = ucf_event_table + PMC_EVENT_TABLE_SIZE(ucf); 3314206089Sfabient } else if (pe >= PMC_EV_UCP_FIRST && pe <= PMC_EV_UCP_LAST) { 3315206089Sfabient switch (cpu) { 3316206089Sfabient case PMC_CPU_INTEL_COREI7: 3317206089Sfabient ev = corei7uc_event_table; 3318206089Sfabient evfence = corei7uc_event_table + PMC_EVENT_TABLE_SIZE(corei7uc); 3319206089Sfabient break; 3320232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 3321232366Sdavide ev = sandybridgeuc_event_table; 3322232366Sdavide evfence = sandybridgeuc_event_table + PMC_EVENT_TABLE_SIZE(sandybridgeuc); 3323232366Sdavide break; 3324206089Sfabient case PMC_CPU_INTEL_WESTMERE: 3325206089Sfabient ev = westmereuc_event_table; 3326206089Sfabient evfence = westmereuc_event_table + PMC_EVENT_TABLE_SIZE(westmereuc); 3327206089Sfabient break; 3328206089Sfabient default: /* Unknown CPU type. */ 3329206089Sfabient break; 3330206089Sfabient } 3331206089Sfabient } else if (pe >= PMC_EV_K7_FIRST && pe <= PMC_EV_K7_LAST) { 3332183725Sjkoshy ev = k7_event_table; 3333183725Sjkoshy evfence = k7_event_table + PMC_EVENT_TABLE_SIZE(k7); 3334183725Sjkoshy } else if (pe >= PMC_EV_K8_FIRST && pe <= PMC_EV_K8_LAST) { 3335183725Sjkoshy ev = k8_event_table; 3336183725Sjkoshy evfence = k8_event_table + PMC_EVENT_TABLE_SIZE(k8); 3337183725Sjkoshy } else if (pe >= PMC_EV_P4_FIRST && pe <= PMC_EV_P4_LAST) { 3338183725Sjkoshy ev = p4_event_table; 3339183725Sjkoshy evfence = p4_event_table + PMC_EVENT_TABLE_SIZE(p4); 3340183725Sjkoshy } else if (pe >= PMC_EV_P5_FIRST && pe <= PMC_EV_P5_LAST) { 3341183725Sjkoshy ev = p5_event_table; 3342183725Sjkoshy evfence = p5_event_table + PMC_EVENT_TABLE_SIZE(p5); 3343183725Sjkoshy } else if (pe >= PMC_EV_P6_FIRST && pe <= PMC_EV_P6_LAST) { 3344183725Sjkoshy ev = p6_event_table; 3345183725Sjkoshy evfence = p6_event_table + PMC_EVENT_TABLE_SIZE(p6); 3346200928Srpaulo } else if (pe >= PMC_EV_XSCALE_FIRST && pe <= PMC_EV_XSCALE_LAST) { 3347200928Srpaulo ev = xscale_event_table; 3348200928Srpaulo evfence = xscale_event_table + PMC_EVENT_TABLE_SIZE(xscale); 3349204635Sgnn } else if (pe >= PMC_EV_MIPS24K_FIRST && pe <= PMC_EV_MIPS24K_LAST) { 3350204635Sgnn ev = mips24k_event_table; 3351233628Sfabient evfence = mips24k_event_table + PMC_EVENT_TABLE_SIZE(mips24k); 3352233335Sgonzo } else if (pe >= PMC_EV_OCTEON_FIRST && pe <= PMC_EV_OCTEON_LAST) { 3353233335Sgonzo ev = octeon_event_table; 3354233335Sgonzo evfence = octeon_event_table + PMC_EVENT_TABLE_SIZE(octeon); 3355228869Sjhibbits } else if (pe >= PMC_EV_PPC7450_FIRST && pe <= PMC_EV_PPC7450_LAST) { 3356228869Sjhibbits ev = ppc7450_event_table; 3357233628Sfabient evfence = ppc7450_event_table + PMC_EVENT_TABLE_SIZE(ppc7450); 3358263122Sjhibbits } else if (pe >= PMC_EV_PPC970_FIRST && pe <= PMC_EV_PPC970_LAST) { 3359263122Sjhibbits ev = ppc970_event_table; 3360263122Sjhibbits evfence = ppc970_event_table + PMC_EVENT_TABLE_SIZE(ppc970); 3361183725Sjkoshy } else if (pe == PMC_EV_TSC_TSC) { 3362183725Sjkoshy ev = tsc_event_table; 3363183725Sjkoshy evfence = tsc_event_table + PMC_EVENT_TABLE_SIZE(tsc); 3364242622Sdim } else if ((int)pe >= PMC_EV_SOFT_FIRST && (int)pe <= PMC_EV_SOFT_LAST) { 3365233628Sfabient ev = soft_event_table; 3366233628Sfabient evfence = soft_event_table + soft_event_info.pm_nevent; 3367183725Sjkoshy } 3368183725Sjkoshy 3369183725Sjkoshy for (; ev != evfence; ev++) 3370183725Sjkoshy if (pe == ev->pm_ev_code) 3371183725Sjkoshy return (ev->pm_ev_name); 3372183725Sjkoshy 3373185363Sjkoshy return (NULL); 3374185363Sjkoshy} 3375185363Sjkoshy 3376185363Sjkoshyconst char * 3377185363Sjkoshypmc_name_of_event(enum pmc_event pe) 3378185363Sjkoshy{ 3379185363Sjkoshy const char *n; 3380185363Sjkoshy 3381185363Sjkoshy if ((n = _pmc_name_of_event(pe, cpu_info.pm_cputype)) != NULL) 3382185363Sjkoshy return (n); 3383185363Sjkoshy 3384147191Sjkoshy errno = EINVAL; 3385174406Sjkoshy return (NULL); 3386147191Sjkoshy} 3387145256Sjkoshy 3388147191Sjkoshyconst char * 3389147191Sjkoshypmc_name_of_mode(enum pmc_mode pm) 3390147191Sjkoshy{ 3391147191Sjkoshy if ((int) pm >= PMC_MODE_FIRST && 3392147191Sjkoshy pm <= PMC_MODE_LAST) 3393174406Sjkoshy return (pmc_mode_names[pm]); 3394145256Sjkoshy 3395147191Sjkoshy errno = EINVAL; 3396174406Sjkoshy return (NULL); 3397147191Sjkoshy} 3398145256Sjkoshy 3399147191Sjkoshyconst char * 3400147191Sjkoshypmc_name_of_state(enum pmc_state ps) 3401147191Sjkoshy{ 3402147191Sjkoshy if ((int) ps >= PMC_STATE_FIRST && 3403147191Sjkoshy ps <= PMC_STATE_LAST) 3404174406Sjkoshy return (pmc_state_names[ps]); 3405145256Sjkoshy 3406147191Sjkoshy errno = EINVAL; 3407174406Sjkoshy return (NULL); 3408145256Sjkoshy} 3409145256Sjkoshy 3410145256Sjkoshyint 3411147191Sjkoshypmc_ncpu(void) 3412145256Sjkoshy{ 3413147191Sjkoshy if (pmc_syscall == -1) { 3414147191Sjkoshy errno = ENXIO; 3415174406Sjkoshy return (-1); 3416147191Sjkoshy } 3417145256Sjkoshy 3418174406Sjkoshy return (cpu_info.pm_ncpu); 3419145256Sjkoshy} 3420145256Sjkoshy 3421145256Sjkoshyint 3422147191Sjkoshypmc_npmc(int cpu) 3423145256Sjkoshy{ 3424147191Sjkoshy if (pmc_syscall == -1) { 3425147191Sjkoshy errno = ENXIO; 3426174406Sjkoshy return (-1); 3427147191Sjkoshy } 3428145256Sjkoshy 3429147191Sjkoshy if (cpu < 0 || cpu >= (int) cpu_info.pm_ncpu) { 3430147191Sjkoshy errno = EINVAL; 3431174406Sjkoshy return (-1); 3432147191Sjkoshy } 3433145256Sjkoshy 3434174406Sjkoshy return (cpu_info.pm_npmc); 3435145256Sjkoshy} 3436145256Sjkoshy 3437145256Sjkoshyint 3438147191Sjkoshypmc_pmcinfo(int cpu, struct pmc_pmcinfo **ppmci) 3439145256Sjkoshy{ 3440147191Sjkoshy int nbytes, npmc; 3441147191Sjkoshy struct pmc_op_getpmcinfo *pmci; 3442145256Sjkoshy 3443147191Sjkoshy if ((npmc = pmc_npmc(cpu)) < 0) 3444174406Sjkoshy return (-1); 3445145256Sjkoshy 3446147191Sjkoshy nbytes = sizeof(struct pmc_op_getpmcinfo) + 3447147191Sjkoshy npmc * sizeof(struct pmc_info); 3448145256Sjkoshy 3449147191Sjkoshy if ((pmci = calloc(1, nbytes)) == NULL) 3450174406Sjkoshy return (-1); 3451145256Sjkoshy 3452147191Sjkoshy pmci->pm_cpu = cpu; 3453145256Sjkoshy 3454147191Sjkoshy if (PMC_CALL(GETPMCINFO, pmci) < 0) { 3455147191Sjkoshy free(pmci); 3456174406Sjkoshy return (-1); 3457147191Sjkoshy } 3458145256Sjkoshy 3459147191Sjkoshy /* kernel<->library, library<->userland interfaces are identical */ 3460147191Sjkoshy *ppmci = (struct pmc_pmcinfo *) pmci; 3461174406Sjkoshy return (0); 3462145256Sjkoshy} 3463145256Sjkoshy 3464145256Sjkoshyint 3465145256Sjkoshypmc_read(pmc_id_t pmc, pmc_value_t *value) 3466145256Sjkoshy{ 3467145256Sjkoshy struct pmc_op_pmcrw pmc_read_op; 3468145256Sjkoshy 3469145256Sjkoshy pmc_read_op.pm_pmcid = pmc; 3470145256Sjkoshy pmc_read_op.pm_flags = PMC_F_OLDVALUE; 3471145256Sjkoshy pmc_read_op.pm_value = -1; 3472145256Sjkoshy 3473145256Sjkoshy if (PMC_CALL(PMCRW, &pmc_read_op) < 0) 3474174406Sjkoshy return (-1); 3475145256Sjkoshy 3476145256Sjkoshy *value = pmc_read_op.pm_value; 3477174406Sjkoshy return (0); 3478145256Sjkoshy} 3479145256Sjkoshy 3480145256Sjkoshyint 3481147191Sjkoshypmc_release(pmc_id_t pmc) 3482145256Sjkoshy{ 3483147191Sjkoshy struct pmc_op_simple pmc_release_args; 3484145256Sjkoshy 3485147191Sjkoshy pmc_release_args.pm_pmcid = pmc; 3486174406Sjkoshy return (PMC_CALL(PMCRELEASE, &pmc_release_args)); 3487145256Sjkoshy} 3488145256Sjkoshy 3489145256Sjkoshyint 3490145256Sjkoshypmc_rw(pmc_id_t pmc, pmc_value_t newvalue, pmc_value_t *oldvaluep) 3491145256Sjkoshy{ 3492145256Sjkoshy struct pmc_op_pmcrw pmc_rw_op; 3493145256Sjkoshy 3494145256Sjkoshy pmc_rw_op.pm_pmcid = pmc; 3495145256Sjkoshy pmc_rw_op.pm_flags = PMC_F_NEWVALUE | PMC_F_OLDVALUE; 3496145256Sjkoshy pmc_rw_op.pm_value = newvalue; 3497145256Sjkoshy 3498145256Sjkoshy if (PMC_CALL(PMCRW, &pmc_rw_op) < 0) 3499174406Sjkoshy return (-1); 3500145256Sjkoshy 3501145256Sjkoshy *oldvaluep = pmc_rw_op.pm_value; 3502174406Sjkoshy return (0); 3503145256Sjkoshy} 3504145256Sjkoshy 3505145256Sjkoshyint 3506145256Sjkoshypmc_set(pmc_id_t pmc, pmc_value_t value) 3507145256Sjkoshy{ 3508145256Sjkoshy struct pmc_op_pmcsetcount sc; 3509145256Sjkoshy 3510145256Sjkoshy sc.pm_pmcid = pmc; 3511145256Sjkoshy sc.pm_count = value; 3512145256Sjkoshy 3513145256Sjkoshy if (PMC_CALL(PMCSETCOUNT, &sc) < 0) 3514174406Sjkoshy return (-1); 3515174406Sjkoshy return (0); 3516145256Sjkoshy} 3517145256Sjkoshy 3518145256Sjkoshyint 3519147191Sjkoshypmc_start(pmc_id_t pmc) 3520145256Sjkoshy{ 3521147191Sjkoshy struct pmc_op_simple pmc_start_args; 3522145256Sjkoshy 3523147191Sjkoshy pmc_start_args.pm_pmcid = pmc; 3524174406Sjkoshy return (PMC_CALL(PMCSTART, &pmc_start_args)); 3525145256Sjkoshy} 3526145256Sjkoshy 3527145256Sjkoshyint 3528147191Sjkoshypmc_stop(pmc_id_t pmc) 3529145256Sjkoshy{ 3530147191Sjkoshy struct pmc_op_simple pmc_stop_args; 3531145256Sjkoshy 3532147191Sjkoshy pmc_stop_args.pm_pmcid = pmc; 3533174406Sjkoshy return (PMC_CALL(PMCSTOP, &pmc_stop_args)); 3534145256Sjkoshy} 3535145256Sjkoshy 3536145256Sjkoshyint 3537145774Sjkoshypmc_width(pmc_id_t pmcid, uint32_t *width) 3538145774Sjkoshy{ 3539145774Sjkoshy unsigned int i; 3540145774Sjkoshy enum pmc_class cl; 3541145774Sjkoshy 3542145774Sjkoshy cl = PMC_ID_TO_CLASS(pmcid); 3543145774Sjkoshy for (i = 0; i < cpu_info.pm_nclass; i++) 3544145774Sjkoshy if (cpu_info.pm_classes[i].pm_class == cl) { 3545145774Sjkoshy *width = cpu_info.pm_classes[i].pm_width; 3546174406Sjkoshy return (0); 3547145774Sjkoshy } 3548177107Sjkoshy errno = EINVAL; 3549177107Sjkoshy return (-1); 3550145774Sjkoshy} 3551145774Sjkoshy 3552145774Sjkoshyint 3553147191Sjkoshypmc_write(pmc_id_t pmc, pmc_value_t value) 3554145774Sjkoshy{ 3555147191Sjkoshy struct pmc_op_pmcrw pmc_write_op; 3556145774Sjkoshy 3557147191Sjkoshy pmc_write_op.pm_pmcid = pmc; 3558147191Sjkoshy pmc_write_op.pm_flags = PMC_F_NEWVALUE; 3559147191Sjkoshy pmc_write_op.pm_value = value; 3560174406Sjkoshy return (PMC_CALL(PMCRW, &pmc_write_op)); 3561145256Sjkoshy} 3562145256Sjkoshy 3563145256Sjkoshyint 3564147191Sjkoshypmc_writelog(uint32_t userdata) 3565145256Sjkoshy{ 3566147191Sjkoshy struct pmc_op_writelog wl; 3567145256Sjkoshy 3568147191Sjkoshy wl.pm_userdata = userdata; 3569174406Sjkoshy return (PMC_CALL(WRITELOG, &wl)); 3570145256Sjkoshy} 3571