blob: f711990b4b6f84beefc47d25bdb12b062a9707b2 [file] [log] [blame]
/* Copyright (C) 2021-2023 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
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
#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"
/* 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.
<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
<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)
<tsd_ftn>: If <tsd_sz>==0, this parameter is ignored.
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.
<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
<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.
<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;
<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;
<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 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