]>
Commit | Line | Data |
---|---|---|
fd67aa11 | 1 | /* Copyright (C) 2021-2024 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 | #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 */ | |
bb368aad VM |
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 */ | |
8fe04eeb VM |
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 */ | |
bb368aad VM |
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 |