xref: /netbsd-src/external/gpl3/binutils.old/dist/gprofng/common/hwcfuncs.h (revision c42dbd0ed2e61fe6eda8590caa852ccf34719964)
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 */
22*c42dbd0eSchristos 
23*c42dbd0eSchristos #ifndef __HWCFUNCS_H
24*c42dbd0eSchristos #define __HWCFUNCS_H
25*c42dbd0eSchristos 
26*c42dbd0eSchristos #ifdef LIBCOLLECTOR_SRC /* running in libcollector */
27*c42dbd0eSchristos #define hwcfuncs_int_logerr         __collector_hwcfuncs_int_logerr
28*c42dbd0eSchristos #define hwcfuncs_parse_ctr          __collector_hwcfuncs_parse_ctr
29*c42dbd0eSchristos #define hwcfuncs_parse_attrs        __collector_hwcfuncs_parse_attrs
30*c42dbd0eSchristos #define hwcfuncs_bind_descriptor    __collector_hwcfuncs_bind_descriptor
31*c42dbd0eSchristos #define hwcfuncs_bind_hwcentry      __collector_hwcfuncs_bind_hwcentry
32*c42dbd0eSchristos #define hwcfuncs_assign_regnos      __collector_hwcfuncs_assign_regnos
33*c42dbd0eSchristos #define regno_is_valid              __collector_regno_is_valid
34*c42dbd0eSchristos #define hwcfuncs_get_ctrs           __collector_hwcfuncs_get_ctrs
35*c42dbd0eSchristos #define hwcfuncs_errmsg_get         __collector_hwcfuncs_errmsg_get
36*c42dbd0eSchristos #endif  /* --- LIBCOLLECTOR_SRC --- */
37*c42dbd0eSchristos 
38*c42dbd0eSchristos #include <signal.h>     /* siginfo_t */
39*c42dbd0eSchristos #include <limits.h>     /* UINT64_t */
40*c42dbd0eSchristos #include <sys/types.h>
41*c42dbd0eSchristos #include <stdint.h>
42*c42dbd0eSchristos 
43*c42dbd0eSchristos #include "hwcentry.h"   /* for Hwcentry type */
44*c42dbd0eSchristos #include "gp-time.h"
45*c42dbd0eSchristos 
46*c42dbd0eSchristos typedef unsigned int uint_t;
47*c42dbd0eSchristos 
48*c42dbd0eSchristos #ifdef	__cplusplus
49*c42dbd0eSchristos extern "C" {
50*c42dbd0eSchristos #endif
51*c42dbd0eSchristos 
52*c42dbd0eSchristos /*---------------------------------------------------------------------------*/
53*c42dbd0eSchristos /* compile options */
54*c42dbd0eSchristos 
55*c42dbd0eSchristos #define HWC_DEBUG   0 /* 0/1 to enable extra HWC debug */
56*c42dbd0eSchristos 
57*c42dbd0eSchristos /*---------------------------------------------------------------------------*/
58*c42dbd0eSchristos /* typedefs */
59*c42dbd0eSchristos /* generic hw event */
60*c42dbd0eSchristos   typedef struct _hwc_event_t
61*c42dbd0eSchristos   { /* generalized counter event */
62*c42dbd0eSchristos     hrtime_t ce_hrt;            /* gethrtime() */
63*c42dbd0eSchristos     uint64_t ce_pic[MAX_PICS];  /* counter samples or start values */
64*c42dbd0eSchristos   } hwc_event_t;
65*c42dbd0eSchristos 
66*c42dbd0eSchristos   /* supplementary data that accompanies some hw events */
67*c42dbd0eSchristos   typedef struct
68*c42dbd0eSchristos   { /* supplementary data fields */
69*c42dbd0eSchristos     uint64_t smpl_pc;           /* pc related to event */
70*c42dbd0eSchristos     uint64_t smpl_data_source;  /* chip-specific data source encoding */
71*c42dbd0eSchristos     uint64_t smpl_latency;      /* latency related to event */
72*c42dbd0eSchristos     uint64_t smpl_mem_addr;     /* memory address related to event */
73*c42dbd0eSchristos   } hwc_sample_t;
74*c42dbd0eSchristos #define HWCFUNCS_INVALID_U64 0xFEEDBEEFDEADBEEFllu /* identifies fields as unused */
75*c42dbd0eSchristos 
76*c42dbd0eSchristos typedef struct {                                /* supplementary data fields */
77*c42dbd0eSchristos     hwc_sample_t sample[MAX_PICS];  /* counter samples or start values */
78*c42dbd0eSchristos } hwc_event_samples_t;
79*c42dbd0eSchristos 
80*c42dbd0eSchristos #define HWCFUNCS_SAMPLE_RESET(sample) \
81*c42dbd0eSchristos 	do { \
82*c42dbd0eSchristos 	    (sample)->smpl_pc          =HWCFUNCS_INVALID_U64; \
83*c42dbd0eSchristos 	    (sample)->smpl_data_source =HWCFUNCS_INVALID_U64; \
84*c42dbd0eSchristos 	    (sample)->smpl_latency     =HWCFUNCS_INVALID_U64; \
85*c42dbd0eSchristos 	    (sample)->smpl_mem_addr    =HWCFUNCS_INVALID_U64; \
86*c42dbd0eSchristos 	} while(0)
87*c42dbd0eSchristos 
88*c42dbd0eSchristos #define HWCFUNCS_SAMPLE_IS_RESET(sample) \
89*c42dbd0eSchristos 	( \
90*c42dbd0eSchristos 	    (sample)->smpl_pc         ==HWCFUNCS_INVALID_U64 && \
91*c42dbd0eSchristos 	    (sample)->smpl_data_source==HWCFUNCS_INVALID_U64 && \
92*c42dbd0eSchristos 	    (sample)->smpl_latency    ==HWCFUNCS_INVALID_U64 && \
93*c42dbd0eSchristos 	    (sample)->smpl_mem_addr   ==HWCFUNCS_INVALID_U64 \
94*c42dbd0eSchristos 	)
95*c42dbd0eSchristos 
96*c42dbd0eSchristos /*---------------------------------------------------------------------------*/
97*c42dbd0eSchristos /* macros */
98*c42dbd0eSchristos 
99*c42dbd0eSchristos #define HW_INTERVAL_MAX         UINT64_MAX
100*c42dbd0eSchristos #define HW_INTERVAL_PRESET(x)   (HW_INTERVAL_MAX - ((uint64_t)(x) - 1))
101*c42dbd0eSchristos #define HW_INTERVAL_TYPE(x)     ((uint64_t) (x)
102*c42dbd0eSchristos 
103*c42dbd0eSchristos /* parsing */
104*c42dbd0eSchristos #define HWCFUNCS_MAX_ATTRS              20
105*c42dbd0eSchristos #define HWCFUNCS_PARSE_ATTR             '~'
106*c42dbd0eSchristos #define HWCFUNCS_PARSE_EQUAL            '='
107*c42dbd0eSchristos #define HWCFUNCS_PARSE_BACKTRACK        '+'
108*c42dbd0eSchristos #define HWCFUNCS_PARSE_BACKTRACK_OFF    '-'
109*c42dbd0eSchristos #define HWCFUNCS_PARSE_REGNUM           '/'
110*c42dbd0eSchristos #define HWCFUNCS_PARSE_VALUE            ','
111*c42dbd0eSchristos 
112*c42dbd0eSchristos /* error codes */
113*c42dbd0eSchristos #define HWCFUNCS_ERROR_GENERIC          (-1)
114*c42dbd0eSchristos #define HWCFUNCS_ERROR_NOT_SUPPORTED    (-2)
115*c42dbd0eSchristos #define HWCFUNCS_ERROR_ALREADY_CALLED   (-3)
116*c42dbd0eSchristos #define HWCFUNCS_ERROR_HWCINIT          (-4)
117*c42dbd0eSchristos #define HWCFUNCS_ERROR_HWCARGS          (-5)
118*c42dbd0eSchristos #define HWCFUNCS_ERROR_MEMORY           (-6)
119*c42dbd0eSchristos #define HWCFUNCS_ERROR_UNAVAIL          (-7)
120*c42dbd0eSchristos #define HWCFUNCS_ERROR_ERRNO_ZERO       (-8)
121*c42dbd0eSchristos #define HWCFUNCS_ERROR_UNEXPECTED       (-99)
122*c42dbd0eSchristos 
123*c42dbd0eSchristos /*---------------------------------------------------------------------------*/
124*c42dbd0eSchristos /* prototypes */
125*c42dbd0eSchristos 
126*c42dbd0eSchristos typedef void (*hwcfuncs_abort_fn_t) (int errnum, const char *msg);
127*c42dbd0eSchristos 
128*c42dbd0eSchristos extern void hwcfuncs_int_logerr(const char *format,...);
129*c42dbd0eSchristos /* Log an error to the internal error buffer. See hwcfuncs_errmsg_get().
130*c42dbd0eSchristos      Note: Not MT-safe; don't even enable logging in an MT environment.
131*c42dbd0eSchristos        Recommend using this call only during init.
132*c42dbd0eSchristos      Note: when a libcpc call fails, it may automatically call
133*c42dbd0eSchristos        cpcN_capture_errmsg() to log the error message in the same internal buffer.
134*c42dbd0eSchristos        Recommend using this call only for non-cpc failures.
135*c42dbd0eSchristos  */
136*c42dbd0eSchristos 
137*c42dbd0eSchristos #define HWCFUNCS_SUPPORT_OVERFLOW_PROFILING 0x01llu
138*c42dbd0eSchristos #define HWCFUNCS_SUPPORT_PEBS_SAMPLING      0x02llu
139*c42dbd0eSchristos #define HWCFUNCS_SUPPORT_OVERFLOW_CTR_ID    0x04llu // OS identifies which counter overflowed
140*c42dbd0eSchristos   /* get info about session
141*c42dbd0eSchristos      Input:
142*c42dbd0eSchristos        <cpuver>: if not NULL, returns value of CPC cpu version
143*c42dbd0eSchristos        <cciname>: if not NULL, returns name of CPU
144*c42dbd0eSchristos        <npics>: if not NULL, returns maximum # of HWCs
145*c42dbd0eSchristos        <docref>: if not NULL, returns documentation reference
146*c42dbd0eSchristos        <support>: if not NULL, returns bitmask (see above) of hwc support
147*c42dbd0eSchristos      Return: none
148*c42dbd0eSchristos    */
149*c42dbd0eSchristos 
150*c42dbd0eSchristos   typedef void* (*hwcfuncs_tsd_get_fn_t) (void);
151*c42dbd0eSchristos   typedef void (hwcf_hwc_cb_t) (uint_t cpcregno, const char *name);
152*c42dbd0eSchristos   typedef void (hwcf_attr_cb_t) (const char *attr);
153*c42dbd0eSchristos 
154*c42dbd0eSchristos   extern void
155*c42dbd0eSchristos   hwcfuncs_parse_ctr (const char *counter_def, int *pplus, char **pnameOnly,
156*c42dbd0eSchristos 		      char **pattrs, char **pregstr, regno_t *pregno);
157*c42dbd0eSchristos /* Parse a counter definition string (value must already be stripped off).
158*c42dbd0eSchristos      Input:
159*c42dbd0eSchristos        <counter_def>: input whose format is
160*c42dbd0eSchristos 	 [+|-]<countername>[~attrs...][/<regno>]
161*c42dbd0eSchristos        pointers to return values:  Any can be NULL.
162*c42dbd0eSchristos      Return:
163*c42dbd0eSchristos        <plus>: 1 if [+] is found, -1 if [-] is found, 0 otherwise
164*c42dbd0eSchristos        <pnameonly>: strdup(<countername>)
165*c42dbd0eSchristos        <pattrs>: strdup([~attrs...]) if specified, NULL otherwise.
166*c42dbd0eSchristos        <pregstr>: strdup(/<regno>) if specified, NULL otherwise.
167*c42dbd0eSchristos        <pregno>: <regno> if readable, REGNO_ANY if not specd, or -2 otherwise.
168*c42dbd0eSchristos    */
169*c42dbd0eSchristos 
170*c42dbd0eSchristos   typedef struct
171*c42dbd0eSchristos   {
172*c42dbd0eSchristos     char *ca_name;
173*c42dbd0eSchristos     uint64_t ca_val;
174*c42dbd0eSchristos   } hwcfuncs_attr_t; /* matches cpc_attr_t */
175*c42dbd0eSchristos 
176*c42dbd0eSchristos   void * hwcfuncs_parse_attrs (const char *countername,
177*c42dbd0eSchristos 			       hwcfuncs_attr_t attrs[], unsigned max_attrs,
178*c42dbd0eSchristos 			       uint_t *pnum_attrs, char **errstring);
179*c42dbd0eSchristos   /* Extract the attribute fields from <countername>.
180*c42dbd0eSchristos        Input:
181*c42dbd0eSchristos 	 <countername>: string whose format is
182*c42dbd0eSchristos 	    [+]<ctrname>[~attributes...][/<regno>][,...]
183*c42dbd0eSchristos 	 <attrs>: array of attributes to be returned
184*c42dbd0eSchristos 	 <max_attrs>: number of elements in <attrs>
185*c42dbd0eSchristos 	 <pnum_attrs>: if not NULL, will return how many attrs were found.
186*c42dbd0eSchristos 	 <errstring>: pointer to a buffer for storing error info, or NULL.
187*c42dbd0eSchristos        Return: upon success, a pointer to an allocated copy of <countername>, or
188*c42dbd0eSchristos 	   NULL if there's a failure.  (A copy is made in order to provide storage
189*c42dbd0eSchristos 	   for the ca_name fields in the <attrs> array.)
190*c42dbd0eSchristos 
191*c42dbd0eSchristos 	   The pointer should be freed when <attrs> is no longer in use.
192*c42dbd0eSchristos 	   <attrs> will be filled in data from countername.
193*c42dbd0eSchristos 	 <pnum_attrs> will have the number of elements in <attrs>.  May be
194*c42dbd0eSchristos 	   non-zero even if return value indicates an error.
195*c42dbd0eSchristos 	 <errstring> NULL if no error, otherwise, a malloc'd GTXT string.
196*c42dbd0eSchristos    */
197*c42dbd0eSchristos 
198*c42dbd0eSchristos   extern int hwcfuncs_bind_descriptor (const char *defstring);
199*c42dbd0eSchristos   /* Bind counters to resources.
200*c42dbd0eSchristos      Input:
201*c42dbd0eSchristos        <defstring>: string whose format is
202*c42dbd0eSchristos 	  :%s:%s:0x%x:%d:%d,0x%x[:%s...repeat for each ctr]
203*c42dbd0eSchristos 	 where the fields are:
204*c42dbd0eSchristos 	  :<userName>:<internalCtr>:<register>:<timeoutVal>:<tag>:<memop>
205*c42dbd0eSchristos      Return: 0 if successful
206*c42dbd0eSchristos 	HWCFUNCS_ERROR_HWCINIT if resources unavailable
207*c42dbd0eSchristos 	HWCFUNCS_ERROR_HWCARGS if counters were not specified correctly
208*c42dbd0eSchristos    */
209*c42dbd0eSchristos 
210*c42dbd0eSchristos   extern int hwcfuncs_bind_hwcentry (const Hwcentry *entries[],
211*c42dbd0eSchristos 				     unsigned numctrs);
212*c42dbd0eSchristos   /* Bind counters to resources.
213*c42dbd0eSchristos      Input:
214*c42dbd0eSchristos        <entries>: array of counters
215*c42dbd0eSchristos        <numctrs>: number of items in <entries>
216*c42dbd0eSchristos      Return: 0 if successful
217*c42dbd0eSchristos 	HWCFUNCS_ERROR_HWCINIT if resources unavailable
218*c42dbd0eSchristos 	HWCFUNCS_ERROR_HWCARGS if counters were not specified correctly
219*c42dbd0eSchristos    */
220*c42dbd0eSchristos 
221*c42dbd0eSchristos   extern int hwcfuncs_assign_regnos (Hwcentry *entries[], unsigned numctrs);
222*c42dbd0eSchristos   /* Assign entries[]->reg_num values as needed by platform
223*c42dbd0eSchristos        Note: modifies <entries> by supplying a regno to each counter
224*c42dbd0eSchristos      Input:
225*c42dbd0eSchristos        <entries>: array of counters
226*c42dbd0eSchristos        <numctrs>: number of items in <entries>
227*c42dbd0eSchristos      Output:
228*c42dbd0eSchristos        <entries>: array of counters is modified
229*c42dbd0eSchristos      Return: 0 if successful
230*c42dbd0eSchristos 	HWCFUNCS_ERROR_HWCINIT if resources unavailable
231*c42dbd0eSchristos 	HWCFUNCS_ERROR_HWCARGS if counters were not specified correctly
232*c42dbd0eSchristos    */
233*c42dbd0eSchristos 
234*c42dbd0eSchristos   extern int regno_is_valid (const Hwcentry *pctr, regno_t regno);
235*c42dbd0eSchristos   /* return 1 if <regno> is in Hwcentry's list
236*c42dbd0eSchristos      Input:
237*c42dbd0eSchristos        <pctr>: counter definition, reg_list[] should be initialized
238*c42dbd0eSchristos        <regno>: register to check
239*c42dbd0eSchristos      Return: 1 if <regno> is in Hwcentry's list, 0 otherwise
240*c42dbd0eSchristos    */
241*c42dbd0eSchristos 
242*c42dbd0eSchristos   extern Hwcentry **hwcfuncs_get_ctrs (unsigned *defcnt);
243*c42dbd0eSchristos   /* Get descriptions of the currently bound counters.
244*c42dbd0eSchristos      Input:
245*c42dbd0eSchristos        <defcnt>: if not NULL, returns number of counter definitions.
246*c42dbd0eSchristos      Return:
247*c42dbd0eSchristos        table of counter definition pointers
248*c42dbd0eSchristos    */
249*c42dbd0eSchristos 
250*c42dbd0eSchristos   extern char *hwcfuncs_errmsg_get (char * buf, size_t bufsize,
251*c42dbd0eSchristos 				    int enable_capture);
252*c42dbd0eSchristos   /* Gets a recent HWC error message.
253*c42dbd0eSchristos        To clear previous error messages and insure error message is enabled,
254*c42dbd0eSchristos        call hwcfuncs_errmsg_get(NULL,0,1).
255*c42dbd0eSchristos        Once enabled, one error is stored in an internal buffer.  A call to this
256*c42dbd0eSchristos        function will clear the buffer and allow a new message to be captured.
257*c42dbd0eSchristos        Note: Not MT-safe - don't enable this feature in an MT environment.
258*c42dbd0eSchristos      Input:
259*c42dbd0eSchristos        <buf>: pointer to buffer or NULL.
260*c42dbd0eSchristos        <bufsize>: size of <buf>
261*c42dbd0eSchristos        <enable_capture>: 0 - disable buffering, 1 - enable buffering.
262*c42dbd0eSchristos      Return: error string or an empty string.
263*c42dbd0eSchristos    */
264*c42dbd0eSchristos 
265*c42dbd0eSchristos #ifdef	__cplusplus
266*c42dbd0eSchristos }
267*c42dbd0eSchristos #endif
268*c42dbd0eSchristos 
269*c42dbd0eSchristos #endif /* ! __HWCFUNCS_H */
270