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: stable/11/lib/libpmc/libpmc.c 339767 2018-10-26 05:12:56Z mmacy $"); 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); 64339767Smmacystatic int f17h_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 65339767Smmacy struct pmc_op_pmcallocate *_pmc_config); 66147759Sjkoshystatic int p4_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 67147759Sjkoshy struct pmc_op_pmcallocate *_pmc_config); 68147191Sjkoshy#endif 69147191Sjkoshy#if defined(__i386__) 70145256Sjkoshystatic int p5_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 71145256Sjkoshy struct pmc_op_pmcallocate *_pmc_config); 72147191Sjkoshystatic int p6_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 73145256Sjkoshy struct pmc_op_pmcallocate *_pmc_config); 74145256Sjkoshy#endif 75183725Sjkoshy#if defined(__amd64__) || defined(__i386__) 76183725Sjkoshystatic int tsc_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 77183725Sjkoshy struct pmc_op_pmcallocate *_pmc_config); 78183725Sjkoshy#endif 79277835Sbr#if defined(__arm__) 80200928Srpaulo#if defined(__XSCALE__) 81200928Srpaulostatic int xscale_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 82200928Srpaulo struct pmc_op_pmcallocate *_pmc_config); 83200928Srpaulo#endif 84277835Sbrstatic int armv7_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 85277835Sbr struct pmc_op_pmcallocate *_pmc_config); 86277835Sbr#endif 87283112Sbr#if defined(__aarch64__) 88283112Sbrstatic int arm64_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 89283112Sbr struct pmc_op_pmcallocate *_pmc_config); 90283112Sbr#endif 91204635Sgnn#if defined(__mips__) 92233320Sgonzostatic int mips_allocate_pmc(enum pmc_event _pe, char* ctrspec, 93204635Sgnn struct pmc_op_pmcallocate *_pmc_config); 94204635Sgnn#endif /* __mips__ */ 95233628Sfabientstatic int soft_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 96233628Sfabient struct pmc_op_pmcallocate *_pmc_config); 97204635Sgnn 98228869Sjhibbits#if defined(__powerpc__) 99261342Sjhibbitsstatic int powerpc_allocate_pmc(enum pmc_event _pe, char* ctrspec, 100228869Sjhibbits struct pmc_op_pmcallocate *_pmc_config); 101228869Sjhibbits#endif /* __powerpc__ */ 102204635Sgnn 103145256Sjkoshy#define PMC_CALL(cmd, params) \ 104145256Sjkoshy syscall(pmc_syscall, PMC_OP_##cmd, (params)) 105145256Sjkoshy 106145256Sjkoshy/* 107145256Sjkoshy * Event aliases provide a way for the user to ask for generic events 108145256Sjkoshy * like "cache-misses", or "instructions-retired". These aliases are 109145256Sjkoshy * mapped to the appropriate canonical event descriptions using a 110145256Sjkoshy * lookup table. 111145256Sjkoshy */ 112145256Sjkoshystruct pmc_event_alias { 113145256Sjkoshy const char *pm_alias; 114145256Sjkoshy const char *pm_spec; 115145256Sjkoshy}; 116145256Sjkoshy 117145256Sjkoshystatic const struct pmc_event_alias *pmc_mdep_event_aliases; 118145256Sjkoshy 119145256Sjkoshy/* 120183725Sjkoshy * The pmc_event_descr structure maps symbolic names known to the user 121145256Sjkoshy * to integer codes used by the PMC KLD. 122145256Sjkoshy */ 123145256Sjkoshystruct pmc_event_descr { 124145256Sjkoshy const char *pm_ev_name; 125145256Sjkoshy enum pmc_event pm_ev_code; 126145256Sjkoshy}; 127145256Sjkoshy 128183725Sjkoshy/* 129183725Sjkoshy * The pmc_class_descr structure maps class name prefixes for 130183725Sjkoshy * event names to event tables and other PMC class data. 131183725Sjkoshy */ 132183725Sjkoshystruct pmc_class_descr { 133183725Sjkoshy const char *pm_evc_name; 134183725Sjkoshy size_t pm_evc_name_size; 135183725Sjkoshy enum pmc_class pm_evc_class; 136183725Sjkoshy const struct pmc_event_descr *pm_evc_event_table; 137183725Sjkoshy size_t pm_evc_event_table_size; 138183725Sjkoshy int (*pm_evc_allocate_pmc)(enum pmc_event _pe, 139183725Sjkoshy char *_ctrspec, struct pmc_op_pmcallocate *_pa); 140183725Sjkoshy}; 141183725Sjkoshy 142183725Sjkoshy#define PMC_TABLE_SIZE(N) (sizeof(N)/sizeof(N[0])) 143183725Sjkoshy#define PMC_EVENT_TABLE_SIZE(N) PMC_TABLE_SIZE(N##_event_table) 144183725Sjkoshy 145183725Sjkoshy#undef __PMC_EV 146183725Sjkoshy#define __PMC_EV(C,N) { #N, PMC_EV_ ## C ## _ ## N }, 147183725Sjkoshy 148183725Sjkoshy/* 149185363Sjkoshy * PMC_CLASSDEP_TABLE(NAME, CLASS) 150183725Sjkoshy * 151185363Sjkoshy * Define a table mapping event names and aliases to HWPMC event IDs. 152183725Sjkoshy */ 153185363Sjkoshy#define PMC_CLASSDEP_TABLE(N, C) \ 154183725Sjkoshy static const struct pmc_event_descr N##_event_table[] = \ 155183725Sjkoshy { \ 156183725Sjkoshy __PMC_EV_##C() \ 157185363Sjkoshy } 158185363Sjkoshy 159185363SjkoshyPMC_CLASSDEP_TABLE(iaf, IAF); 160185363SjkoshyPMC_CLASSDEP_TABLE(k7, K7); 161185363SjkoshyPMC_CLASSDEP_TABLE(k8, K8); 162339767SmmacyPMC_CLASSDEP_TABLE(f17h, F17H); 163185363SjkoshyPMC_CLASSDEP_TABLE(p4, P4); 164185363SjkoshyPMC_CLASSDEP_TABLE(p5, P5); 165185363SjkoshyPMC_CLASSDEP_TABLE(p6, P6); 166200928SrpauloPMC_CLASSDEP_TABLE(xscale, XSCALE); 167277835SbrPMC_CLASSDEP_TABLE(armv7, ARMV7); 168283112SbrPMC_CLASSDEP_TABLE(armv8, ARMV8); 169204635SgnnPMC_CLASSDEP_TABLE(mips24k, MIPS24K); 170281098SadrianPMC_CLASSDEP_TABLE(mips74k, MIPS74K); 171233335SgonzoPMC_CLASSDEP_TABLE(octeon, OCTEON); 172206089SfabientPMC_CLASSDEP_TABLE(ucf, UCF); 173228869SjhibbitsPMC_CLASSDEP_TABLE(ppc7450, PPC7450); 174261342SjhibbitsPMC_CLASSDEP_TABLE(ppc970, PPC970); 175281713SjhibbitsPMC_CLASSDEP_TABLE(e500, E500); 176185363Sjkoshy 177233628Sfabientstatic struct pmc_event_descr soft_event_table[PMC_EV_DYN_COUNT]; 178233628Sfabient 179185363Sjkoshy#undef __PMC_EV_ALIAS 180185363Sjkoshy#define __PMC_EV_ALIAS(N,CODE) { N, PMC_EV_##CODE }, 181185363Sjkoshy 182185363Sjkoshystatic const struct pmc_event_descr atom_event_table[] = 183185363Sjkoshy{ 184185363Sjkoshy __PMC_EV_ALIAS_ATOM() 185185363Sjkoshy}; 186185363Sjkoshy 187263446Shirenstatic const struct pmc_event_descr atom_silvermont_event_table[] = 188263446Shiren{ 189263446Shiren __PMC_EV_ALIAS_ATOM_SILVERMONT() 190263446Shiren}; 191263446Shiren 192185363Sjkoshystatic const struct pmc_event_descr core_event_table[] = 193185363Sjkoshy{ 194185363Sjkoshy __PMC_EV_ALIAS_CORE() 195185363Sjkoshy}; 196185363Sjkoshy 197185363Sjkoshy 198185363Sjkoshystatic const struct pmc_event_descr core2_event_table[] = 199185363Sjkoshy{ 200185363Sjkoshy __PMC_EV_ALIAS_CORE2() 201185363Sjkoshy}; 202185363Sjkoshy 203187761Sjeffstatic const struct pmc_event_descr corei7_event_table[] = 204187761Sjeff{ 205187761Sjeff __PMC_EV_ALIAS_COREI7() 206187761Sjeff}; 207187761Sjeff 208267062Skibstatic const struct pmc_event_descr nehalem_ex_event_table[] = 209267062Skib{ 210267062Skib __PMC_EV_ALIAS_COREI7() 211267062Skib}; 212267062Skib 213248842Ssbrunostatic const struct pmc_event_descr haswell_event_table[] = 214248842Ssbruno{ 215248842Ssbruno __PMC_EV_ALIAS_HASWELL() 216248842Ssbruno}; 217248842Ssbruno 218277177Srrsstatic const struct pmc_event_descr haswell_xeon_event_table[] = 219277177Srrs{ 220277177Srrs __PMC_EV_ALIAS_HASWELL_XEON() 221277177Srrs}; 222277177Srrs 223291494Srrsstatic const struct pmc_event_descr broadwell_event_table[] = 224291494Srrs{ 225291494Srrs __PMC_EV_ALIAS_BROADWELL() 226291494Srrs}; 227277177Srrs 228291494Srrsstatic const struct pmc_event_descr broadwell_xeon_event_table[] = 229291494Srrs{ 230291494Srrs __PMC_EV_ALIAS_BROADWELL_XEON() 231291494Srrs}; 232291494Srrs 233291494Srrsstatic const struct pmc_event_descr skylake_event_table[] = 234291494Srrs{ 235291494Srrs __PMC_EV_ALIAS_SKYLAKE() 236291494Srrs}; 237291494Srrs 238323799Skibstatic const struct pmc_event_descr skylake_xeon_event_table[] = 239323799Skib{ 240323799Skib __PMC_EV_ALIAS_SKYLAKE_XEON() 241323799Skib}; 242323799Skib 243240164Sfabientstatic const struct pmc_event_descr ivybridge_event_table[] = 244240164Sfabient{ 245240164Sfabient __PMC_EV_ALIAS_IVYBRIDGE() 246240164Sfabient}; 247240164Sfabient 248246166Ssbrunostatic const struct pmc_event_descr ivybridge_xeon_event_table[] = 249246166Ssbruno{ 250246166Ssbruno __PMC_EV_ALIAS_IVYBRIDGE_XEON() 251246166Ssbruno}; 252246166Ssbruno 253232366Sdavidestatic const struct pmc_event_descr sandybridge_event_table[] = 254232366Sdavide{ 255232366Sdavide __PMC_EV_ALIAS_SANDYBRIDGE() 256232366Sdavide}; 257232366Sdavide 258241738Ssbrunostatic const struct pmc_event_descr sandybridge_xeon_event_table[] = 259241738Ssbruno{ 260241738Ssbruno __PMC_EV_ALIAS_SANDYBRIDGE_XEON() 261241738Ssbruno}; 262241738Ssbruno 263206089Sfabientstatic const struct pmc_event_descr westmere_event_table[] = 264206089Sfabient{ 265206089Sfabient __PMC_EV_ALIAS_WESTMERE() 266206089Sfabient}; 267206089Sfabient 268267062Skibstatic const struct pmc_event_descr westmere_ex_event_table[] = 269267062Skib{ 270267062Skib __PMC_EV_ALIAS_WESTMERE() 271267062Skib}; 272267062Skib 273206089Sfabientstatic const struct pmc_event_descr corei7uc_event_table[] = 274206089Sfabient{ 275206089Sfabient __PMC_EV_ALIAS_COREI7UC() 276206089Sfabient}; 277206089Sfabient 278248842Ssbrunostatic const struct pmc_event_descr haswelluc_event_table[] = 279248842Ssbruno{ 280248842Ssbruno __PMC_EV_ALIAS_HASWELLUC() 281248842Ssbruno}; 282248842Ssbruno 283291494Srrsstatic const struct pmc_event_descr broadwelluc_event_table[] = 284291494Srrs{ 285291494Srrs __PMC_EV_ALIAS_BROADWELLUC() 286291494Srrs}; 287291494Srrs 288232366Sdavidestatic const struct pmc_event_descr sandybridgeuc_event_table[] = 289232366Sdavide{ 290232366Sdavide __PMC_EV_ALIAS_SANDYBRIDGEUC() 291232366Sdavide}; 292232366Sdavide 293206089Sfabientstatic const struct pmc_event_descr westmereuc_event_table[] = 294206089Sfabient{ 295206089Sfabient __PMC_EV_ALIAS_WESTMEREUC() 296206089Sfabient}; 297206089Sfabient 298284218Sbrstatic const struct pmc_event_descr cortex_a8_event_table[] = 299284218Sbr{ 300284218Sbr __PMC_EV_ALIAS_ARMV7_CORTEX_A8() 301284218Sbr}; 302284218Sbr 303284218Sbrstatic const struct pmc_event_descr cortex_a9_event_table[] = 304284218Sbr{ 305284218Sbr __PMC_EV_ALIAS_ARMV7_CORTEX_A9() 306284218Sbr}; 307284218Sbr 308283112Sbrstatic const struct pmc_event_descr cortex_a53_event_table[] = 309283112Sbr{ 310283112Sbr __PMC_EV_ALIAS_ARMV8_CORTEX_A53() 311283112Sbr}; 312283112Sbr 313283112Sbrstatic const struct pmc_event_descr cortex_a57_event_table[] = 314283112Sbr{ 315283112Sbr __PMC_EV_ALIAS_ARMV8_CORTEX_A57() 316283112Sbr}; 317283112Sbr 318185363Sjkoshy/* 319185363Sjkoshy * PMC_MDEP_TABLE(NAME, PRIMARYCLASS, ADDITIONAL_CLASSES...) 320185363Sjkoshy * 321185363Sjkoshy * Map a CPU to the PMC classes it supports. 322185363Sjkoshy */ 323185363Sjkoshy#define PMC_MDEP_TABLE(N,C,...) \ 324183725Sjkoshy static const enum pmc_class N##_pmc_classes[] = { \ 325183725Sjkoshy PMC_CLASS_##C, __VA_ARGS__ \ 326183725Sjkoshy } 327183725Sjkoshy 328233628SfabientPMC_MDEP_TABLE(atom, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 329263446ShirenPMC_MDEP_TABLE(atom_silvermont, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 330233628SfabientPMC_MDEP_TABLE(core, IAP, PMC_CLASS_SOFT, PMC_CLASS_TSC); 331233628SfabientPMC_MDEP_TABLE(core2, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 332233628SfabientPMC_MDEP_TABLE(corei7, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 333267062SkibPMC_MDEP_TABLE(nehalem_ex, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 334248842SsbrunoPMC_MDEP_TABLE(haswell, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 335277177SrrsPMC_MDEP_TABLE(haswell_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 336291494SrrsPMC_MDEP_TABLE(broadwell, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 337291494SrrsPMC_MDEP_TABLE(broadwell_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 338291494SrrsPMC_MDEP_TABLE(skylake, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 339323799SkibPMC_MDEP_TABLE(skylake_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 340240164SfabientPMC_MDEP_TABLE(ivybridge, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 341246166SsbrunoPMC_MDEP_TABLE(ivybridge_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 342233628SfabientPMC_MDEP_TABLE(sandybridge, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 343241738SsbrunoPMC_MDEP_TABLE(sandybridge_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 344233628SfabientPMC_MDEP_TABLE(westmere, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); 345267062SkibPMC_MDEP_TABLE(westmere_ex, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); 346233628SfabientPMC_MDEP_TABLE(k7, K7, PMC_CLASS_SOFT, PMC_CLASS_TSC); 347233628SfabientPMC_MDEP_TABLE(k8, K8, PMC_CLASS_SOFT, PMC_CLASS_TSC); 348339767SmmacyPMC_MDEP_TABLE(f17h, F17H, PMC_CLASS_SOFT, PMC_CLASS_TSC); 349233628SfabientPMC_MDEP_TABLE(p4, P4, PMC_CLASS_SOFT, PMC_CLASS_TSC); 350233628SfabientPMC_MDEP_TABLE(p5, P5, PMC_CLASS_SOFT, PMC_CLASS_TSC); 351233628SfabientPMC_MDEP_TABLE(p6, P6, PMC_CLASS_SOFT, PMC_CLASS_TSC); 352233628SfabientPMC_MDEP_TABLE(xscale, XSCALE, PMC_CLASS_SOFT, PMC_CLASS_XSCALE); 353284218SbrPMC_MDEP_TABLE(cortex_a8, ARMV7, PMC_CLASS_SOFT, PMC_CLASS_ARMV7); 354284218SbrPMC_MDEP_TABLE(cortex_a9, ARMV7, PMC_CLASS_SOFT, PMC_CLASS_ARMV7); 355283112SbrPMC_MDEP_TABLE(cortex_a53, ARMV8, PMC_CLASS_SOFT, PMC_CLASS_ARMV8); 356283112SbrPMC_MDEP_TABLE(cortex_a57, ARMV8, PMC_CLASS_SOFT, PMC_CLASS_ARMV8); 357233628SfabientPMC_MDEP_TABLE(mips24k, MIPS24K, PMC_CLASS_SOFT, PMC_CLASS_MIPS24K); 358281098SadrianPMC_MDEP_TABLE(mips74k, MIPS74K, PMC_CLASS_SOFT, PMC_CLASS_MIPS74K); 359233628SfabientPMC_MDEP_TABLE(octeon, OCTEON, PMC_CLASS_SOFT, PMC_CLASS_OCTEON); 360281713SjhibbitsPMC_MDEP_TABLE(ppc7450, PPC7450, PMC_CLASS_SOFT, PMC_CLASS_PPC7450, PMC_CLASS_TSC); 361281713SjhibbitsPMC_MDEP_TABLE(ppc970, PPC970, PMC_CLASS_SOFT, PMC_CLASS_PPC970, PMC_CLASS_TSC); 362281713SjhibbitsPMC_MDEP_TABLE(e500, E500, PMC_CLASS_SOFT, PMC_CLASS_E500, PMC_CLASS_TSC); 363233628SfabientPMC_MDEP_TABLE(generic, SOFT, PMC_CLASS_SOFT); 364183725Sjkoshy 365183725Sjkoshystatic const struct pmc_event_descr tsc_event_table[] = 366145256Sjkoshy{ 367183725Sjkoshy __PMC_EV_TSC() 368145256Sjkoshy}; 369145256Sjkoshy 370183725Sjkoshy#undef PMC_CLASS_TABLE_DESC 371185363Sjkoshy#define PMC_CLASS_TABLE_DESC(NAME, CLASS, EVENTS, ALLOCATOR) \ 372185363Sjkoshystatic const struct pmc_class_descr NAME##_class_table_descr = \ 373185363Sjkoshy { \ 374185363Sjkoshy .pm_evc_name = #CLASS "-", \ 375185363Sjkoshy .pm_evc_name_size = sizeof(#CLASS "-") - 1, \ 376185363Sjkoshy .pm_evc_class = PMC_CLASS_##CLASS , \ 377185363Sjkoshy .pm_evc_event_table = EVENTS##_event_table , \ 378183725Sjkoshy .pm_evc_event_table_size = \ 379185363Sjkoshy PMC_EVENT_TABLE_SIZE(EVENTS), \ 380185363Sjkoshy .pm_evc_allocate_pmc = ALLOCATOR##_allocate_pmc \ 381183725Sjkoshy } 382183725Sjkoshy 383185363Sjkoshy#if defined(__i386__) || defined(__amd64__) 384185363SjkoshyPMC_CLASS_TABLE_DESC(iaf, IAF, iaf, iaf); 385185363SjkoshyPMC_CLASS_TABLE_DESC(atom, IAP, atom, iap); 386263446ShirenPMC_CLASS_TABLE_DESC(atom_silvermont, IAP, atom_silvermont, iap); 387185363SjkoshyPMC_CLASS_TABLE_DESC(core, IAP, core, iap); 388185363SjkoshyPMC_CLASS_TABLE_DESC(core2, IAP, core2, iap); 389187761SjeffPMC_CLASS_TABLE_DESC(corei7, IAP, corei7, iap); 390267062SkibPMC_CLASS_TABLE_DESC(nehalem_ex, IAP, nehalem_ex, iap); 391248842SsbrunoPMC_CLASS_TABLE_DESC(haswell, IAP, haswell, iap); 392279833SrstonePMC_CLASS_TABLE_DESC(haswell_xeon, IAP, haswell_xeon, iap); 393291494SrrsPMC_CLASS_TABLE_DESC(broadwell, IAP, broadwell, iap); 394291494SrrsPMC_CLASS_TABLE_DESC(broadwell_xeon, IAP, broadwell_xeon, iap); 395291494SrrsPMC_CLASS_TABLE_DESC(skylake, IAP, skylake, iap); 396323799SkibPMC_CLASS_TABLE_DESC(skylake_xeon, IAP, skylake_xeon, iap); 397240164SfabientPMC_CLASS_TABLE_DESC(ivybridge, IAP, ivybridge, iap); 398246166SsbrunoPMC_CLASS_TABLE_DESC(ivybridge_xeon, IAP, ivybridge_xeon, iap); 399232366SdavidePMC_CLASS_TABLE_DESC(sandybridge, IAP, sandybridge, iap); 400241738SsbrunoPMC_CLASS_TABLE_DESC(sandybridge_xeon, IAP, sandybridge_xeon, iap); 401206089SfabientPMC_CLASS_TABLE_DESC(westmere, IAP, westmere, iap); 402267062SkibPMC_CLASS_TABLE_DESC(westmere_ex, IAP, westmere_ex, iap); 403206089SfabientPMC_CLASS_TABLE_DESC(ucf, UCF, ucf, ucf); 404206089SfabientPMC_CLASS_TABLE_DESC(corei7uc, UCP, corei7uc, ucp); 405248842SsbrunoPMC_CLASS_TABLE_DESC(haswelluc, UCP, haswelluc, ucp); 406291494SrrsPMC_CLASS_TABLE_DESC(broadwelluc, UCP, broadwelluc, ucp); 407232366SdavidePMC_CLASS_TABLE_DESC(sandybridgeuc, UCP, sandybridgeuc, ucp); 408206089SfabientPMC_CLASS_TABLE_DESC(westmereuc, UCP, westmereuc, ucp); 409185363Sjkoshy#endif 410183725Sjkoshy#if defined(__i386__) 411185363SjkoshyPMC_CLASS_TABLE_DESC(k7, K7, k7, k7); 412183725Sjkoshy#endif 413183725Sjkoshy#if defined(__i386__) || defined(__amd64__) 414185363SjkoshyPMC_CLASS_TABLE_DESC(k8, K8, k8, k8); 415339767SmmacyPMC_CLASS_TABLE_DESC(f17h, F17H, f17h, f17h); 416185363SjkoshyPMC_CLASS_TABLE_DESC(p4, P4, p4, p4); 417183725Sjkoshy#endif 418183725Sjkoshy#if defined(__i386__) 419185363SjkoshyPMC_CLASS_TABLE_DESC(p5, P5, p5, p5); 420185363SjkoshyPMC_CLASS_TABLE_DESC(p6, P6, p6, p6); 421183725Sjkoshy#endif 422183725Sjkoshy#if defined(__i386__) || defined(__amd64__) 423185363SjkoshyPMC_CLASS_TABLE_DESC(tsc, TSC, tsc, tsc); 424183725Sjkoshy#endif 425277835Sbr#if defined(__arm__) 426200928Srpaulo#if defined(__XSCALE__) 427200928SrpauloPMC_CLASS_TABLE_DESC(xscale, XSCALE, xscale, xscale); 428200928Srpaulo#endif 429289317SbzPMC_CLASS_TABLE_DESC(cortex_a8, ARMV7, cortex_a8, armv7); 430284218SbrPMC_CLASS_TABLE_DESC(cortex_a9, ARMV7, cortex_a9, armv7); 431277835Sbr#endif 432283112Sbr#if defined(__aarch64__) 433283112SbrPMC_CLASS_TABLE_DESC(cortex_a53, ARMV8, cortex_a53, arm64); 434283112SbrPMC_CLASS_TABLE_DESC(cortex_a57, ARMV8, cortex_a57, arm64); 435283112Sbr#endif 436204635Sgnn#if defined(__mips__) 437233320SgonzoPMC_CLASS_TABLE_DESC(mips24k, MIPS24K, mips24k, mips); 438281098SadrianPMC_CLASS_TABLE_DESC(mips74k, MIPS74K, mips74k, mips); 439233335SgonzoPMC_CLASS_TABLE_DESC(octeon, OCTEON, octeon, mips); 440204635Sgnn#endif /* __mips__ */ 441228869Sjhibbits#if defined(__powerpc__) 442261342SjhibbitsPMC_CLASS_TABLE_DESC(ppc7450, PPC7450, ppc7450, powerpc); 443261342SjhibbitsPMC_CLASS_TABLE_DESC(ppc970, PPC970, ppc970, powerpc); 444281713SjhibbitsPMC_CLASS_TABLE_DESC(e500, E500, e500, powerpc); 445228869Sjhibbits#endif 446228869Sjhibbits 447233628Sfabientstatic struct pmc_class_descr soft_class_table_descr = 448233628Sfabient{ 449233628Sfabient .pm_evc_name = "SOFT-", 450233628Sfabient .pm_evc_name_size = sizeof("SOFT-") - 1, 451233628Sfabient .pm_evc_class = PMC_CLASS_SOFT, 452233628Sfabient .pm_evc_event_table = NULL, 453233628Sfabient .pm_evc_event_table_size = 0, 454233628Sfabient .pm_evc_allocate_pmc = soft_allocate_pmc 455233628Sfabient}; 456233628Sfabient 457183725Sjkoshy#undef PMC_CLASS_TABLE_DESC 458183725Sjkoshy 459185363Sjkoshystatic const struct pmc_class_descr **pmc_class_table; 460185363Sjkoshy#define PMC_CLASS_TABLE_SIZE cpu_info.pm_nclass 461185363Sjkoshy 462183725Sjkoshystatic const enum pmc_class *pmc_mdep_class_list; 463183725Sjkoshystatic size_t pmc_mdep_class_list_size; 464183725Sjkoshy 465145256Sjkoshy/* 466145256Sjkoshy * Mapping tables, mapping enumeration values to human readable 467145256Sjkoshy * strings. 468145256Sjkoshy */ 469145256Sjkoshy 470145256Sjkoshystatic const char * pmc_capability_names[] = { 471145256Sjkoshy#undef __PMC_CAP 472145256Sjkoshy#define __PMC_CAP(N,V,D) #N , 473145256Sjkoshy __PMC_CAPS() 474145256Sjkoshy}; 475145256Sjkoshy 476283120Sjhbstruct pmc_class_map { 477283120Sjhb enum pmc_class pm_class; 478283120Sjhb const char *pm_name; 479283120Sjhb}; 480283120Sjhb 481283120Sjhbstatic const struct pmc_class_map pmc_class_names[] = { 482145256Sjkoshy#undef __PMC_CLASS 483283120Sjhb#define __PMC_CLASS(S,V,D) { .pm_class = PMC_CLASS_##S, .pm_name = #S } , 484145256Sjkoshy __PMC_CLASSES() 485145256Sjkoshy}; 486145256Sjkoshy 487183725Sjkoshystruct pmc_cputype_map { 488228557Sdim enum pmc_cputype pm_cputype; 489183725Sjkoshy const char *pm_name; 490183725Sjkoshy}; 491183725Sjkoshy 492183725Sjkoshystatic const struct pmc_cputype_map pmc_cputype_names[] = { 493145256Sjkoshy#undef __PMC_CPU 494183725Sjkoshy#define __PMC_CPU(S, V, D) { .pm_cputype = PMC_CPU_##S, .pm_name = #S } , 495145256Sjkoshy __PMC_CPUS() 496145256Sjkoshy}; 497145256Sjkoshy 498145256Sjkoshystatic const char * pmc_disposition_names[] = { 499145256Sjkoshy#undef __PMC_DISP 500145256Sjkoshy#define __PMC_DISP(D) #D , 501145256Sjkoshy __PMC_DISPOSITIONS() 502145256Sjkoshy}; 503145256Sjkoshy 504145256Sjkoshystatic const char * pmc_mode_names[] = { 505145256Sjkoshy#undef __PMC_MODE 506145256Sjkoshy#define __PMC_MODE(M,N) #M , 507145256Sjkoshy __PMC_MODES() 508145256Sjkoshy}; 509145256Sjkoshy 510145256Sjkoshystatic const char * pmc_state_names[] = { 511145256Sjkoshy#undef __PMC_STATE 512145256Sjkoshy#define __PMC_STATE(S) #S , 513145256Sjkoshy __PMC_STATES() 514145256Sjkoshy}; 515145256Sjkoshy 516233628Sfabient/* 517233628Sfabient * Filled in by pmc_init(). 518233628Sfabient */ 519233628Sfabientstatic int pmc_syscall = -1; 520233628Sfabientstatic struct pmc_cpuinfo cpu_info; 521233628Sfabientstatic struct pmc_op_getdyneventinfo soft_event_info; 522145256Sjkoshy 523145256Sjkoshy/* Event masks for events */ 524145256Sjkoshystruct pmc_masks { 525145256Sjkoshy const char *pm_name; 526240164Sfabient const uint64_t pm_value; 527145256Sjkoshy}; 528145256Sjkoshy#define PMCMASK(N,V) { .pm_name = #N, .pm_value = (V) } 529206089Sfabient#define NULLMASK { .pm_name = NULL } 530145256Sjkoshy 531147759Sjkoshy#if defined(__amd64__) || defined(__i386__) 532145256Sjkoshystatic int 533240164Sfabientpmc_parse_mask(const struct pmc_masks *pmask, char *p, uint64_t *evmask) 534145256Sjkoshy{ 535145256Sjkoshy const struct pmc_masks *pm; 536145256Sjkoshy char *q, *r; 537145256Sjkoshy int c; 538145256Sjkoshy 539145256Sjkoshy if (pmask == NULL) /* no mask keywords */ 540174406Sjkoshy return (-1); 541183107Sjkoshy q = strchr(p, '='); /* skip '=' */ 542145256Sjkoshy if (*++q == '\0') /* no more data */ 543174406Sjkoshy return (-1); 544145256Sjkoshy c = 0; /* count of mask keywords seen */ 545145256Sjkoshy while ((r = strsep(&q, "+")) != NULL) { 546183725Sjkoshy for (pm = pmask; pm->pm_name && strcasecmp(r, pm->pm_name); 547183725Sjkoshy pm++) 548145256Sjkoshy ; 549145256Sjkoshy if (pm->pm_name == NULL) /* not found */ 550174406Sjkoshy return (-1); 551145256Sjkoshy *evmask |= pm->pm_value; 552145256Sjkoshy c++; 553145256Sjkoshy } 554174406Sjkoshy return (c); 555145256Sjkoshy} 556145340Smarcel#endif 557145256Sjkoshy 558145256Sjkoshy#define KWMATCH(p,kw) (strcasecmp((p), (kw)) == 0) 559145256Sjkoshy#define KWPREFIXMATCH(p,kw) (strncasecmp((p), (kw), sizeof((kw)) - 1) == 0) 560145256Sjkoshy#define EV_ALIAS(N,S) { .pm_alias = N, .pm_spec = S } 561145256Sjkoshy 562145340Smarcel#if defined(__i386__) 563145256Sjkoshy 564145256Sjkoshy/* 565145256Sjkoshy * AMD K7 (Athlon) CPUs. 566145256Sjkoshy */ 567145256Sjkoshy 568145256Sjkoshystatic struct pmc_event_alias k7_aliases[] = { 569145351Sjkoshy EV_ALIAS("branches", "k7-retired-branches"), 570145351Sjkoshy EV_ALIAS("branch-mispredicts", "k7-retired-branches-mispredicted"), 571145351Sjkoshy EV_ALIAS("cycles", "tsc"), 572183075Sjkoshy EV_ALIAS("dc-misses", "k7-dc-misses"), 573145351Sjkoshy EV_ALIAS("ic-misses", "k7-ic-misses"), 574145351Sjkoshy EV_ALIAS("instructions", "k7-retired-instructions"), 575145351Sjkoshy EV_ALIAS("interrupts", "k7-hardware-interrupts"), 576145351Sjkoshy EV_ALIAS(NULL, NULL) 577145256Sjkoshy}; 578145256Sjkoshy 579145256Sjkoshy#define K7_KW_COUNT "count" 580145256Sjkoshy#define K7_KW_EDGE "edge" 581145256Sjkoshy#define K7_KW_INV "inv" 582145256Sjkoshy#define K7_KW_OS "os" 583145256Sjkoshy#define K7_KW_UNITMASK "unitmask" 584145256Sjkoshy#define K7_KW_USR "usr" 585145256Sjkoshy 586145256Sjkoshystatic int 587145256Sjkoshyk7_allocate_pmc(enum pmc_event pe, char *ctrspec, 588145256Sjkoshy struct pmc_op_pmcallocate *pmc_config) 589145256Sjkoshy{ 590183107Sjkoshy char *e, *p, *q; 591183107Sjkoshy int c, has_unitmask; 592145256Sjkoshy uint32_t count, unitmask; 593145256Sjkoshy 594147191Sjkoshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 595183725Sjkoshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 596145256Sjkoshy 597145256Sjkoshy if (pe == PMC_EV_K7_DC_REFILLS_FROM_L2 || 598145256Sjkoshy pe == PMC_EV_K7_DC_REFILLS_FROM_SYSTEM || 599145256Sjkoshy pe == PMC_EV_K7_DC_WRITEBACKS) { 600145256Sjkoshy has_unitmask = 1; 601147191Sjkoshy unitmask = AMD_PMC_UNITMASK_MOESI; 602145256Sjkoshy } else 603145256Sjkoshy unitmask = has_unitmask = 0; 604145256Sjkoshy 605145256Sjkoshy while ((p = strsep(&ctrspec, ",")) != NULL) { 606145256Sjkoshy if (KWPREFIXMATCH(p, K7_KW_COUNT "=")) { 607145256Sjkoshy q = strchr(p, '='); 608145256Sjkoshy if (*++q == '\0') /* skip '=' */ 609174406Sjkoshy return (-1); 610145256Sjkoshy 611145256Sjkoshy count = strtol(q, &e, 0); 612145256Sjkoshy if (e == q || *e != '\0') 613174406Sjkoshy return (-1); 614145256Sjkoshy 615145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 616147191Sjkoshy pmc_config->pm_md.pm_amd.pm_amd_config |= 617147191Sjkoshy AMD_PMC_TO_COUNTER(count); 618145256Sjkoshy 619145256Sjkoshy } else if (KWMATCH(p, K7_KW_EDGE)) { 620145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_EDGE; 621145256Sjkoshy } else if (KWMATCH(p, K7_KW_INV)) { 622145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_INVERT; 623145256Sjkoshy } else if (KWMATCH(p, K7_KW_OS)) { 624145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 625145256Sjkoshy } else if (KWPREFIXMATCH(p, K7_KW_UNITMASK "=")) { 626145256Sjkoshy if (has_unitmask == 0) 627174406Sjkoshy return (-1); 628145256Sjkoshy unitmask = 0; 629145256Sjkoshy q = strchr(p, '='); 630145256Sjkoshy if (*++q == '\0') /* skip '=' */ 631174406Sjkoshy return (-1); 632145256Sjkoshy 633145256Sjkoshy while ((c = tolower(*q++)) != 0) 634145256Sjkoshy if (c == 'm') 635147191Sjkoshy unitmask |= AMD_PMC_UNITMASK_M; 636145256Sjkoshy else if (c == 'o') 637147191Sjkoshy unitmask |= AMD_PMC_UNITMASK_O; 638145256Sjkoshy else if (c == 'e') 639147191Sjkoshy unitmask |= AMD_PMC_UNITMASK_E; 640145256Sjkoshy else if (c == 's') 641147191Sjkoshy unitmask |= AMD_PMC_UNITMASK_S; 642145256Sjkoshy else if (c == 'i') 643147191Sjkoshy unitmask |= AMD_PMC_UNITMASK_I; 644145256Sjkoshy else if (c == '+') 645145256Sjkoshy continue; 646145256Sjkoshy else 647174406Sjkoshy return (-1); 648145256Sjkoshy 649145256Sjkoshy if (unitmask == 0) 650174406Sjkoshy return (-1); 651145256Sjkoshy 652145256Sjkoshy } else if (KWMATCH(p, K7_KW_USR)) { 653145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_USER; 654145256Sjkoshy } else 655174406Sjkoshy return (-1); 656145256Sjkoshy } 657145256Sjkoshy 658145256Sjkoshy if (has_unitmask) { 659145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 660147191Sjkoshy pmc_config->pm_md.pm_amd.pm_amd_config |= 661147191Sjkoshy AMD_PMC_TO_UNITMASK(unitmask); 662145256Sjkoshy } 663145256Sjkoshy 664174406Sjkoshy return (0); 665145256Sjkoshy 666145256Sjkoshy} 667145256Sjkoshy 668147191Sjkoshy#endif 669147191Sjkoshy 670147759Sjkoshy#if defined(__amd64__) || defined(__i386__) 671147191Sjkoshy 672145256Sjkoshy/* 673185363Sjkoshy * Intel Core (Family 6, Model E) PMCs. 674185363Sjkoshy */ 675185363Sjkoshy 676185363Sjkoshystatic struct pmc_event_alias core_aliases[] = { 677185363Sjkoshy EV_ALIAS("branches", "iap-br-instr-ret"), 678185363Sjkoshy EV_ALIAS("branch-mispredicts", "iap-br-mispred-ret"), 679185363Sjkoshy EV_ALIAS("cycles", "tsc-tsc"), 680185363Sjkoshy EV_ALIAS("ic-misses", "iap-icache-misses"), 681185363Sjkoshy EV_ALIAS("instructions", "iap-instr-ret"), 682185363Sjkoshy EV_ALIAS("interrupts", "iap-core-hw-int-rx"), 683185363Sjkoshy EV_ALIAS("unhalted-cycles", "iap-unhalted-core-cycles"), 684185363Sjkoshy EV_ALIAS(NULL, NULL) 685185363Sjkoshy}; 686185363Sjkoshy 687185363Sjkoshy/* 688185363Sjkoshy * Intel Core2 (Family 6, Model F), Core2Extreme (Family 6, Model 17H) 689185363Sjkoshy * and Atom (Family 6, model 1CH) PMCs. 690198433Sjkoshy * 691198433Sjkoshy * We map aliases to events on the fixed-function counters if these 692198433Sjkoshy * are present. Note that not all CPUs in this family contain fixed-function 693198433Sjkoshy * counters. 694185363Sjkoshy */ 695185363Sjkoshy 696185363Sjkoshystatic struct pmc_event_alias core2_aliases[] = { 697185363Sjkoshy EV_ALIAS("branches", "iap-br-inst-retired.any"), 698185363Sjkoshy EV_ALIAS("branch-mispredicts", "iap-br-inst-retired.mispred"), 699185363Sjkoshy EV_ALIAS("cycles", "tsc-tsc"), 700185363Sjkoshy EV_ALIAS("ic-misses", "iap-l1i-misses"), 701185363Sjkoshy EV_ALIAS("instructions", "iaf-instr-retired.any"), 702185363Sjkoshy EV_ALIAS("interrupts", "iap-hw-int-rcv"), 703185363Sjkoshy EV_ALIAS("unhalted-cycles", "iaf-cpu-clk-unhalted.core"), 704185363Sjkoshy EV_ALIAS(NULL, NULL) 705185363Sjkoshy}; 706185363Sjkoshy 707198433Sjkoshystatic struct pmc_event_alias core2_aliases_without_iaf[] = { 708198433Sjkoshy EV_ALIAS("branches", "iap-br-inst-retired.any"), 709198433Sjkoshy EV_ALIAS("branch-mispredicts", "iap-br-inst-retired.mispred"), 710198433Sjkoshy EV_ALIAS("cycles", "tsc-tsc"), 711198433Sjkoshy EV_ALIAS("ic-misses", "iap-l1i-misses"), 712198433Sjkoshy EV_ALIAS("instructions", "iap-inst-retired.any_p"), 713198433Sjkoshy EV_ALIAS("interrupts", "iap-hw-int-rcv"), 714198433Sjkoshy EV_ALIAS("unhalted-cycles", "iap-cpu-clk-unhalted.core_p"), 715198433Sjkoshy EV_ALIAS(NULL, NULL) 716198433Sjkoshy}; 717198433Sjkoshy 718198433Sjkoshy#define atom_aliases core2_aliases 719198433Sjkoshy#define atom_aliases_without_iaf core2_aliases_without_iaf 720263446Shiren#define atom_silvermont_aliases core2_aliases 721263446Shiren#define atom_silvermont_aliases_without_iaf core2_aliases_without_iaf 722198433Sjkoshy#define corei7_aliases core2_aliases 723198433Sjkoshy#define corei7_aliases_without_iaf core2_aliases_without_iaf 724267062Skib#define nehalem_ex_aliases core2_aliases 725267062Skib#define nehalem_ex_aliases_without_iaf core2_aliases_without_iaf 726248842Ssbruno#define haswell_aliases core2_aliases 727248842Ssbruno#define haswell_aliases_without_iaf core2_aliases_without_iaf 728277177Srrs#define haswell_xeon_aliases core2_aliases 729277177Srrs#define haswell_xeon_aliases_without_iaf core2_aliases_without_iaf 730291494Srrs#define broadwell_aliases core2_aliases 731291494Srrs#define broadwell_aliases_without_iaf core2_aliases_without_iaf 732291494Srrs#define broadwell_xeon_aliases core2_aliases 733291494Srrs#define broadwell_xeon_aliases_without_iaf core2_aliases_without_iaf 734291494Srrs#define skylake_aliases core2_aliases 735291494Srrs#define skylake_aliases_without_iaf core2_aliases_without_iaf 736323799Skib#define skylake_xeon_aliases core2_aliases 737323799Skib#define skylake_xeon_aliases_without_iaf core2_aliases_without_iaf 738240164Sfabient#define ivybridge_aliases core2_aliases 739240164Sfabient#define ivybridge_aliases_without_iaf core2_aliases_without_iaf 740246166Ssbruno#define ivybridge_xeon_aliases core2_aliases 741246166Ssbruno#define ivybridge_xeon_aliases_without_iaf core2_aliases_without_iaf 742232366Sdavide#define sandybridge_aliases core2_aliases 743232366Sdavide#define sandybridge_aliases_without_iaf core2_aliases_without_iaf 744241738Ssbruno#define sandybridge_xeon_aliases core2_aliases 745241738Ssbruno#define sandybridge_xeon_aliases_without_iaf core2_aliases_without_iaf 746206089Sfabient#define westmere_aliases core2_aliases 747206089Sfabient#define westmere_aliases_without_iaf core2_aliases_without_iaf 748267062Skib#define westmere_ex_aliases core2_aliases 749267062Skib#define westmere_ex_aliases_without_iaf core2_aliases_without_iaf 750198433Sjkoshy 751185363Sjkoshy#define IAF_KW_OS "os" 752185363Sjkoshy#define IAF_KW_USR "usr" 753185363Sjkoshy#define IAF_KW_ANYTHREAD "anythread" 754185363Sjkoshy 755185363Sjkoshy/* 756185363Sjkoshy * Parse an event specifier for Intel fixed function counters. 757185363Sjkoshy */ 758185363Sjkoshystatic int 759185363Sjkoshyiaf_allocate_pmc(enum pmc_event pe, char *ctrspec, 760185363Sjkoshy struct pmc_op_pmcallocate *pmc_config) 761185363Sjkoshy{ 762185363Sjkoshy char *p; 763185363Sjkoshy 764185363Sjkoshy (void) pe; 765185363Sjkoshy 766185363Sjkoshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 767185363Sjkoshy pmc_config->pm_md.pm_iaf.pm_iaf_flags = 0; 768185363Sjkoshy 769185363Sjkoshy while ((p = strsep(&ctrspec, ",")) != NULL) { 770185363Sjkoshy if (KWMATCH(p, IAF_KW_OS)) 771185363Sjkoshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 772185363Sjkoshy else if (KWMATCH(p, IAF_KW_USR)) 773185363Sjkoshy pmc_config->pm_caps |= PMC_CAP_USER; 774185363Sjkoshy else if (KWMATCH(p, IAF_KW_ANYTHREAD)) 775185363Sjkoshy pmc_config->pm_md.pm_iaf.pm_iaf_flags |= IAF_ANY; 776185363Sjkoshy else 777185363Sjkoshy return (-1); 778185363Sjkoshy } 779185363Sjkoshy 780185363Sjkoshy return (0); 781185363Sjkoshy} 782185363Sjkoshy 783185363Sjkoshy/* 784185363Sjkoshy * Core/Core2 support. 785185363Sjkoshy */ 786185363Sjkoshy 787185363Sjkoshy#define IAP_KW_AGENT "agent" 788185363Sjkoshy#define IAP_KW_ANYTHREAD "anythread" 789185363Sjkoshy#define IAP_KW_CACHESTATE "cachestate" 790185363Sjkoshy#define IAP_KW_CMASK "cmask" 791185363Sjkoshy#define IAP_KW_CORE "core" 792185363Sjkoshy#define IAP_KW_EDGE "edge" 793185363Sjkoshy#define IAP_KW_INV "inv" 794185363Sjkoshy#define IAP_KW_OS "os" 795185363Sjkoshy#define IAP_KW_PREFETCH "prefetch" 796185363Sjkoshy#define IAP_KW_SNOOPRESPONSE "snoopresponse" 797185363Sjkoshy#define IAP_KW_SNOOPTYPE "snooptype" 798185363Sjkoshy#define IAP_KW_TRANSITION "trans" 799185363Sjkoshy#define IAP_KW_USR "usr" 800206089Sfabient#define IAP_KW_RSP "rsp" 801185363Sjkoshy 802185363Sjkoshystatic struct pmc_masks iap_core_mask[] = { 803185363Sjkoshy PMCMASK(all, (0x3 << 14)), 804185363Sjkoshy PMCMASK(this, (0x1 << 14)), 805185363Sjkoshy NULLMASK 806185363Sjkoshy}; 807185363Sjkoshy 808185363Sjkoshystatic struct pmc_masks iap_agent_mask[] = { 809185363Sjkoshy PMCMASK(this, 0), 810185363Sjkoshy PMCMASK(any, (0x1 << 13)), 811185363Sjkoshy NULLMASK 812185363Sjkoshy}; 813185363Sjkoshy 814185363Sjkoshystatic struct pmc_masks iap_prefetch_mask[] = { 815185363Sjkoshy PMCMASK(both, (0x3 << 12)), 816185363Sjkoshy PMCMASK(only, (0x1 << 12)), 817185363Sjkoshy PMCMASK(exclude, 0), 818185363Sjkoshy NULLMASK 819185363Sjkoshy}; 820185363Sjkoshy 821185363Sjkoshystatic struct pmc_masks iap_cachestate_mask[] = { 822185363Sjkoshy PMCMASK(i, (1 << 8)), 823185363Sjkoshy PMCMASK(s, (1 << 9)), 824185363Sjkoshy PMCMASK(e, (1 << 10)), 825185363Sjkoshy PMCMASK(m, (1 << 11)), 826185363Sjkoshy NULLMASK 827185363Sjkoshy}; 828185363Sjkoshy 829185363Sjkoshystatic struct pmc_masks iap_snoopresponse_mask[] = { 830185363Sjkoshy PMCMASK(clean, (1 << 8)), 831185363Sjkoshy PMCMASK(hit, (1 << 9)), 832185363Sjkoshy PMCMASK(hitm, (1 << 11)), 833185363Sjkoshy NULLMASK 834185363Sjkoshy}; 835185363Sjkoshy 836185363Sjkoshystatic struct pmc_masks iap_snooptype_mask[] = { 837185363Sjkoshy PMCMASK(cmp2s, (1 << 8)), 838185363Sjkoshy PMCMASK(cmp2i, (1 << 9)), 839185363Sjkoshy NULLMASK 840185363Sjkoshy}; 841185363Sjkoshy 842185363Sjkoshystatic struct pmc_masks iap_transition_mask[] = { 843185363Sjkoshy PMCMASK(any, 0x00), 844185363Sjkoshy PMCMASK(frequency, 0x10), 845185363Sjkoshy NULLMASK 846185363Sjkoshy}; 847185363Sjkoshy 848240164Sfabientstatic struct pmc_masks iap_rsp_mask_i7_wm[] = { 849206089Sfabient PMCMASK(DMND_DATA_RD, (1 << 0)), 850206089Sfabient PMCMASK(DMND_RFO, (1 << 1)), 851206089Sfabient PMCMASK(DMND_IFETCH, (1 << 2)), 852206089Sfabient PMCMASK(WB, (1 << 3)), 853206089Sfabient PMCMASK(PF_DATA_RD, (1 << 4)), 854206089Sfabient PMCMASK(PF_RFO, (1 << 5)), 855206089Sfabient PMCMASK(PF_IFETCH, (1 << 6)), 856206089Sfabient PMCMASK(OTHER, (1 << 7)), 857206089Sfabient PMCMASK(UNCORE_HIT, (1 << 8)), 858206089Sfabient PMCMASK(OTHER_CORE_HIT_SNP, (1 << 9)), 859206089Sfabient PMCMASK(OTHER_CORE_HITM, (1 << 10)), 860206089Sfabient PMCMASK(REMOTE_CACHE_FWD, (1 << 12)), 861206089Sfabient PMCMASK(REMOTE_DRAM, (1 << 13)), 862206089Sfabient PMCMASK(LOCAL_DRAM, (1 << 14)), 863206089Sfabient PMCMASK(NON_DRAM, (1 << 15)), 864206089Sfabient NULLMASK 865206089Sfabient}; 866206089Sfabient 867241738Ssbrunostatic struct pmc_masks iap_rsp_mask_sb_sbx_ib[] = { 868240164Sfabient PMCMASK(REQ_DMND_DATA_RD, (1ULL << 0)), 869240164Sfabient PMCMASK(REQ_DMND_RFO, (1ULL << 1)), 870240164Sfabient PMCMASK(REQ_DMND_IFETCH, (1ULL << 2)), 871240164Sfabient PMCMASK(REQ_WB, (1ULL << 3)), 872240164Sfabient PMCMASK(REQ_PF_DATA_RD, (1ULL << 4)), 873240164Sfabient PMCMASK(REQ_PF_RFO, (1ULL << 5)), 874240164Sfabient PMCMASK(REQ_PF_IFETCH, (1ULL << 6)), 875240164Sfabient PMCMASK(REQ_PF_LLC_DATA_RD, (1ULL << 7)), 876240164Sfabient PMCMASK(REQ_PF_LLC_RFO, (1ULL << 8)), 877240164Sfabient PMCMASK(REQ_PF_LLC_IFETCH, (1ULL << 9)), 878240164Sfabient PMCMASK(REQ_BUS_LOCKS, (1ULL << 10)), 879240164Sfabient PMCMASK(REQ_STRM_ST, (1ULL << 11)), 880240164Sfabient PMCMASK(REQ_OTHER, (1ULL << 15)), 881240164Sfabient PMCMASK(RES_ANY, (1ULL << 16)), 882240164Sfabient PMCMASK(RES_SUPPLIER_SUPP, (1ULL << 17)), 883240164Sfabient PMCMASK(RES_SUPPLIER_LLC_HITM, (1ULL << 18)), 884240164Sfabient PMCMASK(RES_SUPPLIER_LLC_HITE, (1ULL << 19)), 885240164Sfabient PMCMASK(RES_SUPPLIER_LLC_HITS, (1ULL << 20)), 886240164Sfabient PMCMASK(RES_SUPPLIER_LLC_HITF, (1ULL << 21)), 887240164Sfabient PMCMASK(RES_SUPPLIER_LOCAL, (1ULL << 22)), 888241974Ssbruno PMCMASK(RES_SNOOP_SNP_NONE, (1ULL << 31)), 889240164Sfabient PMCMASK(RES_SNOOP_SNP_NO_NEEDED,(1ULL << 32)), 890240164Sfabient PMCMASK(RES_SNOOP_SNP_MISS, (1ULL << 33)), 891240164Sfabient PMCMASK(RES_SNOOP_HIT_NO_FWD, (1ULL << 34)), 892240164Sfabient PMCMASK(RES_SNOOP_HIT_FWD, (1ULL << 35)), 893240164Sfabient PMCMASK(RES_SNOOP_HITM, (1ULL << 36)), 894240164Sfabient PMCMASK(RES_NON_DRAM, (1ULL << 37)), 895240164Sfabient NULLMASK 896240164Sfabient}; 897240164Sfabient 898291494Srrs/* Broadwell is defined to use the same mask as Haswell */ 899248842Ssbrunostatic struct pmc_masks iap_rsp_mask_haswell[] = { 900248842Ssbruno PMCMASK(REQ_DMND_DATA_RD, (1ULL << 0)), 901248842Ssbruno PMCMASK(REQ_DMND_RFO, (1ULL << 1)), 902248842Ssbruno PMCMASK(REQ_DMND_IFETCH, (1ULL << 2)), 903248842Ssbruno PMCMASK(REQ_PF_DATA_RD, (1ULL << 4)), 904248842Ssbruno PMCMASK(REQ_PF_RFO, (1ULL << 5)), 905248842Ssbruno PMCMASK(REQ_PF_IFETCH, (1ULL << 6)), 906248842Ssbruno PMCMASK(REQ_OTHER, (1ULL << 15)), 907248842Ssbruno PMCMASK(RES_ANY, (1ULL << 16)), 908248842Ssbruno PMCMASK(RES_SUPPLIER_SUPP, (1ULL << 17)), 909248842Ssbruno PMCMASK(RES_SUPPLIER_LLC_HITM, (1ULL << 18)), 910248842Ssbruno PMCMASK(RES_SUPPLIER_LLC_HITE, (1ULL << 19)), 911248842Ssbruno PMCMASK(RES_SUPPLIER_LLC_HITS, (1ULL << 20)), 912248842Ssbruno PMCMASK(RES_SUPPLIER_LLC_HITF, (1ULL << 21)), 913248842Ssbruno PMCMASK(RES_SUPPLIER_LOCAL, (1ULL << 22)), 914291494Srrs /* 915291494Srrs * For processor type 06_45H 22 is L4_HIT_LOCAL_L4 916291494Srrs * and 23, 24 and 25 are also defined. 917291494Srrs */ 918248842Ssbruno PMCMASK(RES_SNOOP_SNP_NONE, (1ULL << 31)), 919248842Ssbruno PMCMASK(RES_SNOOP_SNP_NO_NEEDED,(1ULL << 32)), 920248842Ssbruno PMCMASK(RES_SNOOP_SNP_MISS, (1ULL << 33)), 921248842Ssbruno PMCMASK(RES_SNOOP_HIT_NO_FWD, (1ULL << 34)), 922248842Ssbruno PMCMASK(RES_SNOOP_HIT_FWD, (1ULL << 35)), 923248842Ssbruno PMCMASK(RES_SNOOP_HITM, (1ULL << 36)), 924248842Ssbruno PMCMASK(RES_NON_DRAM, (1ULL << 37)), 925248842Ssbruno NULLMASK 926248842Ssbruno}; 927248842Ssbruno 928291494Srrsstatic struct pmc_masks iap_rsp_mask_skylake[] = { 929291494Srrs PMCMASK(REQ_DMND_DATA_RD, (1ULL << 0)), 930291494Srrs PMCMASK(REQ_DMND_RFO, (1ULL << 1)), 931291494Srrs PMCMASK(REQ_DMND_IFETCH, (1ULL << 2)), 932291494Srrs PMCMASK(REQ_PF_DATA_RD, (1ULL << 7)), 933291494Srrs PMCMASK(REQ_PF_RFO, (1ULL << 8)), 934291494Srrs PMCMASK(REQ_STRM_ST, (1ULL << 11)), 935291494Srrs PMCMASK(REQ_OTHER, (1ULL << 15)), 936291494Srrs PMCMASK(RES_ANY, (1ULL << 16)), 937291494Srrs PMCMASK(RES_SUPPLIER_SUPP, (1ULL << 17)), 938291494Srrs PMCMASK(RES_SUPPLIER_LLC_HITM, (1ULL << 18)), 939291494Srrs PMCMASK(RES_SUPPLIER_LLC_HITE, (1ULL << 19)), 940291494Srrs PMCMASK(RES_SUPPLIER_LLC_HITS, (1ULL << 20)), 941291494Srrs PMCMASK(RES_SUPPLIER_L4_HIT, (1ULL << 22)), 942291494Srrs PMCMASK(RES_SUPPLIER_DRAM, (1ULL << 26)), 943291494Srrs PMCMASK(RES_SUPPLIER_SPL_HIT, (1ULL << 30)), 944291494Srrs PMCMASK(RES_SNOOP_SNP_NONE, (1ULL << 31)), 945291494Srrs PMCMASK(RES_SNOOP_SNP_NO_NEEDED,(1ULL << 32)), 946291494Srrs PMCMASK(RES_SNOOP_SNP_MISS, (1ULL << 33)), 947291494Srrs PMCMASK(RES_SNOOP_HIT_NO_FWD, (1ULL << 34)), 948291494Srrs PMCMASK(RES_SNOOP_HIT_FWD, (1ULL << 35)), 949291494Srrs PMCMASK(RES_SNOOP_HITM, (1ULL << 36)), 950291494Srrs PMCMASK(RES_NON_DRAM, (1ULL << 37)), 951291494Srrs NULLMASK 952291494Srrs}; 953291494Srrs 954291494Srrs 955185363Sjkoshystatic int 956185363Sjkoshyiap_allocate_pmc(enum pmc_event pe, char *ctrspec, 957185363Sjkoshy struct pmc_op_pmcallocate *pmc_config) 958185363Sjkoshy{ 959185363Sjkoshy char *e, *p, *q; 960240164Sfabient uint64_t cachestate, evmask, rsp; 961185363Sjkoshy int count, n; 962185363Sjkoshy 963185363Sjkoshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE | 964185363Sjkoshy PMC_CAP_QUALIFIER); 965185363Sjkoshy pmc_config->pm_md.pm_iap.pm_iap_config = 0; 966185363Sjkoshy 967206089Sfabient cachestate = evmask = rsp = 0; 968185363Sjkoshy 969185363Sjkoshy /* Parse additional modifiers if present */ 970185363Sjkoshy while ((p = strsep(&ctrspec, ",")) != NULL) { 971185363Sjkoshy 972185363Sjkoshy n = 0; 973185363Sjkoshy if (KWPREFIXMATCH(p, IAP_KW_CMASK "=")) { 974185363Sjkoshy q = strchr(p, '='); 975185363Sjkoshy if (*++q == '\0') /* skip '=' */ 976185363Sjkoshy return (-1); 977185363Sjkoshy count = strtol(q, &e, 0); 978185363Sjkoshy if (e == q || *e != '\0') 979185363Sjkoshy return (-1); 980185363Sjkoshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 981185363Sjkoshy pmc_config->pm_md.pm_iap.pm_iap_config |= 982185363Sjkoshy IAP_CMASK(count); 983185363Sjkoshy } else if (KWMATCH(p, IAP_KW_EDGE)) { 984185363Sjkoshy pmc_config->pm_caps |= PMC_CAP_EDGE; 985185363Sjkoshy } else if (KWMATCH(p, IAP_KW_INV)) { 986185363Sjkoshy pmc_config->pm_caps |= PMC_CAP_INVERT; 987185363Sjkoshy } else if (KWMATCH(p, IAP_KW_OS)) { 988185363Sjkoshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 989185363Sjkoshy } else if (KWMATCH(p, IAP_KW_USR)) { 990185363Sjkoshy pmc_config->pm_caps |= PMC_CAP_USER; 991185363Sjkoshy } else if (KWMATCH(p, IAP_KW_ANYTHREAD)) { 992185363Sjkoshy pmc_config->pm_md.pm_iap.pm_iap_config |= IAP_ANY; 993193809Sjkoshy } else if (KWPREFIXMATCH(p, IAP_KW_CORE "=")) { 994185363Sjkoshy n = pmc_parse_mask(iap_core_mask, p, &evmask); 995185363Sjkoshy if (n != 1) 996185363Sjkoshy return (-1); 997193809Sjkoshy } else if (KWPREFIXMATCH(p, IAP_KW_AGENT "=")) { 998185363Sjkoshy n = pmc_parse_mask(iap_agent_mask, p, &evmask); 999185363Sjkoshy if (n != 1) 1000185363Sjkoshy return (-1); 1001193809Sjkoshy } else if (KWPREFIXMATCH(p, IAP_KW_PREFETCH "=")) { 1002185363Sjkoshy n = pmc_parse_mask(iap_prefetch_mask, p, &evmask); 1003185363Sjkoshy if (n != 1) 1004185363Sjkoshy return (-1); 1005193809Sjkoshy } else if (KWPREFIXMATCH(p, IAP_KW_CACHESTATE "=")) { 1006185363Sjkoshy n = pmc_parse_mask(iap_cachestate_mask, p, &cachestate); 1007185363Sjkoshy } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_CORE && 1008193809Sjkoshy KWPREFIXMATCH(p, IAP_KW_TRANSITION "=")) { 1009185363Sjkoshy n = pmc_parse_mask(iap_transition_mask, p, &evmask); 1010185363Sjkoshy if (n != 1) 1011185363Sjkoshy return (-1); 1012185363Sjkoshy } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM || 1013263446Shiren cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM_SILVERMONT || 1014185585Sjkoshy cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2 || 1015206089Sfabient cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2EXTREME) { 1016193809Sjkoshy if (KWPREFIXMATCH(p, IAP_KW_SNOOPRESPONSE "=")) { 1017185363Sjkoshy n = pmc_parse_mask(iap_snoopresponse_mask, p, 1018185363Sjkoshy &evmask); 1019193809Sjkoshy } else if (KWPREFIXMATCH(p, IAP_KW_SNOOPTYPE "=")) { 1020185363Sjkoshy n = pmc_parse_mask(iap_snooptype_mask, p, 1021185363Sjkoshy &evmask); 1022185363Sjkoshy } else 1023185363Sjkoshy return (-1); 1024206089Sfabient } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_COREI7 || 1025267062Skib cpu_info.pm_cputype == PMC_CPU_INTEL_WESTMERE || 1026267062Skib cpu_info.pm_cputype == PMC_CPU_INTEL_NEHALEM_EX || 1027267062Skib cpu_info.pm_cputype == PMC_CPU_INTEL_WESTMERE_EX) { 1028206089Sfabient if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 1029240164Sfabient n = pmc_parse_mask(iap_rsp_mask_i7_wm, p, &rsp); 1030206089Sfabient } else 1031206089Sfabient return (-1); 1032240164Sfabient } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_SANDYBRIDGE || 1033241738Ssbruno cpu_info.pm_cputype == PMC_CPU_INTEL_SANDYBRIDGE_XEON || 1034323798Skib cpu_info.pm_cputype == PMC_CPU_INTEL_IVYBRIDGE || 1035323798Skib cpu_info.pm_cputype == PMC_CPU_INTEL_IVYBRIDGE_XEON ) { 1036240164Sfabient if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 1037241738Ssbruno n = pmc_parse_mask(iap_rsp_mask_sb_sbx_ib, p, &rsp); 1038240164Sfabient } else 1039240164Sfabient return (-1); 1040277177Srrs } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_HASWELL || 1041323798Skib cpu_info.pm_cputype == PMC_CPU_INTEL_HASWELL_XEON) { 1042248842Ssbruno if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 1043248842Ssbruno n = pmc_parse_mask(iap_rsp_mask_haswell, p, &rsp); 1044248842Ssbruno } else 1045248842Ssbruno return (-1); 1046291494Srrs } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_BROADWELL || 1047323798Skib cpu_info.pm_cputype == PMC_CPU_INTEL_BROADWELL_XEON) { 1048291494Srrs /* Broadwell is defined to use same mask as haswell */ 1049291494Srrs if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 1050291494Srrs n = pmc_parse_mask(iap_rsp_mask_haswell, p, &rsp); 1051291494Srrs } else 1052291494Srrs return (-1); 1053291494Srrs 1054323799Skib } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_SKYLAKE || 1055323799Skib cpu_info.pm_cputype == PMC_CPU_INTEL_SKYLAKE_XEON) { 1056291494Srrs if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { 1057291494Srrs n = pmc_parse_mask(iap_rsp_mask_skylake, p, &rsp); 1058291494Srrs } else 1059291494Srrs return (-1); 1060291494Srrs 1061185363Sjkoshy } else 1062185363Sjkoshy return (-1); 1063185363Sjkoshy 1064185363Sjkoshy if (n < 0) /* Parsing failed. */ 1065185363Sjkoshy return (-1); 1066185363Sjkoshy } 1067185363Sjkoshy 1068185363Sjkoshy pmc_config->pm_md.pm_iap.pm_iap_config |= evmask; 1069185363Sjkoshy 1070185363Sjkoshy /* 1071185363Sjkoshy * If the event requires a 'cachestate' qualifier but was not 1072185363Sjkoshy * specified by the user, use a sensible default. 1073185363Sjkoshy */ 1074185363Sjkoshy switch (pe) { 1075185363Sjkoshy case PMC_EV_IAP_EVENT_28H: /* Core, Core2, Atom */ 1076185363Sjkoshy case PMC_EV_IAP_EVENT_29H: /* Core, Core2, Atom */ 1077185363Sjkoshy case PMC_EV_IAP_EVENT_2AH: /* Core, Core2, Atom */ 1078185363Sjkoshy case PMC_EV_IAP_EVENT_2BH: /* Atom, Core2 */ 1079185363Sjkoshy case PMC_EV_IAP_EVENT_2EH: /* Core, Core2, Atom */ 1080185363Sjkoshy case PMC_EV_IAP_EVENT_30H: /* Core, Core2, Atom */ 1081185363Sjkoshy case PMC_EV_IAP_EVENT_32H: /* Core */ 1082185363Sjkoshy case PMC_EV_IAP_EVENT_40H: /* Core */ 1083185363Sjkoshy case PMC_EV_IAP_EVENT_41H: /* Core */ 1084185363Sjkoshy case PMC_EV_IAP_EVENT_42H: /* Core, Core2, Atom */ 1085185363Sjkoshy if (cachestate == 0) 1086185363Sjkoshy cachestate = (0xF << 8); 1087207482Srstone break; 1088207482Srstone case PMC_EV_IAP_EVENT_77H: /* Atom */ 1089207482Srstone /* IAP_EVENT_77H only accepts a cachestate qualifier on the 1090207482Srstone * Atom processor 1091207482Srstone */ 1092207482Srstone if(cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM && cachestate == 0) 1093207482Srstone cachestate = (0xF << 8); 1094207482Srstone break; 1095185363Sjkoshy default: 1096185363Sjkoshy break; 1097185363Sjkoshy } 1098185363Sjkoshy 1099185363Sjkoshy pmc_config->pm_md.pm_iap.pm_iap_config |= cachestate; 1100206089Sfabient pmc_config->pm_md.pm_iap.pm_iap_rsp = rsp; 1101185363Sjkoshy 1102185363Sjkoshy return (0); 1103185363Sjkoshy} 1104185363Sjkoshy 1105185363Sjkoshy/* 1106206089Sfabient * Intel Uncore. 1107206089Sfabient */ 1108206089Sfabient 1109206089Sfabientstatic int 1110206089Sfabientucf_allocate_pmc(enum pmc_event pe, char *ctrspec, 1111206089Sfabient struct pmc_op_pmcallocate *pmc_config) 1112206089Sfabient{ 1113206089Sfabient (void) pe; 1114206089Sfabient (void) ctrspec; 1115206089Sfabient 1116206089Sfabient pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1117206089Sfabient pmc_config->pm_md.pm_ucf.pm_ucf_flags = 0; 1118206089Sfabient 1119206089Sfabient return (0); 1120206089Sfabient} 1121206089Sfabient 1122206089Sfabient#define UCP_KW_CMASK "cmask" 1123206089Sfabient#define UCP_KW_EDGE "edge" 1124206089Sfabient#define UCP_KW_INV "inv" 1125206089Sfabient 1126206089Sfabientstatic int 1127206089Sfabientucp_allocate_pmc(enum pmc_event pe, char *ctrspec, 1128206089Sfabient struct pmc_op_pmcallocate *pmc_config) 1129206089Sfabient{ 1130206089Sfabient char *e, *p, *q; 1131206089Sfabient int count, n; 1132206089Sfabient 1133206089Sfabient (void) pe; 1134206089Sfabient 1135206089Sfabient pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE | 1136206089Sfabient PMC_CAP_QUALIFIER); 1137206089Sfabient pmc_config->pm_md.pm_ucp.pm_ucp_config = 0; 1138206089Sfabient 1139206089Sfabient /* Parse additional modifiers if present */ 1140206089Sfabient while ((p = strsep(&ctrspec, ",")) != NULL) { 1141206089Sfabient 1142206089Sfabient n = 0; 1143206089Sfabient if (KWPREFIXMATCH(p, UCP_KW_CMASK "=")) { 1144206089Sfabient q = strchr(p, '='); 1145206089Sfabient if (*++q == '\0') /* skip '=' */ 1146206089Sfabient return (-1); 1147206089Sfabient count = strtol(q, &e, 0); 1148206089Sfabient if (e == q || *e != '\0') 1149206089Sfabient return (-1); 1150206089Sfabient pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 1151206089Sfabient pmc_config->pm_md.pm_ucp.pm_ucp_config |= 1152206089Sfabient UCP_CMASK(count); 1153206089Sfabient } else if (KWMATCH(p, UCP_KW_EDGE)) { 1154206089Sfabient pmc_config->pm_caps |= PMC_CAP_EDGE; 1155206089Sfabient } else if (KWMATCH(p, UCP_KW_INV)) { 1156206089Sfabient pmc_config->pm_caps |= PMC_CAP_INVERT; 1157206089Sfabient } else 1158206089Sfabient return (-1); 1159206089Sfabient 1160206089Sfabient if (n < 0) /* Parsing failed. */ 1161206089Sfabient return (-1); 1162206089Sfabient } 1163206089Sfabient 1164206089Sfabient return (0); 1165206089Sfabient} 1166339767Smmacy/* AMD Fam17H PMCs */ 1167339767Smmacystatic struct pmc_event_alias f17h_aliases[] = { 1168339767Smmacy EV_ALIAS("branches", "ex_ret_brn_tkn"), 1169339767Smmacy EV_ALIAS("branch-mispredicts", 1170339767Smmacy "ex_ret_brn_tkn_misp"), 1171339767Smmacy EV_ALIAS("cycles", "tsc"), 1172339767Smmacy EV_ALIAS("dc-access", "ls_dc_access"), 1173339767Smmacy EV_ALIAS("ic-misses", "ic_fw32_miss"), 1174339767Smmacy EV_ALIAS("instructions", "ex_ret_inst"), 1175339767Smmacy EV_ALIAS("unhalted-cycles", "ls_not_halted_cycle"), 1176339767Smmacy EV_ALIAS(NULL, NULL) 1177339767Smmacy}; 1178339767Smmacy#define __F17HMASK(N, V) PMCMASK(N, (1 << (V))) 1179339767Smmacystatic const struct pmc_masks f17h_mask_FPU_PIPEASSIGMENT[] = { 1180339767Smmacy __F17HMASK(FPU_PIPEASSIGMENT_uOP_P0, 0), 1181339767Smmacy __F17HMASK(FPU_PIPEASSIGMENT_uOP_P1, 1), 1182339767Smmacy __F17HMASK(FPU_PIPEASSIGMENT_uOP_P2, 2), 1183339767Smmacy __F17HMASK(FPU_PIPEASSIGMENT_uOP_P3, 3), 1184339767Smmacy __F17HMASK(FPU_PIPEASSIGMENT_MultiuOP_P0, 4), 1185339767Smmacy __F17HMASK(FPU_PIPEASSIGMENT_MultiuOP_P1, 5), 1186339767Smmacy __F17HMASK(FPU_PIPEASSIGMENT_MultiuOP_P2, 6), 1187339767Smmacy __F17HMASK(FPU_PIPEASSIGMENT_MultiuOP_P3, 7), 1188339767Smmacy NULLMASK 1189339767Smmacy}; 1190339767Smmacystatic const struct pmc_masks f17h_mask_FP_SCHED_EMPTY[] = { 1191339767Smmacy __F17HMASK(FP_SCHED_EMPTY, 0x0), 1192339767Smmacy NULLMASK 1193339767Smmacy}; 1194339767Smmacystatic const struct pmc_masks f17h_mask_FP_RET_X87_FPOPS[] = { 1195339767Smmacy __F17HMASK(FP_RET_X87_ADDSUBOPS, 0), 1196339767Smmacy __F17HMASK(FP_RET_X87_MULOPS, 1), 1197339767Smmacy __F17HMASK(FP_RET_X87_DIVSQRTOPS, 2), 1198339767Smmacy NULLMASK 1199339767Smmacy}; 1200339767Smmacystatic const struct pmc_masks f17h_mask_FP_RET_SSEAVX_OPS[] = { 1201339767Smmacy __F17HMASK(FP_RET_SSEAVX_SPADDSUBOPS, 0), 1202339767Smmacy __F17HMASK(FP_RET_SSEAVX_SPMULOPS, 1), 1203339767Smmacy __F17HMASK(FP_RET_SSEAVX_SPDIVOPS, 2), 1204339767Smmacy __F17HMASK(FP_RET_SSEAVX_SPMULADDOPS, 3), 1205339767Smmacy __F17HMASK(FP_RET_SSEAVX_DPADDSUBOPS, 4), 1206339767Smmacy __F17HMASK(FP_RET_SSEAVX_DPMULOPS, 5), 1207339767Smmacy __F17HMASK(FP_RET_SSEAVX_DPDIVOPS, 6), 1208339767Smmacy __F17HMASK(FP_RET_SSEAVX_DPMULADDOPS, 7), 1209339767Smmacy NULLMASK 1210339767Smmacy}; 1211339767Smmacystatic const struct pmc_masks f17h_mask_FP_NUM_MOVELIM_SCAL_OPT[] = { 1212339767Smmacy __F17HMASK(FP_NUM_SSEMOV_OPS, 0), 1213339767Smmacy __F17HMASK(FP_NUM_SSEMOV_ELIM, 1), 1214339767Smmacy __F17HMASK(FP_NUM_OPS_OPTPOT, 2), 1215339767Smmacy __F17HMASK(FP_NUM_OPS_OPT, 3), 1216339767Smmacy NULLMASK 1217339767Smmacy}; 1218339767Smmacystatic const struct pmc_masks f17h_mask_FP_RET_SEROPS[] = { 1219339767Smmacy __F17HMASK(FP_RET_SSE_BOTEXEC, 0), 1220339767Smmacy __F17HMASK(FP_RET_SSE_CTRL, 1), 1221339767Smmacy __F17HMASK(FP_RET_BOTEXEC, 2), 1222339767Smmacy __F17HMASK(FP_RET_X87_CTRL, 3), 1223339767Smmacy NULLMASK 1224339767Smmacy}; 1225339767Smmacystatic const struct pmc_masks f17h_mask_LS_BAD_STATUS2[] = { 1226339767Smmacy __F17HMASK(LS_BAD_STATUS2_STLI_NOSTATE, 0), 1227339767Smmacy __F17HMASK(LS_BAD_STATUS2_STLI_OTHER, 1), 1228339767Smmacy __F17HMASK(LS_BAD_STATUS2_STLF_NODATA, 2), 1229339767Smmacy NULLMASK 1230339767Smmacy}; 1231339767Smmacystatic const struct pmc_masks f17h_mask_LS_LOCKS[] = { 1232339767Smmacy __F17HMASK(LS_LOCKS_BUSLOCKS, 0), 1233339767Smmacy __F17HMASK(LS_LOCKS_NONSPECLOCK, 1), 1234339767Smmacy __F17HMASK(LS_SPECLOCK, 2), 1235339767Smmacy __F17HMASK(LS_SPECLCOK_MAPCOMMIT, 3), 1236339767Smmacy NULLMASK 1237339767Smmacy}; 1238339767Smmacystatic const struct pmc_masks f17h_mask_LS_RET_CLFLUSH_INST[] = { 1239339767Smmacy __F17HMASK(LS_RET_CLFLUSH_INST, 0x0), 1240339767Smmacy NULLMASK 1241339767Smmacy}; 1242339767Smmacystatic const struct pmc_masks f17h_mask_LS_RET_CPUID_INST[] = { 1243339767Smmacy __F17HMASK(LS_RET_CPUID_INST, 0x0), 1244339767Smmacy NULLMASK 1245339767Smmacy}; 1246339767Smmacystatic const struct pmc_masks f17h_mask_LS_DISPATCH[] = { 1247339767Smmacy __F17HMASK(LS_DISPATCH_LD, 0), 1248339767Smmacy __F17HMASK(LS_DISPATCH_STR, 1), 1249339767Smmacy __F17HMASK(LS_DISPATCH_LDSTR, 2), 1250339767Smmacy NULLMASK 1251339767Smmacy}; 1252339767Smmacystatic const struct pmc_masks f17h_mask_LS_SMI_RX[] = { 1253339767Smmacy __F17HMASK(LS_SMI_RX, 0x0), 1254339767Smmacy NULLMASK 1255339767Smmacy}; 1256339767Smmacystatic const struct pmc_masks f17h_mask_LS_STLF[] = { 1257339767Smmacy __F17HMASK(LS_STLF, 0x0), 1258339767Smmacy NULLMASK 1259339767Smmacy}; 1260339767Smmacystatic const struct pmc_masks f17h_mask_LS_STLF_COMMITCANCEL[] = { 1261339767Smmacy __F17HMASK(LS_STLF_COMMITCANCEL, 0x0), 1262339767Smmacy NULLMASK 1263339767Smmacy}; 1264339767Smmacystatic const struct pmc_masks f17h_mask_LS_DC_ACCESS[] = { 1265339767Smmacy __F17HMASK(LS_DC_ACCESS, 0x0), 1266339767Smmacy NULLMASK 1267339767Smmacy}; 1268339767Smmacystatic const struct pmc_masks f17h_mask_LS_MAB_ALLOCPIPE[] = { 1269339767Smmacy __F17HMASK(LS_MAB_ALLOCPIPE_DATAPIPE, 0), 1270339767Smmacy __F17HMASK(LS_MAB_ALLOCPIPE_STPIPE, 1), 1271339767Smmacy __F17HMASK(LS_MAB_ALLOCPIPE_TLBPIPELATE, 2), 1272339767Smmacy __F17HMASK(LS_MAB_ALLOCPIPE_HWPF, 3), 1273339767Smmacy __F17HMASK(LS_MAB_ALLOCPIPE_TLPPIPEEARLY, 4), 1274339767Smmacy NULLMASK 1275339767Smmacy}; 1276339767Smmacystatic const struct pmc_masks f17h_mask_LS_REFFILS_FROM_SYS[] = { 1277339767Smmacy __F17HMASK(LS_MABRESP_LCL_L2, 0), 1278339767Smmacy __F17HMASK(LS_MABRESP_LCL_CACHE, 1), 1279339767Smmacy __F17HMASK(LS_MABRESP_LCL_DRAM, 3), 1280339767Smmacy __F17HMASK(LS_MABRESP_LCL_RMT_CACHE, 4), 1281339767Smmacy __F17HMASK(LS_MABRESP_LCL_RMT_DRAM, 6), 1282339767Smmacy NULLMASK 1283339767Smmacy}; 1284339767Smmacystatic const struct pmc_masks f17h_mask_LS_L1_DTLBMISS[] = { 1285339767Smmacy __F17HMASK(LS_TLBRELOAD_4KL2HIT, 0), 1286339767Smmacy __F17HMASK(LS_TLBRELOAD_32KL2HIT, 1), 1287339767Smmacy __F17HMASK(LS_TLBRELOAD_2ML2HIT, 2), 1288339767Smmacy __F17HMASK(LS_TLBRELOAD_1GL2HIT, 3), 1289339767Smmacy __F17HMASK(LS_TLBRELOAD_4KL2MISS, 4), 1290339767Smmacy __F17HMASK(LS_TLBRELOAD_32KML2MISS, 5), 1291339767Smmacy __F17HMASK(LS_TLBRELOAD_2ML2MISS, 6), 1292339767Smmacy __F17HMASK(LS_TLBRELOAD_1GL2MISS, 7), 1293339767Smmacy NULLMASK 1294339767Smmacy}; 1295339767Smmacystatic const struct pmc_masks f17h_mask_LS_TABLEWALKER[] = { 1296339767Smmacy __F17HMASK(LS_PERFMON_TW_ALLOCDSIDE0, 0), 1297339767Smmacy __F17HMASK(LS_PERFMON_TW_ALLOCDSIDE1, 1), 1298339767Smmacy __F17HMASK(LS_PERFMON_TW_ALLOCISIDE0, 2), 1299339767Smmacy __F17HMASK(LS_PERFMON_TW_ALLOCISIDE1, 3), 1300339767Smmacy NULLMASK 1301339767Smmacy}; 1302339767Smmacystatic const struct pmc_masks f17h_mask_LS_MISAL_ACCESS[] = { 1303339767Smmacy __F17HMASK(LS_MISAL_ACCESS, 0x0), 1304339767Smmacy NULLMASK 1305339767Smmacy}; 1306339767Smmacystatic const struct pmc_masks f17h_mask_LS_PREF_INST_DISPATCH[] = { 1307339767Smmacy __F17HMASK(LS_LOAD_PREF_W, 0), 1308339767Smmacy __F17HMASK(LS_STORE_PREF_W, 1), 1309339767Smmacy __F17HMASK(LS_PREF_PREFETCH_NTA, 2), 1310339767Smmacy NULLMASK 1311339767Smmacy}; 1312339767Smmacystatic const struct pmc_masks f17h_mask_LS_HWPF_ALLOCATED[] = { 1313339767Smmacy __F17HMASK(LS_ALLOC_STREAM_PF, 0), 1314339767Smmacy __F17HMASK(LS_ALLOC_STRIDE_PF, 1), 1315339767Smmacy NULLMASK 1316339767Smmacy}; 1317339767Smmacystatic const struct pmc_masks f17h_mask_LS_HWPF_HIT[] = { 1318339767Smmacy __F17HMASK(LS_HIT_STREAM_PF, 0), 1319339767Smmacy __F17HMASK(LS_HIT_STRIDE_PF, 1), 1320339767Smmacy NULLMASK 1321339767Smmacy}; 1322339767Smmacystatic const struct pmc_masks f17h_mask_LS_TW_INPROG_DSIDE[] = { 1323339767Smmacy __F17HMASK(LS_TW_INPROG_DSIDE0, 0), 1324339767Smmacy __F17HMASK(LS_TW_INPROG_ISIDE0, 1), 1325339767Smmacy __F17HMASK(LS_TW_INPROG_DSIDE1, 2), 1326339767Smmacy __F17HMASK(LS_TW_INPROG_ISIDE1, 3), 1327339767Smmacy NULLMASK 1328339767Smmacy}; 1329339767Smmacystatic const struct pmc_masks f17h_mask_LS_INEF_SW_PREF[] = { 1330339767Smmacy __F17HMASK(LS_INEF_SW_PREF_DATAPIPE_SW_PF_DCHIT, 0), 1331339767Smmacy __F17HMASK(LS_INEF_SW_PREF_MAB_MCH_CNT, 1), 1332339767Smmacy NULLMASK 1333339767Smmacy}; 1334339767Smmacystatic const struct pmc_masks f17h_mask_LS_MAB_MCH_CNT[] = { 1335339767Smmacy __F17HMASK(LS_MAB_MCH_CNT, 0x0), 1336339767Smmacy NULLMASK 1337339767Smmacy}; 1338339767Smmacystatic const struct pmc_masks f17h_mask_LS_HW_PF_MABALLOC[] = { 1339339767Smmacy __F17HMASK(LS_MABALLOC_HW_PFSTREAM, 0), 1340339767Smmacy __F17HMASK(LS_MABALLOC_HW_PFSTRIDE, 1), 1341339767Smmacy __F17HMASK(LS_MABALLOC_PFREGION, 2), 1342339767Smmacy NULLMASK 1343339767Smmacy}; 1344339767Smmacystatic const struct pmc_masks f17h_mask_LS_HW_PF_MATCH[] = { 1345339767Smmacy __F17HMASK(LS_MATCH_HW_PFSTREAM, 0), 1346339767Smmacy __F17HMASK(LS_MATCH_HW_PFSTRIDE, 1), 1347339767Smmacy __F17HMASK(LS_MATCH_HW_PFREGION, 2), 1348339767Smmacy NULLMASK 1349339767Smmacy}; 1350339767Smmacystatic const struct pmc_masks f17h_mask_LS_SW_PF_DCFILLS[] = { 1351339767Smmacy __F17HMASK(LS_SW_PF_MABRESP_LCL_L2, 0), 1352339767Smmacy __F17HMASK(LS_SW_PF_MABRESP_LCL_L2_CACHE, 1), 1353339767Smmacy __F17HMASK(LS_SW_PF_MABRESP_LCL_DRM, 3), 1354339767Smmacy __F17HMASK(LS_SW_PF_MABRESP_RMT_CACHE, 4), 1355339767Smmacy __F17HMASK(LS_SW_PF_MABRESP_RMT_DRAM, 6), 1356339767Smmacy NULLMASK 1357339767Smmacy}; 1358339767Smmacystatic const struct pmc_masks f17h_mask_LS_HW_PF_DCFILLS[] = { 1359339767Smmacy __F17HMASK(LS_HW_PF_MABRESP_LCL_L2, 0), 1360339767Smmacy __F17HMASK(LS_HW_PF_MABRESP_LCL_CACHE, 1), 1361339767Smmacy __F17HMASK(LS_HW_PF_MABRESP_LCL_DRAM, 3), 1362339767Smmacy __F17HMASK(LS_HW_PF_MABRESP_RMT_CACHE, 4), 1363339767Smmacy __F17HMASK(LS_HW_PF_MABRESP_RMT_DRAM, 6), 1364339767Smmacy NULLMASK 1365339767Smmacy}; 1366339767Smmacystatic const struct pmc_masks f17h_mask_LS_TW_DCFILLS[] = { 1367339767Smmacy __F17HMASK(LS_TW_MABRESP_LCL_L2, 0), 1368339767Smmacy __F17HMASK(LS_TW_MABRESP_LCL_CACHE, 1), 1369339767Smmacy __F17HMASK(LS_TW_MABRESP_LCL_DRAM, 3), 1370339767Smmacy __F17HMASK(LS_TW_MABRESP_RMT_CACHE, 4), 1371339767Smmacy __F17HMASK(LS_TW_MABRESP_RMT_DRAM, 6), 1372339767Smmacy NULLMASK 1373339767Smmacy}; 1374206089Sfabient 1375339767Smmacystatic const struct pmc_masks f17h_mask_LS_ALLOC_MAB_COUNT[] = { 1376339767Smmacy __F17HMASK(LS_ALLOC_MAB_COUNT, 0x0), 1377339767Smmacy NULLMASK 1378339767Smmacy}; 1379339767Smmacystatic const struct pmc_masks f17h_mask_LS_TW_INITLEVEL[] = { 1380339767Smmacy __F17HMASK(LS_TW_INITLGH_NATIVE_PDPT, 0), 1381339767Smmacy __F17HMASK(LS_TW_INITLGH_NATIVE_PDT, 1), 1382339767Smmacy __F17HMASK(LS_TW_INITLGH_NATIVE_PFT, 2), 1383339767Smmacy __F17HMASK(LS_TW_INITLGH_NATIVE_PG, 3), 1384339767Smmacy __F17HMASK(LS_TW_INITL_NESTED_PDPT, 4), 1385339767Smmacy __F17HMASK(LS_TW_INITL_NESTED_PDT, 5), 1386339767Smmacy __F17HMASK(LS_TW_INITL_NESTED_PFT, 6), 1387339767Smmacy __F17HMASK(LS_TW_INITL_NESTED_PG, 7), 1388339767Smmacy NULLMASK 1389339767Smmacy}; 1390339767Smmacystatic const struct pmc_masks f17h_mask_LS_NOT_HALTED_CYCLE[] = { 1391339767Smmacy __F17HMASK(LS_NOT_HALTED_CYCLE, 0x00), 1392339767Smmacy NULLMASK 1393339767Smmacy}; 1394339767Smmacystatic const struct pmc_masks f17h_mask_LS_TW_RETURN_TYPES[] = { 1395339767Smmacy __F17HMASK(LS_TWC_RET_TYPE_SPEC_VALID, 0), 1396339767Smmacy __F17HMASK(LS_TWC_RET_TYPE_SPEC_FAULT_NAB, 2), 1397339767Smmacy __F17HMASK(LS_TWC_RET_TYPE_SPEC_FAULT_AB, 3), 1398339767Smmacy __F17HMASK(LS_TWC_RET_TYPE_NONSPEC_VALID, 6), 1399339767Smmacy __F17HMASK(LS_TWC_RET_TYPE_NONSPEC_FAULT, 7), 1400339767Smmacy NULLMASK 1401339767Smmacy}; 1402339767Smmacystatic const struct pmc_masks f17h_mask_IC_FW32[] = { 1403339767Smmacy __F17HMASK(IC_FW32, 0x0), 1404339767Smmacy NULLMASK 1405339767Smmacy}; 1406339767Smmacystatic const struct pmc_masks f17h_mask_IC_FW32_MISS[] = { 1407339767Smmacy __F17HMASK(IC_FW32_MISS, 0x0), 1408339767Smmacy NULLMASK 1409339767Smmacy}; 1410339767Smmacystatic const struct pmc_masks f17h_mask_IC_CACHEFILL_L2[] = { 1411339767Smmacy __F17HMASK(IC_CACHEFILL_L2, 0x0), 1412339767Smmacy NULLMASK 1413339767Smmacy}; 1414339767Smmacystatic const struct pmc_masks f17h_mask_IC_CACHEFILL_SYS[] = { 1415339767Smmacy __F17HMASK(IC_CACHEFILL_SYS, 0x0), 1416339767Smmacy NULLMASK 1417339767Smmacy}; 1418339767Smmacystatic const struct pmc_masks f17h_mask_BP_L1TLBMISS_L2HIT[] = { 1419339767Smmacy __F17HMASK(BP_L1TLBMISS_L2HIT, 0x0), 1420339767Smmacy NULLMASK 1421339767Smmacy}; 1422339767Smmacystatic const struct pmc_masks f17h_mask_BP_L1TLBMISS_L2MISS[] = { 1423339767Smmacy __F17HMASK(BP_L1TLBMISS_L2MISS, 0x0), 1424339767Smmacy NULLMASK 1425339767Smmacy}; 1426339767Smmacystatic const struct pmc_masks f17h_mask_IC_FETCHSTALL[] = { 1427339767Smmacy __F17HMASK(IC_FETCHSTALL_BACKPRESSURE, 0), 1428339767Smmacy __F17HMASK(IC_FETCHSTALL_DQEMPTY, 1), 1429339767Smmacy __F17HMASK(IC_FETCHSTALL_ANY, 2), 1430339767Smmacy NULLMASK 1431339767Smmacy}; 1432339767Smmacystatic const struct pmc_masks f17h_mask_BP_L1_BTBCORRECT[] = { 1433339767Smmacy __F17HMASK(BP_L1_BTBCORRECT, 0x0), 1434339767Smmacy NULLMASK 1435339767Smmacy}; 1436339767Smmacystatic const struct pmc_masks f17h_mask_BP_L2_BTBCORRECT[] = { 1437339767Smmacy __F17HMASK(BP_L2_BTBCORRECT, 0x0), 1438339767Smmacy NULLMASK 1439339767Smmacy}; 1440339767Smmacystatic const struct pmc_masks f17h_mask_IC_CACHEINVAL[] = { 1441339767Smmacy __F17HMASK(IC_CACHEINVAL_FILLINV, 0), 1442339767Smmacy __F17HMASK(IC_CACHEINVAL_L2_INV_PROVBE, 1), 1443339767Smmacy NULLMASK 1444339767Smmacy}; 1445339767Smmacystatic const struct pmc_masks f17h_mask_BP_TLB_REL[] = { 1446339767Smmacy __F17HMASK(BP_TLB_REL, 0x0), 1447339767Smmacy NULLMASK 1448339767Smmacy}; 1449339767Smmacystatic const struct pmc_masks f17h_mask_ICOC_MODE_SWITCH[] = { 1450339767Smmacy __F17HMASK(IC2OC_MODE_SWITCH, 0), 1451339767Smmacy __F17HMASK(OC2IC_MODE_SWITCH, 1), 1452339767Smmacy NULLMASK 1453339767Smmacy}; 1454339767Smmacystatic const struct pmc_masks f17h_mask_DE_DISPATCH_TOKEN_STALLS[] = { 1455339767Smmacy __F17HMASK(DE_ALSQ1_TOKEN_STALL, 0), 1456339767Smmacy __F17HMASK(DE_ALSQ2_TOKEN_STALL, 1), 1457339767Smmacy __F17HMASK(DE_ALSQ3_TOKEN_STALL, 2), 1458339767Smmacy __F17HMASK(DE_ALSQ3_0_TOKEN_STALL, 3), 1459339767Smmacy __F17HMASK(DE_ALU_TOKEN_STALL, 4), 1460339767Smmacy __F17HMASK(DE_AGSQ_TOKEN_STALL, 5), 1461339767Smmacy __F17HMASK(DE_RETIRE_TOKEN_STALLS, 6), 1462339767Smmacy NULLMASK 1463339767Smmacy}; 1464339767Smmacystatic const struct pmc_masks f17h_mask_EX_RET_INST[] = { 1465339767Smmacy __F17HMASK(EX_RET_INST, 0x0), 1466339767Smmacy NULLMASK 1467339767Smmacy}; 1468339767Smmacystatic const struct pmc_masks f17h_mask_EX_RET_COPS[] = { 1469339767Smmacy __F17HMASK(EX_RET_COPS, 0x0), 1470339767Smmacy NULLMASK 1471339767Smmacy}; 1472339767Smmacystatic const struct pmc_masks f17h_mask_EX_RET_BRN[] = { 1473339767Smmacy __F17HMASK(EX_RET_BRN, 0x0), 1474339767Smmacy NULLMASK 1475339767Smmacy}; 1476339767Smmacystatic const struct pmc_masks f17h_mask_EX_RET_BRN_MISP[] = { 1477339767Smmacy __F17HMASK(EX_RET_BRN_MISP, 0x0), 1478339767Smmacy NULLMASK 1479339767Smmacy}; 1480339767Smmacystatic const struct pmc_masks f17h_mask_EX_RET_BRN_TKN[] = { 1481339767Smmacy __F17HMASK(EX_RET_BRN_TKN, 0x0), 1482339767Smmacy NULLMASK 1483339767Smmacy}; 1484339767Smmacystatic const struct pmc_masks f17h_mask_EX_RET_BRN_TKN_MISP[] = { 1485339767Smmacy __F17HMASK(EX_RET_BRN_TKN_MISP, 0x0), 1486339767Smmacy NULLMASK 1487339767Smmacy}; 1488339767Smmacystatic const struct pmc_masks f17h_mask_EX_RET_BRN_FAR[] = { 1489339767Smmacy __F17HMASK(EX_RET_BRN_FAR, 0x0), 1490339767Smmacy NULLMASK 1491339767Smmacy}; 1492339767Smmacystatic const struct pmc_masks f17h_mask_EX_RET_BRN_RESYNC[] = { 1493339767Smmacy __F17HMASK(EX_RET_BRN_RESYNC, 0x0), 1494339767Smmacy NULLMASK 1495339767Smmacy}; 1496339767Smmacystatic const struct pmc_masks f17h_mask_EX_RET_BRN_NEAR_RET[] = { 1497339767Smmacy __F17HMASK(EX_RET_BRN_NEAR_RET, 0x0), 1498339767Smmacy NULLMASK 1499339767Smmacy}; 1500339767Smmacystatic const struct pmc_masks f17h_mask_EX_RET_BRN_NEAR_RET_MISPRED[] = { 1501339767Smmacy __F17HMASK(EX_RET_BRN_NEAR_RET_MISPRED, 0x0), 1502339767Smmacy NULLMASK 1503339767Smmacy}; 1504339767Smmacystatic const struct pmc_masks f17h_mask_EX_RET_BRN_IND_MISP[] = { 1505339767Smmacy __F17HMASK(EX_RET_BRN_IND_MISP, 0x0), 1506339767Smmacy NULLMASK 1507339767Smmacy}; 1508339767Smmacystatic const struct pmc_masks f17h_mask_EX_RET_MMX_FP_INSTR[] = { 1509339767Smmacy __F17HMASK(EX_RET_MMX_X87_INST, 0), 1510339767Smmacy __F17HMASK(EX_RET_MMX_INSTR, 1), 1511339767Smmacy __F17HMASK(EX_RET_MMX_SSE_INSTR, 2), 1512339767Smmacy NULLMASK 1513339767Smmacy}; 1514339767Smmacystatic const struct pmc_masks f17h_mask_EX_RET_COND_BRN[] = { 1515339767Smmacy __F17HMASK(EX_RET_COND_BRN, 0x0), 1516339767Smmacy NULLMASK 1517339767Smmacy}; 1518339767Smmacystatic const struct pmc_masks f17h_mask_EX_DIV_BUSY[] = { 1519339767Smmacy __F17HMASK(EX_DIV_BUSY, 0x0), 1520339767Smmacy NULLMASK 1521339767Smmacy}; 1522339767Smmacystatic const struct pmc_masks f17h_mask_EX_DIV_COUNT[] = { 1523339767Smmacy __F17HMASK(EX_DIV_COUNT, 0x0), 1524339767Smmacy NULLMASK 1525339767Smmacy}; 1526339767Smmacystatic const struct pmc_masks f17h_mask_L2_REQUEST_G1[] = { 1527339767Smmacy __F17HMASK(L2_REQUEST_G1_OTHERREQ, 0), 1528339767Smmacy __F17HMASK(L2_REQUEST_G1_HWPF, 1), 1529339767Smmacy __F17HMASK(L2_REQUEST_G1_PREFETCHL2, 2), 1530339767Smmacy __F17HMASK(L2_REQUEST_G1_CHANGETOX, 3), 1531339767Smmacy __F17HMASK(L2_REQUEST_G1_CACHEABLEICRD, 4), 1532339767Smmacy __F17HMASK(L2_REQUEST_G1_LSRDBLKC, 5), 1533339767Smmacy __F17HMASK(L2_REQUEST_G1_RDBLKX, 6), 1534339767Smmacy __F17HMASK(L2_REQUEST_G1_RDBLKL, 7), 1535339767Smmacy NULLMASK 1536339767Smmacy}; 1537339767Smmacystatic const struct pmc_masks f17h_mask_L2_REQUEST_G2[] = { 1538339767Smmacy __F17HMASK(L2_REQUEST_G2_BUSLOCKRESP, 0), 1539339767Smmacy __F17HMASK(L2_REQUEST_G2_BUSLOCKORIG, 1), 1540339767Smmacy __F17HMASK(L2_REQUEST_G2_SMCINV, 2), 1541339767Smmacy __F17HMASK(L2_REQUEST_G2_ICRDSIZENC, 3), 1542339767Smmacy __F17HMASK(L2_REQUEST_G2_ICRDSIZE, 4), 1543339767Smmacy __F17HMASK(L2_REQUEST_G2_LSRDSIZENC, 5), 1544339767Smmacy __F17HMASK(L2_REQUEST_G2_LSRDSIZE, 6), 1545339767Smmacy __F17HMASK(L2_REQUEST_G2_GROUP1, 7), 1546339767Smmacy NULLMASK 1547339767Smmacy}; 1548339767Smmacystatic const struct pmc_masks f17h_mask_L2_LATENCY[] = { 1549339767Smmacy __F17HMASK(L2_LATENCY_CYC_WAITINGONFILLS, 0x0), 1550339767Smmacy NULLMASK 1551339767Smmacy}; 1552339767Smmacystatic const struct pmc_masks f17h_mask_L2_WBCREQ[] = { 1553339767Smmacy __F17HMASK(L2_WBCREQ_CLZERO, 0), 1554339767Smmacy __F17HMASK(L2_WBCREQ_LOCALICCLR, 1), 1555339767Smmacy __F17HMASK(L2_WBCREQ_ZEROBYTESTORE, 2), 1556339767Smmacy __F17HMASK(L2_WBCREQ_ILINEFLUSH, 3), 1557339767Smmacy __F17HMASK(L2_WBCREQ_CACHELINEFLUSH, 4), 1558339767Smmacy __F17HMASK(L2_WBCREQ_WBCCLOSE, 5), 1559339767Smmacy __F17HMASK(L2_WBCREQ_WCBWRITE, 6), 1560339767Smmacy NULLMASK 1561339767Smmacy}; 1562339767Smmacystatic const struct pmc_masks f17h_mask_L2_CACHEREQSTAT[] = { 1563339767Smmacy __F17HMASK(L2_CACHEREQSTAT_ICFILLMISS, 0), 1564339767Smmacy __F17HMASK(L2_CACHEREQSTAT_ICFILLHITS, 1), 1565339767Smmacy __F17HMASK(L2_CACHEREQSTAT_ICFILLHITX, 2), 1566339767Smmacy __F17HMASK(L2_CACHEREQSTAT_LSRDBLKC, 3), 1567339767Smmacy __F17HMASK(L2_CACHEREQSTAT_LSRDBLKX, 4), 1568339767Smmacy __F17HMASK(L2_CACHEREQSTAT_LSRDBLKLHITS, 5), 1569339767Smmacy __F17HMASK(L2_CACHEREQSTAT_LSRDBLKLHITX, 6), 1570339767Smmacy __F17HMASK(L2_CACHEREQSTAT_LSRDBLKCS, 7), 1571339767Smmacy NULLMASK 1572339767Smmacy}; 1573339767Smmacystatic const struct pmc_masks f17h_mask_L2_SMCEVENTS[] = { 1574339767Smmacy __F17HMASK(L2_SMCEVENTS_ICFILLSTQCAMMATOT, 0), 1575339767Smmacy __F17HMASK(L2_SMCEVENTS_ICFILLSTQCAMMATTT, 1), 1576339767Smmacy __F17HMASK(L2_SMCEVENTS_LSRDBLKLSXCHGTOX, 2), 1577339767Smmacy __F17HMASK(L2_SMCEVENTS_RDBLKXCHGTOX, 3), 1578339767Smmacy __F17HMASK(L2_SMCEVENTS_LSRDBLKLSCHITL2ICVAL, 4), 1579339767Smmacy __F17HMASK(L2_SMCEVENTS_ICFETCHHITL2, 5), 1580339767Smmacy __F17HMASK(L2_SMCEVENTS_ICFETCHHITL2DCVAL, 6), 1581339767Smmacy NULLMASK 1582339767Smmacy}; 1583339767Smmacystatic const struct pmc_masks f17h_mask_L2_FILLPENDING[] = { 1584339767Smmacy __F17HMASK(L2_FILLPENDING_L2FILLBUSY, 0), 1585339767Smmacy NULLMASK 1586339767Smmacy}; 1587339767Smmacystatic const struct pmc_masks f17h_mask_EX_TAGGED_IBSOPS[] = { 1588339767Smmacy __F17HMASK(EX_TAGGED_IBSOPS, 0x0), 1589339767Smmacy __F17HMASK(EX_TAGGED_IBSOPS_RET, 0x1), 1590339767Smmacy __F17HMASK(EX_TAGGED_IBSOPS_CNT_RLOVER, 0x2), 1591339767Smmacy NULLMASK 1592339767Smmacy}; 1593339767Smmacystatic const struct pmc_masks f17h_mask_EX_RET_FUSED_BRNCH_INST[] = { 1594339767Smmacy __F17HMASK(EX_RET_FUSED_BRNCH_INST, 0x0), 1595339767Smmacy NULLMASK 1596339767Smmacy}; 1597339767Smmacy 1598339767Smmacy#define F17H_KW_COUNT "count" 1599339767Smmacy#define F17H_KW_EDGE "edge" 1600339767Smmacy#define F17H_KW_INV "inv" 1601339767Smmacy#define F17H_KW_MASK "mask" 1602339767Smmacy#define F17H_KW_OS "os" 1603339767Smmacy#define F17H_KW_USR "usr" 1604339767Smmacy 1605339767Smmacystatic int 1606339767Smmacyf17h_allocate_pmc(enum pmc_event pe, char *ctrspec, 1607339767Smmacy struct pmc_op_pmcallocate *pmc_config) 1608339767Smmacy{ 1609339767Smmacy char *e, *p, *q; 1610339767Smmacy int n; 1611339767Smmacy uint32_t count; 1612339767Smmacy const struct pmc_masks *pmask; 1613339767Smmacy uint64_t evmask = 0; 1614339767Smmacy (void)ctrspec; 1615339767Smmacy 1616339767Smmacy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1617339767Smmacy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 1618339767Smmacy 1619339767Smmacy 1620339767Smmacy#define __F17HSETMASK(M) pmask = f17h_mask_##M 1621339767Smmacy switch (pe) { 1622339767Smmacy case PMC_EV_F17H_FPU_PIPEASSIGMENT: 1623339767Smmacy __F17HSETMASK(FPU_PIPEASSIGMENT); 1624339767Smmacy break; 1625339767Smmacy case PMC_EV_F17H_FP_SCHED_EMPTY: 1626339767Smmacy __F17HSETMASK(FP_SCHED_EMPTY); 1627339767Smmacy break; 1628339767Smmacy case PMC_EV_F17H_FP_RET_X87_FPOPS: 1629339767Smmacy __F17HSETMASK(FP_RET_X87_FPOPS); 1630339767Smmacy break; 1631339767Smmacy case PMC_EV_F17H_FP_RET_SSEAVX_OPS: 1632339767Smmacy __F17HSETMASK(FP_RET_SSEAVX_OPS); 1633339767Smmacy break; 1634339767Smmacy case PMC_EV_F17H_FP_NUM_MOVELIM_SCAL_OPT: 1635339767Smmacy __F17HSETMASK(FP_NUM_MOVELIM_SCAL_OPT); 1636339767Smmacy break; 1637339767Smmacy case PMC_EV_F17H_FP_RET_SEROPS: 1638339767Smmacy __F17HSETMASK(FP_RET_SEROPS); 1639339767Smmacy break; 1640339767Smmacy case PMC_EV_F17H_LS_BAD_STATUS2: 1641339767Smmacy __F17HSETMASK(LS_BAD_STATUS2); 1642339767Smmacy break; 1643339767Smmacy case PMC_EV_F17H_LS_LOCKS: 1644339767Smmacy __F17HSETMASK(LS_LOCKS); 1645339767Smmacy break; 1646339767Smmacy case PMC_EV_F17H_LS_RET_CLFLUSH_INST: 1647339767Smmacy __F17HSETMASK(LS_RET_CLFLUSH_INST); 1648339767Smmacy break; 1649339767Smmacy case PMC_EV_F17H_LS_RET_CPUID_INST: 1650339767Smmacy __F17HSETMASK(LS_RET_CPUID_INST); 1651339767Smmacy break; 1652339767Smmacy case PMC_EV_F17H_LS_DISPATCH: 1653339767Smmacy __F17HSETMASK(LS_DISPATCH); 1654339767Smmacy break; 1655339767Smmacy case PMC_EV_F17H_LS_SMI_RX: 1656339767Smmacy __F17HSETMASK(LS_SMI_RX); 1657339767Smmacy break; 1658339767Smmacy case PMC_EV_F17H_LS_STLF: 1659339767Smmacy __F17HSETMASK(LS_STLF); 1660339767Smmacy break; 1661339767Smmacy case PMC_EV_F17H_LS_STLF_COMMITCANCEL: 1662339767Smmacy __F17HSETMASK(LS_STLF_COMMITCANCEL); 1663339767Smmacy break; 1664339767Smmacy case PMC_EV_F17H_LS_DC_ACCESS: 1665339767Smmacy __F17HSETMASK(LS_DC_ACCESS); 1666339767Smmacy break; 1667339767Smmacy case PMC_EV_F17H_LS_MAB_ALLOCPIPE: 1668339767Smmacy __F17HSETMASK(LS_MAB_ALLOCPIPE); 1669339767Smmacy break; 1670339767Smmacy case PMC_EV_F17H_LS_REFFILS_FROM_SYS: 1671339767Smmacy __F17HSETMASK(LS_REFFILS_FROM_SYS); 1672339767Smmacy break; 1673339767Smmacy case PMC_EV_F17H_LS_L1_DTLBMISS: 1674339767Smmacy __F17HSETMASK(LS_L1_DTLBMISS); 1675339767Smmacy break; 1676339767Smmacy case PMC_EV_F17H_LS_TABLEWALKER: 1677339767Smmacy __F17HSETMASK(LS_TABLEWALKER); 1678339767Smmacy break; 1679339767Smmacy case PMC_EV_F17H_LS_MISAL_ACCESS: 1680339767Smmacy __F17HSETMASK(LS_MISAL_ACCESS); 1681339767Smmacy break; 1682339767Smmacy case PMC_EV_F17H_LS_PREF_INST_DISPATCH: 1683339767Smmacy __F17HSETMASK(LS_PREF_INST_DISPATCH); 1684339767Smmacy break; 1685339767Smmacy case PMC_EV_F17H_LS_HWPF_ALLOCATED: 1686339767Smmacy __F17HSETMASK(LS_HWPF_ALLOCATED); 1687339767Smmacy break; 1688339767Smmacy case PMC_EV_F17H_LS_HWPF_HIT: 1689339767Smmacy __F17HSETMASK(LS_HWPF_HIT); 1690339767Smmacy break; 1691339767Smmacy case PMC_EV_F17H_LS_TW_INPROG_DSIDE: 1692339767Smmacy __F17HSETMASK(LS_TW_INPROG_DSIDE); 1693339767Smmacy break; 1694339767Smmacy case PMC_EV_F17H_LS_INEF_SW_PREF: 1695339767Smmacy __F17HSETMASK(LS_INEF_SW_PREF); 1696339767Smmacy break; 1697339767Smmacy case PMC_EV_F17H_LS_MAB_MCH_CNT: 1698339767Smmacy __F17HSETMASK(LS_MAB_MCH_CNT); 1699339767Smmacy break; 1700339767Smmacy case PMC_EV_F17H_LS_HW_PF_MABALLOC: 1701339767Smmacy __F17HSETMASK(LS_HW_PF_MABALLOC); 1702339767Smmacy break; 1703339767Smmacy case PMC_EV_F17H_LS_HW_PF_MATCH: 1704339767Smmacy __F17HSETMASK(LS_HW_PF_MATCH); 1705339767Smmacy break; 1706339767Smmacy case PMC_EV_F17H_LS_SW_PF_DCFILLS: 1707339767Smmacy __F17HSETMASK(LS_SW_PF_DCFILLS); 1708339767Smmacy break; 1709339767Smmacy case PMC_EV_F17H_LS_HW_PF_DCFILLS: 1710339767Smmacy __F17HSETMASK(LS_HW_PF_DCFILLS); 1711339767Smmacy break; 1712339767Smmacy case PMC_EV_F17H_LS_TW_DCFILLS: 1713339767Smmacy __F17HSETMASK(LS_TW_DCFILLS); 1714339767Smmacy break; 1715339767Smmacy case PMC_EV_F17H_LS_ALLOC_MAB_COUNT: 1716339767Smmacy __F17HSETMASK(LS_ALLOC_MAB_COUNT); 1717339767Smmacy break; 1718339767Smmacy case PMC_EV_F17H_LS_TW_INITLEVEL: 1719339767Smmacy __F17HSETMASK(LS_TW_INITLEVEL); 1720339767Smmacy break; 1721339767Smmacy case PMC_EV_F17H_LS_NOT_HALTED_CYCLE: 1722339767Smmacy __F17HSETMASK(LS_NOT_HALTED_CYCLE); 1723339767Smmacy break; 1724339767Smmacy case PMC_EV_F17H_LS_TW_RETURN_TYPES: 1725339767Smmacy __F17HSETMASK(LS_TW_RETURN_TYPES); 1726339767Smmacy break; 1727339767Smmacy case PMC_EV_F17H_IC_FW32: 1728339767Smmacy __F17HSETMASK(IC_FW32); 1729339767Smmacy break; 1730339767Smmacy case PMC_EV_F17H_IC_FW32_MISS: 1731339767Smmacy __F17HSETMASK(IC_FW32_MISS); 1732339767Smmacy break; 1733339767Smmacy case PMC_EV_F17H_IC_CACHEFILL_L2: 1734339767Smmacy __F17HSETMASK(IC_CACHEFILL_L2); 1735339767Smmacy break; 1736339767Smmacy case PMC_EV_F17H_IC_CACHEFILL_SYS: 1737339767Smmacy __F17HSETMASK(IC_CACHEFILL_SYS); 1738339767Smmacy break; 1739339767Smmacy case PMC_EV_F17H_BP_L1TLBMISS_L2HIT: 1740339767Smmacy __F17HSETMASK(BP_L1TLBMISS_L2HIT); 1741339767Smmacy break; 1742339767Smmacy case PMC_EV_F17H_BP_L1TLBMISS_L2MISS: 1743339767Smmacy __F17HSETMASK(BP_L1TLBMISS_L2MISS); 1744339767Smmacy break; 1745339767Smmacy case PMC_EV_F17H_IC_FETCHSTALL: 1746339767Smmacy __F17HSETMASK(IC_FETCHSTALL); 1747339767Smmacy break; 1748339767Smmacy case PMC_EV_F17H_BP_L1_BTBCORRECT: 1749339767Smmacy __F17HSETMASK(BP_L1_BTBCORRECT); 1750339767Smmacy break; 1751339767Smmacy case PMC_EV_F17H_BP_L2_BTBCORRECT: 1752339767Smmacy __F17HSETMASK(BP_L2_BTBCORRECT); 1753339767Smmacy break; 1754339767Smmacy case PMC_EV_F17H_IC_CACHEINVAL: 1755339767Smmacy __F17HSETMASK(IC_CACHEINVAL); 1756339767Smmacy break; 1757339767Smmacy case PMC_EV_F17H_BP_TLB_REL: 1758339767Smmacy __F17HSETMASK(BP_TLB_REL); 1759339767Smmacy break; 1760339767Smmacy case PMC_EV_F17H_ICOC_MODE_SWITCH: 1761339767Smmacy __F17HSETMASK(ICOC_MODE_SWITCH); 1762339767Smmacy break; 1763339767Smmacy case PMC_EV_F17H_DE_DISPATCH_TOKEN_STALLS: 1764339767Smmacy __F17HSETMASK(DE_DISPATCH_TOKEN_STALLS); 1765339767Smmacy break; 1766339767Smmacy case PMC_EV_F17H_EX_RET_INST: 1767339767Smmacy __F17HSETMASK(EX_RET_INST); 1768339767Smmacy break; 1769339767Smmacy case PMC_EV_F17H_EX_RET_COPS: 1770339767Smmacy __F17HSETMASK(EX_RET_COPS); 1771339767Smmacy break; 1772339767Smmacy case PMC_EV_F17H_EX_RET_BRN: 1773339767Smmacy __F17HSETMASK(EX_RET_BRN); 1774339767Smmacy break; 1775339767Smmacy case PMC_EV_F17H_EX_RET_BRN_MISP: 1776339767Smmacy __F17HSETMASK(EX_RET_BRN_MISP); 1777339767Smmacy break; 1778339767Smmacy case PMC_EV_F17H_EX_RET_BRN_TKN: 1779339767Smmacy __F17HSETMASK(EX_RET_BRN_TKN); 1780339767Smmacy break; 1781339767Smmacy case PMC_EV_F17H_EX_RET_BRN_TKN_MISP: 1782339767Smmacy __F17HSETMASK(EX_RET_BRN_TKN_MISP); 1783339767Smmacy break; 1784339767Smmacy case PMC_EV_F17H_EX_RET_BRN_FAR: 1785339767Smmacy __F17HSETMASK(EX_RET_BRN_FAR); 1786339767Smmacy break; 1787339767Smmacy case PMC_EV_F17H_EX_RET_BRN_RESYNC: 1788339767Smmacy __F17HSETMASK(EX_RET_BRN_RESYNC); 1789339767Smmacy break; 1790339767Smmacy case PMC_EV_F17H_EX_RET_BRN_NEAR_RET: 1791339767Smmacy __F17HSETMASK(EX_RET_BRN_NEAR_RET); 1792339767Smmacy break; 1793339767Smmacy case PMC_EV_F17H_EX_RET_BRN_NEAR_RET_MISPRED: 1794339767Smmacy __F17HSETMASK(EX_RET_BRN_NEAR_RET_MISPRED); 1795339767Smmacy break; 1796339767Smmacy case PMC_EV_F17H_EX_RET_BRN_IND_MISP: 1797339767Smmacy __F17HSETMASK(EX_RET_BRN_IND_MISP); 1798339767Smmacy break; 1799339767Smmacy case PMC_EV_F17H_EX_RET_MMX_FP_INSTR: 1800339767Smmacy __F17HSETMASK(EX_RET_MMX_FP_INSTR); 1801339767Smmacy break; 1802339767Smmacy case PMC_EV_F17H_EX_RET_COND_BRN: 1803339767Smmacy __F17HSETMASK(EX_RET_COND_BRN); 1804339767Smmacy break; 1805339767Smmacy case PMC_EV_F17H_EX_DIV_BUSY: 1806339767Smmacy __F17HSETMASK(EX_DIV_BUSY); 1807339767Smmacy break; 1808339767Smmacy case PMC_EV_F17H_EX_DIV_COUNT: 1809339767Smmacy __F17HSETMASK(EX_DIV_COUNT); 1810339767Smmacy break; 1811339767Smmacy case PMC_EV_F17H_L2_REQUEST_G1: 1812339767Smmacy __F17HSETMASK(L2_REQUEST_G1); 1813339767Smmacy break; 1814339767Smmacy case PMC_EV_F17H_L2_REQUEST_G2: 1815339767Smmacy __F17HSETMASK(L2_REQUEST_G2); 1816339767Smmacy break; 1817339767Smmacy case PMC_EV_F17H_L2_LATENCY: 1818339767Smmacy __F17HSETMASK(L2_LATENCY); 1819339767Smmacy break; 1820339767Smmacy case PMC_EV_F17H_L2_WBCREQ: 1821339767Smmacy __F17HSETMASK(L2_WBCREQ); 1822339767Smmacy break; 1823339767Smmacy case PMC_EV_F17H_L2_CACHEREQSTAT: 1824339767Smmacy __F17HSETMASK(L2_CACHEREQSTAT); 1825339767Smmacy break; 1826339767Smmacy case PMC_EV_F17H_L2_SMCEVENTS: 1827339767Smmacy __F17HSETMASK(L2_SMCEVENTS); 1828339767Smmacy break; 1829339767Smmacy case PMC_EV_F17H_L2_FILLPENDING: 1830339767Smmacy __F17HSETMASK(L2_FILLPENDING); 1831339767Smmacy break; 1832339767Smmacy case PMC_EV_F17H_EX_TAGGED_IBSOPS: 1833339767Smmacy __F17HSETMASK(EX_TAGGED_IBSOPS); 1834339767Smmacy break; 1835339767Smmacy case PMC_EV_F17H_EX_RET_FUSED_BRNCH_INST: 1836339767Smmacy __F17HSETMASK(EX_RET_FUSED_BRNCH_INST); 1837339767Smmacy break; 1838339767Smmacy default: 1839339767Smmacy printf(" %s failed, event not supported\n", __FUNCTION__); 1840339767Smmacy return -1; 1841339767Smmacy } 1842339767Smmacy while ((p = strsep(&ctrspec, ",")) != NULL) { 1843339767Smmacy if (KWPREFIXMATCH(p, F17H_KW_COUNT "=")) { 1844339767Smmacy q = strchr(p, '='); 1845339767Smmacy if (*++q == '\0') /* skip '=' */ 1846339767Smmacy return (-1); 1847339767Smmacy 1848339767Smmacy count = strtol(q, &e, 0); 1849339767Smmacy if (e == q || *e != '\0') 1850339767Smmacy return (-1); 1851339767Smmacy 1852339767Smmacy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 1853339767Smmacy pmc_config->pm_md.pm_amd.pm_amd_config |= 1854339767Smmacy AMD_PMC_TO_COUNTER(count); 1855339767Smmacy 1856339767Smmacy } else if (KWMATCH(p, F17H_KW_EDGE)) { 1857339767Smmacy pmc_config->pm_caps |= PMC_CAP_EDGE; 1858339767Smmacy } else if (KWMATCH(p, F17H_KW_INV)) { 1859339767Smmacy pmc_config->pm_caps |= PMC_CAP_INVERT; 1860339767Smmacy } else if (KWPREFIXMATCH(p, F17H_KW_MASK "=")) { 1861339767Smmacy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 1862339767Smmacy return (-1); 1863339767Smmacy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1864339767Smmacy } else if (KWMATCH(p, F17H_KW_OS)) { 1865339767Smmacy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 1866339767Smmacy } else if (KWMATCH(p, F17H_KW_USR)) { 1867339767Smmacy pmc_config->pm_caps |= PMC_CAP_USER; 1868339767Smmacy } else 1869339767Smmacy return (-1); 1870339767Smmacy} 1871339767Smmacy if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) { 1872339767Smmacy pmc_config->pm_md.pm_amd.pm_amd_config = 1873339767Smmacy AMD_PMC_TO_UNITMASK(evmask); 1874339767Smmacy } 1875339767Smmacy return 0; 1876339767Smmacy} 1877206089Sfabient/* 1878147191Sjkoshy * AMD K8 PMCs. 1879147191Sjkoshy * 1880147191Sjkoshy * These are very similar to AMD K7 PMCs, but support more kinds of 1881147191Sjkoshy * events. 1882147191Sjkoshy */ 1883147191Sjkoshy 1884147191Sjkoshystatic struct pmc_event_alias k8_aliases[] = { 1885147191Sjkoshy EV_ALIAS("branches", "k8-fr-retired-taken-branches"), 1886147191Sjkoshy EV_ALIAS("branch-mispredicts", 1887147191Sjkoshy "k8-fr-retired-taken-branches-mispredicted"), 1888147191Sjkoshy EV_ALIAS("cycles", "tsc"), 1889147191Sjkoshy EV_ALIAS("dc-misses", "k8-dc-miss"), 1890147191Sjkoshy EV_ALIAS("ic-misses", "k8-ic-miss"), 1891183107Sjkoshy EV_ALIAS("instructions", "k8-fr-retired-x86-instructions"), 1892147191Sjkoshy EV_ALIAS("interrupts", "k8-fr-taken-hardware-interrupts"), 1893155998Sjkoshy EV_ALIAS("unhalted-cycles", "k8-bu-cpu-clk-unhalted"), 1894147191Sjkoshy EV_ALIAS(NULL, NULL) 1895147191Sjkoshy}; 1896147191Sjkoshy 1897147191Sjkoshy#define __K8MASK(N,V) PMCMASK(N,(1 << (V))) 1898147191Sjkoshy 1899147191Sjkoshy/* 1900147191Sjkoshy * Parsing tables 1901147191Sjkoshy */ 1902147191Sjkoshy 1903147191Sjkoshy/* fp dispatched fpu ops */ 1904147191Sjkoshystatic const struct pmc_masks k8_mask_fdfo[] = { 1905147191Sjkoshy __K8MASK(add-pipe-excluding-junk-ops, 0), 1906147191Sjkoshy __K8MASK(multiply-pipe-excluding-junk-ops, 1), 1907147191Sjkoshy __K8MASK(store-pipe-excluding-junk-ops, 2), 1908147191Sjkoshy __K8MASK(add-pipe-junk-ops, 3), 1909147191Sjkoshy __K8MASK(multiply-pipe-junk-ops, 4), 1910147191Sjkoshy __K8MASK(store-pipe-junk-ops, 5), 1911147191Sjkoshy NULLMASK 1912147191Sjkoshy}; 1913147191Sjkoshy 1914147191Sjkoshy/* ls segment register loads */ 1915147191Sjkoshystatic const struct pmc_masks k8_mask_lsrl[] = { 1916147191Sjkoshy __K8MASK(es, 0), 1917147191Sjkoshy __K8MASK(cs, 1), 1918147191Sjkoshy __K8MASK(ss, 2), 1919147191Sjkoshy __K8MASK(ds, 3), 1920147191Sjkoshy __K8MASK(fs, 4), 1921147191Sjkoshy __K8MASK(gs, 5), 1922147191Sjkoshy __K8MASK(hs, 6), 1923147191Sjkoshy NULLMASK 1924147191Sjkoshy}; 1925147191Sjkoshy 1926147191Sjkoshy/* ls locked operation */ 1927147191Sjkoshystatic const struct pmc_masks k8_mask_llo[] = { 1928147191Sjkoshy __K8MASK(locked-instructions, 0), 1929147191Sjkoshy __K8MASK(cycles-in-request, 1), 1930147191Sjkoshy __K8MASK(cycles-to-complete, 2), 1931147191Sjkoshy NULLMASK 1932147191Sjkoshy}; 1933147191Sjkoshy 1934147191Sjkoshy/* dc refill from {l2,system} and dc copyback */ 1935147191Sjkoshystatic const struct pmc_masks k8_mask_dc[] = { 1936147191Sjkoshy __K8MASK(invalid, 0), 1937147191Sjkoshy __K8MASK(shared, 1), 1938147191Sjkoshy __K8MASK(exclusive, 2), 1939147191Sjkoshy __K8MASK(owner, 3), 1940147191Sjkoshy __K8MASK(modified, 4), 1941147191Sjkoshy NULLMASK 1942147191Sjkoshy}; 1943147191Sjkoshy 1944147191Sjkoshy/* dc one bit ecc error */ 1945147191Sjkoshystatic const struct pmc_masks k8_mask_dobee[] = { 1946147191Sjkoshy __K8MASK(scrubber, 0), 1947147191Sjkoshy __K8MASK(piggyback, 1), 1948147191Sjkoshy NULLMASK 1949147191Sjkoshy}; 1950147191Sjkoshy 1951147191Sjkoshy/* dc dispatched prefetch instructions */ 1952147191Sjkoshystatic const struct pmc_masks k8_mask_ddpi[] = { 1953147191Sjkoshy __K8MASK(load, 0), 1954147191Sjkoshy __K8MASK(store, 1), 1955147191Sjkoshy __K8MASK(nta, 2), 1956147191Sjkoshy NULLMASK 1957147191Sjkoshy}; 1958147191Sjkoshy 1959147191Sjkoshy/* dc dcache accesses by locks */ 1960147191Sjkoshystatic const struct pmc_masks k8_mask_dabl[] = { 1961147191Sjkoshy __K8MASK(accesses, 0), 1962147191Sjkoshy __K8MASK(misses, 1), 1963147191Sjkoshy NULLMASK 1964147191Sjkoshy}; 1965147191Sjkoshy 1966147191Sjkoshy/* bu internal l2 request */ 1967147191Sjkoshystatic const struct pmc_masks k8_mask_bilr[] = { 1968147191Sjkoshy __K8MASK(ic-fill, 0), 1969147191Sjkoshy __K8MASK(dc-fill, 1), 1970147191Sjkoshy __K8MASK(tlb-reload, 2), 1971147191Sjkoshy __K8MASK(tag-snoop, 3), 1972147191Sjkoshy __K8MASK(cancelled, 4), 1973147191Sjkoshy NULLMASK 1974147191Sjkoshy}; 1975147191Sjkoshy 1976147191Sjkoshy/* bu fill request l2 miss */ 1977147191Sjkoshystatic const struct pmc_masks k8_mask_bfrlm[] = { 1978147191Sjkoshy __K8MASK(ic-fill, 0), 1979147191Sjkoshy __K8MASK(dc-fill, 1), 1980147191Sjkoshy __K8MASK(tlb-reload, 2), 1981147191Sjkoshy NULLMASK 1982147191Sjkoshy}; 1983147191Sjkoshy 1984147191Sjkoshy/* bu fill into l2 */ 1985147191Sjkoshystatic const struct pmc_masks k8_mask_bfil[] = { 1986147191Sjkoshy __K8MASK(dirty-l2-victim, 0), 1987147191Sjkoshy __K8MASK(victim-from-l2, 1), 1988147191Sjkoshy NULLMASK 1989147191Sjkoshy}; 1990147191Sjkoshy 1991147191Sjkoshy/* fr retired fpu instructions */ 1992147191Sjkoshystatic const struct pmc_masks k8_mask_frfi[] = { 1993147191Sjkoshy __K8MASK(x87, 0), 1994147191Sjkoshy __K8MASK(mmx-3dnow, 1), 1995147191Sjkoshy __K8MASK(packed-sse-sse2, 2), 1996147191Sjkoshy __K8MASK(scalar-sse-sse2, 3), 1997147191Sjkoshy NULLMASK 1998147191Sjkoshy}; 1999147191Sjkoshy 2000147191Sjkoshy/* fr retired fastpath double op instructions */ 2001147191Sjkoshystatic const struct pmc_masks k8_mask_frfdoi[] = { 2002147191Sjkoshy __K8MASK(low-op-pos-0, 0), 2003147191Sjkoshy __K8MASK(low-op-pos-1, 1), 2004147191Sjkoshy __K8MASK(low-op-pos-2, 2), 2005147191Sjkoshy NULLMASK 2006147191Sjkoshy}; 2007147191Sjkoshy 2008147191Sjkoshy/* fr fpu exceptions */ 2009147191Sjkoshystatic const struct pmc_masks k8_mask_ffe[] = { 2010147191Sjkoshy __K8MASK(x87-reclass-microfaults, 0), 2011147191Sjkoshy __K8MASK(sse-retype-microfaults, 1), 2012147191Sjkoshy __K8MASK(sse-reclass-microfaults, 2), 2013147191Sjkoshy __K8MASK(sse-and-x87-microtraps, 3), 2014147191Sjkoshy NULLMASK 2015147191Sjkoshy}; 2016147191Sjkoshy 2017147191Sjkoshy/* nb memory controller page access event */ 2018147191Sjkoshystatic const struct pmc_masks k8_mask_nmcpae[] = { 2019147191Sjkoshy __K8MASK(page-hit, 0), 2020147191Sjkoshy __K8MASK(page-miss, 1), 2021147191Sjkoshy __K8MASK(page-conflict, 2), 2022147191Sjkoshy NULLMASK 2023147191Sjkoshy}; 2024147191Sjkoshy 2025147191Sjkoshy/* nb memory controller turnaround */ 2026147191Sjkoshystatic const struct pmc_masks k8_mask_nmct[] = { 2027147191Sjkoshy __K8MASK(dimm-turnaround, 0), 2028147191Sjkoshy __K8MASK(read-to-write-turnaround, 1), 2029147191Sjkoshy __K8MASK(write-to-read-turnaround, 2), 2030147191Sjkoshy NULLMASK 2031147191Sjkoshy}; 2032147191Sjkoshy 2033147191Sjkoshy/* nb memory controller bypass saturation */ 2034147191Sjkoshystatic const struct pmc_masks k8_mask_nmcbs[] = { 2035147191Sjkoshy __K8MASK(memory-controller-hi-pri-bypass, 0), 2036147191Sjkoshy __K8MASK(memory-controller-lo-pri-bypass, 1), 2037147191Sjkoshy __K8MASK(dram-controller-interface-bypass, 2), 2038147191Sjkoshy __K8MASK(dram-controller-queue-bypass, 3), 2039147191Sjkoshy NULLMASK 2040147191Sjkoshy}; 2041147191Sjkoshy 2042147191Sjkoshy/* nb sized commands */ 2043147191Sjkoshystatic const struct pmc_masks k8_mask_nsc[] = { 2044147191Sjkoshy __K8MASK(nonpostwrszbyte, 0), 2045147191Sjkoshy __K8MASK(nonpostwrszdword, 1), 2046147191Sjkoshy __K8MASK(postwrszbyte, 2), 2047147191Sjkoshy __K8MASK(postwrszdword, 3), 2048147191Sjkoshy __K8MASK(rdszbyte, 4), 2049147191Sjkoshy __K8MASK(rdszdword, 5), 2050147191Sjkoshy __K8MASK(rdmodwr, 6), 2051147191Sjkoshy NULLMASK 2052147191Sjkoshy}; 2053147191Sjkoshy 2054147191Sjkoshy/* nb probe result */ 2055147191Sjkoshystatic const struct pmc_masks k8_mask_npr[] = { 2056147191Sjkoshy __K8MASK(probe-miss, 0), 2057147191Sjkoshy __K8MASK(probe-hit, 1), 2058147191Sjkoshy __K8MASK(probe-hit-dirty-no-memory-cancel, 2), 2059147191Sjkoshy __K8MASK(probe-hit-dirty-with-memory-cancel, 3), 2060147191Sjkoshy NULLMASK 2061147191Sjkoshy}; 2062147191Sjkoshy 2063147191Sjkoshy/* nb hypertransport bus bandwidth */ 2064147191Sjkoshystatic const struct pmc_masks k8_mask_nhbb[] = { /* HT bus bandwidth */ 2065147191Sjkoshy __K8MASK(command, 0), 2066183107Sjkoshy __K8MASK(data, 1), 2067147191Sjkoshy __K8MASK(buffer-release, 2), 2068147191Sjkoshy __K8MASK(nop, 3), 2069147191Sjkoshy NULLMASK 2070147191Sjkoshy}; 2071147191Sjkoshy 2072147191Sjkoshy#undef __K8MASK 2073147191Sjkoshy 2074147191Sjkoshy#define K8_KW_COUNT "count" 2075147191Sjkoshy#define K8_KW_EDGE "edge" 2076147191Sjkoshy#define K8_KW_INV "inv" 2077147191Sjkoshy#define K8_KW_MASK "mask" 2078147191Sjkoshy#define K8_KW_OS "os" 2079147191Sjkoshy#define K8_KW_USR "usr" 2080147191Sjkoshy 2081147191Sjkoshystatic int 2082147191Sjkoshyk8_allocate_pmc(enum pmc_event pe, char *ctrspec, 2083147191Sjkoshy struct pmc_op_pmcallocate *pmc_config) 2084147191Sjkoshy{ 2085183107Sjkoshy char *e, *p, *q; 2086183107Sjkoshy int n; 2087240164Sfabient uint32_t count; 2088240164Sfabient uint64_t evmask; 2089147191Sjkoshy const struct pmc_masks *pm, *pmask; 2090147191Sjkoshy 2091183725Sjkoshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2092147191Sjkoshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 2093147191Sjkoshy 2094147191Sjkoshy pmask = NULL; 2095147191Sjkoshy evmask = 0; 2096147191Sjkoshy 2097147191Sjkoshy#define __K8SETMASK(M) pmask = k8_mask_##M 2098147191Sjkoshy 2099147191Sjkoshy /* setup parsing tables */ 2100147191Sjkoshy switch (pe) { 2101147191Sjkoshy case PMC_EV_K8_FP_DISPATCHED_FPU_OPS: 2102147191Sjkoshy __K8SETMASK(fdfo); 2103147191Sjkoshy break; 2104147191Sjkoshy case PMC_EV_K8_LS_SEGMENT_REGISTER_LOAD: 2105147191Sjkoshy __K8SETMASK(lsrl); 2106147191Sjkoshy break; 2107147191Sjkoshy case PMC_EV_K8_LS_LOCKED_OPERATION: 2108147191Sjkoshy __K8SETMASK(llo); 2109147191Sjkoshy break; 2110147191Sjkoshy case PMC_EV_K8_DC_REFILL_FROM_L2: 2111147191Sjkoshy case PMC_EV_K8_DC_REFILL_FROM_SYSTEM: 2112147191Sjkoshy case PMC_EV_K8_DC_COPYBACK: 2113147191Sjkoshy __K8SETMASK(dc); 2114147191Sjkoshy break; 2115147191Sjkoshy case PMC_EV_K8_DC_ONE_BIT_ECC_ERROR: 2116147191Sjkoshy __K8SETMASK(dobee); 2117147191Sjkoshy break; 2118147191Sjkoshy case PMC_EV_K8_DC_DISPATCHED_PREFETCH_INSTRUCTIONS: 2119147191Sjkoshy __K8SETMASK(ddpi); 2120147191Sjkoshy break; 2121147191Sjkoshy case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS: 2122147191Sjkoshy __K8SETMASK(dabl); 2123147191Sjkoshy break; 2124147191Sjkoshy case PMC_EV_K8_BU_INTERNAL_L2_REQUEST: 2125147191Sjkoshy __K8SETMASK(bilr); 2126147191Sjkoshy break; 2127147191Sjkoshy case PMC_EV_K8_BU_FILL_REQUEST_L2_MISS: 2128147191Sjkoshy __K8SETMASK(bfrlm); 2129147191Sjkoshy break; 2130147191Sjkoshy case PMC_EV_K8_BU_FILL_INTO_L2: 2131147191Sjkoshy __K8SETMASK(bfil); 2132147191Sjkoshy break; 2133147191Sjkoshy case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS: 2134147191Sjkoshy __K8SETMASK(frfi); 2135147191Sjkoshy break; 2136147191Sjkoshy case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS: 2137147191Sjkoshy __K8SETMASK(frfdoi); 2138147191Sjkoshy break; 2139147191Sjkoshy case PMC_EV_K8_FR_FPU_EXCEPTIONS: 2140147191Sjkoshy __K8SETMASK(ffe); 2141147191Sjkoshy break; 2142147191Sjkoshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_PAGE_ACCESS_EVENT: 2143147191Sjkoshy __K8SETMASK(nmcpae); 2144147191Sjkoshy break; 2145147191Sjkoshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_TURNAROUND: 2146147191Sjkoshy __K8SETMASK(nmct); 2147147191Sjkoshy break; 2148147191Sjkoshy case PMC_EV_K8_NB_MEMORY_CONTROLLER_BYPASS_SATURATION: 2149147191Sjkoshy __K8SETMASK(nmcbs); 2150147191Sjkoshy break; 2151147191Sjkoshy case PMC_EV_K8_NB_SIZED_COMMANDS: 2152147191Sjkoshy __K8SETMASK(nsc); 2153147191Sjkoshy break; 2154147191Sjkoshy case PMC_EV_K8_NB_PROBE_RESULT: 2155147191Sjkoshy __K8SETMASK(npr); 2156147191Sjkoshy break; 2157147191Sjkoshy case PMC_EV_K8_NB_HT_BUS0_BANDWIDTH: 2158147191Sjkoshy case PMC_EV_K8_NB_HT_BUS1_BANDWIDTH: 2159147191Sjkoshy case PMC_EV_K8_NB_HT_BUS2_BANDWIDTH: 2160147191Sjkoshy __K8SETMASK(nhbb); 2161147191Sjkoshy break; 2162147191Sjkoshy 2163147191Sjkoshy default: 2164147191Sjkoshy break; /* no options defined */ 2165147191Sjkoshy } 2166147191Sjkoshy 2167147191Sjkoshy while ((p = strsep(&ctrspec, ",")) != NULL) { 2168147191Sjkoshy if (KWPREFIXMATCH(p, K8_KW_COUNT "=")) { 2169147191Sjkoshy q = strchr(p, '='); 2170147191Sjkoshy if (*++q == '\0') /* skip '=' */ 2171174406Sjkoshy return (-1); 2172147191Sjkoshy 2173147191Sjkoshy count = strtol(q, &e, 0); 2174147191Sjkoshy if (e == q || *e != '\0') 2175174406Sjkoshy return (-1); 2176147191Sjkoshy 2177147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 2178147191Sjkoshy pmc_config->pm_md.pm_amd.pm_amd_config |= 2179147191Sjkoshy AMD_PMC_TO_COUNTER(count); 2180147191Sjkoshy 2181147191Sjkoshy } else if (KWMATCH(p, K8_KW_EDGE)) { 2182147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_EDGE; 2183147191Sjkoshy } else if (KWMATCH(p, K8_KW_INV)) { 2184147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_INVERT; 2185147191Sjkoshy } else if (KWPREFIXMATCH(p, K8_KW_MASK "=")) { 2186147191Sjkoshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 2187174406Sjkoshy return (-1); 2188147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2189147191Sjkoshy } else if (KWMATCH(p, K8_KW_OS)) { 2190147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2191147191Sjkoshy } else if (KWMATCH(p, K8_KW_USR)) { 2192147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_USER; 2193147191Sjkoshy } else 2194174406Sjkoshy return (-1); 2195147191Sjkoshy } 2196147191Sjkoshy 2197147191Sjkoshy /* other post processing */ 2198147191Sjkoshy switch (pe) { 2199147191Sjkoshy case PMC_EV_K8_FP_DISPATCHED_FPU_OPS: 2200147191Sjkoshy case PMC_EV_K8_FP_CYCLES_WITH_NO_FPU_OPS_RETIRED: 2201147191Sjkoshy case PMC_EV_K8_FP_DISPATCHED_FPU_FAST_FLAG_OPS: 2202147191Sjkoshy case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS: 2203147191Sjkoshy case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS: 2204147191Sjkoshy case PMC_EV_K8_FR_FPU_EXCEPTIONS: 2205147191Sjkoshy /* XXX only available in rev B and later */ 2206147191Sjkoshy break; 2207147191Sjkoshy case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS: 2208147191Sjkoshy /* XXX only available in rev C and later */ 2209147191Sjkoshy break; 2210147191Sjkoshy case PMC_EV_K8_LS_LOCKED_OPERATION: 2211147191Sjkoshy /* XXX CPU Rev A,B evmask is to be zero */ 2212147191Sjkoshy if (evmask & (evmask - 1)) /* > 1 bit set */ 2213174406Sjkoshy return (-1); 2214147191Sjkoshy if (evmask == 0) { 2215147191Sjkoshy evmask = 0x01; /* Rev C and later: #instrs */ 2216147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2217147191Sjkoshy } 2218147191Sjkoshy break; 2219147191Sjkoshy default: 2220147191Sjkoshy if (evmask == 0 && pmask != NULL) { 2221147191Sjkoshy for (pm = pmask; pm->pm_name; pm++) 2222147191Sjkoshy evmask |= pm->pm_value; 2223147191Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2224147191Sjkoshy } 2225147191Sjkoshy } 2226147191Sjkoshy 2227147191Sjkoshy if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) 2228147191Sjkoshy pmc_config->pm_md.pm_amd.pm_amd_config = 2229147191Sjkoshy AMD_PMC_TO_UNITMASK(evmask); 2230147191Sjkoshy 2231174406Sjkoshy return (0); 2232147191Sjkoshy} 2233147191Sjkoshy 2234147191Sjkoshy#endif 2235147191Sjkoshy 2236147759Sjkoshy#if defined(__amd64__) || defined(__i386__) 2237147191Sjkoshy 2238147191Sjkoshy/* 2239145256Sjkoshy * Intel P4 PMCs 2240145256Sjkoshy */ 2241145256Sjkoshy 2242145256Sjkoshystatic struct pmc_event_alias p4_aliases[] = { 2243145351Sjkoshy EV_ALIAS("branches", "p4-branch-retired,mask=mmtp+mmtm"), 2244145351Sjkoshy EV_ALIAS("branch-mispredicts", "p4-mispred-branch-retired"), 2245145351Sjkoshy EV_ALIAS("cycles", "tsc"), 2246145351Sjkoshy EV_ALIAS("instructions", 2247145351Sjkoshy "p4-instr-retired,mask=nbogusntag+nbogustag"), 2248155998Sjkoshy EV_ALIAS("unhalted-cycles", "p4-global-power-events"), 2249145256Sjkoshy EV_ALIAS(NULL, NULL) 2250145256Sjkoshy}; 2251145256Sjkoshy 2252145256Sjkoshy#define P4_KW_ACTIVE "active" 2253145256Sjkoshy#define P4_KW_ACTIVE_ANY "any" 2254145256Sjkoshy#define P4_KW_ACTIVE_BOTH "both" 2255145256Sjkoshy#define P4_KW_ACTIVE_NONE "none" 2256145256Sjkoshy#define P4_KW_ACTIVE_SINGLE "single" 2257145256Sjkoshy#define P4_KW_BUSREQTYPE "busreqtype" 2258145256Sjkoshy#define P4_KW_CASCADE "cascade" 2259145256Sjkoshy#define P4_KW_EDGE "edge" 2260145256Sjkoshy#define P4_KW_INV "complement" 2261145256Sjkoshy#define P4_KW_OS "os" 2262145256Sjkoshy#define P4_KW_MASK "mask" 2263145256Sjkoshy#define P4_KW_PRECISE "precise" 2264145256Sjkoshy#define P4_KW_TAG "tag" 2265145256Sjkoshy#define P4_KW_THRESHOLD "threshold" 2266145256Sjkoshy#define P4_KW_USR "usr" 2267145256Sjkoshy 2268145256Sjkoshy#define __P4MASK(N,V) PMCMASK(N, (1 << (V))) 2269145256Sjkoshy 2270145256Sjkoshystatic const struct pmc_masks p4_mask_tcdm[] = { /* tc deliver mode */ 2271145256Sjkoshy __P4MASK(dd, 0), 2272145256Sjkoshy __P4MASK(db, 1), 2273145256Sjkoshy __P4MASK(di, 2), 2274145256Sjkoshy __P4MASK(bd, 3), 2275145256Sjkoshy __P4MASK(bb, 4), 2276145256Sjkoshy __P4MASK(bi, 5), 2277145256Sjkoshy __P4MASK(id, 6), 2278145256Sjkoshy __P4MASK(ib, 7), 2279145256Sjkoshy NULLMASK 2280145256Sjkoshy}; 2281145256Sjkoshy 2282145256Sjkoshystatic const struct pmc_masks p4_mask_bfr[] = { /* bpu fetch request */ 2283145256Sjkoshy __P4MASK(tcmiss, 0), 2284145256Sjkoshy NULLMASK, 2285145256Sjkoshy}; 2286145256Sjkoshy 2287145256Sjkoshystatic const struct pmc_masks p4_mask_ir[] = { /* itlb reference */ 2288145256Sjkoshy __P4MASK(hit, 0), 2289145256Sjkoshy __P4MASK(miss, 1), 2290145256Sjkoshy __P4MASK(hit-uc, 2), 2291145256Sjkoshy NULLMASK 2292145256Sjkoshy}; 2293145256Sjkoshy 2294145256Sjkoshystatic const struct pmc_masks p4_mask_memcan[] = { /* memory cancel */ 2295145256Sjkoshy __P4MASK(st-rb-full, 2), 2296145256Sjkoshy __P4MASK(64k-conf, 3), 2297145256Sjkoshy NULLMASK 2298145256Sjkoshy}; 2299145256Sjkoshy 2300145256Sjkoshystatic const struct pmc_masks p4_mask_memcomp[] = { /* memory complete */ 2301145256Sjkoshy __P4MASK(lsc, 0), 2302145256Sjkoshy __P4MASK(ssc, 1), 2303145256Sjkoshy NULLMASK 2304145256Sjkoshy}; 2305145256Sjkoshy 2306145256Sjkoshystatic const struct pmc_masks p4_mask_lpr[] = { /* load port replay */ 2307145256Sjkoshy __P4MASK(split-ld, 1), 2308145256Sjkoshy NULLMASK 2309145256Sjkoshy}; 2310145256Sjkoshy 2311145256Sjkoshystatic const struct pmc_masks p4_mask_spr[] = { /* store port replay */ 2312145256Sjkoshy __P4MASK(split-st, 1), 2313145256Sjkoshy NULLMASK 2314145256Sjkoshy}; 2315145256Sjkoshy 2316145256Sjkoshystatic const struct pmc_masks p4_mask_mlr[] = { /* mob load replay */ 2317145256Sjkoshy __P4MASK(no-sta, 1), 2318145256Sjkoshy __P4MASK(no-std, 3), 2319145256Sjkoshy __P4MASK(partial-data, 4), 2320145256Sjkoshy __P4MASK(unalgn-addr, 5), 2321145256Sjkoshy NULLMASK 2322145256Sjkoshy}; 2323145256Sjkoshy 2324145256Sjkoshystatic const struct pmc_masks p4_mask_pwt[] = { /* page walk type */ 2325145256Sjkoshy __P4MASK(dtmiss, 0), 2326145256Sjkoshy __P4MASK(itmiss, 1), 2327145256Sjkoshy NULLMASK 2328145256Sjkoshy}; 2329145256Sjkoshy 2330145256Sjkoshystatic const struct pmc_masks p4_mask_bcr[] = { /* bsq cache reference */ 2331145256Sjkoshy __P4MASK(rd-2ndl-hits, 0), 2332145256Sjkoshy __P4MASK(rd-2ndl-hite, 1), 2333145256Sjkoshy __P4MASK(rd-2ndl-hitm, 2), 2334145256Sjkoshy __P4MASK(rd-3rdl-hits, 3), 2335145256Sjkoshy __P4MASK(rd-3rdl-hite, 4), 2336145256Sjkoshy __P4MASK(rd-3rdl-hitm, 5), 2337145256Sjkoshy __P4MASK(rd-2ndl-miss, 8), 2338145256Sjkoshy __P4MASK(rd-3rdl-miss, 9), 2339145256Sjkoshy __P4MASK(wr-2ndl-miss, 10), 2340145256Sjkoshy NULLMASK 2341145256Sjkoshy}; 2342145256Sjkoshy 2343145256Sjkoshystatic const struct pmc_masks p4_mask_ia[] = { /* ioq allocation */ 2344145256Sjkoshy __P4MASK(all-read, 5), 2345145256Sjkoshy __P4MASK(all-write, 6), 2346145256Sjkoshy __P4MASK(mem-uc, 7), 2347145256Sjkoshy __P4MASK(mem-wc, 8), 2348145256Sjkoshy __P4MASK(mem-wt, 9), 2349145256Sjkoshy __P4MASK(mem-wp, 10), 2350145256Sjkoshy __P4MASK(mem-wb, 11), 2351145256Sjkoshy __P4MASK(own, 13), 2352145256Sjkoshy __P4MASK(other, 14), 2353145256Sjkoshy __P4MASK(prefetch, 15), 2354145256Sjkoshy NULLMASK 2355145256Sjkoshy}; 2356145256Sjkoshy 2357145256Sjkoshystatic const struct pmc_masks p4_mask_iae[] = { /* ioq active entries */ 2358145256Sjkoshy __P4MASK(all-read, 5), 2359145256Sjkoshy __P4MASK(all-write, 6), 2360145256Sjkoshy __P4MASK(mem-uc, 7), 2361145256Sjkoshy __P4MASK(mem-wc, 8), 2362145256Sjkoshy __P4MASK(mem-wt, 9), 2363145256Sjkoshy __P4MASK(mem-wp, 10), 2364145256Sjkoshy __P4MASK(mem-wb, 11), 2365145256Sjkoshy __P4MASK(own, 13), 2366145256Sjkoshy __P4MASK(other, 14), 2367145256Sjkoshy __P4MASK(prefetch, 15), 2368145256Sjkoshy NULLMASK 2369145256Sjkoshy}; 2370145256Sjkoshy 2371145256Sjkoshystatic const struct pmc_masks p4_mask_fda[] = { /* fsb data activity */ 2372145256Sjkoshy __P4MASK(drdy-drv, 0), 2373145256Sjkoshy __P4MASK(drdy-own, 1), 2374145256Sjkoshy __P4MASK(drdy-other, 2), 2375145256Sjkoshy __P4MASK(dbsy-drv, 3), 2376145256Sjkoshy __P4MASK(dbsy-own, 4), 2377145256Sjkoshy __P4MASK(dbsy-other, 5), 2378145256Sjkoshy NULLMASK 2379145256Sjkoshy}; 2380145256Sjkoshy 2381145256Sjkoshystatic const struct pmc_masks p4_mask_ba[] = { /* bsq allocation */ 2382145256Sjkoshy __P4MASK(req-type0, 0), 2383145256Sjkoshy __P4MASK(req-type1, 1), 2384145256Sjkoshy __P4MASK(req-len0, 2), 2385145256Sjkoshy __P4MASK(req-len1, 3), 2386145256Sjkoshy __P4MASK(req-io-type, 5), 2387145256Sjkoshy __P4MASK(req-lock-type, 6), 2388145256Sjkoshy __P4MASK(req-cache-type, 7), 2389145256Sjkoshy __P4MASK(req-split-type, 8), 2390145256Sjkoshy __P4MASK(req-dem-type, 9), 2391145256Sjkoshy __P4MASK(req-ord-type, 10), 2392145256Sjkoshy __P4MASK(mem-type0, 11), 2393145256Sjkoshy __P4MASK(mem-type1, 12), 2394145256Sjkoshy __P4MASK(mem-type2, 13), 2395145256Sjkoshy NULLMASK 2396145256Sjkoshy}; 2397145256Sjkoshy 2398145256Sjkoshystatic const struct pmc_masks p4_mask_sia[] = { /* sse input assist */ 2399145256Sjkoshy __P4MASK(all, 15), 2400145256Sjkoshy NULLMASK 2401145256Sjkoshy}; 2402145256Sjkoshy 2403145256Sjkoshystatic const struct pmc_masks p4_mask_psu[] = { /* packed sp uop */ 2404145256Sjkoshy __P4MASK(all, 15), 2405145256Sjkoshy NULLMASK 2406145256Sjkoshy}; 2407145256Sjkoshy 2408145256Sjkoshystatic const struct pmc_masks p4_mask_pdu[] = { /* packed dp uop */ 2409145256Sjkoshy __P4MASK(all, 15), 2410145256Sjkoshy NULLMASK 2411145256Sjkoshy}; 2412145256Sjkoshy 2413145256Sjkoshystatic const struct pmc_masks p4_mask_ssu[] = { /* scalar sp uop */ 2414145256Sjkoshy __P4MASK(all, 15), 2415145256Sjkoshy NULLMASK 2416145256Sjkoshy}; 2417145256Sjkoshy 2418145256Sjkoshystatic const struct pmc_masks p4_mask_sdu[] = { /* scalar dp uop */ 2419145256Sjkoshy __P4MASK(all, 15), 2420145256Sjkoshy NULLMASK 2421145256Sjkoshy}; 2422145256Sjkoshy 2423145256Sjkoshystatic const struct pmc_masks p4_mask_64bmu[] = { /* 64 bit mmx uop */ 2424145256Sjkoshy __P4MASK(all, 15), 2425145256Sjkoshy NULLMASK 2426145256Sjkoshy}; 2427145256Sjkoshy 2428145256Sjkoshystatic const struct pmc_masks p4_mask_128bmu[] = { /* 128 bit mmx uop */ 2429145256Sjkoshy __P4MASK(all, 15), 2430145256Sjkoshy NULLMASK 2431145256Sjkoshy}; 2432145256Sjkoshy 2433145256Sjkoshystatic const struct pmc_masks p4_mask_xfu[] = { /* X87 fp uop */ 2434145256Sjkoshy __P4MASK(all, 15), 2435145256Sjkoshy NULLMASK 2436145256Sjkoshy}; 2437145256Sjkoshy 2438145256Sjkoshystatic const struct pmc_masks p4_mask_xsmu[] = { /* x87 simd moves uop */ 2439145256Sjkoshy __P4MASK(allp0, 3), 2440145256Sjkoshy __P4MASK(allp2, 4), 2441145256Sjkoshy NULLMASK 2442145256Sjkoshy}; 2443145256Sjkoshy 2444145256Sjkoshystatic const struct pmc_masks p4_mask_gpe[] = { /* global power events */ 2445145256Sjkoshy __P4MASK(running, 0), 2446145256Sjkoshy NULLMASK 2447145256Sjkoshy}; 2448145256Sjkoshy 2449145256Sjkoshystatic const struct pmc_masks p4_mask_tmx[] = { /* TC ms xfer */ 2450145256Sjkoshy __P4MASK(cisc, 0), 2451145256Sjkoshy NULLMASK 2452145256Sjkoshy}; 2453145256Sjkoshy 2454145256Sjkoshystatic const struct pmc_masks p4_mask_uqw[] = { /* uop queue writes */ 2455145256Sjkoshy __P4MASK(from-tc-build, 0), 2456145256Sjkoshy __P4MASK(from-tc-deliver, 1), 2457145256Sjkoshy __P4MASK(from-rom, 2), 2458145256Sjkoshy NULLMASK 2459145256Sjkoshy}; 2460145256Sjkoshy 2461145351Sjkoshystatic const struct pmc_masks p4_mask_rmbt[] = { 2462145351Sjkoshy /* retired mispred branch type */ 2463145256Sjkoshy __P4MASK(conditional, 1), 2464145256Sjkoshy __P4MASK(call, 2), 2465145256Sjkoshy __P4MASK(return, 3), 2466145256Sjkoshy __P4MASK(indirect, 4), 2467145256Sjkoshy NULLMASK 2468145256Sjkoshy}; 2469145256Sjkoshy 2470145256Sjkoshystatic const struct pmc_masks p4_mask_rbt[] = { /* retired branch type */ 2471145256Sjkoshy __P4MASK(conditional, 1), 2472145256Sjkoshy __P4MASK(call, 2), 2473145256Sjkoshy __P4MASK(retired, 3), 2474145256Sjkoshy __P4MASK(indirect, 4), 2475145256Sjkoshy NULLMASK 2476145256Sjkoshy}; 2477145256Sjkoshy 2478145256Sjkoshystatic const struct pmc_masks p4_mask_rs[] = { /* resource stall */ 2479145256Sjkoshy __P4MASK(sbfull, 5), 2480145256Sjkoshy NULLMASK 2481145256Sjkoshy}; 2482145256Sjkoshy 2483145256Sjkoshystatic const struct pmc_masks p4_mask_wb[] = { /* WC buffer */ 2484145256Sjkoshy __P4MASK(wcb-evicts, 0), 2485145256Sjkoshy __P4MASK(wcb-full-evict, 1), 2486145256Sjkoshy NULLMASK 2487145256Sjkoshy}; 2488145256Sjkoshy 2489145256Sjkoshystatic const struct pmc_masks p4_mask_fee[] = { /* front end event */ 2490145256Sjkoshy __P4MASK(nbogus, 0), 2491145256Sjkoshy __P4MASK(bogus, 1), 2492145256Sjkoshy NULLMASK 2493145256Sjkoshy}; 2494145256Sjkoshy 2495145256Sjkoshystatic const struct pmc_masks p4_mask_ee[] = { /* execution event */ 2496145256Sjkoshy __P4MASK(nbogus0, 0), 2497145256Sjkoshy __P4MASK(nbogus1, 1), 2498145256Sjkoshy __P4MASK(nbogus2, 2), 2499145256Sjkoshy __P4MASK(nbogus3, 3), 2500145256Sjkoshy __P4MASK(bogus0, 4), 2501145256Sjkoshy __P4MASK(bogus1, 5), 2502145256Sjkoshy __P4MASK(bogus2, 6), 2503145256Sjkoshy __P4MASK(bogus3, 7), 2504145256Sjkoshy NULLMASK 2505145256Sjkoshy}; 2506145256Sjkoshy 2507145256Sjkoshystatic const struct pmc_masks p4_mask_re[] = { /* replay event */ 2508145256Sjkoshy __P4MASK(nbogus, 0), 2509145256Sjkoshy __P4MASK(bogus, 1), 2510145256Sjkoshy NULLMASK 2511145256Sjkoshy}; 2512145256Sjkoshy 2513145256Sjkoshystatic const struct pmc_masks p4_mask_insret[] = { /* instr retired */ 2514145256Sjkoshy __P4MASK(nbogusntag, 0), 2515145256Sjkoshy __P4MASK(nbogustag, 1), 2516145256Sjkoshy __P4MASK(bogusntag, 2), 2517145256Sjkoshy __P4MASK(bogustag, 3), 2518145256Sjkoshy NULLMASK 2519145256Sjkoshy}; 2520145256Sjkoshy 2521145256Sjkoshystatic const struct pmc_masks p4_mask_ur[] = { /* uops retired */ 2522145256Sjkoshy __P4MASK(nbogus, 0), 2523145256Sjkoshy __P4MASK(bogus, 1), 2524145256Sjkoshy NULLMASK 2525145256Sjkoshy}; 2526145256Sjkoshy 2527145256Sjkoshystatic const struct pmc_masks p4_mask_ut[] = { /* uop type */ 2528145256Sjkoshy __P4MASK(tagloads, 1), 2529145256Sjkoshy __P4MASK(tagstores, 2), 2530145256Sjkoshy NULLMASK 2531145256Sjkoshy}; 2532145256Sjkoshy 2533145256Sjkoshystatic const struct pmc_masks p4_mask_br[] = { /* branch retired */ 2534145256Sjkoshy __P4MASK(mmnp, 0), 2535145256Sjkoshy __P4MASK(mmnm, 1), 2536145256Sjkoshy __P4MASK(mmtp, 2), 2537145256Sjkoshy __P4MASK(mmtm, 3), 2538145256Sjkoshy NULLMASK 2539145256Sjkoshy}; 2540145256Sjkoshy 2541145256Sjkoshystatic const struct pmc_masks p4_mask_mbr[] = { /* mispred branch retired */ 2542145256Sjkoshy __P4MASK(nbogus, 0), 2543145256Sjkoshy NULLMASK 2544145256Sjkoshy}; 2545145256Sjkoshy 2546145256Sjkoshystatic const struct pmc_masks p4_mask_xa[] = { /* x87 assist */ 2547145256Sjkoshy __P4MASK(fpsu, 0), 2548145256Sjkoshy __P4MASK(fpso, 1), 2549145256Sjkoshy __P4MASK(poao, 2), 2550145256Sjkoshy __P4MASK(poau, 3), 2551145256Sjkoshy __P4MASK(prea, 4), 2552145256Sjkoshy NULLMASK 2553145256Sjkoshy}; 2554145256Sjkoshy 2555145256Sjkoshystatic const struct pmc_masks p4_mask_machclr[] = { /* machine clear */ 2556145256Sjkoshy __P4MASK(clear, 0), 2557145256Sjkoshy __P4MASK(moclear, 2), 2558145256Sjkoshy __P4MASK(smclear, 3), 2559145256Sjkoshy NULLMASK 2560145256Sjkoshy}; 2561145256Sjkoshy 2562145256Sjkoshy/* P4 event parser */ 2563145256Sjkoshystatic int 2564145256Sjkoshyp4_allocate_pmc(enum pmc_event pe, char *ctrspec, 2565145256Sjkoshy struct pmc_op_pmcallocate *pmc_config) 2566145256Sjkoshy{ 2567145256Sjkoshy 2568145256Sjkoshy char *e, *p, *q; 2569145256Sjkoshy int count, has_tag, has_busreqtype, n; 2570240164Sfabient uint32_t cccractivemask; 2571240164Sfabient uint64_t evmask; 2572145256Sjkoshy const struct pmc_masks *pm, *pmask; 2573145256Sjkoshy 2574183725Sjkoshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 2575147191Sjkoshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig = 2576147191Sjkoshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 0; 2577145256Sjkoshy 2578145256Sjkoshy pmask = NULL; 2579145256Sjkoshy evmask = 0; 2580145256Sjkoshy cccractivemask = 0x3; 2581145256Sjkoshy has_tag = has_busreqtype = 0; 2582145256Sjkoshy 2583145256Sjkoshy#define __P4SETMASK(M) do { \ 2584183107Sjkoshy pmask = p4_mask_##M; \ 2585145256Sjkoshy} while (0) 2586145256Sjkoshy 2587145256Sjkoshy switch (pe) { 2588145256Sjkoshy case PMC_EV_P4_TC_DELIVER_MODE: 2589145256Sjkoshy __P4SETMASK(tcdm); 2590145256Sjkoshy break; 2591145256Sjkoshy case PMC_EV_P4_BPU_FETCH_REQUEST: 2592145256Sjkoshy __P4SETMASK(bfr); 2593145256Sjkoshy break; 2594145256Sjkoshy case PMC_EV_P4_ITLB_REFERENCE: 2595145256Sjkoshy __P4SETMASK(ir); 2596145256Sjkoshy break; 2597145256Sjkoshy case PMC_EV_P4_MEMORY_CANCEL: 2598145256Sjkoshy __P4SETMASK(memcan); 2599145256Sjkoshy break; 2600145256Sjkoshy case PMC_EV_P4_MEMORY_COMPLETE: 2601145256Sjkoshy __P4SETMASK(memcomp); 2602145256Sjkoshy break; 2603145256Sjkoshy case PMC_EV_P4_LOAD_PORT_REPLAY: 2604145256Sjkoshy __P4SETMASK(lpr); 2605145256Sjkoshy break; 2606145256Sjkoshy case PMC_EV_P4_STORE_PORT_REPLAY: 2607145256Sjkoshy __P4SETMASK(spr); 2608145256Sjkoshy break; 2609145256Sjkoshy case PMC_EV_P4_MOB_LOAD_REPLAY: 2610145256Sjkoshy __P4SETMASK(mlr); 2611145256Sjkoshy break; 2612145256Sjkoshy case PMC_EV_P4_PAGE_WALK_TYPE: 2613145256Sjkoshy __P4SETMASK(pwt); 2614145256Sjkoshy break; 2615145256Sjkoshy case PMC_EV_P4_BSQ_CACHE_REFERENCE: 2616145256Sjkoshy __P4SETMASK(bcr); 2617145256Sjkoshy break; 2618145256Sjkoshy case PMC_EV_P4_IOQ_ALLOCATION: 2619145256Sjkoshy __P4SETMASK(ia); 2620145256Sjkoshy has_busreqtype = 1; 2621145256Sjkoshy break; 2622145256Sjkoshy case PMC_EV_P4_IOQ_ACTIVE_ENTRIES: 2623145256Sjkoshy __P4SETMASK(iae); 2624145256Sjkoshy has_busreqtype = 1; 2625145256Sjkoshy break; 2626145256Sjkoshy case PMC_EV_P4_FSB_DATA_ACTIVITY: 2627145256Sjkoshy __P4SETMASK(fda); 2628145256Sjkoshy break; 2629145256Sjkoshy case PMC_EV_P4_BSQ_ALLOCATION: 2630145256Sjkoshy __P4SETMASK(ba); 2631145256Sjkoshy break; 2632145256Sjkoshy case PMC_EV_P4_SSE_INPUT_ASSIST: 2633145256Sjkoshy __P4SETMASK(sia); 2634145256Sjkoshy break; 2635145256Sjkoshy case PMC_EV_P4_PACKED_SP_UOP: 2636145256Sjkoshy __P4SETMASK(psu); 2637145256Sjkoshy break; 2638145256Sjkoshy case PMC_EV_P4_PACKED_DP_UOP: 2639145256Sjkoshy __P4SETMASK(pdu); 2640145256Sjkoshy break; 2641145256Sjkoshy case PMC_EV_P4_SCALAR_SP_UOP: 2642145256Sjkoshy __P4SETMASK(ssu); 2643145256Sjkoshy break; 2644145256Sjkoshy case PMC_EV_P4_SCALAR_DP_UOP: 2645145256Sjkoshy __P4SETMASK(sdu); 2646145256Sjkoshy break; 2647145256Sjkoshy case PMC_EV_P4_64BIT_MMX_UOP: 2648145256Sjkoshy __P4SETMASK(64bmu); 2649145256Sjkoshy break; 2650145256Sjkoshy case PMC_EV_P4_128BIT_MMX_UOP: 2651145256Sjkoshy __P4SETMASK(128bmu); 2652145256Sjkoshy break; 2653145256Sjkoshy case PMC_EV_P4_X87_FP_UOP: 2654145256Sjkoshy __P4SETMASK(xfu); 2655145256Sjkoshy break; 2656145256Sjkoshy case PMC_EV_P4_X87_SIMD_MOVES_UOP: 2657145256Sjkoshy __P4SETMASK(xsmu); 2658145256Sjkoshy break; 2659145256Sjkoshy case PMC_EV_P4_GLOBAL_POWER_EVENTS: 2660145256Sjkoshy __P4SETMASK(gpe); 2661145256Sjkoshy break; 2662145256Sjkoshy case PMC_EV_P4_TC_MS_XFER: 2663145256Sjkoshy __P4SETMASK(tmx); 2664145256Sjkoshy break; 2665145256Sjkoshy case PMC_EV_P4_UOP_QUEUE_WRITES: 2666145256Sjkoshy __P4SETMASK(uqw); 2667145256Sjkoshy break; 2668145256Sjkoshy case PMC_EV_P4_RETIRED_MISPRED_BRANCH_TYPE: 2669145256Sjkoshy __P4SETMASK(rmbt); 2670145256Sjkoshy break; 2671145256Sjkoshy case PMC_EV_P4_RETIRED_BRANCH_TYPE: 2672145256Sjkoshy __P4SETMASK(rbt); 2673145256Sjkoshy break; 2674145256Sjkoshy case PMC_EV_P4_RESOURCE_STALL: 2675145256Sjkoshy __P4SETMASK(rs); 2676145256Sjkoshy break; 2677145256Sjkoshy case PMC_EV_P4_WC_BUFFER: 2678145256Sjkoshy __P4SETMASK(wb); 2679145256Sjkoshy break; 2680145256Sjkoshy case PMC_EV_P4_BSQ_ACTIVE_ENTRIES: 2681145256Sjkoshy case PMC_EV_P4_B2B_CYCLES: 2682145256Sjkoshy case PMC_EV_P4_BNR: 2683145256Sjkoshy case PMC_EV_P4_SNOOP: 2684145256Sjkoshy case PMC_EV_P4_RESPONSE: 2685145256Sjkoshy break; 2686145256Sjkoshy case PMC_EV_P4_FRONT_END_EVENT: 2687145256Sjkoshy __P4SETMASK(fee); 2688145256Sjkoshy break; 2689145256Sjkoshy case PMC_EV_P4_EXECUTION_EVENT: 2690145256Sjkoshy __P4SETMASK(ee); 2691145256Sjkoshy break; 2692145256Sjkoshy case PMC_EV_P4_REPLAY_EVENT: 2693145256Sjkoshy __P4SETMASK(re); 2694145256Sjkoshy break; 2695145256Sjkoshy case PMC_EV_P4_INSTR_RETIRED: 2696145256Sjkoshy __P4SETMASK(insret); 2697145256Sjkoshy break; 2698145256Sjkoshy case PMC_EV_P4_UOPS_RETIRED: 2699145256Sjkoshy __P4SETMASK(ur); 2700145256Sjkoshy break; 2701145256Sjkoshy case PMC_EV_P4_UOP_TYPE: 2702145256Sjkoshy __P4SETMASK(ut); 2703145256Sjkoshy break; 2704145256Sjkoshy case PMC_EV_P4_BRANCH_RETIRED: 2705145256Sjkoshy __P4SETMASK(br); 2706145256Sjkoshy break; 2707145256Sjkoshy case PMC_EV_P4_MISPRED_BRANCH_RETIRED: 2708145256Sjkoshy __P4SETMASK(mbr); 2709145256Sjkoshy break; 2710145256Sjkoshy case PMC_EV_P4_X87_ASSIST: 2711145256Sjkoshy __P4SETMASK(xa); 2712145256Sjkoshy break; 2713145256Sjkoshy case PMC_EV_P4_MACHINE_CLEAR: 2714145256Sjkoshy __P4SETMASK(machclr); 2715145256Sjkoshy break; 2716145256Sjkoshy default: 2717174406Sjkoshy return (-1); 2718145256Sjkoshy } 2719145256Sjkoshy 2720145256Sjkoshy /* process additional flags */ 2721145256Sjkoshy while ((p = strsep(&ctrspec, ",")) != NULL) { 2722145256Sjkoshy if (KWPREFIXMATCH(p, P4_KW_ACTIVE)) { 2723145256Sjkoshy q = strchr(p, '='); 2724145256Sjkoshy if (*++q == '\0') /* skip '=' */ 2725174406Sjkoshy return (-1); 2726145256Sjkoshy 2727183725Sjkoshy if (strcasecmp(q, P4_KW_ACTIVE_NONE) == 0) 2728145256Sjkoshy cccractivemask = 0x0; 2729183725Sjkoshy else if (strcasecmp(q, P4_KW_ACTIVE_SINGLE) == 0) 2730145256Sjkoshy cccractivemask = 0x1; 2731183725Sjkoshy else if (strcasecmp(q, P4_KW_ACTIVE_BOTH) == 0) 2732145256Sjkoshy cccractivemask = 0x2; 2733183725Sjkoshy else if (strcasecmp(q, P4_KW_ACTIVE_ANY) == 0) 2734145256Sjkoshy cccractivemask = 0x3; 2735145256Sjkoshy else 2736174406Sjkoshy return (-1); 2737145256Sjkoshy 2738145256Sjkoshy } else if (KWPREFIXMATCH(p, P4_KW_BUSREQTYPE)) { 2739145256Sjkoshy if (has_busreqtype == 0) 2740174406Sjkoshy return (-1); 2741145256Sjkoshy 2742145256Sjkoshy q = strchr(p, '='); 2743145256Sjkoshy if (*++q == '\0') /* skip '=' */ 2744174406Sjkoshy return (-1); 2745145256Sjkoshy 2746145256Sjkoshy count = strtol(q, &e, 0); 2747145256Sjkoshy if (e == q || *e != '\0') 2748174406Sjkoshy return (-1); 2749145256Sjkoshy evmask = (evmask & ~0x1F) | (count & 0x1F); 2750145256Sjkoshy } else if (KWMATCH(p, P4_KW_CASCADE)) 2751145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_CASCADE; 2752145256Sjkoshy else if (KWMATCH(p, P4_KW_EDGE)) 2753145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_EDGE; 2754145256Sjkoshy else if (KWMATCH(p, P4_KW_INV)) 2755145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_INVERT; 2756145256Sjkoshy else if (KWPREFIXMATCH(p, P4_KW_MASK "=")) { 2757145256Sjkoshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 2758174406Sjkoshy return (-1); 2759145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2760145256Sjkoshy } else if (KWMATCH(p, P4_KW_OS)) 2761145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 2762145256Sjkoshy else if (KWMATCH(p, P4_KW_PRECISE)) 2763145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_PRECISE; 2764145256Sjkoshy else if (KWPREFIXMATCH(p, P4_KW_TAG "=")) { 2765145256Sjkoshy if (has_tag == 0) 2766174406Sjkoshy return (-1); 2767145256Sjkoshy 2768145256Sjkoshy q = strchr(p, '='); 2769145256Sjkoshy if (*++q == '\0') /* skip '=' */ 2770174406Sjkoshy return (-1); 2771145256Sjkoshy 2772145256Sjkoshy count = strtol(q, &e, 0); 2773145256Sjkoshy if (e == q || *e != '\0') 2774174406Sjkoshy return (-1); 2775145256Sjkoshy 2776145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_TAGGING; 2777147191Sjkoshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig |= 2778145256Sjkoshy P4_ESCR_TO_TAG_VALUE(count); 2779145256Sjkoshy } else if (KWPREFIXMATCH(p, P4_KW_THRESHOLD "=")) { 2780145256Sjkoshy q = strchr(p, '='); 2781145256Sjkoshy if (*++q == '\0') /* skip '=' */ 2782174406Sjkoshy return (-1); 2783145256Sjkoshy 2784145256Sjkoshy count = strtol(q, &e, 0); 2785145256Sjkoshy if (e == q || *e != '\0') 2786174406Sjkoshy return (-1); 2787145256Sjkoshy 2788145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 2789147191Sjkoshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig &= 2790147191Sjkoshy ~P4_CCCR_THRESHOLD_MASK; 2791147191Sjkoshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |= 2792147191Sjkoshy P4_CCCR_TO_THRESHOLD(count); 2793145256Sjkoshy } else if (KWMATCH(p, P4_KW_USR)) 2794145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_USER; 2795145256Sjkoshy else 2796174406Sjkoshy return (-1); 2797145256Sjkoshy } 2798145256Sjkoshy 2799145256Sjkoshy /* other post processing */ 2800145256Sjkoshy if (pe == PMC_EV_P4_IOQ_ALLOCATION || 2801145256Sjkoshy pe == PMC_EV_P4_FSB_DATA_ACTIVITY || 2802145256Sjkoshy pe == PMC_EV_P4_BSQ_ALLOCATION) 2803145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_EDGE; 2804145256Sjkoshy 2805145256Sjkoshy /* fill in thread activity mask */ 2806147191Sjkoshy pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |= 2807145256Sjkoshy P4_CCCR_TO_ACTIVE_THREAD(cccractivemask); 2808145256Sjkoshy 2809145256Sjkoshy if (evmask) 2810145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2811145256Sjkoshy 2812145256Sjkoshy switch (pe) { 2813145256Sjkoshy case PMC_EV_P4_FSB_DATA_ACTIVITY: 2814145256Sjkoshy if ((evmask & 0x06) == 0x06 || 2815145256Sjkoshy (evmask & 0x18) == 0x18) 2816174406Sjkoshy return (-1); /* can't have own+other bits together */ 2817145256Sjkoshy if (evmask == 0) /* default:drdy-{drv,own}+dbsy{drv,own} */ 2818145256Sjkoshy evmask = 0x1D; 2819145256Sjkoshy break; 2820145256Sjkoshy case PMC_EV_P4_MACHINE_CLEAR: 2821145256Sjkoshy /* only one bit is allowed to be set */ 2822145256Sjkoshy if ((evmask & (evmask - 1)) != 0) 2823174406Sjkoshy return (-1); 2824145256Sjkoshy if (evmask == 0) { 2825183107Sjkoshy evmask = 0x1; /* 'CLEAR' */ 2826145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2827145256Sjkoshy } 2828145256Sjkoshy break; 2829145256Sjkoshy default: 2830145256Sjkoshy if (evmask == 0 && pmask) { 2831145256Sjkoshy for (pm = pmask; pm->pm_name; pm++) 2832145256Sjkoshy evmask |= pm->pm_value; 2833145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 2834145256Sjkoshy } 2835145256Sjkoshy } 2836145256Sjkoshy 2837147191Sjkoshy pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 2838147191Sjkoshy P4_ESCR_TO_EVENT_MASK(evmask); 2839145256Sjkoshy 2840174406Sjkoshy return (0); 2841145256Sjkoshy} 2842145256Sjkoshy 2843147759Sjkoshy#endif 2844147759Sjkoshy 2845147759Sjkoshy#if defined(__i386__) 2846147759Sjkoshy 2847145256Sjkoshy/* 2848147191Sjkoshy * Pentium style PMCs 2849147191Sjkoshy */ 2850147191Sjkoshy 2851147191Sjkoshystatic struct pmc_event_alias p5_aliases[] = { 2852183105Sjkoshy EV_ALIAS("branches", "p5-taken-branches"), 2853183105Sjkoshy EV_ALIAS("cycles", "tsc"), 2854183105Sjkoshy EV_ALIAS("dc-misses", "p5-data-read-miss-or-write-miss"), 2855183105Sjkoshy EV_ALIAS("ic-misses", "p5-code-cache-miss"), 2856183105Sjkoshy EV_ALIAS("instructions", "p5-instructions-executed"), 2857183105Sjkoshy EV_ALIAS("interrupts", "p5-hardware-interrupts"), 2858183105Sjkoshy EV_ALIAS("unhalted-cycles", 2859183105Sjkoshy "p5-number-of-cycles-not-in-halt-state"), 2860147191Sjkoshy EV_ALIAS(NULL, NULL) 2861147191Sjkoshy}; 2862147191Sjkoshy 2863147191Sjkoshystatic int 2864147191Sjkoshyp5_allocate_pmc(enum pmc_event pe, char *ctrspec, 2865147191Sjkoshy struct pmc_op_pmcallocate *pmc_config) 2866147191Sjkoshy{ 2867174406Sjkoshy return (-1 || pe || ctrspec || pmc_config); /* shut up gcc */ 2868147191Sjkoshy} 2869147191Sjkoshy 2870147191Sjkoshy/* 2871145256Sjkoshy * Pentium Pro style PMCs. These PMCs are found in Pentium II, Pentium III, 2872145256Sjkoshy * and Pentium M CPUs. 2873145256Sjkoshy */ 2874145256Sjkoshy 2875145256Sjkoshystatic struct pmc_event_alias p6_aliases[] = { 2876145351Sjkoshy EV_ALIAS("branches", "p6-br-inst-retired"), 2877145351Sjkoshy EV_ALIAS("branch-mispredicts", "p6-br-miss-pred-retired"), 2878145351Sjkoshy EV_ALIAS("cycles", "tsc"), 2879145351Sjkoshy EV_ALIAS("dc-misses", "p6-dcu-lines-in"), 2880168612Sjkoshy EV_ALIAS("ic-misses", "p6-ifu-fetch-miss"), 2881145351Sjkoshy EV_ALIAS("instructions", "p6-inst-retired"), 2882145351Sjkoshy EV_ALIAS("interrupts", "p6-hw-int-rx"), 2883155998Sjkoshy EV_ALIAS("unhalted-cycles", "p6-cpu-clk-unhalted"), 2884145351Sjkoshy EV_ALIAS(NULL, NULL) 2885145256Sjkoshy}; 2886145256Sjkoshy 2887145256Sjkoshy#define P6_KW_CMASK "cmask" 2888145256Sjkoshy#define P6_KW_EDGE "edge" 2889145256Sjkoshy#define P6_KW_INV "inv" 2890145256Sjkoshy#define P6_KW_OS "os" 2891145256Sjkoshy#define P6_KW_UMASK "umask" 2892145256Sjkoshy#define P6_KW_USR "usr" 2893145256Sjkoshy 2894145256Sjkoshystatic struct pmc_masks p6_mask_mesi[] = { 2895145256Sjkoshy PMCMASK(m, 0x01), 2896145256Sjkoshy PMCMASK(e, 0x02), 2897145256Sjkoshy PMCMASK(s, 0x04), 2898145256Sjkoshy PMCMASK(i, 0x08), 2899145256Sjkoshy NULLMASK 2900145256Sjkoshy}; 2901145256Sjkoshy 2902145256Sjkoshystatic struct pmc_masks p6_mask_mesihw[] = { 2903145256Sjkoshy PMCMASK(m, 0x01), 2904145256Sjkoshy PMCMASK(e, 0x02), 2905145256Sjkoshy PMCMASK(s, 0x04), 2906145256Sjkoshy PMCMASK(i, 0x08), 2907145256Sjkoshy PMCMASK(nonhw, 0x00), 2908145256Sjkoshy PMCMASK(hw, 0x10), 2909145256Sjkoshy PMCMASK(both, 0x30), 2910145256Sjkoshy NULLMASK 2911145256Sjkoshy}; 2912145256Sjkoshy 2913145256Sjkoshystatic struct pmc_masks p6_mask_hw[] = { 2914145256Sjkoshy PMCMASK(nonhw, 0x00), 2915145256Sjkoshy PMCMASK(hw, 0x10), 2916145256Sjkoshy PMCMASK(both, 0x30), 2917145256Sjkoshy NULLMASK 2918145256Sjkoshy}; 2919145256Sjkoshy 2920145256Sjkoshystatic struct pmc_masks p6_mask_any[] = { 2921145256Sjkoshy PMCMASK(self, 0x00), 2922145256Sjkoshy PMCMASK(any, 0x20), 2923145256Sjkoshy NULLMASK 2924145256Sjkoshy}; 2925145256Sjkoshy 2926145256Sjkoshystatic struct pmc_masks p6_mask_ekp[] = { 2927145256Sjkoshy PMCMASK(nta, 0x00), 2928145256Sjkoshy PMCMASK(t1, 0x01), 2929145256Sjkoshy PMCMASK(t2, 0x02), 2930145256Sjkoshy PMCMASK(wos, 0x03), 2931145256Sjkoshy NULLMASK 2932145256Sjkoshy}; 2933145256Sjkoshy 2934145256Sjkoshystatic struct pmc_masks p6_mask_pps[] = { 2935145256Sjkoshy PMCMASK(packed-and-scalar, 0x00), 2936145256Sjkoshy PMCMASK(scalar, 0x01), 2937145256Sjkoshy NULLMASK 2938145256Sjkoshy}; 2939145256Sjkoshy 2940145256Sjkoshystatic struct pmc_masks p6_mask_mite[] = { 2941145256Sjkoshy PMCMASK(packed-multiply, 0x01), 2942145256Sjkoshy PMCMASK(packed-shift, 0x02), 2943145256Sjkoshy PMCMASK(pack, 0x04), 2944145256Sjkoshy PMCMASK(unpack, 0x08), 2945145256Sjkoshy PMCMASK(packed-logical, 0x10), 2946145256Sjkoshy PMCMASK(packed-arithmetic, 0x20), 2947145256Sjkoshy NULLMASK 2948145256Sjkoshy}; 2949145256Sjkoshy 2950145256Sjkoshystatic struct pmc_masks p6_mask_fmt[] = { 2951145256Sjkoshy PMCMASK(mmxtofp, 0x00), 2952145256Sjkoshy PMCMASK(fptommx, 0x01), 2953145256Sjkoshy NULLMASK 2954145256Sjkoshy}; 2955145256Sjkoshy 2956145256Sjkoshystatic struct pmc_masks p6_mask_sr[] = { 2957145256Sjkoshy PMCMASK(es, 0x01), 2958145256Sjkoshy PMCMASK(ds, 0x02), 2959145256Sjkoshy PMCMASK(fs, 0x04), 2960145256Sjkoshy PMCMASK(gs, 0x08), 2961145256Sjkoshy NULLMASK 2962145256Sjkoshy}; 2963145256Sjkoshy 2964145256Sjkoshystatic struct pmc_masks p6_mask_eet[] = { 2965145256Sjkoshy PMCMASK(all, 0x00), 2966145256Sjkoshy PMCMASK(freq, 0x02), 2967145256Sjkoshy NULLMASK 2968145256Sjkoshy}; 2969145256Sjkoshy 2970145256Sjkoshystatic struct pmc_masks p6_mask_efur[] = { 2971145256Sjkoshy PMCMASK(all, 0x00), 2972145256Sjkoshy PMCMASK(loadop, 0x01), 2973145256Sjkoshy PMCMASK(stdsta, 0x02), 2974145256Sjkoshy NULLMASK 2975145256Sjkoshy}; 2976145256Sjkoshy 2977145256Sjkoshystatic struct pmc_masks p6_mask_essir[] = { 2978145256Sjkoshy PMCMASK(sse-packed-single, 0x00), 2979145256Sjkoshy PMCMASK(sse-packed-single-scalar-single, 0x01), 2980145256Sjkoshy PMCMASK(sse2-packed-double, 0x02), 2981145256Sjkoshy PMCMASK(sse2-scalar-double, 0x03), 2982145256Sjkoshy NULLMASK 2983145256Sjkoshy}; 2984145256Sjkoshy 2985145256Sjkoshystatic struct pmc_masks p6_mask_esscir[] = { 2986145256Sjkoshy PMCMASK(sse-packed-single, 0x00), 2987145256Sjkoshy PMCMASK(sse-scalar-single, 0x01), 2988145256Sjkoshy PMCMASK(sse2-packed-double, 0x02), 2989145256Sjkoshy PMCMASK(sse2-scalar-double, 0x03), 2990145256Sjkoshy NULLMASK 2991145256Sjkoshy}; 2992145256Sjkoshy 2993145256Sjkoshy/* P6 event parser */ 2994145256Sjkoshystatic int 2995145256Sjkoshyp6_allocate_pmc(enum pmc_event pe, char *ctrspec, 2996145256Sjkoshy struct pmc_op_pmcallocate *pmc_config) 2997145256Sjkoshy{ 2998145256Sjkoshy char *e, *p, *q; 2999240164Sfabient uint64_t evmask; 3000145256Sjkoshy int count, n; 3001145256Sjkoshy const struct pmc_masks *pm, *pmask; 3002145256Sjkoshy 3003183725Sjkoshy pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 3004147191Sjkoshy pmc_config->pm_md.pm_ppro.pm_ppro_config = 0; 3005145256Sjkoshy 3006145256Sjkoshy evmask = 0; 3007145256Sjkoshy 3008145256Sjkoshy#define P6MASKSET(M) pmask = p6_mask_ ## M 3009145256Sjkoshy 3010145256Sjkoshy switch(pe) { 3011183107Sjkoshy case PMC_EV_P6_L2_IFETCH: P6MASKSET(mesi); break; 3012145256Sjkoshy case PMC_EV_P6_L2_LD: P6MASKSET(mesi); break; 3013145256Sjkoshy case PMC_EV_P6_L2_ST: P6MASKSET(mesi); break; 3014145256Sjkoshy case PMC_EV_P6_L2_RQSTS: P6MASKSET(mesi); break; 3015145256Sjkoshy case PMC_EV_P6_BUS_DRDY_CLOCKS: 3016145256Sjkoshy case PMC_EV_P6_BUS_LOCK_CLOCKS: 3017145256Sjkoshy case PMC_EV_P6_BUS_TRAN_BRD: 3018145256Sjkoshy case PMC_EV_P6_BUS_TRAN_RFO: 3019145256Sjkoshy case PMC_EV_P6_BUS_TRANS_WB: 3020145256Sjkoshy case PMC_EV_P6_BUS_TRAN_IFETCH: 3021145256Sjkoshy case PMC_EV_P6_BUS_TRAN_INVAL: 3022145256Sjkoshy case PMC_EV_P6_BUS_TRAN_PWR: 3023145256Sjkoshy case PMC_EV_P6_BUS_TRANS_P: 3024145256Sjkoshy case PMC_EV_P6_BUS_TRANS_IO: 3025145256Sjkoshy case PMC_EV_P6_BUS_TRAN_DEF: 3026145256Sjkoshy case PMC_EV_P6_BUS_TRAN_BURST: 3027145256Sjkoshy case PMC_EV_P6_BUS_TRAN_ANY: 3028145256Sjkoshy case PMC_EV_P6_BUS_TRAN_MEM: 3029145256Sjkoshy P6MASKSET(any); break; 3030145256Sjkoshy case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED: 3031145256Sjkoshy case PMC_EV_P6_EMON_KNI_PREF_MISS: 3032145256Sjkoshy P6MASKSET(ekp); break; 3033145256Sjkoshy case PMC_EV_P6_EMON_KNI_INST_RETIRED: 3034145256Sjkoshy case PMC_EV_P6_EMON_KNI_COMP_INST_RET: 3035145256Sjkoshy P6MASKSET(pps); break; 3036145256Sjkoshy case PMC_EV_P6_MMX_INSTR_TYPE_EXEC: 3037145256Sjkoshy P6MASKSET(mite); break; 3038145256Sjkoshy case PMC_EV_P6_FP_MMX_TRANS: 3039145256Sjkoshy P6MASKSET(fmt); break; 3040145256Sjkoshy case PMC_EV_P6_SEG_RENAME_STALLS: 3041145256Sjkoshy case PMC_EV_P6_SEG_REG_RENAMES: 3042145256Sjkoshy P6MASKSET(sr); break; 3043145256Sjkoshy case PMC_EV_P6_EMON_EST_TRANS: 3044145256Sjkoshy P6MASKSET(eet); break; 3045145256Sjkoshy case PMC_EV_P6_EMON_FUSED_UOPS_RET: 3046145256Sjkoshy P6MASKSET(efur); break; 3047145256Sjkoshy case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED: 3048145256Sjkoshy P6MASKSET(essir); break; 3049145256Sjkoshy case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED: 3050145256Sjkoshy P6MASKSET(esscir); break; 3051145256Sjkoshy default: 3052145256Sjkoshy pmask = NULL; 3053145256Sjkoshy break; 3054145256Sjkoshy } 3055145256Sjkoshy 3056145256Sjkoshy /* Pentium M PMCs have a few events with different semantics */ 3057145256Sjkoshy if (cpu_info.pm_cputype == PMC_CPU_INTEL_PM) { 3058145256Sjkoshy if (pe == PMC_EV_P6_L2_LD || 3059145256Sjkoshy pe == PMC_EV_P6_L2_LINES_IN || 3060145256Sjkoshy pe == PMC_EV_P6_L2_LINES_OUT) 3061145256Sjkoshy P6MASKSET(mesihw); 3062145256Sjkoshy else if (pe == PMC_EV_P6_L2_M_LINES_OUTM) 3063145256Sjkoshy P6MASKSET(hw); 3064145256Sjkoshy } 3065145256Sjkoshy 3066145256Sjkoshy /* Parse additional modifiers if present */ 3067145256Sjkoshy while ((p = strsep(&ctrspec, ",")) != NULL) { 3068145256Sjkoshy if (KWPREFIXMATCH(p, P6_KW_CMASK "=")) { 3069145256Sjkoshy q = strchr(p, '='); 3070145256Sjkoshy if (*++q == '\0') /* skip '=' */ 3071174406Sjkoshy return (-1); 3072145256Sjkoshy count = strtol(q, &e, 0); 3073145256Sjkoshy if (e == q || *e != '\0') 3074174406Sjkoshy return (-1); 3075145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 3076147191Sjkoshy pmc_config->pm_md.pm_ppro.pm_ppro_config |= 3077147191Sjkoshy P6_EVSEL_TO_CMASK(count); 3078145256Sjkoshy } else if (KWMATCH(p, P6_KW_EDGE)) { 3079145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_EDGE; 3080145256Sjkoshy } else if (KWMATCH(p, P6_KW_INV)) { 3081145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_INVERT; 3082145256Sjkoshy } else if (KWMATCH(p, P6_KW_OS)) { 3083145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_SYSTEM; 3084145256Sjkoshy } else if (KWPREFIXMATCH(p, P6_KW_UMASK "=")) { 3085145256Sjkoshy evmask = 0; 3086145256Sjkoshy if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 3087174406Sjkoshy return (-1); 3088145256Sjkoshy if ((pe == PMC_EV_P6_BUS_DRDY_CLOCKS || 3089145256Sjkoshy pe == PMC_EV_P6_BUS_LOCK_CLOCKS || 3090145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_BRD || 3091145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_RFO || 3092145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_IFETCH || 3093145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_INVAL || 3094145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_PWR || 3095145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_DEF || 3096145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_BURST || 3097145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_ANY || 3098145256Sjkoshy pe == PMC_EV_P6_BUS_TRAN_MEM || 3099145256Sjkoshy pe == PMC_EV_P6_BUS_TRANS_IO || 3100145256Sjkoshy pe == PMC_EV_P6_BUS_TRANS_P || 3101145256Sjkoshy pe == PMC_EV_P6_BUS_TRANS_WB || 3102145256Sjkoshy pe == PMC_EV_P6_EMON_EST_TRANS || 3103145256Sjkoshy pe == PMC_EV_P6_EMON_FUSED_UOPS_RET || 3104145256Sjkoshy pe == PMC_EV_P6_EMON_KNI_COMP_INST_RET || 3105145256Sjkoshy pe == PMC_EV_P6_EMON_KNI_INST_RETIRED || 3106145256Sjkoshy pe == PMC_EV_P6_EMON_KNI_PREF_DISPATCHED || 3107145256Sjkoshy pe == PMC_EV_P6_EMON_KNI_PREF_MISS || 3108145256Sjkoshy pe == PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED || 3109145256Sjkoshy pe == PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED || 3110145256Sjkoshy pe == PMC_EV_P6_FP_MMX_TRANS) 3111174406Sjkoshy && (n > 1)) /* Only one mask keyword is allowed. */ 3112174406Sjkoshy return (-1); 3113145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 3114145256Sjkoshy } else if (KWMATCH(p, P6_KW_USR)) { 3115145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_USER; 3116145256Sjkoshy } else 3117174406Sjkoshy return (-1); 3118145256Sjkoshy } 3119145256Sjkoshy 3120145256Sjkoshy /* post processing */ 3121145256Sjkoshy switch (pe) { 3122145256Sjkoshy 3123145256Sjkoshy /* 3124145256Sjkoshy * The following events default to an evmask of 0 3125145256Sjkoshy */ 3126145256Sjkoshy 3127145256Sjkoshy /* default => 'self' */ 3128145256Sjkoshy case PMC_EV_P6_BUS_DRDY_CLOCKS: 3129145256Sjkoshy case PMC_EV_P6_BUS_LOCK_CLOCKS: 3130145256Sjkoshy case PMC_EV_P6_BUS_TRAN_BRD: 3131145256Sjkoshy case PMC_EV_P6_BUS_TRAN_RFO: 3132145256Sjkoshy case PMC_EV_P6_BUS_TRANS_WB: 3133145256Sjkoshy case PMC_EV_P6_BUS_TRAN_IFETCH: 3134145256Sjkoshy case PMC_EV_P6_BUS_TRAN_INVAL: 3135145256Sjkoshy case PMC_EV_P6_BUS_TRAN_PWR: 3136145256Sjkoshy case PMC_EV_P6_BUS_TRANS_P: 3137145256Sjkoshy case PMC_EV_P6_BUS_TRANS_IO: 3138145256Sjkoshy case PMC_EV_P6_BUS_TRAN_DEF: 3139145256Sjkoshy case PMC_EV_P6_BUS_TRAN_BURST: 3140145256Sjkoshy case PMC_EV_P6_BUS_TRAN_ANY: 3141145256Sjkoshy case PMC_EV_P6_BUS_TRAN_MEM: 3142145256Sjkoshy 3143145256Sjkoshy /* default => 'nta' */ 3144145256Sjkoshy case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED: 3145145256Sjkoshy case PMC_EV_P6_EMON_KNI_PREF_MISS: 3146145256Sjkoshy 3147145256Sjkoshy /* default => 'packed and scalar' */ 3148145256Sjkoshy case PMC_EV_P6_EMON_KNI_INST_RETIRED: 3149145256Sjkoshy case PMC_EV_P6_EMON_KNI_COMP_INST_RET: 3150145256Sjkoshy 3151145256Sjkoshy /* default => 'mmx to fp transitions' */ 3152145256Sjkoshy case PMC_EV_P6_FP_MMX_TRANS: 3153145256Sjkoshy 3154145256Sjkoshy /* default => 'SSE Packed Single' */ 3155145256Sjkoshy case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED: 3156145256Sjkoshy case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED: 3157145256Sjkoshy 3158145256Sjkoshy /* default => 'all fused micro-ops' */ 3159145256Sjkoshy case PMC_EV_P6_EMON_FUSED_UOPS_RET: 3160145256Sjkoshy 3161145256Sjkoshy /* default => 'all transitions' */ 3162145256Sjkoshy case PMC_EV_P6_EMON_EST_TRANS: 3163145256Sjkoshy break; 3164145256Sjkoshy 3165145256Sjkoshy case PMC_EV_P6_MMX_UOPS_EXEC: 3166145256Sjkoshy evmask = 0x0F; /* only value allowed */ 3167145256Sjkoshy break; 3168145256Sjkoshy 3169145256Sjkoshy default: 3170145256Sjkoshy /* 3171145256Sjkoshy * For all other events, set the default event mask 3172145256Sjkoshy * to a logical OR of all the allowed event mask bits. 3173145256Sjkoshy */ 3174145256Sjkoshy if (evmask == 0 && pmask) { 3175145256Sjkoshy for (pm = pmask; pm->pm_name; pm++) 3176145256Sjkoshy evmask |= pm->pm_value; 3177145256Sjkoshy pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 3178145256Sjkoshy } 3179145256Sjkoshy 3180145256Sjkoshy break; 3181145256Sjkoshy } 3182145256Sjkoshy 3183145256Sjkoshy if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) 3184147191Sjkoshy pmc_config->pm_md.pm_ppro.pm_ppro_config |= 3185147191Sjkoshy P6_EVSEL_TO_UMASK(evmask); 3186145256Sjkoshy 3187174406Sjkoshy return (0); 3188145256Sjkoshy} 3189145256Sjkoshy 3190147191Sjkoshy#endif 3191147191Sjkoshy 3192183725Sjkoshy#if defined(__i386__) || defined(__amd64__) 3193183725Sjkoshystatic int 3194183725Sjkoshytsc_allocate_pmc(enum pmc_event pe, char *ctrspec, 3195183725Sjkoshy struct pmc_op_pmcallocate *pmc_config) 3196183725Sjkoshy{ 3197183725Sjkoshy if (pe != PMC_EV_TSC_TSC) 3198183725Sjkoshy return (-1); 3199183725Sjkoshy 3200183725Sjkoshy /* TSC events must be unqualified. */ 3201183725Sjkoshy if (ctrspec && *ctrspec != '\0') 3202183725Sjkoshy return (-1); 3203183725Sjkoshy 3204183725Sjkoshy pmc_config->pm_md.pm_amd.pm_amd_config = 0; 3205183725Sjkoshy pmc_config->pm_caps |= PMC_CAP_READ; 3206183725Sjkoshy 3207183725Sjkoshy return (0); 3208183725Sjkoshy} 3209183725Sjkoshy#endif 3210183725Sjkoshy 3211233628Sfabientstatic struct pmc_event_alias generic_aliases[] = { 3212233628Sfabient EV_ALIAS("instructions", "SOFT-CLOCK.HARD"), 3213233628Sfabient EV_ALIAS(NULL, NULL) 3214233628Sfabient}; 3215233628Sfabient 3216233628Sfabientstatic int 3217233628Sfabientsoft_allocate_pmc(enum pmc_event pe, char *ctrspec, 3218233628Sfabient struct pmc_op_pmcallocate *pmc_config) 3219233628Sfabient{ 3220233628Sfabient (void)ctrspec; 3221233628Sfabient (void)pmc_config; 3222233628Sfabient 3223242622Sdim if ((int)pe < PMC_EV_SOFT_FIRST || (int)pe > PMC_EV_SOFT_LAST) 3224233628Sfabient return (-1); 3225233628Sfabient 3226233628Sfabient pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 3227233628Sfabient return (0); 3228233628Sfabient} 3229233628Sfabient 3230277835Sbr#if defined(__arm__) 3231200928Srpaulo#if defined(__XSCALE__) 3232200928Srpaulo 3233200928Srpaulostatic struct pmc_event_alias xscale_aliases[] = { 3234200928Srpaulo EV_ALIAS("branches", "BRANCH_RETIRED"), 3235200928Srpaulo EV_ALIAS("branch-mispredicts", "BRANCH_MISPRED"), 3236200928Srpaulo EV_ALIAS("dc-misses", "DC_MISS"), 3237200928Srpaulo EV_ALIAS("ic-misses", "IC_MISS"), 3238200928Srpaulo EV_ALIAS("instructions", "INSTR_RETIRED"), 3239200928Srpaulo EV_ALIAS(NULL, NULL) 3240200928Srpaulo}; 3241200928Srpaulostatic int 3242200928Srpauloxscale_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 3243200928Srpaulo struct pmc_op_pmcallocate *pmc_config __unused) 3244200928Srpaulo{ 3245200928Srpaulo switch (pe) { 3246200928Srpaulo default: 3247200928Srpaulo break; 3248200928Srpaulo } 3249200928Srpaulo 3250200928Srpaulo return (0); 3251200928Srpaulo} 3252200928Srpaulo#endif 3253200928Srpaulo 3254284218Sbrstatic struct pmc_event_alias cortex_a8_aliases[] = { 3255277835Sbr EV_ALIAS("dc-misses", "L1_DCACHE_REFILL"), 3256277835Sbr EV_ALIAS("ic-misses", "L1_ICACHE_REFILL"), 3257277835Sbr EV_ALIAS("instructions", "INSTR_EXECUTED"), 3258277835Sbr EV_ALIAS(NULL, NULL) 3259277835Sbr}; 3260284218Sbr 3261284218Sbrstatic struct pmc_event_alias cortex_a9_aliases[] = { 3262284218Sbr EV_ALIAS("dc-misses", "L1_DCACHE_REFILL"), 3263284218Sbr EV_ALIAS("ic-misses", "L1_ICACHE_REFILL"), 3264284218Sbr EV_ALIAS("instructions", "INSTR_EXECUTED"), 3265284218Sbr EV_ALIAS(NULL, NULL) 3266284218Sbr}; 3267284218Sbr 3268277835Sbrstatic int 3269277835Sbrarmv7_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 3270277835Sbr struct pmc_op_pmcallocate *pmc_config __unused) 3271277835Sbr{ 3272277835Sbr switch (pe) { 3273277835Sbr default: 3274277835Sbr break; 3275277835Sbr } 3276277835Sbr 3277277835Sbr return (0); 3278277835Sbr} 3279277835Sbr#endif 3280277835Sbr 3281283112Sbr#if defined(__aarch64__) 3282283112Sbrstatic struct pmc_event_alias cortex_a53_aliases[] = { 3283283112Sbr EV_ALIAS(NULL, NULL) 3284283112Sbr}; 3285283112Sbrstatic struct pmc_event_alias cortex_a57_aliases[] = { 3286283112Sbr EV_ALIAS(NULL, NULL) 3287283112Sbr}; 3288283112Sbrstatic int 3289283112Sbrarm64_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 3290283112Sbr struct pmc_op_pmcallocate *pmc_config __unused) 3291283112Sbr{ 3292283112Sbr switch (pe) { 3293283112Sbr default: 3294283112Sbr break; 3295283112Sbr } 3296283112Sbr 3297283112Sbr return (0); 3298283112Sbr} 3299283112Sbr#endif 3300283112Sbr 3301204635Sgnn#if defined(__mips__) 3302204635Sgnn 3303204635Sgnnstatic struct pmc_event_alias mips24k_aliases[] = { 3304204635Sgnn EV_ALIAS("instructions", "INSTR_EXECUTED"), 3305204635Sgnn EV_ALIAS("branches", "BRANCH_COMPLETED"), 3306204635Sgnn EV_ALIAS("branch-mispredicts", "BRANCH_MISPRED"), 3307204635Sgnn EV_ALIAS(NULL, NULL) 3308204635Sgnn}; 3309204635Sgnn 3310281098Sadrianstatic struct pmc_event_alias mips74k_aliases[] = { 3311281098Sadrian EV_ALIAS("instructions", "INSTR_EXECUTED"), 3312281098Sadrian EV_ALIAS("branches", "BRANCH_INSNS"), 3313281098Sadrian EV_ALIAS("branch-mispredicts", "MISPREDICTED_BRANCH_INSNS"), 3314281098Sadrian EV_ALIAS(NULL, NULL) 3315281098Sadrian}; 3316281098Sadrian 3317233335Sgonzostatic struct pmc_event_alias octeon_aliases[] = { 3318233335Sgonzo EV_ALIAS("instructions", "RET"), 3319233335Sgonzo EV_ALIAS("branches", "BR"), 3320233335Sgonzo EV_ALIAS("branch-mispredicts", "BRMIS"), 3321233335Sgonzo EV_ALIAS(NULL, NULL) 3322233335Sgonzo}; 3323233335Sgonzo 3324233320Sgonzo#define MIPS_KW_OS "os" 3325233320Sgonzo#define MIPS_KW_USR "usr" 3326233320Sgonzo#define MIPS_KW_ANYTHREAD "anythread" 3327204635Sgnn 3328204635Sgnnstatic int 3329233320Sgonzomips_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 3330204635Sgnn struct pmc_op_pmcallocate *pmc_config __unused) 3331204635Sgnn{ 3332204635Sgnn char *p; 3333204635Sgnn 3334204635Sgnn (void) pe; 3335204635Sgnn 3336204635Sgnn pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 3337204635Sgnn 3338204635Sgnn while ((p = strsep(&ctrspec, ",")) != NULL) { 3339233320Sgonzo if (KWMATCH(p, MIPS_KW_OS)) 3340204635Sgnn pmc_config->pm_caps |= PMC_CAP_SYSTEM; 3341233320Sgonzo else if (KWMATCH(p, MIPS_KW_USR)) 3342204635Sgnn pmc_config->pm_caps |= PMC_CAP_USER; 3343233320Sgonzo else if (KWMATCH(p, MIPS_KW_ANYTHREAD)) 3344204635Sgnn pmc_config->pm_caps |= (PMC_CAP_USER | PMC_CAP_SYSTEM); 3345204635Sgnn else 3346204635Sgnn return (-1); 3347204635Sgnn } 3348204635Sgnn 3349204635Sgnn return (0); 3350204635Sgnn} 3351233320Sgonzo 3352204635Sgnn#endif /* __mips__ */ 3353204635Sgnn 3354228869Sjhibbits#if defined(__powerpc__) 3355204635Sgnn 3356228869Sjhibbitsstatic struct pmc_event_alias ppc7450_aliases[] = { 3357228869Sjhibbits EV_ALIAS("instructions", "INSTR_COMPLETED"), 3358228869Sjhibbits EV_ALIAS("branches", "BRANCHES_COMPLETED"), 3359228869Sjhibbits EV_ALIAS("branch-mispredicts", "MISPREDICTED_BRANCHES"), 3360228869Sjhibbits EV_ALIAS(NULL, NULL) 3361228869Sjhibbits}; 3362228869Sjhibbits 3363261342Sjhibbitsstatic struct pmc_event_alias ppc970_aliases[] = { 3364261342Sjhibbits EV_ALIAS("instructions", "INSTR_COMPLETED"), 3365261342Sjhibbits EV_ALIAS("cycles", "CYCLES"), 3366261342Sjhibbits EV_ALIAS(NULL, NULL) 3367261342Sjhibbits}; 3368228869Sjhibbits 3369281713Sjhibbitsstatic struct pmc_event_alias e500_aliases[] = { 3370281713Sjhibbits EV_ALIAS("instructions", "INSTR_COMPLETED"), 3371281713Sjhibbits EV_ALIAS("cycles", "CYCLES"), 3372281713Sjhibbits EV_ALIAS(NULL, NULL) 3373281713Sjhibbits}; 3374281713Sjhibbits 3375261342Sjhibbits#define POWERPC_KW_OS "os" 3376261342Sjhibbits#define POWERPC_KW_USR "usr" 3377261342Sjhibbits#define POWERPC_KW_ANYTHREAD "anythread" 3378261342Sjhibbits 3379228869Sjhibbitsstatic int 3380261342Sjhibbitspowerpc_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, 3381261342Sjhibbits struct pmc_op_pmcallocate *pmc_config __unused) 3382228869Sjhibbits{ 3383228869Sjhibbits char *p; 3384228869Sjhibbits 3385228869Sjhibbits (void) pe; 3386228869Sjhibbits 3387228869Sjhibbits pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 3388228869Sjhibbits 3389228869Sjhibbits while ((p = strsep(&ctrspec, ",")) != NULL) { 3390261342Sjhibbits if (KWMATCH(p, POWERPC_KW_OS)) 3391228869Sjhibbits pmc_config->pm_caps |= PMC_CAP_SYSTEM; 3392261342Sjhibbits else if (KWMATCH(p, POWERPC_KW_USR)) 3393228869Sjhibbits pmc_config->pm_caps |= PMC_CAP_USER; 3394261342Sjhibbits else if (KWMATCH(p, POWERPC_KW_ANYTHREAD)) 3395228869Sjhibbits pmc_config->pm_caps |= (PMC_CAP_USER | PMC_CAP_SYSTEM); 3396228869Sjhibbits else 3397228869Sjhibbits return (-1); 3398228869Sjhibbits } 3399228869Sjhibbits 3400228869Sjhibbits return (0); 3401228869Sjhibbits} 3402261342Sjhibbits 3403228869Sjhibbits#endif /* __powerpc__ */ 3404228869Sjhibbits 3405228869Sjhibbits 3406145256Sjkoshy/* 3407183725Sjkoshy * Match an event name `name' with its canonical form. 3408183725Sjkoshy * 3409185363Sjkoshy * Matches are case insensitive and spaces, periods, underscores and 3410185363Sjkoshy * hyphen characters are considered to match each other. 3411185363Sjkoshy * 3412183725Sjkoshy * Returns 1 for a match, 0 otherwise. 3413183725Sjkoshy */ 3414183725Sjkoshy 3415183725Sjkoshystatic int 3416183725Sjkoshypmc_match_event_name(const char *name, const char *canonicalname) 3417183725Sjkoshy{ 3418183725Sjkoshy int cc, nc; 3419183725Sjkoshy const unsigned char *c, *n; 3420183725Sjkoshy 3421183725Sjkoshy c = (const unsigned char *) canonicalname; 3422183725Sjkoshy n = (const unsigned char *) name; 3423183725Sjkoshy 3424183725Sjkoshy for (; (nc = *n) && (cc = *c); n++, c++) { 3425183725Sjkoshy 3426185363Sjkoshy if ((nc == ' ' || nc == '_' || nc == '-' || nc == '.') && 3427185363Sjkoshy (cc == ' ' || cc == '_' || cc == '-' || cc == '.')) 3428183725Sjkoshy continue; 3429183725Sjkoshy 3430185363Sjkoshy if (toupper(nc) == toupper(cc)) 3431183725Sjkoshy continue; 3432183725Sjkoshy 3433185363Sjkoshy 3434183725Sjkoshy return (0); 3435183725Sjkoshy } 3436183725Sjkoshy 3437183725Sjkoshy if (*n == '\0' && *c == '\0') 3438183725Sjkoshy return (1); 3439183725Sjkoshy 3440183725Sjkoshy return (0); 3441183725Sjkoshy} 3442183725Sjkoshy 3443183725Sjkoshy/* 3444183725Sjkoshy * Match an event name against all the event named supported by a 3445183725Sjkoshy * PMC class. 3446183725Sjkoshy * 3447183725Sjkoshy * Returns an event descriptor pointer on match or NULL otherwise. 3448183725Sjkoshy */ 3449183725Sjkoshystatic const struct pmc_event_descr * 3450183725Sjkoshypmc_match_event_class(const char *name, 3451183725Sjkoshy const struct pmc_class_descr *pcd) 3452183725Sjkoshy{ 3453183725Sjkoshy size_t n; 3454183725Sjkoshy const struct pmc_event_descr *ev; 3455185363Sjkoshy 3456183725Sjkoshy ev = pcd->pm_evc_event_table; 3457183725Sjkoshy for (n = 0; n < pcd->pm_evc_event_table_size; n++, ev++) 3458183725Sjkoshy if (pmc_match_event_name(name, ev->pm_ev_name)) 3459183725Sjkoshy return (ev); 3460183725Sjkoshy 3461183725Sjkoshy return (NULL); 3462183725Sjkoshy} 3463183725Sjkoshy 3464183725Sjkoshystatic int 3465183725Sjkoshypmc_mdep_is_compatible_class(enum pmc_class pc) 3466183725Sjkoshy{ 3467183725Sjkoshy size_t n; 3468183725Sjkoshy 3469183725Sjkoshy for (n = 0; n < pmc_mdep_class_list_size; n++) 3470183725Sjkoshy if (pmc_mdep_class_list[n] == pc) 3471183725Sjkoshy return (1); 3472183725Sjkoshy return (0); 3473183725Sjkoshy} 3474183725Sjkoshy 3475183725Sjkoshy/* 3476147191Sjkoshy * API entry points 3477145256Sjkoshy */ 3478145256Sjkoshy 3479147191Sjkoshyint 3480147191Sjkoshypmc_allocate(const char *ctrspec, enum pmc_mode mode, 3481147191Sjkoshy uint32_t flags, int cpu, pmc_id_t *pmcid) 3482145256Sjkoshy{ 3483183725Sjkoshy size_t n; 3484147191Sjkoshy int retval; 3485147191Sjkoshy char *r, *spec_copy; 3486147191Sjkoshy const char *ctrname; 3487183725Sjkoshy const struct pmc_event_descr *ev; 3488183725Sjkoshy const struct pmc_event_alias *alias; 3489147191Sjkoshy struct pmc_op_pmcallocate pmc_config; 3490183725Sjkoshy const struct pmc_class_descr *pcd; 3491145256Sjkoshy 3492147191Sjkoshy spec_copy = NULL; 3493147191Sjkoshy retval = -1; 3494145256Sjkoshy 3495147191Sjkoshy if (mode != PMC_MODE_SS && mode != PMC_MODE_TS && 3496147191Sjkoshy mode != PMC_MODE_SC && mode != PMC_MODE_TC) { 3497147191Sjkoshy errno = EINVAL; 3498147191Sjkoshy goto out; 3499147191Sjkoshy } 3500145256Sjkoshy 3501147191Sjkoshy /* replace an event alias with the canonical event specifier */ 3502147191Sjkoshy if (pmc_mdep_event_aliases) 3503183725Sjkoshy for (alias = pmc_mdep_event_aliases; alias->pm_alias; alias++) 3504183725Sjkoshy if (!strcasecmp(ctrspec, alias->pm_alias)) { 3505183725Sjkoshy spec_copy = strdup(alias->pm_spec); 3506147191Sjkoshy break; 3507147191Sjkoshy } 3508145256Sjkoshy 3509147191Sjkoshy if (spec_copy == NULL) 3510147191Sjkoshy spec_copy = strdup(ctrspec); 3511145256Sjkoshy 3512147191Sjkoshy r = spec_copy; 3513147191Sjkoshy ctrname = strsep(&r, ","); 3514145256Sjkoshy 3515183725Sjkoshy /* 3516183725Sjkoshy * If a explicit class prefix was given by the user, restrict the 3517183725Sjkoshy * search for the event to the specified PMC class. 3518183725Sjkoshy */ 3519183725Sjkoshy ev = NULL; 3520185363Sjkoshy for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) { 3521185363Sjkoshy pcd = pmc_class_table[n]; 3522183725Sjkoshy if (pmc_mdep_is_compatible_class(pcd->pm_evc_class) && 3523183725Sjkoshy strncasecmp(ctrname, pcd->pm_evc_name, 3524183725Sjkoshy pcd->pm_evc_name_size) == 0) { 3525183725Sjkoshy if ((ev = pmc_match_event_class(ctrname + 3526183725Sjkoshy pcd->pm_evc_name_size, pcd)) == NULL) { 3527183725Sjkoshy errno = EINVAL; 3528183725Sjkoshy goto out; 3529183725Sjkoshy } 3530147191Sjkoshy break; 3531183725Sjkoshy } 3532183725Sjkoshy } 3533145256Sjkoshy 3534183725Sjkoshy /* 3535183725Sjkoshy * Otherwise, search for this event in all compatible PMC 3536183725Sjkoshy * classes. 3537183725Sjkoshy */ 3538185363Sjkoshy for (n = 0; ev == NULL && n < PMC_CLASS_TABLE_SIZE; n++) { 3539185363Sjkoshy pcd = pmc_class_table[n]; 3540183725Sjkoshy if (pmc_mdep_is_compatible_class(pcd->pm_evc_class)) 3541183725Sjkoshy ev = pmc_match_event_class(ctrname, pcd); 3542183725Sjkoshy } 3543183725Sjkoshy 3544183725Sjkoshy if (ev == NULL) { 3545147191Sjkoshy errno = EINVAL; 3546147191Sjkoshy goto out; 3547147191Sjkoshy } 3548145256Sjkoshy 3549147191Sjkoshy bzero(&pmc_config, sizeof(pmc_config)); 3550183725Sjkoshy pmc_config.pm_ev = ev->pm_ev_code; 3551183725Sjkoshy pmc_config.pm_class = pcd->pm_evc_class; 3552147191Sjkoshy pmc_config.pm_cpu = cpu; 3553147191Sjkoshy pmc_config.pm_mode = mode; 3554147191Sjkoshy pmc_config.pm_flags = flags; 3555145256Sjkoshy 3556147191Sjkoshy if (PMC_IS_SAMPLING_MODE(mode)) 3557147191Sjkoshy pmc_config.pm_caps |= PMC_CAP_INTERRUPT; 3558145256Sjkoshy 3559183725Sjkoshy if (pcd->pm_evc_allocate_pmc(ev->pm_ev_code, r, &pmc_config) < 0) { 3560147191Sjkoshy errno = EINVAL; 3561147191Sjkoshy goto out; 3562147191Sjkoshy } 3563145256Sjkoshy 3564147191Sjkoshy if (PMC_CALL(PMCALLOCATE, &pmc_config) < 0) 3565147191Sjkoshy goto out; 3566145256Sjkoshy 3567147191Sjkoshy *pmcid = pmc_config.pm_pmcid; 3568145256Sjkoshy 3569147191Sjkoshy retval = 0; 3570145256Sjkoshy 3571147191Sjkoshy out: 3572147191Sjkoshy if (spec_copy) 3573147191Sjkoshy free(spec_copy); 3574145256Sjkoshy 3575174406Sjkoshy return (retval); 3576147191Sjkoshy} 3577145256Sjkoshy 3578147191Sjkoshyint 3579147191Sjkoshypmc_attach(pmc_id_t pmc, pid_t pid) 3580147191Sjkoshy{ 3581147191Sjkoshy struct pmc_op_pmcattach pmc_attach_args; 3582145256Sjkoshy 3583147191Sjkoshy pmc_attach_args.pm_pmc = pmc; 3584147191Sjkoshy pmc_attach_args.pm_pid = pid; 3585145256Sjkoshy 3586174406Sjkoshy return (PMC_CALL(PMCATTACH, &pmc_attach_args)); 3587147191Sjkoshy} 3588145256Sjkoshy 3589147191Sjkoshyint 3590147191Sjkoshypmc_capabilities(pmc_id_t pmcid, uint32_t *caps) 3591147191Sjkoshy{ 3592147191Sjkoshy unsigned int i; 3593147191Sjkoshy enum pmc_class cl; 3594145256Sjkoshy 3595147191Sjkoshy cl = PMC_ID_TO_CLASS(pmcid); 3596147191Sjkoshy for (i = 0; i < cpu_info.pm_nclass; i++) 3597147191Sjkoshy if (cpu_info.pm_classes[i].pm_class == cl) { 3598147191Sjkoshy *caps = cpu_info.pm_classes[i].pm_caps; 3599174406Sjkoshy return (0); 3600147191Sjkoshy } 3601177107Sjkoshy errno = EINVAL; 3602177107Sjkoshy return (-1); 3603147191Sjkoshy} 3604145256Sjkoshy 3605147191Sjkoshyint 3606147191Sjkoshypmc_configure_logfile(int fd) 3607147191Sjkoshy{ 3608147191Sjkoshy struct pmc_op_configurelog cla; 3609145256Sjkoshy 3610147191Sjkoshy cla.pm_logfd = fd; 3611147191Sjkoshy if (PMC_CALL(CONFIGURELOG, &cla) < 0) 3612174406Sjkoshy return (-1); 3613174406Sjkoshy return (0); 3614147191Sjkoshy} 3615145256Sjkoshy 3616147191Sjkoshyint 3617147191Sjkoshypmc_cpuinfo(const struct pmc_cpuinfo **pci) 3618147191Sjkoshy{ 3619147191Sjkoshy if (pmc_syscall == -1) { 3620147191Sjkoshy errno = ENXIO; 3621174406Sjkoshy return (-1); 3622147191Sjkoshy } 3623145256Sjkoshy 3624147219Sjkoshy *pci = &cpu_info; 3625174406Sjkoshy return (0); 3626147191Sjkoshy} 3627145256Sjkoshy 3628147191Sjkoshyint 3629147191Sjkoshypmc_detach(pmc_id_t pmc, pid_t pid) 3630147191Sjkoshy{ 3631147191Sjkoshy struct pmc_op_pmcattach pmc_detach_args; 3632145256Sjkoshy 3633147191Sjkoshy pmc_detach_args.pm_pmc = pmc; 3634147191Sjkoshy pmc_detach_args.pm_pid = pid; 3635174406Sjkoshy return (PMC_CALL(PMCDETACH, &pmc_detach_args)); 3636147191Sjkoshy} 3637147191Sjkoshy 3638147191Sjkoshyint 3639147191Sjkoshypmc_disable(int cpu, int pmc) 3640145256Sjkoshy{ 3641147191Sjkoshy struct pmc_op_pmcadmin ssa; 3642145256Sjkoshy 3643147191Sjkoshy ssa.pm_cpu = cpu; 3644147191Sjkoshy ssa.pm_pmc = pmc; 3645147191Sjkoshy ssa.pm_state = PMC_STATE_DISABLED; 3646174406Sjkoshy return (PMC_CALL(PMCADMIN, &ssa)); 3647147191Sjkoshy} 3648145256Sjkoshy 3649147191Sjkoshyint 3650147191Sjkoshypmc_enable(int cpu, int pmc) 3651147191Sjkoshy{ 3652147191Sjkoshy struct pmc_op_pmcadmin ssa; 3653145256Sjkoshy 3654147191Sjkoshy ssa.pm_cpu = cpu; 3655147191Sjkoshy ssa.pm_pmc = pmc; 3656147191Sjkoshy ssa.pm_state = PMC_STATE_FREE; 3657174406Sjkoshy return (PMC_CALL(PMCADMIN, &ssa)); 3658147191Sjkoshy} 3659145256Sjkoshy 3660147191Sjkoshy/* 3661147191Sjkoshy * Return a list of events known to a given PMC class. 'cl' is the 3662147191Sjkoshy * PMC class identifier, 'eventnames' is the returned list of 'const 3663147191Sjkoshy * char *' pointers pointing to the names of the events. 'nevents' is 3664147191Sjkoshy * the number of event name pointers returned. 3665147191Sjkoshy * 3666147191Sjkoshy * The space for 'eventnames' is allocated using malloc(3). The caller 3667147191Sjkoshy * is responsible for freeing this space when done. 3668147191Sjkoshy */ 3669147191Sjkoshyint 3670147191Sjkoshypmc_event_names_of_class(enum pmc_class cl, const char ***eventnames, 3671147191Sjkoshy int *nevents) 3672147191Sjkoshy{ 3673147191Sjkoshy int count; 3674147191Sjkoshy const char **names; 3675147191Sjkoshy const struct pmc_event_descr *ev; 3676147191Sjkoshy 3677147191Sjkoshy switch (cl) 3678147191Sjkoshy { 3679185363Sjkoshy case PMC_CLASS_IAF: 3680185363Sjkoshy ev = iaf_event_table; 3681185363Sjkoshy count = PMC_EVENT_TABLE_SIZE(iaf); 3682185363Sjkoshy break; 3683185363Sjkoshy case PMC_CLASS_IAP: 3684185363Sjkoshy /* 3685185363Sjkoshy * Return the most appropriate set of event name 3686185363Sjkoshy * spellings for the current CPU. 3687185363Sjkoshy */ 3688185363Sjkoshy switch (cpu_info.pm_cputype) { 3689185363Sjkoshy default: 3690185363Sjkoshy case PMC_CPU_INTEL_ATOM: 3691185363Sjkoshy ev = atom_event_table; 3692185363Sjkoshy count = PMC_EVENT_TABLE_SIZE(atom); 3693185363Sjkoshy break; 3694263446Shiren case PMC_CPU_INTEL_ATOM_SILVERMONT: 3695263446Shiren ev = atom_silvermont_event_table; 3696263446Shiren count = PMC_EVENT_TABLE_SIZE(atom_silvermont); 3697263446Shiren break; 3698185363Sjkoshy case PMC_CPU_INTEL_CORE: 3699185363Sjkoshy ev = core_event_table; 3700185363Sjkoshy count = PMC_EVENT_TABLE_SIZE(core); 3701185363Sjkoshy break; 3702185363Sjkoshy case PMC_CPU_INTEL_CORE2: 3703185585Sjkoshy case PMC_CPU_INTEL_CORE2EXTREME: 3704185363Sjkoshy ev = core2_event_table; 3705185363Sjkoshy count = PMC_EVENT_TABLE_SIZE(core2); 3706185363Sjkoshy break; 3707187761Sjeff case PMC_CPU_INTEL_COREI7: 3708187761Sjeff ev = corei7_event_table; 3709187761Sjeff count = PMC_EVENT_TABLE_SIZE(corei7); 3710187761Sjeff break; 3711267062Skib case PMC_CPU_INTEL_NEHALEM_EX: 3712267062Skib ev = nehalem_ex_event_table; 3713267062Skib count = PMC_EVENT_TABLE_SIZE(nehalem_ex); 3714267062Skib break; 3715248842Ssbruno case PMC_CPU_INTEL_HASWELL: 3716248842Ssbruno ev = haswell_event_table; 3717248842Ssbruno count = PMC_EVENT_TABLE_SIZE(haswell); 3718248842Ssbruno break; 3719277177Srrs case PMC_CPU_INTEL_HASWELL_XEON: 3720277177Srrs ev = haswell_xeon_event_table; 3721277177Srrs count = PMC_EVENT_TABLE_SIZE(haswell_xeon); 3722277177Srrs break; 3723291494Srrs case PMC_CPU_INTEL_BROADWELL: 3724291494Srrs ev = broadwell_event_table; 3725291494Srrs count = PMC_EVENT_TABLE_SIZE(broadwell); 3726291494Srrs break; 3727291494Srrs case PMC_CPU_INTEL_BROADWELL_XEON: 3728291494Srrs ev = broadwell_xeon_event_table; 3729291494Srrs count = PMC_EVENT_TABLE_SIZE(broadwell_xeon); 3730291494Srrs break; 3731291494Srrs case PMC_CPU_INTEL_SKYLAKE: 3732291494Srrs ev = skylake_event_table; 3733291494Srrs count = PMC_EVENT_TABLE_SIZE(skylake); 3734291494Srrs break; 3735323799Skib case PMC_CPU_INTEL_SKYLAKE_XEON: 3736323799Skib ev = skylake_xeon_event_table; 3737323799Skib count = PMC_EVENT_TABLE_SIZE(skylake_xeon); 3738323799Skib break; 3739240164Sfabient case PMC_CPU_INTEL_IVYBRIDGE: 3740240164Sfabient ev = ivybridge_event_table; 3741240164Sfabient count = PMC_EVENT_TABLE_SIZE(ivybridge); 3742240164Sfabient break; 3743246166Ssbruno case PMC_CPU_INTEL_IVYBRIDGE_XEON: 3744246166Ssbruno ev = ivybridge_xeon_event_table; 3745246166Ssbruno count = PMC_EVENT_TABLE_SIZE(ivybridge_xeon); 3746246166Ssbruno break; 3747232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 3748232366Sdavide ev = sandybridge_event_table; 3749232366Sdavide count = PMC_EVENT_TABLE_SIZE(sandybridge); 3750232366Sdavide break; 3751241738Ssbruno case PMC_CPU_INTEL_SANDYBRIDGE_XEON: 3752241738Ssbruno ev = sandybridge_xeon_event_table; 3753241738Ssbruno count = PMC_EVENT_TABLE_SIZE(sandybridge_xeon); 3754241738Ssbruno break; 3755206089Sfabient case PMC_CPU_INTEL_WESTMERE: 3756206089Sfabient ev = westmere_event_table; 3757206089Sfabient count = PMC_EVENT_TABLE_SIZE(westmere); 3758206089Sfabient break; 3759267062Skib case PMC_CPU_INTEL_WESTMERE_EX: 3760267062Skib ev = westmere_ex_event_table; 3761267062Skib count = PMC_EVENT_TABLE_SIZE(westmere_ex); 3762267062Skib break; 3763185363Sjkoshy } 3764185363Sjkoshy break; 3765206089Sfabient case PMC_CLASS_UCF: 3766206089Sfabient ev = ucf_event_table; 3767206089Sfabient count = PMC_EVENT_TABLE_SIZE(ucf); 3768206089Sfabient break; 3769206089Sfabient case PMC_CLASS_UCP: 3770206089Sfabient /* 3771206089Sfabient * Return the most appropriate set of event name 3772206089Sfabient * spellings for the current CPU. 3773206089Sfabient */ 3774206089Sfabient switch (cpu_info.pm_cputype) { 3775206089Sfabient default: 3776206089Sfabient case PMC_CPU_INTEL_COREI7: 3777206089Sfabient ev = corei7uc_event_table; 3778206089Sfabient count = PMC_EVENT_TABLE_SIZE(corei7uc); 3779206089Sfabient break; 3780248842Ssbruno case PMC_CPU_INTEL_HASWELL: 3781248842Ssbruno ev = haswelluc_event_table; 3782248842Ssbruno count = PMC_EVENT_TABLE_SIZE(haswelluc); 3783248842Ssbruno break; 3784291494Srrs case PMC_CPU_INTEL_BROADWELL: 3785291494Srrs ev = broadwelluc_event_table; 3786291494Srrs count = PMC_EVENT_TABLE_SIZE(broadwelluc); 3787291494Srrs break; 3788232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 3789232366Sdavide ev = sandybridgeuc_event_table; 3790232366Sdavide count = PMC_EVENT_TABLE_SIZE(sandybridgeuc); 3791232366Sdavide break; 3792206089Sfabient case PMC_CPU_INTEL_WESTMERE: 3793206089Sfabient ev = westmereuc_event_table; 3794206089Sfabient count = PMC_EVENT_TABLE_SIZE(westmereuc); 3795206089Sfabient break; 3796206089Sfabient } 3797206089Sfabient break; 3798147191Sjkoshy case PMC_CLASS_TSC: 3799183725Sjkoshy ev = tsc_event_table; 3800183725Sjkoshy count = PMC_EVENT_TABLE_SIZE(tsc); 3801145256Sjkoshy break; 3802147191Sjkoshy case PMC_CLASS_K7: 3803183725Sjkoshy ev = k7_event_table; 3804183725Sjkoshy count = PMC_EVENT_TABLE_SIZE(k7); 3805145256Sjkoshy break; 3806147191Sjkoshy case PMC_CLASS_K8: 3807183725Sjkoshy ev = k8_event_table; 3808183725Sjkoshy count = PMC_EVENT_TABLE_SIZE(k8); 3809145256Sjkoshy break; 3810339767Smmacy case PMC_CLASS_F17H: 3811339767Smmacy ev = f17h_event_table; 3812339767Smmacy count = PMC_EVENT_TABLE_SIZE(f17h); 3813339767Smmacy break; 3814183725Sjkoshy case PMC_CLASS_P4: 3815183725Sjkoshy ev = p4_event_table; 3816183725Sjkoshy count = PMC_EVENT_TABLE_SIZE(p4); 3817183725Sjkoshy break; 3818147191Sjkoshy case PMC_CLASS_P5: 3819183725Sjkoshy ev = p5_event_table; 3820183725Sjkoshy count = PMC_EVENT_TABLE_SIZE(p5); 3821145256Sjkoshy break; 3822147191Sjkoshy case PMC_CLASS_P6: 3823183725Sjkoshy ev = p6_event_table; 3824183725Sjkoshy count = PMC_EVENT_TABLE_SIZE(p6); 3825145256Sjkoshy break; 3826200928Srpaulo case PMC_CLASS_XSCALE: 3827200928Srpaulo ev = xscale_event_table; 3828200928Srpaulo count = PMC_EVENT_TABLE_SIZE(xscale); 3829200928Srpaulo break; 3830277835Sbr case PMC_CLASS_ARMV7: 3831284218Sbr switch (cpu_info.pm_cputype) { 3832284218Sbr default: 3833284218Sbr case PMC_CPU_ARMV7_CORTEX_A8: 3834284218Sbr ev = cortex_a8_event_table; 3835284218Sbr count = PMC_EVENT_TABLE_SIZE(cortex_a8); 3836284218Sbr break; 3837284218Sbr case PMC_CPU_ARMV7_CORTEX_A9: 3838284218Sbr ev = cortex_a9_event_table; 3839284218Sbr count = PMC_EVENT_TABLE_SIZE(cortex_a9); 3840284218Sbr break; 3841284218Sbr } 3842277835Sbr break; 3843283112Sbr case PMC_CLASS_ARMV8: 3844283112Sbr switch (cpu_info.pm_cputype) { 3845283112Sbr default: 3846283112Sbr case PMC_CPU_ARMV8_CORTEX_A53: 3847283112Sbr ev = cortex_a53_event_table; 3848283112Sbr count = PMC_EVENT_TABLE_SIZE(cortex_a53); 3849283112Sbr break; 3850283112Sbr case PMC_CPU_ARMV8_CORTEX_A57: 3851283112Sbr ev = cortex_a57_event_table; 3852283112Sbr count = PMC_EVENT_TABLE_SIZE(cortex_a57); 3853283112Sbr break; 3854283112Sbr } 3855283112Sbr break; 3856204635Sgnn case PMC_CLASS_MIPS24K: 3857204635Sgnn ev = mips24k_event_table; 3858204635Sgnn count = PMC_EVENT_TABLE_SIZE(mips24k); 3859204635Sgnn break; 3860281098Sadrian case PMC_CLASS_MIPS74K: 3861281098Sadrian ev = mips74k_event_table; 3862281098Sadrian count = PMC_EVENT_TABLE_SIZE(mips74k); 3863281098Sadrian break; 3864233335Sgonzo case PMC_CLASS_OCTEON: 3865233335Sgonzo ev = octeon_event_table; 3866233335Sgonzo count = PMC_EVENT_TABLE_SIZE(octeon); 3867233335Sgonzo break; 3868228869Sjhibbits case PMC_CLASS_PPC7450: 3869228869Sjhibbits ev = ppc7450_event_table; 3870228869Sjhibbits count = PMC_EVENT_TABLE_SIZE(ppc7450); 3871228869Sjhibbits break; 3872261342Sjhibbits case PMC_CLASS_PPC970: 3873261342Sjhibbits ev = ppc970_event_table; 3874261342Sjhibbits count = PMC_EVENT_TABLE_SIZE(ppc970); 3875261342Sjhibbits break; 3876281713Sjhibbits case PMC_CLASS_E500: 3877281713Sjhibbits ev = e500_event_table; 3878281713Sjhibbits count = PMC_EVENT_TABLE_SIZE(e500); 3879281713Sjhibbits break; 3880233628Sfabient case PMC_CLASS_SOFT: 3881233628Sfabient ev = soft_event_table; 3882233628Sfabient count = soft_event_info.pm_nevent; 3883233628Sfabient break; 3884145256Sjkoshy default: 3885147191Sjkoshy errno = EINVAL; 3886174406Sjkoshy return (-1); 3887145256Sjkoshy } 3888145256Sjkoshy 3889147191Sjkoshy if ((names = malloc(count * sizeof(const char *))) == NULL) 3890174406Sjkoshy return (-1); 3891145256Sjkoshy 3892147191Sjkoshy *eventnames = names; 3893147191Sjkoshy *nevents = count; 3894145256Sjkoshy 3895147191Sjkoshy for (;count--; ev++, names++) 3896147191Sjkoshy *names = ev->pm_ev_name; 3897233628Sfabient 3898174406Sjkoshy return (0); 3899147191Sjkoshy} 3900145256Sjkoshy 3901147191Sjkoshyint 3902147191Sjkoshypmc_flush_logfile(void) 3903147191Sjkoshy{ 3904174406Sjkoshy return (PMC_CALL(FLUSHLOG,0)); 3905147191Sjkoshy} 3906145256Sjkoshy 3907147191Sjkoshyint 3908226514Sfabientpmc_close_logfile(void) 3909226514Sfabient{ 3910226514Sfabient return (PMC_CALL(CLOSELOG,0)); 3911226514Sfabient} 3912226514Sfabient 3913226514Sfabientint 3914147191Sjkoshypmc_get_driver_stats(struct pmc_driverstats *ds) 3915147191Sjkoshy{ 3916147191Sjkoshy struct pmc_op_getdriverstats gms; 3917145256Sjkoshy 3918147191Sjkoshy if (PMC_CALL(GETDRIVERSTATS, &gms) < 0) 3919174406Sjkoshy return (-1); 3920145256Sjkoshy 3921147191Sjkoshy /* copy out fields in the current userland<->library interface */ 3922147191Sjkoshy ds->pm_intr_ignored = gms.pm_intr_ignored; 3923147191Sjkoshy ds->pm_intr_processed = gms.pm_intr_processed; 3924147191Sjkoshy ds->pm_intr_bufferfull = gms.pm_intr_bufferfull; 3925147191Sjkoshy ds->pm_syscalls = gms.pm_syscalls; 3926147191Sjkoshy ds->pm_syscall_errors = gms.pm_syscall_errors; 3927147191Sjkoshy ds->pm_buffer_requests = gms.pm_buffer_requests; 3928147191Sjkoshy ds->pm_buffer_requests_failed = gms.pm_buffer_requests_failed; 3929147191Sjkoshy ds->pm_log_sweeps = gms.pm_log_sweeps; 3930174406Sjkoshy return (0); 3931147191Sjkoshy} 3932145256Sjkoshy 3933147191Sjkoshyint 3934147191Sjkoshypmc_get_msr(pmc_id_t pmc, uint32_t *msr) 3935147191Sjkoshy{ 3936147191Sjkoshy struct pmc_op_getmsr gm; 3937147191Sjkoshy 3938147191Sjkoshy gm.pm_pmcid = pmc; 3939147191Sjkoshy if (PMC_CALL(PMCGETMSR, &gm) < 0) 3940174406Sjkoshy return (-1); 3941147191Sjkoshy *msr = gm.pm_msr; 3942174406Sjkoshy return (0); 3943145256Sjkoshy} 3944145256Sjkoshy 3945145256Sjkoshyint 3946145256Sjkoshypmc_init(void) 3947145256Sjkoshy{ 3948145256Sjkoshy int error, pmc_mod_id; 3949147219Sjkoshy unsigned int n; 3950145256Sjkoshy uint32_t abi_version; 3951145256Sjkoshy struct module_stat pmc_modstat; 3952147219Sjkoshy struct pmc_op_getcpuinfo op_cpu_info; 3953198433Sjkoshy#if defined(__amd64__) || defined(__i386__) 3954198433Sjkoshy int cpu_has_iaf_counters; 3955198433Sjkoshy unsigned int t; 3956198433Sjkoshy#endif 3957145256Sjkoshy 3958145256Sjkoshy if (pmc_syscall != -1) /* already inited */ 3959174406Sjkoshy return (0); 3960145256Sjkoshy 3961145256Sjkoshy /* retrieve the system call number from the KLD */ 3962145256Sjkoshy if ((pmc_mod_id = modfind(PMC_MODULE_NAME)) < 0) 3963174406Sjkoshy return (-1); 3964145256Sjkoshy 3965145256Sjkoshy pmc_modstat.version = sizeof(struct module_stat); 3966145256Sjkoshy if ((error = modstat(pmc_mod_id, &pmc_modstat)) < 0) 3967174406Sjkoshy return (-1); 3968145256Sjkoshy 3969145256Sjkoshy pmc_syscall = pmc_modstat.data.intval; 3970145256Sjkoshy 3971147191Sjkoshy /* check the kernel module's ABI against our compiled-in version */ 3972147191Sjkoshy abi_version = PMC_VERSION; 3973145256Sjkoshy if (PMC_CALL(GETMODULEVERSION, &abi_version) < 0) 3974145256Sjkoshy return (pmc_syscall = -1); 3975145256Sjkoshy 3976298896Spfg /* ignore patch & minor numbers for the comparison */ 3977147191Sjkoshy if ((abi_version & 0xFF000000) != (PMC_VERSION & 0xFF000000)) { 3978145256Sjkoshy errno = EPROGMISMATCH; 3979145256Sjkoshy return (pmc_syscall = -1); 3980145256Sjkoshy } 3981145256Sjkoshy 3982147219Sjkoshy if (PMC_CALL(GETCPUINFO, &op_cpu_info) < 0) 3983145256Sjkoshy return (pmc_syscall = -1); 3984145256Sjkoshy 3985147219Sjkoshy cpu_info.pm_cputype = op_cpu_info.pm_cputype; 3986147219Sjkoshy cpu_info.pm_ncpu = op_cpu_info.pm_ncpu; 3987147219Sjkoshy cpu_info.pm_npmc = op_cpu_info.pm_npmc; 3988147219Sjkoshy cpu_info.pm_nclass = op_cpu_info.pm_nclass; 3989147219Sjkoshy for (n = 0; n < cpu_info.pm_nclass; n++) 3990328837Sjhibbits memcpy(&cpu_info.pm_classes[n], &op_cpu_info.pm_classes[n], 3991328837Sjhibbits sizeof(cpu_info.pm_classes[n])); 3992147219Sjkoshy 3993185363Sjkoshy pmc_class_table = malloc(PMC_CLASS_TABLE_SIZE * 3994185363Sjkoshy sizeof(struct pmc_class_descr *)); 3995185363Sjkoshy 3996185363Sjkoshy if (pmc_class_table == NULL) 3997185363Sjkoshy return (-1); 3998185363Sjkoshy 3999198433Sjkoshy for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) 4000198433Sjkoshy pmc_class_table[n] = NULL; 4001185363Sjkoshy 4002185363Sjkoshy /* 4003233628Sfabient * Get soft events list. 4004233628Sfabient */ 4005233628Sfabient soft_event_info.pm_class = PMC_CLASS_SOFT; 4006233628Sfabient if (PMC_CALL(GETDYNEVENTINFO, &soft_event_info) < 0) 4007233628Sfabient return (pmc_syscall = -1); 4008233628Sfabient 4009233628Sfabient /* Map soft events to static list. */ 4010233628Sfabient for (n = 0; n < soft_event_info.pm_nevent; n++) { 4011233628Sfabient soft_event_table[n].pm_ev_name = 4012233628Sfabient soft_event_info.pm_events[n].pm_ev_name; 4013233628Sfabient soft_event_table[n].pm_ev_code = 4014233628Sfabient soft_event_info.pm_events[n].pm_ev_code; 4015233628Sfabient } 4016233628Sfabient soft_class_table_descr.pm_evc_event_table_size = \ 4017233628Sfabient soft_event_info.pm_nevent; 4018233628Sfabient soft_class_table_descr.pm_evc_event_table = \ 4019233628Sfabient soft_event_table; 4020233628Sfabient 4021233628Sfabient /* 4022185363Sjkoshy * Fill in the class table. 4023185363Sjkoshy */ 4024185363Sjkoshy n = 0; 4025233628Sfabient 4026233628Sfabient /* Fill soft events information. */ 4027233628Sfabient pmc_class_table[n++] = &soft_class_table_descr; 4028185363Sjkoshy#if defined(__amd64__) || defined(__i386__) 4029233628Sfabient if (cpu_info.pm_cputype != PMC_CPU_GENERIC) 4030233628Sfabient pmc_class_table[n++] = &tsc_class_table_descr; 4031198433Sjkoshy 4032198433Sjkoshy /* 4033198433Sjkoshy * Check if this CPU has fixed function counters. 4034198433Sjkoshy */ 4035198433Sjkoshy cpu_has_iaf_counters = 0; 4036198433Sjkoshy for (t = 0; t < cpu_info.pm_nclass; t++) 4037212224Sfabient if (cpu_info.pm_classes[t].pm_class == PMC_CLASS_IAF && 4038212224Sfabient cpu_info.pm_classes[t].pm_num > 0) 4039198433Sjkoshy cpu_has_iaf_counters = 1; 4040185363Sjkoshy#endif 4041185363Sjkoshy 4042183725Sjkoshy#define PMC_MDEP_INIT(C) do { \ 4043183725Sjkoshy pmc_mdep_event_aliases = C##_aliases; \ 4044183725Sjkoshy pmc_mdep_class_list = C##_pmc_classes; \ 4045183725Sjkoshy pmc_mdep_class_list_size = \ 4046183725Sjkoshy PMC_TABLE_SIZE(C##_pmc_classes); \ 4047183725Sjkoshy } while (0) 4048183725Sjkoshy 4049198433Sjkoshy#define PMC_MDEP_INIT_INTEL_V2(C) do { \ 4050198433Sjkoshy PMC_MDEP_INIT(C); \ 4051212224Sfabient pmc_class_table[n++] = &iaf_class_table_descr; \ 4052212224Sfabient if (!cpu_has_iaf_counters) \ 4053198433Sjkoshy pmc_mdep_event_aliases = \ 4054198433Sjkoshy C##_aliases_without_iaf; \ 4055198433Sjkoshy pmc_class_table[n] = &C##_class_table_descr; \ 4056198433Sjkoshy } while (0) 4057198433Sjkoshy 4058183725Sjkoshy /* Configure the event name parser. */ 4059145256Sjkoshy switch (cpu_info.pm_cputype) { 4060145340Smarcel#if defined(__i386__) 4061145256Sjkoshy case PMC_CPU_AMD_K7: 4062183725Sjkoshy PMC_MDEP_INIT(k7); 4063185363Sjkoshy pmc_class_table[n] = &k7_class_table_descr; 4064145256Sjkoshy break; 4065145256Sjkoshy case PMC_CPU_INTEL_P5: 4066183725Sjkoshy PMC_MDEP_INIT(p5); 4067185363Sjkoshy pmc_class_table[n] = &p5_class_table_descr; 4068145256Sjkoshy break; 4069145256Sjkoshy case PMC_CPU_INTEL_P6: /* P6 ... Pentium M CPUs have */ 4070145256Sjkoshy case PMC_CPU_INTEL_PII: /* similar PMCs. */ 4071145256Sjkoshy case PMC_CPU_INTEL_PIII: 4072145256Sjkoshy case PMC_CPU_INTEL_PM: 4073183725Sjkoshy PMC_MDEP_INIT(p6); 4074185363Sjkoshy pmc_class_table[n] = &p6_class_table_descr; 4075145256Sjkoshy break; 4076147759Sjkoshy#endif 4077147759Sjkoshy#if defined(__amd64__) || defined(__i386__) 4078183725Sjkoshy case PMC_CPU_AMD_K8: 4079183725Sjkoshy PMC_MDEP_INIT(k8); 4080185363Sjkoshy pmc_class_table[n] = &k8_class_table_descr; 4081183725Sjkoshy break; 4082339767Smmacy case PMC_CPU_AMD_F17H: 4083339767Smmacy PMC_MDEP_INIT(f17h); 4084339767Smmacy pmc_class_table[n] = &f17h_class_table_descr; 4085339767Smmacy break; 4086185363Sjkoshy case PMC_CPU_INTEL_ATOM: 4087198433Sjkoshy PMC_MDEP_INIT_INTEL_V2(atom); 4088185363Sjkoshy break; 4089263446Shiren case PMC_CPU_INTEL_ATOM_SILVERMONT: 4090263446Shiren PMC_MDEP_INIT_INTEL_V2(atom_silvermont); 4091263446Shiren break; 4092185363Sjkoshy case PMC_CPU_INTEL_CORE: 4093185363Sjkoshy PMC_MDEP_INIT(core); 4094202157Sjkoshy pmc_class_table[n] = &core_class_table_descr; 4095185363Sjkoshy break; 4096185363Sjkoshy case PMC_CPU_INTEL_CORE2: 4097185585Sjkoshy case PMC_CPU_INTEL_CORE2EXTREME: 4098198433Sjkoshy PMC_MDEP_INIT_INTEL_V2(core2); 4099185363Sjkoshy break; 4100187761Sjeff case PMC_CPU_INTEL_COREI7: 4101206089Sfabient pmc_class_table[n++] = &ucf_class_table_descr; 4102206089Sfabient pmc_class_table[n++] = &corei7uc_class_table_descr; 4103198433Sjkoshy PMC_MDEP_INIT_INTEL_V2(corei7); 4104187761Sjeff break; 4105267062Skib case PMC_CPU_INTEL_NEHALEM_EX: 4106267062Skib PMC_MDEP_INIT_INTEL_V2(nehalem_ex); 4107267062Skib break; 4108248842Ssbruno case PMC_CPU_INTEL_HASWELL: 4109248842Ssbruno pmc_class_table[n++] = &ucf_class_table_descr; 4110248842Ssbruno pmc_class_table[n++] = &haswelluc_class_table_descr; 4111248842Ssbruno PMC_MDEP_INIT_INTEL_V2(haswell); 4112248842Ssbruno break; 4113277177Srrs case PMC_CPU_INTEL_HASWELL_XEON: 4114277177Srrs PMC_MDEP_INIT_INTEL_V2(haswell_xeon); 4115277177Srrs break; 4116291494Srrs case PMC_CPU_INTEL_BROADWELL: 4117291494Srrs pmc_class_table[n++] = &ucf_class_table_descr; 4118291494Srrs pmc_class_table[n++] = &broadwelluc_class_table_descr; 4119291494Srrs PMC_MDEP_INIT_INTEL_V2(broadwell); 4120291494Srrs break; 4121291494Srrs case PMC_CPU_INTEL_BROADWELL_XEON: 4122291494Srrs PMC_MDEP_INIT_INTEL_V2(broadwell_xeon); 4123291494Srrs break; 4124291494Srrs case PMC_CPU_INTEL_SKYLAKE: 4125291494Srrs PMC_MDEP_INIT_INTEL_V2(skylake); 4126291494Srrs break; 4127323799Skib case PMC_CPU_INTEL_SKYLAKE_XEON: 4128323799Skib PMC_MDEP_INIT_INTEL_V2(skylake_xeon); 4129323799Skib break; 4130240164Sfabient case PMC_CPU_INTEL_IVYBRIDGE: 4131240164Sfabient PMC_MDEP_INIT_INTEL_V2(ivybridge); 4132240164Sfabient break; 4133246166Ssbruno case PMC_CPU_INTEL_IVYBRIDGE_XEON: 4134246166Ssbruno PMC_MDEP_INIT_INTEL_V2(ivybridge_xeon); 4135246166Ssbruno break; 4136232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 4137232366Sdavide pmc_class_table[n++] = &ucf_class_table_descr; 4138232366Sdavide pmc_class_table[n++] = &sandybridgeuc_class_table_descr; 4139232366Sdavide PMC_MDEP_INIT_INTEL_V2(sandybridge); 4140232366Sdavide break; 4141241738Ssbruno case PMC_CPU_INTEL_SANDYBRIDGE_XEON: 4142241738Ssbruno PMC_MDEP_INIT_INTEL_V2(sandybridge_xeon); 4143241738Ssbruno break; 4144206089Sfabient case PMC_CPU_INTEL_WESTMERE: 4145206089Sfabient pmc_class_table[n++] = &ucf_class_table_descr; 4146206089Sfabient pmc_class_table[n++] = &westmereuc_class_table_descr; 4147206089Sfabient PMC_MDEP_INIT_INTEL_V2(westmere); 4148206089Sfabient break; 4149267062Skib case PMC_CPU_INTEL_WESTMERE_EX: 4150267062Skib PMC_MDEP_INIT_INTEL_V2(westmere_ex); 4151267062Skib break; 4152145256Sjkoshy case PMC_CPU_INTEL_PIV: 4153183725Sjkoshy PMC_MDEP_INIT(p4); 4154185363Sjkoshy pmc_class_table[n] = &p4_class_table_descr; 4155145256Sjkoshy break; 4156145256Sjkoshy#endif 4157233628Sfabient case PMC_CPU_GENERIC: 4158233628Sfabient PMC_MDEP_INIT(generic); 4159233628Sfabient break; 4160277835Sbr#if defined(__arm__) 4161200928Srpaulo#if defined(__XSCALE__) 4162200928Srpaulo case PMC_CPU_INTEL_XSCALE: 4163200928Srpaulo PMC_MDEP_INIT(xscale); 4164200928Srpaulo pmc_class_table[n] = &xscale_class_table_descr; 4165200928Srpaulo break; 4166200928Srpaulo#endif 4167284218Sbr case PMC_CPU_ARMV7_CORTEX_A8: 4168284218Sbr PMC_MDEP_INIT(cortex_a8); 4169284218Sbr pmc_class_table[n] = &cortex_a8_class_table_descr; 4170277835Sbr break; 4171284218Sbr case PMC_CPU_ARMV7_CORTEX_A9: 4172284218Sbr PMC_MDEP_INIT(cortex_a9); 4173284218Sbr pmc_class_table[n] = &cortex_a9_class_table_descr; 4174284218Sbr break; 4175277835Sbr#endif 4176283112Sbr#if defined(__aarch64__) 4177283112Sbr case PMC_CPU_ARMV8_CORTEX_A53: 4178283112Sbr PMC_MDEP_INIT(cortex_a53); 4179283112Sbr pmc_class_table[n] = &cortex_a53_class_table_descr; 4180283112Sbr break; 4181283112Sbr case PMC_CPU_ARMV8_CORTEX_A57: 4182283112Sbr PMC_MDEP_INIT(cortex_a57); 4183283112Sbr pmc_class_table[n] = &cortex_a57_class_table_descr; 4184283112Sbr break; 4185283112Sbr#endif 4186204635Sgnn#if defined(__mips__) 4187204635Sgnn case PMC_CPU_MIPS_24K: 4188204635Sgnn PMC_MDEP_INIT(mips24k); 4189204635Sgnn pmc_class_table[n] = &mips24k_class_table_descr; 4190204635Sgnn break; 4191281098Sadrian case PMC_CPU_MIPS_74K: 4192281098Sadrian PMC_MDEP_INIT(mips74k); 4193281098Sadrian pmc_class_table[n] = &mips74k_class_table_descr; 4194281098Sadrian break; 4195233335Sgonzo case PMC_CPU_MIPS_OCTEON: 4196233335Sgonzo PMC_MDEP_INIT(octeon); 4197233335Sgonzo pmc_class_table[n] = &octeon_class_table_descr; 4198233335Sgonzo break; 4199204635Sgnn#endif /* __mips__ */ 4200228869Sjhibbits#if defined(__powerpc__) 4201228869Sjhibbits case PMC_CPU_PPC_7450: 4202228869Sjhibbits PMC_MDEP_INIT(ppc7450); 4203228869Sjhibbits pmc_class_table[n] = &ppc7450_class_table_descr; 4204228869Sjhibbits break; 4205261342Sjhibbits case PMC_CPU_PPC_970: 4206261342Sjhibbits PMC_MDEP_INIT(ppc970); 4207261342Sjhibbits pmc_class_table[n] = &ppc970_class_table_descr; 4208261342Sjhibbits break; 4209281713Sjhibbits case PMC_CPU_PPC_E500: 4210281713Sjhibbits PMC_MDEP_INIT(e500); 4211281713Sjhibbits pmc_class_table[n] = &e500_class_table_descr; 4212281713Sjhibbits break; 4213228869Sjhibbits#endif 4214145256Sjkoshy default: 4215145256Sjkoshy /* 4216145256Sjkoshy * Some kind of CPU this version of the library knows nothing 4217145256Sjkoshy * about. This shouldn't happen since the abi version check 4218145256Sjkoshy * should have caught this. 4219145256Sjkoshy */ 4220145256Sjkoshy errno = ENXIO; 4221145256Sjkoshy return (pmc_syscall = -1); 4222145256Sjkoshy } 4223145256Sjkoshy 4224174406Sjkoshy return (0); 4225145256Sjkoshy} 4226145256Sjkoshy 4227147191Sjkoshyconst char * 4228147191Sjkoshypmc_name_of_capability(enum pmc_caps cap) 4229145256Sjkoshy{ 4230147191Sjkoshy int i; 4231145256Sjkoshy 4232147191Sjkoshy /* 4233147191Sjkoshy * 'cap' should have a single bit set and should be in 4234147191Sjkoshy * range. 4235147191Sjkoshy */ 4236147191Sjkoshy if ((cap & (cap - 1)) || cap < PMC_CAP_FIRST || 4237147191Sjkoshy cap > PMC_CAP_LAST) { 4238145256Sjkoshy errno = EINVAL; 4239174406Sjkoshy return (NULL); 4240145256Sjkoshy } 4241145256Sjkoshy 4242147191Sjkoshy i = ffs(cap); 4243174406Sjkoshy return (pmc_capability_names[i - 1]); 4244147191Sjkoshy} 4245145256Sjkoshy 4246147191Sjkoshyconst char * 4247147191Sjkoshypmc_name_of_class(enum pmc_class pc) 4248147191Sjkoshy{ 4249283120Sjhb size_t n; 4250145256Sjkoshy 4251283120Sjhb for (n = 0; n < PMC_TABLE_SIZE(pmc_class_names); n++) 4252283120Sjhb if (pc == pmc_class_names[n].pm_class) 4253283120Sjhb return (pmc_class_names[n].pm_name); 4254283120Sjhb 4255147191Sjkoshy errno = EINVAL; 4256174406Sjkoshy return (NULL); 4257147191Sjkoshy} 4258145256Sjkoshy 4259147191Sjkoshyconst char * 4260147191Sjkoshypmc_name_of_cputype(enum pmc_cputype cp) 4261147191Sjkoshy{ 4262183725Sjkoshy size_t n; 4263183725Sjkoshy 4264183725Sjkoshy for (n = 0; n < PMC_TABLE_SIZE(pmc_cputype_names); n++) 4265183725Sjkoshy if (cp == pmc_cputype_names[n].pm_cputype) 4266183725Sjkoshy return (pmc_cputype_names[n].pm_name); 4267183725Sjkoshy 4268147191Sjkoshy errno = EINVAL; 4269174406Sjkoshy return (NULL); 4270147191Sjkoshy} 4271145256Sjkoshy 4272147191Sjkoshyconst char * 4273147191Sjkoshypmc_name_of_disposition(enum pmc_disp pd) 4274147191Sjkoshy{ 4275147191Sjkoshy if ((int) pd >= PMC_DISP_FIRST && 4276147191Sjkoshy pd <= PMC_DISP_LAST) 4277174406Sjkoshy return (pmc_disposition_names[pd]); 4278145256Sjkoshy 4279147191Sjkoshy errno = EINVAL; 4280174406Sjkoshy return (NULL); 4281147191Sjkoshy} 4282145256Sjkoshy 4283147191Sjkoshyconst char * 4284185363Sjkoshy_pmc_name_of_event(enum pmc_event pe, enum pmc_cputype cpu) 4285147191Sjkoshy{ 4286183725Sjkoshy const struct pmc_event_descr *ev, *evfence; 4287145256Sjkoshy 4288183725Sjkoshy ev = evfence = NULL; 4289185363Sjkoshy if (pe >= PMC_EV_IAF_FIRST && pe <= PMC_EV_IAF_LAST) { 4290185363Sjkoshy ev = iaf_event_table; 4291185363Sjkoshy evfence = iaf_event_table + PMC_EVENT_TABLE_SIZE(iaf); 4292185363Sjkoshy } else if (pe >= PMC_EV_IAP_FIRST && pe <= PMC_EV_IAP_LAST) { 4293185363Sjkoshy switch (cpu) { 4294185363Sjkoshy case PMC_CPU_INTEL_ATOM: 4295185363Sjkoshy ev = atom_event_table; 4296185363Sjkoshy evfence = atom_event_table + PMC_EVENT_TABLE_SIZE(atom); 4297185363Sjkoshy break; 4298263446Shiren case PMC_CPU_INTEL_ATOM_SILVERMONT: 4299263446Shiren ev = atom_silvermont_event_table; 4300263446Shiren evfence = atom_silvermont_event_table + 4301263446Shiren PMC_EVENT_TABLE_SIZE(atom_silvermont); 4302263446Shiren break; 4303185363Sjkoshy case PMC_CPU_INTEL_CORE: 4304185363Sjkoshy ev = core_event_table; 4305185363Sjkoshy evfence = core_event_table + PMC_EVENT_TABLE_SIZE(core); 4306185363Sjkoshy break; 4307185363Sjkoshy case PMC_CPU_INTEL_CORE2: 4308185585Sjkoshy case PMC_CPU_INTEL_CORE2EXTREME: 4309185363Sjkoshy ev = core2_event_table; 4310185363Sjkoshy evfence = core2_event_table + PMC_EVENT_TABLE_SIZE(core2); 4311185363Sjkoshy break; 4312187761Sjeff case PMC_CPU_INTEL_COREI7: 4313187761Sjeff ev = corei7_event_table; 4314187761Sjeff evfence = corei7_event_table + PMC_EVENT_TABLE_SIZE(corei7); 4315187761Sjeff break; 4316267062Skib case PMC_CPU_INTEL_NEHALEM_EX: 4317267062Skib ev = nehalem_ex_event_table; 4318267062Skib evfence = nehalem_ex_event_table + 4319267062Skib PMC_EVENT_TABLE_SIZE(nehalem_ex); 4320267062Skib break; 4321248842Ssbruno case PMC_CPU_INTEL_HASWELL: 4322248842Ssbruno ev = haswell_event_table; 4323248842Ssbruno evfence = haswell_event_table + PMC_EVENT_TABLE_SIZE(haswell); 4324248842Ssbruno break; 4325277177Srrs case PMC_CPU_INTEL_HASWELL_XEON: 4326277177Srrs ev = haswell_xeon_event_table; 4327277177Srrs evfence = haswell_xeon_event_table + PMC_EVENT_TABLE_SIZE(haswell_xeon); 4328277177Srrs break; 4329291494Srrs case PMC_CPU_INTEL_BROADWELL: 4330291494Srrs ev = broadwell_event_table; 4331291494Srrs evfence = broadwell_event_table + PMC_EVENT_TABLE_SIZE(broadwell); 4332291494Srrs break; 4333291494Srrs case PMC_CPU_INTEL_BROADWELL_XEON: 4334291494Srrs ev = broadwell_xeon_event_table; 4335291494Srrs evfence = broadwell_xeon_event_table + PMC_EVENT_TABLE_SIZE(broadwell_xeon); 4336291494Srrs break; 4337291494Srrs case PMC_CPU_INTEL_SKYLAKE: 4338291494Srrs ev = skylake_event_table; 4339323798Skib evfence = skylake_event_table + 4340323798Skib PMC_EVENT_TABLE_SIZE(skylake); 4341291494Srrs break; 4342323799Skib case PMC_CPU_INTEL_SKYLAKE_XEON: 4343323799Skib ev = skylake_xeon_event_table; 4344323799Skib evfence = skylake_xeon_event_table + 4345323799Skib PMC_EVENT_TABLE_SIZE(skylake_xeon); 4346323799Skib break; 4347240164Sfabient case PMC_CPU_INTEL_IVYBRIDGE: 4348240164Sfabient ev = ivybridge_event_table; 4349240164Sfabient evfence = ivybridge_event_table + PMC_EVENT_TABLE_SIZE(ivybridge); 4350240164Sfabient break; 4351246166Ssbruno case PMC_CPU_INTEL_IVYBRIDGE_XEON: 4352246166Ssbruno ev = ivybridge_xeon_event_table; 4353246166Ssbruno evfence = ivybridge_xeon_event_table + PMC_EVENT_TABLE_SIZE(ivybridge_xeon); 4354246166Ssbruno break; 4355232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 4356232366Sdavide ev = sandybridge_event_table; 4357232366Sdavide evfence = sandybridge_event_table + PMC_EVENT_TABLE_SIZE(sandybridge); 4358232366Sdavide break; 4359241738Ssbruno case PMC_CPU_INTEL_SANDYBRIDGE_XEON: 4360241738Ssbruno ev = sandybridge_xeon_event_table; 4361241738Ssbruno evfence = sandybridge_xeon_event_table + PMC_EVENT_TABLE_SIZE(sandybridge_xeon); 4362241738Ssbruno break; 4363206089Sfabient case PMC_CPU_INTEL_WESTMERE: 4364206089Sfabient ev = westmere_event_table; 4365206089Sfabient evfence = westmere_event_table + PMC_EVENT_TABLE_SIZE(westmere); 4366206089Sfabient break; 4367267062Skib case PMC_CPU_INTEL_WESTMERE_EX: 4368267062Skib ev = westmere_ex_event_table; 4369267062Skib evfence = westmere_ex_event_table + 4370267062Skib PMC_EVENT_TABLE_SIZE(westmere_ex); 4371267062Skib break; 4372185363Sjkoshy default: /* Unknown CPU type. */ 4373185363Sjkoshy break; 4374185363Sjkoshy } 4375206089Sfabient } else if (pe >= PMC_EV_UCF_FIRST && pe <= PMC_EV_UCF_LAST) { 4376206089Sfabient ev = ucf_event_table; 4377206089Sfabient evfence = ucf_event_table + PMC_EVENT_TABLE_SIZE(ucf); 4378206089Sfabient } else if (pe >= PMC_EV_UCP_FIRST && pe <= PMC_EV_UCP_LAST) { 4379206089Sfabient switch (cpu) { 4380206089Sfabient case PMC_CPU_INTEL_COREI7: 4381206089Sfabient ev = corei7uc_event_table; 4382206089Sfabient evfence = corei7uc_event_table + PMC_EVENT_TABLE_SIZE(corei7uc); 4383206089Sfabient break; 4384232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 4385232366Sdavide ev = sandybridgeuc_event_table; 4386232366Sdavide evfence = sandybridgeuc_event_table + PMC_EVENT_TABLE_SIZE(sandybridgeuc); 4387232366Sdavide break; 4388206089Sfabient case PMC_CPU_INTEL_WESTMERE: 4389206089Sfabient ev = westmereuc_event_table; 4390206089Sfabient evfence = westmereuc_event_table + PMC_EVENT_TABLE_SIZE(westmereuc); 4391206089Sfabient break; 4392206089Sfabient default: /* Unknown CPU type. */ 4393206089Sfabient break; 4394206089Sfabient } 4395206089Sfabient } else if (pe >= PMC_EV_K7_FIRST && pe <= PMC_EV_K7_LAST) { 4396183725Sjkoshy ev = k7_event_table; 4397183725Sjkoshy evfence = k7_event_table + PMC_EVENT_TABLE_SIZE(k7); 4398183725Sjkoshy } else if (pe >= PMC_EV_K8_FIRST && pe <= PMC_EV_K8_LAST) { 4399183725Sjkoshy ev = k8_event_table; 4400183725Sjkoshy evfence = k8_event_table + PMC_EVENT_TABLE_SIZE(k8); 4401339767Smmacy } else if ((int)pe >= PMC_EV_F17H_FIRST && 4402339767Smmacy (int)pe <= PMC_EV_F17H_LAST) { 4403339767Smmacy ev = f17h_event_table; 4404339767Smmacy evfence = f17h_event_table + PMC_EVENT_TABLE_SIZE(f17h); 4405183725Sjkoshy } else if (pe >= PMC_EV_P4_FIRST && pe <= PMC_EV_P4_LAST) { 4406183725Sjkoshy ev = p4_event_table; 4407183725Sjkoshy evfence = p4_event_table + PMC_EVENT_TABLE_SIZE(p4); 4408183725Sjkoshy } else if (pe >= PMC_EV_P5_FIRST && pe <= PMC_EV_P5_LAST) { 4409183725Sjkoshy ev = p5_event_table; 4410183725Sjkoshy evfence = p5_event_table + PMC_EVENT_TABLE_SIZE(p5); 4411183725Sjkoshy } else if (pe >= PMC_EV_P6_FIRST && pe <= PMC_EV_P6_LAST) { 4412183725Sjkoshy ev = p6_event_table; 4413183725Sjkoshy evfence = p6_event_table + PMC_EVENT_TABLE_SIZE(p6); 4414200928Srpaulo } else if (pe >= PMC_EV_XSCALE_FIRST && pe <= PMC_EV_XSCALE_LAST) { 4415200928Srpaulo ev = xscale_event_table; 4416200928Srpaulo evfence = xscale_event_table + PMC_EVENT_TABLE_SIZE(xscale); 4417277835Sbr } else if (pe >= PMC_EV_ARMV7_FIRST && pe <= PMC_EV_ARMV7_LAST) { 4418284218Sbr switch (cpu) { 4419284218Sbr case PMC_CPU_ARMV7_CORTEX_A8: 4420284218Sbr ev = cortex_a8_event_table; 4421284218Sbr evfence = cortex_a8_event_table + PMC_EVENT_TABLE_SIZE(cortex_a8); 4422284218Sbr break; 4423284218Sbr case PMC_CPU_ARMV7_CORTEX_A9: 4424284218Sbr ev = cortex_a9_event_table; 4425284218Sbr evfence = cortex_a9_event_table + PMC_EVENT_TABLE_SIZE(cortex_a9); 4426284218Sbr break; 4427284218Sbr default: /* Unknown CPU type. */ 4428284218Sbr break; 4429284218Sbr } 4430283112Sbr } else if (pe >= PMC_EV_ARMV8_FIRST && pe <= PMC_EV_ARMV8_LAST) { 4431283112Sbr switch (cpu) { 4432283112Sbr case PMC_CPU_ARMV8_CORTEX_A53: 4433283112Sbr ev = cortex_a53_event_table; 4434283112Sbr evfence = cortex_a53_event_table + PMC_EVENT_TABLE_SIZE(cortex_a53); 4435283112Sbr break; 4436283112Sbr case PMC_CPU_ARMV8_CORTEX_A57: 4437283112Sbr ev = cortex_a57_event_table; 4438283112Sbr evfence = cortex_a57_event_table + PMC_EVENT_TABLE_SIZE(cortex_a57); 4439283112Sbr break; 4440283112Sbr default: /* Unknown CPU type. */ 4441283112Sbr break; 4442283112Sbr } 4443204635Sgnn } else if (pe >= PMC_EV_MIPS24K_FIRST && pe <= PMC_EV_MIPS24K_LAST) { 4444204635Sgnn ev = mips24k_event_table; 4445233628Sfabient evfence = mips24k_event_table + PMC_EVENT_TABLE_SIZE(mips24k); 4446281098Sadrian } else if (pe >= PMC_EV_MIPS74K_FIRST && pe <= PMC_EV_MIPS74K_LAST) { 4447281098Sadrian ev = mips74k_event_table; 4448281098Sadrian evfence = mips74k_event_table + PMC_EVENT_TABLE_SIZE(mips74k); 4449233335Sgonzo } else if (pe >= PMC_EV_OCTEON_FIRST && pe <= PMC_EV_OCTEON_LAST) { 4450233335Sgonzo ev = octeon_event_table; 4451233335Sgonzo evfence = octeon_event_table + PMC_EVENT_TABLE_SIZE(octeon); 4452228869Sjhibbits } else if (pe >= PMC_EV_PPC7450_FIRST && pe <= PMC_EV_PPC7450_LAST) { 4453228869Sjhibbits ev = ppc7450_event_table; 4454233628Sfabient evfence = ppc7450_event_table + PMC_EVENT_TABLE_SIZE(ppc7450); 4455261342Sjhibbits } else if (pe >= PMC_EV_PPC970_FIRST && pe <= PMC_EV_PPC970_LAST) { 4456261342Sjhibbits ev = ppc970_event_table; 4457261342Sjhibbits evfence = ppc970_event_table + PMC_EVENT_TABLE_SIZE(ppc970); 4458281713Sjhibbits } else if (pe >= PMC_EV_E500_FIRST && pe <= PMC_EV_E500_LAST) { 4459281713Sjhibbits ev = e500_event_table; 4460281713Sjhibbits evfence = e500_event_table + PMC_EVENT_TABLE_SIZE(e500); 4461183725Sjkoshy } else if (pe == PMC_EV_TSC_TSC) { 4462183725Sjkoshy ev = tsc_event_table; 4463183725Sjkoshy evfence = tsc_event_table + PMC_EVENT_TABLE_SIZE(tsc); 4464242622Sdim } else if ((int)pe >= PMC_EV_SOFT_FIRST && (int)pe <= PMC_EV_SOFT_LAST) { 4465233628Sfabient ev = soft_event_table; 4466233628Sfabient evfence = soft_event_table + soft_event_info.pm_nevent; 4467183725Sjkoshy } 4468183725Sjkoshy 4469183725Sjkoshy for (; ev != evfence; ev++) 4470183725Sjkoshy if (pe == ev->pm_ev_code) 4471183725Sjkoshy return (ev->pm_ev_name); 4472183725Sjkoshy 4473185363Sjkoshy return (NULL); 4474185363Sjkoshy} 4475185363Sjkoshy 4476185363Sjkoshyconst char * 4477185363Sjkoshypmc_name_of_event(enum pmc_event pe) 4478185363Sjkoshy{ 4479185363Sjkoshy const char *n; 4480185363Sjkoshy 4481185363Sjkoshy if ((n = _pmc_name_of_event(pe, cpu_info.pm_cputype)) != NULL) 4482185363Sjkoshy return (n); 4483185363Sjkoshy 4484147191Sjkoshy errno = EINVAL; 4485174406Sjkoshy return (NULL); 4486147191Sjkoshy} 4487145256Sjkoshy 4488147191Sjkoshyconst char * 4489147191Sjkoshypmc_name_of_mode(enum pmc_mode pm) 4490147191Sjkoshy{ 4491147191Sjkoshy if ((int) pm >= PMC_MODE_FIRST && 4492147191Sjkoshy pm <= PMC_MODE_LAST) 4493174406Sjkoshy return (pmc_mode_names[pm]); 4494145256Sjkoshy 4495147191Sjkoshy errno = EINVAL; 4496174406Sjkoshy return (NULL); 4497147191Sjkoshy} 4498145256Sjkoshy 4499147191Sjkoshyconst char * 4500147191Sjkoshypmc_name_of_state(enum pmc_state ps) 4501147191Sjkoshy{ 4502147191Sjkoshy if ((int) ps >= PMC_STATE_FIRST && 4503147191Sjkoshy ps <= PMC_STATE_LAST) 4504174406Sjkoshy return (pmc_state_names[ps]); 4505145256Sjkoshy 4506147191Sjkoshy errno = EINVAL; 4507174406Sjkoshy return (NULL); 4508145256Sjkoshy} 4509145256Sjkoshy 4510145256Sjkoshyint 4511147191Sjkoshypmc_ncpu(void) 4512145256Sjkoshy{ 4513147191Sjkoshy if (pmc_syscall == -1) { 4514147191Sjkoshy errno = ENXIO; 4515174406Sjkoshy return (-1); 4516147191Sjkoshy } 4517145256Sjkoshy 4518174406Sjkoshy return (cpu_info.pm_ncpu); 4519145256Sjkoshy} 4520145256Sjkoshy 4521145256Sjkoshyint 4522147191Sjkoshypmc_npmc(int cpu) 4523145256Sjkoshy{ 4524147191Sjkoshy if (pmc_syscall == -1) { 4525147191Sjkoshy errno = ENXIO; 4526174406Sjkoshy return (-1); 4527147191Sjkoshy } 4528145256Sjkoshy 4529147191Sjkoshy if (cpu < 0 || cpu >= (int) cpu_info.pm_ncpu) { 4530147191Sjkoshy errno = EINVAL; 4531174406Sjkoshy return (-1); 4532147191Sjkoshy } 4533145256Sjkoshy 4534174406Sjkoshy return (cpu_info.pm_npmc); 4535145256Sjkoshy} 4536145256Sjkoshy 4537145256Sjkoshyint 4538147191Sjkoshypmc_pmcinfo(int cpu, struct pmc_pmcinfo **ppmci) 4539145256Sjkoshy{ 4540147191Sjkoshy int nbytes, npmc; 4541147191Sjkoshy struct pmc_op_getpmcinfo *pmci; 4542145256Sjkoshy 4543147191Sjkoshy if ((npmc = pmc_npmc(cpu)) < 0) 4544174406Sjkoshy return (-1); 4545145256Sjkoshy 4546147191Sjkoshy nbytes = sizeof(struct pmc_op_getpmcinfo) + 4547147191Sjkoshy npmc * sizeof(struct pmc_info); 4548145256Sjkoshy 4549147191Sjkoshy if ((pmci = calloc(1, nbytes)) == NULL) 4550174406Sjkoshy return (-1); 4551145256Sjkoshy 4552147191Sjkoshy pmci->pm_cpu = cpu; 4553145256Sjkoshy 4554147191Sjkoshy if (PMC_CALL(GETPMCINFO, pmci) < 0) { 4555147191Sjkoshy free(pmci); 4556174406Sjkoshy return (-1); 4557147191Sjkoshy } 4558145256Sjkoshy 4559147191Sjkoshy /* kernel<->library, library<->userland interfaces are identical */ 4560147191Sjkoshy *ppmci = (struct pmc_pmcinfo *) pmci; 4561174406Sjkoshy return (0); 4562145256Sjkoshy} 4563145256Sjkoshy 4564145256Sjkoshyint 4565145256Sjkoshypmc_read(pmc_id_t pmc, pmc_value_t *value) 4566145256Sjkoshy{ 4567145256Sjkoshy struct pmc_op_pmcrw pmc_read_op; 4568145256Sjkoshy 4569145256Sjkoshy pmc_read_op.pm_pmcid = pmc; 4570145256Sjkoshy pmc_read_op.pm_flags = PMC_F_OLDVALUE; 4571145256Sjkoshy pmc_read_op.pm_value = -1; 4572145256Sjkoshy 4573145256Sjkoshy if (PMC_CALL(PMCRW, &pmc_read_op) < 0) 4574174406Sjkoshy return (-1); 4575145256Sjkoshy 4576145256Sjkoshy *value = pmc_read_op.pm_value; 4577174406Sjkoshy return (0); 4578145256Sjkoshy} 4579145256Sjkoshy 4580145256Sjkoshyint 4581147191Sjkoshypmc_release(pmc_id_t pmc) 4582145256Sjkoshy{ 4583147191Sjkoshy struct pmc_op_simple pmc_release_args; 4584145256Sjkoshy 4585147191Sjkoshy pmc_release_args.pm_pmcid = pmc; 4586174406Sjkoshy return (PMC_CALL(PMCRELEASE, &pmc_release_args)); 4587145256Sjkoshy} 4588145256Sjkoshy 4589145256Sjkoshyint 4590145256Sjkoshypmc_rw(pmc_id_t pmc, pmc_value_t newvalue, pmc_value_t *oldvaluep) 4591145256Sjkoshy{ 4592145256Sjkoshy struct pmc_op_pmcrw pmc_rw_op; 4593145256Sjkoshy 4594145256Sjkoshy pmc_rw_op.pm_pmcid = pmc; 4595145256Sjkoshy pmc_rw_op.pm_flags = PMC_F_NEWVALUE | PMC_F_OLDVALUE; 4596145256Sjkoshy pmc_rw_op.pm_value = newvalue; 4597145256Sjkoshy 4598145256Sjkoshy if (PMC_CALL(PMCRW, &pmc_rw_op) < 0) 4599174406Sjkoshy return (-1); 4600145256Sjkoshy 4601145256Sjkoshy *oldvaluep = pmc_rw_op.pm_value; 4602174406Sjkoshy return (0); 4603145256Sjkoshy} 4604145256Sjkoshy 4605145256Sjkoshyint 4606145256Sjkoshypmc_set(pmc_id_t pmc, pmc_value_t value) 4607145256Sjkoshy{ 4608145256Sjkoshy struct pmc_op_pmcsetcount sc; 4609145256Sjkoshy 4610145256Sjkoshy sc.pm_pmcid = pmc; 4611145256Sjkoshy sc.pm_count = value; 4612145256Sjkoshy 4613145256Sjkoshy if (PMC_CALL(PMCSETCOUNT, &sc) < 0) 4614174406Sjkoshy return (-1); 4615174406Sjkoshy return (0); 4616145256Sjkoshy} 4617145256Sjkoshy 4618145256Sjkoshyint 4619147191Sjkoshypmc_start(pmc_id_t pmc) 4620145256Sjkoshy{ 4621147191Sjkoshy struct pmc_op_simple pmc_start_args; 4622145256Sjkoshy 4623147191Sjkoshy pmc_start_args.pm_pmcid = pmc; 4624174406Sjkoshy return (PMC_CALL(PMCSTART, &pmc_start_args)); 4625145256Sjkoshy} 4626145256Sjkoshy 4627145256Sjkoshyint 4628147191Sjkoshypmc_stop(pmc_id_t pmc) 4629145256Sjkoshy{ 4630147191Sjkoshy struct pmc_op_simple pmc_stop_args; 4631145256Sjkoshy 4632147191Sjkoshy pmc_stop_args.pm_pmcid = pmc; 4633174406Sjkoshy return (PMC_CALL(PMCSTOP, &pmc_stop_args)); 4634145256Sjkoshy} 4635145256Sjkoshy 4636145256Sjkoshyint 4637145774Sjkoshypmc_width(pmc_id_t pmcid, uint32_t *width) 4638145774Sjkoshy{ 4639145774Sjkoshy unsigned int i; 4640145774Sjkoshy enum pmc_class cl; 4641145774Sjkoshy 4642145774Sjkoshy cl = PMC_ID_TO_CLASS(pmcid); 4643145774Sjkoshy for (i = 0; i < cpu_info.pm_nclass; i++) 4644145774Sjkoshy if (cpu_info.pm_classes[i].pm_class == cl) { 4645145774Sjkoshy *width = cpu_info.pm_classes[i].pm_width; 4646174406Sjkoshy return (0); 4647145774Sjkoshy } 4648177107Sjkoshy errno = EINVAL; 4649177107Sjkoshy return (-1); 4650145774Sjkoshy} 4651145774Sjkoshy 4652145774Sjkoshyint 4653147191Sjkoshypmc_write(pmc_id_t pmc, pmc_value_t value) 4654145774Sjkoshy{ 4655147191Sjkoshy struct pmc_op_pmcrw pmc_write_op; 4656145774Sjkoshy 4657147191Sjkoshy pmc_write_op.pm_pmcid = pmc; 4658147191Sjkoshy pmc_write_op.pm_flags = PMC_F_NEWVALUE; 4659147191Sjkoshy pmc_write_op.pm_value = value; 4660174406Sjkoshy return (PMC_CALL(PMCRW, &pmc_write_op)); 4661145256Sjkoshy} 4662145256Sjkoshy 4663145256Sjkoshyint 4664147191Sjkoshypmc_writelog(uint32_t userdata) 4665145256Sjkoshy{ 4666147191Sjkoshy struct pmc_op_writelog wl; 4667145256Sjkoshy 4668147191Sjkoshy wl.pm_userdata = userdata; 4669174406Sjkoshy return (PMC_CALL(WRITELOG, &wl)); 4670145256Sjkoshy} 4671