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