summaryrefslogtreecommitdiff
path: root/gprofng/common/hwcdrv.h
blob: f711990b4b6f84beefc47d25bdb12b062a9707b2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
/* Copyright (C) 2021-2023 Free Software Foundation, Inc.
   Contributed by Oracle.

   This file is part of GNU Binutils.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, 51 Franklin Street - Fifth Floor, Boston,
   MA 02110-1301, USA.  */

/* Hardware counter profiling driver's header */

#ifndef __HWCDRV_H
#define __HWCDRV_H

#include "hwcfuncs.h"

#ifdef linux
#define HWCFUNCS_SIGNAL         SIGIO
#define HWCFUNCS_SIGNAL_STRING  "SIGIO"
#else
#define HWCFUNCS_SIGNAL         SIGEMT
#define HWCFUNCS_SIGNAL_STRING  "SIGEMT"
#endif

#ifndef LIBCOLLECTOR_SRC /* not running in libcollector */
#include <string.h>

#else /* running in libcollector */
#include "collector_module.h"
#include "libcol_util.h"

#define get_hwcdrv                  __collector_get_hwcdrv
#define hwcdrv_drivers              __collector_hwcdrv_drivers
#define hwcdrv_cpc1_api             __collector_hwcdrv_cpc1_api
#define hwcdrv_cpc2_api             __collector_hwcdrv_cpc2_api
#define hwcdrv_default              __collector_hwcdrv_default
#define hwcdrv_driver               __collector_hwcdrv_driver
#define hwcdrv_init                 __collector_hwcdrv_init
#define hwcdrv_get_info             __collector_hwcdrv_get_info
#define hwcdrv_enable_mt            __collector_hwcdrv_enable_mt
#define hwcdrv_get_descriptions     __collector_hwcdrv_get_descriptions
#define hwcdrv_assign_regnos        __collector_hwcdrv_assign_regnos
#define hwcdrv_create_counters      __collector_hwcdrv_create_counters
#define hwcdrv_start                __collector_hwcdrv_start
#define hwcdrv_overflow             __collector_hwcdrv_overflow
#define hwcdrv_read_events          __collector_hwcdrv_read_events
#define hwcdrv_sighlr_restart       __collector_hwcdrv_sighlr_restart
#define hwcdrv_lwp_suspend          __collector_hwcdrv_lwp_suspend
#define hwcdrv_lwp_resume           __collector_hwcdrv_lwp_resume
#define hwcdrv_free_counters        __collector_hwcdrv_free_counters
#define hwcdrv_lwp_init             __collector_hwcdrv_lwp_init
#define hwcdrv_lwp_fini             __collector_hwcdrv_lwp_fini
#define hwcdrv_assign_all_regnos    __collector_hwcdrv_assign_all_regnos
#define hwcdrv_lookup_cpuver        __collector_hwcdrv_lookup_cpuver
#define hwcfuncs_int_capture_errmsg  __collector_hwcfuncs_int_capture_errmsg

#define GTXT(x) x

/* Implemented by libcollector */
#define calloc          __collector_calloc
#define close           CALL_UTIL(close)
#define fcntl           CALL_UTIL(fcntl)
#define fprintf         CALL_UTIL(fprintf)
//#define free            __collector_free
#define free(...)
#define gethrtime       __collector_gethrtime
#define ioctl           CALL_UTIL(ioctl)
#define malloc          __collector_malloc
#define memcpy          __collector_memcpy
#define memset          CALL_UTIL(memset)
#define mmap            CALL_UTIL(mmap)
#define snprintf        CALL_UTIL(snprintf)
#define strchr          CALL_UTIL(strchr)
#define strcmp          CALL_UTIL(strcmp)
#define strncmp         CALL_UTIL(strncmp)
#define strcpy          CALL_UTIL(strcpy)
#define strdup          __collector_strdup
#define strncpy         CALL_UTIL(strncpy)
#define strerror        CALL_UTIL(strerror)
#define strlen          CALL_UTIL(strlen)
#define strstr          CALL_UTIL(strstr)
#define strtol          CALL_UTIL(strtol)
#define strtoll         CALL_UTIL(strtoll)
#define strtoul         CALL_UTIL(strtoul)
#define strtoull        CALL_UTIL(strtoull)
#define syscall         CALL_UTIL(syscall)
#define sysconf         CALL_UTIL(sysconf)
#define vsnprintf       CALL_UTIL(vsnprintf)

#endif  /* --- LIBCOLLECTOR_SRC --- */

