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