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 driver's header */ 22*c42dbd0eSchristos 23*c42dbd0eSchristos #ifndef __HWCDRV_H 24*c42dbd0eSchristos #define __HWCDRV_H 25*c42dbd0eSchristos 26*c42dbd0eSchristos #include "hwcfuncs.h" 27*c42dbd0eSchristos 28*c42dbd0eSchristos #ifdef linux 29*c42dbd0eSchristos #define HWCFUNCS_SIGNAL SIGIO 30*c42dbd0eSchristos #define HWCFUNCS_SIGNAL_STRING "SIGIO" 31*c42dbd0eSchristos #else 32*c42dbd0eSchristos #define HWCFUNCS_SIGNAL SIGEMT 33*c42dbd0eSchristos #define HWCFUNCS_SIGNAL_STRING "SIGEMT" 34*c42dbd0eSchristos #endif 35*c42dbd0eSchristos 36*c42dbd0eSchristos #ifndef LIBCOLLECTOR_SRC /* not running in libcollector */ 37*c42dbd0eSchristos #include <string.h> 38*c42dbd0eSchristos 39*c42dbd0eSchristos #else /* running in libcollector */ 40*c42dbd0eSchristos #include "collector_module.h" 41*c42dbd0eSchristos #include "libcol_util.h" 42*c42dbd0eSchristos 43*c42dbd0eSchristos #define get_hwcdrv __collector_get_hwcdrv 44*c42dbd0eSchristos #define hwcdrv_drivers __collector_hwcdrv_drivers 45*c42dbd0eSchristos #define hwcdrv_cpc1_api __collector_hwcdrv_cpc1_api 46*c42dbd0eSchristos #define hwcdrv_cpc2_api __collector_hwcdrv_cpc2_api 47*c42dbd0eSchristos #define hwcdrv_default __collector_hwcdrv_default 48*c42dbd0eSchristos #define hwcdrv_driver __collector_hwcdrv_driver 49*c42dbd0eSchristos #define hwcdrv_init __collector_hwcdrv_init 50*c42dbd0eSchristos #define hwcdrv_get_info __collector_hwcdrv_get_info 51*c42dbd0eSchristos #define hwcdrv_enable_mt __collector_hwcdrv_enable_mt 52*c42dbd0eSchristos #define hwcdrv_get_descriptions __collector_hwcdrv_get_descriptions 53*c42dbd0eSchristos #define hwcdrv_assign_regnos __collector_hwcdrv_assign_regnos 54*c42dbd0eSchristos #define hwcdrv_create_counters __collector_hwcdrv_create_counters 55*c42dbd0eSchristos #define hwcdrv_start __collector_hwcdrv_start 56*c42dbd0eSchristos #define hwcdrv_overflow __collector_hwcdrv_overflow 57*c42dbd0eSchristos #define hwcdrv_read_events __collector_hwcdrv_read_events 58*c42dbd0eSchristos #define hwcdrv_sighlr_restart __collector_hwcdrv_sighlr_restart 59*c42dbd0eSchristos #define hwcdrv_lwp_suspend __collector_hwcdrv_lwp_suspend 60*c42dbd0eSchristos #define hwcdrv_lwp_resume __collector_hwcdrv_lwp_resume 61*c42dbd0eSchristos #define hwcdrv_free_counters __collector_hwcdrv_free_counters 62*c42dbd0eSchristos #define hwcdrv_lwp_init __collector_hwcdrv_lwp_init 63*c42dbd0eSchristos #define hwcdrv_lwp_fini __collector_hwcdrv_lwp_fini 64*c42dbd0eSchristos #define hwcdrv_assign_all_regnos __collector_hwcdrv_assign_all_regnos 65*c42dbd0eSchristos #define hwcdrv_lookup_cpuver __collector_hwcdrv_lookup_cpuver 66*c42dbd0eSchristos #define hwcfuncs_int_capture_errmsg __collector_hwcfuncs_int_capture_errmsg 67*c42dbd0eSchristos 68*c42dbd0eSchristos #define GTXT(x) x 69*c42dbd0eSchristos 70*c42dbd0eSchristos /* Implemented by libcollector */ 71*c42dbd0eSchristos #define calloc __collector_calloc 72*c42dbd0eSchristos #define close CALL_UTIL(close) 73*c42dbd0eSchristos #define fcntl CALL_UTIL(fcntl) 74*c42dbd0eSchristos #define fprintf CALL_UTIL(fprintf) 75*c42dbd0eSchristos //#define free __collector_free 76*c42dbd0eSchristos #define free(...) 77*c42dbd0eSchristos #define gethrtime __collector_gethrtime 78*c42dbd0eSchristos #define ioctl CALL_UTIL(ioctl) 79*c42dbd0eSchristos #define malloc __collector_malloc 80*c42dbd0eSchristos #define memcpy __collector_memcpy 81*c42dbd0eSchristos #define memset CALL_UTIL(memset) 82*c42dbd0eSchristos #define mmap CALL_UTIL(mmap) 83*c42dbd0eSchristos #define snprintf CALL_UTIL(snprintf) 84*c42dbd0eSchristos #define strchr CALL_UTIL(strchr) 85*c42dbd0eSchristos #define strcmp CALL_UTIL(strcmp) 86*c42dbd0eSchristos #define strncmp CALL_UTIL(strncmp) 87*c42dbd0eSchristos #define strcpy CALL_UTIL(strcpy) 88*c42dbd0eSchristos #define strdup __collector_strdup 89*c42dbd0eSchristos #define strncpy CALL_UTIL(strncpy) 90*c42dbd0eSchristos #define strerror CALL_UTIL(strerror) 91*c42dbd0eSchristos #define strlen CALL_UTIL(strlen) 92*c42dbd0eSchristos #define strstr CALL_UTIL(strstr) 93*c42dbd0eSchristos #define strtol CALL_UTIL(strtol) 94*c42dbd0eSchristos #define strtoll CALL_UTIL(strtoll) 95*c42dbd0eSchristos #define strtoul CALL_UTIL(strtoul) 96*c42dbd0eSchristos #define strtoull CALL_UTIL(strtoull) 97*c42dbd0eSchristos #define syscall CALL_UTIL(syscall) 98*c42dbd0eSchristos #define sysconf CALL_UTIL(sysconf) 99*c42dbd0eSchristos #define vsnprintf CALL_UTIL(vsnprintf) 100*c42dbd0eSchristos 101*c42dbd0eSchristos #endif /* --- LIBCOLLECTOR_SRC --- */ 102*c42dbd0eSchristos 103*c42dbd0eSchristos /* TprintfT(<level>,...) definitions. Adjust per module as needed */ 104*c42dbd0eSchristos #define DBG_LT0 0 // for high-level configuration, unexpected errors/warnings 105*c42dbd0eSchristos #define DBG_LT1 1 // for configuration details, warnings 106*c42dbd0eSchristos #define DBG_LT2 2 107*c42dbd0eSchristos #define DBG_LT3 3 108*c42dbd0eSchristos #define DBG_LT4 4 109*c42dbd0eSchristos 110*c42dbd0eSchristos #ifdef __cplusplus 111*c42dbd0eSchristos extern "C" 112*c42dbd0eSchristos { 113*c42dbd0eSchristos #endif 114*c42dbd0eSchristos 115*c42dbd0eSchristos /* hwcdrv api */ 116*c42dbd0eSchristos typedef struct 117*c42dbd0eSchristos { 118*c42dbd0eSchristos int (*hwcdrv_init)(hwcfuncs_abort_fn_t abort_ftn, int * tsd_sz); 119*c42dbd0eSchristos /* Initialize hwc counter library (do not call again after fork) 120*c42dbd0eSchristos Must be called before other functions. 121*c42dbd0eSchristos Input: 122*c42dbd0eSchristos <abort_ftn>: NULL or callback function to be used for fatal errors 123*c42dbd0eSchristos <tsd_sz>: If not NULL, returns size in bytes required for thread-specific storage 124*c42dbd0eSchristos Return: 0 if successful 125*c42dbd0eSchristos */ 126*c42dbd0eSchristos 127*c42dbd0eSchristos void (*hwcdrv_get_info)(int *cpuver, const char **cciname, uint_t *npics, 128*c42dbd0eSchristos const char **docref, uint64_t *support); 129*c42dbd0eSchristos /* get info about session 130*c42dbd0eSchristos Input: 131*c42dbd0eSchristos <cpuver>: if not NULL, returns value of CPC cpu version 132*c42dbd0eSchristos <cciname>: if not NULL, returns name of CPU 133*c42dbd0eSchristos <npics>: if not NULL, returns maximum # of HWCs 134*c42dbd0eSchristos <docref>: if not NULL, returns documentation reference 135*c42dbd0eSchristos <support>: if not NULL, returns bitmask (see hwcfuncs.h) of hwc support 136*c42dbd0eSchristos Return: 0 if successful, nonzero otherwise 137*c42dbd0eSchristos */ 138*c42dbd0eSchristos 139*c42dbd0eSchristos int (*hwcdrv_enable_mt)(hwcfuncs_tsd_get_fn_t tsd_ftn); 140*c42dbd0eSchristos /* Enables multi-threaded mode (do not need to call again after fork) 141*c42dbd0eSchristos Input: 142*c42dbd0eSchristos <tsd_ftn>: If <tsd_sz>==0, this parameter is ignored. 143*c42dbd0eSchristos Otherwise: 144*c42dbd0eSchristos tsd_ftn() must be able to return a pointer to thread-specific 145*c42dbd0eSchristos memory of <tsd_sz> bytes. 146*c42dbd0eSchristos For a given thread, tsd_ftn() must 147*c42dbd0eSchristos always return the same pointer. 148*c42dbd0eSchristos Return: none 149*c42dbd0eSchristos */ 150*c42dbd0eSchristos 151*c42dbd0eSchristos int (*hwcdrv_get_descriptions)(hwcf_hwc_cb_t *hwc_find_action, 152*c42dbd0eSchristos hwcf_attr_cb_t *attr_find_action); 153*c42dbd0eSchristos /* Initiate callbacks with all available HWC names and and HWC attributes. 154*c42dbd0eSchristos Input: 155*c42dbd0eSchristos <hwc_find_action>: if not NULL, will be called once for each HWC 156*c42dbd0eSchristos <attr_find_action>: if not NULL, will be called once for each attribute 157*c42dbd0eSchristos Return: 0 if successful 158*c42dbd0eSchristos or a cpc return code upon error 159*c42dbd0eSchristos */ 160*c42dbd0eSchristos 161*c42dbd0eSchristos int (*hwcdrv_assign_regnos)(Hwcentry* entries[], unsigned numctrs); 162*c42dbd0eSchristos /* Assign entries[]->reg_num values as needed by platform 163*c42dbd0eSchristos Input: 164*c42dbd0eSchristos <entries>: array of counters 165*c42dbd0eSchristos <numctrs>: number of items in <entries> 166*c42dbd0eSchristos Return: 0 if successful 167*c42dbd0eSchristos HWCFUNCS_ERROR_HWCINIT if resources unavailable 168*c42dbd0eSchristos HWCFUNCS_ERROR_HWCARGS if counters were not specified correctly 169*c42dbd0eSchristos */ 170*c42dbd0eSchristos 171*c42dbd0eSchristos int (*hwcdrv_create_counters)(unsigned hwcdef_cnt, Hwcentry *hwcdef); 172*c42dbd0eSchristos /* Create the counters, but don't start them. 173*c42dbd0eSchristos call this once in main thread to create counters. 174*c42dbd0eSchristos Input: 175*c42dbd0eSchristos <defcnt>: number of counter definitions. 176*c42dbd0eSchristos <hwcdef>: counter definitions. 177*c42dbd0eSchristos Return: 0 if successful 178*c42dbd0eSchristos or a cpc return code upon error 179*c42dbd0eSchristos */ 180*c42dbd0eSchristos 181*c42dbd0eSchristos int (*hwcdrv_start)(void); 182*c42dbd0eSchristos /* Start the counters. 183*c42dbd0eSchristos call this once in main thread to start counters. 184*c42dbd0eSchristos Return: 0 if successful 185*c42dbd0eSchristos or a cpc return code upon error 186*c42dbd0eSchristos */ 187*c42dbd0eSchristos 188*c42dbd0eSchristos int (*hwcdrv_overflow)(siginfo_t *si, hwc_event_t *sample, 189*c42dbd0eSchristos hwc_event_t *lost_samples); 190*c42dbd0eSchristos /* Linux only. Capture current counter values. 191*c42dbd0eSchristos This is intended to be called from SIGEMT handler; 192*c42dbd0eSchristos Input: 193*c42dbd0eSchristos <si>: signal handler context information 194*c42dbd0eSchristos <sample>: returns non-zero values for counters that overflowed 195*c42dbd0eSchristos <lost_samples>: returns non-zero values for counters that "lost" counts 196*c42dbd0eSchristos Return: 0 if successful 197*c42dbd0eSchristos or a cpc return code upon error. 198*c42dbd0eSchristos */ 199*c42dbd0eSchristos 200*c42dbd0eSchristos int (*hwcdrv_read_events)(hwc_event_t *overflow_data, 201*c42dbd0eSchristos hwc_event_samples_t *sampled_data); 202*c42dbd0eSchristos /* Read current counter values and samples. Read of samples is destructive. 203*c42dbd0eSchristos Note: hwcdrv_read_events is not supported on Linux. 204*c42dbd0eSchristos <overflow_data>: returns snapshot of counter values 205*c42dbd0eSchristos <sampled_data>: returns sampled data 206*c42dbd0eSchristos Return: 0 if successful 207*c42dbd0eSchristos HWCFUNCS_ERROR_UNAVAIL if resource unavailable(e.g. called before initted) 208*c42dbd0eSchristos (other values may be possible) 209*c42dbd0eSchristos */ 210*c42dbd0eSchristos 211*c42dbd0eSchristos int (*hwcdrv_sighlr_restart)(const hwc_event_t* startVals); 212*c42dbd0eSchristos /* Restarts the counters at the given value. 213*c42dbd0eSchristos This is intended to be called from SIGEMT handler; 214*c42dbd0eSchristos Input: 215*c42dbd0eSchristos <startVals>: Solaris: new start values. 216*c42dbd0eSchristos Linux: pointer may be NULL; startVals is ignored. 217*c42dbd0eSchristos Return: 0 if successful 218*c42dbd0eSchristos or a cpc return code upon error. 219*c42dbd0eSchristos */ 220*c42dbd0eSchristos 221*c42dbd0eSchristos int (*hwcdrv_lwp_suspend)(void); 222*c42dbd0eSchristos /* Attempt to stop counters on this lwp only. 223*c42dbd0eSchristos hwcdrv_lwp_resume() should be used to restart counters. 224*c42dbd0eSchristos Return: 0 if successful 225*c42dbd0eSchristos or a cpc return code upon error. 226*c42dbd0eSchristos */ 227*c42dbd0eSchristos 228*c42dbd0eSchristos int (*hwcdrv_lwp_resume)(void); 229*c42dbd0eSchristos /* Attempt to restart counters on this lwp when counters were 230*c42dbd0eSchristos stopped with hwcdrv_lwp_suspend(). 231*c42dbd0eSchristos Return: 0 if successful 232*c42dbd0eSchristos or a cpc return code upon error. 233*c42dbd0eSchristos */ 234*c42dbd0eSchristos 235*c42dbd0eSchristos int (*hwcdrv_free_counters)(void); 236*c42dbd0eSchristos /* Stops counters on this lwp only and frees resources. 237*c42dbd0eSchristos This will fail w/ unpredictable results if other lwps's are 238*c42dbd0eSchristos still running. After this call returns, 239*c42dbd0eSchristos hwcdrv_create_counters() may be called with new values. 240*c42dbd0eSchristos Return: 0 if successful 241*c42dbd0eSchristos or a cpc return code upon error. 242*c42dbd0eSchristos */ 243*c42dbd0eSchristos 244*c42dbd0eSchristos int (*hwcdrv_lwp_init)(void); 245*c42dbd0eSchristos /* per-thread counter init. 246*c42dbd0eSchristos Solaris: nop. 247*c42dbd0eSchristos Linux: just after thread creation call this from inside thread 248*c42dbd0eSchristos to create context and start counters. 249*c42dbd0eSchristos Return: 0 if successful 250*c42dbd0eSchristos or a perfctr return code upon error 251*c42dbd0eSchristos */ 252*c42dbd0eSchristos 253*c42dbd0eSchristos void (*hwcdrv_lwp_fini)(void); 254*c42dbd0eSchristos /* per-thread counter cleanup. 255*c42dbd0eSchristos Solaris: nop. 256*c42dbd0eSchristos Linux: call in each thread upon thread destruction. 257*c42dbd0eSchristos */ 258*c42dbd0eSchristos 259*c42dbd0eSchristos int hwcdrv_init_status; 260*c42dbd0eSchristos } hwcdrv_api_t; 261*c42dbd0eSchristos 262*c42dbd0eSchristos extern hwcdrv_api_t *get_hwcdrv (); 263*c42dbd0eSchristos extern hwcdrv_api_t *__collector_get_hwcdrv (); 264*c42dbd0eSchristos extern int __collector_hwcfuncs_bind_descriptor (const char *defstring); 265*c42dbd0eSchristos extern Hwcentry **__collector_hwcfuncs_get_ctrs (unsigned *defcnt); 266*c42dbd0eSchristos extern hwcdrv_api_t *hwcdrv_drivers[]; // array of available drivers 267*c42dbd0eSchristos 268*c42dbd0eSchristos /* prototypes for internal use by hwcdrv drivers */ 269*c42dbd0eSchristos typedef struct 270*c42dbd0eSchristos { // see hwcdrv_get_info() for field definitions 271*c42dbd0eSchristos int cpcN_cpuver; 272*c42dbd0eSchristos uint_t cpcN_npics; 273*c42dbd0eSchristos const char *cpcN_docref; 274*c42dbd0eSchristos const char *cpcN_cciname; 275*c42dbd0eSchristos } hwcdrv_about_t; 276*c42dbd0eSchristos 277*c42dbd0eSchristos extern int hwcdrv_assign_all_regnos (Hwcentry* entries[], unsigned numctrs); 278*c42dbd0eSchristos /* assign user's counters to specific CPU registers */ 279*c42dbd0eSchristos 280*c42dbd0eSchristos extern int hwcdrv_lookup_cpuver (const char * cpcN_cciname); 281*c42dbd0eSchristos /* returns hwc_cpus.h ID for a given string. */ 282*c42dbd0eSchristos 283*c42dbd0eSchristos extern void hwcfuncs_int_capture_errmsg (const char *fn, int subcode, 284*c42dbd0eSchristos const char *fmt, va_list ap); 285*c42dbd0eSchristos #define logerr hwcfuncs_int_logerr 286*c42dbd0eSchristos 287*c42dbd0eSchristos /*---------------------------------------------------------------------------*/ 288*c42dbd0eSchristos /* prototypes for internal use by linux hwcdrv drivers */ 289*c42dbd0eSchristos #define PERFCTR_FIXED_MAGIC 0x40000000 /* tells perfctr to use intel fixed pmcs */ 290*c42dbd0eSchristos #define PERFCTR_UMASK_SHIFT 8 291*c42dbd0eSchristos #define EXTENDED_EVNUM_2_EVSEL(evnum) \ 292*c42dbd0eSchristos ( (((eventsel_t)(evnum) & 0x0f00ULL) << 24) | ((eventsel_t)(evnum) & ~0x0f00ULL) ) 293*c42dbd0eSchristos 294*c42dbd0eSchristos typedef uint64_t eventsel_t; 295*c42dbd0eSchristos extern int hwcfuncs_get_x86_eventsel (unsigned int regno, const char *int_name, 296*c42dbd0eSchristos eventsel_t *return_event, uint_t *return_pmc_sel); 297*c42dbd0eSchristos 298*c42dbd0eSchristos typedef int (hwcdrv_get_events_fn_t) (hwcf_hwc_cb_t *hwc_cb); 299*c42dbd0eSchristos typedef int (hwcdrv_get_eventnum_fn_t) (const char *eventname, uint_t pmc, 300*c42dbd0eSchristos eventsel_t *eventnum, 301*c42dbd0eSchristos eventsel_t *valid_umask, uint_t *pmc_sel); 302*c42dbd0eSchristos extern hwcdrv_get_eventnum_fn_t *hwcdrv_get_x86_eventnum; 303*c42dbd0eSchristos 304*c42dbd0eSchristos typedef struct 305*c42dbd0eSchristos { 306*c42dbd0eSchristos const char * attrname; // user-visible name of attribute 307*c42dbd0eSchristos int is_inverted; // nonzero means boolean attribute is inverted 308*c42dbd0eSchristos eventsel_t mask; // which attribute bits can be set? 309*c42dbd0eSchristos eventsel_t shift; // how far to shift bits for use in x86 register 310*c42dbd0eSchristos } attr_info_t; 311*c42dbd0eSchristos extern const attr_info_t *perfctr_attrs_table; 312*c42dbd0eSchristos 313*c42dbd0eSchristos /* hdrv_pcbe api: cpu-specific drivers for Linux */ 314*c42dbd0eSchristos typedef struct 315*c42dbd0eSchristos { 316*c42dbd0eSchristos int (*hdrv_pcbe_init)(void); 317*c42dbd0eSchristos uint_t (*hdrv_pcbe_ncounters)(void); 318*c42dbd0eSchristos const char *(*hdrv_pcbe_impl_name)(void); 319*c42dbd0eSchristos const char *(*hdrv_pcbe_cpuref)(void); 320*c42dbd0eSchristos int (*hdrv_pcbe_get_events)(hwcf_hwc_cb_t *hwc_cb); 321*c42dbd0eSchristos int (*hdrv_pcbe_get_eventnum)(const char * eventname, uint_t pmc, 322*c42dbd0eSchristos eventsel_t *eventnum, eventsel_t *valid_umask, 323*c42dbd0eSchristos uint_t *pmc_sel); 324*c42dbd0eSchristos } hdrv_pcbe_api_t; 325*c42dbd0eSchristos 326*c42dbd0eSchristos #ifdef __cplusplus 327*c42dbd0eSchristos } 328*c42dbd0eSchristos #endif 329*c42dbd0eSchristos 330*c42dbd0eSchristos #endif 331