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 #ifndef _HWCENTRY_H 22 #define _HWCENTRY_H 23 24 #ifndef LIBCOLLECTOR_SRC /* not running in libcollector */ 25 #include <stdio.h> /* FILE */ 26 #endif /* --- LIBCOLLECTOR_SRC --- */ 27 #include <stdlib.h> /* size_t */ 28 #include "hwc_cpus.h" 29 #include "gp-time.h" 30 31 #ifdef __cplusplus 32 extern "C" 33 { 34 #endif 35 36 /* ABS backtrack types */ 37 typedef enum 38 { 39 /* !! Lowest 2 bits are used to indicate load and store, respectively !! */ 40 /* Example: On SPARC, backtrack.c did this: if (ABS_memop & inst_type) ... */ 41 ABST_NONE = 0x0, 42 ABST_LOAD = 0x1, 43 ABST_STORE = 0x2, 44 ABST_LDST = 0x3, 45 ABST_COUNT = 0x4, 46 ABST_US_DTLBM = 0xF, 47 ABST_NOPC = 0x100, 48 ABST_CLKDS = 0x103, // Obsolete 49 ABST_EXACT = 0x203, 50 ABST_LDST_SPARC64 = 0x303, 51 ABST_EXACT_PEBS_PLUS1 = 0x403 52 /* full description below... */ 53 } ABST_type; 54 55 #define ABST_PLUS_BY_DEFAULT(n) ((n)==ABST_EXACT || (n)==ABST_EXACT_PEBS_PLUS1) 56 #define ABST_BACKTRACK_ENABLED(n) ((n)!=ABST_NONE && (n)!=ABST_NOPC) 57 #define ABST_MEMSPACE_ENABLED(n) ((n)!=ABST_NONE && (n)!=ABST_NOPC && (n)!=ABST_COUNT) 58 59 /* ABS determines the type of backtracking available for a particular metric. 60 * Backtracking is enabled with the "+" in "-h +<countername>...". 61 * 62 * When Backtracking is not possible: 63 * 64 * ABST_NONE=0: Either the user did not specify "+", or backtracking 65 * is not applicable to the metric, for example: 66 * clk cycles, 67 * instruct counts (dispatch + branch + prefetch), 68 * i$, 69 * FP ops 70 * ABST_NOPC=0x100 Used for non-program-related external events, for example: 71 * system interface events, 72 * memory controller counters 73 * Of all ABST_type options, only ABST_NOPC prevents hwprofile.c 74 * from recording PC/stack information. 75 * 76 * When backtracking is allowed: 77 * 78 * ABST_LOAD=1: data read events, used with metrics like: 79 * D$, E$, P$ read misses and hits. 80 * [DC+EC+PC]_rd*, Re_*_miss*, 81 * EC_snoop_cb(?) 82 * ABST_STORE=2: data write events, used with metrics like: 83 * D$ writes and write related misses 84 * DC_wr/wr-miss, EC_wb, WC=writecache, Rstall_storeQ 85 * [EC+PC=pcache]_snoop_inv(?), WC_snoop_cb(?), 86 * ABST_LDST=3: data reads/writes, used with metrics like: 87 * E$ references, misses. 88 * ABST_COUNT=4: dedicated assembly instruction: '%hi(0xfc000)' 89 * See SW_count_n metric on sparc. 90 * ABST_US_DTLBM=0xF: for load-store on Sparc -- seems to be used only 91 * for "unskidded DTLB_miss" with DTLB_miss metric. 92 * Checks two adjacent instructions for Data access. 93 * ABST_CLKDS=0x103: data reads/writes, used with Clock-based Dataspace 94 * profiling. Ultrasparc T2 and earlier. 95 * ABST_EXACT=0x203: data reads/writes, precise trap with no skid 96 * ABST_LDST_SPARC64=0x303: Fujitsu SPARC64 load/store 97 * ABST_EXACT_PEBS_PLUS1=0x403: data reads/writes, precise sampling with 1 instr. skid 98 */ 99 100 /* Hwcentry - structure for defining a counter. 101 * Some fields have different usage when returned from 102 * hwc_lookup(), hwc_post_lookup(), or hwc_scan_*(). 103 * Each function will describe its return values in more detail. 104 */ 105 typedef struct 106 { 107 char *name; /* user HWC specification */ 108 char *int_name; /* internal HWC specification */ 109 regno_t reg_num; /* register in CPU, aka picnum, or REGNO_ANY */ 110 char *metric; /* descriptive name, for well-known counters only */ 111 volatile int val; /* default or actual overflow value */ 112 int timecvt; /* multiplier to convert metric to time, 0 if N/A */ 113 ABST_type memop; /* type of backtracking allowed */ 114 char *short_desc; /* optional one-liner description, or NULL */ 115 /* the fields above this line are expected, in order, by the tables in hwctable.c */ 116 /* ================================================== */ 117 /* the fields below this line are more flexible */ 118 unsigned int use_perf_event_type : 16; /* Set 1 to use two fields below */ 119 unsigned int type : 16; /* Type of perf_event_attr */ 120 long long config; /* perf_event_type -specific configuration */ 121 int sort_order; /* "tag" to associate experiment record with HWC def */ 122 regno_t *reg_list; /* if not NULL, legal values for <reg_num> field above */ 123 /* Note: reg_list will be terminated by REGNO_ANY */ 124 /* Max size of array is MAX_PICS */ 125 hrtime_t min_time; /* target minimum time between overflow events. 0 is off. See HWCTIME_* macros */ 126 hrtime_t min_time_default; /* if min_time==HWCTIME_AUTO, use this value instead. 0 is off. */ 127 int ref_val; /* if min_time==HWCTIME_AUTO, use this time. 0 is off. */ 128 int lval, hval; /* temporary to allow DBX to build until dbx glue.cc fixed */ 129 } Hwcentry; 130 131 // Hwcentry.min_time canned values 132 #define HWCTIME_TBD ((hrtime_t)( -1LL)) /* self-adjusting enabled but nsecs not yet selected */ 133 #define HWCTIME_HI ( 1 * 1000 * 1000LL ) /* 1 msec represented in nsecs */ 134 #define HWCTIME_ON ( 10 * 1000 * 1000LL ) /* 10 msec represented in nsecs */ 135 #define HWCTIME_LO ( 100 * 1000 * 1000LL ) /* 100 msec represented in nsecs */ 136 137 #define HWC_VAL_HI(refVal) (((refVal)/10) + 1) 138 #define HWC_VAL_ON(refVal) (refVal) 139 #define HWC_VAL_LO(refVal) (((refVal)*10)/100*100 + 1) // zero's out lower digits, add 1 140 #define HWC_VAL_CUSTOM(refVal, targetNanoSec) ((double)(refVal)*(targetNanoSec)/HWCTIME_ON) 141 142 #define HWCENTRY_USES_SAMPLING(h) ((h)->memop==ABST_EXACT_PEBS_PLUS1) 143 144 extern int hwc_lookup (int forKernel, hrtime_t min_time_default, 145 const char *uname, Hwcentry *list[], unsigned listsz, 146 char **emsg, char **wmsg); 147 /* Parses counter cmdline string. Returns counter definitions. 148 * Input: 149 * <forKernel> lookup using which table: 0-collect or 1-er_kernel 150 * <min_time_default> minimum nseconds between events if Hwcentry.min_time == HWCTIME_TBD. 0 to disable. 151 * <uname> command line HWC definition of format: 152 * <ctr_def>...[{','|(whitespace)}<ctr_n_def>] where 153 * <ctr_def> == [+]<ctr>[/<reg#>][,<interval>] 154 * <list> array of pointers to store counter definitions 155 * <listsz> number of elements in <list> 156 * Returns: 157 * Success: 158 * Returns number of valid counters in <list> and <list>'s elements 159 * will be initialized as follows: 160 * 161 * <list[]->name>: 162 * Copy of the <uname> with the following modification: 163 * if backtracking is not supported, the + will be removed. 164 * <list[]->int_name>: 165 * For well-known and convenience ctrs, the internal HWC specification, 166 * e.g. BSQ_cache_reference~emask=0x0100. 167 * For raw ctrs, this will be a copy of <name>. 168 * <list[]->reg_num>: 169 * Register number if specified by user or table, REGNO_ANY otherwise. 170 * <list[]->metric>: 171 * For well-known counters, descriptive name, e.g. "D$ Read Misses". 172 * NULL otherwise. 173 * <list[]->val>: 174 * Overflow value selected by user, default value otherwise. 175 * <list[]->timecvt>: 176 * Value from tables. 177 * <list[]->memop>: 178 * If + is selected and backtracking is allowed, value from table. 179 * ABST_NONE or ABST_NOPC otherwise. 180 * 181 * It is the responsibility of the caller to free 'name' and 'int_name'. 182 * 'metric' is a static string and shouldn't be freed. 183 * 'emsg' will point to NULL 184 * 185 * Failure: 186 * Frees all allocated elements. 187 * emsg will point to a string with an error message to print 188 * returns -1 189 */ 190 191 extern char *hwc_validate_ctrs (int forKernel, Hwcentry *list[], unsigned listsz); 192 /* Validates that the vector of specified HW counters can be loaded (more-or-less) 193 * Some invalid combinations, especially on Linux will not be detected 194 */ 195 196 extern int hwc_get_cpc_cpuver (); 197 /* Return the cpc_cpuver for this system. Other possible values: 198 * CPUVER_GENERIC=0, CPU could not be determined, but HWCs are ok. 199 * CPUVER_UNDEFINED=-1, HWCs are not available. 200 */ 201 202 extern char *hwc_get_docref (char *buf, size_t buflen); 203 /* Return a CPU HWC document reference, or NULL. */ 204 205 // TBR 206 extern char *hwc_get_default_cntrs (); 207 /* Return a default HW counter string; may be NULL, or zero-length */ 208 /* NULL means none is defined in the table; or zero-length means string defined could not be loaded */ 209 210 extern char *hwc_get_default_cntrs2 (int forKernel, int style); 211 /* like hwc_get_default_cntrs() for style==1 */ 212 /* but allows other styles of formatting as well */ 213 /* deprecate and eventually remove hwc_get_default_cntrs() */ 214 215 extern char *hwc_get_orig_default_cntrs (); 216 /* Get the default HW counter string as set in the table */ 217 /* NULL means none is defined in the table */ 218 219 extern void hwc_update_val (Hwcentry *ctr); 220 /* Check time-based intervals and update Hwcentry.val as needed */ 221 222 extern char *hwc_get_cpuname (char *buf, size_t buflen); 223 /* Return the cpc cpu name for this system, or NULL. */ 224 225 extern unsigned hwc_get_max_regs (); 226 /* Return number of counters registers for this system. */ 227 228 extern unsigned hwc_get_max_concurrent (int forKernel); 229 /* Return the max number of simultaneous counters for this system. */ 230 231 extern char **hwc_get_attrs (int forKernel); 232 /* Return: 233 * Array of attributes (strings) supported by this system. 234 * Last element in array is null. 235 * Array and its elements should NOT be freed by the caller. 236 */ 237 238 extern unsigned hwc_scan_attrs (void (*action)(const char *attr, 239 const char *desc)); 240 /* Scan the HW counter attributes, and call function for each attribute. 241 * Input: 242 * <action>: 243 * If NULL, no action is performed, but count is still returned. 244 * Otherwise called for each type of attributes, or if none exist, 245 * called once with NULL parameter. 246 * Return: count of times <action> would have been called w/ non-NULL data. 247 */ 248 249 extern Hwcentry *hwc_post_lookup (Hwcentry * pret_ctr, char *uname, 250 char * int_name, int cpc_cpuver); 251 /* When post-processing a run, look up a Hwcentry for given type of system. 252 * Input: 253 * <pret_ctr>: storage for counter definition 254 * <uname>: well-known name, convenience name, or complete HWC defintion. 255 * <int_name>: Hwcentry->int_name or NULL for don't care 256 * <cpc_cpuver>: version of cpu used for experiment. 257 * Return: 258 * <pret_ctr>'s elements set as follows: 259 * 260 * <pret_ctr->name>: 261 * Copy of <uname> with the following modifications: 262 * 1) + and /<regnum> will be stripped off 263 * 2) attributes will be sorted and values will shown in hex. 264 * <pret_ctr->int_name>: 265 * For well-known/convenience counters, the internal HWC specification 266 * from the table, e.g. BSQ_cache_reference~emask=0x0100. 267 * Otherwise, a copy of <uname>. 268 * <pret_ctr->reg_num>: 269 * Register number if specified by user or table, 270 * REGNO_ANY othewise. 271 * <pret_ctr->metric>: 272 * For well-known counters, descriptive name, e.g. "D$ Read Misses". 273 * NULL otherwise. 274 * <pret_ctr->timecvt>: 275 * For well-known/convenience/hidden counters, value from table. 276 * 0 otherwise. 277 * <pret_ctr->memop>: 278 * For well-known/convenience/hidden counters, value from table. 279 * ABST_NONE otherwise. 280 * <pret_ctr->sort_order>: 281 * Set to 0. 282 * 283 * It is the responsibility of the caller to free 'name' and 'int_name'. 284 * 'metric' is a static string and shouldn't be freed. 285 */ 286 287 extern Hwcentry **hwc_get_std_ctrs (int forKernel); 288 /* Return: 289 * Array of well-known counters supported by this system. 290 * Last element in array will be NULL. 291 * Array and its elements should NOT be freed by the caller. 292 */ 293 294 extern unsigned hwc_scan_std_ctrs (void (*action)(const Hwcentry *)); 295 /* Call <action> for each well-known counter. 296 * Input: 297 * <action>: 298 * If NULL, no action is performed, but count is still returned. 299 * Otherwise called for each type of attributes, or if none exist, 300 * called once with NULL parameter. 301 * Return: 302 * Count of times <action> would have been called w/ non-NULL data. 303 * If <action> is not NULL, Hwcentry fields will be set as follows: 304 * <ctr->name>: 305 * HWC alias name, e.g. dcrm. 306 * <ctr->int_name>: 307 * The internal HWC specification, e.g. BSQ_cache_reference~emask=0x0100. 308 * <ctr->reg_num>: 309 * Register number if specified by the table, REGNO_ANY otherwise. 310 * <ctr->metric>: 311 * Descriptive name, e.g. "D$ Read Misses". 312 * <ctr->lval>: 313 * Low-resolution overflow value. 314 * <ctr->val>: 315 * Default overflow value. 316 * <ctr->hval>: 317 * High-resolution overflow value. 318 * <ctr->timecvt>: 319 * multiplier to convert metric to time, 0 otherwise. 320 * <ctr->memop>: 321 * ABST_* type for this counter. 322 * <ctr->reg_list>: 323 * Array of legal <reg_num> values. Terminated by REGNO_ANY. 324 * 325 * Note: All fields point to static data, none should be freed. 326 */ 327 328 extern Hwcentry **hwc_get_raw_ctrs (int forKernel); 329 /* Return: 330 * Table of raw (not well-known) counters supported by this system. 331 * Last element in array will be NULL. 332 * Table and its elements should NOT be freed by the caller. 333 */ 334 335 extern unsigned hwc_scan_raw_ctrs (void (*action)(const Hwcentry *)); 336 /* Call <action> for each raw counter. 337 * Input: 338 * <action>: 339 * If NULL, no action is performed, but count is still returned. 340 * Otherwise called for each type of attributes, or if none exist, 341 * called once with NULL parameter. 342 * Return: 343 * Count of times <action> would have been called w/ non-NULL data. 344 * If <action> is not NULL, Hwcentry fields will be set as follows: 345 * <ctr->name>: 346 * HWC raw name without attributes, e.g. BSQ_cache_reference. 347 * <ctr->int_name>: 348 * NULL. 349 * <ctr->metric>: 350 * NULL. 351 * The remainder of the fields are the same as for 352 * hwc_scan_std_ctrs(). 353 * 354 * Note: All fields point to static data, none should be freed. 355 */ 356 357 extern void 358 hwc_usage (int forKernel, const char *cmd, const char *dataspace_msg); 359 /* Print an i18n'd description of "-h" usage, used by collect and er_kernel. 360 */ 361 362 extern void hwc_usage_f (int forKernel, FILE *f, const char *cmd, 363 const char *dataspace_msg, int show_syntax, 364 int show_short_desc); 365 /* Print an i18n'd description of "-h" usage to a FILE. Used by GUI. */ 366 367 extern char *hwc_rate_string (const Hwcentry *pctr, int force_numeric_format); 368 /* Returns {"on"|"hi"|"lo"|""|<value>}. Return value must be freed by caller. */ 369 370 extern char *hwc_i18n_metric (const Hwcentry *ctr); 371 /* Get a basic lable for a counter, properly i18n'd. 372 * Note: NOT MT SAFE. 373 * Examples: 374 * CPU Cycles 375 * DC_rd Events 376 * Pseudocode: 377 * if(ctr->metric != NULL) { 378 * sprintf(metricbuf, PTXT(ctr->metric) ); 379 * } else if (ctr->name != NULL) { 380 * sprintf(metricbuf, GTXT("%s Events"), ctr->name ); 381 * } else if (ctr->int_name != NULL) { 382 * sprintf(metricbuf, GTXT("%s Events"), ctr->int_name ); 383 * } 384 * Return: pointer to a buffer containing the above description. 385 */ 386 387 extern char *hwc_hwcentry_string (char *buf, size_t buflen, const Hwcentry *ctr); 388 /* Get a i18n'd description of a HW counter's options. 389 * Examples of well-known counters: 390 * cycles[/{0|1}],9999991 ('CPU Cycles', alias for Cycle_cnt; CPU-cycles) 391 * dcr[/0],1000003 ('D$ Read Refs', alias for DC_rd; load events) 392 * Examples of raw counters: 393 * Cycle_cnt[/{0|1}],1000003 (CPU-cycles) 394 * DC_rd[/0],1000003 (load events) 395 * Return: <buf>, filled in. 396 */ 397 398 extern char *hwc_hwcentry_specd_string (char *buf, size_t buflen, const Hwcentry *ctr); 399 /* Get a i18n'd description of a HW counter's specific configuration. 400 * Examples of well-known counters: 401 * cycles,9999991 ('CPU Cycles') 402 * +dcr/0,1000003 ('D$ Read Refs') 403 * Examples of raw counters: 404 * Cycle_cnt,1000003 405 * +DC_rd/0,1000003 406 * Return: <buf>, filled in. 407 */ 408 409 extern const char *hwc_memop_string (ABST_type memop); 410 /* Get a i18n'd description of a variable of type ABST_type. 411 * Return: pointer to static string. 412 */ 413 414 #ifdef __cplusplus 415 } 416 #endif 417 418 #endif 419