diff options
Diffstat (limited to 'gprofng/common/hwcentry.h')
-rw-r--r-- | gprofng/common/hwcentry.h | 417 |
1 files changed, 417 insertions, 0 deletions
diff --git a/gprofng/common/hwcentry.h b/gprofng/common/hwcentry.h new file mode 100644 index 0000000..8611ab7 --- /dev/null +++ b/gprofng/common/hwcentry.h @@ -0,0 +1,417 @@ +/* Copyright (C) 2021 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 */ + int type; /* Type of perf_event_attr */ + long long config; /* perf_event_type -specific configuration */ + /* the fields above this line are expected, in order, by the tables in hwctable.c */ + /* ================================================== */ + /* the fields below this line are more flexible */ + int sort_order; /* "tag" to associate experiment record with HWC def */ + regno_t *reg_list; /* if not NULL, legal values for <reg_num> field above */ + /* Note: reg_list will be terminated by REGNO_ANY */ + /* Max size of array is MAX_PICS */ + 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. */ + + // TBR + extern char *hwc_get_default_cntrs (); + /* Return a default HW counter string; may be NULL, or zero-length */ + /* NULL means none is defined in the table; or zero-length means string defined could not be loaded */ + + 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 (); + /* 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 |