xref: /netbsd-src/external/gpl3/binutils/dist/gprofng/common/hwcfuncs.h (revision cb63e24e8d6aae7ddac1859a9015f48b1d8bd90e)
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