diff options
Diffstat (limited to 'gprofng/common/hwcdrv.h')
-rw-r--r-- | gprofng/common/hwcdrv.h | 330 |
1 files changed, 330 insertions, 0 deletions
diff --git a/gprofng/common/hwcdrv.h b/gprofng/common/hwcdrv.h new file mode 100644 index 0000000..14c55cf --- /dev/null +++ b/gprofng/common/hwcdrv.h @@ -0,0 +1,330 @@ +/* Copyright (C) 2021 Free Software Foundation, Inc. + Contributed by Oracle. + + This file is part of GNU Binutils. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +/* Hardware counter profiling driver's header */ + +#ifndef __HWCDRV_H +#define __HWCDRV_H + +#include "hwcfuncs.h" + +#ifdef linux +#define HWCFUNCS_SIGNAL SIGIO +#define HWCFUNCS_SIGNAL_STRING "SIGIO" +#else +#define HWCFUNCS_SIGNAL SIGEMT +#define HWCFUNCS_SIGNAL_STRING "SIGEMT" +#endif + +#ifndef LIBCOLLECTOR_SRC /* not running in libcollector */ +#include <string.h> + +#else /* running in libcollector */ +#include "collector_module.h" +#include "libcol_util.h" + +#define get_hwcdrv __collector_get_hwcdrv +#define hwcdrv_drivers __collector_hwcdrv_drivers +#define hwcdrv_cpc1_api __collector_hwcdrv_cpc1_api +#define hwcdrv_cpc2_api __collector_hwcdrv_cpc2_api +#define hwcdrv_default __collector_hwcdrv_default +#define hwcdrv_driver __collector_hwcdrv_driver +#define hwcdrv_init __collector_hwcdrv_init +#define hwcdrv_get_info __collector_hwcdrv_get_info +#define hwcdrv_enable_mt __collector_hwcdrv_enable_mt +#define hwcdrv_get_descriptions __collector_hwcdrv_get_descriptions +#define hwcdrv_assign_regnos __collector_hwcdrv_assign_regnos +#define hwcdrv_create_counters __collector_hwcdrv_create_counters +#define hwcdrv_start __collector_hwcdrv_start +#define hwcdrv_overflow __collector_hwcdrv_overflow +#define hwcdrv_read_events __collector_hwcdrv_read_events +#define hwcdrv_sighlr_restart __collector_hwcdrv_sighlr_restart +#define hwcdrv_lwp_suspend __collector_hwcdrv_lwp_suspend +#define hwcdrv_lwp_resume __collector_hwcdrv_lwp_resume +#define hwcdrv_free_counters __collector_hwcdrv_free_counters +#define hwcdrv_lwp_init __collector_hwcdrv_lwp_init +#define hwcdrv_lwp_fini __collector_hwcdrv_lwp_fini +#define hwcdrv_assign_all_regnos __collector_hwcdrv_assign_all_regnos +#define hwcdrv_lookup_cpuver __collector_hwcdrv_lookup_cpuver +#define hwcfuncs_int_capture_errmsg __collector_hwcfuncs_int_capture_errmsg + +#define GTXT(x) x + +/* Implemented by libcollector */ +#define calloc __collector_calloc +#define close CALL_UTIL(close) +#define fcntl CALL_UTIL(fcntl) +#define fprintf CALL_UTIL(fprintf) +//#define free __collector_free +#define free(...) +#define gethrtime __collector_gethrtime +#define ioctl CALL_UTIL(ioctl) +#define malloc __collector_malloc +#define memcpy __collector_memcpy +#define memset CALL_UTIL(memset) +#define mmap CALL_UTIL(mmap) +#define snprintf CALL_UTIL(snprintf) +#define strchr CALL_UTIL(strchr) +#define strcmp CALL_UTIL(strcmp) +#define strncmp CALL_UTIL(strncmp) +#define strcpy CALL_UTIL(strcpy) +#define strdup __collector_strdup +#define strncpy CALL_UTIL(strncpy) +#define strerror CALL_UTIL(strerror) +#define strlen CALL_UTIL(strlen) +#define strstr CALL_UTIL(strstr) +#define strtol CALL_UTIL(strtol) +#define strtoll CALL_UTIL(strtoll) +#define strtoul CALL_UTIL(strtoul) +#define strtoull CALL_UTIL(strtoull) +#define syscall CALL_UTIL(syscall) +#define sysconf CALL_UTIL(sysconf) +#define vsnprintf CALL_UTIL(vsnprintf) + +#endif /* --- LIBCOLLECTOR_SRC --- */ + +/* TprintfT(<level>,...) definitions. Adjust per module as needed */ +#define DBG_LT0 0 // for high-level configuration, unexpected errors/warnings +#define DBG_LT1 1 // for configuration details, warnings +#define DBG_LT2 2 +#define DBG_LT3 3 +#define DBG_LT4 4 + +#ifdef __cplusplus +extern "C" +{ +#endif + + /* hwcdrv api */ + typedef struct + { + int (*hwcdrv_init)(hwcfuncs_abort_fn_t abort_ftn, int * tsd_sz); + /* Initialize hwc counter library (do not call again after fork) + Must be called before other functions. + Input: + <abort_ftn>: NULL or callback function to be used for fatal errors + <tsd_sz>: If not NULL, returns size in bytes required for thread-specific storage + Return: 0 if successful + */ + + void (*hwcdrv_get_info)(int *cpuver, const char **cciname, uint_t *npics, + const char **docref, uint64_t *support); + /* get info about session + Input: + <cpuver>: if not NULL, returns value of CPC cpu version + <cciname>: if not NULL, returns name of CPU + <npics>: if not NULL, returns maximum # of HWCs + <docref>: if not NULL, returns documentation reference + <support>: if not NULL, returns bitmask (see hwcfuncs.h) of hwc support + Return: 0 if successful, nonzero otherwise + */ + + int (*hwcdrv_enable_mt)(hwcfuncs_tsd_get_fn_t tsd_ftn); + /* Enables multi-threaded mode (do not need to call again after fork) + Input: + <tsd_ftn>: If <tsd_sz>==0, this parameter is ignored. + Otherwise: + tsd_ftn() must be able to return a pointer to thread-specific + memory of <tsd_sz> bytes. + For a given thread, tsd_ftn() must + always return the same pointer. + Return: none + */ + + int (*hwcdrv_get_descriptions)(hwcf_hwc_cb_t *hwc_find_action, + hwcf_attr_cb_t *attr_find_action); + /* Initiate callbacks with all available HWC names and and HWC attributes. + Input: + <hwc_find_action>: if not NULL, will be called once for each HWC + <attr_find_action>: if not NULL, will be called once for each attribute + Return: 0 if successful + or a cpc return code upon error + */ + + int (*hwcdrv_assign_regnos)(Hwcentry* entries[], unsigned numctrs); + /* Assign entries[]->reg_num values as needed by platform + Input: + <entries>: array of counters + <numctrs>: number of items in <entries> + Return: 0 if successful + HWCFUNCS_ERROR_HWCINIT if resources unavailable + HWCFUNCS_ERROR_HWCARGS if counters were not specified correctly + */ + + int (*hwcdrv_create_counters)(unsigned hwcdef_cnt, Hwcentry *hwcdef); + /* Create the counters, but don't start them. + call this once in main thread to create counters. + Input: + <defcnt>: number of counter definitions. + <hwcdef>: counter definitions. + Return: 0 if successful + or a cpc return code upon error + */ + + int (*hwcdrv_start)(void); + /* Start the counters. + call this once in main thread to start counters. + Return: 0 if successful + or a cpc return code upon error + */ + + int (*hwcdrv_overflow)(siginfo_t *si, hwc_event_t *sample, + hwc_event_t *lost_samples); + /* Linux only. Capture current counter values. + This is intended to be called from SIGEMT handler; + Input: + <si>: signal handler context information + <sample>: returns non-zero values for counters that overflowed + <lost_samples>: returns non-zero values for counters that "lost" counts + Return: 0 if successful + or a cpc return code upon error. + */ + + int (*hwcdrv_read_events)(hwc_event_t *overflow_data, + hwc_event_samples_t *sampled_data); + /* Read current counter values and samples. Read of samples is destructive. + Note: hwcdrv_read_events is not supported on Linux. + <overflow_data>: returns snapshot of counter values + <sampled_data>: returns sampled data + Return: 0 if successful + HWCFUNCS_ERROR_UNAVAIL if resource unavailable(e.g. called before initted) + (other values may be possible) + */ + + int (*hwcdrv_sighlr_restart)(const hwc_event_t* startVals); + /* Restarts the counters at the given value. + This is intended to be called from SIGEMT handler; + Input: + <startVals>: Solaris: new start values. + Linux: pointer may be NULL; startVals is ignored. + Return: 0 if successful + or a cpc return code upon error. + */ + + int (*hwcdrv_lwp_suspend)(void); + /* Attempt to stop counters on this lwp only. + hwcdrv_lwp_resume() should be used to restart counters. + Return: 0 if successful + or a cpc return code upon error. + */ + + int (*hwcdrv_lwp_resume)(void); + /* Attempt to restart counters on this lwp when counters were + stopped with hwcdrv_lwp_suspend(). + Return: 0 if successful + or a cpc return code upon error. + */ + + int (*hwcdrv_free_counters)(void); + /* Stops counters on this lwp only and frees resources. + This will fail w/ unpredictable results if other lwps's are + still running. After this call returns, + hwcdrv_create_counters() may be called with new values. + Return: 0 if successful + or a cpc return code upon error. + */ + + int (*hwcdrv_lwp_init)(void); + /* per-thread counter init. + Solaris: nop. + Linux: just after thread creation call this from inside thread + to create context and start counters. + Return: 0 if successful + or a perfctr return code upon error + */ + + void (*hwcdrv_lwp_fini)(void); + /* per-thread counter cleanup. + Solaris: nop. + Linux: call in each thread upon thread destruction. + */ + + int hwcdrv_init_status; + } hwcdrv_api_t; + + extern hwcdrv_api_t *get_hwcdrv (); + extern hwcdrv_api_t *__collector_get_hwcdrv (); + extern int __collector_hwcfuncs_bind_descriptor (const char *defstring); + extern Hwcentry **__collector_hwcfuncs_get_ctrs (unsigned *defcnt); + extern hwcdrv_api_t *hwcdrv_drivers[]; // array of available drivers + + /* prototypes for internal use by hwcdrv drivers */ + typedef struct + { // see hwcdrv_get_info() for field definitions + int cpcN_cpuver; + uint_t cpcN_npics; + const char *cpcN_docref; + const char *cpcN_cciname; + } hwcdrv_about_t; + + extern int hwcdrv_assign_all_regnos (Hwcentry* entries[], unsigned numctrs); + /* assign user's counters to specific CPU registers */ + + extern int hwcdrv_lookup_cpuver (const char * cpcN_cciname); + /* returns hwc_cpus.h ID for a given string. */ + + extern void hwcfuncs_int_capture_errmsg (const char *fn, int subcode, + const char *fmt, va_list ap); +#define logerr hwcfuncs_int_logerr + + /*---------------------------------------------------------------------------*/ + /* prototypes for internal use by linux hwcdrv drivers */ +#define PERFCTR_FIXED_MAGIC 0x40000000 /* tells perfctr to use intel fixed pmcs */ +#define PERFCTR_UMASK_SHIFT 8 +#define EXTENDED_EVNUM_2_EVSEL(evnum) \ + ( (((eventsel_t)(evnum) & 0x0f00ULL) << 24) | ((eventsel_t)(evnum) & ~0x0f00ULL) ) + + typedef uint64_t eventsel_t; + extern int hwcfuncs_get_x86_eventsel (unsigned int regno, const char *int_name, + eventsel_t *return_event, uint_t *return_pmc_sel); + + typedef int (hwcdrv_get_events_fn_t) (hwcf_hwc_cb_t *hwc_cb); + typedef int (hwcdrv_get_eventnum_fn_t) (const char *eventname, uint_t pmc, + eventsel_t *eventnum, + eventsel_t *valid_umask, uint_t *pmc_sel); + extern hwcdrv_get_eventnum_fn_t *hwcdrv_get_x86_eventnum; + + typedef struct + { + const char * attrname; // user-visible name of attribute + int is_inverted; // nonzero means boolean attribute is inverted + eventsel_t mask; // which attribute bits can be set? + eventsel_t shift; // how far to shift bits for use in x86 register + } attr_info_t; + extern const attr_info_t *perfctr_attrs_table; + + /* hdrv_pcbe api: cpu-specific drivers for Linux */ + typedef struct + { + int (*hdrv_pcbe_init)(void); + uint_t (*hdrv_pcbe_ncounters)(void); + const char *(*hdrv_pcbe_impl_name)(void); + const char *(*hdrv_pcbe_cpuref)(void); + int (*hdrv_pcbe_get_events)(hwcf_hwc_cb_t *hwc_cb); + int (*hdrv_pcbe_get_eventnum)(const char * eventname, uint_t pmc, + eventsel_t *eventnum, eventsel_t *valid_umask, + uint_t *pmc_sel); + } hdrv_pcbe_api_t; + +#ifdef __cplusplus +} +#endif + +#endif |