1*c42dbd0eSchristos /* Copyright (C) 2021 Free Software Foundation, Inc. 2*c42dbd0eSchristos Contributed by Oracle. 3*c42dbd0eSchristos 4*c42dbd0eSchristos This file is part of GNU Binutils. 5*c42dbd0eSchristos 6*c42dbd0eSchristos This program is free software; you can redistribute it and/or modify 7*c42dbd0eSchristos it under the terms of the GNU General Public License as published by 8*c42dbd0eSchristos the Free Software Foundation; either version 3, or (at your option) 9*c42dbd0eSchristos any later version. 10*c42dbd0eSchristos 11*c42dbd0eSchristos This program is distributed in the hope that it will be useful, 12*c42dbd0eSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of 13*c42dbd0eSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*c42dbd0eSchristos GNU General Public License for more details. 15*c42dbd0eSchristos 16*c42dbd0eSchristos You should have received a copy of the GNU General Public License 17*c42dbd0eSchristos along with this program; if not, write to the Free Software 18*c42dbd0eSchristos Foundation, 51 Franklin Street - Fifth Floor, Boston, 19*c42dbd0eSchristos MA 02110-1301, USA. */ 20*c42dbd0eSchristos 21*c42dbd0eSchristos /* Hardware counter profiling */ 22*c42dbd0eSchristos 23*c42dbd0eSchristos #ifndef __HWCFUNCS_H 24*c42dbd0eSchristos #define __HWCFUNCS_H 25*c42dbd0eSchristos 26*c42dbd0eSchristos #ifdef LIBCOLLECTOR_SRC /* running in libcollector */ 27*c42dbd0eSchristos #define hwcfuncs_int_logerr __collector_hwcfuncs_int_logerr 28*c42dbd0eSchristos #define hwcfuncs_parse_ctr __collector_hwcfuncs_parse_ctr 29*c42dbd0eSchristos #define hwcfuncs_parse_attrs __collector_hwcfuncs_parse_attrs 30*c42dbd0eSchristos #define hwcfuncs_bind_descriptor __collector_hwcfuncs_bind_descriptor 31*c42dbd0eSchristos #define hwcfuncs_bind_hwcentry __collector_hwcfuncs_bind_hwcentry 32*c42dbd0eSchristos #define hwcfuncs_assign_regnos __collector_hwcfuncs_assign_regnos 33*c42dbd0eSchristos #define regno_is_valid __collector_regno_is_valid 34*c42dbd0eSchristos #define hwcfuncs_get_ctrs __collector_hwcfuncs_get_ctrs 35*c42dbd0eSchristos #define hwcfuncs_errmsg_get __collector_hwcfuncs_errmsg_get 36*c42dbd0eSchristos #endif /* --- LIBCOLLECTOR_SRC --- */ 37*c42dbd0eSchristos 38*c42dbd0eSchristos #include <signal.h> /* siginfo_t */ 39*c42dbd0eSchristos #include <limits.h> /* UINT64_t */ 40*c42dbd0eSchristos #include <sys/types.h> 41*c42dbd0eSchristos #include <stdint.h> 42*c42dbd0eSchristos 43*c42dbd0eSchristos #include "hwcentry.h" /* for Hwcentry type */ 44*c42dbd0eSchristos #include "gp-time.h" 45*c42dbd0eSchristos 46*c42dbd0eSchristos typedef unsigned int uint_t; 47*c42dbd0eSchristos 48*c42dbd0eSchristos #ifdef __cplusplus 49*c42dbd0eSchristos extern "C" { 50*c42dbd0eSchristos #endif 51*c42dbd0eSchristos 52*c42dbd0eSchristos /*---------------------------------------------------------------------------*/ 53*c42dbd0eSchristos /* compile options */ 54*c42dbd0eSchristos 55*c42dbd0eSchristos #define HWC_DEBUG 0 /* 0/1 to enable extra HWC debug */ 56*c42dbd0eSchristos 57*c42dbd0eSchristos /*---------------------------------------------------------------------------*/ 58*c42dbd0eSchristos /* typedefs */ 59*c42dbd0eSchristos /* generic hw event */ 60*c42dbd0eSchristos typedef struct _hwc_event_t 61*c42dbd0eSchristos { /* generalized counter event */ 62*c42dbd0eSchristos hrtime_t ce_hrt; /* gethrtime() */ 63*c42dbd0eSchristos uint64_t ce_pic[MAX_PICS]; /* counter samples or start values */ 64*c42dbd0eSchristos } hwc_event_t; 65*c42dbd0eSchristos 66*c42dbd0eSchristos /* supplementary data that accompanies some hw events */ 67*c42dbd0eSchristos typedef struct 68*c42dbd0eSchristos { /* supplementary data fields */ 69*c42dbd0eSchristos uint64_t smpl_pc; /* pc related to event */ 70*c42dbd0eSchristos uint64_t smpl_data_source; /* chip-specific data source encoding */ 71*c42dbd0eSchristos uint64_t smpl_latency; /* latency related to event */ 72*c42dbd0eSchristos uint64_t smpl_mem_addr; /* memory address related to event */ 73*c42dbd0eSchristos } hwc_sample_t; 74*c42dbd0eSchristos #define HWCFUNCS_INVALID_U64 0xFEEDBEEFDEADBEEFllu /* identifies fields as unused */ 75*c42dbd0eSchristos 76*c42dbd0eSchristos typedef struct { /* supplementary data fields */ 77*c42dbd0eSchristos hwc_sample_t sample[MAX_PICS]; /* counter samples or start values */ 78*c42dbd0eSchristos } hwc_event_samples_t; 79*c42dbd0eSchristos 80*c42dbd0eSchristos #define HWCFUNCS_SAMPLE_RESET(sample) \ 81*c42dbd0eSchristos do { \ 82*c42dbd0eSchristos (sample)->smpl_pc =HWCFUNCS_INVALID_U64; \ 83*c42dbd0eSchristos (sample)->smpl_data_source =HWCFUNCS_INVALID_U64; \ 84*c42dbd0eSchristos (sample)->smpl_latency =HWCFUNCS_INVALID_U64; \ 85*c42dbd0eSchristos (sample)->smpl_mem_addr =HWCFUNCS_INVALID_U64; \ 86*c42dbd0eSchristos } while(0) 87*c42dbd0eSchristos 88*c42dbd0eSchristos #define HWCFUNCS_SAMPLE_IS_RESET(sample) \ 89*c42dbd0eSchristos ( \ 90*c42dbd0eSchristos (sample)->smpl_pc ==HWCFUNCS_INVALID_U64 && \ 91*c42dbd0eSchristos (sample)->smpl_data_source==HWCFUNCS_INVALID_U64 && \ 92*c42dbd0eSchristos (sample)->smpl_latency ==HWCFUNCS_INVALID_U64 && \ 93*c42dbd0eSchristos (sample)->smpl_mem_addr ==HWCFUNCS_INVALID_U64 \ 94*c42dbd0eSchristos ) 95*c42dbd0eSchristos 96*c42dbd0eSchristos /*---------------------------------------------------------------------------*/ 97*c42dbd0eSchristos /* macros */ 98*c42dbd0eSchristos 99*c42dbd0eSchristos #define HW_INTERVAL_MAX UINT64_MAX 100*c42dbd0eSchristos #define HW_INTERVAL_PRESET(x) (HW_INTERVAL_MAX - ((uint64_t)(x) - 1)) 101*c42dbd0eSchristos #define HW_INTERVAL_TYPE(x) ((uint64_t) (x) 102*c42dbd0eSchristos 103*c42dbd0eSchristos /* parsing */ 104*c42dbd0eSchristos #define HWCFUNCS_MAX_ATTRS 20 105*c42dbd0eSchristos #define HWCFUNCS_PARSE_ATTR '~' 106*c42dbd0eSchristos #define HWCFUNCS_PARSE_EQUAL '=' 107*c42dbd0eSchristos #define HWCFUNCS_PARSE_BACKTRACK '+' 108*c42dbd0eSchristos #define HWCFUNCS_PARSE_BACKTRACK_OFF '-' 109*c42dbd0eSchristos #define HWCFUNCS_PARSE_REGNUM '/' 110*c42dbd0eSchristos #define HWCFUNCS_PARSE_VALUE ',' 111*c42dbd0eSchristos 112*c42dbd0eSchristos /* error codes */ 113*c42dbd0eSchristos #define HWCFUNCS_ERROR_GENERIC (-1) 114*c42dbd0eSchristos #define HWCFUNCS_ERROR_NOT_SUPPORTED (-2) 115*c42dbd0eSchristos #define HWCFUNCS_ERROR_ALREADY_CALLED (-3) 116*c42dbd0eSchristos #define HWCFUNCS_ERROR_HWCINIT (-4) 117*c42dbd0eSchristos #define HWCFUNCS_ERROR_HWCARGS (-5) 118*c42dbd0eSchristos #define HWCFUNCS_ERROR_MEMORY (-6) 119*c42dbd0eSchristos #define HWCFUNCS_ERROR_UNAVAIL (-7) 120*c42dbd0eSchristos #define HWCFUNCS_ERROR_ERRNO_ZERO (-8) 121*c42dbd0eSchristos #define HWCFUNCS_ERROR_UNEXPECTED (-99) 122*c42dbd0eSchristos 123*c42dbd0eSchristos /*---------------------------------------------------------------------------*/ 124*c42dbd0eSchristos /* prototypes */ 125*c42dbd0eSchristos 126*c42dbd0eSchristos typedef void (*hwcfuncs_abort_fn_t) (int errnum, const char *msg); 127*c42dbd0eSchristos 128*c42dbd0eSchristos extern void hwcfuncs_int_logerr(const char *format,...); 129*c42dbd0eSchristos /* Log an error to the internal error buffer. See hwcfuncs_errmsg_get(). 130*c42dbd0eSchristos Note: Not MT-safe; don't even enable logging in an MT environment. 131*c42dbd0eSchristos Recommend using this call only during init. 132*c42dbd0eSchristos Note: when a libcpc call fails, it may automatically call 133*c42dbd0eSchristos cpcN_capture_errmsg() to log the error message in the same internal buffer. 134*c42dbd0eSchristos Recommend using this call only for non-cpc failures. 135*c42dbd0eSchristos */ 136*c42dbd0eSchristos 137*c42dbd0eSchristos #define HWCFUNCS_SUPPORT_OVERFLOW_PROFILING 0x01llu 138*c42dbd0eSchristos #define HWCFUNCS_SUPPORT_PEBS_SAMPLING 0x02llu 139*c42dbd0eSchristos #define HWCFUNCS_SUPPORT_OVERFLOW_CTR_ID 0x04llu // OS identifies which counter overflowed 140*c42dbd0eSchristos /* get info about session 141*c42dbd0eSchristos Input: 142*c42dbd0eSchristos <cpuver>: if not NULL, returns value of CPC cpu version 143*c42dbd0eSchristos <cciname>: if not NULL, returns name of CPU 144*c42dbd0eSchristos <npics>: if not NULL, returns maximum # of HWCs 145*c42dbd0eSchristos <docref>: if not NULL, returns documentation reference 146*c42dbd0eSchristos <support>: if not NULL, returns bitmask (see above) of hwc support 147*c42dbd0eSchristos Return: none 148*c42dbd0eSchristos */ 149*c42dbd0eSchristos 150*c42dbd0eSchristos typedef void* (*hwcfuncs_tsd_get_fn_t) (void); 151*c42dbd0eSchristos typedef void (hwcf_hwc_cb_t) (uint_t cpcregno, const char *name); 152*c42dbd0eSchristos typedef void (hwcf_attr_cb_t) (const char *attr); 153*c42dbd0eSchristos 154*c42dbd0eSchristos extern void 155*c42dbd0eSchristos hwcfuncs_parse_ctr (const char *counter_def, int *pplus, char **pnameOnly, 156*c42dbd0eSchristos char **pattrs, char **pregstr, regno_t *pregno); 157*c42dbd0eSchristos /* Parse a counter definition string (value must already be stripped off). 158*c42dbd0eSchristos Input: 159*c42dbd0eSchristos <counter_def>: input whose format is 160*c42dbd0eSchristos [+|-]<countername>[~attrs...][/<regno>] 161*c42dbd0eSchristos pointers to return values: Any can be NULL. 162*c42dbd0eSchristos Return: 163*c42dbd0eSchristos <plus>: 1 if [+] is found, -1 if [-] is found, 0 otherwise 164*c42dbd0eSchristos <pnameonly>: strdup(<countername>) 165*c42dbd0eSchristos <pattrs>: strdup([~attrs...]) if specified, NULL otherwise. 166*c42dbd0eSchristos <pregstr>: strdup(/<regno>) if specified, NULL otherwise. 167*c42dbd0eSchristos <pregno>: <regno> if readable, REGNO_ANY if not specd, or -2 otherwise. 168*c42dbd0eSchristos */ 169*c42dbd0eSchristos 170*c42dbd0eSchristos typedef struct 171*c42dbd0eSchristos { 172*c42dbd0eSchristos char *ca_name; 173*c42dbd0eSchristos uint64_t ca_val; 174*c42dbd0eSchristos } hwcfuncs_attr_t; /* matches cpc_attr_t */ 175*c42dbd0eSchristos 176*c42dbd0eSchristos void * hwcfuncs_parse_attrs (const char *countername, 177*c42dbd0eSchristos hwcfuncs_attr_t attrs[], unsigned max_attrs, 178*c42dbd0eSchristos uint_t *pnum_attrs, char **errstring); 179*c42dbd0eSchristos /* Extract the attribute fields from <countername>. 180*c42dbd0eSchristos Input: 181*c42dbd0eSchristos <countername>: string whose format is 182*c42dbd0eSchristos [+]<ctrname>[~attributes...][/<regno>][,...] 183*c42dbd0eSchristos <attrs>: array of attributes to be returned 184*c42dbd0eSchristos <max_attrs>: number of elements in <attrs> 185*c42dbd0eSchristos <pnum_attrs>: if not NULL, will return how many attrs were found. 186*c42dbd0eSchristos <errstring>: pointer to a buffer for storing error info, or NULL. 187*c42dbd0eSchristos Return: upon success, a pointer to an allocated copy of <countername>, or 188*c42dbd0eSchristos NULL if there's a failure. (A copy is made in order to provide storage 189*c42dbd0eSchristos for the ca_name fields in the <attrs> array.) 190*c42dbd0eSchristos 191*c42dbd0eSchristos The pointer should be freed when <attrs> is no longer in use. 192*c42dbd0eSchristos <attrs> will be filled in data from countername. 193*c42dbd0eSchristos <pnum_attrs> will have the number of elements in <attrs>. May be 194*c42dbd0eSchristos non-zero even if return value indicates an error. 195*c42dbd0eSchristos <errstring> NULL if no error, otherwise, a malloc'd GTXT string. 196*c42dbd0eSchristos */ 197*c42dbd0eSchristos 198*c42dbd0eSchristos extern int hwcfuncs_bind_descriptor (const char *defstring); 199*c42dbd0eSchristos /* Bind counters to resources. 200*c42dbd0eSchristos Input: 201*c42dbd0eSchristos <defstring>: string whose format is 202*c42dbd0eSchristos :%s:%s:0x%x:%d:%d,0x%x[:%s...repeat for each ctr] 203*c42dbd0eSchristos where the fields are: 204*c42dbd0eSchristos :<userName>:<internalCtr>:<register>:<timeoutVal>:<tag>:<memop> 205*c42dbd0eSchristos Return: 0 if successful 206*c42dbd0eSchristos HWCFUNCS_ERROR_HWCINIT if resources unavailable 207*c42dbd0eSchristos HWCFUNCS_ERROR_HWCARGS if counters were not specified correctly 208*c42dbd0eSchristos */ 209*c42dbd0eSchristos 210*c42dbd0eSchristos extern int hwcfuncs_bind_hwcentry (const Hwcentry *entries[], 211*c42dbd0eSchristos unsigned numctrs); 212*c42dbd0eSchristos /* Bind counters to resources. 213*c42dbd0eSchristos Input: 214*c42dbd0eSchristos <entries>: array of counters 215*c42dbd0eSchristos <numctrs>: number of items in <entries> 216*c42dbd0eSchristos Return: 0 if successful 217*c42dbd0eSchristos HWCFUNCS_ERROR_HWCINIT if resources unavailable 218*c42dbd0eSchristos HWCFUNCS_ERROR_HWCARGS if counters were not specified correctly 219*c42dbd0eSchristos */ 220*c42dbd0eSchristos 221*c42dbd0eSchristos extern int hwcfuncs_assign_regnos (Hwcentry *entries[], unsigned numctrs); 222*c42dbd0eSchristos /* Assign entries[]->reg_num values as needed by platform 223*c42dbd0eSchristos Note: modifies <entries> by supplying a regno to each counter 224*c42dbd0eSchristos Input: 225*c42dbd0eSchristos <entries>: array of counters 226*c42dbd0eSchristos <numctrs>: number of items in <entries> 227*c42dbd0eSchristos Output: 228*c42dbd0eSchristos <entries>: array of counters is modified 229*c42dbd0eSchristos Return: 0 if successful 230*c42dbd0eSchristos HWCFUNCS_ERROR_HWCINIT if resources unavailable 231*c42dbd0eSchristos HWCFUNCS_ERROR_HWCARGS if counters were not specified correctly 232*c42dbd0eSchristos */ 233*c42dbd0eSchristos 234*c42dbd0eSchristos extern int regno_is_valid (const Hwcentry *pctr, regno_t regno); 235*c42dbd0eSchristos /* return 1 if <regno> is in Hwcentry's list 236*c42dbd0eSchristos Input: 237*c42dbd0eSchristos <pctr>: counter definition, reg_list[] should be initialized 238*c42dbd0eSchristos <regno>: register to check 239*c42dbd0eSchristos Return: 1 if <regno> is in Hwcentry's list, 0 otherwise 240*c42dbd0eSchristos */ 241*c42dbd0eSchristos 242*c42dbd0eSchristos extern Hwcentry **hwcfuncs_get_ctrs (unsigned *defcnt); 243*c42dbd0eSchristos /* Get descriptions of the currently bound counters. 244*c42dbd0eSchristos Input: 245*c42dbd0eSchristos <defcnt>: if not NULL, returns number of counter definitions. 246*c42dbd0eSchristos Return: 247*c42dbd0eSchristos table of counter definition pointers 248*c42dbd0eSchristos */ 249*c42dbd0eSchristos 250*c42dbd0eSchristos extern char *hwcfuncs_errmsg_get (char * buf, size_t bufsize, 251*c42dbd0eSchristos int enable_capture); 252*c42dbd0eSchristos /* Gets a recent HWC error message. 253*c42dbd0eSchristos To clear previous error messages and insure error message is enabled, 254*c42dbd0eSchristos call hwcfuncs_errmsg_get(NULL,0,1). 255*c42dbd0eSchristos Once enabled, one error is stored in an internal buffer. A call to this 256*c42dbd0eSchristos function will clear the buffer and allow a new message to be captured. 257*c42dbd0eSchristos Note: Not MT-safe - don't enable this feature in an MT environment. 258*c42dbd0eSchristos Input: 259*c42dbd0eSchristos <buf>: pointer to buffer or NULL. 260*c42dbd0eSchristos <bufsize>: size of <buf> 261*c42dbd0eSchristos <enable_capture>: 0 - disable buffering, 1 - enable buffering. 262*c42dbd0eSchristos Return: error string or an empty string. 263*c42dbd0eSchristos */ 264*c42dbd0eSchristos 265*c42dbd0eSchristos #ifdef __cplusplus 266*c42dbd0eSchristos } 267*c42dbd0eSchristos #endif 268*c42dbd0eSchristos 269*c42dbd0eSchristos #endif /* ! __HWCFUNCS_H */ 270