libpmc.c revision 291494
1145256Sjkoshy/*- 2177107Sjkoshy * Copyright (c) 2003-2008 Joseph Koshy 3145256Sjkoshy * All rights reserved. 4145256Sjkoshy * 5145256Sjkoshy * Redistribution and use in source and binary forms, with or without 6145256Sjkoshy * modification, are permitted provided that the following conditions 7145256Sjkoshy * are met: 8145256Sjkoshy * 1. Redistributions of source code must retain the above copyright 9145256Sjkoshy * notice, this list of conditions and the following disclaimer. 10145256Sjkoshy * 2. Redistributions in binary form must reproduce the above copyright 11145256Sjkoshy * notice, this list of conditions and the following disclaimer in the 12145256Sjkoshy * documentation and/or other materials provided with the distribution. 13145256Sjkoshy * 14145256Sjkoshy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15145256Sjkoshy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16145256Sjkoshy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17145256Sjkoshy * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18145256Sjkoshy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19145256Sjkoshy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20145256Sjkoshy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21145256Sjkoshy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22145256Sjkoshy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23145256Sjkoshy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24145256Sjkoshy * SUCH DAMAGE. 25145256Sjkoshy */ 26145256Sjkoshy 27145256Sjkoshy#include <sys/cdefs.h> 28145256Sjkoshy__FBSDID("$FreeBSD: head/lib/libpmc/libpmc.c 291494 2015-11-30 17:35:49Z rrs $"); 29145256Sjkoshy 30145256Sjkoshy#include <sys/types.h> 31261342Sjhibbits#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 77277835Sbr#if defined(__arm__) 78200928Srpaulo#if defined(__XSCALE__) 79200928Srpaulostatic int xscale_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 80200928Srpaulo struct pmc_op_pmcallocate *_pmc_config); 81200928Srpaulo#endif 82277835Sbrstatic int armv7_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 83277835Sbr struct pmc_op_pmcallocate *_pmc_config); 84277835Sbr#endif 85283112Sbr#if defined(__aarch64__) 86283112Sbrstatic int arm64_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 87283112Sbr struct pmc_op_pmcallocate *_pmc_config); 88283112Sbr#endif 89204635Sgnn#if defined(__mips__) 90233320Sgonzostatic int mips_allocate_pmc(enum pmc_event _pe, char* ctrspec, 91204635Sgnn struct pmc_op_pmcallocate *_pmc_config); 92204635Sgnn#endif /* __mips__ */ 93233628Sfabientstatic int soft_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 94233628Sfabient struct pmc_op_pmcallocate *_pmc_config); 95204635Sgnn 96228869Sjhibbits#if defined(__powerpc__) 97261342Sjhibbitsstatic int powerpc_allocate_pmc(enum pmc_event _pe, char* ctrspec, 98228869Sjhibbits struct pmc_op_pmcallocate *_pmc_config); 99228869Sjhibbits#endif /* __powerpc__ */ 100204635Sgnn 101145256Sjkoshy#define PMC_CALL(cmd, params) \ 102145256Sjkoshy syscall(pmc_syscall, PMC_OP_##cmd, (params)) 103145256Sjkoshy 104145256Sjkoshy/* 105145256Sjkoshy * Event aliases provide a way for the user to ask for generic events 106145256Sjkoshy * like "cache-misses", or "instructions-retired". These aliases are 107145256Sjkoshy * mapped to the appropriate canonical event descriptions using a 108145256Sjkoshy * lookup table. 109145256Sjkoshy */ 110145256Sjkoshystruct pmc_event_alias { 111145256Sjkoshy const char *pm_alias; 112145256Sjkoshy const char *pm_spec; 113145256Sjkoshy}; 114145256Sjkoshy 115145256Sjkoshystatic const struct pmc_event_alias *pmc_mdep_event_aliases; 116145256Sjkoshy 117145256Sjkoshy/* 118183725Sjkoshy * The pmc_event_descr structure maps symbolic names known to the user 119145256Sjkoshy * to integer codes used by the PMC KLD. 120145256Sjkoshy */ 121145256Sjkoshystruct pmc_event_descr { 122145256Sjkoshy const char *pm_ev_name; 123145256Sjkoshy enum pmc_event pm_ev_code; 124145256Sjkoshy}; 125145256Sjkoshy 126183725Sjkoshy/* 127183725Sjkoshy * The pmc_class_descr structure maps class name prefixes for 128183725Sjkoshy * event names to event tables and other PMC class data. 129183725Sjkoshy */ 130183725Sjkoshystruct pmc_class_descr { 131183725Sjkoshy const char *pm_evc_name; 132183725Sjkoshy size_t pm_evc_name_size; 133183725Sjkoshy enum pmc_class pm_evc_class; 134183725Sjkoshy const struct pmc_event_descr *pm_evc_event_table; 135183725Sjkoshy size_t pm_evc_event_table_size; 136183725Sjkoshy int (*pm_evc_allocate_pmc)(enum pmc_event _pe, 137183725Sjkoshy char *_ctrspec, struct pmc_op_pmcallocate *_pa); 138183725Sjkoshy}; 139183725Sjkoshy 140183725Sjkoshy#define PMC_TABLE_SIZE(N) (sizeof(N)/sizeof(N[0])) 141183725Sjkoshy#define PMC_EVENT_TABLE_SIZE(N) PMC_TABLE_SIZE(N##_event_table) 142183725Sjkoshy 143183725Sjkoshy#undef __PMC_EV 144183725Sjkoshy#define __PMC_EV(C,N) { #N, PMC_EV_ ## C ## _ ## N }, 145183725Sjkoshy 146183725Sjkoshy/* 147185363Sjkoshy * PMC_CLASSDEP_TABLE(NAME, CLASS) 148183725Sjkoshy * 149185363Sjkoshy * Define a table mapping event names and aliases to HWPMC event IDs. 150183725Sjkoshy */ 151185363Sjkoshy#define PMC_CLASSDEP_TABLE(N, C) \ 152183725Sjkoshy static const struct pmc_event_descr N##_event_table[] = \ 153183725Sjkoshy { \ 154183725Sjkoshy __PMC_EV_##C() \ 155185363Sjkoshy } 156185363Sjkoshy 157185363SjkoshyPMC_CLASSDEP_TABLE(iaf, IAF); 158185363SjkoshyPMC_CLASSDEP_TABLE(k7, K7); 159185363SjkoshyPMC_CLASSDEP_TABLE(k8, K8); 160185363SjkoshyPMC_CLASSDEP_TABLE(p4, P4); 161185363SjkoshyPMC_CLASSDEP_TABLE(p5, P5); 162185363SjkoshyPMC_CLASSDEP_TABLE(p6, P6); 163200928SrpauloPMC_CLASSDEP_TABLE(xscale, XSCALE); 164277835SbrPMC_CLASSDEP_TABLE(armv7, ARMV7); 165283112SbrPMC_CLASSDEP_TABLE(armv8, ARMV8); 166204635SgnnPMC_CLASSDEP_TABLE(mips24k, MIPS24K); 167281098SadrianPMC_CLASSDEP_TABLE(mips74k, MIPS74K); 168233335SgonzoPMC_CLASSDEP_TABLE(octeon, OCTEON); 169206089SfabientPMC_CLASSDEP_TABLE(ucf, UCF); 170228869SjhibbitsPMC_CLASSDEP_TABLE(ppc7450, PPC7450); 171261342SjhibbitsPMC_CLASSDEP_TABLE(ppc970, PPC970); 172281713SjhibbitsPMC_CLASSDEP_TABLE(e500, E500); 173185363Sjkoshy 174233628Sfabientstatic struct pmc_event_descr soft_event_table[PMC_EV_DYN_COUNT]; 175233628Sfabient 176185363Sjkoshy#undef __PMC_EV_ALIAS 177185363Sjkoshy#define __PMC_EV_ALIAS(N,CODE) { N, PMC_EV_##CODE }, 178185363Sjkoshy 179185363Sjkoshystatic const struct pmc_event_descr atom_event_table[] = 180185363Sjkoshy{ 181185363Sjkoshy __PMC_EV_ALIAS_ATOM() 182185363Sjkoshy}; 183185363Sjkoshy 184263446Shirenstatic const struct pmc_event_descr atom_silvermont_event_table[] = 185263446Shiren{ 186263446Shiren __PMC_EV_ALIAS_ATOM_SILVERMONT() 187263446Shiren}; 188263446Shiren 189185363Sjkoshystatic const struct pmc_event_descr core_event_table[] = 190185363Sjkoshy{ 191185363Sjkoshy __PMC_EV_ALIAS_CORE() 192185363Sjkoshy}; 193185363Sjkoshy 194185363Sjkoshy 195185363Sjkoshystatic const struct pmc_event_descr core2_event_table[] = 196185363Sjkoshy{ 197185363Sjkoshy __PMC_EV_ALIAS_CORE2() 198185363Sjkoshy}; 199185363Sjkoshy 200187761Sjeffstatic const struct pmc_event_descr corei7_event_table[] = 201187761Sjeff{ 202187761Sjeff __PMC_EV_ALIAS_COREI7() 203187761Sjeff}; 204187761Sjeff 205267062Skibstatic const struct pmc_event_descr nehalem_ex_event_table[] = 206267062Skib{ 207267062Skib __PMC_EV_ALIAS_COREI7() 208267062Skib}; 209267062Skib 210248842Ssbrunostatic const struct pmc_event_descr haswell_event_table[] = 211248842Ssbruno{ 212248842Ssbruno __PMC_EV_ALIAS_HASWELL() 213248842Ssbruno}; 214248842Ssbruno 215277177Srrsstatic const struct pmc_event_descr haswell_xeon_event_table[] = 216277177Srrs{ 217277177Srrs __PMC_EV_ALIAS_HASWELL_XEON() 218277177Srrs}; 219277177Srrs 220291494Srrsstatic const struct pmc_event_descr broadwell_event_table[] = 221291494Srrs{ 222291494Srrs __PMC_EV_ALIAS_BROADWELL() 223291494Srrs}; 224277177Srrs 225291494Srrsstatic const struct pmc_event_descr broadwell_xeon_event_table[] = 226291494Srrs{ 227291494Srrs __PMC_EV_ALIAS_BROADWELL_XEON() 228291494Srrs}; 229291494Srrs 230291494Srrsstatic const struct pmc_event_descr skylake_event_table[] = 231291494Srrs{ 232291494Srrs __PMC_EV_ALIAS_SKYLAKE() 233291494Srrs}; 234291494Srrs 235240164Sfabientstatic const struct pmc_event_descr ivybridge_event_table[] = 236240164Sfabient{ 237240164Sfabient __PMC_EV_ALIAS_IVYBRIDGE() 238240164Sfabient}; 239240164Sfabient 240246166Ssbrunostatic const struct pmc_event_descr ivybridge_xeon_event_table[] = 241246166Ssbruno{ 242246166Ssbruno __PMC_EV_ALIAS_IVYBRIDGE_XEON() 243246166Ssbruno}; 244246166Ssbruno 245232366Sdavidestatic const struct pmc_event_descr sandybridge_event_table[] = 246232366Sdavide{ 247232366Sdavide __PMC_EV_ALIAS_SANDYBRIDGE() 248232366Sdavide}; 249232366Sdavide 250241738Ssbrunostatic const struct pmc_event_descr sandybridge_xeon_event_table[] = 251241738Ssbruno{ 252241738Ssbruno __PMC_EV_ALIAS_SANDYBRIDGE_XEON() 253241738Ssbruno}; 254241738Ssbruno 255206089Sfabientstatic const struct pmc_event_descr westmere_event_table[] = 256206089Sfabient{ 257206089Sfabient __PMC_EV_ALIAS_WESTMERE() 258206089Sfabient}; 259206089Sfabient 260267062Skibstatic const struct pmc_event_descr westmere_ex_event_table[] = 261267062Skib{ 262267062Skib __PMC_EV_ALIAS_WESTMERE() 263267062Skib}; 264267062Skib 265206089Sfabientstatic const struct pmc_event_descr corei7uc_event_table[] = 266206089Sfabient{ 267206089Sfabient __PMC_EV_ALIAS_COREI7UC() 268206089Sfabient}; 269206089Sfabient 270248842Ssbrunostatic const struct pmc_event_descr haswelluc_event_table[] = 271248842Ssbruno{ 272248842Ssbruno __PMC_EV_ALIAS_HASWELLUC() 273248842Ssbruno}; 274248842Ssbruno 275291494Srrsstatic const struct pmc_event_descr broadwelluc_event_table[] = 276291494Srrs{ 277291494Srrs __PMC_EV_ALIAS_BROADWELLUC() 278291494Srrs}; 279291494Srrs 280232366Sdavidestatic const struct pmc_event_descr sandybridgeuc_event_table[] = 281232366Sdavide{ 282232366Sdavide __PMC_EV_ALIAS_SANDYBRIDGEUC() 283232366Sdavide}; 284232366Sdavide 285206089Sfabientstatic const struct pmc_event_descr westmereuc_event_table[] = 286206089Sfabient{ 287206089Sfabient __PMC_EV_ALIAS_WESTMEREUC() 288206089Sfabient}; 289206089Sfabient 290284218Sbrstatic const struct pmc_event_descr cortex_a8_event_table[] = 291284218Sbr{ 292284218Sbr __PMC_EV_ALIAS_ARMV7_CORTEX_A8() 293284218Sbr}; 294284218Sbr 295284218Sbrstatic const struct pmc_event_descr cortex_a9_event_table[] = 296284218Sbr{ 297284218Sbr __PMC_EV_ALIAS_ARMV7_CORTEX_A9() 298284218Sbr}; 299284218Sbr 300283112Sbrstatic const struct pmc_event_descr cortex_a53_event_table[] = 301283112Sbr{ 302283112Sbr __PMC_EV_ALIAS_ARMV8_CORTEX_A53() 303283112Sbr}; 304283112Sbr 305283112Sbrstatic const struct pmc_event_descr cortex_a57_event_table[] = 306283112Sbr{ 307283112Sbr __PMC_EV_ALIAS_ARMV8_CORTEX_A57() 308283112Sbr}; 309283112Sbr 310185363Sjkoshy/* 311185363Sjkoshy * PMC_MDEP_TABLE(NAME, PRIMARYCLASS, ADDITIONAL_CLASSES...) 312185363Sjkoshy * 313185363Sjkoshy * Map a CPU to the PMC classes it supports. 314185363Sjkoshy */ 315185363Sjkoshy#define PMC_MDEP_TABLE(N,C,...) \ 316183725Sjkoshy static const enum pmc_class N##_pmc_classes[] = { \ 317183725Sjkoshy PMC_CLASS_##C, __VA_ARGS__ \ 318183725Sjkoshy } 319183725Sjkoshy 320233628SfabientPMC_MDEP_TABLE(atom, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 321263446ShirenPMC_MDEP_TABLE(atom_silvermont, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 322233628SfabientPMC_MDEP_TABLE(core, IAP, PMC_CLASS_SOFT, PMC_CLASS_TSC); 323233628SfabientPMC_MDEP_TABLE(core2, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 324233628SfabientPMC_MDEP_TABLE(corei7, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 325267062SkibPMC_MDEP_TABLE(nehalem_ex, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 326248842SsbrunoPMC_MDEP_TABLE(haswell, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 327277177SrrsPMC_MDEP_TABLE(haswell_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 328291494SrrsPMC_MDEP_TABLE(broadwell, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 329291494SrrsPMC_MDEP_TABLE(broadwell_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 330291494SrrsPMC_MDEP_TABLE(skylake, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 331240164SfabientPMC_MDEP_TABLE(ivybridge, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 332246166SsbrunoPMC_MDEP_TABLE(ivybridge_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 333233628SfabientPMC_MDEP_TABLE(sandybridge, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 334241738SsbrunoPMC_MDEP_TABLE(sandybridge_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 335233628SfabientPMC_MDEP_TABLE(westmere, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 336267062SkibPMC_MDEP_TABLE(westmere_ex, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 337233628SfabientPMC_MDEP_TABLE(k7, K7, PMC_CLASS_SOFT, PMC_CLASS_TSC); 338233628SfabientPMC_MDEP_TABLE(k8, K8, PMC_CLASS_SOFT, PMC_CLASS_TSC); 339233628SfabientPMC_MDEP_TABLE(p4, P4, PMC_CLASS_SOFT, PMC_CLASS_TSC); 340233628SfabientPMC_MDEP_TABLE(p5, P5, PMC_CLASS_SOFT, PMC_CLASS_TSC); 341233628SfabientPMC_MDEP_TABLE(p6, P6, PMC_CLASS_SOFT, PMC_CLASS_TSC); 342233628SfabientPMC_MDEP_TABLE(xscale, XSCALE, PMC_CLASS_SOFT, PMC_CLASS_XSCALE); 343284218SbrPMC_MDEP_TABLE(cortex_a8, ARMV7, PMC_CLASS_SOFT, PMC_CLASS_ARMV7); 344284218SbrPMC_MDEP_TABLE(cortex_a9, ARMV7, PMC_CLASS_SOFT, PMC_CLASS_ARMV7); 345283112SbrPMC_MDEP_TABLE(cortex_a53, ARMV8, PMC_CLASS_SOFT, PMC_CLASS_ARMV8); 346283112SbrPMC_MDEP_TABLE(cortex_a57, ARMV8, PMC_CLASS_SOFT, PMC_CLASS_ARMV8); 347233628SfabientPMC_MDEP_TABLE(mips24k, MIPS24K, PMC_CLASS_SOFT, PMC_CLASS_MIPS24K); 348281098SadrianPMC_MDEP_TABLE(mips74k, MIPS74K, PMC_CLASS_SOFT, PMC_CLASS_MIPS74K); 349233628SfabientPMC_MDEP_TABLE(octeon, OCTEON, PMC_CLASS_SOFT, PMC_CLASS_OCTEON); 350281713SjhibbitsPMC_MDEP_TABLE(ppc7450, PPC7450, PMC_CLASS_SOFT, PMC_CLASS_PPC7450, PMC_CLASS_TSC); 351281713SjhibbitsPMC_MDEP_TABLE(ppc970, PPC970, PMC_CLASS_SOFT, PMC_CLASS_PPC970, PMC_CLASS_TSC); 352281713SjhibbitsPMC_MDEP_TABLE(e500, E500, PMC_CLASS_SOFT, PMC_CLASS_E500, PMC_CLASS_TSC); 353233628SfabientPMC_MDEP_TABLE(generic, SOFT, PMC_CLASS_SOFT); 354183725Sjkoshy 355183725Sjkoshystatic const struct pmc_event_descr tsc_event_table[] = 356145256Sjkoshy{ 357183725Sjkoshy __PMC_EV_TSC() 358145256Sjkoshy}; 359145256Sjkoshy 360183725Sjkoshy#undef PMC_CLASS_TABLE_DESC 361185363Sjkoshy#define PMC_CLASS_TABLE_DESC(NAME, CLASS, EVENTS, ALLOCATOR) \ 362185363Sjkoshystatic const struct pmc_class_descr NAME##_class_table_descr = \ 363185363Sjkoshy { \ 364185363Sjkoshy .pm_evc_name = #CLASS "-", \ 365185363Sjkoshy .pm_evc_name_size = sizeof(#CLASS "-") - 1, \ 366185363Sjkoshy .pm_evc_class = PMC_CLASS_##CLASS , \ 367185363Sjkoshy .pm_evc_event_table = EVENTS##_event_table , \ 368183725Sjkoshy .pm_evc_event_table_size = \ 369185363Sjkoshy PMC_EVENT_TABLE_SIZE(EVENTS), \ 370185363Sjkoshy .pm_evc_allocate_pmc = ALLOCATOR##_allocate_pmc \ 371183725Sjkoshy } 372183725Sjkoshy 373185363Sjkoshy#if defined(__i386__) || defined(__amd64__) 374185363SjkoshyPMC_CLASS_TABLE_DESC(iaf, IAF, iaf, iaf); 375185363SjkoshyPMC_CLASS_TABLE_DESC(atom, IAP, atom, iap); 376263446ShirenPMC_CLASS_TABLE_DESC(atom_silvermont, IAP, atom_silvermont, iap); 377185363SjkoshyPMC_CLASS_TABLE_DESC(core, IAP, core, iap); 378185363SjkoshyPMC_CLASS_TABLE_DESC(core2, IAP, core2, iap); 379187761SjeffPMC_CLASS_TABLE_DESC(corei7, IAP, corei7, iap); 380267062SkibPMC_CLASS_TABLE_DESC(nehalem_ex, IAP, nehalem_ex, iap); 381248842SsbrunoPMC_CLASS_TABLE_DESC(haswell, IAP, haswell, iap); 382279833SrstonePMC_CLASS_TABLE_DESC(haswell_xeon, IAP, haswell_xeon, iap); 383291494SrrsPMC_CLASS_TABLE_DESC(broadwell, IAP, broadwell, iap); 384291494SrrsPMC_CLASS_TABLE_DESC(broadwell_xeon, IAP, broadwell_xeon, iap); 385291494SrrsPMC_CLASS_TABLE_DESC(skylake, IAP, skylake, iap); 386240164SfabientPMC_CLASS_TABLE_DESC(ivybridge, IAP, ivybridge, iap); 387246166SsbrunoPMC_CLASS_TABLE_DESC(ivybridge_xeon, IAP, ivybridge_xeon, iap); 388232366SdavidePMC_CLASS_TABLE_DESC(sandybridge, IAP, sandybridge, iap); 389241738SsbrunoPMC_CLASS_TABLE_DESC(sandybridge_xeon, IAP, sandybridge_xeon, iap); 390206089SfabientPMC_CLASS_TABLE_DESC(westmere, IAP, westmere, iap); 391267062SkibPMC_CLASS_TABLE_DESC(westmere_ex, IAP, westmere_ex, iap); 392206089SfabientPMC_CLASS_TABLE_DESC(ucf, UCF, ucf, ucf); 393206089SfabientPMC_CLASS_TABLE_DESC(corei7uc, UCP, corei7uc, ucp); 394248842SsbrunoPMC_CLASS_TABLE_DESC(haswelluc, UCP, haswelluc, ucp); 395291494SrrsPMC_CLASS_TABLE_DESC(broadwelluc, UCP, broadwelluc, ucp); 396232366SdavidePMC_CLASS_TABLE_DESC(sandybridgeuc, UCP, sandybridgeuc, ucp); 397206089SfabientPMC_CLASS_TABLE_DESC(westmereuc, UCP, westmereuc, ucp); 398185363Sjkoshy#endif 399183725Sjkoshy#if defined(__i386__) 400185363SjkoshyPMC_CLASS_TABLE_DESC(k7, K7, k7, k7); 401183725Sjkoshy#endif 402183725Sjkoshy#if defined(__i386__) || defined(__amd64__) 403185363SjkoshyPMC_CLASS_TABLE_DESC(k8, K8, k8, k8); 404185363SjkoshyPMC_CLASS_TABLE_DESC(p4, P4, p4, p4); 405183725Sjkoshy#endif 406183725Sjkoshy#if defined(__i386__) 407185363SjkoshyPMC_CLASS_TABLE_DESC(p5, P5, p5, p5); 408185363SjkoshyPMC_CLASS_TABLE_DESC(p6, P6, p6, p6); 409183725Sjkoshy#endif 410183725Sjkoshy#if defined(__i386__) || defined(__amd64__) 411185363SjkoshyPMC_CLASS_TABLE_DESC(tsc, TSC, tsc, tsc); 412183725Sjkoshy#endif 413277835Sbr#if defined(__arm__) 414200928Srpaulo#if defined(__XSCALE__) 415200928SrpauloPMC_CLASS_TABLE_DESC(xscale, XSCALE, xscale, xscale); 416200928Srpaulo#endif 417289317SbzPMC_CLASS_TABLE_DESC(cortex_a8, ARMV7, cortex_a8, armv7); 418284218SbrPMC_CLASS_TABLE_DESC(cortex_a9, ARMV7, cortex_a9, armv7); 419277835Sbr#endif 420283112Sbr#if defined(__aarch64__) 421283112SbrPMC_CLASS_TABLE_DESC(cortex_a53, ARMV8, cortex_a53, arm64); 422283112SbrPMC_CLASS_TABLE_DESC(cortex_a57, ARMV8, cortex_a57, arm64); 423283112Sbr#endif 424204635Sgnn#if defined(__mips__) 425233320SgonzoPMC_CLASS_TABLE_DESC(mips24k, MIPS24K, mips24k, mips); 426281098SadrianPMC_CLASS_TABLE_DESC(mips74k, MIPS74K, mips74k, mips); 427233335SgonzoPMC_CLASS_TABLE_DESC(octeon, OCTEON, octeon, mips); 428204635Sgnn#endif /* __mips__ */ 429228869Sjhibbits#if defined(__powerpc__) 430261342SjhibbitsPMC_CLASS_TABLE_DESC(ppc7450, PPC7450, ppc7450, powerpc); 431261342SjhibbitsPMC_CLASS_TABLE_DESC(ppc970, PPC970, ppc970, powerpc); 432281713SjhibbitsPMC_CLASS_TABLE_DESC(e500, E500, e500, powerpc); 433228869Sjhibbits#endif 434228869Sjhibbits 435233628Sfabientstatic struct pmc_class_descr soft_class_table_descr = 436233628Sfabient{ 437233628Sfabient .pm_evc_name = "SOFT-", 438233628Sfabient .pm_evc_name_size = sizeof("SOFT-") - 1, 439233628Sfabient .pm_evc_class = PMC_CLASS_SOFT, 440233628Sfabient .pm_evc_event_table = NULL, 441233628Sfabient .pm_evc_event_table_size = 0, 442233628Sfabient .pm_evc_allocate_pmc = soft_allocate_pmc 443233628Sfabient}; 444233628Sfabient 445183725Sjkoshy#undef PMC_CLASS_TABLE_DESC 446183725Sjkoshy 447185363Sjkoshystatic const struct pmc_class_descr **pmc_class_table; 448185363Sjkoshy#define PMC_CLASS_TABLE_SIZE cpu_info.pm_nclass 449185363Sjkoshy 450183725Sjkoshystatic const enum pmc_class *pmc_mdep_class_list; 451183725Sjkoshystatic size_t pmc_mdep_class_list_size; 452183725Sjkoshy 453145256Sjkoshy/* 454145256Sjkoshy * Mapping tables, mapping enumeration values to human readable 455145256Sjkoshy * strings. 456145256Sjkoshy */ 457145256Sjkoshy 458145256Sjkoshystatic const char * pmc_capability_names[] = { 459145256Sjkoshy#undef __PMC_CAP 460145256Sjkoshy#define __PMC_CAP(N,V,D) #N , 461145256Sjkoshy __PMC_CAPS() 462145256Sjkoshy}; 463145256Sjkoshy 464283120Sjhbstruct pmc_class_map { 465283120Sjhb enum pmc_class pm_class; 466283120Sjhb const char *pm_name; 467283120Sjhb}; 468283120Sjhb 469283120Sjhbstatic const struct pmc_class_map pmc_class_names[] = { 470145256Sjkoshy#undef __PMC_CLASS 471283120Sjhb#define __PMC_CLASS(S,V,D) { .pm_class = PMC_CLASS_##S, .pm_name = #S } , 472145256Sjkoshy __PMC_CLASSES() 473145256Sjkoshy}; 474145256Sjkoshy 475183725Sjkoshystruct pmc_cputype_map { 476228557Sdim enum pmc_cputype pm_cputype; 477183725Sjkoshy const char *pm_name; 478183725Sjkoshy}; 479183725Sjkoshy 480183725Sjkoshystatic const struct pmc_cputype_map pmc_cputype_names[] = { 481145256Sjkoshy#undef __PMC_CPU 482183725Sjkoshy#define __PMC_CPU(S, V, D) { .pm_cputype = PMC_CPU_##S, .pm_name = #S } , 483145256Sjkoshy __PMC_CPUS() 484145256Sjkoshy}; 485145256Sjkoshy 486145256Sjkoshystatic const char * pmc_disposition_names[] = { 487145256Sjkoshy#undef __PMC_DISP 488145256Sjkoshy#define __PMC_DISP(D) #D , 489145256Sjkoshy __PMC_DISPOSITIONS() 490145256Sjkoshy}; 491145256Sjkoshy 492145256Sjkoshystatic const char * pmc_mode_names[] = { 493145256Sjkoshy#undef __PMC_MODE 494145256Sjkoshy#define __PMC_MODE(M,N) #M , 495145256Sjkoshy __PMC_MODES() 496145256Sjkoshy}; 497145256Sjkoshy 498145256Sjkoshystatic const char * pmc_state_names[] = { 499145256Sjkoshy#undef __PMC_STATE 500145256Sjkoshy#define __PMC_STATE(S) #S , 501145256Sjkoshy __PMC_STATES() 502145256Sjkoshy}; 503145256Sjkoshy 504233628Sfabient/* 505233628Sfabient * Filled in by pmc_init(). 506233628Sfabient */ 507233628Sfabientstatic int pmc_syscall = -1; 508233628Sfabientstatic struct pmc_cpuinfo cpu_info; 509233628Sfabientstatic struct pmc_op_getdyneventinfo soft_event_info; 510145256Sjkoshy 511145256Sjkoshy/* Event masks for events */ 512145256Sjkoshystruct pmc_masks { 513145256Sjkoshy const char *pm_name; 514240164Sfabient const uint64_t pm_value; 515145256Sjkoshy}; 516145256Sjkoshy#define PMCMASK(N,V) { .pm_name = #N, .pm_value = (V) } 517206089Sfabient#define NULLMASK { .pm_name = NULL } 518145256Sjkoshy 519147759Sjkoshy#if defined(__amd64__) || defined(__i386__) 520145256Sjkoshystatic int 521240164Sfabientpmc_parse_mask(const struct pmc_masks *pmask, char *p, uint64_t *evmask) 522145256Sjkoshy{ 523145256Sjkoshy const struct pmc_masks *pm; 524145256Sjkoshy char *q, *r; 525145256Sjkoshy int c; 526145256Sjkoshy 527145256Sjkoshy if (pmask == NULL) /* no mask keywords */ 528174406Sjkoshy return (-1); 529183107Sjkoshy q = strchr(p, '='); /* skip '=' */ 530145256Sjkoshy if (*++q == '\0') /* no more data */ 531174406Sjkoshy return (-1); 532145256Sjkoshy c = 0; /* count of mask keywords seen */ 533145256Sjkoshy while ((r = strsep(&q, "+")) != NULL) { 534183725Sjkoshy for (pm = pmask; pm->pm_name && strcasecmp(r, pm->pm_name); 535183725Sjkoshy pm++) 536145256Sjkoshy ; 537145256Sjkoshy if (pm->pm_name == NULL) /* not found */ 538174406Sjkoshy return (-1); 539145256Sjkoshy *evmask |= pm->pm_value; 540145256Sjkoshy c++; 541145256Sjkoshy } 542174406Sjkoshy return (c); 543145256Sjkoshy} 544145340Smarcel#endif 545145256Sjkoshy 546145256Sjkoshy#define KWMATCH(p,kw) (strcasecmp((p), (kw)) == 0) 547145256Sjkoshy#define KWPREFIXMATCH(p,kw) (strncasecmp((p), (kw), sizeof((kw)) - 1) == 0) 548145256Sjkoshy#define EV_ALIAS(N,S) { .pm_alias = N, .pm_spec = S } 549145256Sjkoshy 550145340Smarcel#if defined(__i386__) 551145256Sjkoshy 552145256Sjkoshy/* 553145256Sjkoshy * AMD K7 (Athlon) CPUs. 554145256Sjkoshy */ 555145256Sjkoshy 556145256Sjkoshystatic struct pmc_event_alias k7_aliases[] = { 557145351Sjkoshy EV_ALIAS("branches", "k7-retired-branches"), 558145351Sjkoshy EV_ALIAS("branch-mispredicts", "k7-retired-branches-mispredicted"), 559145351Sjkoshy EV_ALIAS("cycles", "tsc"), 560183075Sjkoshy EV_ALIAS("dc-misses", "k7-dc-misses"), 561145351Sjkoshy EV_ALIAS("ic-misses", "k7-ic-misses"), 562145351Sjkoshy EV_ALIAS("instructions", "k7-retired-instructions"), 563145351Sjkoshy EV_ALIAS("interrupts", "k7-hardware-interrupts"), 564145351Sjkoshy EV_ALIAS(NULL, NULL) 565145256Sjkoshy}; 566145256Sjkoshy 567145256Sjkoshy#define K7_KW_COUNT "count" 568145256Sjkoshy#define K7_KW_EDGE "edge" 569145256Sjkoshy#define K7_KW_INV "inv" 570145256Sjkoshy#define K7_KW_OS "os" 571145256Sjkoshy#define K7_KW_UNITMASK "unitmask" 572145256Sjkoshy#define K7_KW_USR "usr" 573145256Sjkoshy 574145256Sjkoshystatic int 575145256Sjkoshyk7_allocate_pmc(enum pmc_event pe, char *ctrspec, 576145256Sjkoshy struct pmc_op_pmcallocate *pmc_config) 577145256Sjkoshy{ 578183107Sjkoshy char *e, *p, *q; 579183107Sjkoshy int c, has_unitmask; 580145256Sjkoshy uint32_t count, unitmask; 581145256Sjkoshy 582147191Sjkoshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 583183725Sjkoshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 584145256Sjkoshy 585145256Sjkoshy if (pe == PMC_EV_K7_DC_REFILLS_FROM_L2 || 586145256Sjkoshy pe == PMC_EV_K7_DC_REFILLS_FROM_SYSTEM || 587145256Sjkoshy pe == PMC_EV_K7_DC_WRITEBACKS) { 588145256Sjkoshy has_unitmask = 1; 589147191Sjkoshy unitmask = AMD_PMC_UNITMASK_MOESI; 590145256Sjkoshy } else 591145256Sjkoshy unitmask = has_unitmask = 0; 592145256Sjkoshy 593145256Sjkoshy while ((p = strsep(&ctrspec, ",")) != NULL) { 594145256Sjkoshy if (KWPREFIXMATCH(p, K7_KW_COUNT "=")) { 595145256Sjkoshy q = strchr(p, '='); 596145256Sjkoshy if (*++q == '\0') /* skip '=' */ 597174406Sjkoshy return (-1); 598145256Sjkoshy 599145256Sjkoshy count = strtol(q, &e, 0); 600145256Sjkoshy if (e == q || *e != '\0') 601174406Sjkoshy return (-1); 602145256Sjkoshy 603145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 604147191Sjkoshy pmc_config->pm_md.pm_amd.pm_amd_config |= 605147191Sjkoshy AMD_PMC_TO_COUNTER(count); 606145256Sjkoshy 607145256Sjkoshy } else if (KWMATCH(p, K7_KW_EDGE)) { 608145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_EDGE; 609145256Sjkoshy } else if (KWMATCH(p, K7_KW_INV)) { 610145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_INVERT; 611145256Sjkoshy } else if (KWMATCH(p, K7_KW_OS)) { 612145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 613145256Sjkoshy } else if (KWPREFIXMATCH(p, K7_KW_UNITMASK "=")) { 614145256Sjkoshy if (has_unitmask == 0) 615174406Sjkoshy return (-1); 616145256Sjkoshy unitmask = 0; 617145256Sjkoshy q = strchr(p, '='); 618145256Sjkoshy if (*++q == '\0') /* skip '=' */ 619174406Sjkoshy return (-1); 620145256Sjkoshy 621145256Sjkoshy while ((c = tolower(*q++)) != 0) 622145256Sjkoshy if (c == 'm') 623147191Sjkoshy unitmask |= AMD_PMC_UNITMASK_M; 624145256Sjkoshy else if (c == 'o') 625147191Sjkoshy unitmask |= AMD_PMC_UNITMASK_O; 626145256Sjkoshy else if (c == 'e') 627147191Sjkoshy unitmask |= AMD_PMC_UNITMASK_E; 628145256Sjkoshy else if (c == 's') 629147191Sjkoshy unitmask |= AMD_PMC_UNITMASK_S; 630145256Sjkoshy else if (c == 'i') 631147191Sjkoshy unitmask |= AMD_PMC_UNITMASK_I; 632145256Sjkoshy else if (c == '+') 633145256Sjkoshy continue; 634145256Sjkoshy else 635174406Sjkoshy return (-1); 636145256Sjkoshy 637145256Sjkoshy if (unitmask == 0) 638174406Sjkoshy return (-1); 639145256Sjkoshy 640145256Sjkoshy } else if (KWMATCH(p, K7_KW_USR)) { 641145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_USER; 642145256Sjkoshy } else 643174406Sjkoshy return (-1); 644145256Sjkoshy } 645145256Sjkoshy 646145256Sjkoshy if (has_unitmask) { 647145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 648147191Sjkoshy pmc_config->pm_md.pm_amd.pm_amd_config |= 649147191Sjkoshy AMD_PMC_TO_UNITMASK(unitmask); 650145256Sjkoshy } 651145256Sjkoshy 652174406Sjkoshy return (0); 653145256Sjkoshy 654145256Sjkoshy} 655145256Sjkoshy 656147191Sjkoshy#endif 657147191Sjkoshy 658147759Sjkoshy#if defined(__amd64__) || defined(__i386__) 659147191Sjkoshy 660145256Sjkoshy/* 661185363Sjkoshy * Intel Core (Family 6, Model E) PMCs. 662185363Sjkoshy */ 663185363Sjkoshy 664185363Sjkoshystatic struct pmc_event_alias core_aliases[] = { 665185363Sjkoshy EV_ALIAS("branches", "iap-br-instr-ret"), 666185363Sjkoshy EV_ALIAS("branch-mispredicts", "iap-br-mispred-ret"), 667185363Sjkoshy EV_ALIAS("cycles", "tsc-tsc"), 668185363Sjkoshy EV_ALIAS("ic-misses", "iap-icache-misses"), 669185363Sjkoshy EV_ALIAS("instructions", "iap-instr-ret"), 670185363Sjkoshy EV_ALIAS("interrupts", "iap-core-hw-int-rx"), 671185363Sjkoshy EV_ALIAS("unhalted-cycles", "iap-unhalted-core-cycles"), 672185363Sjkoshy EV_ALIAS(NULL, NULL) 673185363Sjkoshy}; 674185363Sjkoshy 675185363Sjkoshy/* 676185363Sjkoshy * Intel Core2 (Family 6, Model F), Core2Extreme (Family 6, Model 17H) 677185363Sjkoshy * and Atom (Family 6, model 1CH) PMCs. 678198433Sjkoshy * 679198433Sjkoshy * We map aliases to events on the fixed-function counters if these 680198433Sjkoshy * are present. Note that not all CPUs in this family contain fixed-function 681198433Sjkoshy * counters. 682185363Sjkoshy */ 683185363Sjkoshy 684185363Sjkoshystatic struct pmc_event_alias core2_aliases[] = { 685185363Sjkoshy EV_ALIAS("branches", "iap-br-inst-retired.any"), 686185363Sjkoshy EV_ALIAS("branch-mispredicts", "iap-br-inst-retired.mispred"), 687185363Sjkoshy EV_ALIAS("cycles", "tsc-tsc"), 688185363Sjkoshy EV_ALIAS("ic-misses", "iap-l1i-misses"), 689185363Sjkoshy EV_ALIAS("instructions", "iaf-instr-retired.any"), 690185363Sjkoshy EV_ALIAS("interrupts", "iap-hw-int-rcv"), 691185363Sjkoshy EV_ALIAS("unhalted-cycles", "iaf-cpu-clk-unhalted.core"), 692185363Sjkoshy EV_ALIAS(NULL, NULL) 693185363Sjkoshy}; 694185363Sjkoshy 695198433Sjkoshystatic struct pmc_event_alias core2_aliases_without_iaf[] = { 696198433Sjkoshy EV_ALIAS("branches", "iap-br-inst-retired.any"), 697198433Sjkoshy EV_ALIAS("branch-mispredicts", "iap-br-inst-retired.mispred"), 698198433Sjkoshy EV_ALIAS("cycles", "tsc-tsc"), 699198433Sjkoshy EV_ALIAS("ic-misses", "iap-l1i-misses"), 700198433Sjkoshy EV_ALIAS("instructions", "iap-inst-retired.any_p"), 701198433Sjkoshy EV_ALIAS("interrupts", "iap-hw-int-rcv"), 702198433Sjkoshy EV_ALIAS("unhalted-cycles", "iap-cpu-clk-unhalted.core_p"), 703198433Sjkoshy EV_ALIAS(NULL, NULL) 704198433Sjkoshy}; 705198433Sjkoshy 706198433Sjkoshy#define atom_aliases core2_aliases 707198433Sjkoshy#define atom_aliases_without_iaf core2_aliases_without_iaf 708263446Shiren#define atom_silvermont_aliases core2_aliases 709263446Shiren#define atom_silvermont_aliases_without_iaf core2_aliases_without_iaf 710198433Sjkoshy#define corei7_aliases core2_aliases 711198433Sjkoshy#define corei7_aliases_without_iaf core2_aliases_without_iaf 712267062Skib#define nehalem_ex_aliases core2_aliases 713267062Skib#define nehalem_ex_aliases_without_iaf core2_aliases_without_iaf 714248842Ssbruno#define haswell_aliases core2_aliases 715248842Ssbruno#define haswell_aliases_without_iaf core2_aliases_without_iaf 716277177Srrs#define haswell_xeon_aliases core2_aliases 717277177Srrs#define haswell_xeon_aliases_without_iaf core2_aliases_without_iaf 718291494Srrs#define broadwell_aliases core2_aliases 719291494Srrs#define broadwell_aliases_without_iaf core2_aliases_without_iaf 720291494Srrs#define broadwell_xeon_aliases core2_aliases 721291494Srrs#define broadwell_xeon_aliases_without_iaf core2_aliases_without_iaf 722291494Srrs#define skylake_aliases core2_aliases 723291494Srrs#define skylake_aliases_without_iaf core2_aliases_without_iaf 724240164Sfabient#define ivybridge_aliases core2_aliases 725240164Sfabient#define ivybridge_aliases_without_iaf core2_aliases_without_iaf 726246166Ssbruno#define ivybridge_xeon_aliases core2_aliases 727246166Ssbruno#define ivybridge_xeon_aliases_without_iaf core2_aliases_without_iaf 728232366Sdavide#define sandybridge_aliases core2_aliases 729232366Sdavide#define sandybridge_aliases_without_iaf core2_aliases_without_iaf 730241738Ssbruno#define sandybridge_xeon_aliases core2_aliases 731241738Ssbruno#define sandybridge_xeon_aliases_without_iaf core2_aliases_without_iaf 732206089Sfabient#define westmere_aliases core2_aliases 733206089Sfabient#define westmere_aliases_without_iaf core2_aliases_without_iaf 734267062Skib#define westmere_ex_aliases core2_aliases 735267062Skib#define westmere_ex_aliases_without_iaf core2_aliases_without_iaf 736198433Sjkoshy 737185363Sjkoshy#define IAF_KW_OS "os" 738185363Sjkoshy#define IAF_KW_USR "usr" 739185363Sjkoshy#define IAF_KW_ANYTHREAD "anythread" 740185363Sjkoshy 741185363Sjkoshy/* 742185363Sjkoshy * Parse an event specifier for Intel fixed function counters. 743185363Sjkoshy */ 744185363Sjkoshystatic int 745185363Sjkoshyiaf_allocate_pmc(enum pmc_event pe, char *ctrspec, 746185363Sjkoshy struct pmc_op_pmcallocate *pmc_config) 747185363Sjkoshy{ 748185363Sjkoshy char *p; 749185363Sjkoshy 750185363Sjkoshy (void) pe; 751185363Sjkoshy 752185363Sjkoshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 753185363Sjkoshy pmc_config->pm_md.pm_iaf.pm_iaf_flags = 0; 754185363Sjkoshy 755185363Sjkoshy while ((p = strsep(&ctrspec, ",")) != NULL) { 756185363Sjkoshy if (KWMATCH(p, IAF_KW_OS)) 757185363Sjkoshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 758185363Sjkoshy else if (KWMATCH(p, IAF_KW_USR)) 759185363Sjkoshy pmc_config->pm_caps |= PMC_CAP_USER; 760185363Sjkoshy else if (KWMATCH(p, IAF_KW_ANYTHREAD)) 761185363Sjkoshy pmc_config->pm_md.pm_iaf.pm_iaf_flags |= IAF_ANY; 762185363Sjkoshy else 763185363Sjkoshy return (-1); 764185363Sjkoshy } 765185363Sjkoshy 766185363Sjkoshy return (0); 767185363Sjkoshy} 768185363Sjkoshy 769185363Sjkoshy/* 770185363Sjkoshy * Core/Core2 support. 771185363Sjkoshy */ 772185363Sjkoshy 773185363Sjkoshy#define IAP_KW_AGENT "agent" 774185363Sjkoshy#define IAP_KW_ANYTHREAD "anythread" 775185363Sjkoshy#define IAP_KW_CACHESTATE "cachestate" 776185363Sjkoshy#define IAP_KW_CMASK "cmask" 777185363Sjkoshy#define IAP_KW_CORE "core" 778185363Sjkoshy#define IAP_KW_EDGE "edge" 779185363Sjkoshy#define IAP_KW_INV "inv" 780185363Sjkoshy#define IAP_KW_OS "os" 781185363Sjkoshy#define IAP_KW_PREFETCH "prefetch" 782185363Sjkoshy#define IAP_KW_SNOOPRESPONSE "snoopresponse" 783185363Sjkoshy#define IAP_KW_SNOOPTYPE "snooptype" 784185363Sjkoshy#define IAP_KW_TRANSITION "trans" 785185363Sjkoshy#define IAP_KW_USR "usr" 786206089Sfabient#define IAP_KW_RSP "rsp" 787185363Sjkoshy 788185363Sjkoshystatic struct pmc_masks iap_core_mask[] = { 789185363Sjkoshy PMCMASK(all, (0x3 << 14)), 790185363Sjkoshy PMCMASK(this, (0x1 << 14)), 791185363Sjkoshy NULLMASK 792185363Sjkoshy}; 793185363Sjkoshy 794185363Sjkoshystatic struct pmc_masks iap_agent_mask[] = { 795185363Sjkoshy PMCMASK(this, 0), 796185363Sjkoshy PMCMASK(any, (0x1 << 13)), 797185363Sjkoshy NULLMASK 798185363Sjkoshy}; 799185363Sjkoshy 800185363Sjkoshystatic struct pmc_masks iap_prefetch_mask[] = { 801185363Sjkoshy PMCMASK(both, (0x3 << 12)), 802185363Sjkoshy PMCMASK(only, (0x1 << 12)), 803185363Sjkoshy PMCMASK(exclude, 0), 804185363Sjkoshy NULLMASK 805185363Sjkoshy}; 806185363Sjkoshy 807185363Sjkoshystatic struct pmc_masks iap_cachestate_mask[] = { 808185363Sjkoshy PMCMASK(i, (1 << 8)), 809185363Sjkoshy PMCMASK(s, (1 << 9)), 810185363Sjkoshy PMCMASK(e, (1 << 10)), 811185363Sjkoshy PMCMASK(m, (1 << 11)), 812185363Sjkoshy NULLMASK 813185363Sjkoshy}; 814185363Sjkoshy 815185363Sjkoshystatic struct pmc_masks iap_snoopresponse_mask[] = { 816185363Sjkoshy PMCMASK(clean, (1 << 8)), 817185363Sjkoshy PMCMASK(hit, (1 << 9)), 818185363Sjkoshy PMCMASK(hitm, (1 << 11)), 819185363Sjkoshy NULLMASK 820185363Sjkoshy}; 821185363Sjkoshy 822185363Sjkoshystatic struct pmc_masks iap_snooptype_mask[] = { 823185363Sjkoshy PMCMASK(cmp2s, (1 << 8)), 824185363Sjkoshy PMCMASK(cmp2i, (1 << 9)), 825185363Sjkoshy NULLMASK 826185363Sjkoshy}; 827185363Sjkoshy 828185363Sjkoshystatic struct pmc_masks iap_transition_mask[] = { 829185363Sjkoshy PMCMASK(any, 0x00), 830185363Sjkoshy PMCMASK(frequency, 0x10), 831185363Sjkoshy NULLMASK 832185363Sjkoshy}; 833185363Sjkoshy 834240164Sfabientstatic struct pmc_masks iap_rsp_mask_i7_wm[] = { 835206089Sfabient PMCMASK(DMND_DATA_RD, (1 << 0)), 836206089Sfabient PMCMASK(DMND_RFO, (1 << 1)), 837206089Sfabient PMCMASK(DMND_IFETCH, (1 << 2)), 838206089Sfabient PMCMASK(WB, (1 << 3)), 839206089Sfabient PMCMASK(PF_DATA_RD, (1 << 4)), 840206089Sfabient PMCMASK(PF_RFO, (1 << 5)), 841206089Sfabient PMCMASK(PF_IFETCH, (1 << 6)), 842206089Sfabient PMCMASK(OTHER, (1 << 7)), 843206089Sfabient PMCMASK(UNCORE_HIT, (1 << 8)), 844206089Sfabient PMCMASK(OTHER_CORE_HIT_SNP, (1 << 9)), 845206089Sfabient PMCMASK(OTHER_CORE_HITM, (1 << 10)), 846206089Sfabient PMCMASK(REMOTE_CACHE_FWD, (1 << 12)), 847206089Sfabient PMCMASK(REMOTE_DRAM, (1 << 13)), 848206089Sfabient PMCMASK(LOCAL_DRAM, (1 << 14)), 849206089Sfabient PMCMASK(NON_DRAM, (1 << 15)), 850206089Sfabient NULLMASK 851206089Sfabient}; 852206089Sfabient 853241738Ssbrunostatic struct pmc_masks iap_rsp_mask_sb_sbx_ib[] = { 854240164Sfabient PMCMASK(REQ_DMND_DATA_RD, (1ULL << 0)), 855240164Sfabient PMCMASK(REQ_DMND_RFO, (1ULL << 1)), 856240164Sfabient PMCMASK(REQ_DMND_IFETCH, (1ULL << 2)), 857240164Sfabient PMCMASK(REQ_WB, (1ULL << 3)), 858240164Sfabient PMCMASK(REQ_PF_DATA_RD, (1ULL << 4)), 859240164Sfabient PMCMASK(REQ_PF_RFO, (1ULL << 5)), 860240164Sfabient PMCMASK(REQ_PF_IFETCH, (1ULL << 6)), 861240164Sfabient PMCMASK(REQ_PF_LLC_DATA_RD, (1ULL << 7)), 862240164Sfabient PMCMASK(REQ_PF_LLC_RFO, (1ULL << 8)), 863240164Sfabient PMCMASK(REQ_PF_LLC_IFETCH, (1ULL << 9)), 864240164Sfabient PMCMASK(REQ_BUS_LOCKS, (1ULL << 10)), 865240164Sfabient PMCMASK(REQ_STRM_ST, (1ULL << 11)), 866240164Sfabient PMCMASK(REQ_OTHER, (1ULL << 15)), 867240164Sfabient PMCMASK(RES_ANY, (1ULL << 16)), 868240164Sfabient PMCMASK(RES_SUPPLIER_SUPP, (1ULL << 17)), 869240164Sfabient PMCMASK(RES_SUPPLIER_LLC_HITM, (1ULL << 18)), 870240164Sfabient PMCMASK(RES_SUPPLIER_LLC_HITE, (1ULL << 19)), 871240164Sfabient PMCMASK(RES_SUPPLIER_LLC_HITS, (1ULL << 20)), 872240164Sfabient PMCMASK(RES_SUPPLIER_LLC_HITF, (1ULL << 21)), 873240164Sfabient PMCMASK(RES_SUPPLIER_LOCAL, (1ULL << 22)), 874241974Ssbruno PMCMASK(RES_SNOOP_SNP_NONE, (1ULL << 31)), 875240164Sfabient PMCMASK(RES_SNOOP_SNP_NO_NEEDED,(1ULL << 32)), 876240164Sfabient PMCMASK(RES_SNOOP_SNP_MISS, (1ULL << 33)), 877240164Sfabient PMCMASK(RES_SNOOP_HIT_NO_FWD, (1ULL << 34)), 878240164Sfabient PMCMASK(RES_SNOOP_HIT_FWD, (1ULL << 35)), 879240164Sfabient PMCMASK(RES_SNOOP_HITM, (1ULL << 36)), 880240164Sfabient PMCMASK(RES_NON_DRAM, (1ULL << 37)), 881240164Sfabient NULLMASK 882240164Sfabient}; 883240164Sfabient 884291494Srrs/* Broadwell is defined to use the same mask as Haswell */ 885248842Ssbrunostatic struct pmc_masks iap_rsp_mask_haswell[] = { 886248842Ssbruno PMCMASK(REQ_DMND_DATA_RD, (1ULL << 0)), 887248842Ssbruno PMCMASK(REQ_DMND_RFO, (1ULL << 1)), 888248842Ssbruno PMCMASK(REQ_DMND_IFETCH, (1ULL << 2)), 889248842Ssbruno PMCMASK(REQ_PF_DATA_RD, (1ULL << 4)), 890248842Ssbruno PMCMASK(REQ_PF_RFO, (1ULL << 5)), 891248842Ssbruno PMCMASK(REQ_PF_IFETCH, (1ULL << 6)), 892248842Ssbruno PMCMASK(REQ_OTHER, (1ULL << 15)), 893248842Ssbruno PMCMASK(RES_ANY, (1ULL << 16)), 894248842Ssbruno PMCMASK(RES_SUPPLIER_SUPP, (1ULL << 17)), 895248842Ssbruno PMCMASK(RES_SUPPLIER_LLC_HITM, (1ULL << 18)), 896248842Ssbruno PMCMASK(RES_SUPPLIER_LLC_HITE, (1ULL << 19)), 897248842Ssbruno PMCMASK(RES_SUPPLIER_LLC_HITS, (1ULL << 20)), 898248842Ssbruno PMCMASK(RES_SUPPLIER_LLC_HITF, (1ULL << 21)), 899248842Ssbruno PMCMASK(RES_SUPPLIER_LOCAL, (1ULL << 22)), 900291494Srrs /* 901291494Srrs * For processor type 06_45H 22 is L4_HIT_LOCAL_L4 902291494Srrs * and 23, 24 and 25 are also defined. 903291494Srrs */ 904248842Ssbruno PMCMASK(RES_SNOOP_SNP_NONE, (1ULL << 31)), 905248842Ssbruno PMCMASK(RES_SNOOP_SNP_NO_NEEDED,(1ULL << 32)), 906248842Ssbruno PMCMASK(RES_SNOOP_SNP_MISS, (1ULL << 33)), 907248842Ssbruno PMCMASK(RES_SNOOP_HIT_NO_FWD, (1ULL << 34)), 908248842Ssbruno PMCMASK(RES_SNOOP_HIT_FWD, (1ULL << 35)), 909248842Ssbruno PMCMASK(RES_SNOOP_HITM, (1ULL << 36)), 910248842Ssbruno PMCMASK(RES_NON_DRAM, (1ULL << 37)), 911248842Ssbruno NULLMASK 912248842Ssbruno}; 913248842Ssbruno 914291494Srrsstatic struct pmc_masks iap_rsp_mask_skylake[] = { 915291494Srrs PMCMASK(REQ_DMND_DATA_RD, (1ULL << 0)), 916291494Srrs PMCMASK(REQ_DMND_RFO, (1ULL << 1)), 917291494Srrs PMCMASK(REQ_DMND_IFETCH, (1ULL << 2)), 918291494Srrs PMCMASK(REQ_PF_DATA_RD, (1ULL << 7)), 919291494Srrs PMCMASK(REQ_PF_RFO, (1ULL << 8)), 920291494Srrs PMCMASK(REQ_STRM_ST, (1ULL << 11)), 921291494Srrs PMCMASK(REQ_OTHER, (1ULL << 15)), 922291494Srrs PMCMASK(RES_ANY, (1ULL << 16)), 923291494Srrs PMCMASK(RES_SUPPLIER_SUPP, (1ULL << 17)), 924291494Srrs PMCMASK(RES_SUPPLIER_LLC_HITM, (1ULL << 18)), 925291494Srrs PMCMASK(RES_SUPPLIER_LLC_HITE, (1ULL << 19)), 926291494Srrs PMCMASK(RES_SUPPLIER_LLC_HITS, (1ULL << 20)), 927291494Srrs PMCMASK(RES_SUPPLIER_L4_HIT, (1ULL << 22)), 928291494Srrs PMCMASK(RES_SUPPLIER_DRAM, (1ULL << 26)), 929291494Srrs PMCMASK(RES_SUPPLIER_SPL_HIT, (1ULL << 30)), 930291494Srrs PMCMASK(RES_SNOOP_SNP_NONE, (1ULL << 31)), 931291494Srrs PMCMASK(RES_SNOOP_SNP_NO_NEEDED,(1ULL << 32)), 932291494Srrs PMCMASK(RES_SNOOP_SNP_MISS, (1ULL << 33)), 933291494Srrs PMCMASK(RES_SNOOP_HIT_NO_FWD, (1ULL << 34)), 934291494Srrs PMCMASK(RES_SNOOP_HIT_FWD, (1ULL << 35)), 935291494Srrs PMCMASK(RES_SNOOP_HITM, (1ULL << 36)), 936291494Srrs PMCMASK(RES_NON_DRAM, (1ULL << 37)), 937291494Srrs NULLMASK 938291494Srrs}; 939291494Srrs 940291494Srrs 941185363Sjkoshystatic int 942185363Sjkoshyiap_allocate_pmc(enum pmc_event pe, char *ctrspec, 943185363Sjkoshy struct pmc_op_pmcallocate *pmc_config) 944185363Sjkoshy{ 945185363Sjkoshy char *e, *p, *q; 946240164Sfabient uint64_t cachestate, evmask, rsp; 947185363Sjkoshy int count, n; 948185363Sjkoshy 949185363Sjkoshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE | 950185363Sjkoshy PMC_CAP_QUALIFIER); 951185363Sjkoshy pmc_config->pm_md.pm_iap.pm_iap_config = 0; 952185363Sjkoshy 953206089Sfabient cachestate = evmask = rsp = 0; 954185363Sjkoshy 955185363Sjkoshy /* Parse additional modifiers if present */ 956185363Sjkoshy while ((p = strsep(&ctrspec, ",")) != NULL) { 957185363Sjkoshy 958185363Sjkoshy n = 0; 959185363Sjkoshy if (KWPREFIXMATCH(p, IAP_KW_CMASK "=")) { 960185363Sjkoshy q = strchr(p, '='); 961185363Sjkoshy if (*++q == '\0') /* skip '=' */ 962185363Sjkoshy return (-1); 963185363Sjkoshy count = strtol(q, &e, 0); 964185363Sjkoshy if (e == q || *e != '\0') 965185363Sjkoshy return (-1); 966185363Sjkoshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 967185363Sjkoshy pmc_config->pm_md.pm_iap.pm_iap_config |= 968185363Sjkoshy IAP_CMASK(count); 969185363Sjkoshy } else if (KWMATCH(p, IAP_KW_EDGE)) { 970185363Sjkoshy pmc_config->pm_caps |= PMC_CAP_EDGE; 971185363Sjkoshy } else if (KWMATCH(p, IAP_KW_INV)) { 972185363Sjkoshy pmc_config->pm_caps |= PMC_CAP_INVERT; 973185363Sjkoshy } else if (KWMATCH(p, IAP_KW_OS)) { 974185363Sjkoshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 975185363Sjkoshy } else if (KWMATCH(p, IAP_KW_USR)) { 976185363Sjkoshy pmc_config->pm_caps |= PMC_CAP_USER; 977185363Sjkoshy } else if (KWMATCH(p, IAP_KW_ANYTHREAD)) { 978185363Sjkoshy pmc_config->pm_md.pm_iap.pm_iap_config |= IAP_ANY; 979193809Sjkoshy } else if (KWPREFIXMATCH(p, IAP_KW_CORE "=")) { 980185363Sjkoshy n = pmc_parse_mask(iap_core_mask, p, &evmask); 981185363Sjkoshy if (n != 1) 982185363Sjkoshy return (-1); 983193809Sjkoshy } else if (KWPREFIXMATCH(p, IAP_KW_AGENT "=")) { 984185363Sjkoshy n = pmc_parse_mask(iap_agent_mask, p, &evmask); 985185363Sjkoshy if (n != 1) 986185363Sjkoshy return (-1); 987193809Sjkoshy } else if (KWPREFIXMATCH(p, IAP_KW_PREFETCH "=")) { 988185363Sjkoshy n = pmc_parse_mask(iap_prefetch_mask, p, &evmask); 989185363Sjkoshy if (n != 1) 990185363Sjkoshy return (-1); 991193809Sjkoshy } else if (KWPREFIXMATCH(p, IAP_KW_CACHESTATE "=")) { 992185363Sjkoshy n = pmc_parse_mask(iap_cachestate_mask, p, &cachestate); 993185363Sjkoshy } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_CORE && 994193809Sjkoshy KWPREFIXMATCH(p, IAP_KW_TRANSITION "=")) { 995185363Sjkoshy n = pmc_parse_mask(iap_transition_mask, p, &evmask); 996185363Sjkoshy if (n != 1) 997185363Sjkoshy return (-1); 998185363Sjkoshy } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM || 999263446Shiren cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM_SILVERMONT || 1000185585Sjkoshy cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2 || 1001206089Sfabient cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2EXTREME) { 1002193809Sjkoshy if (KWPREFIXMATCH(p, IAP_KW_SNOOPRESPONSE "=")) { 1003185363Sjkoshy n = pmc_parse_mask(iap_snoopresponse_mask, p, 1004185363Sjkoshy &evmask); 1005193809Sjkoshy } else if (KWPREFIXMATCH(p, IAP_KW_SNOOPTYPE "=")) { 1006185363Sjkoshy n = pmc_parse_mask(iap_snooptype_mask, p, 1007185363Sjkoshy &evmask); 1008185363Sjkoshy } else 1009185363Sjkoshy return (-1); 1010206089Sfabient } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_COREI7 || 1011267062Skib cpu_info.pm_cputype == PMC_CPU_INTEL_WESTMERE || 1012267062Skib cpu_info.pm_cputype == PMC_CPU_INTEL_NEHALEM_EX || 1013267062Skib cpu_info.pm_cputype == PMC_CPU_INTEL_WESTMERE_EX) { 1014206089Sfabient if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 1015240164Sfabient n = pmc_parse_mask(iap_rsp_mask_i7_wm, p, &rsp); 1016206089Sfabient } else 1017206089Sfabient return (-1); 1018240164Sfabient } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_SANDYBRIDGE || 1019241738Ssbruno cpu_info.pm_cputype == PMC_CPU_INTEL_SANDYBRIDGE_XEON || 1020246166Ssbruno cpu_info.pm_cputype == PMC_CPU_INTEL_IVYBRIDGE || 1021246166Ssbruno cpu_info.pm_cputype == PMC_CPU_INTEL_IVYBRIDGE_XEON ) { 1022240164Sfabient if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 1023241738Ssbruno n = pmc_parse_mask(iap_rsp_mask_sb_sbx_ib, p, &rsp); 1024240164Sfabient } else 1025240164Sfabient return (-1); 1026277177Srrs } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_HASWELL || 1027277177Srrs cpu_info.pm_cputype == PMC_CPU_INTEL_HASWELL_XEON) { 1028248842Ssbruno if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 1029248842Ssbruno n = pmc_parse_mask(iap_rsp_mask_haswell, p, &rsp); 1030248842Ssbruno } else 1031248842Ssbruno return (-1); 1032291494Srrs } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_BROADWELL || 1033291494Srrs cpu_info.pm_cputype == PMC_CPU_INTEL_BROADWELL_XEON) { 1034291494Srrs /* Broadwell is defined to use same mask as haswell */ 1035291494Srrs if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 1036291494Srrs n = pmc_parse_mask(iap_rsp_mask_haswell, p, &rsp); 1037291494Srrs } else 1038291494Srrs return (-1); 1039291494Srrs 1040291494Srrs } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_SKYLAKE) { 1041291494Srrs if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 1042291494Srrs n = pmc_parse_mask(iap_rsp_mask_skylake, p, &rsp); 1043291494Srrs } else 1044291494Srrs return (-1); 1045291494Srrs 1046185363Sjkoshy } else 1047185363Sjkoshy return (-1); 1048185363Sjkoshy 1049185363Sjkoshy if (n < 0) /* Parsing failed. */ 1050185363Sjkoshy return (-1); 1051185363Sjkoshy } 1052185363Sjkoshy 1053185363Sjkoshy pmc_config->pm_md.pm_iap.pm_iap_config |= evmask; 1054185363Sjkoshy 1055185363Sjkoshy /* 1056185363Sjkoshy * If the event requires a 'cachestate' qualifier but was not 1057185363Sjkoshy * specified by the user, use a sensible default. 1058185363Sjkoshy */ 1059185363Sjkoshy switch (pe) { 1060185363Sjkoshy case PMC_EV_IAP_EVENT_28H: /* Core, Core2, Atom */ 1061185363Sjkoshy case PMC_EV_IAP_EVENT_29H: /* Core, Core2, Atom */ 1062185363Sjkoshy case PMC_EV_IAP_EVENT_2AH: /* Core, Core2, Atom */ 1063185363Sjkoshy case PMC_EV_IAP_EVENT_2BH: /* Atom, Core2 */ 1064185363Sjkoshy case PMC_EV_IAP_EVENT_2EH: /* Core, Core2, Atom */ 1065185363Sjkoshy case PMC_EV_IAP_EVENT_30H: /* Core, Core2, Atom */ 1066185363Sjkoshy case PMC_EV_IAP_EVENT_32H: /* Core */ 1067185363Sjkoshy case PMC_EV_IAP_EVENT_40H: /* Core */ 1068185363Sjkoshy case PMC_EV_IAP_EVENT_41H: /* Core */ 1069185363Sjkoshy case PMC_EV_IAP_EVENT_42H: /* Core, Core2, Atom */ 1070185363Sjkoshy if (cachestate == 0) 1071185363Sjkoshy cachestate = (0xF << 8); 1072207482Srstone break; 1073207482Srstone case PMC_EV_IAP_EVENT_77H: /* Atom */ 1074207482Srstone /* IAP_EVENT_77H only accepts a cachestate qualifier on the 1075207482Srstone * Atom processor 1076207482Srstone */ 1077207482Srstone if(cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM && cachestate == 0) 1078207482Srstone cachestate = (0xF << 8); 1079207482Srstone break; 1080185363Sjkoshy default: 1081185363Sjkoshy break; 1082185363Sjkoshy } 1083185363Sjkoshy 1084185363Sjkoshy pmc_config->pm_md.pm_iap.pm_iap_config |= cachestate; 1085206089Sfabient pmc_config->pm_md.pm_iap.pm_iap_rsp = rsp; 1086185363Sjkoshy 1087185363Sjkoshy return (0); 1088185363Sjkoshy} 1089185363Sjkoshy 1090185363Sjkoshy/* 1091206089Sfabient * Intel Uncore. 1092206089Sfabient */ 1093206089Sfabient 1094206089Sfabientstatic int 1095206089Sfabientucf_allocate_pmc(enum pmc_event pe, char *ctrspec, 1096206089Sfabient struct pmc_op_pmcallocate *pmc_config) 1097206089Sfabient{ 1098206089Sfabient (void) pe; 1099206089Sfabient (void) ctrspec; 1100206089Sfabient 1101206089Sfabient pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1102206089Sfabient pmc_config->pm_md.pm_ucf.pm_ucf_flags = 0; 1103206089Sfabient 1104206089Sfabient return (0); 1105206089Sfabient} 1106206089Sfabient 1107206089Sfabient#define UCP_KW_CMASK "cmask" 1108206089Sfabient#define UCP_KW_EDGE "edge" 1109206089Sfabient#define UCP_KW_INV "inv" 1110206089Sfabient 1111206089Sfabientstatic int 1112206089Sfabientucp_allocate_pmc(enum pmc_event pe, char *ctrspec, 1113206089Sfabient struct pmc_op_pmcallocate *pmc_config) 1114206089Sfabient{ 1115206089Sfabient char *e, *p, *q; 1116206089Sfabient int count, n; 1117206089Sfabient 1118206089Sfabient (void) pe; 1119206089Sfabient 1120206089Sfabient pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE | 1121206089Sfabient PMC_CAP_QUALIFIER); 1122206089Sfabient pmc_config->pm_md.pm_ucp.pm_ucp_config = 0; 1123206089Sfabient 1124206089Sfabient /* Parse additional modifiers if present */ 1125206089Sfabient while ((p = strsep(&ctrspec, ",")) != NULL) { 1126206089Sfabient 1127206089Sfabient n = 0; 1128206089Sfabient if (KWPREFIXMATCH(p, UCP_KW_CMASK "=")) { 1129206089Sfabient q = strchr(p, '='); 1130206089Sfabient if (*++q == '\0') /* skip '=' */ 1131206089Sfabient return (-1); 1132206089Sfabient count = strtol(q, &e, 0); 1133206089Sfabient if (e == q || *e != '\0') 1134206089Sfabient return (-1); 1135206089Sfabient pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 1136206089Sfabient pmc_config->pm_md.pm_ucp.pm_ucp_config |= 1137206089Sfabient UCP_CMASK(count); 1138206089Sfabient } else if (KWMATCH(p, UCP_KW_EDGE)) { 1139206089Sfabient pmc_config->pm_caps |= PMC_CAP_EDGE; 1140206089Sfabient } else if (KWMATCH(p, UCP_KW_INV)) { 1141206089Sfabient pmc_config->pm_caps |= PMC_CAP_INVERT; 1142206089Sfabient } else 1143206089Sfabient return (-1); 1144206089Sfabient 1145206089Sfabient if (n < 0) /* Parsing failed. */ 1146206089Sfabient return (-1); 1147206089Sfabient } 1148206089Sfabient 1149206089Sfabient return (0); 1150206089Sfabient} 1151206089Sfabient 1152206089Sfabient/* 1153147191Sjkoshy * AMD K8 PMCs. 1154147191Sjkoshy * 1155147191Sjkoshy * These are very similar to AMD K7 PMCs, but support more kinds of 1156147191Sjkoshy * events. 1157147191Sjkoshy */ 1158147191Sjkoshy 1159147191Sjkoshystatic struct pmc_event_alias k8_aliases[] = { 1160147191Sjkoshy EV_ALIAS("branches", "k8-fr-retired-taken-branches"), 1161147191Sjkoshy EV_ALIAS("branch-mispredicts", 1162147191Sjkoshy "k8-fr-retired-taken-branches-mispredicted"), 1163147191Sjkoshy EV_ALIAS("cycles", "tsc"), 1164147191Sjkoshy EV_ALIAS("dc-misses", "k8-dc-miss"), 1165147191Sjkoshy EV_ALIAS("ic-misses", "k8-ic-miss"), 1166183107Sjkoshy EV_ALIAS("instructions", "k8-fr-retired-x86-instructions"), 1167147191Sjkoshy EV_ALIAS("interrupts", "k8-fr-taken-hardware-interrupts"), 1168155998Sjkoshy EV_ALIAS("unhalted-cycles", "k8-bu-cpu-clk-unhalted"), 1169147191Sjkoshy EV_ALIAS(NULL, NULL) 1170147191Sjkoshy}; 1171147191Sjkoshy 1172147191Sjkoshy#define __K8MASK(N,V) PMCMASK(N,(1 << (V))) 1173147191Sjkoshy 1174147191Sjkoshy/* 1175147191Sjkoshy * Parsing tables 1176147191Sjkoshy */ 1177147191Sjkoshy 1178147191Sjkoshy/* fp dispatched fpu ops */ 1179147191Sjkoshystatic const struct pmc_masks k8_mask_fdfo[] = { 1180147191Sjkoshy __K8MASK(add-pipe-excluding-junk-ops, 0), 1181147191Sjkoshy __K8MASK(multiply-pipe-excluding-junk-ops, 1), 1182147191Sjkoshy __K8MASK(store-pipe-excluding-junk-ops, 2), 1183147191Sjkoshy __K8MASK(add-pipe-junk-ops, 3), 1184147191Sjkoshy __K8MASK(multiply-pipe-junk-ops, 4), 1185147191Sjkoshy __K8MASK(store-pipe-junk-ops, 5), 1186147191Sjkoshy NULLMASK 1187147191Sjkoshy}; 1188147191Sjkoshy 1189147191Sjkoshy/* ls segment register loads */ 1190147191Sjkoshystatic const struct pmc_masks k8_mask_lsrl[] = { 1191147191Sjkoshy __K8MASK(es, 0), 1192147191Sjkoshy __K8MASK(cs, 1), 1193147191Sjkoshy __K8MASK(ss, 2), 1194147191Sjkoshy __K8MASK(ds, 3), 1195147191Sjkoshy __K8MASK(fs, 4), 1196147191Sjkoshy __K8MASK(gs, 5), 1197147191Sjkoshy __K8MASK(hs, 6), 1198147191Sjkoshy NULLMASK 1199147191Sjkoshy}; 1200147191Sjkoshy 1201147191Sjkoshy/* ls locked operation */ 1202147191Sjkoshystatic const struct pmc_masks k8_mask_llo[] = { 1203147191Sjkoshy __K8MASK(locked-instructions, 0), 1204147191Sjkoshy __K8MASK(cycles-in-request, 1), 1205147191Sjkoshy __K8MASK(cycles-to-complete, 2), 1206147191Sjkoshy NULLMASK 1207147191Sjkoshy}; 1208147191Sjkoshy 1209147191Sjkoshy/* dc refill from {l2,system} and dc copyback */ 1210147191Sjkoshystatic const struct pmc_masks k8_mask_dc[] = { 1211147191Sjkoshy __K8MASK(invalid, 0), 1212147191Sjkoshy __K8MASK(shared, 1), 1213147191Sjkoshy __K8MASK(exclusive, 2), 1214147191Sjkoshy __K8MASK(owner, 3), 1215147191Sjkoshy __K8MASK(modified, 4), 1216147191Sjkoshy NULLMASK 1217147191Sjkoshy}; 1218147191Sjkoshy 1219147191Sjkoshy/* dc one bit ecc error */ 1220147191Sjkoshystatic const struct pmc_masks k8_mask_dobee[] = { 1221147191Sjkoshy __K8MASK(scrubber, 0), 1222147191Sjkoshy __K8MASK(piggyback, 1), 1223147191Sjkoshy NULLMASK 1224147191Sjkoshy}; 1225147191Sjkoshy 1226147191Sjkoshy/* dc dispatched prefetch instructions */ 1227147191Sjkoshystatic const struct pmc_masks k8_mask_ddpi[] = { 1228147191Sjkoshy __K8MASK(load, 0), 1229147191Sjkoshy __K8MASK(store, 1), 1230147191Sjkoshy __K8MASK(nta, 2), 1231147191Sjkoshy NULLMASK 1232147191Sjkoshy}; 1233147191Sjkoshy 1234147191Sjkoshy/* dc dcache accesses by locks */ 1235147191Sjkoshystatic const struct pmc_masks k8_mask_dabl[] = { 1236147191Sjkoshy __K8MASK(accesses, 0), 1237147191Sjkoshy __K8MASK(misses, 1), 1238147191Sjkoshy NULLMASK 1239147191Sjkoshy}; 1240147191Sjkoshy 1241147191Sjkoshy/* bu internal l2 request */ 1242147191Sjkoshystatic const struct pmc_masks k8_mask_bilr[] = { 1243147191Sjkoshy __K8MASK(ic-fill, 0), 1244147191Sjkoshy __K8MASK(dc-fill, 1), 1245147191Sjkoshy __K8MASK(tlb-reload, 2), 1246147191Sjkoshy __K8MASK(tag-snoop, 3), 1247147191Sjkoshy __K8MASK(cancelled, 4), 1248147191Sjkoshy NULLMASK 1249147191Sjkoshy}; 1250147191Sjkoshy 1251147191Sjkoshy/* bu fill request l2 miss */ 1252147191Sjkoshystatic const struct pmc_masks k8_mask_bfrlm[] = { 1253147191Sjkoshy __K8MASK(ic-fill, 0), 1254147191Sjkoshy __K8MASK(dc-fill, 1), 1255147191Sjkoshy __K8MASK(tlb-reload, 2), 1256147191Sjkoshy NULLMASK 1257147191Sjkoshy}; 1258147191Sjkoshy 1259147191Sjkoshy/* bu fill into l2 */ 1260147191Sjkoshystatic const struct pmc_masks k8_mask_bfil[] = { 1261147191Sjkoshy __K8MASK(dirty-l2-victim, 0), 1262147191Sjkoshy __K8MASK(victim-from-l2, 1), 1263147191Sjkoshy NULLMASK 1264147191Sjkoshy}; 1265147191Sjkoshy 1266147191Sjkoshy/* fr retired fpu instructions */ 1267147191Sjkoshystatic const struct pmc_masks k8_mask_frfi[] = { 1268147191Sjkoshy __K8MASK(x87, 0), 1269147191Sjkoshy __K8MASK(mmx-3dnow, 1), 1270147191Sjkoshy __K8MASK(packed-sse-sse2, 2), 1271147191Sjkoshy __K8MASK(scalar-sse-sse2, 3), 1272147191Sjkoshy NULLMASK 1273147191Sjkoshy}; 1274147191Sjkoshy 1275147191Sjkoshy/* fr retired fastpath double op instructions */ 1276147191Sjkoshystatic const struct pmc_masks k8_mask_frfdoi[] = { 1277147191Sjkoshy __K8MASK(low-op-pos-0, 0), 1278147191Sjkoshy __K8MASK(low-op-pos-1, 1), 1279147191Sjkoshy __K8MASK(low-op-pos-2, 2), 1280147191Sjkoshy NULLMASK 1281147191Sjkoshy}; 1282147191Sjkoshy 1283147191Sjkoshy/* fr fpu exceptions */ 1284147191Sjkoshystatic const struct pmc_masks k8_mask_ffe[] = { 1285147191Sjkoshy __K8MASK(x87-reclass-microfaults, 0), 1286147191Sjkoshy __K8MASK(sse-retype-microfaults, 1), 1287147191Sjkoshy __K8MASK(sse-reclass-microfaults, 2), 1288147191Sjkoshy __K8MASK(sse-and-x87-microtraps, 3), 1289147191Sjkoshy NULLMASK 1290147191Sjkoshy}; 1291147191Sjkoshy 1292147191Sjkoshy/* nb memory controller page access event */ 1293147191Sjkoshystatic const struct pmc_masks k8_mask_nmcpae[] = { 1294147191Sjkoshy __K8MASK(page-hit, 0), 1295147191Sjkoshy __K8MASK(page-miss, 1), 1296147191Sjkoshy __K8MASK(page-conflict, 2), 1297147191Sjkoshy NULLMASK 1298147191Sjkoshy}; 1299147191Sjkoshy 1300147191Sjkoshy/* nb memory controller turnaround */ 1301147191Sjkoshystatic const struct pmc_masks k8_mask_nmct[] = { 1302147191Sjkoshy __K8MASK(dimm-turnaround, 0), 1303147191Sjkoshy __K8MASK(read-to-write-turnaround, 1), 1304147191Sjkoshy __K8MASK(write-to-read-turnaround, 2), 1305147191Sjkoshy NULLMASK 1306147191Sjkoshy}; 1307147191Sjkoshy 1308147191Sjkoshy/* nb memory controller bypass saturation */ 1309147191Sjkoshystatic const struct pmc_masks k8_mask_nmcbs[] = { 1310147191Sjkoshy __K8MASK(memory-controller-hi-pri-bypass, 0), 1311147191Sjkoshy __K8MASK(memory-controller-lo-pri-bypass, 1), 1312147191Sjkoshy __K8MASK(dram-controller-interface-bypass, 2), 1313147191Sjkoshy __K8MASK(dram-controller-queue-bypass, 3), 1314147191Sjkoshy NULLMASK 1315147191Sjkoshy}; 1316147191Sjkoshy 1317147191Sjkoshy/* nb sized commands */ 1318147191Sjkoshystatic const struct pmc_masks k8_mask_nsc[] = { 1319147191Sjkoshy __K8MASK(nonpostwrszbyte, 0), 1320147191Sjkoshy __K8MASK(nonpostwrszdword, 1), 1321147191Sjkoshy __K8MASK(postwrszbyte, 2), 1322147191Sjkoshy __K8MASK(postwrszdword, 3), 1323147191Sjkoshy __K8MASK(rdszbyte, 4), 1324147191Sjkoshy __K8MASK(rdszdword, 5), 1325147191Sjkoshy __K8MASK(rdmodwr, 6), 1326147191Sjkoshy NULLMASK 1327147191Sjkoshy}; 1328147191Sjkoshy 1329147191Sjkoshy/* nb probe result */ 1330147191Sjkoshystatic const struct pmc_masks k8_mask_npr[] = { 1331147191Sjkoshy __K8MASK(probe-miss, 0), 1332147191Sjkoshy __K8MASK(probe-hit, 1), 1333147191Sjkoshy __K8MASK(probe-hit-dirty-no-memory-cancel, 2), 1334147191Sjkoshy __K8MASK(probe-hit-dirty-with-memory-cancel, 3), 1335147191Sjkoshy NULLMASK 1336147191Sjkoshy}; 1337147191Sjkoshy 1338147191Sjkoshy/* nb hypertransport bus bandwidth */ 1339147191Sjkoshystatic const struct pmc_masks k8_mask_nhbb[] = { /* HT bus bandwidth */ 1340147191Sjkoshy __K8MASK(command, 0), 1341183107Sjkoshy __K8MASK(data, 1), 1342147191Sjkoshy __K8MASK(buffer-release, 2), 1343147191Sjkoshy __K8MASK(nop, 3), 1344147191Sjkoshy NULLMASK 1345147191Sjkoshy}; 1346147191Sjkoshy 1347147191Sjkoshy#undef __K8MASK 1348147191Sjkoshy 1349147191Sjkoshy#define K8_KW_COUNT "count" 1350147191Sjkoshy#define K8_KW_EDGE "edge" 1351147191Sjkoshy#define K8_KW_INV "inv" 1352147191Sjkoshy#define K8_KW_MASK "mask" 1353147191Sjkoshy#define K8_KW_OS "os" 1354147191Sjkoshy#define K8_KW_USR "usr" 1355147191Sjkoshy 1356147191Sjkoshystatic int 1357147191Sjkoshyk8_allocate_pmc(enum pmc_event pe, char *ctrspec, 1358147191Sjkoshy struct pmc_op_pmcallocate *pmc_config) 1359147191Sjkoshy{ 1360183107Sjkoshy char *e, *p, *q; 1361183107Sjkoshy int n; 1362240164Sfabient uint32_t count; 1363240164Sfabient uint64_t evmask; 1364147191Sjkoshy const struct pmc_masks *pm, *pmask; 1365147191Sjkoshy 1366183725Sjkoshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1367147191Sjkoshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 1368147191Sjkoshy 1369147191Sjkoshy pmask = NULL; 1370147191Sjkoshy evmask = 0; 1371147191Sjkoshy 1372147191Sjkoshy#define __K8SETMASK(M) pmask = k8_mask_##M 1373147191Sjkoshy 1374147191Sjkoshy /* setup parsing tables */ 1375147191Sjkoshy switch (pe) { 1376147191Sjkoshy case PMC_EV_K8_FP_DISPATCHED_FPU_OPS: 1377147191Sjkoshy __K8SETMASK(fdfo); 1378147191Sjkoshy break; 1379147191Sjkoshy case PMC_EV_K8_LS_SEGMENT_REGISTER_LOAD: 1380147191Sjkoshy __K8SETMASK(lsrl); 1381147191Sjkoshy break; 1382147191Sjkoshy case PMC_EV_K8_LS_LOCKED_OPERATION: 1383147191Sjkoshy __K8SETMASK(llo); 1384147191Sjkoshy break; 1385147191Sjkoshy case PMC_EV_K8_DC_REFILL_FROM_L2: 1386147191Sjkoshy case PMC_EV_K8_DC_REFILL_FROM_SYSTEM: 1387147191Sjkoshy case PMC_EV_K8_DC_COPYBACK: 1388147191Sjkoshy __K8SETMASK(dc); 1389147191Sjkoshy break; 1390147191Sjkoshy case PMC_EV_K8_DC_ONE_BIT_ECC_ERROR: 1391147191Sjkoshy __K8SETMASK(dobee); 1392147191Sjkoshy break; 1393147191Sjkoshy case PMC_EV_K8_DC_DISPATCHED_PREFETCH_INSTRUCTIONS: 1394147191Sjkoshy __K8SETMASK(ddpi); 1395147191Sjkoshy break; 1396147191Sjkoshy case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS: 1397147191Sjkoshy __K8SETMASK(dabl); 1398147191Sjkoshy break; 1399147191Sjkoshy case PMC_EV_K8_BU_INTERNAL_L2_REQUEST: 1400147191Sjkoshy __K8SETMASK(bilr); 1401147191Sjkoshy break; 1402147191Sjkoshy case PMC_EV_K8_BU_FILL_REQUEST_L2_MISS: 1403147191Sjkoshy __K8SETMASK(bfrlm); 1404147191Sjkoshy break; 1405147191Sjkoshy case PMC_EV_K8_BU_FILL_INTO_L2: 1406147191Sjkoshy __K8SETMASK(bfil); 1407147191Sjkoshy break; 1408147191Sjkoshy case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS: 1409147191Sjkoshy __K8SETMASK(frfi); 1410147191Sjkoshy break; 1411147191Sjkoshy case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS: 1412147191Sjkoshy __K8SETMASK(frfdoi); 1413147191Sjkoshy break; 1414147191Sjkoshy case PMC_EV_K8_FR_FPU_EXCEPTIONS: 1415147191Sjkoshy __K8SETMASK(ffe); 1416147191Sjkoshy break; 1417147191Sjkoshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_PAGE_ACCESS_EVENT: 1418147191Sjkoshy __K8SETMASK(nmcpae); 1419147191Sjkoshy break; 1420147191Sjkoshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_TURNAROUND: 1421147191Sjkoshy __K8SETMASK(nmct); 1422147191Sjkoshy break; 1423147191Sjkoshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_BYPASS_SATURATION: 1424147191Sjkoshy __K8SETMASK(nmcbs); 1425147191Sjkoshy break; 1426147191Sjkoshy case PMC_EV_K8_NB_SIZED_COMMANDS: 1427147191Sjkoshy __K8SETMASK(nsc); 1428147191Sjkoshy break; 1429147191Sjkoshy case PMC_EV_K8_NB_PROBE_RESULT: 1430147191Sjkoshy __K8SETMASK(npr); 1431147191Sjkoshy break; 1432147191Sjkoshy case PMC_EV_K8_NB_HT_BUS0_BANDWIDTH: 1433147191Sjkoshy case PMC_EV_K8_NB_HT_BUS1_BANDWIDTH: 1434147191Sjkoshy case PMC_EV_K8_NB_HT_BUS2_BANDWIDTH: 1435147191Sjkoshy __K8SETMASK(nhbb); 1436147191Sjkoshy break; 1437147191Sjkoshy 1438147191Sjkoshy default: 1439147191Sjkoshy break; /* no options defined */ 1440147191Sjkoshy } 1441147191Sjkoshy 1442147191Sjkoshy while ((p = strsep(&ctrspec, ",")) != NULL) { 1443147191Sjkoshy if (KWPREFIXMATCH(p, K8_KW_COUNT "=")) { 1444147191Sjkoshy q = strchr(p, '='); 1445147191Sjkoshy if (*++q == '\0') /* skip '=' */ 1446174406Sjkoshy return (-1); 1447147191Sjkoshy 1448147191Sjkoshy count = strtol(q, &e, 0); 1449147191Sjkoshy if (e == q || *e != '\0') 1450174406Sjkoshy return (-1); 1451147191Sjkoshy 1452147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 1453147191Sjkoshy pmc_config->pm_md.pm_amd.pm_amd_config |= 1454147191Sjkoshy AMD_PMC_TO_COUNTER(count); 1455147191Sjkoshy 1456147191Sjkoshy } else if (KWMATCH(p, K8_KW_EDGE)) { 1457147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_EDGE; 1458147191Sjkoshy } else if (KWMATCH(p, K8_KW_INV)) { 1459147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_INVERT; 1460147191Sjkoshy } else if (KWPREFIXMATCH(p, K8_KW_MASK "=")) { 1461147191Sjkoshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 1462174406Sjkoshy return (-1); 1463147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1464147191Sjkoshy } else if (KWMATCH(p, K8_KW_OS)) { 1465147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 1466147191Sjkoshy } else if (KWMATCH(p, K8_KW_USR)) { 1467147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_USER; 1468147191Sjkoshy } else 1469174406Sjkoshy return (-1); 1470147191Sjkoshy } 1471147191Sjkoshy 1472147191Sjkoshy /* other post processing */ 1473147191Sjkoshy switch (pe) { 1474147191Sjkoshy case PMC_EV_K8_FP_DISPATCHED_FPU_OPS: 1475147191Sjkoshy case PMC_EV_K8_FP_CYCLES_WITH_NO_FPU_OPS_RETIRED: 1476147191Sjkoshy case PMC_EV_K8_FP_DISPATCHED_FPU_FAST_FLAG_OPS: 1477147191Sjkoshy case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS: 1478147191Sjkoshy case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS: 1479147191Sjkoshy case PMC_EV_K8_FR_FPU_EXCEPTIONS: 1480147191Sjkoshy /* XXX only available in rev B and later */ 1481147191Sjkoshy break; 1482147191Sjkoshy case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS: 1483147191Sjkoshy /* XXX only available in rev C and later */ 1484147191Sjkoshy break; 1485147191Sjkoshy case PMC_EV_K8_LS_LOCKED_OPERATION: 1486147191Sjkoshy /* XXX CPU Rev A,B evmask is to be zero */ 1487147191Sjkoshy if (evmask & (evmask - 1)) /* > 1 bit set */ 1488174406Sjkoshy return (-1); 1489147191Sjkoshy if (evmask == 0) { 1490147191Sjkoshy evmask = 0x01; /* Rev C and later: #instrs */ 1491147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1492147191Sjkoshy } 1493147191Sjkoshy break; 1494147191Sjkoshy default: 1495147191Sjkoshy if (evmask == 0 && pmask != NULL) { 1496147191Sjkoshy for (pm = pmask; pm->pm_name; pm++) 1497147191Sjkoshy evmask |= pm->pm_value; 1498147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1499147191Sjkoshy } 1500147191Sjkoshy } 1501147191Sjkoshy 1502147191Sjkoshy if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) 1503147191Sjkoshy pmc_config->pm_md.pm_amd.pm_amd_config = 1504147191Sjkoshy AMD_PMC_TO_UNITMASK(evmask); 1505147191Sjkoshy 1506174406Sjkoshy return (0); 1507147191Sjkoshy} 1508147191Sjkoshy 1509147191Sjkoshy#endif 1510147191Sjkoshy 1511147759Sjkoshy#if defined(__amd64__) || defined(__i386__) 1512147191Sjkoshy 1513147191Sjkoshy/* 1514145256Sjkoshy * Intel P4 PMCs 1515145256Sjkoshy */ 1516145256Sjkoshy 1517145256Sjkoshystatic struct pmc_event_alias p4_aliases[] = { 1518145351Sjkoshy EV_ALIAS("branches", "p4-branch-retired,mask=mmtp+mmtm"), 1519145351Sjkoshy EV_ALIAS("branch-mispredicts", "p4-mispred-branch-retired"), 1520145351Sjkoshy EV_ALIAS("cycles", "tsc"), 1521145351Sjkoshy EV_ALIAS("instructions", 1522145351Sjkoshy "p4-instr-retired,mask=nbogusntag+nbogustag"), 1523155998Sjkoshy EV_ALIAS("unhalted-cycles", "p4-global-power-events"), 1524145256Sjkoshy EV_ALIAS(NULL, NULL) 1525145256Sjkoshy}; 1526145256Sjkoshy 1527145256Sjkoshy#define P4_KW_ACTIVE "active" 1528145256Sjkoshy#define P4_KW_ACTIVE_ANY "any" 1529145256Sjkoshy#define P4_KW_ACTIVE_BOTH "both" 1530145256Sjkoshy#define P4_KW_ACTIVE_NONE "none" 1531145256Sjkoshy#define P4_KW_ACTIVE_SINGLE "single" 1532145256Sjkoshy#define P4_KW_BUSREQTYPE "busreqtype" 1533145256Sjkoshy#define P4_KW_CASCADE "cascade" 1534145256Sjkoshy#define P4_KW_EDGE "edge" 1535145256Sjkoshy#define P4_KW_INV "complement" 1536145256Sjkoshy#define P4_KW_OS "os" 1537145256Sjkoshy#define P4_KW_MASK "mask" 1538145256Sjkoshy#define P4_KW_PRECISE "precise" 1539145256Sjkoshy#define P4_KW_TAG "tag" 1540145256Sjkoshy#define P4_KW_THRESHOLD "threshold" 1541145256Sjkoshy#define P4_KW_USR "usr" 1542145256Sjkoshy 1543145256Sjkoshy#define __P4MASK(N,V) PMCMASK(N, (1 << (V))) 1544145256Sjkoshy 1545145256Sjkoshystatic const struct pmc_masks p4_mask_tcdm[] = { /* tc deliver mode */ 1546145256Sjkoshy __P4MASK(dd, 0), 1547145256Sjkoshy __P4MASK(db, 1), 1548145256Sjkoshy __P4MASK(di, 2), 1549145256Sjkoshy __P4MASK(bd, 3), 1550145256Sjkoshy __P4MASK(bb, 4), 1551145256Sjkoshy __P4MASK(bi, 5), 1552145256Sjkoshy __P4MASK(id, 6), 1553145256Sjkoshy __P4MASK(ib, 7), 1554145256Sjkoshy NULLMASK 1555145256Sjkoshy}; 1556145256Sjkoshy 1557145256Sjkoshystatic const struct pmc_masks p4_mask_bfr[] = { /* bpu fetch request */ 1558145256Sjkoshy __P4MASK(tcmiss, 0), 1559145256Sjkoshy NULLMASK, 1560145256Sjkoshy}; 1561145256Sjkoshy 1562145256Sjkoshystatic const struct pmc_masks p4_mask_ir[] = { /* itlb reference */ 1563145256Sjkoshy __P4MASK(hit, 0), 1564145256Sjkoshy __P4MASK(miss, 1), 1565145256Sjkoshy __P4MASK(hit-uc, 2), 1566145256Sjkoshy NULLMASK 1567145256Sjkoshy}; 1568145256Sjkoshy 1569145256Sjkoshystatic const struct pmc_masks p4_mask_memcan[] = { /* memory cancel */ 1570145256Sjkoshy __P4MASK(st-rb-full, 2), 1571145256Sjkoshy __P4MASK(64k-conf, 3), 1572145256Sjkoshy NULLMASK 1573145256Sjkoshy}; 1574145256Sjkoshy 1575145256Sjkoshystatic const struct pmc_masks p4_mask_memcomp[] = { /* memory complete */ 1576145256Sjkoshy __P4MASK(lsc, 0), 1577145256Sjkoshy __P4MASK(ssc, 1), 1578145256Sjkoshy NULLMASK 1579145256Sjkoshy}; 1580145256Sjkoshy 1581145256Sjkoshystatic const struct pmc_masks p4_mask_lpr[] = { /* load port replay */ 1582145256Sjkoshy __P4MASK(split-ld, 1), 1583145256Sjkoshy NULLMASK 1584145256Sjkoshy}; 1585145256Sjkoshy 1586145256Sjkoshystatic const struct pmc_masks p4_mask_spr[] = { /* store port replay */ 1587145256Sjkoshy __P4MASK(split-st, 1), 1588145256Sjkoshy NULLMASK 1589145256Sjkoshy}; 1590145256Sjkoshy 1591145256Sjkoshystatic const struct pmc_masks p4_mask_mlr[] = { /* mob load replay */ 1592145256Sjkoshy __P4MASK(no-sta, 1), 1593145256Sjkoshy __P4MASK(no-std, 3), 1594145256Sjkoshy __P4MASK(partial-data, 4), 1595145256Sjkoshy __P4MASK(unalgn-addr, 5), 1596145256Sjkoshy NULLMASK 1597145256Sjkoshy}; 1598145256Sjkoshy 1599145256Sjkoshystatic const struct pmc_masks p4_mask_pwt[] = { /* page walk type */ 1600145256Sjkoshy __P4MASK(dtmiss, 0), 1601145256Sjkoshy __P4MASK(itmiss, 1), 1602145256Sjkoshy NULLMASK 1603145256Sjkoshy}; 1604145256Sjkoshy 1605145256Sjkoshystatic const struct pmc_masks p4_mask_bcr[] = { /* bsq cache reference */ 1606145256Sjkoshy __P4MASK(rd-2ndl-hits, 0), 1607145256Sjkoshy __P4MASK(rd-2ndl-hite, 1), 1608145256Sjkoshy __P4MASK(rd-2ndl-hitm, 2), 1609145256Sjkoshy __P4MASK(rd-3rdl-hits, 3), 1610145256Sjkoshy __P4MASK(rd-3rdl-hite, 4), 1611145256Sjkoshy __P4MASK(rd-3rdl-hitm, 5), 1612145256Sjkoshy __P4MASK(rd-2ndl-miss, 8), 1613145256Sjkoshy __P4MASK(rd-3rdl-miss, 9), 1614145256Sjkoshy __P4MASK(wr-2ndl-miss, 10), 1615145256Sjkoshy NULLMASK 1616145256Sjkoshy}; 1617145256Sjkoshy 1618145256Sjkoshystatic const struct pmc_masks p4_mask_ia[] = { /* ioq allocation */ 1619145256Sjkoshy __P4MASK(all-read, 5), 1620145256Sjkoshy __P4MASK(all-write, 6), 1621145256Sjkoshy __P4MASK(mem-uc, 7), 1622145256Sjkoshy __P4MASK(mem-wc, 8), 1623145256Sjkoshy __P4MASK(mem-wt, 9), 1624145256Sjkoshy __P4MASK(mem-wp, 10), 1625145256Sjkoshy __P4MASK(mem-wb, 11), 1626145256Sjkoshy __P4MASK(own, 13), 1627145256Sjkoshy __P4MASK(other, 14), 1628145256Sjkoshy __P4MASK(prefetch, 15), 1629145256Sjkoshy NULLMASK 1630145256Sjkoshy}; 1631145256Sjkoshy 1632145256Sjkoshystatic const struct pmc_masks p4_mask_iae[] = { /* ioq active entries */ 1633145256Sjkoshy __P4MASK(all-read, 5), 1634145256Sjkoshy __P4MASK(all-write, 6), 1635145256Sjkoshy __P4MASK(mem-uc, 7), 1636145256Sjkoshy __P4MASK(mem-wc, 8), 1637145256Sjkoshy __P4MASK(mem-wt, 9), 1638145256Sjkoshy __P4MASK(mem-wp, 10), 1639145256Sjkoshy __P4MASK(mem-wb, 11), 1640145256Sjkoshy __P4MASK(own, 13), 1641145256Sjkoshy __P4MASK(other, 14), 1642145256Sjkoshy __P4MASK(prefetch, 15), 1643145256Sjkoshy NULLMASK 1644145256Sjkoshy}; 1645145256Sjkoshy 1646145256Sjkoshystatic const struct pmc_masks p4_mask_fda[] = { /* fsb data activity */ 1647145256Sjkoshy __P4MASK(drdy-drv, 0), 1648145256Sjkoshy __P4MASK(drdy-own, 1), 1649145256Sjkoshy __P4MASK(drdy-other, 2), 1650145256Sjkoshy __P4MASK(dbsy-drv, 3), 1651145256Sjkoshy __P4MASK(dbsy-own, 4), 1652145256Sjkoshy __P4MASK(dbsy-other, 5), 1653145256Sjkoshy NULLMASK 1654145256Sjkoshy}; 1655145256Sjkoshy 1656145256Sjkoshystatic const struct pmc_masks p4_mask_ba[] = { /* bsq allocation */ 1657145256Sjkoshy __P4MASK(req-type0, 0), 1658145256Sjkoshy __P4MASK(req-type1, 1), 1659145256Sjkoshy __P4MASK(req-len0, 2), 1660145256Sjkoshy __P4MASK(req-len1, 3), 1661145256Sjkoshy __P4MASK(req-io-type, 5), 1662145256Sjkoshy __P4MASK(req-lock-type, 6), 1663145256Sjkoshy __P4MASK(req-cache-type, 7), 1664145256Sjkoshy __P4MASK(req-split-type, 8), 1665145256Sjkoshy __P4MASK(req-dem-type, 9), 1666145256Sjkoshy __P4MASK(req-ord-type, 10), 1667145256Sjkoshy __P4MASK(mem-type0, 11), 1668145256Sjkoshy __P4MASK(mem-type1, 12), 1669145256Sjkoshy __P4MASK(mem-type2, 13), 1670145256Sjkoshy NULLMASK 1671145256Sjkoshy}; 1672145256Sjkoshy 1673145256Sjkoshystatic const struct pmc_masks p4_mask_sia[] = { /* sse input assist */ 1674145256Sjkoshy __P4MASK(all, 15), 1675145256Sjkoshy NULLMASK 1676145256Sjkoshy}; 1677145256Sjkoshy 1678145256Sjkoshystatic const struct pmc_masks p4_mask_psu[] = { /* packed sp uop */ 1679145256Sjkoshy __P4MASK(all, 15), 1680145256Sjkoshy NULLMASK 1681145256Sjkoshy}; 1682145256Sjkoshy 1683145256Sjkoshystatic const struct pmc_masks p4_mask_pdu[] = { /* packed dp uop */ 1684145256Sjkoshy __P4MASK(all, 15), 1685145256Sjkoshy NULLMASK 1686145256Sjkoshy}; 1687145256Sjkoshy 1688145256Sjkoshystatic const struct pmc_masks p4_mask_ssu[] = { /* scalar sp uop */ 1689145256Sjkoshy __P4MASK(all, 15), 1690145256Sjkoshy NULLMASK 1691145256Sjkoshy}; 1692145256Sjkoshy 1693145256Sjkoshystatic const struct pmc_masks p4_mask_sdu[] = { /* scalar dp uop */ 1694145256Sjkoshy __P4MASK(all, 15), 1695145256Sjkoshy NULLMASK 1696145256Sjkoshy}; 1697145256Sjkoshy 1698145256Sjkoshystatic const struct pmc_masks p4_mask_64bmu[] = { /* 64 bit mmx uop */ 1699145256Sjkoshy __P4MASK(all, 15), 1700145256Sjkoshy NULLMASK 1701145256Sjkoshy}; 1702145256Sjkoshy 1703145256Sjkoshystatic const struct pmc_masks p4_mask_128bmu[] = { /* 128 bit mmx uop */ 1704145256Sjkoshy __P4MASK(all, 15), 1705145256Sjkoshy NULLMASK 1706145256Sjkoshy}; 1707145256Sjkoshy 1708145256Sjkoshystatic const struct pmc_masks p4_mask_xfu[] = { /* X87 fp uop */ 1709145256Sjkoshy __P4MASK(all, 15), 1710145256Sjkoshy NULLMASK 1711145256Sjkoshy}; 1712145256Sjkoshy 1713145256Sjkoshystatic const struct pmc_masks p4_mask_xsmu[] = { /* x87 simd moves uop */ 1714145256Sjkoshy __P4MASK(allp0, 3), 1715145256Sjkoshy __P4MASK(allp2, 4), 1716145256Sjkoshy NULLMASK 1717145256Sjkoshy}; 1718145256Sjkoshy 1719145256Sjkoshystatic const struct pmc_masks p4_mask_gpe[] = { /* global power events */ 1720145256Sjkoshy __P4MASK(running, 0), 1721145256Sjkoshy NULLMASK 1722145256Sjkoshy}; 1723145256Sjkoshy 1724145256Sjkoshystatic const struct pmc_masks p4_mask_tmx[] = { /* TC ms xfer */ 1725145256Sjkoshy __P4MASK(cisc, 0), 1726145256Sjkoshy NULLMASK 1727145256Sjkoshy}; 1728145256Sjkoshy 1729145256Sjkoshystatic const struct pmc_masks p4_mask_uqw[] = { /* uop queue writes */ 1730145256Sjkoshy __P4MASK(from-tc-build, 0), 1731145256Sjkoshy __P4MASK(from-tc-deliver, 1), 1732145256Sjkoshy __P4MASK(from-rom, 2), 1733145256Sjkoshy NULLMASK 1734145256Sjkoshy}; 1735145256Sjkoshy 1736145351Sjkoshystatic const struct pmc_masks p4_mask_rmbt[] = { 1737145351Sjkoshy /* retired mispred branch type */ 1738145256Sjkoshy __P4MASK(conditional, 1), 1739145256Sjkoshy __P4MASK(call, 2), 1740145256Sjkoshy __P4MASK(return, 3), 1741145256Sjkoshy __P4MASK(indirect, 4), 1742145256Sjkoshy NULLMASK 1743145256Sjkoshy}; 1744145256Sjkoshy 1745145256Sjkoshystatic const struct pmc_masks p4_mask_rbt[] = { /* retired branch type */ 1746145256Sjkoshy __P4MASK(conditional, 1), 1747145256Sjkoshy __P4MASK(call, 2), 1748145256Sjkoshy __P4MASK(retired, 3), 1749145256Sjkoshy __P4MASK(indirect, 4), 1750145256Sjkoshy NULLMASK 1751145256Sjkoshy}; 1752145256Sjkoshy 1753145256Sjkoshystatic const struct pmc_masks p4_mask_rs[] = { /* resource stall */ 1754145256Sjkoshy __P4MASK(sbfull, 5), 1755145256Sjkoshy NULLMASK 1756145256Sjkoshy}; 1757145256Sjkoshy 1758145256Sjkoshystatic const struct pmc_masks p4_mask_wb[] = { /* WC buffer */ 1759145256Sjkoshy __P4MASK(wcb-evicts, 0), 1760145256Sjkoshy __P4MASK(wcb-full-evict, 1), 1761145256Sjkoshy NULLMASK 1762145256Sjkoshy}; 1763145256Sjkoshy 1764145256Sjkoshystatic const struct pmc_masks p4_mask_fee[] = { /* front end event */ 1765145256Sjkoshy __P4MASK(nbogus, 0), 1766145256Sjkoshy __P4MASK(bogus, 1), 1767145256Sjkoshy NULLMASK 1768145256Sjkoshy}; 1769145256Sjkoshy 1770145256Sjkoshystatic const struct pmc_masks p4_mask_ee[] = { /* execution event */ 1771145256Sjkoshy __P4MASK(nbogus0, 0), 1772145256Sjkoshy __P4MASK(nbogus1, 1), 1773145256Sjkoshy __P4MASK(nbogus2, 2), 1774145256Sjkoshy __P4MASK(nbogus3, 3), 1775145256Sjkoshy __P4MASK(bogus0, 4), 1776145256Sjkoshy __P4MASK(bogus1, 5), 1777145256Sjkoshy __P4MASK(bogus2, 6), 1778145256Sjkoshy __P4MASK(bogus3, 7), 1779145256Sjkoshy NULLMASK 1780145256Sjkoshy}; 1781145256Sjkoshy 1782145256Sjkoshystatic const struct pmc_masks p4_mask_re[] = { /* replay event */ 1783145256Sjkoshy __P4MASK(nbogus, 0), 1784145256Sjkoshy __P4MASK(bogus, 1), 1785145256Sjkoshy NULLMASK 1786145256Sjkoshy}; 1787145256Sjkoshy 1788145256Sjkoshystatic const struct pmc_masks p4_mask_insret[] = { /* instr retired */ 1789145256Sjkoshy __P4MASK(nbogusntag, 0), 1790145256Sjkoshy __P4MASK(nbogustag, 1), 1791145256Sjkoshy __P4MASK(bogusntag, 2), 1792145256Sjkoshy __P4MASK(bogustag, 3), 1793145256Sjkoshy NULLMASK 1794145256Sjkoshy}; 1795145256Sjkoshy 1796145256Sjkoshystatic const struct pmc_masks p4_mask_ur[] = { /* uops retired */ 1797145256Sjkoshy __P4MASK(nbogus, 0), 1798145256Sjkoshy __P4MASK(bogus, 1), 1799145256Sjkoshy NULLMASK 1800145256Sjkoshy}; 1801145256Sjkoshy 1802145256Sjkoshystatic const struct pmc_masks p4_mask_ut[] = { /* uop type */ 1803145256Sjkoshy __P4MASK(tagloads, 1), 1804145256Sjkoshy __P4MASK(tagstores, 2), 1805145256Sjkoshy NULLMASK 1806145256Sjkoshy}; 1807145256Sjkoshy 1808145256Sjkoshystatic const struct pmc_masks p4_mask_br[] = { /* branch retired */ 1809145256Sjkoshy __P4MASK(mmnp, 0), 1810145256Sjkoshy __P4MASK(mmnm, 1), 1811145256Sjkoshy __P4MASK(mmtp, 2), 1812145256Sjkoshy __P4MASK(mmtm, 3), 1813145256Sjkoshy NULLMASK 1814145256Sjkoshy}; 1815145256Sjkoshy 1816145256Sjkoshystatic const struct pmc_masks p4_mask_mbr[] = { /* mispred branch retired */ 1817145256Sjkoshy __P4MASK(nbogus, 0), 1818145256Sjkoshy NULLMASK 1819145256Sjkoshy}; 1820145256Sjkoshy 1821145256Sjkoshystatic const struct pmc_masks p4_mask_xa[] = { /* x87 assist */ 1822145256Sjkoshy __P4MASK(fpsu, 0), 1823145256Sjkoshy __P4MASK(fpso, 1), 1824145256Sjkoshy __P4MASK(poao, 2), 1825145256Sjkoshy __P4MASK(poau, 3), 1826145256Sjkoshy __P4MASK(prea, 4), 1827145256Sjkoshy NULLMASK 1828145256Sjkoshy}; 1829145256Sjkoshy 1830145256Sjkoshystatic const struct pmc_masks p4_mask_machclr[] = { /* machine clear */ 1831145256Sjkoshy __P4MASK(clear, 0), 1832145256Sjkoshy __P4MASK(moclear, 2), 1833145256Sjkoshy __P4MASK(smclear, 3), 1834145256Sjkoshy NULLMASK 1835145256Sjkoshy}; 1836145256Sjkoshy 1837145256Sjkoshy/* P4 event parser */ 1838145256Sjkoshystatic int 1839145256Sjkoshyp4_allocate_pmc(enum pmc_event pe, char *ctrspec, 1840145256Sjkoshy struct pmc_op_pmcallocate *pmc_config) 1841145256Sjkoshy{ 1842145256Sjkoshy 1843145256Sjkoshy char *e, *p, *q; 1844145256Sjkoshy int count, has_tag, has_busreqtype, n; 1845240164Sfabient uint32_t cccractivemask; 1846240164Sfabient uint64_t evmask; 1847145256Sjkoshy const struct pmc_masks *pm, *pmask; 1848145256Sjkoshy 1849183725Sjkoshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1850147191Sjkoshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig = 1851147191Sjkoshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 0; 1852145256Sjkoshy 1853145256Sjkoshy pmask = NULL; 1854145256Sjkoshy evmask = 0; 1855145256Sjkoshy cccractivemask = 0x3; 1856145256Sjkoshy has_tag = has_busreqtype = 0; 1857145256Sjkoshy 1858145256Sjkoshy#define __P4SETMASK(M) do { \ 1859183107Sjkoshy pmask = p4_mask_##M; \ 1860145256Sjkoshy} while (0) 1861145256Sjkoshy 1862145256Sjkoshy switch (pe) { 1863145256Sjkoshy case PMC_EV_P4_TC_DELIVER_MODE: 1864145256Sjkoshy __P4SETMASK(tcdm); 1865145256Sjkoshy break; 1866145256Sjkoshy case PMC_EV_P4_BPU_FETCH_REQUEST: 1867145256Sjkoshy __P4SETMASK(bfr); 1868145256Sjkoshy break; 1869145256Sjkoshy case PMC_EV_P4_ITLB_REFERENCE: 1870145256Sjkoshy __P4SETMASK(ir); 1871145256Sjkoshy break; 1872145256Sjkoshy case PMC_EV_P4_MEMORY_CANCEL: 1873145256Sjkoshy __P4SETMASK(memcan); 1874145256Sjkoshy break; 1875145256Sjkoshy case PMC_EV_P4_MEMORY_COMPLETE: 1876145256Sjkoshy __P4SETMASK(memcomp); 1877145256Sjkoshy break; 1878145256Sjkoshy case PMC_EV_P4_LOAD_PORT_REPLAY: 1879145256Sjkoshy __P4SETMASK(lpr); 1880145256Sjkoshy break; 1881145256Sjkoshy case PMC_EV_P4_STORE_PORT_REPLAY: 1882145256Sjkoshy __P4SETMASK(spr); 1883145256Sjkoshy break; 1884145256Sjkoshy case PMC_EV_P4_MOB_LOAD_REPLAY: 1885145256Sjkoshy __P4SETMASK(mlr); 1886145256Sjkoshy break; 1887145256Sjkoshy case PMC_EV_P4_PAGE_WALK_TYPE: 1888145256Sjkoshy __P4SETMASK(pwt); 1889145256Sjkoshy break; 1890145256Sjkoshy case PMC_EV_P4_BSQ_CACHE_REFERENCE: 1891145256Sjkoshy __P4SETMASK(bcr); 1892145256Sjkoshy break; 1893145256Sjkoshy case PMC_EV_P4_IOQ_ALLOCATION: 1894145256Sjkoshy __P4SETMASK(ia); 1895145256Sjkoshy has_busreqtype = 1; 1896145256Sjkoshy break; 1897145256Sjkoshy case PMC_EV_P4_IOQ_ACTIVE_ENTRIES: 1898145256Sjkoshy __P4SETMASK(iae); 1899145256Sjkoshy has_busreqtype = 1; 1900145256Sjkoshy break; 1901145256Sjkoshy case PMC_EV_P4_FSB_DATA_ACTIVITY: 1902145256Sjkoshy __P4SETMASK(fda); 1903145256Sjkoshy break; 1904145256Sjkoshy case PMC_EV_P4_BSQ_ALLOCATION: 1905145256Sjkoshy __P4SETMASK(ba); 1906145256Sjkoshy break; 1907145256Sjkoshy case PMC_EV_P4_SSE_INPUT_ASSIST: 1908145256Sjkoshy __P4SETMASK(sia); 1909145256Sjkoshy break; 1910145256Sjkoshy case PMC_EV_P4_PACKED_SP_UOP: 1911145256Sjkoshy __P4SETMASK(psu); 1912145256Sjkoshy break; 1913145256Sjkoshy case PMC_EV_P4_PACKED_DP_UOP: 1914145256Sjkoshy __P4SETMASK(pdu); 1915145256Sjkoshy break; 1916145256Sjkoshy case PMC_EV_P4_SCALAR_SP_UOP: 1917145256Sjkoshy __P4SETMASK(ssu); 1918145256Sjkoshy break; 1919145256Sjkoshy case PMC_EV_P4_SCALAR_DP_UOP: 1920145256Sjkoshy __P4SETMASK(sdu); 1921145256Sjkoshy break; 1922145256Sjkoshy case PMC_EV_P4_64BIT_MMX_UOP: 1923145256Sjkoshy __P4SETMASK(64bmu); 1924145256Sjkoshy break; 1925145256Sjkoshy case PMC_EV_P4_128BIT_MMX_UOP: 1926145256Sjkoshy __P4SETMASK(128bmu); 1927145256Sjkoshy break; 1928145256Sjkoshy case PMC_EV_P4_X87_FP_UOP: 1929145256Sjkoshy __P4SETMASK(xfu); 1930145256Sjkoshy break; 1931145256Sjkoshy case PMC_EV_P4_X87_SIMD_MOVES_UOP: 1932145256Sjkoshy __P4SETMASK(xsmu); 1933145256Sjkoshy break; 1934145256Sjkoshy case PMC_EV_P4_GLOBAL_POWER_EVENTS: 1935145256Sjkoshy __P4SETMASK(gpe); 1936145256Sjkoshy break; 1937145256Sjkoshy case PMC_EV_P4_TC_MS_XFER: 1938145256Sjkoshy __P4SETMASK(tmx); 1939145256Sjkoshy break; 1940145256Sjkoshy case PMC_EV_P4_UOP_QUEUE_WRITES: 1941145256Sjkoshy __P4SETMASK(uqw); 1942145256Sjkoshy break; 1943145256Sjkoshy case PMC_EV_P4_RETIRED_MISPRED_BRANCH_TYPE: 1944145256Sjkoshy __P4SETMASK(rmbt); 1945145256Sjkoshy break; 1946145256Sjkoshy case PMC_EV_P4_RETIRED_BRANCH_TYPE: 1947145256Sjkoshy __P4SETMASK(rbt); 1948145256Sjkoshy break; 1949145256Sjkoshy case PMC_EV_P4_RESOURCE_STALL: 1950145256Sjkoshy __P4SETMASK(rs); 1951145256Sjkoshy break; 1952145256Sjkoshy case PMC_EV_P4_WC_BUFFER: 1953145256Sjkoshy __P4SETMASK(wb); 1954145256Sjkoshy break; 1955145256Sjkoshy case PMC_EV_P4_BSQ_ACTIVE_ENTRIES: 1956145256Sjkoshy case PMC_EV_P4_B2B_CYCLES: 1957145256Sjkoshy case PMC_EV_P4_BNR: 1958145256Sjkoshy case PMC_EV_P4_SNOOP: 1959145256Sjkoshy case PMC_EV_P4_RESPONSE: 1960145256Sjkoshy break; 1961145256Sjkoshy case PMC_EV_P4_FRONT_END_EVENT: 1962145256Sjkoshy __P4SETMASK(fee); 1963145256Sjkoshy break; 1964145256Sjkoshy case PMC_EV_P4_EXECUTION_EVENT: 1965145256Sjkoshy __P4SETMASK(ee); 1966145256Sjkoshy break; 1967145256Sjkoshy case PMC_EV_P4_REPLAY_EVENT: 1968145256Sjkoshy __P4SETMASK(re); 1969145256Sjkoshy break; 1970145256Sjkoshy case PMC_EV_P4_INSTR_RETIRED: 1971145256Sjkoshy __P4SETMASK(insret); 1972145256Sjkoshy break; 1973145256Sjkoshy case PMC_EV_P4_UOPS_RETIRED: 1974145256Sjkoshy __P4SETMASK(ur); 1975145256Sjkoshy break; 1976145256Sjkoshy case PMC_EV_P4_UOP_TYPE: 1977145256Sjkoshy __P4SETMASK(ut); 1978145256Sjkoshy break; 1979145256Sjkoshy case PMC_EV_P4_BRANCH_RETIRED: 1980145256Sjkoshy __P4SETMASK(br); 1981145256Sjkoshy break; 1982145256Sjkoshy case PMC_EV_P4_MISPRED_BRANCH_RETIRED: 1983145256Sjkoshy __P4SETMASK(mbr); 1984145256Sjkoshy break; 1985145256Sjkoshy case PMC_EV_P4_X87_ASSIST: 1986145256Sjkoshy __P4SETMASK(xa); 1987145256Sjkoshy break; 1988145256Sjkoshy case PMC_EV_P4_MACHINE_CLEAR: 1989145256Sjkoshy __P4SETMASK(machclr); 1990145256Sjkoshy break; 1991145256Sjkoshy default: 1992174406Sjkoshy return (-1); 1993145256Sjkoshy } 1994145256Sjkoshy 1995145256Sjkoshy /* process additional flags */ 1996145256Sjkoshy while ((p = strsep(&ctrspec, ",")) != NULL) { 1997145256Sjkoshy if (KWPREFIXMATCH(p, P4_KW_ACTIVE)) { 1998145256Sjkoshy q = strchr(p, '='); 1999145256Sjkoshy if (*++q == '\0') /* skip '=' */ 2000174406Sjkoshy return (-1); 2001145256Sjkoshy 2002183725Sjkoshy if (strcasecmp(q, P4_KW_ACTIVE_NONE) == 0) 2003145256Sjkoshy cccractivemask = 0x0; 2004183725Sjkoshy else if (strcasecmp(q, P4_KW_ACTIVE_SINGLE) == 0) 2005145256Sjkoshy cccractivemask = 0x1; 2006183725Sjkoshy else if (strcasecmp(q, P4_KW_ACTIVE_BOTH) == 0) 2007145256Sjkoshy cccractivemask = 0x2; 2008183725Sjkoshy else if (strcasecmp(q, P4_KW_ACTIVE_ANY) == 0) 2009145256Sjkoshy cccractivemask = 0x3; 2010145256Sjkoshy else 2011174406Sjkoshy return (-1); 2012145256Sjkoshy 2013145256Sjkoshy } else if (KWPREFIXMATCH(p, P4_KW_BUSREQTYPE)) { 2014145256Sjkoshy if (has_busreqtype == 0) 2015174406Sjkoshy return (-1); 2016145256Sjkoshy 2017145256Sjkoshy q = strchr(p, '='); 2018145256Sjkoshy if (*++q == '\0') /* skip '=' */ 2019174406Sjkoshy return (-1); 2020145256Sjkoshy 2021145256Sjkoshy count = strtol(q, &e, 0); 2022145256Sjkoshy if (e == q || *e != '\0') 2023174406Sjkoshy return (-1); 2024145256Sjkoshy evmask = (evmask & ~0x1F) | (count & 0x1F); 2025145256Sjkoshy } else if (KWMATCH(p, P4_KW_CASCADE)) 2026145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_CASCADE; 2027145256Sjkoshy else if (KWMATCH(p, P4_KW_EDGE)) 2028145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_EDGE; 2029145256Sjkoshy else if (KWMATCH(p, P4_KW_INV)) 2030145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_INVERT; 2031145256Sjkoshy else if (KWPREFIXMATCH(p, P4_KW_MASK "=")) { 2032145256Sjkoshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 2033174406Sjkoshy return (-1); 2034145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2035145256Sjkoshy } else if (KWMATCH(p, P4_KW_OS)) 2036145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2037145256Sjkoshy else if (KWMATCH(p, P4_KW_PRECISE)) 2038145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_PRECISE; 2039145256Sjkoshy else if (KWPREFIXMATCH(p, P4_KW_TAG "=")) { 2040145256Sjkoshy if (has_tag == 0) 2041174406Sjkoshy return (-1); 2042145256Sjkoshy 2043145256Sjkoshy q = strchr(p, '='); 2044145256Sjkoshy if (*++q == '\0') /* skip '=' */ 2045174406Sjkoshy return (-1); 2046145256Sjkoshy 2047145256Sjkoshy count = strtol(q, &e, 0); 2048145256Sjkoshy if (e == q || *e != '\0') 2049174406Sjkoshy return (-1); 2050145256Sjkoshy 2051145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_TAGGING; 2052147191Sjkoshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig |= 2053145256Sjkoshy P4_ESCR_TO_TAG_VALUE(count); 2054145256Sjkoshy } else if (KWPREFIXMATCH(p, P4_KW_THRESHOLD "=")) { 2055145256Sjkoshy q = strchr(p, '='); 2056145256Sjkoshy if (*++q == '\0') /* skip '=' */ 2057174406Sjkoshy return (-1); 2058145256Sjkoshy 2059145256Sjkoshy count = strtol(q, &e, 0); 2060145256Sjkoshy if (e == q || *e != '\0') 2061174406Sjkoshy return (-1); 2062145256Sjkoshy 2063145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 2064147191Sjkoshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig &= 2065147191Sjkoshy ~P4_CCCR_THRESHOLD_MASK; 2066147191Sjkoshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |= 2067147191Sjkoshy P4_CCCR_TO_THRESHOLD(count); 2068145256Sjkoshy } else if (KWMATCH(p, P4_KW_USR)) 2069145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_USER; 2070145256Sjkoshy else 2071174406Sjkoshy return (-1); 2072145256Sjkoshy } 2073145256Sjkoshy 2074145256Sjkoshy /* other post processing */ 2075145256Sjkoshy if (pe == PMC_EV_P4_IOQ_ALLOCATION || 2076145256Sjkoshy pe == PMC_EV_P4_FSB_DATA_ACTIVITY || 2077145256Sjkoshy pe == PMC_EV_P4_BSQ_ALLOCATION) 2078145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_EDGE; 2079145256Sjkoshy 2080145256Sjkoshy /* fill in thread activity mask */ 2081147191Sjkoshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |= 2082145256Sjkoshy P4_CCCR_TO_ACTIVE_THREAD(cccractivemask); 2083145256Sjkoshy 2084145256Sjkoshy if (evmask) 2085145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2086145256Sjkoshy 2087145256Sjkoshy switch (pe) { 2088145256Sjkoshy case PMC_EV_P4_FSB_DATA_ACTIVITY: 2089145256Sjkoshy if ((evmask & 0x06) == 0x06 || 2090145256Sjkoshy (evmask & 0x18) == 0x18) 2091174406Sjkoshy return (-1); /* can't have own+other bits together */ 2092145256Sjkoshy if (evmask == 0) /* default:drdy-{drv,own}+dbsy{drv,own} */ 2093145256Sjkoshy evmask = 0x1D; 2094145256Sjkoshy break; 2095145256Sjkoshy case PMC_EV_P4_MACHINE_CLEAR: 2096145256Sjkoshy /* only one bit is allowed to be set */ 2097145256Sjkoshy if ((evmask & (evmask - 1)) != 0) 2098174406Sjkoshy return (-1); 2099145256Sjkoshy if (evmask == 0) { 2100183107Sjkoshy evmask = 0x1; /* 'CLEAR' */ 2101145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2102145256Sjkoshy } 2103145256Sjkoshy break; 2104145256Sjkoshy default: 2105145256Sjkoshy if (evmask == 0 && pmask) { 2106145256Sjkoshy for (pm = pmask; pm->pm_name; pm++) 2107145256Sjkoshy evmask |= pm->pm_value; 2108145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2109145256Sjkoshy } 2110145256Sjkoshy } 2111145256Sjkoshy 2112147191Sjkoshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 2113147191Sjkoshy P4_ESCR_TO_EVENT_MASK(evmask); 2114145256Sjkoshy 2115174406Sjkoshy return (0); 2116145256Sjkoshy} 2117145256Sjkoshy 2118147759Sjkoshy#endif 2119147759Sjkoshy 2120147759Sjkoshy#if defined(__i386__) 2121147759Sjkoshy 2122145256Sjkoshy/* 2123147191Sjkoshy * Pentium style PMCs 2124147191Sjkoshy */ 2125147191Sjkoshy 2126147191Sjkoshystatic struct pmc_event_alias p5_aliases[] = { 2127183105Sjkoshy EV_ALIAS("branches", "p5-taken-branches"), 2128183105Sjkoshy EV_ALIAS("cycles", "tsc"), 2129183105Sjkoshy EV_ALIAS("dc-misses", "p5-data-read-miss-or-write-miss"), 2130183105Sjkoshy EV_ALIAS("ic-misses", "p5-code-cache-miss"), 2131183105Sjkoshy EV_ALIAS("instructions", "p5-instructions-executed"), 2132183105Sjkoshy EV_ALIAS("interrupts", "p5-hardware-interrupts"), 2133183105Sjkoshy EV_ALIAS("unhalted-cycles", 2134183105Sjkoshy "p5-number-of-cycles-not-in-halt-state"), 2135147191Sjkoshy EV_ALIAS(NULL, NULL) 2136147191Sjkoshy}; 2137147191Sjkoshy 2138147191Sjkoshystatic int 2139147191Sjkoshyp5_allocate_pmc(enum pmc_event pe, char *ctrspec, 2140147191Sjkoshy struct pmc_op_pmcallocate *pmc_config) 2141147191Sjkoshy{ 2142174406Sjkoshy return (-1 || pe || ctrspec || pmc_config); /* shut up gcc */ 2143147191Sjkoshy} 2144147191Sjkoshy 2145147191Sjkoshy/* 2146145256Sjkoshy * Pentium Pro style PMCs. These PMCs are found in Pentium II, Pentium III, 2147145256Sjkoshy * and Pentium M CPUs. 2148145256Sjkoshy */ 2149145256Sjkoshy 2150145256Sjkoshystatic struct pmc_event_alias p6_aliases[] = { 2151145351Sjkoshy EV_ALIAS("branches", "p6-br-inst-retired"), 2152145351Sjkoshy EV_ALIAS("branch-mispredicts", "p6-br-miss-pred-retired"), 2153145351Sjkoshy EV_ALIAS("cycles", "tsc"), 2154145351Sjkoshy EV_ALIAS("dc-misses", "p6-dcu-lines-in"), 2155168612Sjkoshy EV_ALIAS("ic-misses", "p6-ifu-fetch-miss"), 2156145351Sjkoshy EV_ALIAS("instructions", "p6-inst-retired"), 2157145351Sjkoshy EV_ALIAS("interrupts", "p6-hw-int-rx"), 2158155998Sjkoshy EV_ALIAS("unhalted-cycles", "p6-cpu-clk-unhalted"), 2159145351Sjkoshy EV_ALIAS(NULL, NULL) 2160145256Sjkoshy}; 2161145256Sjkoshy 2162145256Sjkoshy#define P6_KW_CMASK "cmask" 2163145256Sjkoshy#define P6_KW_EDGE "edge" 2164145256Sjkoshy#define P6_KW_INV "inv" 2165145256Sjkoshy#define P6_KW_OS "os" 2166145256Sjkoshy#define P6_KW_UMASK "umask" 2167145256Sjkoshy#define P6_KW_USR "usr" 2168145256Sjkoshy 2169145256Sjkoshystatic struct pmc_masks p6_mask_mesi[] = { 2170145256Sjkoshy PMCMASK(m, 0x01), 2171145256Sjkoshy PMCMASK(e, 0x02), 2172145256Sjkoshy PMCMASK(s, 0x04), 2173145256Sjkoshy PMCMASK(i, 0x08), 2174145256Sjkoshy NULLMASK 2175145256Sjkoshy}; 2176145256Sjkoshy 2177145256Sjkoshystatic struct pmc_masks p6_mask_mesihw[] = { 2178145256Sjkoshy PMCMASK(m, 0x01), 2179145256Sjkoshy PMCMASK(e, 0x02), 2180145256Sjkoshy PMCMASK(s, 0x04), 2181145256Sjkoshy PMCMASK(i, 0x08), 2182145256Sjkoshy PMCMASK(nonhw, 0x00), 2183145256Sjkoshy PMCMASK(hw, 0x10), 2184145256Sjkoshy PMCMASK(both, 0x30), 2185145256Sjkoshy NULLMASK 2186145256Sjkoshy}; 2187145256Sjkoshy 2188145256Sjkoshystatic struct pmc_masks p6_mask_hw[] = { 2189145256Sjkoshy PMCMASK(nonhw, 0x00), 2190145256Sjkoshy PMCMASK(hw, 0x10), 2191145256Sjkoshy PMCMASK(both, 0x30), 2192145256Sjkoshy NULLMASK 2193145256Sjkoshy}; 2194145256Sjkoshy 2195145256Sjkoshystatic struct pmc_masks p6_mask_any[] = { 2196145256Sjkoshy PMCMASK(self, 0x00), 2197145256Sjkoshy PMCMASK(any, 0x20), 2198145256Sjkoshy NULLMASK 2199145256Sjkoshy}; 2200145256Sjkoshy 2201145256Sjkoshystatic struct pmc_masks p6_mask_ekp[] = { 2202145256Sjkoshy PMCMASK(nta, 0x00), 2203145256Sjkoshy PMCMASK(t1, 0x01), 2204145256Sjkoshy PMCMASK(t2, 0x02), 2205145256Sjkoshy PMCMASK(wos, 0x03), 2206145256Sjkoshy NULLMASK 2207145256Sjkoshy}; 2208145256Sjkoshy 2209145256Sjkoshystatic struct pmc_masks p6_mask_pps[] = { 2210145256Sjkoshy PMCMASK(packed-and-scalar, 0x00), 2211145256Sjkoshy PMCMASK(scalar, 0x01), 2212145256Sjkoshy NULLMASK 2213145256Sjkoshy}; 2214145256Sjkoshy 2215145256Sjkoshystatic struct pmc_masks p6_mask_mite[] = { 2216145256Sjkoshy PMCMASK(packed-multiply, 0x01), 2217145256Sjkoshy PMCMASK(packed-shift, 0x02), 2218145256Sjkoshy PMCMASK(pack, 0x04), 2219145256Sjkoshy PMCMASK(unpack, 0x08), 2220145256Sjkoshy PMCMASK(packed-logical, 0x10), 2221145256Sjkoshy PMCMASK(packed-arithmetic, 0x20), 2222145256Sjkoshy NULLMASK 2223145256Sjkoshy}; 2224145256Sjkoshy 2225145256Sjkoshystatic struct pmc_masks p6_mask_fmt[] = { 2226145256Sjkoshy PMCMASK(mmxtofp, 0x00), 2227145256Sjkoshy PMCMASK(fptommx, 0x01), 2228145256Sjkoshy NULLMASK 2229145256Sjkoshy}; 2230145256Sjkoshy 2231145256Sjkoshystatic struct pmc_masks p6_mask_sr[] = { 2232145256Sjkoshy PMCMASK(es, 0x01), 2233145256Sjkoshy PMCMASK(ds, 0x02), 2234145256Sjkoshy PMCMASK(fs, 0x04), 2235145256Sjkoshy PMCMASK(gs, 0x08), 2236145256Sjkoshy NULLMASK 2237145256Sjkoshy}; 2238145256Sjkoshy 2239145256Sjkoshystatic struct pmc_masks p6_mask_eet[] = { 2240145256Sjkoshy PMCMASK(all, 0x00), 2241145256Sjkoshy PMCMASK(freq, 0x02), 2242145256Sjkoshy NULLMASK 2243145256Sjkoshy}; 2244145256Sjkoshy 2245145256Sjkoshystatic struct pmc_masks p6_mask_efur[] = { 2246145256Sjkoshy PMCMASK(all, 0x00), 2247145256Sjkoshy PMCMASK(loadop, 0x01), 2248145256Sjkoshy PMCMASK(stdsta, 0x02), 2249145256Sjkoshy NULLMASK 2250145256Sjkoshy}; 2251145256Sjkoshy 2252145256Sjkoshystatic struct pmc_masks p6_mask_essir[] = { 2253145256Sjkoshy PMCMASK(sse-packed-single, 0x00), 2254145256Sjkoshy PMCMASK(sse-packed-single-scalar-single, 0x01), 2255145256Sjkoshy PMCMASK(sse2-packed-double, 0x02), 2256145256Sjkoshy PMCMASK(sse2-scalar-double, 0x03), 2257145256Sjkoshy NULLMASK 2258145256Sjkoshy}; 2259145256Sjkoshy 2260145256Sjkoshystatic struct pmc_masks p6_mask_esscir[] = { 2261145256Sjkoshy PMCMASK(sse-packed-single, 0x00), 2262145256Sjkoshy PMCMASK(sse-scalar-single, 0x01), 2263145256Sjkoshy PMCMASK(sse2-packed-double, 0x02), 2264145256Sjkoshy PMCMASK(sse2-scalar-double, 0x03), 2265145256Sjkoshy NULLMASK 2266145256Sjkoshy}; 2267145256Sjkoshy 2268145256Sjkoshy/* P6 event parser */ 2269145256Sjkoshystatic int 2270145256Sjkoshyp6_allocate_pmc(enum pmc_event pe, char *ctrspec, 2271145256Sjkoshy struct pmc_op_pmcallocate *pmc_config) 2272145256Sjkoshy{ 2273145256Sjkoshy char *e, *p, *q; 2274240164Sfabient uint64_t evmask; 2275145256Sjkoshy int count, n; 2276145256Sjkoshy const struct pmc_masks *pm, *pmask; 2277145256Sjkoshy 2278183725Sjkoshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2279147191Sjkoshy pmc_config->pm_md.pm_ppro.pm_ppro_config = 0; 2280145256Sjkoshy 2281145256Sjkoshy evmask = 0; 2282145256Sjkoshy 2283145256Sjkoshy#define P6MASKSET(M) pmask = p6_mask_ ## M 2284145256Sjkoshy 2285145256Sjkoshy switch(pe) { 2286183107Sjkoshy case PMC_EV_P6_L2_IFETCH: P6MASKSET(mesi); break; 2287145256Sjkoshy case PMC_EV_P6_L2_LD: P6MASKSET(mesi); break; 2288145256Sjkoshy case PMC_EV_P6_L2_ST: P6MASKSET(mesi); break; 2289145256Sjkoshy case PMC_EV_P6_L2_RQSTS: P6MASKSET(mesi); break; 2290145256Sjkoshy case PMC_EV_P6_BUS_DRDY_CLOCKS: 2291145256Sjkoshy case PMC_EV_P6_BUS_LOCK_CLOCKS: 2292145256Sjkoshy case PMC_EV_P6_BUS_TRAN_BRD: 2293145256Sjkoshy case PMC_EV_P6_BUS_TRAN_RFO: 2294145256Sjkoshy case PMC_EV_P6_BUS_TRANS_WB: 2295145256Sjkoshy case PMC_EV_P6_BUS_TRAN_IFETCH: 2296145256Sjkoshy case PMC_EV_P6_BUS_TRAN_INVAL: 2297145256Sjkoshy case PMC_EV_P6_BUS_TRAN_PWR: 2298145256Sjkoshy case PMC_EV_P6_BUS_TRANS_P: 2299145256Sjkoshy case PMC_EV_P6_BUS_TRANS_IO: 2300145256Sjkoshy case PMC_EV_P6_BUS_TRAN_DEF: 2301145256Sjkoshy case PMC_EV_P6_BUS_TRAN_BURST: 2302145256Sjkoshy case PMC_EV_P6_BUS_TRAN_ANY: 2303145256Sjkoshy case PMC_EV_P6_BUS_TRAN_MEM: 2304145256Sjkoshy P6MASKSET(any); break; 2305145256Sjkoshy case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED: 2306145256Sjkoshy case PMC_EV_P6_EMON_KNI_PREF_MISS: 2307145256Sjkoshy P6MASKSET(ekp); break; 2308145256Sjkoshy case PMC_EV_P6_EMON_KNI_INST_RETIRED: 2309145256Sjkoshy case PMC_EV_P6_EMON_KNI_COMP_INST_RET: 2310145256Sjkoshy P6MASKSET(pps); break; 2311145256Sjkoshy case PMC_EV_P6_MMX_INSTR_TYPE_EXEC: 2312145256Sjkoshy P6MASKSET(mite); break; 2313145256Sjkoshy case PMC_EV_P6_FP_MMX_TRANS: 2314145256Sjkoshy P6MASKSET(fmt); break; 2315145256Sjkoshy case PMC_EV_P6_SEG_RENAME_STALLS: 2316145256Sjkoshy case PMC_EV_P6_SEG_REG_RENAMES: 2317145256Sjkoshy P6MASKSET(sr); break; 2318145256Sjkoshy case PMC_EV_P6_EMON_EST_TRANS: 2319145256Sjkoshy P6MASKSET(eet); break; 2320145256Sjkoshy case PMC_EV_P6_EMON_FUSED_UOPS_RET: 2321145256Sjkoshy P6MASKSET(efur); break; 2322145256Sjkoshy case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED: 2323145256Sjkoshy P6MASKSET(essir); break; 2324145256Sjkoshy case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED: 2325145256Sjkoshy P6MASKSET(esscir); break; 2326145256Sjkoshy default: 2327145256Sjkoshy pmask = NULL; 2328145256Sjkoshy break; 2329145256Sjkoshy } 2330145256Sjkoshy 2331145256Sjkoshy /* Pentium M PMCs have a few events with different semantics */ 2332145256Sjkoshy if (cpu_info.pm_cputype == PMC_CPU_INTEL_PM) { 2333145256Sjkoshy if (pe == PMC_EV_P6_L2_LD || 2334145256Sjkoshy pe == PMC_EV_P6_L2_LINES_IN || 2335145256Sjkoshy pe == PMC_EV_P6_L2_LINES_OUT) 2336145256Sjkoshy P6MASKSET(mesihw); 2337145256Sjkoshy else if (pe == PMC_EV_P6_L2_M_LINES_OUTM) 2338145256Sjkoshy P6MASKSET(hw); 2339145256Sjkoshy } 2340145256Sjkoshy 2341145256Sjkoshy /* Parse additional modifiers if present */ 2342145256Sjkoshy while ((p = strsep(&ctrspec, ",")) != NULL) { 2343145256Sjkoshy if (KWPREFIXMATCH(p, P6_KW_CMASK "=")) { 2344145256Sjkoshy q = strchr(p, '='); 2345145256Sjkoshy if (*++q == '\0') /* skip '=' */ 2346174406Sjkoshy return (-1); 2347145256Sjkoshy count = strtol(q, &e, 0); 2348145256Sjkoshy if (e == q || *e != '\0') 2349174406Sjkoshy return (-1); 2350145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 2351147191Sjkoshy pmc_config->pm_md.pm_ppro.pm_ppro_config |= 2352147191Sjkoshy P6_EVSEL_TO_CMASK(count); 2353145256Sjkoshy } else if (KWMATCH(p, P6_KW_EDGE)) { 2354145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_EDGE; 2355145256Sjkoshy } else if (KWMATCH(p, P6_KW_INV)) { 2356145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_INVERT; 2357145256Sjkoshy } else if (KWMATCH(p, P6_KW_OS)) { 2358145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2359145256Sjkoshy } else if (KWPREFIXMATCH(p, P6_KW_UMASK "=")) { 2360145256Sjkoshy evmask = 0; 2361145256Sjkoshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 2362174406Sjkoshy return (-1); 2363145256Sjkoshy if ((pe == PMC_EV_P6_BUS_DRDY_CLOCKS || 2364145256Sjkoshy pe == PMC_EV_P6_BUS_LOCK_CLOCKS || 2365145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_BRD || 2366145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_RFO || 2367145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_IFETCH || 2368145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_INVAL || 2369145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_PWR || 2370145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_DEF || 2371145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_BURST || 2372145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_ANY || 2373145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_MEM || 2374145256Sjkoshy pe == PMC_EV_P6_BUS_TRANS_IO || 2375145256Sjkoshy pe == PMC_EV_P6_BUS_TRANS_P || 2376145256Sjkoshy pe == PMC_EV_P6_BUS_TRANS_WB || 2377145256Sjkoshy pe == PMC_EV_P6_EMON_EST_TRANS || 2378145256Sjkoshy pe == PMC_EV_P6_EMON_FUSED_UOPS_RET || 2379145256Sjkoshy pe == PMC_EV_P6_EMON_KNI_COMP_INST_RET || 2380145256Sjkoshy pe == PMC_EV_P6_EMON_KNI_INST_RETIRED || 2381145256Sjkoshy pe == PMC_EV_P6_EMON_KNI_PREF_DISPATCHED || 2382145256Sjkoshy pe == PMC_EV_P6_EMON_KNI_PREF_MISS || 2383145256Sjkoshy pe == PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED || 2384145256Sjkoshy pe == PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED || 2385145256Sjkoshy pe == PMC_EV_P6_FP_MMX_TRANS) 2386174406Sjkoshy && (n > 1)) /* Only one mask keyword is allowed. */ 2387174406Sjkoshy return (-1); 2388145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2389145256Sjkoshy } else if (KWMATCH(p, P6_KW_USR)) { 2390145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_USER; 2391145256Sjkoshy } else 2392174406Sjkoshy return (-1); 2393145256Sjkoshy } 2394145256Sjkoshy 2395145256Sjkoshy /* post processing */ 2396145256Sjkoshy switch (pe) { 2397145256Sjkoshy 2398145256Sjkoshy /* 2399145256Sjkoshy * The following events default to an evmask of 0 2400145256Sjkoshy */ 2401145256Sjkoshy 2402145256Sjkoshy /* default => 'self' */ 2403145256Sjkoshy case PMC_EV_P6_BUS_DRDY_CLOCKS: 2404145256Sjkoshy case PMC_EV_P6_BUS_LOCK_CLOCKS: 2405145256Sjkoshy case PMC_EV_P6_BUS_TRAN_BRD: 2406145256Sjkoshy case PMC_EV_P6_BUS_TRAN_RFO: 2407145256Sjkoshy case PMC_EV_P6_BUS_TRANS_WB: 2408145256Sjkoshy case PMC_EV_P6_BUS_TRAN_IFETCH: 2409145256Sjkoshy case PMC_EV_P6_BUS_TRAN_INVAL: 2410145256Sjkoshy case PMC_EV_P6_BUS_TRAN_PWR: 2411145256Sjkoshy case PMC_EV_P6_BUS_TRANS_P: 2412145256Sjkoshy case PMC_EV_P6_BUS_TRANS_IO: 2413145256Sjkoshy case PMC_EV_P6_BUS_TRAN_DEF: 2414145256Sjkoshy case PMC_EV_P6_BUS_TRAN_BURST: 2415145256Sjkoshy case PMC_EV_P6_BUS_TRAN_ANY: 2416145256Sjkoshy case PMC_EV_P6_BUS_TRAN_MEM: 2417145256Sjkoshy 2418145256Sjkoshy /* default => 'nta' */ 2419145256Sjkoshy case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED: 2420145256Sjkoshy case PMC_EV_P6_EMON_KNI_PREF_MISS: 2421145256Sjkoshy 2422145256Sjkoshy /* default => 'packed and scalar' */ 2423145256Sjkoshy case PMC_EV_P6_EMON_KNI_INST_RETIRED: 2424145256Sjkoshy case PMC_EV_P6_EMON_KNI_COMP_INST_RET: 2425145256Sjkoshy 2426145256Sjkoshy /* default => 'mmx to fp transitions' */ 2427145256Sjkoshy case PMC_EV_P6_FP_MMX_TRANS: 2428145256Sjkoshy 2429145256Sjkoshy /* default => 'SSE Packed Single' */ 2430145256Sjkoshy case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED: 2431145256Sjkoshy case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED: 2432145256Sjkoshy 2433145256Sjkoshy /* default => 'all fused micro-ops' */ 2434145256Sjkoshy case PMC_EV_P6_EMON_FUSED_UOPS_RET: 2435145256Sjkoshy 2436145256Sjkoshy /* default => 'all transitions' */ 2437145256Sjkoshy case PMC_EV_P6_EMON_EST_TRANS: 2438145256Sjkoshy break; 2439145256Sjkoshy 2440145256Sjkoshy case PMC_EV_P6_MMX_UOPS_EXEC: 2441145256Sjkoshy evmask = 0x0F; /* only value allowed */ 2442145256Sjkoshy break; 2443145256Sjkoshy 2444145256Sjkoshy default: 2445145256Sjkoshy /* 2446145256Sjkoshy * For all other events, set the default event mask 2447145256Sjkoshy * to a logical OR of all the allowed event mask bits. 2448145256Sjkoshy */ 2449145256Sjkoshy if (evmask == 0 && pmask) { 2450145256Sjkoshy for (pm = pmask; pm->pm_name; pm++) 2451145256Sjkoshy evmask |= pm->pm_value; 2452145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2453145256Sjkoshy } 2454145256Sjkoshy 2455145256Sjkoshy break; 2456145256Sjkoshy } 2457145256Sjkoshy 2458145256Sjkoshy if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) 2459147191Sjkoshy pmc_config->pm_md.pm_ppro.pm_ppro_config |= 2460147191Sjkoshy P6_EVSEL_TO_UMASK(evmask); 2461145256Sjkoshy 2462174406Sjkoshy return (0); 2463145256Sjkoshy} 2464145256Sjkoshy 2465147191Sjkoshy#endif 2466147191Sjkoshy 2467183725Sjkoshy#if defined(__i386__) || defined(__amd64__) 2468183725Sjkoshystatic int 2469183725Sjkoshytsc_allocate_pmc(enum pmc_event pe, char *ctrspec, 2470183725Sjkoshy struct pmc_op_pmcallocate *pmc_config) 2471183725Sjkoshy{ 2472183725Sjkoshy if (pe != PMC_EV_TSC_TSC) 2473183725Sjkoshy return (-1); 2474183725Sjkoshy 2475183725Sjkoshy /* TSC events must be unqualified. */ 2476183725Sjkoshy if (ctrspec && *ctrspec != '\0') 2477183725Sjkoshy return (-1); 2478183725Sjkoshy 2479183725Sjkoshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 2480183725Sjkoshy pmc_config->pm_caps |= PMC_CAP_READ; 2481183725Sjkoshy 2482183725Sjkoshy return (0); 2483183725Sjkoshy} 2484183725Sjkoshy#endif 2485183725Sjkoshy 2486233628Sfabientstatic struct pmc_event_alias generic_aliases[] = { 2487233628Sfabient EV_ALIAS("instructions", "SOFT-CLOCK.HARD"), 2488233628Sfabient EV_ALIAS(NULL, NULL) 2489233628Sfabient}; 2490233628Sfabient 2491233628Sfabientstatic int 2492233628Sfabientsoft_allocate_pmc(enum pmc_event pe, char *ctrspec, 2493233628Sfabient struct pmc_op_pmcallocate *pmc_config) 2494233628Sfabient{ 2495233628Sfabient (void)ctrspec; 2496233628Sfabient (void)pmc_config; 2497233628Sfabient 2498242622Sdim if ((int)pe < PMC_EV_SOFT_FIRST || (int)pe > PMC_EV_SOFT_LAST) 2499233628Sfabient return (-1); 2500233628Sfabient 2501233628Sfabient pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2502233628Sfabient return (0); 2503233628Sfabient} 2504233628Sfabient 2505277835Sbr#if defined(__arm__) 2506200928Srpaulo#if defined(__XSCALE__) 2507200928Srpaulo 2508200928Srpaulostatic struct pmc_event_alias xscale_aliases[] = { 2509200928Srpaulo EV_ALIAS("branches", "BRANCH_RETIRED"), 2510200928Srpaulo EV_ALIAS("branch-mispredicts", "BRANCH_MISPRED"), 2511200928Srpaulo EV_ALIAS("dc-misses", "DC_MISS"), 2512200928Srpaulo EV_ALIAS("ic-misses", "IC_MISS"), 2513200928Srpaulo EV_ALIAS("instructions", "INSTR_RETIRED"), 2514200928Srpaulo EV_ALIAS(NULL, NULL) 2515200928Srpaulo}; 2516200928Srpaulostatic int 2517200928Srpauloxscale_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 2518200928Srpaulo struct pmc_op_pmcallocate *pmc_config __unused) 2519200928Srpaulo{ 2520200928Srpaulo switch (pe) { 2521200928Srpaulo default: 2522200928Srpaulo break; 2523200928Srpaulo } 2524200928Srpaulo 2525200928Srpaulo return (0); 2526200928Srpaulo} 2527200928Srpaulo#endif 2528200928Srpaulo 2529284218Sbrstatic struct pmc_event_alias cortex_a8_aliases[] = { 2530277835Sbr EV_ALIAS("dc-misses", "L1_DCACHE_REFILL"), 2531277835Sbr EV_ALIAS("ic-misses", "L1_ICACHE_REFILL"), 2532277835Sbr EV_ALIAS("instructions", "INSTR_EXECUTED"), 2533277835Sbr EV_ALIAS(NULL, NULL) 2534277835Sbr}; 2535284218Sbr 2536284218Sbrstatic struct pmc_event_alias cortex_a9_aliases[] = { 2537284218Sbr EV_ALIAS("dc-misses", "L1_DCACHE_REFILL"), 2538284218Sbr EV_ALIAS("ic-misses", "L1_ICACHE_REFILL"), 2539284218Sbr EV_ALIAS("instructions", "INSTR_EXECUTED"), 2540284218Sbr EV_ALIAS(NULL, NULL) 2541284218Sbr}; 2542284218Sbr 2543277835Sbrstatic int 2544277835Sbrarmv7_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 2545277835Sbr struct pmc_op_pmcallocate *pmc_config __unused) 2546277835Sbr{ 2547277835Sbr switch (pe) { 2548277835Sbr default: 2549277835Sbr break; 2550277835Sbr } 2551277835Sbr 2552277835Sbr return (0); 2553277835Sbr} 2554277835Sbr#endif 2555277835Sbr 2556283112Sbr#if defined(__aarch64__) 2557283112Sbrstatic struct pmc_event_alias cortex_a53_aliases[] = { 2558283112Sbr EV_ALIAS(NULL, NULL) 2559283112Sbr}; 2560283112Sbrstatic struct pmc_event_alias cortex_a57_aliases[] = { 2561283112Sbr EV_ALIAS(NULL, NULL) 2562283112Sbr}; 2563283112Sbrstatic int 2564283112Sbrarm64_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 2565283112Sbr struct pmc_op_pmcallocate *pmc_config __unused) 2566283112Sbr{ 2567283112Sbr switch (pe) { 2568283112Sbr default: 2569283112Sbr break; 2570283112Sbr } 2571283112Sbr 2572283112Sbr return (0); 2573283112Sbr} 2574283112Sbr#endif 2575283112Sbr 2576204635Sgnn#if defined(__mips__) 2577204635Sgnn 2578204635Sgnnstatic struct pmc_event_alias mips24k_aliases[] = { 2579204635Sgnn EV_ALIAS("instructions", "INSTR_EXECUTED"), 2580204635Sgnn EV_ALIAS("branches", "BRANCH_COMPLETED"), 2581204635Sgnn EV_ALIAS("branch-mispredicts", "BRANCH_MISPRED"), 2582204635Sgnn EV_ALIAS(NULL, NULL) 2583204635Sgnn}; 2584204635Sgnn 2585281098Sadrianstatic struct pmc_event_alias mips74k_aliases[] = { 2586281098Sadrian EV_ALIAS("instructions", "INSTR_EXECUTED"), 2587281098Sadrian EV_ALIAS("branches", "BRANCH_INSNS"), 2588281098Sadrian EV_ALIAS("branch-mispredicts", "MISPREDICTED_BRANCH_INSNS"), 2589281098Sadrian EV_ALIAS(NULL, NULL) 2590281098Sadrian}; 2591281098Sadrian 2592233335Sgonzostatic struct pmc_event_alias octeon_aliases[] = { 2593233335Sgonzo EV_ALIAS("instructions", "RET"), 2594233335Sgonzo EV_ALIAS("branches", "BR"), 2595233335Sgonzo EV_ALIAS("branch-mispredicts", "BRMIS"), 2596233335Sgonzo EV_ALIAS(NULL, NULL) 2597233335Sgonzo}; 2598233335Sgonzo 2599233320Sgonzo#define MIPS_KW_OS "os" 2600233320Sgonzo#define MIPS_KW_USR "usr" 2601233320Sgonzo#define MIPS_KW_ANYTHREAD "anythread" 2602204635Sgnn 2603204635Sgnnstatic int 2604233320Sgonzomips_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 2605204635Sgnn struct pmc_op_pmcallocate *pmc_config __unused) 2606204635Sgnn{ 2607204635Sgnn char *p; 2608204635Sgnn 2609204635Sgnn (void) pe; 2610204635Sgnn 2611204635Sgnn pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2612204635Sgnn 2613204635Sgnn while ((p = strsep(&ctrspec, ",")) != NULL) { 2614233320Sgonzo if (KWMATCH(p, MIPS_KW_OS)) 2615204635Sgnn pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2616233320Sgonzo else if (KWMATCH(p, MIPS_KW_USR)) 2617204635Sgnn pmc_config->pm_caps |= PMC_CAP_USER; 2618233320Sgonzo else if (KWMATCH(p, MIPS_KW_ANYTHREAD)) 2619204635Sgnn pmc_config->pm_caps |= (PMC_CAP_USER | PMC_CAP_SYSTEM); 2620204635Sgnn else 2621204635Sgnn return (-1); 2622204635Sgnn } 2623204635Sgnn 2624204635Sgnn return (0); 2625204635Sgnn} 2626233320Sgonzo 2627204635Sgnn#endif /* __mips__ */ 2628204635Sgnn 2629228869Sjhibbits#if defined(__powerpc__) 2630204635Sgnn 2631228869Sjhibbitsstatic struct pmc_event_alias ppc7450_aliases[] = { 2632228869Sjhibbits EV_ALIAS("instructions", "INSTR_COMPLETED"), 2633228869Sjhibbits EV_ALIAS("branches", "BRANCHES_COMPLETED"), 2634228869Sjhibbits EV_ALIAS("branch-mispredicts", "MISPREDICTED_BRANCHES"), 2635228869Sjhibbits EV_ALIAS(NULL, NULL) 2636228869Sjhibbits}; 2637228869Sjhibbits 2638261342Sjhibbitsstatic struct pmc_event_alias ppc970_aliases[] = { 2639261342Sjhibbits EV_ALIAS("instructions", "INSTR_COMPLETED"), 2640261342Sjhibbits EV_ALIAS("cycles", "CYCLES"), 2641261342Sjhibbits EV_ALIAS(NULL, NULL) 2642261342Sjhibbits}; 2643228869Sjhibbits 2644281713Sjhibbitsstatic struct pmc_event_alias e500_aliases[] = { 2645281713Sjhibbits EV_ALIAS("instructions", "INSTR_COMPLETED"), 2646281713Sjhibbits EV_ALIAS("cycles", "CYCLES"), 2647281713Sjhibbits EV_ALIAS(NULL, NULL) 2648281713Sjhibbits}; 2649281713Sjhibbits 2650261342Sjhibbits#define POWERPC_KW_OS "os" 2651261342Sjhibbits#define POWERPC_KW_USR "usr" 2652261342Sjhibbits#define POWERPC_KW_ANYTHREAD "anythread" 2653261342Sjhibbits 2654228869Sjhibbitsstatic int 2655261342Sjhibbitspowerpc_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 2656261342Sjhibbits struct pmc_op_pmcallocate *pmc_config __unused) 2657228869Sjhibbits{ 2658228869Sjhibbits char *p; 2659228869Sjhibbits 2660228869Sjhibbits (void) pe; 2661228869Sjhibbits 2662228869Sjhibbits pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2663228869Sjhibbits 2664228869Sjhibbits while ((p = strsep(&ctrspec, ",")) != NULL) { 2665261342Sjhibbits if (KWMATCH(p, POWERPC_KW_OS)) 2666228869Sjhibbits pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2667261342Sjhibbits else if (KWMATCH(p, POWERPC_KW_USR)) 2668228869Sjhibbits pmc_config->pm_caps |= PMC_CAP_USER; 2669261342Sjhibbits else if (KWMATCH(p, POWERPC_KW_ANYTHREAD)) 2670228869Sjhibbits pmc_config->pm_caps |= (PMC_CAP_USER | PMC_CAP_SYSTEM); 2671228869Sjhibbits else 2672228869Sjhibbits return (-1); 2673228869Sjhibbits } 2674228869Sjhibbits 2675228869Sjhibbits return (0); 2676228869Sjhibbits} 2677261342Sjhibbits 2678228869Sjhibbits#endif /* __powerpc__ */ 2679228869Sjhibbits 2680228869Sjhibbits 2681145256Sjkoshy/* 2682183725Sjkoshy * Match an event name `name' with its canonical form. 2683183725Sjkoshy * 2684185363Sjkoshy * Matches are case insensitive and spaces, periods, underscores and 2685185363Sjkoshy * hyphen characters are considered to match each other. 2686185363Sjkoshy * 2687183725Sjkoshy * Returns 1 for a match, 0 otherwise. 2688183725Sjkoshy */ 2689183725Sjkoshy 2690183725Sjkoshystatic int 2691183725Sjkoshypmc_match_event_name(const char *name, const char *canonicalname) 2692183725Sjkoshy{ 2693183725Sjkoshy int cc, nc; 2694183725Sjkoshy const unsigned char *c, *n; 2695183725Sjkoshy 2696183725Sjkoshy c = (const unsigned char *) canonicalname; 2697183725Sjkoshy n = (const unsigned char *) name; 2698183725Sjkoshy 2699183725Sjkoshy for (; (nc = *n) && (cc = *c); n++, c++) { 2700183725Sjkoshy 2701185363Sjkoshy if ((nc == ' ' || nc == '_' || nc == '-' || nc == '.') && 2702185363Sjkoshy (cc == ' ' || cc == '_' || cc == '-' || cc == '.')) 2703183725Sjkoshy continue; 2704183725Sjkoshy 2705185363Sjkoshy if (toupper(nc) == toupper(cc)) 2706183725Sjkoshy continue; 2707183725Sjkoshy 2708185363Sjkoshy 2709183725Sjkoshy return (0); 2710183725Sjkoshy } 2711183725Sjkoshy 2712183725Sjkoshy if (*n == '\0' && *c == '\0') 2713183725Sjkoshy return (1); 2714183725Sjkoshy 2715183725Sjkoshy return (0); 2716183725Sjkoshy} 2717183725Sjkoshy 2718183725Sjkoshy/* 2719183725Sjkoshy * Match an event name against all the event named supported by a 2720183725Sjkoshy * PMC class. 2721183725Sjkoshy * 2722183725Sjkoshy * Returns an event descriptor pointer on match or NULL otherwise. 2723183725Sjkoshy */ 2724183725Sjkoshystatic const struct pmc_event_descr * 2725183725Sjkoshypmc_match_event_class(const char *name, 2726183725Sjkoshy const struct pmc_class_descr *pcd) 2727183725Sjkoshy{ 2728183725Sjkoshy size_t n; 2729183725Sjkoshy const struct pmc_event_descr *ev; 2730185363Sjkoshy 2731183725Sjkoshy ev = pcd->pm_evc_event_table; 2732183725Sjkoshy for (n = 0; n < pcd->pm_evc_event_table_size; n++, ev++) 2733183725Sjkoshy if (pmc_match_event_name(name, ev->pm_ev_name)) 2734183725Sjkoshy return (ev); 2735183725Sjkoshy 2736183725Sjkoshy return (NULL); 2737183725Sjkoshy} 2738183725Sjkoshy 2739183725Sjkoshystatic int 2740183725Sjkoshypmc_mdep_is_compatible_class(enum pmc_class pc) 2741183725Sjkoshy{ 2742183725Sjkoshy size_t n; 2743183725Sjkoshy 2744183725Sjkoshy for (n = 0; n < pmc_mdep_class_list_size; n++) 2745183725Sjkoshy if (pmc_mdep_class_list[n] == pc) 2746183725Sjkoshy return (1); 2747183725Sjkoshy return (0); 2748183725Sjkoshy} 2749183725Sjkoshy 2750183725Sjkoshy/* 2751147191Sjkoshy * API entry points 2752145256Sjkoshy */ 2753145256Sjkoshy 2754147191Sjkoshyint 2755147191Sjkoshypmc_allocate(const char *ctrspec, enum pmc_mode mode, 2756147191Sjkoshy uint32_t flags, int cpu, pmc_id_t *pmcid) 2757145256Sjkoshy{ 2758183725Sjkoshy size_t n; 2759147191Sjkoshy int retval; 2760147191Sjkoshy char *r, *spec_copy; 2761147191Sjkoshy const char *ctrname; 2762183725Sjkoshy const struct pmc_event_descr *ev; 2763183725Sjkoshy const struct pmc_event_alias *alias; 2764147191Sjkoshy struct pmc_op_pmcallocate pmc_config; 2765183725Sjkoshy const struct pmc_class_descr *pcd; 2766145256Sjkoshy 2767147191Sjkoshy spec_copy = NULL; 2768147191Sjkoshy retval = -1; 2769145256Sjkoshy 2770147191Sjkoshy if (mode != PMC_MODE_SS && mode != PMC_MODE_TS && 2771147191Sjkoshy mode != PMC_MODE_SC && mode != PMC_MODE_TC) { 2772147191Sjkoshy errno = EINVAL; 2773147191Sjkoshy goto out; 2774147191Sjkoshy } 2775145256Sjkoshy 2776147191Sjkoshy /* replace an event alias with the canonical event specifier */ 2777147191Sjkoshy if (pmc_mdep_event_aliases) 2778183725Sjkoshy for (alias = pmc_mdep_event_aliases; alias->pm_alias; alias++) 2779183725Sjkoshy if (!strcasecmp(ctrspec, alias->pm_alias)) { 2780183725Sjkoshy spec_copy = strdup(alias->pm_spec); 2781147191Sjkoshy break; 2782147191Sjkoshy } 2783145256Sjkoshy 2784147191Sjkoshy if (spec_copy == NULL) 2785147191Sjkoshy spec_copy = strdup(ctrspec); 2786145256Sjkoshy 2787147191Sjkoshy r = spec_copy; 2788147191Sjkoshy ctrname = strsep(&r, ","); 2789145256Sjkoshy 2790183725Sjkoshy /* 2791183725Sjkoshy * If a explicit class prefix was given by the user, restrict the 2792183725Sjkoshy * search for the event to the specified PMC class. 2793183725Sjkoshy */ 2794183725Sjkoshy ev = NULL; 2795185363Sjkoshy for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) { 2796185363Sjkoshy pcd = pmc_class_table[n]; 2797183725Sjkoshy if (pmc_mdep_is_compatible_class(pcd->pm_evc_class) && 2798183725Sjkoshy strncasecmp(ctrname, pcd->pm_evc_name, 2799183725Sjkoshy pcd->pm_evc_name_size) == 0) { 2800183725Sjkoshy if ((ev = pmc_match_event_class(ctrname + 2801183725Sjkoshy pcd->pm_evc_name_size, pcd)) == NULL) { 2802183725Sjkoshy errno = EINVAL; 2803183725Sjkoshy goto out; 2804183725Sjkoshy } 2805147191Sjkoshy break; 2806183725Sjkoshy } 2807183725Sjkoshy } 2808145256Sjkoshy 2809183725Sjkoshy /* 2810183725Sjkoshy * Otherwise, search for this event in all compatible PMC 2811183725Sjkoshy * classes. 2812183725Sjkoshy */ 2813185363Sjkoshy for (n = 0; ev == NULL && n < PMC_CLASS_TABLE_SIZE; n++) { 2814185363Sjkoshy pcd = pmc_class_table[n]; 2815183725Sjkoshy if (pmc_mdep_is_compatible_class(pcd->pm_evc_class)) 2816183725Sjkoshy ev = pmc_match_event_class(ctrname, pcd); 2817183725Sjkoshy } 2818183725Sjkoshy 2819183725Sjkoshy if (ev == NULL) { 2820147191Sjkoshy errno = EINVAL; 2821147191Sjkoshy goto out; 2822147191Sjkoshy } 2823145256Sjkoshy 2824147191Sjkoshy bzero(&pmc_config, sizeof(pmc_config)); 2825183725Sjkoshy pmc_config.pm_ev = ev->pm_ev_code; 2826183725Sjkoshy pmc_config.pm_class = pcd->pm_evc_class; 2827147191Sjkoshy pmc_config.pm_cpu = cpu; 2828147191Sjkoshy pmc_config.pm_mode = mode; 2829147191Sjkoshy pmc_config.pm_flags = flags; 2830145256Sjkoshy 2831147191Sjkoshy if (PMC_IS_SAMPLING_MODE(mode)) 2832147191Sjkoshy pmc_config.pm_caps |= PMC_CAP_INTERRUPT; 2833145256Sjkoshy 2834183725Sjkoshy if (pcd->pm_evc_allocate_pmc(ev->pm_ev_code, r, &pmc_config) < 0) { 2835147191Sjkoshy errno = EINVAL; 2836147191Sjkoshy goto out; 2837147191Sjkoshy } 2838145256Sjkoshy 2839147191Sjkoshy if (PMC_CALL(PMCALLOCATE, &pmc_config) < 0) 2840147191Sjkoshy goto out; 2841145256Sjkoshy 2842147191Sjkoshy *pmcid = pmc_config.pm_pmcid; 2843145256Sjkoshy 2844147191Sjkoshy retval = 0; 2845145256Sjkoshy 2846147191Sjkoshy out: 2847147191Sjkoshy if (spec_copy) 2848147191Sjkoshy free(spec_copy); 2849145256Sjkoshy 2850174406Sjkoshy return (retval); 2851147191Sjkoshy} 2852145256Sjkoshy 2853147191Sjkoshyint 2854147191Sjkoshypmc_attach(pmc_id_t pmc, pid_t pid) 2855147191Sjkoshy{ 2856147191Sjkoshy struct pmc_op_pmcattach pmc_attach_args; 2857145256Sjkoshy 2858147191Sjkoshy pmc_attach_args.pm_pmc = pmc; 2859147191Sjkoshy pmc_attach_args.pm_pid = pid; 2860145256Sjkoshy 2861174406Sjkoshy return (PMC_CALL(PMCATTACH, &pmc_attach_args)); 2862147191Sjkoshy} 2863145256Sjkoshy 2864147191Sjkoshyint 2865147191Sjkoshypmc_capabilities(pmc_id_t pmcid, uint32_t *caps) 2866147191Sjkoshy{ 2867147191Sjkoshy unsigned int i; 2868147191Sjkoshy enum pmc_class cl; 2869145256Sjkoshy 2870147191Sjkoshy cl = PMC_ID_TO_CLASS(pmcid); 2871147191Sjkoshy for (i = 0; i < cpu_info.pm_nclass; i++) 2872147191Sjkoshy if (cpu_info.pm_classes[i].pm_class == cl) { 2873147191Sjkoshy *caps = cpu_info.pm_classes[i].pm_caps; 2874174406Sjkoshy return (0); 2875147191Sjkoshy } 2876177107Sjkoshy errno = EINVAL; 2877177107Sjkoshy return (-1); 2878147191Sjkoshy} 2879145256Sjkoshy 2880147191Sjkoshyint 2881147191Sjkoshypmc_configure_logfile(int fd) 2882147191Sjkoshy{ 2883147191Sjkoshy struct pmc_op_configurelog cla; 2884145256Sjkoshy 2885147191Sjkoshy cla.pm_logfd = fd; 2886147191Sjkoshy if (PMC_CALL(CONFIGURELOG, &cla) < 0) 2887174406Sjkoshy return (-1); 2888174406Sjkoshy return (0); 2889147191Sjkoshy} 2890145256Sjkoshy 2891147191Sjkoshyint 2892147191Sjkoshypmc_cpuinfo(const struct pmc_cpuinfo **pci) 2893147191Sjkoshy{ 2894147191Sjkoshy if (pmc_syscall == -1) { 2895147191Sjkoshy errno = ENXIO; 2896174406Sjkoshy return (-1); 2897147191Sjkoshy } 2898145256Sjkoshy 2899147219Sjkoshy *pci = &cpu_info; 2900174406Sjkoshy return (0); 2901147191Sjkoshy} 2902145256Sjkoshy 2903147191Sjkoshyint 2904147191Sjkoshypmc_detach(pmc_id_t pmc, pid_t pid) 2905147191Sjkoshy{ 2906147191Sjkoshy struct pmc_op_pmcattach pmc_detach_args; 2907145256Sjkoshy 2908147191Sjkoshy pmc_detach_args.pm_pmc = pmc; 2909147191Sjkoshy pmc_detach_args.pm_pid = pid; 2910174406Sjkoshy return (PMC_CALL(PMCDETACH, &pmc_detach_args)); 2911147191Sjkoshy} 2912147191Sjkoshy 2913147191Sjkoshyint 2914147191Sjkoshypmc_disable(int cpu, int pmc) 2915145256Sjkoshy{ 2916147191Sjkoshy struct pmc_op_pmcadmin ssa; 2917145256Sjkoshy 2918147191Sjkoshy ssa.pm_cpu = cpu; 2919147191Sjkoshy ssa.pm_pmc = pmc; 2920147191Sjkoshy ssa.pm_state = PMC_STATE_DISABLED; 2921174406Sjkoshy return (PMC_CALL(PMCADMIN, &ssa)); 2922147191Sjkoshy} 2923145256Sjkoshy 2924147191Sjkoshyint 2925147191Sjkoshypmc_enable(int cpu, int pmc) 2926147191Sjkoshy{ 2927147191Sjkoshy struct pmc_op_pmcadmin ssa; 2928145256Sjkoshy 2929147191Sjkoshy ssa.pm_cpu = cpu; 2930147191Sjkoshy ssa.pm_pmc = pmc; 2931147191Sjkoshy ssa.pm_state = PMC_STATE_FREE; 2932174406Sjkoshy return (PMC_CALL(PMCADMIN, &ssa)); 2933147191Sjkoshy} 2934145256Sjkoshy 2935147191Sjkoshy/* 2936147191Sjkoshy * Return a list of events known to a given PMC class. 'cl' is the 2937147191Sjkoshy * PMC class identifier, 'eventnames' is the returned list of 'const 2938147191Sjkoshy * char *' pointers pointing to the names of the events. 'nevents' is 2939147191Sjkoshy * the number of event name pointers returned. 2940147191Sjkoshy * 2941147191Sjkoshy * The space for 'eventnames' is allocated using malloc(3). The caller 2942147191Sjkoshy * is responsible for freeing this space when done. 2943147191Sjkoshy */ 2944147191Sjkoshyint 2945147191Sjkoshypmc_event_names_of_class(enum pmc_class cl, const char ***eventnames, 2946147191Sjkoshy int *nevents) 2947147191Sjkoshy{ 2948147191Sjkoshy int count; 2949147191Sjkoshy const char **names; 2950147191Sjkoshy const struct pmc_event_descr *ev; 2951147191Sjkoshy 2952147191Sjkoshy switch (cl) 2953147191Sjkoshy { 2954185363Sjkoshy case PMC_CLASS_IAF: 2955185363Sjkoshy ev = iaf_event_table; 2956185363Sjkoshy count = PMC_EVENT_TABLE_SIZE(iaf); 2957185363Sjkoshy break; 2958185363Sjkoshy case PMC_CLASS_IAP: 2959185363Sjkoshy /* 2960185363Sjkoshy * Return the most appropriate set of event name 2961185363Sjkoshy * spellings for the current CPU. 2962185363Sjkoshy */ 2963185363Sjkoshy switch (cpu_info.pm_cputype) { 2964185363Sjkoshy default: 2965185363Sjkoshy case PMC_CPU_INTEL_ATOM: 2966185363Sjkoshy ev = atom_event_table; 2967185363Sjkoshy count = PMC_EVENT_TABLE_SIZE(atom); 2968185363Sjkoshy break; 2969263446Shiren case PMC_CPU_INTEL_ATOM_SILVERMONT: 2970263446Shiren ev = atom_silvermont_event_table; 2971263446Shiren count = PMC_EVENT_TABLE_SIZE(atom_silvermont); 2972263446Shiren break; 2973185363Sjkoshy case PMC_CPU_INTEL_CORE: 2974185363Sjkoshy ev = core_event_table; 2975185363Sjkoshy count = PMC_EVENT_TABLE_SIZE(core); 2976185363Sjkoshy break; 2977185363Sjkoshy case PMC_CPU_INTEL_CORE2: 2978185585Sjkoshy case PMC_CPU_INTEL_CORE2EXTREME: 2979185363Sjkoshy ev = core2_event_table; 2980185363Sjkoshy count = PMC_EVENT_TABLE_SIZE(core2); 2981185363Sjkoshy break; 2982187761Sjeff case PMC_CPU_INTEL_COREI7: 2983187761Sjeff ev = corei7_event_table; 2984187761Sjeff count = PMC_EVENT_TABLE_SIZE(corei7); 2985187761Sjeff break; 2986267062Skib case PMC_CPU_INTEL_NEHALEM_EX: 2987267062Skib ev = nehalem_ex_event_table; 2988267062Skib count = PMC_EVENT_TABLE_SIZE(nehalem_ex); 2989267062Skib break; 2990248842Ssbruno case PMC_CPU_INTEL_HASWELL: 2991248842Ssbruno ev = haswell_event_table; 2992248842Ssbruno count = PMC_EVENT_TABLE_SIZE(haswell); 2993248842Ssbruno break; 2994277177Srrs case PMC_CPU_INTEL_HASWELL_XEON: 2995277177Srrs ev = haswell_xeon_event_table; 2996277177Srrs count = PMC_EVENT_TABLE_SIZE(haswell_xeon); 2997277177Srrs break; 2998291494Srrs case PMC_CPU_INTEL_BROADWELL: 2999291494Srrs ev = broadwell_event_table; 3000291494Srrs count = PMC_EVENT_TABLE_SIZE(broadwell); 3001291494Srrs break; 3002291494Srrs case PMC_CPU_INTEL_BROADWELL_XEON: 3003291494Srrs ev = broadwell_xeon_event_table; 3004291494Srrs count = PMC_EVENT_TABLE_SIZE(broadwell_xeon); 3005291494Srrs break; 3006291494Srrs case PMC_CPU_INTEL_SKYLAKE: 3007291494Srrs ev = skylake_event_table; 3008291494Srrs count = PMC_EVENT_TABLE_SIZE(skylake); 3009291494Srrs break; 3010240164Sfabient case PMC_CPU_INTEL_IVYBRIDGE: 3011240164Sfabient ev = ivybridge_event_table; 3012240164Sfabient count = PMC_EVENT_TABLE_SIZE(ivybridge); 3013240164Sfabient break; 3014246166Ssbruno case PMC_CPU_INTEL_IVYBRIDGE_XEON: 3015246166Ssbruno ev = ivybridge_xeon_event_table; 3016246166Ssbruno count = PMC_EVENT_TABLE_SIZE(ivybridge_xeon); 3017246166Ssbruno break; 3018232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 3019232366Sdavide ev = sandybridge_event_table; 3020232366Sdavide count = PMC_EVENT_TABLE_SIZE(sandybridge); 3021232366Sdavide break; 3022241738Ssbruno case PMC_CPU_INTEL_SANDYBRIDGE_XEON: 3023241738Ssbruno ev = sandybridge_xeon_event_table; 3024241738Ssbruno count = PMC_EVENT_TABLE_SIZE(sandybridge_xeon); 3025241738Ssbruno break; 3026206089Sfabient case PMC_CPU_INTEL_WESTMERE: 3027206089Sfabient ev = westmere_event_table; 3028206089Sfabient count = PMC_EVENT_TABLE_SIZE(westmere); 3029206089Sfabient break; 3030267062Skib case PMC_CPU_INTEL_WESTMERE_EX: 3031267062Skib ev = westmere_ex_event_table; 3032267062Skib count = PMC_EVENT_TABLE_SIZE(westmere_ex); 3033267062Skib break; 3034185363Sjkoshy } 3035185363Sjkoshy break; 3036206089Sfabient case PMC_CLASS_UCF: 3037206089Sfabient ev = ucf_event_table; 3038206089Sfabient count = PMC_EVENT_TABLE_SIZE(ucf); 3039206089Sfabient break; 3040206089Sfabient case PMC_CLASS_UCP: 3041206089Sfabient /* 3042206089Sfabient * Return the most appropriate set of event name 3043206089Sfabient * spellings for the current CPU. 3044206089Sfabient */ 3045206089Sfabient switch (cpu_info.pm_cputype) { 3046206089Sfabient default: 3047206089Sfabient case PMC_CPU_INTEL_COREI7: 3048206089Sfabient ev = corei7uc_event_table; 3049206089Sfabient count = PMC_EVENT_TABLE_SIZE(corei7uc); 3050206089Sfabient break; 3051248842Ssbruno case PMC_CPU_INTEL_HASWELL: 3052248842Ssbruno ev = haswelluc_event_table; 3053248842Ssbruno count = PMC_EVENT_TABLE_SIZE(haswelluc); 3054248842Ssbruno break; 3055291494Srrs case PMC_CPU_INTEL_BROADWELL: 3056291494Srrs ev = broadwelluc_event_table; 3057291494Srrs count = PMC_EVENT_TABLE_SIZE(broadwelluc); 3058291494Srrs break; 3059232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 3060232366Sdavide ev = sandybridgeuc_event_table; 3061232366Sdavide count = PMC_EVENT_TABLE_SIZE(sandybridgeuc); 3062232366Sdavide break; 3063206089Sfabient case PMC_CPU_INTEL_WESTMERE: 3064206089Sfabient ev = westmereuc_event_table; 3065206089Sfabient count = PMC_EVENT_TABLE_SIZE(westmereuc); 3066206089Sfabient break; 3067206089Sfabient } 3068206089Sfabient break; 3069147191Sjkoshy case PMC_CLASS_TSC: 3070183725Sjkoshy ev = tsc_event_table; 3071183725Sjkoshy count = PMC_EVENT_TABLE_SIZE(tsc); 3072145256Sjkoshy break; 3073147191Sjkoshy case PMC_CLASS_K7: 3074183725Sjkoshy ev = k7_event_table; 3075183725Sjkoshy count = PMC_EVENT_TABLE_SIZE(k7); 3076145256Sjkoshy break; 3077147191Sjkoshy case PMC_CLASS_K8: 3078183725Sjkoshy ev = k8_event_table; 3079183725Sjkoshy count = PMC_EVENT_TABLE_SIZE(k8); 3080145256Sjkoshy break; 3081183725Sjkoshy case PMC_CLASS_P4: 3082183725Sjkoshy ev = p4_event_table; 3083183725Sjkoshy count = PMC_EVENT_TABLE_SIZE(p4); 3084183725Sjkoshy break; 3085147191Sjkoshy case PMC_CLASS_P5: 3086183725Sjkoshy ev = p5_event_table; 3087183725Sjkoshy count = PMC_EVENT_TABLE_SIZE(p5); 3088145256Sjkoshy break; 3089147191Sjkoshy case PMC_CLASS_P6: 3090183725Sjkoshy ev = p6_event_table; 3091183725Sjkoshy count = PMC_EVENT_TABLE_SIZE(p6); 3092145256Sjkoshy break; 3093200928Srpaulo case PMC_CLASS_XSCALE: 3094200928Srpaulo ev = xscale_event_table; 3095200928Srpaulo count = PMC_EVENT_TABLE_SIZE(xscale); 3096200928Srpaulo break; 3097277835Sbr case PMC_CLASS_ARMV7: 3098284218Sbr switch (cpu_info.pm_cputype) { 3099284218Sbr default: 3100284218Sbr case PMC_CPU_ARMV7_CORTEX_A8: 3101284218Sbr ev = cortex_a8_event_table; 3102284218Sbr count = PMC_EVENT_TABLE_SIZE(cortex_a8); 3103284218Sbr break; 3104284218Sbr case PMC_CPU_ARMV7_CORTEX_A9: 3105284218Sbr ev = cortex_a9_event_table; 3106284218Sbr count = PMC_EVENT_TABLE_SIZE(cortex_a9); 3107284218Sbr break; 3108284218Sbr } 3109277835Sbr break; 3110283112Sbr case PMC_CLASS_ARMV8: 3111283112Sbr switch (cpu_info.pm_cputype) { 3112283112Sbr default: 3113283112Sbr case PMC_CPU_ARMV8_CORTEX_A53: 3114283112Sbr ev = cortex_a53_event_table; 3115283112Sbr count = PMC_EVENT_TABLE_SIZE(cortex_a53); 3116283112Sbr break; 3117283112Sbr case PMC_CPU_ARMV8_CORTEX_A57: 3118283112Sbr ev = cortex_a57_event_table; 3119283112Sbr count = PMC_EVENT_TABLE_SIZE(cortex_a57); 3120283112Sbr break; 3121283112Sbr } 3122283112Sbr break; 3123204635Sgnn case PMC_CLASS_MIPS24K: 3124204635Sgnn ev = mips24k_event_table; 3125204635Sgnn count = PMC_EVENT_TABLE_SIZE(mips24k); 3126204635Sgnn break; 3127281098Sadrian case PMC_CLASS_MIPS74K: 3128281098Sadrian ev = mips74k_event_table; 3129281098Sadrian count = PMC_EVENT_TABLE_SIZE(mips74k); 3130281098Sadrian break; 3131233335Sgonzo case PMC_CLASS_OCTEON: 3132233335Sgonzo ev = octeon_event_table; 3133233335Sgonzo count = PMC_EVENT_TABLE_SIZE(octeon); 3134233335Sgonzo break; 3135228869Sjhibbits case PMC_CLASS_PPC7450: 3136228869Sjhibbits ev = ppc7450_event_table; 3137228869Sjhibbits count = PMC_EVENT_TABLE_SIZE(ppc7450); 3138228869Sjhibbits break; 3139261342Sjhibbits case PMC_CLASS_PPC970: 3140261342Sjhibbits ev = ppc970_event_table; 3141261342Sjhibbits count = PMC_EVENT_TABLE_SIZE(ppc970); 3142261342Sjhibbits break; 3143281713Sjhibbits case PMC_CLASS_E500: 3144281713Sjhibbits ev = e500_event_table; 3145281713Sjhibbits count = PMC_EVENT_TABLE_SIZE(e500); 3146281713Sjhibbits break; 3147233628Sfabient case PMC_CLASS_SOFT: 3148233628Sfabient ev = soft_event_table; 3149233628Sfabient count = soft_event_info.pm_nevent; 3150233628Sfabient break; 3151145256Sjkoshy default: 3152147191Sjkoshy errno = EINVAL; 3153174406Sjkoshy return (-1); 3154145256Sjkoshy } 3155145256Sjkoshy 3156147191Sjkoshy if ((names = malloc(count * sizeof(const char *))) == NULL) 3157174406Sjkoshy return (-1); 3158145256Sjkoshy 3159147191Sjkoshy *eventnames = names; 3160147191Sjkoshy *nevents = count; 3161145256Sjkoshy 3162147191Sjkoshy for (;count--; ev++, names++) 3163147191Sjkoshy *names = ev->pm_ev_name; 3164233628Sfabient 3165174406Sjkoshy return (0); 3166147191Sjkoshy} 3167145256Sjkoshy 3168147191Sjkoshyint 3169147191Sjkoshypmc_flush_logfile(void) 3170147191Sjkoshy{ 3171174406Sjkoshy return (PMC_CALL(FLUSHLOG,0)); 3172147191Sjkoshy} 3173145256Sjkoshy 3174147191Sjkoshyint 3175226514Sfabientpmc_close_logfile(void) 3176226514Sfabient{ 3177226514Sfabient return (PMC_CALL(CLOSELOG,0)); 3178226514Sfabient} 3179226514Sfabient 3180226514Sfabientint 3181147191Sjkoshypmc_get_driver_stats(struct pmc_driverstats *ds) 3182147191Sjkoshy{ 3183147191Sjkoshy struct pmc_op_getdriverstats gms; 3184145256Sjkoshy 3185147191Sjkoshy if (PMC_CALL(GETDRIVERSTATS, &gms) < 0) 3186174406Sjkoshy return (-1); 3187145256Sjkoshy 3188147191Sjkoshy /* copy out fields in the current userland<->library interface */ 3189147191Sjkoshy ds->pm_intr_ignored = gms.pm_intr_ignored; 3190147191Sjkoshy ds->pm_intr_processed = gms.pm_intr_processed; 3191147191Sjkoshy ds->pm_intr_bufferfull = gms.pm_intr_bufferfull; 3192147191Sjkoshy ds->pm_syscalls = gms.pm_syscalls; 3193147191Sjkoshy ds->pm_syscall_errors = gms.pm_syscall_errors; 3194147191Sjkoshy ds->pm_buffer_requests = gms.pm_buffer_requests; 3195147191Sjkoshy ds->pm_buffer_requests_failed = gms.pm_buffer_requests_failed; 3196147191Sjkoshy ds->pm_log_sweeps = gms.pm_log_sweeps; 3197174406Sjkoshy return (0); 3198147191Sjkoshy} 3199145256Sjkoshy 3200147191Sjkoshyint 3201147191Sjkoshypmc_get_msr(pmc_id_t pmc, uint32_t *msr) 3202147191Sjkoshy{ 3203147191Sjkoshy struct pmc_op_getmsr gm; 3204147191Sjkoshy 3205147191Sjkoshy gm.pm_pmcid = pmc; 3206147191Sjkoshy if (PMC_CALL(PMCGETMSR, &gm) < 0) 3207174406Sjkoshy return (-1); 3208147191Sjkoshy *msr = gm.pm_msr; 3209174406Sjkoshy return (0); 3210145256Sjkoshy} 3211145256Sjkoshy 3212145256Sjkoshyint 3213145256Sjkoshypmc_init(void) 3214145256Sjkoshy{ 3215145256Sjkoshy int error, pmc_mod_id; 3216147219Sjkoshy unsigned int n; 3217145256Sjkoshy uint32_t abi_version; 3218145256Sjkoshy struct module_stat pmc_modstat; 3219147219Sjkoshy struct pmc_op_getcpuinfo op_cpu_info; 3220198433Sjkoshy#if defined(__amd64__) || defined(__i386__) 3221198433Sjkoshy int cpu_has_iaf_counters; 3222198433Sjkoshy unsigned int t; 3223198433Sjkoshy#endif 3224145256Sjkoshy 3225145256Sjkoshy if (pmc_syscall != -1) /* already inited */ 3226174406Sjkoshy return (0); 3227145256Sjkoshy 3228145256Sjkoshy /* retrieve the system call number from the KLD */ 3229145256Sjkoshy if ((pmc_mod_id = modfind(PMC_MODULE_NAME)) < 0) 3230174406Sjkoshy return (-1); 3231145256Sjkoshy 3232145256Sjkoshy pmc_modstat.version = sizeof(struct module_stat); 3233145256Sjkoshy if ((error = modstat(pmc_mod_id, &pmc_modstat)) < 0) 3234174406Sjkoshy return (-1); 3235145256Sjkoshy 3236145256Sjkoshy pmc_syscall = pmc_modstat.data.intval; 3237145256Sjkoshy 3238147191Sjkoshy /* check the kernel module's ABI against our compiled-in version */ 3239147191Sjkoshy abi_version = PMC_VERSION; 3240145256Sjkoshy if (PMC_CALL(GETMODULEVERSION, &abi_version) < 0) 3241145256Sjkoshy return (pmc_syscall = -1); 3242145256Sjkoshy 3243147191Sjkoshy /* ignore patch & minor numbers for the comparision */ 3244147191Sjkoshy if ((abi_version & 0xFF000000) != (PMC_VERSION & 0xFF000000)) { 3245145256Sjkoshy errno = EPROGMISMATCH; 3246145256Sjkoshy return (pmc_syscall = -1); 3247145256Sjkoshy } 3248145256Sjkoshy 3249147219Sjkoshy if (PMC_CALL(GETCPUINFO, &op_cpu_info) < 0) 3250145256Sjkoshy return (pmc_syscall = -1); 3251145256Sjkoshy 3252147219Sjkoshy cpu_info.pm_cputype = op_cpu_info.pm_cputype; 3253147219Sjkoshy cpu_info.pm_ncpu = op_cpu_info.pm_ncpu; 3254147219Sjkoshy cpu_info.pm_npmc = op_cpu_info.pm_npmc; 3255147219Sjkoshy cpu_info.pm_nclass = op_cpu_info.pm_nclass; 3256147219Sjkoshy for (n = 0; n < cpu_info.pm_nclass; n++) 3257147219Sjkoshy cpu_info.pm_classes[n] = op_cpu_info.pm_classes[n]; 3258147219Sjkoshy 3259185363Sjkoshy pmc_class_table = malloc(PMC_CLASS_TABLE_SIZE * 3260185363Sjkoshy sizeof(struct pmc_class_descr *)); 3261185363Sjkoshy 3262185363Sjkoshy if (pmc_class_table == NULL) 3263185363Sjkoshy return (-1); 3264185363Sjkoshy 3265198433Sjkoshy for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) 3266198433Sjkoshy pmc_class_table[n] = NULL; 3267185363Sjkoshy 3268185363Sjkoshy /* 3269233628Sfabient * Get soft events list. 3270233628Sfabient */ 3271233628Sfabient soft_event_info.pm_class = PMC_CLASS_SOFT; 3272233628Sfabient if (PMC_CALL(GETDYNEVENTINFO, &soft_event_info) < 0) 3273233628Sfabient return (pmc_syscall = -1); 3274233628Sfabient 3275233628Sfabient /* Map soft events to static list. */ 3276233628Sfabient for (n = 0; n < soft_event_info.pm_nevent; n++) { 3277233628Sfabient soft_event_table[n].pm_ev_name = 3278233628Sfabient soft_event_info.pm_events[n].pm_ev_name; 3279233628Sfabient soft_event_table[n].pm_ev_code = 3280233628Sfabient soft_event_info.pm_events[n].pm_ev_code; 3281233628Sfabient } 3282233628Sfabient soft_class_table_descr.pm_evc_event_table_size = \ 3283233628Sfabient soft_event_info.pm_nevent; 3284233628Sfabient soft_class_table_descr.pm_evc_event_table = \ 3285233628Sfabient soft_event_table; 3286233628Sfabient 3287233628Sfabient /* 3288185363Sjkoshy * Fill in the class table. 3289185363Sjkoshy */ 3290185363Sjkoshy n = 0; 3291233628Sfabient 3292233628Sfabient /* Fill soft events information. */ 3293233628Sfabient pmc_class_table[n++] = &soft_class_table_descr; 3294185363Sjkoshy#if defined(__amd64__) || defined(__i386__) 3295233628Sfabient if (cpu_info.pm_cputype != PMC_CPU_GENERIC) 3296233628Sfabient pmc_class_table[n++] = &tsc_class_table_descr; 3297198433Sjkoshy 3298198433Sjkoshy /* 3299198433Sjkoshy * Check if this CPU has fixed function counters. 3300198433Sjkoshy */ 3301198433Sjkoshy cpu_has_iaf_counters = 0; 3302198433Sjkoshy for (t = 0; t < cpu_info.pm_nclass; t++) 3303212224Sfabient if (cpu_info.pm_classes[t].pm_class == PMC_CLASS_IAF && 3304212224Sfabient cpu_info.pm_classes[t].pm_num > 0) 3305198433Sjkoshy cpu_has_iaf_counters = 1; 3306185363Sjkoshy#endif 3307185363Sjkoshy 3308183725Sjkoshy#define PMC_MDEP_INIT(C) do { \ 3309183725Sjkoshy pmc_mdep_event_aliases = C##_aliases; \ 3310183725Sjkoshy pmc_mdep_class_list = C##_pmc_classes; \ 3311183725Sjkoshy pmc_mdep_class_list_size = \ 3312183725Sjkoshy PMC_TABLE_SIZE(C##_pmc_classes); \ 3313183725Sjkoshy } while (0) 3314183725Sjkoshy 3315198433Sjkoshy#define PMC_MDEP_INIT_INTEL_V2(C) do { \ 3316198433Sjkoshy PMC_MDEP_INIT(C); \ 3317212224Sfabient pmc_class_table[n++] = &iaf_class_table_descr; \ 3318212224Sfabient if (!cpu_has_iaf_counters) \ 3319198433Sjkoshy pmc_mdep_event_aliases = \ 3320198433Sjkoshy C##_aliases_without_iaf; \ 3321198433Sjkoshy pmc_class_table[n] = &C##_class_table_descr; \ 3322198433Sjkoshy } while (0) 3323198433Sjkoshy 3324183725Sjkoshy /* Configure the event name parser. */ 3325145256Sjkoshy switch (cpu_info.pm_cputype) { 3326145340Smarcel#if defined(__i386__) 3327145256Sjkoshy case PMC_CPU_AMD_K7: 3328183725Sjkoshy PMC_MDEP_INIT(k7); 3329185363Sjkoshy pmc_class_table[n] = &k7_class_table_descr; 3330145256Sjkoshy break; 3331145256Sjkoshy case PMC_CPU_INTEL_P5: 3332183725Sjkoshy PMC_MDEP_INIT(p5); 3333185363Sjkoshy pmc_class_table[n] = &p5_class_table_descr; 3334145256Sjkoshy break; 3335145256Sjkoshy case PMC_CPU_INTEL_P6: /* P6 ... Pentium M CPUs have */ 3336145256Sjkoshy case PMC_CPU_INTEL_PII: /* similar PMCs. */ 3337145256Sjkoshy case PMC_CPU_INTEL_PIII: 3338145256Sjkoshy case PMC_CPU_INTEL_PM: 3339183725Sjkoshy PMC_MDEP_INIT(p6); 3340185363Sjkoshy pmc_class_table[n] = &p6_class_table_descr; 3341145256Sjkoshy break; 3342147759Sjkoshy#endif 3343147759Sjkoshy#if defined(__amd64__) || defined(__i386__) 3344183725Sjkoshy case PMC_CPU_AMD_K8: 3345183725Sjkoshy PMC_MDEP_INIT(k8); 3346185363Sjkoshy pmc_class_table[n] = &k8_class_table_descr; 3347183725Sjkoshy break; 3348185363Sjkoshy case PMC_CPU_INTEL_ATOM: 3349198433Sjkoshy PMC_MDEP_INIT_INTEL_V2(atom); 3350185363Sjkoshy break; 3351263446Shiren case PMC_CPU_INTEL_ATOM_SILVERMONT: 3352263446Shiren PMC_MDEP_INIT_INTEL_V2(atom_silvermont); 3353263446Shiren break; 3354185363Sjkoshy case PMC_CPU_INTEL_CORE: 3355185363Sjkoshy PMC_MDEP_INIT(core); 3356202157Sjkoshy pmc_class_table[n] = &core_class_table_descr; 3357185363Sjkoshy break; 3358185363Sjkoshy case PMC_CPU_INTEL_CORE2: 3359185585Sjkoshy case PMC_CPU_INTEL_CORE2EXTREME: 3360198433Sjkoshy PMC_MDEP_INIT_INTEL_V2(core2); 3361185363Sjkoshy break; 3362187761Sjeff case PMC_CPU_INTEL_COREI7: 3363206089Sfabient pmc_class_table[n++] = &ucf_class_table_descr; 3364206089Sfabient pmc_class_table[n++] = &corei7uc_class_table_descr; 3365198433Sjkoshy PMC_MDEP_INIT_INTEL_V2(corei7); 3366187761Sjeff break; 3367267062Skib case PMC_CPU_INTEL_NEHALEM_EX: 3368267062Skib PMC_MDEP_INIT_INTEL_V2(nehalem_ex); 3369267062Skib break; 3370248842Ssbruno case PMC_CPU_INTEL_HASWELL: 3371248842Ssbruno pmc_class_table[n++] = &ucf_class_table_descr; 3372248842Ssbruno pmc_class_table[n++] = &haswelluc_class_table_descr; 3373248842Ssbruno PMC_MDEP_INIT_INTEL_V2(haswell); 3374248842Ssbruno break; 3375277177Srrs case PMC_CPU_INTEL_HASWELL_XEON: 3376277177Srrs PMC_MDEP_INIT_INTEL_V2(haswell_xeon); 3377277177Srrs break; 3378291494Srrs case PMC_CPU_INTEL_BROADWELL: 3379291494Srrs pmc_class_table[n++] = &ucf_class_table_descr; 3380291494Srrs pmc_class_table[n++] = &broadwelluc_class_table_descr; 3381291494Srrs PMC_MDEP_INIT_INTEL_V2(broadwell); 3382291494Srrs break; 3383291494Srrs case PMC_CPU_INTEL_BROADWELL_XEON: 3384291494Srrs PMC_MDEP_INIT_INTEL_V2(broadwell_xeon); 3385291494Srrs break; 3386291494Srrs case PMC_CPU_INTEL_SKYLAKE: 3387291494Srrs PMC_MDEP_INIT_INTEL_V2(skylake); 3388291494Srrs break; 3389240164Sfabient case PMC_CPU_INTEL_IVYBRIDGE: 3390240164Sfabient PMC_MDEP_INIT_INTEL_V2(ivybridge); 3391240164Sfabient break; 3392246166Ssbruno case PMC_CPU_INTEL_IVYBRIDGE_XEON: 3393246166Ssbruno PMC_MDEP_INIT_INTEL_V2(ivybridge_xeon); 3394246166Ssbruno break; 3395232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 3396232366Sdavide pmc_class_table[n++] = &ucf_class_table_descr; 3397232366Sdavide pmc_class_table[n++] = &sandybridgeuc_class_table_descr; 3398232366Sdavide PMC_MDEP_INIT_INTEL_V2(sandybridge); 3399232366Sdavide break; 3400241738Ssbruno case PMC_CPU_INTEL_SANDYBRIDGE_XEON: 3401241738Ssbruno PMC_MDEP_INIT_INTEL_V2(sandybridge_xeon); 3402241738Ssbruno break; 3403206089Sfabient case PMC_CPU_INTEL_WESTMERE: 3404206089Sfabient pmc_class_table[n++] = &ucf_class_table_descr; 3405206089Sfabient pmc_class_table[n++] = &westmereuc_class_table_descr; 3406206089Sfabient PMC_MDEP_INIT_INTEL_V2(westmere); 3407206089Sfabient break; 3408267062Skib case PMC_CPU_INTEL_WESTMERE_EX: 3409267062Skib PMC_MDEP_INIT_INTEL_V2(westmere_ex); 3410267062Skib break; 3411145256Sjkoshy case PMC_CPU_INTEL_PIV: 3412183725Sjkoshy PMC_MDEP_INIT(p4); 3413185363Sjkoshy pmc_class_table[n] = &p4_class_table_descr; 3414145256Sjkoshy break; 3415145256Sjkoshy#endif 3416233628Sfabient case PMC_CPU_GENERIC: 3417233628Sfabient PMC_MDEP_INIT(generic); 3418233628Sfabient break; 3419277835Sbr#if defined(__arm__) 3420200928Srpaulo#if defined(__XSCALE__) 3421200928Srpaulo case PMC_CPU_INTEL_XSCALE: 3422200928Srpaulo PMC_MDEP_INIT(xscale); 3423200928Srpaulo pmc_class_table[n] = &xscale_class_table_descr; 3424200928Srpaulo break; 3425200928Srpaulo#endif 3426284218Sbr case PMC_CPU_ARMV7_CORTEX_A8: 3427284218Sbr PMC_MDEP_INIT(cortex_a8); 3428284218Sbr pmc_class_table[n] = &cortex_a8_class_table_descr; 3429277835Sbr break; 3430284218Sbr case PMC_CPU_ARMV7_CORTEX_A9: 3431284218Sbr PMC_MDEP_INIT(cortex_a9); 3432284218Sbr pmc_class_table[n] = &cortex_a9_class_table_descr; 3433284218Sbr break; 3434277835Sbr#endif 3435283112Sbr#if defined(__aarch64__) 3436283112Sbr case PMC_CPU_ARMV8_CORTEX_A53: 3437283112Sbr PMC_MDEP_INIT(cortex_a53); 3438283112Sbr pmc_class_table[n] = &cortex_a53_class_table_descr; 3439283112Sbr break; 3440283112Sbr case PMC_CPU_ARMV8_CORTEX_A57: 3441283112Sbr PMC_MDEP_INIT(cortex_a57); 3442283112Sbr pmc_class_table[n] = &cortex_a57_class_table_descr; 3443283112Sbr break; 3444283112Sbr#endif 3445204635Sgnn#if defined(__mips__) 3446204635Sgnn case PMC_CPU_MIPS_24K: 3447204635Sgnn PMC_MDEP_INIT(mips24k); 3448204635Sgnn pmc_class_table[n] = &mips24k_class_table_descr; 3449204635Sgnn break; 3450281098Sadrian case PMC_CPU_MIPS_74K: 3451281098Sadrian PMC_MDEP_INIT(mips74k); 3452281098Sadrian pmc_class_table[n] = &mips74k_class_table_descr; 3453281098Sadrian break; 3454233335Sgonzo case PMC_CPU_MIPS_OCTEON: 3455233335Sgonzo PMC_MDEP_INIT(octeon); 3456233335Sgonzo pmc_class_table[n] = &octeon_class_table_descr; 3457233335Sgonzo break; 3458204635Sgnn#endif /* __mips__ */ 3459228869Sjhibbits#if defined(__powerpc__) 3460228869Sjhibbits case PMC_CPU_PPC_7450: 3461228869Sjhibbits PMC_MDEP_INIT(ppc7450); 3462228869Sjhibbits pmc_class_table[n] = &ppc7450_class_table_descr; 3463228869Sjhibbits break; 3464261342Sjhibbits case PMC_CPU_PPC_970: 3465261342Sjhibbits PMC_MDEP_INIT(ppc970); 3466261342Sjhibbits pmc_class_table[n] = &ppc970_class_table_descr; 3467261342Sjhibbits break; 3468281713Sjhibbits case PMC_CPU_PPC_E500: 3469281713Sjhibbits PMC_MDEP_INIT(e500); 3470281713Sjhibbits pmc_class_table[n] = &e500_class_table_descr; 3471281713Sjhibbits break; 3472228869Sjhibbits#endif 3473145256Sjkoshy default: 3474145256Sjkoshy /* 3475145256Sjkoshy * Some kind of CPU this version of the library knows nothing 3476145256Sjkoshy * about. This shouldn't happen since the abi version check 3477145256Sjkoshy * should have caught this. 3478145256Sjkoshy */ 3479145256Sjkoshy errno = ENXIO; 3480145256Sjkoshy return (pmc_syscall = -1); 3481145256Sjkoshy } 3482145256Sjkoshy 3483174406Sjkoshy return (0); 3484145256Sjkoshy} 3485145256Sjkoshy 3486147191Sjkoshyconst char * 3487147191Sjkoshypmc_name_of_capability(enum pmc_caps cap) 3488145256Sjkoshy{ 3489147191Sjkoshy int i; 3490145256Sjkoshy 3491147191Sjkoshy /* 3492147191Sjkoshy * 'cap' should have a single bit set and should be in 3493147191Sjkoshy * range. 3494147191Sjkoshy */ 3495147191Sjkoshy if ((cap & (cap - 1)) || cap < PMC_CAP_FIRST || 3496147191Sjkoshy cap > PMC_CAP_LAST) { 3497145256Sjkoshy errno = EINVAL; 3498174406Sjkoshy return (NULL); 3499145256Sjkoshy } 3500145256Sjkoshy 3501147191Sjkoshy i = ffs(cap); 3502174406Sjkoshy return (pmc_capability_names[i - 1]); 3503147191Sjkoshy} 3504145256Sjkoshy 3505147191Sjkoshyconst char * 3506147191Sjkoshypmc_name_of_class(enum pmc_class pc) 3507147191Sjkoshy{ 3508283120Sjhb size_t n; 3509145256Sjkoshy 3510283120Sjhb for (n = 0; n < PMC_TABLE_SIZE(pmc_class_names); n++) 3511283120Sjhb if (pc == pmc_class_names[n].pm_class) 3512283120Sjhb return (pmc_class_names[n].pm_name); 3513283120Sjhb 3514147191Sjkoshy errno = EINVAL; 3515174406Sjkoshy return (NULL); 3516147191Sjkoshy} 3517145256Sjkoshy 3518147191Sjkoshyconst char * 3519147191Sjkoshypmc_name_of_cputype(enum pmc_cputype cp) 3520147191Sjkoshy{ 3521183725Sjkoshy size_t n; 3522183725Sjkoshy 3523183725Sjkoshy for (n = 0; n < PMC_TABLE_SIZE(pmc_cputype_names); n++) 3524183725Sjkoshy if (cp == pmc_cputype_names[n].pm_cputype) 3525183725Sjkoshy return (pmc_cputype_names[n].pm_name); 3526183725Sjkoshy 3527147191Sjkoshy errno = EINVAL; 3528174406Sjkoshy return (NULL); 3529147191Sjkoshy} 3530145256Sjkoshy 3531147191Sjkoshyconst char * 3532147191Sjkoshypmc_name_of_disposition(enum pmc_disp pd) 3533147191Sjkoshy{ 3534147191Sjkoshy if ((int) pd >= PMC_DISP_FIRST && 3535147191Sjkoshy pd <= PMC_DISP_LAST) 3536174406Sjkoshy return (pmc_disposition_names[pd]); 3537145256Sjkoshy 3538147191Sjkoshy errno = EINVAL; 3539174406Sjkoshy return (NULL); 3540147191Sjkoshy} 3541145256Sjkoshy 3542147191Sjkoshyconst char * 3543185363Sjkoshy_pmc_name_of_event(enum pmc_event pe, enum pmc_cputype cpu) 3544147191Sjkoshy{ 3545183725Sjkoshy const struct pmc_event_descr *ev, *evfence; 3546145256Sjkoshy 3547183725Sjkoshy ev = evfence = NULL; 3548185363Sjkoshy if (pe >= PMC_EV_IAF_FIRST && pe <= PMC_EV_IAF_LAST) { 3549185363Sjkoshy ev = iaf_event_table; 3550185363Sjkoshy evfence = iaf_event_table + PMC_EVENT_TABLE_SIZE(iaf); 3551185363Sjkoshy } else if (pe >= PMC_EV_IAP_FIRST && pe <= PMC_EV_IAP_LAST) { 3552185363Sjkoshy switch (cpu) { 3553185363Sjkoshy case PMC_CPU_INTEL_ATOM: 3554185363Sjkoshy ev = atom_event_table; 3555185363Sjkoshy evfence = atom_event_table + PMC_EVENT_TABLE_SIZE(atom); 3556185363Sjkoshy break; 3557263446Shiren case PMC_CPU_INTEL_ATOM_SILVERMONT: 3558263446Shiren ev = atom_silvermont_event_table; 3559263446Shiren evfence = atom_silvermont_event_table + 3560263446Shiren PMC_EVENT_TABLE_SIZE(atom_silvermont); 3561263446Shiren break; 3562185363Sjkoshy case PMC_CPU_INTEL_CORE: 3563185363Sjkoshy ev = core_event_table; 3564185363Sjkoshy evfence = core_event_table + PMC_EVENT_TABLE_SIZE(core); 3565185363Sjkoshy break; 3566185363Sjkoshy case PMC_CPU_INTEL_CORE2: 3567185585Sjkoshy case PMC_CPU_INTEL_CORE2EXTREME: 3568185363Sjkoshy ev = core2_event_table; 3569185363Sjkoshy evfence = core2_event_table + PMC_EVENT_TABLE_SIZE(core2); 3570185363Sjkoshy break; 3571187761Sjeff case PMC_CPU_INTEL_COREI7: 3572187761Sjeff ev = corei7_event_table; 3573187761Sjeff evfence = corei7_event_table + PMC_EVENT_TABLE_SIZE(corei7); 3574187761Sjeff break; 3575267062Skib case PMC_CPU_INTEL_NEHALEM_EX: 3576267062Skib ev = nehalem_ex_event_table; 3577267062Skib evfence = nehalem_ex_event_table + 3578267062Skib PMC_EVENT_TABLE_SIZE(nehalem_ex); 3579267062Skib break; 3580248842Ssbruno case PMC_CPU_INTEL_HASWELL: 3581248842Ssbruno ev = haswell_event_table; 3582248842Ssbruno evfence = haswell_event_table + PMC_EVENT_TABLE_SIZE(haswell); 3583248842Ssbruno break; 3584277177Srrs case PMC_CPU_INTEL_HASWELL_XEON: 3585277177Srrs ev = haswell_xeon_event_table; 3586277177Srrs evfence = haswell_xeon_event_table + PMC_EVENT_TABLE_SIZE(haswell_xeon); 3587277177Srrs break; 3588291494Srrs case PMC_CPU_INTEL_BROADWELL: 3589291494Srrs ev = broadwell_event_table; 3590291494Srrs evfence = broadwell_event_table + PMC_EVENT_TABLE_SIZE(broadwell); 3591291494Srrs break; 3592291494Srrs case PMC_CPU_INTEL_BROADWELL_XEON: 3593291494Srrs ev = broadwell_xeon_event_table; 3594291494Srrs evfence = broadwell_xeon_event_table + PMC_EVENT_TABLE_SIZE(broadwell_xeon); 3595291494Srrs break; 3596291494Srrs case PMC_CPU_INTEL_SKYLAKE: 3597291494Srrs ev = skylake_event_table; 3598291494Srrs evfence = skylake_event_table + PMC_EVENT_TABLE_SIZE(skylake); 3599291494Srrs break; 3600240164Sfabient case PMC_CPU_INTEL_IVYBRIDGE: 3601240164Sfabient ev = ivybridge_event_table; 3602240164Sfabient evfence = ivybridge_event_table + PMC_EVENT_TABLE_SIZE(ivybridge); 3603240164Sfabient break; 3604246166Ssbruno case PMC_CPU_INTEL_IVYBRIDGE_XEON: 3605246166Ssbruno ev = ivybridge_xeon_event_table; 3606246166Ssbruno evfence = ivybridge_xeon_event_table + PMC_EVENT_TABLE_SIZE(ivybridge_xeon); 3607246166Ssbruno break; 3608232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 3609232366Sdavide ev = sandybridge_event_table; 3610232366Sdavide evfence = sandybridge_event_table + PMC_EVENT_TABLE_SIZE(sandybridge); 3611232366Sdavide break; 3612241738Ssbruno case PMC_CPU_INTEL_SANDYBRIDGE_XEON: 3613241738Ssbruno ev = sandybridge_xeon_event_table; 3614241738Ssbruno evfence = sandybridge_xeon_event_table + PMC_EVENT_TABLE_SIZE(sandybridge_xeon); 3615241738Ssbruno break; 3616206089Sfabient case PMC_CPU_INTEL_WESTMERE: 3617206089Sfabient ev = westmere_event_table; 3618206089Sfabient evfence = westmere_event_table + PMC_EVENT_TABLE_SIZE(westmere); 3619206089Sfabient break; 3620267062Skib case PMC_CPU_INTEL_WESTMERE_EX: 3621267062Skib ev = westmere_ex_event_table; 3622267062Skib evfence = westmere_ex_event_table + 3623267062Skib PMC_EVENT_TABLE_SIZE(westmere_ex); 3624267062Skib break; 3625185363Sjkoshy default: /* Unknown CPU type. */ 3626185363Sjkoshy break; 3627185363Sjkoshy } 3628206089Sfabient } else if (pe >= PMC_EV_UCF_FIRST && pe <= PMC_EV_UCF_LAST) { 3629206089Sfabient ev = ucf_event_table; 3630206089Sfabient evfence = ucf_event_table + PMC_EVENT_TABLE_SIZE(ucf); 3631206089Sfabient } else if (pe >= PMC_EV_UCP_FIRST && pe <= PMC_EV_UCP_LAST) { 3632206089Sfabient switch (cpu) { 3633206089Sfabient case PMC_CPU_INTEL_COREI7: 3634206089Sfabient ev = corei7uc_event_table; 3635206089Sfabient evfence = corei7uc_event_table + PMC_EVENT_TABLE_SIZE(corei7uc); 3636206089Sfabient break; 3637232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 3638232366Sdavide ev = sandybridgeuc_event_table; 3639232366Sdavide evfence = sandybridgeuc_event_table + PMC_EVENT_TABLE_SIZE(sandybridgeuc); 3640232366Sdavide break; 3641206089Sfabient case PMC_CPU_INTEL_WESTMERE: 3642206089Sfabient ev = westmereuc_event_table; 3643206089Sfabient evfence = westmereuc_event_table + PMC_EVENT_TABLE_SIZE(westmereuc); 3644206089Sfabient break; 3645206089Sfabient default: /* Unknown CPU type. */ 3646206089Sfabient break; 3647206089Sfabient } 3648206089Sfabient } else if (pe >= PMC_EV_K7_FIRST && pe <= PMC_EV_K7_LAST) { 3649183725Sjkoshy ev = k7_event_table; 3650183725Sjkoshy evfence = k7_event_table + PMC_EVENT_TABLE_SIZE(k7); 3651183725Sjkoshy } else if (pe >= PMC_EV_K8_FIRST && pe <= PMC_EV_K8_LAST) { 3652183725Sjkoshy ev = k8_event_table; 3653183725Sjkoshy evfence = k8_event_table + PMC_EVENT_TABLE_SIZE(k8); 3654183725Sjkoshy } else if (pe >= PMC_EV_P4_FIRST && pe <= PMC_EV_P4_LAST) { 3655183725Sjkoshy ev = p4_event_table; 3656183725Sjkoshy evfence = p4_event_table + PMC_EVENT_TABLE_SIZE(p4); 3657183725Sjkoshy } else if (pe >= PMC_EV_P5_FIRST && pe <= PMC_EV_P5_LAST) { 3658183725Sjkoshy ev = p5_event_table; 3659183725Sjkoshy evfence = p5_event_table + PMC_EVENT_TABLE_SIZE(p5); 3660183725Sjkoshy } else if (pe >= PMC_EV_P6_FIRST && pe <= PMC_EV_P6_LAST) { 3661183725Sjkoshy ev = p6_event_table; 3662183725Sjkoshy evfence = p6_event_table + PMC_EVENT_TABLE_SIZE(p6); 3663200928Srpaulo } else if (pe >= PMC_EV_XSCALE_FIRST && pe <= PMC_EV_XSCALE_LAST) { 3664200928Srpaulo ev = xscale_event_table; 3665200928Srpaulo evfence = xscale_event_table + PMC_EVENT_TABLE_SIZE(xscale); 3666277835Sbr } else if (pe >= PMC_EV_ARMV7_FIRST && pe <= PMC_EV_ARMV7_LAST) { 3667284218Sbr switch (cpu) { 3668284218Sbr case PMC_CPU_ARMV7_CORTEX_A8: 3669284218Sbr ev = cortex_a8_event_table; 3670284218Sbr evfence = cortex_a8_event_table + PMC_EVENT_TABLE_SIZE(cortex_a8); 3671284218Sbr break; 3672284218Sbr case PMC_CPU_ARMV7_CORTEX_A9: 3673284218Sbr ev = cortex_a9_event_table; 3674284218Sbr evfence = cortex_a9_event_table + PMC_EVENT_TABLE_SIZE(cortex_a9); 3675284218Sbr break; 3676284218Sbr default: /* Unknown CPU type. */ 3677284218Sbr break; 3678284218Sbr } 3679283112Sbr } else if (pe >= PMC_EV_ARMV8_FIRST && pe <= PMC_EV_ARMV8_LAST) { 3680283112Sbr switch (cpu) { 3681283112Sbr case PMC_CPU_ARMV8_CORTEX_A53: 3682283112Sbr ev = cortex_a53_event_table; 3683283112Sbr evfence = cortex_a53_event_table + PMC_EVENT_TABLE_SIZE(cortex_a53); 3684283112Sbr break; 3685283112Sbr case PMC_CPU_ARMV8_CORTEX_A57: 3686283112Sbr ev = cortex_a57_event_table; 3687283112Sbr evfence = cortex_a57_event_table + PMC_EVENT_TABLE_SIZE(cortex_a57); 3688283112Sbr break; 3689283112Sbr default: /* Unknown CPU type. */ 3690283112Sbr break; 3691283112Sbr } 3692204635Sgnn } else if (pe >= PMC_EV_MIPS24K_FIRST && pe <= PMC_EV_MIPS24K_LAST) { 3693204635Sgnn ev = mips24k_event_table; 3694233628Sfabient evfence = mips24k_event_table + PMC_EVENT_TABLE_SIZE(mips24k); 3695281098Sadrian } else if (pe >= PMC_EV_MIPS74K_FIRST && pe <= PMC_EV_MIPS74K_LAST) { 3696281098Sadrian ev = mips74k_event_table; 3697281098Sadrian evfence = mips74k_event_table + PMC_EVENT_TABLE_SIZE(mips74k); 3698233335Sgonzo } else if (pe >= PMC_EV_OCTEON_FIRST && pe <= PMC_EV_OCTEON_LAST) { 3699233335Sgonzo ev = octeon_event_table; 3700233335Sgonzo evfence = octeon_event_table + PMC_EVENT_TABLE_SIZE(octeon); 3701228869Sjhibbits } else if (pe >= PMC_EV_PPC7450_FIRST && pe <= PMC_EV_PPC7450_LAST) { 3702228869Sjhibbits ev = ppc7450_event_table; 3703233628Sfabient evfence = ppc7450_event_table + PMC_EVENT_TABLE_SIZE(ppc7450); 3704261342Sjhibbits } else if (pe >= PMC_EV_PPC970_FIRST && pe <= PMC_EV_PPC970_LAST) { 3705261342Sjhibbits ev = ppc970_event_table; 3706261342Sjhibbits evfence = ppc970_event_table + PMC_EVENT_TABLE_SIZE(ppc970); 3707281713Sjhibbits } else if (pe >= PMC_EV_E500_FIRST && pe <= PMC_EV_E500_LAST) { 3708281713Sjhibbits ev = e500_event_table; 3709281713Sjhibbits evfence = e500_event_table + PMC_EVENT_TABLE_SIZE(e500); 3710183725Sjkoshy } else if (pe == PMC_EV_TSC_TSC) { 3711183725Sjkoshy ev = tsc_event_table; 3712183725Sjkoshy evfence = tsc_event_table + PMC_EVENT_TABLE_SIZE(tsc); 3713242622Sdim } else if ((int)pe >= PMC_EV_SOFT_FIRST && (int)pe <= PMC_EV_SOFT_LAST) { 3714233628Sfabient ev = soft_event_table; 3715233628Sfabient evfence = soft_event_table + soft_event_info.pm_nevent; 3716183725Sjkoshy } 3717183725Sjkoshy 3718183725Sjkoshy for (; ev != evfence; ev++) 3719183725Sjkoshy if (pe == ev->pm_ev_code) 3720183725Sjkoshy return (ev->pm_ev_name); 3721183725Sjkoshy 3722185363Sjkoshy return (NULL); 3723185363Sjkoshy} 3724185363Sjkoshy 3725185363Sjkoshyconst char * 3726185363Sjkoshypmc_name_of_event(enum pmc_event pe) 3727185363Sjkoshy{ 3728185363Sjkoshy const char *n; 3729185363Sjkoshy 3730185363Sjkoshy if ((n = _pmc_name_of_event(pe, cpu_info.pm_cputype)) != NULL) 3731185363Sjkoshy return (n); 3732185363Sjkoshy 3733147191Sjkoshy errno = EINVAL; 3734174406Sjkoshy return (NULL); 3735147191Sjkoshy} 3736145256Sjkoshy 3737147191Sjkoshyconst char * 3738147191Sjkoshypmc_name_of_mode(enum pmc_mode pm) 3739147191Sjkoshy{ 3740147191Sjkoshy if ((int) pm >= PMC_MODE_FIRST && 3741147191Sjkoshy pm <= PMC_MODE_LAST) 3742174406Sjkoshy return (pmc_mode_names[pm]); 3743145256Sjkoshy 3744147191Sjkoshy errno = EINVAL; 3745174406Sjkoshy return (NULL); 3746147191Sjkoshy} 3747145256Sjkoshy 3748147191Sjkoshyconst char * 3749147191Sjkoshypmc_name_of_state(enum pmc_state ps) 3750147191Sjkoshy{ 3751147191Sjkoshy if ((int) ps >= PMC_STATE_FIRST && 3752147191Sjkoshy ps <= PMC_STATE_LAST) 3753174406Sjkoshy return (pmc_state_names[ps]); 3754145256Sjkoshy 3755147191Sjkoshy errno = EINVAL; 3756174406Sjkoshy return (NULL); 3757145256Sjkoshy} 3758145256Sjkoshy 3759145256Sjkoshyint 3760147191Sjkoshypmc_ncpu(void) 3761145256Sjkoshy{ 3762147191Sjkoshy if (pmc_syscall == -1) { 3763147191Sjkoshy errno = ENXIO; 3764174406Sjkoshy return (-1); 3765147191Sjkoshy } 3766145256Sjkoshy 3767174406Sjkoshy return (cpu_info.pm_ncpu); 3768145256Sjkoshy} 3769145256Sjkoshy 3770145256Sjkoshyint 3771147191Sjkoshypmc_npmc(int cpu) 3772145256Sjkoshy{ 3773147191Sjkoshy if (pmc_syscall == -1) { 3774147191Sjkoshy errno = ENXIO; 3775174406Sjkoshy return (-1); 3776147191Sjkoshy } 3777145256Sjkoshy 3778147191Sjkoshy if (cpu < 0 || cpu >= (int) cpu_info.pm_ncpu) { 3779147191Sjkoshy errno = EINVAL; 3780174406Sjkoshy return (-1); 3781147191Sjkoshy } 3782145256Sjkoshy 3783174406Sjkoshy return (cpu_info.pm_npmc); 3784145256Sjkoshy} 3785145256Sjkoshy 3786145256Sjkoshyint 3787147191Sjkoshypmc_pmcinfo(int cpu, struct pmc_pmcinfo **ppmci) 3788145256Sjkoshy{ 3789147191Sjkoshy int nbytes, npmc; 3790147191Sjkoshy struct pmc_op_getpmcinfo *pmci; 3791145256Sjkoshy 3792147191Sjkoshy if ((npmc = pmc_npmc(cpu)) < 0) 3793174406Sjkoshy return (-1); 3794145256Sjkoshy 3795147191Sjkoshy nbytes = sizeof(struct pmc_op_getpmcinfo) + 3796147191Sjkoshy npmc * sizeof(struct pmc_info); 3797145256Sjkoshy 3798147191Sjkoshy if ((pmci = calloc(1, nbytes)) == NULL) 3799174406Sjkoshy return (-1); 3800145256Sjkoshy 3801147191Sjkoshy pmci->pm_cpu = cpu; 3802145256Sjkoshy 3803147191Sjkoshy if (PMC_CALL(GETPMCINFO, pmci) < 0) { 3804147191Sjkoshy free(pmci); 3805174406Sjkoshy return (-1); 3806147191Sjkoshy } 3807145256Sjkoshy 3808147191Sjkoshy /* kernel<->library, library<->userland interfaces are identical */ 3809147191Sjkoshy *ppmci = (struct pmc_pmcinfo *) pmci; 3810174406Sjkoshy return (0); 3811145256Sjkoshy} 3812145256Sjkoshy 3813145256Sjkoshyint 3814145256Sjkoshypmc_read(pmc_id_t pmc, pmc_value_t *value) 3815145256Sjkoshy{ 3816145256Sjkoshy struct pmc_op_pmcrw pmc_read_op; 3817145256Sjkoshy 3818145256Sjkoshy pmc_read_op.pm_pmcid = pmc; 3819145256Sjkoshy pmc_read_op.pm_flags = PMC_F_OLDVALUE; 3820145256Sjkoshy pmc_read_op.pm_value = -1; 3821145256Sjkoshy 3822145256Sjkoshy if (PMC_CALL(PMCRW, &pmc_read_op) < 0) 3823174406Sjkoshy return (-1); 3824145256Sjkoshy 3825145256Sjkoshy *value = pmc_read_op.pm_value; 3826174406Sjkoshy return (0); 3827145256Sjkoshy} 3828145256Sjkoshy 3829145256Sjkoshyint 3830147191Sjkoshypmc_release(pmc_id_t pmc) 3831145256Sjkoshy{ 3832147191Sjkoshy struct pmc_op_simple pmc_release_args; 3833145256Sjkoshy 3834147191Sjkoshy pmc_release_args.pm_pmcid = pmc; 3835174406Sjkoshy return (PMC_CALL(PMCRELEASE, &pmc_release_args)); 3836145256Sjkoshy} 3837145256Sjkoshy 3838145256Sjkoshyint 3839145256Sjkoshypmc_rw(pmc_id_t pmc, pmc_value_t newvalue, pmc_value_t *oldvaluep) 3840145256Sjkoshy{ 3841145256Sjkoshy struct pmc_op_pmcrw pmc_rw_op; 3842145256Sjkoshy 3843145256Sjkoshy pmc_rw_op.pm_pmcid = pmc; 3844145256Sjkoshy pmc_rw_op.pm_flags = PMC_F_NEWVALUE | PMC_F_OLDVALUE; 3845145256Sjkoshy pmc_rw_op.pm_value = newvalue; 3846145256Sjkoshy 3847145256Sjkoshy if (PMC_CALL(PMCRW, &pmc_rw_op) < 0) 3848174406Sjkoshy return (-1); 3849145256Sjkoshy 3850145256Sjkoshy *oldvaluep = pmc_rw_op.pm_value; 3851174406Sjkoshy return (0); 3852145256Sjkoshy} 3853145256Sjkoshy 3854145256Sjkoshyint 3855145256Sjkoshypmc_set(pmc_id_t pmc, pmc_value_t value) 3856145256Sjkoshy{ 3857145256Sjkoshy struct pmc_op_pmcsetcount sc; 3858145256Sjkoshy 3859145256Sjkoshy sc.pm_pmcid = pmc; 3860145256Sjkoshy sc.pm_count = value; 3861145256Sjkoshy 3862145256Sjkoshy if (PMC_CALL(PMCSETCOUNT, &sc) < 0) 3863174406Sjkoshy return (-1); 3864174406Sjkoshy return (0); 3865145256Sjkoshy} 3866145256Sjkoshy 3867145256Sjkoshyint 3868147191Sjkoshypmc_start(pmc_id_t pmc) 3869145256Sjkoshy{ 3870147191Sjkoshy struct pmc_op_simple pmc_start_args; 3871145256Sjkoshy 3872147191Sjkoshy pmc_start_args.pm_pmcid = pmc; 3873174406Sjkoshy return (PMC_CALL(PMCSTART, &pmc_start_args)); 3874145256Sjkoshy} 3875145256Sjkoshy 3876145256Sjkoshyint 3877147191Sjkoshypmc_stop(pmc_id_t pmc) 3878145256Sjkoshy{ 3879147191Sjkoshy struct pmc_op_simple pmc_stop_args; 3880145256Sjkoshy 3881147191Sjkoshy pmc_stop_args.pm_pmcid = pmc; 3882174406Sjkoshy return (PMC_CALL(PMCSTOP, &pmc_stop_args)); 3883145256Sjkoshy} 3884145256Sjkoshy 3885145256Sjkoshyint 3886145774Sjkoshypmc_width(pmc_id_t pmcid, uint32_t *width) 3887145774Sjkoshy{ 3888145774Sjkoshy unsigned int i; 3889145774Sjkoshy enum pmc_class cl; 3890145774Sjkoshy 3891145774Sjkoshy cl = PMC_ID_TO_CLASS(pmcid); 3892145774Sjkoshy for (i = 0; i < cpu_info.pm_nclass; i++) 3893145774Sjkoshy if (cpu_info.pm_classes[i].pm_class == cl) { 3894145774Sjkoshy *width = cpu_info.pm_classes[i].pm_width; 3895174406Sjkoshy return (0); 3896145774Sjkoshy } 3897177107Sjkoshy errno = EINVAL; 3898177107Sjkoshy return (-1); 3899145774Sjkoshy} 3900145774Sjkoshy 3901145774Sjkoshyint 3902147191Sjkoshypmc_write(pmc_id_t pmc, pmc_value_t value) 3903145774Sjkoshy{ 3904147191Sjkoshy struct pmc_op_pmcrw pmc_write_op; 3905145774Sjkoshy 3906147191Sjkoshy pmc_write_op.pm_pmcid = pmc; 3907147191Sjkoshy pmc_write_op.pm_flags = PMC_F_NEWVALUE; 3908147191Sjkoshy pmc_write_op.pm_value = value; 3909174406Sjkoshy return (PMC_CALL(PMCRW, &pmc_write_op)); 3910145256Sjkoshy} 3911145256Sjkoshy 3912145256Sjkoshyint 3913147191Sjkoshypmc_writelog(uint32_t userdata) 3914145256Sjkoshy{ 3915147191Sjkoshy struct pmc_op_writelog wl; 3916145256Sjkoshy 3917147191Sjkoshy wl.pm_userdata = userdata; 3918174406Sjkoshy return (PMC_CALL(WRITELOG, &wl)); 3919145256Sjkoshy} 3920