xref: /netbsd-src/external/gpl3/binutils.old/dist/gprofng/common/hwcdrv.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 driver's header */
22*c42dbd0eSchristos 
23*c42dbd0eSchristos #ifndef __HWCDRV_H
24*c42dbd0eSchristos #define __HWCDRV_H
25*c42dbd0eSchristos 
26*c42dbd0eSchristos #include "hwcfuncs.h"
27*c42dbd0eSchristos 
28*c42dbd0eSchristos #ifdef linux
29*c42dbd0eSchristos #define HWCFUNCS_SIGNAL         SIGIO
30*c42dbd0eSchristos #define HWCFUNCS_SIGNAL_STRING  "SIGIO"
31*c42dbd0eSchristos #else
32*c42dbd0eSchristos #define HWCFUNCS_SIGNAL         SIGEMT
33*c42dbd0eSchristos #define HWCFUNCS_SIGNAL_STRING  "SIGEMT"
34*c42dbd0eSchristos #endif
35*c42dbd0eSchristos 
36*c42dbd0eSchristos #ifndef LIBCOLLECTOR_SRC /* not running in libcollector */
37*c42dbd0eSchristos #include <string.h>
38*c42dbd0eSchristos 
39*c42dbd0eSchristos #else /* running in libcollector */
40*c42dbd0eSchristos #include "collector_module.h"
41*c42dbd0eSchristos #include "libcol_util.h"
42*c42dbd0eSchristos 
43*c42dbd0eSchristos #define get_hwcdrv                  __collector_get_hwcdrv
44*c42dbd0eSchristos #define hwcdrv_drivers              __collector_hwcdrv_drivers
45*c42dbd0eSchristos #define hwcdrv_cpc1_api             __collector_hwcdrv_cpc1_api
46*c42dbd0eSchristos #define hwcdrv_cpc2_api             __collector_hwcdrv_cpc2_api
47*c42dbd0eSchristos #define hwcdrv_default              __collector_hwcdrv_default
48*c42dbd0eSchristos #define hwcdrv_driver               __collector_hwcdrv_driver
49*c42dbd0eSchristos #define hwcdrv_init                 __collector_hwcdrv_init
50*c42dbd0eSchristos #define hwcdrv_get_info             __collector_hwcdrv_get_info
51*c42dbd0eSchristos #define hwcdrv_enable_mt            __collector_hwcdrv_enable_mt
52*c42dbd0eSchristos #define hwcdrv_get_descriptions     __collector_hwcdrv_get_descriptions
53*c42dbd0eSchristos #define hwcdrv_assign_regnos        __collector_hwcdrv_assign_regnos
54*c42dbd0eSchristos #define hwcdrv_create_counters      __collector_hwcdrv_create_counters
55*c42dbd0eSchristos #define hwcdrv_start                __collector_hwcdrv_start
56*c42dbd0eSchristos #define hwcdrv_overflow             __collector_hwcdrv_overflow
57*c42dbd0eSchristos #define hwcdrv_read_events          __collector_hwcdrv_read_events
58*c42dbd0eSchristos #define hwcdrv_sighlr_restart       __collector_hwcdrv_sighlr_restart
59*c42dbd0eSchristos #define hwcdrv_lwp_suspend          __collector_hwcdrv_lwp_suspend
60*c42dbd0eSchristos #define hwcdrv_lwp_resume           __collector_hwcdrv_lwp_resume
61*c42dbd0eSchristos #define hwcdrv_free_counters        __collector_hwcdrv_free_counters
62*c42dbd0eSchristos #define hwcdrv_lwp_init             __collector_hwcdrv_lwp_init
63*c42dbd0eSchristos #define hwcdrv_lwp_fini             __collector_hwcdrv_lwp_fini
64*c42dbd0eSchristos #define hwcdrv_assign_all_regnos    __collector_hwcdrv_assign_all_regnos
65*c42dbd0eSchristos #define hwcdrv_lookup_cpuver        __collector_hwcdrv_lookup_cpuver
66*c42dbd0eSchristos #define hwcfuncs_int_capture_errmsg  __collector_hwcfuncs_int_capture_errmsg
67*c42dbd0eSchristos 
68*c42dbd0eSchristos #define GTXT(x) x
69*c42dbd0eSchristos 
70*c42dbd0eSchristos /* Implemented by libcollector */
71*c42dbd0eSchristos #define calloc          __collector_calloc
72*c42dbd0eSchristos #define close           CALL_UTIL(close)
73*c42dbd0eSchristos #define fcntl           CALL_UTIL(fcntl)
74*c42dbd0eSchristos #define fprintf         CALL_UTIL(fprintf)
75*c42dbd0eSchristos //#define free            __collector_free
76*c42dbd0eSchristos #define free(...)
77*c42dbd0eSchristos #define gethrtime       __collector_gethrtime
78*c42dbd0eSchristos #define ioctl           CALL_UTIL(ioctl)
79*c42dbd0eSchristos #define malloc          __collector_malloc
80*c42dbd0eSchristos #define memcpy          __collector_memcpy
81*c42dbd0eSchristos #define memset          CALL_UTIL(memset)
82*c42dbd0eSchristos #define mmap            CALL_UTIL(mmap)
83*c42dbd0eSchristos #define snprintf        CALL_UTIL(snprintf)
84*c42dbd0eSchristos #define strchr          CALL_UTIL(strchr)
85*c42dbd0eSchristos #define strcmp          CALL_UTIL(strcmp)
86*c42dbd0eSchristos #define strncmp         CALL_UTIL(strncmp)
87*c42dbd0eSchristos #define strcpy          CALL_UTIL(strcpy)
88*c42dbd0eSchristos #define strdup          __collector_strdup
89*c42dbd0eSchristos #define strncpy         CALL_UTIL(strncpy)
90*c42dbd0eSchristos #define strerror        CALL_UTIL(strerror)
91*c42dbd0eSchristos #define strlen          CALL_UTIL(strlen)
92*c42dbd0eSchristos #define strstr          CALL_UTIL(strstr)
93*c42dbd0eSchristos #define strtol          CALL_UTIL(strtol)
94*c42dbd0eSchristos #define strtoll         CALL_UTIL(strtoll)
95*c42dbd0eSchristos #define strtoul         CALL_UTIL(strtoul)
96*c42dbd0eSchristos #define strtoull        CALL_UTIL(strtoull)
97*c42dbd0eSchristos #define syscall         CALL_UTIL(syscall)
98*c42dbd0eSchristos #define sysconf         CALL_UTIL(sysconf)
99*c42dbd0eSchristos #define vsnprintf       CALL_UTIL(vsnprintf)
100*c42dbd0eSchristos 
101*c42dbd0eSchristos #endif  /* --- LIBCOLLECTOR_SRC --- */
102*c42dbd0eSchristos 
103*c42dbd0eSchristos /* TprintfT(<level>,...) definitions.  Adjust per module as needed */
104*c42dbd0eSchristos #define DBG_LT0 0 // for high-level configuration, unexpected errors/warnings
105*c42dbd0eSchristos #define DBG_LT1 1 // for configuration details, warnings
106*c42dbd0eSchristos #define DBG_LT2 2
107*c42dbd0eSchristos #define DBG_LT3 3
108*c42dbd0eSchristos #define DBG_LT4 4
109*c42dbd0eSchristos 
110*c42dbd0eSchristos #ifdef __cplusplus
111*c42dbd0eSchristos extern "C"
112*c42dbd0eSchristos {
113*c42dbd0eSchristos #endif
114*c42dbd0eSchristos 
115*c42dbd0eSchristos   /* hwcdrv api */
116*c42dbd0eSchristos   typedef struct
117*c42dbd0eSchristos   {
118*c42dbd0eSchristos     int (*hwcdrv_init)(hwcfuncs_abort_fn_t abort_ftn, int * tsd_sz);
119*c42dbd0eSchristos     /* Initialize hwc counter library (do not call again after fork)
120*c42dbd0eSchristos 	 Must be called before other functions.
121*c42dbd0eSchristos        Input:
122*c42dbd0eSchristos 	 <abort_ftn>: NULL or callback function to be used for fatal errors
123*c42dbd0eSchristos 	 <tsd_sz>: If not NULL, returns size in bytes required for thread-specific storage
124*c42dbd0eSchristos        Return: 0 if successful
125*c42dbd0eSchristos      */
126*c42dbd0eSchristos 
127*c42dbd0eSchristos     void (*hwcdrv_get_info)(int *cpuver, const char **cciname, uint_t *npics,
128*c42dbd0eSchristos 			    const char **docref, uint64_t *support);
129*c42dbd0eSchristos     /* get info about session
130*c42dbd0eSchristos        Input:
131*c42dbd0eSchristos 	 <cpuver>: if not NULL, returns value of CPC cpu version
132*c42dbd0eSchristos 	 <cciname>: if not NULL, returns name of CPU
133*c42dbd0eSchristos 	 <npics>: if not NULL, returns maximum # of HWCs
134*c42dbd0eSchristos 	 <docref>: if not NULL, returns documentation reference
135*c42dbd0eSchristos 	 <support>: if not NULL, returns bitmask (see hwcfuncs.h) of hwc support
136*c42dbd0eSchristos        Return: 0 if successful, nonzero otherwise
137*c42dbd0eSchristos      */
138*c42dbd0eSchristos 
139*c42dbd0eSchristos     int (*hwcdrv_enable_mt)(hwcfuncs_tsd_get_fn_t tsd_ftn);
140*c42dbd0eSchristos     /* Enables multi-threaded mode (do not need to call again after fork)
141*c42dbd0eSchristos        Input:
142*c42dbd0eSchristos 	 <tsd_ftn>: If <tsd_sz>==0, this parameter is ignored.
143*c42dbd0eSchristos 		    Otherwise:
144*c42dbd0eSchristos 		     tsd_ftn() must be able to return a pointer to thread-specific
145*c42dbd0eSchristos 		     memory of <tsd_sz> bytes.
146*c42dbd0eSchristos 		     For a given thread, tsd_ftn() must
147*c42dbd0eSchristos 		     always return the same pointer.
148*c42dbd0eSchristos        Return: none
149*c42dbd0eSchristos      */
150*c42dbd0eSchristos 
151*c42dbd0eSchristos     int (*hwcdrv_get_descriptions)(hwcf_hwc_cb_t *hwc_find_action,
152*c42dbd0eSchristos 				   hwcf_attr_cb_t *attr_find_action);
153*c42dbd0eSchristos     /* Initiate callbacks with all available HWC names and and HWC attributes.
154*c42dbd0eSchristos        Input:
155*c42dbd0eSchristos 	 <hwc_find_action>: if not NULL, will be called once for each HWC
156*c42dbd0eSchristos 	 <attr_find_action>: if not NULL, will be called once for each attribute
157*c42dbd0eSchristos        Return: 0 if successful
158*c42dbd0eSchristos 	  or a cpc return code upon error
159*c42dbd0eSchristos      */
160*c42dbd0eSchristos 
161*c42dbd0eSchristos     int (*hwcdrv_assign_regnos)(Hwcentry* entries[], unsigned numctrs);
162*c42dbd0eSchristos     /* Assign entries[]->reg_num values as needed by platform
163*c42dbd0eSchristos        Input:
164*c42dbd0eSchristos 	 <entries>: array of counters
165*c42dbd0eSchristos 	 <numctrs>: number of items in <entries>
166*c42dbd0eSchristos        Return: 0 if successful
167*c42dbd0eSchristos 	  HWCFUNCS_ERROR_HWCINIT if resources unavailable
168*c42dbd0eSchristos 	  HWCFUNCS_ERROR_HWCARGS if counters were not specified correctly
169*c42dbd0eSchristos      */
170*c42dbd0eSchristos 
171*c42dbd0eSchristos     int (*hwcdrv_create_counters)(unsigned hwcdef_cnt, Hwcentry *hwcdef);
172*c42dbd0eSchristos     /* Create the counters, but don't start them.
173*c42dbd0eSchristos 	 call this once in main thread to create counters.
174*c42dbd0eSchristos        Input:
175*c42dbd0eSchristos 	 <defcnt>: number of counter definitions.
176*c42dbd0eSchristos 	 <hwcdef>: counter definitions.
177*c42dbd0eSchristos        Return: 0 if successful
178*c42dbd0eSchristos 	  or a cpc return code upon error
179*c42dbd0eSchristos      */
180*c42dbd0eSchristos 
181*c42dbd0eSchristos     int (*hwcdrv_start)(void);
182*c42dbd0eSchristos     /* Start the counters.
183*c42dbd0eSchristos 	 call this once in main thread to start counters.
184*c42dbd0eSchristos        Return: 0 if successful
185*c42dbd0eSchristos 	  or a cpc return code upon error
186*c42dbd0eSchristos      */
187*c42dbd0eSchristos 
188*c42dbd0eSchristos     int (*hwcdrv_overflow)(siginfo_t *si, hwc_event_t *sample,
189*c42dbd0eSchristos 			   hwc_event_t *lost_samples);
190*c42dbd0eSchristos     /* Linux only.  Capture current counter values.
191*c42dbd0eSchristos 	 This is intended to be called from SIGEMT handler;
192*c42dbd0eSchristos        Input:
193*c42dbd0eSchristos 	 <si>: signal handler context information
194*c42dbd0eSchristos 	 <sample>: returns non-zero values for counters that overflowed
195*c42dbd0eSchristos 	 <lost_samples>: returns non-zero values for counters that "lost" counts
196*c42dbd0eSchristos        Return: 0 if successful
197*c42dbd0eSchristos 	  or a cpc return code upon error.
198*c42dbd0eSchristos      */
199*c42dbd0eSchristos 
200*c42dbd0eSchristos     int (*hwcdrv_read_events)(hwc_event_t *overflow_data,
201*c42dbd0eSchristos 			      hwc_event_samples_t *sampled_data);
202*c42dbd0eSchristos     /* Read current counter values and samples.  Read of samples is destructive.
203*c42dbd0eSchristos        Note: hwcdrv_read_events is not supported on Linux.
204*c42dbd0eSchristos        <overflow_data>: returns snapshot of counter values
205*c42dbd0eSchristos        <sampled_data>: returns sampled data
206*c42dbd0eSchristos        Return: 0 if successful
207*c42dbd0eSchristos 	  HWCFUNCS_ERROR_UNAVAIL if resource unavailable(e.g. called before initted)
208*c42dbd0eSchristos 	  (other values may be possible)
209*c42dbd0eSchristos      */
210*c42dbd0eSchristos 
211*c42dbd0eSchristos     int (*hwcdrv_sighlr_restart)(const hwc_event_t* startVals);
212*c42dbd0eSchristos     /* Restarts the counters at the given value.
213*c42dbd0eSchristos 	 This is intended to be called from SIGEMT handler;
214*c42dbd0eSchristos        Input:
215*c42dbd0eSchristos 	 <startVals>: Solaris: new start values.
216*c42dbd0eSchristos 		      Linux: pointer may be NULL; startVals is ignored.
217*c42dbd0eSchristos        Return: 0 if successful
218*c42dbd0eSchristos 	  or a cpc return code upon error.
219*c42dbd0eSchristos      */
220*c42dbd0eSchristos 
221*c42dbd0eSchristos     int (*hwcdrv_lwp_suspend)(void);
222*c42dbd0eSchristos     /* Attempt to stop counters on this lwp only.
223*c42dbd0eSchristos 	 hwcdrv_lwp_resume() should be used to restart counters.
224*c42dbd0eSchristos        Return: 0 if successful
225*c42dbd0eSchristos 	  or a cpc return code upon error.
226*c42dbd0eSchristos      */
227*c42dbd0eSchristos 
228*c42dbd0eSchristos     int (*hwcdrv_lwp_resume)(void);
229*c42dbd0eSchristos     /* Attempt to restart counters on this lwp when counters were
230*c42dbd0eSchristos 	 stopped with hwcdrv_lwp_suspend().
231*c42dbd0eSchristos        Return: 0 if successful
232*c42dbd0eSchristos 	  or a cpc return code upon error.
233*c42dbd0eSchristos      */
234*c42dbd0eSchristos 
235*c42dbd0eSchristos     int (*hwcdrv_free_counters)(void);
236*c42dbd0eSchristos     /* Stops counters on this lwp only and frees resources.
237*c42dbd0eSchristos 	 This will fail w/ unpredictable results if other lwps's are
238*c42dbd0eSchristos 	 still running.  After this call returns,
239*c42dbd0eSchristos 	 hwcdrv_create_counters() may be called with new values.
240*c42dbd0eSchristos        Return: 0 if successful
241*c42dbd0eSchristos 	  or a cpc return code upon error.
242*c42dbd0eSchristos      */
243*c42dbd0eSchristos 
244*c42dbd0eSchristos     int (*hwcdrv_lwp_init)(void);
245*c42dbd0eSchristos     /* per-thread counter init.
246*c42dbd0eSchristos 	 Solaris: nop.
247*c42dbd0eSchristos 	 Linux: just after thread creation call this from inside thread
248*c42dbd0eSchristos 	      to create context and start counters.
249*c42dbd0eSchristos        Return: 0 if successful
250*c42dbd0eSchristos 	  or a perfctr return code upon error
251*c42dbd0eSchristos      */
252*c42dbd0eSchristos 
253*c42dbd0eSchristos     void (*hwcdrv_lwp_fini)(void);
254*c42dbd0eSchristos     /* per-thread counter cleanup.
255*c42dbd0eSchristos 	 Solaris: nop.
256*c42dbd0eSchristos 	 Linux: call in each thread upon thread destruction.
257*c42dbd0eSchristos      */
258*c42dbd0eSchristos 
259*c42dbd0eSchristos     int hwcdrv_init_status;
260*c42dbd0eSchristos   } hwcdrv_api_t;
261*c42dbd0eSchristos 
262*c42dbd0eSchristos   extern hwcdrv_api_t *get_hwcdrv ();
263*c42dbd0eSchristos   extern hwcdrv_api_t *__collector_get_hwcdrv ();
264*c42dbd0eSchristos   extern int __collector_hwcfuncs_bind_descriptor (const char *defstring);
265*c42dbd0eSchristos   extern Hwcentry **__collector_hwcfuncs_get_ctrs (unsigned *defcnt);
266*c42dbd0eSchristos   extern hwcdrv_api_t *hwcdrv_drivers[]; // array of available drivers
267*c42dbd0eSchristos 
268*c42dbd0eSchristos   /* prototypes for internal use by hwcdrv drivers */
269*c42dbd0eSchristos   typedef struct
270*c42dbd0eSchristos   { // see hwcdrv_get_info() for field definitions
271*c42dbd0eSchristos     int cpcN_cpuver;
272*c42dbd0eSchristos     uint_t cpcN_npics;
273*c42dbd0eSchristos     const char *cpcN_docref;
274*c42dbd0eSchristos     const char *cpcN_cciname;
275*c42dbd0eSchristos   } hwcdrv_about_t;
276*c42dbd0eSchristos 
277*c42dbd0eSchristos   extern int hwcdrv_assign_all_regnos (Hwcentry* entries[], unsigned numctrs);
278*c42dbd0eSchristos   /* assign user's counters to specific CPU registers */
279*c42dbd0eSchristos 
280*c42dbd0eSchristos   extern int hwcdrv_lookup_cpuver (const char * cpcN_cciname);
281*c42dbd0eSchristos   /* returns hwc_cpus.h ID for a given string. */
282*c42dbd0eSchristos 
283*c42dbd0eSchristos   extern void hwcfuncs_int_capture_errmsg (const char *fn, int subcode,
284*c42dbd0eSchristos 					   const char *fmt, va_list ap);
285*c42dbd0eSchristos #define logerr  hwcfuncs_int_logerr
286*c42dbd0eSchristos 
287*c42dbd0eSchristos   /*---------------------------------------------------------------------------*/
288*c42dbd0eSchristos   /* prototypes for internal use by linux hwcdrv drivers */
289*c42dbd0eSchristos #define PERFCTR_FIXED_MAGIC 0x40000000 /* tells perfctr to use intel fixed pmcs */
290*c42dbd0eSchristos #define PERFCTR_UMASK_SHIFT 8
291*c42dbd0eSchristos #define EXTENDED_EVNUM_2_EVSEL(evnum) \
292*c42dbd0eSchristos   ( (((eventsel_t)(evnum) & 0x0f00ULL) << 24) | ((eventsel_t)(evnum) & ~0x0f00ULL) )
293*c42dbd0eSchristos 
294*c42dbd0eSchristos   typedef uint64_t eventsel_t;
295*c42dbd0eSchristos   extern int  hwcfuncs_get_x86_eventsel (unsigned int regno, const char *int_name,
296*c42dbd0eSchristos 			     eventsel_t *return_event, uint_t *return_pmc_sel);
297*c42dbd0eSchristos 
298*c42dbd0eSchristos   typedef int (hwcdrv_get_events_fn_t) (hwcf_hwc_cb_t *hwc_cb);
299*c42dbd0eSchristos   typedef int (hwcdrv_get_eventnum_fn_t) (const char *eventname, uint_t pmc,
300*c42dbd0eSchristos 					  eventsel_t *eventnum,
301*c42dbd0eSchristos 					  eventsel_t *valid_umask, uint_t *pmc_sel);
302*c42dbd0eSchristos   extern hwcdrv_get_eventnum_fn_t *hwcdrv_get_x86_eventnum;
303*c42dbd0eSchristos 
304*c42dbd0eSchristos   typedef struct
305*c42dbd0eSchristos   {
306*c42dbd0eSchristos     const char * attrname;  // user-visible name of attribute
307*c42dbd0eSchristos     int is_inverted;        // nonzero means boolean attribute is inverted
308*c42dbd0eSchristos     eventsel_t mask;        // which attribute bits can be set?
309*c42dbd0eSchristos     eventsel_t shift;       // how far to shift bits for use in x86 register
310*c42dbd0eSchristos   } attr_info_t;
311*c42dbd0eSchristos   extern const attr_info_t *perfctr_attrs_table;
312*c42dbd0eSchristos 
313*c42dbd0eSchristos   /* hdrv_pcbe api: cpu-specific drivers for Linux */
314*c42dbd0eSchristos   typedef struct
315*c42dbd0eSchristos   {
316*c42dbd0eSchristos     int (*hdrv_pcbe_init)(void);
317*c42dbd0eSchristos     uint_t (*hdrv_pcbe_ncounters)(void);
318*c42dbd0eSchristos     const char *(*hdrv_pcbe_impl_name)(void);
319*c42dbd0eSchristos     const char *(*hdrv_pcbe_cpuref)(void);
320*c42dbd0eSchristos     int (*hdrv_pcbe_get_events)(hwcf_hwc_cb_t *hwc_cb);
321*c42dbd0eSchristos     int (*hdrv_pcbe_get_eventnum)(const char * eventname, uint_t pmc,
322*c42dbd0eSchristos 				  eventsel_t *eventnum, eventsel_t *valid_umask,
323*c42dbd0eSchristos 				  uint_t *pmc_sel);
324*c42dbd0eSchristos   } hdrv_pcbe_api_t;
325*c42dbd0eSchristos 
326*c42dbd0eSchristos #ifdef __cplusplus
327*c42dbd0eSchristos }
328*c42dbd0eSchristos #endif
329*c42dbd0eSchristos 
330*c42dbd0eSchristos #endif
331