1*cb63e24eSchristos /* Copyright (C) 2021-2024 Free Software Foundation, Inc. 24f645668Schristos Contributed by Oracle. 34f645668Schristos 44f645668Schristos This file is part of GNU Binutils. 54f645668Schristos 64f645668Schristos This program is free software; you can redistribute it and/or modify 74f645668Schristos it under the terms of the GNU General Public License as published by 84f645668Schristos the Free Software Foundation; either version 3, or (at your option) 94f645668Schristos any later version. 104f645668Schristos 114f645668Schristos This program is distributed in the hope that it will be useful, 124f645668Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 134f645668Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 144f645668Schristos GNU General Public License for more details. 154f645668Schristos 164f645668Schristos You should have received a copy of the GNU General Public License 174f645668Schristos along with this program; if not, write to the Free Software 184f645668Schristos Foundation, 51 Franklin Street - Fifth Floor, Boston, 194f645668Schristos MA 02110-1301, USA. */ 204f645668Schristos 214f645668Schristos /* Hardware counter profiling */ 224f645668Schristos 234f645668Schristos #ifndef __HWCFUNCS_H 244f645668Schristos #define __HWCFUNCS_H 254f645668Schristos 264f645668Schristos #ifdef LIBCOLLECTOR_SRC /* running in libcollector */ 274f645668Schristos #define hwcfuncs_int_logerr __collector_hwcfuncs_int_logerr 284f645668Schristos #define hwcfuncs_parse_ctr __collector_hwcfuncs_parse_ctr 294f645668Schristos #define hwcfuncs_parse_attrs __collector_hwcfuncs_parse_attrs 304f645668Schristos #define hwcfuncs_bind_descriptor __collector_hwcfuncs_bind_descriptor 314f645668Schristos #define hwcfuncs_bind_hwcentry __collector_hwcfuncs_bind_hwcentry 324f645668Schristos #define hwcfuncs_assign_regnos __collector_hwcfuncs_assign_regnos 334f645668Schristos #define regno_is_valid __collector_regno_is_valid 344f645668Schristos #define hwcfuncs_get_ctrs __collector_hwcfuncs_get_ctrs 354f645668Schristos #define hwcfuncs_errmsg_get __collector_hwcfuncs_errmsg_get 364f645668Schristos #endif /* --- LIBCOLLECTOR_SRC --- */ 374f645668Schristos 384f645668Schristos #include <signal.h> /* siginfo_t */ 394f645668Schristos #include <limits.h> /* UINT64_t */ 404f645668Schristos #include <sys/types.h> 414f645668Schristos #include <stdint.h> 424f645668Schristos 434f645668Schristos #include "hwcentry.h" /* for Hwcentry type */ 444f645668Schristos #include "gp-time.h" 454f645668Schristos 464f645668Schristos typedef unsigned int uint_t; 474f645668Schristos 484f645668Schristos #ifdef __cplusplus 494f645668Schristos extern "C" { 504f645668Schristos #endif 514f645668Schristos 524f645668Schristos /*---------------------------------------------------------------------------*/ 534f645668Schristos /* compile options */ 544f645668Schristos 554f645668Schristos #define HWC_DEBUG 0 /* 0/1 to enable extra HWC debug */ 564f645668Schristos 574f645668Schristos /*---------------------------------------------------------------------------*/ 584f645668Schristos /* typedefs */ 594f645668Schristos /* generic hw event */ 604f645668Schristos typedef struct _hwc_event_t 614f645668Schristos { /* generalized counter event */ 624f645668Schristos hrtime_t ce_hrt; /* gethrtime() */ 634f645668Schristos uint64_t ce_pic[MAX_PICS]; /* counter samples or start values */ 644f645668Schristos } hwc_event_t; 654f645668Schristos 664f645668Schristos /* supplementary data that accompanies some hw events */ 674f645668Schristos typedef struct 684f645668Schristos { /* supplementary data fields */ 694f645668Schristos uint64_t smpl_pc; /* pc related to event */ 704f645668Schristos uint64_t smpl_data_source; /* chip-specific data source encoding */ 714f645668Schristos uint64_t smpl_latency; /* latency related to event */ 724f645668Schristos uint64_t smpl_mem_addr; /* memory address related to event */ 734f645668Schristos } hwc_sample_t; 744f645668Schristos #define HWCFUNCS_INVALID_U64 0xFEEDBEEFDEADBEEFllu /* identifies fields as unused */ 754f645668Schristos 764f645668Schristos typedef struct { /* supplementary data fields */ 774f645668Schristos hwc_sample_t sample[MAX_PICS]; /* counter samples or start values */ 784f645668Schristos } hwc_event_samples_t; 794f645668Schristos 804f645668Schristos #define HWCFUNCS_SAMPLE_RESET(sample) \ 814f645668Schristos do { \ 824f645668Schristos (sample)->smpl_pc =HWCFUNCS_INVALID_U64; \ 834f645668Schristos (sample)->smpl_data_source =HWCFUNCS_INVALID_U64; \ 844f645668Schristos (sample)->smpl_latency =HWCFUNCS_INVALID_U64; \ 854f645668Schristos (sample)->smpl_mem_addr =HWCFUNCS_INVALID_U64; \ 864f645668Schristos } while(0) 874f645668Schristos 884f645668Schristos #define HWCFUNCS_SAMPLE_IS_RESET(sample) \ 894f645668Schristos ( \ 904f645668Schristos (sample)->smpl_pc ==HWCFUNCS_INVALID_U64 && \ 914f645668Schristos (sample)->smpl_data_source==HWCFUNCS_INVALID_U64 && \ 924f645668Schristos (sample)->smpl_latency ==HWCFUNCS_INVALID_U64 && \ 934f645668Schristos (sample)->smpl_mem_addr ==HWCFUNCS_INVALID_U64 \ 944f645668Schristos ) 954f645668Schristos 964f645668Schristos /*---------------------------------------------------------------------------*/ 974f645668Schristos /* macros */ 984f645668Schristos 994f645668Schristos #define HW_INTERVAL_MAX UINT64_MAX 1004f645668Schristos #define HW_INTERVAL_PRESET(x) (HW_INTERVAL_MAX - ((uint64_t)(x) - 1)) 1014f645668Schristos #define HW_INTERVAL_TYPE(x) ((uint64_t) (x) 1024f645668Schristos 1034f645668Schristos /* parsing */ 1044f645668Schristos #define HWCFUNCS_MAX_ATTRS 20 1054f645668Schristos #define HWCFUNCS_PARSE_ATTR '~' 1064f645668Schristos #define HWCFUNCS_PARSE_EQUAL '=' 1074f645668Schristos #define HWCFUNCS_PARSE_BACKTRACK '+' 1084f645668Schristos #define HWCFUNCS_PARSE_BACKTRACK_OFF '-' 1094f645668Schristos #define HWCFUNCS_PARSE_REGNUM '/' 1104f645668Schristos #define HWCFUNCS_PARSE_VALUE ',' 1114f645668Schristos 1124f645668Schristos /* error codes */ 1134f645668Schristos #define HWCFUNCS_ERROR_GENERIC (-1) 1144f645668Schristos #define HWCFUNCS_ERROR_NOT_SUPPORTED (-2) 1154f645668Schristos #define HWCFUNCS_ERROR_ALREADY_CALLED (-3) 1164f645668Schristos #define HWCFUNCS_ERROR_HWCINIT (-4) 1174f645668Schristos #define HWCFUNCS_ERROR_HWCARGS (-5) 1184f645668Schristos #define HWCFUNCS_ERROR_MEMORY (-6) 1194f645668Schristos #define HWCFUNCS_ERROR_UNAVAIL (-7) 1204f645668Schristos #define HWCFUNCS_ERROR_ERRNO_ZERO (-8) 1214f645668Schristos #define HWCFUNCS_ERROR_UNEXPECTED (-99) 1224f645668Schristos 1234f645668Schristos /*---------------------------------------------------------------------------*/ 1244f645668Schristos /* prototypes */ 1254f645668Schristos 1264f645668Schristos typedef void (*hwcfuncs_abort_fn_t) (int errnum, const char *msg); 1274f645668Schristos 1284f645668Schristos extern void hwcfuncs_int_logerr(const char *format,...); 1294f645668Schristos /* Log an error to the internal error buffer. See hwcfuncs_errmsg_get(). 1304f645668Schristos Note: Not MT-safe; don't even enable logging in an MT environment. 1314f645668Schristos Recommend using this call only during init. 1324f645668Schristos Note: when a libcpc call fails, it may automatically call 1334f645668Schristos cpcN_capture_errmsg() to log the error message in the same internal buffer. 1344f645668Schristos Recommend using this call only for non-cpc failures. 1354f645668Schristos */ 1364f645668Schristos 1374f645668Schristos #define HWCFUNCS_SUPPORT_OVERFLOW_PROFILING 0x01llu 1384f645668Schristos #define HWCFUNCS_SUPPORT_PEBS_SAMPLING 0x02llu 1394f645668Schristos #define HWCFUNCS_SUPPORT_OVERFLOW_CTR_ID 0x04llu // OS identifies which counter overflowed 1404f645668Schristos /* get info about session 1414f645668Schristos Input: 1424f645668Schristos <cpuver>: if not NULL, returns value of CPC cpu version 1434f645668Schristos <cciname>: if not NULL, returns name of CPU 1444f645668Schristos <npics>: if not NULL, returns maximum # of HWCs 1454f645668Schristos <docref>: if not NULL, returns documentation reference 1464f645668Schristos <support>: if not NULL, returns bitmask (see above) of hwc support 1474f645668Schristos Return: none 1484f645668Schristos */ 1494f645668Schristos 1504f645668Schristos typedef void* (*hwcfuncs_tsd_get_fn_t) (void); 1514f645668Schristos typedef void (hwcf_hwc_cb_t) (uint_t cpcregno, const char *name); 1524f645668Schristos typedef void (hwcf_attr_cb_t) (const char *attr); 1534f645668Schristos 1544f645668Schristos extern void 1554f645668Schristos hwcfuncs_parse_ctr (const char *counter_def, int *pplus, char **pnameOnly, 1564f645668Schristos char **pattrs, char **pregstr, regno_t *pregno); 1574f645668Schristos /* Parse a counter definition string (value must already be stripped off). 1584f645668Schristos Input: 1594f645668Schristos <counter_def>: input whose format is 1604f645668Schristos [+|-]<countername>[~attrs...][/<regno>] 1614f645668Schristos pointers to return values: Any can be NULL. 1624f645668Schristos Return: 1634f645668Schristos <plus>: 1 if [+] is found, -1 if [-] is found, 0 otherwise 1644f645668Schristos <pnameonly>: strdup(<countername>) 1654f645668Schristos <pattrs>: strdup([~attrs...]) if specified, NULL otherwise. 1664f645668Schristos <pregstr>: strdup(/<regno>) if specified, NULL otherwise. 1674f645668Schristos <pregno>: <regno> if readable, REGNO_ANY if not specd, or -2 otherwise. 1684f645668Schristos */ 1694f645668Schristos 1704f645668Schristos typedef struct 1714f645668Schristos { 1724f645668Schristos char *ca_name; 1734f645668Schristos uint64_t ca_val; 1744f645668Schristos } hwcfuncs_attr_t; /* matches cpc_attr_t */ 1754f645668Schristos 1764f645668Schristos void * hwcfuncs_parse_attrs (const char *countername, 1774f645668Schristos hwcfuncs_attr_t attrs[], unsigned max_attrs, 1784f645668Schristos uint_t *pnum_attrs, char **errstring); 1794f645668Schristos /* Extract the attribute fields from <countername>. 1804f645668Schristos Input: 1814f645668Schristos <countername>: string whose format is 1824f645668Schristos [+]<ctrname>[~attributes...][/<regno>][,...] 1834f645668Schristos <attrs>: array of attributes to be returned 1844f645668Schristos <max_attrs>: number of elements in <attrs> 1854f645668Schristos <pnum_attrs>: if not NULL, will return how many attrs were found. 1864f645668Schristos <errstring>: pointer to a buffer for storing error info, or NULL. 1874f645668Schristos Return: upon success, a pointer to an allocated copy of <countername>, or 1884f645668Schristos NULL if there's a failure. (A copy is made in order to provide storage 1894f645668Schristos for the ca_name fields in the <attrs> array.) 1904f645668Schristos 1914f645668Schristos The pointer should be freed when <attrs> is no longer in use. 1924f645668Schristos <attrs> will be filled in data from countername. 1934f645668Schristos <pnum_attrs> will have the number of elements in <attrs>. May be 1944f645668Schristos non-zero even if return value indicates an error. 1954f645668Schristos <errstring> NULL if no error, otherwise, a malloc'd GTXT string. 1964f645668Schristos */ 1974f645668Schristos 1984f645668Schristos extern int hwcfuncs_bind_descriptor (const char *defstring); 1994f645668Schristos /* Bind counters to resources. 2004f645668Schristos Input: 2014f645668Schristos <defstring>: string whose format is 2024f645668Schristos :%s:%s:0x%x:%d:%d,0x%x[:%s...repeat for each ctr] 2034f645668Schristos where the fields are: 2044f645668Schristos :<userName>:<internalCtr>:<register>:<timeoutVal>:<tag>:<memop> 2054f645668Schristos Return: 0 if successful 2064f645668Schristos HWCFUNCS_ERROR_HWCINIT if resources unavailable 2074f645668Schristos HWCFUNCS_ERROR_HWCARGS if counters were not specified correctly 2084f645668Schristos */ 2094f645668Schristos 2104f645668Schristos extern int hwcfuncs_bind_hwcentry (const Hwcentry *entries[], 2114f645668Schristos unsigned numctrs); 2124f645668Schristos /* Bind counters to resources. 2134f645668Schristos Input: 2144f645668Schristos <entries>: array of counters 2154f645668Schristos <numctrs>: number of items in <entries> 2164f645668Schristos Return: 0 if successful 2174f645668Schristos HWCFUNCS_ERROR_HWCINIT if resources unavailable 2184f645668Schristos HWCFUNCS_ERROR_HWCARGS if counters were not specified correctly 2194f645668Schristos */ 2204f645668Schristos 2214f645668Schristos extern int hwcfuncs_assign_regnos (Hwcentry *entries[], unsigned numctrs); 2224f645668Schristos /* Assign entries[]->reg_num values as needed by platform 2234f645668Schristos Note: modifies <entries> by supplying a regno to each counter 2244f645668Schristos Input: 2254f645668Schristos <entries>: array of counters 2264f645668Schristos <numctrs>: number of items in <entries> 2274f645668Schristos Output: 2284f645668Schristos <entries>: array of counters is modified 2294f645668Schristos Return: 0 if successful 2304f645668Schristos HWCFUNCS_ERROR_HWCINIT if resources unavailable 2314f645668Schristos HWCFUNCS_ERROR_HWCARGS if counters were not specified correctly 2324f645668Schristos */ 2334f645668Schristos 2344f645668Schristos extern int regno_is_valid (const Hwcentry *pctr, regno_t regno); 2354f645668Schristos /* return 1 if <regno> is in Hwcentry's list 2364f645668Schristos Input: 2374f645668Schristos <pctr>: counter definition, reg_list[] should be initialized 2384f645668Schristos <regno>: register to check 2394f645668Schristos Return: 1 if <regno> is in Hwcentry's list, 0 otherwise 2404f645668Schristos */ 2414f645668Schristos 2424f645668Schristos extern Hwcentry **hwcfuncs_get_ctrs (unsigned *defcnt); 2434f645668Schristos /* Get descriptions of the currently bound counters. 2444f645668Schristos Input: 2454f645668Schristos <defcnt>: if not NULL, returns number of counter definitions. 2464f645668Schristos Return: 2474f645668Schristos table of counter definition pointers 2484f645668Schristos */ 2494f645668Schristos 2504f645668Schristos extern char *hwcfuncs_errmsg_get (char * buf, size_t bufsize, 2514f645668Schristos int enable_capture); 2524f645668Schristos /* Gets a recent HWC error message. 2534f645668Schristos To clear previous error messages and insure error message is enabled, 2544f645668Schristos call hwcfuncs_errmsg_get(NULL,0,1). 2554f645668Schristos Once enabled, one error is stored in an internal buffer. A call to this 2564f645668Schristos function will clear the buffer and allow a new message to be captured. 2574f645668Schristos Note: Not MT-safe - don't enable this feature in an MT environment. 2584f645668Schristos Input: 2594f645668Schristos <buf>: pointer to buffer or NULL. 2604f645668Schristos <bufsize>: size of <buf> 2614f645668Schristos <enable_capture>: 0 - disable buffering, 1 - enable buffering. 2624f645668Schristos Return: error string or an empty string. 2634f645668Schristos */ 2644f645668Schristos 2654f645668Schristos #ifdef __cplusplus 2664f645668Schristos } 2674f645668Schristos #endif 2684f645668Schristos 2694f645668Schristos #endif /* ! __HWCFUNCS_H */ 270