| /* Copyright (C) 2021-2024 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. */ |
| |
| #ifndef _HWCENTRY_H |
| #define _HWCENTRY_H |
| |
| #ifndef LIBCOLLECTOR_SRC /* not running in libcollector */ |
| #include <stdio.h> /* FILE */ |
| #endif /* --- LIBCOLLECTOR_SRC --- */ |
| #include <stdlib.h> /* size_t */ |
| #include "hwc_cpus.h" |
| #include "gp-time.h" |
| |
| #ifdef __cplusplus |
| extern "C" |
| { |
| #endif |
| |
| /* ABS backtrack types */ |
| typedef enum |
| { |
| /* !! Lowest 2 bits are used to indicate load and store, respectively !! */ |
| /* Example: On SPARC, backtrack.c did this: if (ABS_memop & inst_type) ... */ |
| ABST_NONE = 0x0, |
| ABST_LOAD = 0x1, |
| ABST_STORE = 0x2, |
| ABST_LDST = 0x3, |
| ABST_COUNT = 0x4, |
| ABST_US_DTLBM = 0xF, |
| ABST_NOPC = 0x100, |
| ABST_CLKDS = 0x103, // Obsolete |
| ABST_EXACT = 0x203, |
| ABST_LDST_SPARC64 = 0x303, |
| ABST_EXACT_PEBS_PLUS1 = 0x403 |
| /* full description below... */ |
| } ABST_type; |
| |
| #define ABST_PLUS_BY_DEFAULT(n) ((n)==ABST_EXACT || (n)==ABST_EXACT_PEBS_PLUS1) |
| #define ABST_BACKTRACK_ENABLED(n) ((n)!=ABST_NONE && (n)!=ABST_NOPC) |
| #define ABST_MEMSPACE_ENABLED(n) ((n)!=ABST_NONE && (n)!=ABST_NOPC && (n)!=ABST_COUNT) |
| |
| /* ABS determines the type of backtracking available for a particular metric. |
| * Backtracking is enabled with the "+" in "-h +<countername>...". |
| * |
| * When Backtracking is not possible: |
| * |
| * ABST_NONE=0: Either the user did not specify "+", or backtracking |
| * is not applicable to the metric, for example: |
| * clk cycles, |
| * instruct counts (dispatch + branch + prefetch), |
| * i$, |
| * FP ops |
| * ABST_NOPC=0x100 Used for non-program-related external events, for example: |
| * system interface events, |
| * memory controller counters |
| * Of all ABST_type options, only ABST_NOPC prevents hwprofile.c |
| * from recording PC/stack information. |
| * |
| * When backtracking is allowed: |
| * |
| * ABST_LOAD=1: data read events, used with metrics like: |
| * D$, E$, P$ read misses and hits. |
| * [DC+EC+PC]_rd*, Re_*_miss*, |
| * EC_snoop_cb(?) |
| * ABST_STORE=2: data write events, used with metrics like: |
| * D$ writes and write related misses |
| * DC_wr/wr-miss, EC_wb, WC=writecache, Rstall_storeQ |
| * [EC+PC=pcache]_snoop_inv(?), WC_snoop_cb(?), |
| * ABST_LDST=3: data reads/writes, used with metrics like: |
| * E$ references, misses. |
| * ABST_COUNT=4: dedicated assembly instruction: '%hi(0xfc000)' |
| * See SW_count_n metric on sparc. |
| * ABST_US_DTLBM=0xF: for load-store on Sparc -- seems to be used only |
| * for "unskidded DTLB_miss" with DTLB_miss metric. |
| * Checks two adjacent instructions for Data access. |
| * ABST_CLKDS=0x103: data reads/writes, used with Clock-based Dataspace |
| * profiling. Ultrasparc T2 and earlier. |
| * ABST_EXACT=0x203: data reads/writes, precise trap with no skid |
| * ABST_LDST_SPARC64=0x303: Fujitsu SPARC64 load/store |
| * ABST_EXACT_PEBS_PLUS1=0x403: data reads/writes, precise sampling with 1 instr. skid |
| */ |
| |
| /* Hwcentry - structure for defining a counter. |
| * Some fields have different usage when returned from |
| * hwc_lookup(), hwc_post_lookup(), or hwc_scan_*(). |
| * Each function will describe its return values in more detail. |
| */ |
| typedef struct |
| { |
| char *name; /* user HWC specification */ |
| char *int_name; /* internal HWC specification */ |
| regno_t reg_num; /* register in CPU, aka picnum, or REGNO_ANY */ |
| char *metric; /* descriptive name, for well-known counters only */ |
| volatile int val; /* default or actual overflow value */ |
| int timecvt; /* multiplier to convert metric to time, 0 if N/A */ |
| ABST_type memop; /* type of backtracking allowed */ |
| char *short_desc; /* optional one-liner description, or NULL */ |
| /* the fields above this line are expected, in order, by the tables in hwctable.c */ |
| /* ================================================== */ |
| /* the fields below this line are more flexible */ |
| unsigned int use_perf_event_type : 16; /* Set 1 to use two fields below */ |
| unsigned int type : 16; /* Type of perf_event_attr */ |
| long long config; /* perf_event_type -specific configuration */ |
| long long config1; /* perf_event_type -specific configuration */ |
| int sort_order; /* "tag" to associate experiment record with HWC def */ |
| hrtime_t min_time; /* target minimum time between overflow events. 0 is off. See HWCTIME_* macros */ |
| hrtime_t min_time_default; /* if min_time==HWCTIME_AUTO, use this value instead. 0 is off. */ |
| int ref_val; /* if min_time==HWCTIME_AUTO, use this time. 0 is off. */ |
| int lval, hval; /* temporary to allow DBX to build until dbx glue.cc fixed */ |
| } Hwcentry; |
| |
| // Hwcentry.min_time canned values |
| #define HWCTIME_TBD ((hrtime_t)( -1LL)) /* self-adjusting enabled but nsecs not yet selected */ |
| #define HWCTIME_HI ( 1 * 1000 * 1000LL ) /* 1 msec represented in nsecs */ |
| #define HWCTIME_ON ( 10 * 1000 * 1000LL ) /* 10 msec represented in nsecs */ |
| #define HWCTIME_LO ( 100 * 1000 * 1000LL ) /* 100 msec represented in nsecs */ |
| |
| #define HWC_VAL_HI(refVal) (((refVal)/10) + 1) |
| #define HWC_VAL_ON(refVal) (refVal) |
| #define HWC_VAL_LO(refVal) (((refVal)*10)/100*100 + 1) // zero's out lower digits, add 1 |
| #define HWC_VAL_CUSTOM(refVal, targetNanoSec) ((double)(refVal)*(targetNanoSec)/HWCTIME_ON) |
| |
| #define HWCENTRY_USES_SAMPLING(h) ((h)->memop==ABST_EXACT_PEBS_PLUS1) |
| |
| extern int hwc_lookup (int forKernel, hrtime_t min_time_default, |
| const char *uname, Hwcentry *list[], unsigned listsz, |
| char **emsg, char **wmsg); |
| /* Parses counter cmdline string. Returns counter definitions. |
| * Input: |
| * <forKernel> lookup using which table: 0-collect or 1-er_kernel |
| * <min_time_default> minimum nseconds between events if Hwcentry.min_time == HWCTIME_TBD. 0 to disable. |
| * <uname> command line HWC definition of format: |
| * <ctr_def>...[{','|(whitespace)}<ctr_n_def>] where |
| * <ctr_def> == [+]<ctr>[/<reg#>][,<interval>] |
| * <list> array of pointers to store counter definitions |
| * <listsz> number of elements in <list> |
| * Returns: |
| * Success: |
| * Returns number of valid counters in <list> and <list>'s elements |
| * will be initialized as follows: |
| * |
| * <list[]->name>: |
| * Copy of the <uname> with the following modification: |
| * if backtracking is not supported, the + will be removed. |
| * <list[]->int_name>: |
| * For well-known and convenience ctrs, the internal HWC specification, |
| * e.g. BSQ_cache_reference~emask=0x0100. |
| * For raw ctrs, this will be a copy of <name>. |
| * <list[]->reg_num>: |
| * Register number if specified by user or table, REGNO_ANY otherwise. |
| * <list[]->metric>: |
| * For well-known counters, descriptive name, e.g. "D$ Read Misses". |
| * NULL otherwise. |
| * <list[]->val>: |
| * Overflow value selected by user, default value otherwise. |
| * <list[]->timecvt>: |
| * Value from tables. |
| * <list[]->memop>: |
| * If + is selected and backtracking is allowed, value from table. |
| * ABST_NONE or ABST_NOPC otherwise. |
| * |
| * It is the responsibility of the caller to free 'name' and 'int_name'. |
| * 'metric' is a static string and shouldn't be freed. |
| * 'emsg' will point to NULL |
| * |
| * Failure: |
| * Frees all allocated elements. |
| * emsg will point to a string with an error message to print |
| * returns -1 |
| */ |
| |
| extern char *hwc_validate_ctrs (int forKernel, Hwcentry *list[], unsigned listsz); |
| /* Validates that the vector of specified HW counters can be loaded (more-or-less) |
| * Some invalid combinations, especially on Linux will not be detected |
| */ |
| |
| extern int hwc_get_cpc_cpuver (); |
| /* Return the cpc_cpuver for this system. Other possible values: |
| * CPUVER_GENERIC=0, CPU could not be determined, but HWCs are ok. |
| * CPUVER_UNDEFINED=-1, HWCs are not available. |
| */ |
| |
| extern char *hwc_get_docref (char *buf, size_t buflen); |
| /* Return a CPU HWC document reference, or NULL. */ |
| |
| extern char *hwc_get_default_cntrs2 (int forKernel, int style); |
| /* like hwc_get_default_cntrs() for style==1 */ |
| /* but allows other styles of formatting as well */ |
| /* deprecate and eventually remove hwc_get_default_cntrs() */ |
| |
| extern char *hwc_get_orig_default_cntrs (int forKernel); |
| /* Get the default HW counter string as set in the table */ |
| /* NULL means none is defined in the table */ |
| |
| extern void hwc_update_val (Hwcentry *ctr); |
| /* Check time-based intervals and update Hwcentry.val as needed */ |
| |
| extern char *hwc_get_cpuname (char *buf, size_t buflen); |
| /* Return the cpc cpu name for this system, or NULL. */ |
| |
| extern unsigned hwc_get_max_regs (); |
| /* Return number of counters registers for this system. */ |
| |
| extern unsigned hwc_get_max_concurrent (int forKernel); |
| /* Return the max number of simultaneous counters for this system. */ |
| |
| extern char **hwc_get_attrs (int forKernel); |
| /* Return: |
| * Array of attributes (strings) supported by this system. |
| * Last element in array is null. |
| * Array and its elements should NOT be freed by the caller. |
| */ |
| |
| extern unsigned hwc_scan_attrs (void (*action)(const char *attr, |
| const char *desc)); |
| /* Scan the HW counter attributes, and call function for each attribute. |
| * Input: |
| * <action>: |
| * If NULL, no action is performed, but count is still returned. |
| * Otherwise called for each type of attributes, or if none exist, |
| * called once with NULL parameter. |
| * Return: count of times <action> would have been called w/ non-NULL data. |
| */ |
| |
| extern Hwcentry *hwc_post_lookup (Hwcentry * pret_ctr, char *uname, |
| char * int_name, int cpc_cpuver); |
| /* When post-processing a run, look up a Hwcentry for given type of system. |
| * Input: |
| * <pret_ctr>: storage for counter definition |
| * <uname>: well-known name, convenience name, or complete HWC defintion. |
| * <int_name>: Hwcentry->int_name or NULL for don't care |
| * <cpc_cpuver>: version of cpu used for experiment. |
| * Return: |
| * <pret_ctr>'s elements set as follows: |
| * |
| * <pret_ctr->name>: |
| * Copy of <uname> with the following modifications: |
| * 1) + and /<regnum> will be stripped off |
| * 2) attributes will be sorted and values will shown in hex. |
| * <pret_ctr->int_name>: |
| * For well-known/convenience counters, the internal HWC specification |
| * from the table, e.g. BSQ_cache_reference~emask=0x0100. |
| * Otherwise, a copy of <uname>. |
| * <pret_ctr->reg_num>: |
| * Register number if specified by user or table, |
| * REGNO_ANY othewise. |
| * <pret_ctr->metric>: |
| * For well-known counters, descriptive name, e.g. "D$ Read Misses". |
| * NULL otherwise. |
| * <pret_ctr->timecvt>: |
| * For well-known/convenience/hidden counters, value from table. |
| * 0 otherwise. |
| * <pret_ctr->memop>: |
| * For well-known/convenience/hidden counters, value from table. |
| * ABST_NONE otherwise. |
| * <pret_ctr->sort_order>: |
| * Set to 0. |
| * |
| * It is the responsibility of the caller to free 'name' and 'int_name'. |
| * 'metric' is a static string and shouldn't be freed. |
| */ |
| |
| extern Hwcentry **hwc_get_std_ctrs (int forKernel); |
| /* Return: |
| * Array of well-known counters supported by this system. |
| * Last element in array will be NULL. |
| * Array and its elements should NOT be freed by the caller. |
| */ |
| |
| extern unsigned hwc_scan_std_ctrs (void (*action)(const Hwcentry *)); |
| /* Call <action> for each well-known counter. |
| * Input: |
| * <action>: |
| * If NULL, no action is performed, but count is still returned. |
| * Otherwise called for each type of attributes, or if none exist, |
| * called once with NULL parameter. |
| * Return: |
| * Count of times <action> would have been called w/ non-NULL data. |
| * If <action> is not NULL, Hwcentry fields will be set as follows: |
| * <ctr->name>: |
| * HWC alias name, e.g. dcrm. |
| * <ctr->int_name>: |
| * The internal HWC specification, e.g. BSQ_cache_reference~emask=0x0100. |
| * <ctr->reg_num>: |
| * Register number if specified by the table, REGNO_ANY otherwise. |
| * <ctr->metric>: |
| * Descriptive name, e.g. "D$ Read Misses". |
| * <ctr->lval>: |
| * Low-resolution overflow value. |
| * <ctr->val>: |
| * Default overflow value. |
| * <ctr->hval>: |
| * High-resolution overflow value. |
| * <ctr->timecvt>: |
| * multiplier to convert metric to time, 0 otherwise. |
| * <ctr->memop>: |
| * ABST_* type for this counter. |
| * <ctr->reg_list>: |
| * Array of legal <reg_num> values. Terminated by REGNO_ANY. |
| * |
| * Note: All fields point to static data, none should be freed. |
| */ |
| |
| extern Hwcentry **hwc_get_raw_ctrs (int forKernel); |
| /* Return: |
| * Table of raw (not well-known) counters supported by this system. |
| * Last element in array will be NULL. |
| * Table and its elements should NOT be freed by the caller. |
| */ |
| |
| extern unsigned hwc_scan_raw_ctrs (void (*action)(const Hwcentry *)); |
| /* Call <action> for each raw counter. |
| * Input: |
| * <action>: |
| * If NULL, no action is performed, but count is still returned. |
| * Otherwise called for each type of attributes, or if none exist, |
| * called once with NULL parameter. |
| * Return: |
| * Count of times <action> would have been called w/ non-NULL data. |
| * If <action> is not NULL, Hwcentry fields will be set as follows: |
| * <ctr->name>: |
| * HWC raw name without attributes, e.g. BSQ_cache_reference. |
| * <ctr->int_name>: |
| * NULL. |
| * <ctr->metric>: |
| * NULL. |
| * The remainder of the fields are the same as for |
| * hwc_scan_std_ctrs(). |
| * |
| * Note: All fields point to static data, none should be freed. |
| */ |
| |
| extern void |
| hwc_usage (int forKernel, const char *cmd, const char *dataspace_msg); |
| /* Print an i18n'd description of "-h" usage, used by collect and er_kernel. |
| */ |
| |
| extern void hwc_usage_f (int forKernel, FILE *f, const char *cmd, |
| const char *dataspace_msg, int show_syntax, |
| int show_short_desc); |
| /* Print an i18n'd description of "-h" usage to a FILE. Used by GUI. */ |
| |
| extern char *hwc_rate_string (const Hwcentry *pctr, int force_numeric_format); |
| /* Returns {"on"|"hi"|"lo"|""|<value>}. Return value must be freed by caller. */ |
| |
| extern char *hwc_i18n_metric (const Hwcentry *ctr); |
| /* Get a basic lable for a counter, properly i18n'd. |
| * Note: NOT MT SAFE. |
| * Examples: |
| * CPU Cycles |
| * DC_rd Events |
| * Pseudocode: |
| * if(ctr->metric != NULL) { |
| * sprintf(metricbuf, PTXT(ctr->metric) ); |
| * } else if (ctr->name != NULL) { |
| * sprintf(metricbuf, GTXT("%s Events"), ctr->name ); |
| * } else if (ctr->int_name != NULL) { |
| * sprintf(metricbuf, GTXT("%s Events"), ctr->int_name ); |
| * } |
| * Return: pointer to a buffer containing the above description. |
| */ |
| |
| extern char *hwc_hwcentry_string (char *buf, size_t buflen, const Hwcentry *ctr); |
| /* Get a i18n'd description of a HW counter's options. |
| * Examples of well-known counters: |
| * cycles[/{0|1}],9999991 ('CPU Cycles', alias for Cycle_cnt; CPU-cycles) |
| * dcr[/0],1000003 ('D$ Read Refs', alias for DC_rd; load events) |
| * Examples of raw counters: |
| * Cycle_cnt[/{0|1}],1000003 (CPU-cycles) |
| * DC_rd[/0],1000003 (load events) |
| * Return: <buf>, filled in. |
| */ |
| |
| extern char *hwc_hwcentry_specd_string (char *buf, size_t buflen, const Hwcentry *ctr); |
| /* Get a i18n'd description of a HW counter's specific configuration. |
| * Examples of well-known counters: |
| * cycles,9999991 ('CPU Cycles') |
| * +dcr/0,1000003 ('D$ Read Refs') |
| * Examples of raw counters: |
| * Cycle_cnt,1000003 |
| * +DC_rd/0,1000003 |
| * Return: <buf>, filled in. |
| */ |
| |
| extern const char *hwc_memop_string (ABST_type memop); |
| /* Get a i18n'd description of a variable of type ABST_type. |
| * Return: pointer to static string. |
| */ |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif |