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