/* TprintfT(<level>,...) definitions.  Adjust per module as needed */
#define DBG_LT0 0 // for high-level configuration, unexpected errors/warnings
#define DBG_LT1 1 // for configuration details, warnings
#define DBG_LT2 2
#define DBG_LT3 3
#define DBG_LT4 4

#ifdef __cplusplus
extern "C"
{
#endif

  /* hwcdrv api */
  typedef struct
  {
    int (*hwcdrv_init)(hwcfuncs_abort_fn_t abort_ftn, int * tsd_sz);
    /* Initialize hwc counter library (do not call again after fork)
	 Must be called before other functions.
       Input:
	 <abort_ftn>: NULL or callback function to be used for fatal errors
	 <tsd_sz>: If not NULL, returns size in bytes required for thread-specific storage
       Return: 0 if successful
     */

    void (*hwcdrv_get_info)(int *cpuver, const char **cciname, uint_t *npics,
			    const char **docref, uint64_t *support);
    /* get info about session
       Input:
	 <cpuver>: if not NULL, returns value of CPC cpu version
	 <cciname>: if not NULL, returns name of CPU
	 <npics>: if not NULL, returns maximum # of HWCs
	 <docref>: if not NULL, returns documentation reference
	 <support>: if not NULL, returns bitmask (see hwcfuncs.h) of hwc support
       Return: 0 if successful, nonzero otherwise
     */

    int (*hwcdrv_enable_mt)(hwcfuncs_tsd_get_fn_t tsd_ftn);
    /* Enables multi-threaded mode (do not need to call again after fork)
       Input:
	 <tsd_ftn>: If <tsd_sz>==0, this parameter is ignored.
		    Otherwise:
		     tsd_ftn() must be able to return a pointer to thread-specific
		     memory of <tsd_sz> bytes.
		     For a given thread, tsd_ftn() must
		     always return the same pointer.
       Return: none
     */

    int (*hwcdrv_get_descriptions)(hwcf_hwc_cb_t *hwc_find_action,
				   hwcf_attr_cb_t *attr_find_action);
    /* Initiate callbacks with all available HWC names and and HWC attributes.
       Input:
	 <hwc_find_action>: if not NULL, will be called once for each HWC
	 <attr_find_action>: if not NULL, will be called once for each attribute
       Return: 0 if successful
	  or a cpc return code upon error
     */

    int (*hwcdrv_assign_regnos)(Hwcentry* entries[], unsigned numctrs);
    /* Assign entries[]->reg_num values as needed by platform
       Input:
	 <entries>: array of counters
	 <numctrs>: number of items in <entries>
       Return: 0 if successful
	  HWCFUNCS_ERROR_HWCINIT if resources unavailable
	  HWCFUNCS_ERROR_HWCARGS if counters were not specified correctly
     */

    int (*hwcdrv_create_counters)(unsigned hwcdef_cnt, Hwcentry *hwcdef);
    /* Create the counters, but don't start them.
	 call this once in main thread to create counters.
       Input:
	 <defcnt>: number of counter definitions.
	 <hwcdef>: counter definitions.
       Return: 0 if successful
	  or a cpc return code upon error
     */

    int (*hwcdrv_start)(void);
    /* Start the counters.
	 call this once in main thread to start counters.
       Return: 0 if successful
	  or a cpc return code upon error
     */

    int (*hwcdrv_overflow)(siginfo_t *si, hwc_event_t *sample,
			   hwc_event_t *lost_samples);
    /* Linux only.  Capture current counter values.
	 This is intended to be called from SIGEMT handler;
       Input:
	 <si>: signal handler context information
	 <sample>: returns non-zero values for counters that overflowed
	 <lost_samples>: returns non-zero values for counters that "lost" counts
       Return: 0 if successful
	  or a cpc return code upon error.
     */

    int (*hwcdrv_read_events)(hwc_event_t *overflow_data,
			      hwc_event_samples_t *sampled_data);
    /* Read current counter values and samples.  Read of samples is destructive.
       Note: hwcdrv_read_events is not supported on Linux.
       <overflow_data>: returns snapshot of counter values
       <sampled_data>: returns sampled data
       Return: 0 if successful
	  HWCFUNCS_ERROR_UNAVAIL if resource unavailable(e.g. called before initted)
	  (other values may be possible)
     */

    int (*hwcdrv_sighlr_restart)(const hwc_event_t* startVals);
    /* Restarts the counters at the given value.
	 This is intended to be called from SIGEMT handler;
       Input:
	 <startVals>: Solaris: new start values.
		      Linux: pointer may be NULL; startVals is ignored.
       Return: 0 if successful
	  or a cpc return code upon error.
     */

    int (*hwcdrv_lwp_suspend)(void);
    /* Attempt to stop counters on this lwp only.
	 hwcdrv_lwp_resume() should be used to restart counters.
       Return: 0 if successful
	  or a cpc return code upon error.
     */

    int (*hwcdrv_lwp_resume)(void);
    /* Attempt to restart counters on this lwp when counters were
	 stopped with hwcdrv_lwp_suspend().
       Return: 0 if successful
	  or a cpc return code upon error.
     */

    int (*hwcdrv_free_counters)(void);
    /* Stops counters on this lwp only and frees resources.
	 This will fail w/ unpredictable results if other lwps's are
	 still running.  After this call returns,
	 hwcdrv_create_counters() may be called with new values.
       Return: 0 if successful
	  or a cpc return code upon error.
     */

    int (*hwcdrv_lwp_init)(void);
    /* per-thread counter init.
	 Solaris: nop.
	 Linux: just after thread creation call this from inside thread
	      to create context and start counters.
       Return: 0 if successful
	  or a perfctr return code upon error
     */

    void (*hwcdrv_lwp_fini)(void);
    /* per-thread counter cleanup.
	 Solaris: nop.
	 Linux: call in each thread upon thread destruction.
     */

    int hwcdrv_init_status;
  } hwcdrv_api_t;

  extern hwcdrv_api_t *get_hwcdrv ();
  extern hwcdrv_api_t *__collector_get_hwcdrv ();
  extern int __collector_hwcfuncs_bind_descriptor (const char *defstring);
  extern Hwcentry **__collector_hwcfuncs_get_ctrs (unsigned *defcnt);
  extern hwcdrv_api_t *hwcdrv_drivers[]; // array of available drivers

  /* prototypes for internal use by hwcdrv drivers */
  typedef struct
  { // see hwcdrv_get_info() for field definitions
    int cpcN_cpuver;
    uint_t cpcN_npics;
    const char *cpcN_docref;
    const char *cpcN_cciname;
  } hwcdrv_about_t;

  extern int hwcdrv_assign_all_regnos (Hwcentry* entries[], unsigned numctrs);
  /* assign user's counters to specific CPU registers */

  extern int hwcdrv_lookup_cpuver (const char * cpcN_cciname);
  /* returns hwc_cpus.h ID for a given string. */

  extern void hwcfuncs_int_capture_errmsg (const char *fn, int subcode,
					   const char *fmt, va_list ap);
#define logerr  hwcfuncs_int_logerr

  /*---------------------------------------------------------------------------*/
  /* prototypes for internal use by linux hwcdrv drivers */
#define PERFCTR_FIXED_MAGIC 0x40000000 /* tells perfctr to use intel fixed pmcs */
#define PERFCTR_UMASK_SHIFT 8
#define EXTENDED_EVNUM_2_EVSEL(evnum) \
  ( (((eventsel_t)(evnum) & 0x0f00ULL) << 24) | ((eventsel_t)(evnum) & ~0x0f00ULL) )

  typedef uint64_t eventsel_t;
  extern int  hwcfuncs_get_x86_eventsel (unsigned int regno, const char *int_name,
			     eventsel_t *return_event, uint_t *return_pmc_sel);

  typedef int (hwcdrv_get_events_fn_t) (hwcf_hwc_cb_t *hwc_cb);
  typedef int (hwcdrv_get_eventnum_fn_t) (const char *eventname, uint_t pmc,
					  eventsel_t *eventnum,
					  eventsel_t *valid_umask, uint_t *pmc_sel);
  extern hwcdrv_get_eventnum_fn_t *hwcdrv_get_x86_eventnum;

  typedef struct
  {
    const char * attrname;  // user-visible name of attribute
    int is_inverted;        // nonzero means boolean attribute is inverted
    eventsel_t mask;        // which attribute bits can be set?
    eventsel_t shift;       // how far to shift bits for use in x86 register
  } attr_info_t;
  extern const attr_info_t *perfctr_attrs_table;

  /* hdrv_pcbe api: cpu-specific drivers for Linux */
  typedef struct
  {
    int (*hdrv_pcbe_init)(void);
    uint_t (*hdrv_pcbe_ncounters)(void);
    const char *(*hdrv_pcbe_impl_name)(void);
    const char *(*hdrv_pcbe_cpuref)(void);
    int (*hdrv_pcbe_get_events)(hwcf_hwc_cb_t *hwc_cb);
    int (*hdrv_pcbe_get_eventnum)(const char * eventname, uint_t pmc,
				  eventsel_t *eventnum, eventsel_t *valid_umask,
				  uint_t *pmc_sel);
  } hdrv_pcbe_api_t;

#ifdef __cplusplus
}
#endif

#endif