1  /* Copyright (C) 2021-2023 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      int type;           /* Type of perf_event_attr */
     116      long long config;   /* perf_event_type -specific configuration */
     117      /* the fields above this line are expected, in order, by the tables in hwctable.c */
     118      /* ================================================== */
     119      /* the fields below this line are more flexible */
     120      int sort_order;     /* "tag" to associate experiment record with HWC def */
     121      regno_t *reg_list;  /* if not NULL, legal values for <reg_num> field above */
     122      /* Note: reg_list will be terminated by REGNO_ANY */
     123      /* Max size of array is MAX_PICS */
     124      hrtime_t min_time;  /* target minimum time between overflow events.  0 is off.  See HWCTIME_* macros */
     125      hrtime_t min_time_default; /* if min_time==HWCTIME_AUTO, use this value instead.  0 is off. */
     126      int ref_val;    /* if min_time==HWCTIME_AUTO, use this time.  0 is off. */
     127      int lval, hval; /* temporary to allow DBX to build until dbx glue.cc fixed */
     128    } Hwcentry;
     129  
     130    // Hwcentry.min_time canned values
     131  #define HWCTIME_TBD ((hrtime_t)( -1LL)) /* self-adjusting enabled but nsecs not yet selected */
     132  #define HWCTIME_HI  (   1 * 1000 * 1000LL ) /*   1 msec represented in nsecs */
     133  #define HWCTIME_ON  (  10 * 1000 * 1000LL ) /*  10 msec represented in nsecs */
     134  #define HWCTIME_LO  ( 100 * 1000 * 1000LL ) /* 100 msec represented in nsecs */
     135  
     136  #define HWC_VAL_HI(refVal) (((refVal)/10) + 1)
     137  #define HWC_VAL_ON(refVal) (refVal)
     138  #define HWC_VAL_LO(refVal) (((refVal)*10)/100*100 + 1)  // zero's out lower digits, add 1
     139  #define HWC_VAL_CUSTOM(refVal, targetNanoSec) ((double)(refVal)*(targetNanoSec)/HWCTIME_ON)
     140  
     141  #define HWCENTRY_USES_SAMPLING(h)   ((h)->memop==ABST_EXACT_PEBS_PLUS1)
     142  
     143    extern int hwc_lookup (int forKernel, hrtime_t min_time_default,
     144  			 const char *uname, Hwcentry *list[], unsigned listsz,
     145  			 char **emsg, char **wmsg);
     146    /* Parses counter cmdline string.  Returns counter definitions.
     147     * Input:
     148     *   <forKernel> lookup using which table: 0-collect or 1-er_kernel
     149     *   <min_time_default> minimum nseconds between events if Hwcentry.min_time == HWCTIME_TBD.  0 to disable.
     150     *   <uname> command line HWC definition of format:
     151     *           <ctr_def>...[{','|(whitespace)}<ctr_n_def>] where
     152     *           <ctr_def> == [+]<ctr>[/<reg#>][,<interval>]
     153     *   <list> array of pointers to store counter definitions
     154     *   <listsz> number of elements in <list>
     155     * Returns:
     156     *   Success:
     157     *     Returns number of valid counters in <list> and <list>'s elements
     158     *     will be initialized as follows:
     159     *
     160     *     <list[]->name>:
     161     *       Copy of the <uname> with the following modification:
     162     *         if backtracking is not supported, the + will be removed.
     163     *     <list[]->int_name>:
     164     *       For well-known and convenience ctrs, the internal HWC specification,
     165     *         e.g. BSQ_cache_reference~emask=0x0100.
     166     *       For raw ctrs, this will be a copy of <name>.
     167     *     <list[]->reg_num>:
     168     *       Register number if specified by user or table, REGNO_ANY otherwise.
     169     *     <list[]->metric>:
     170     *       For well-known counters, descriptive name, e.g. "D$ Read Misses".
     171     *       NULL otherwise.
     172     *     <list[]->val>:
     173     *       Overflow value selected by user, default value otherwise.
     174     *     <list[]->timecvt>:
     175     *       Value from tables.
     176     *     <list[]->memop>:
     177     *       If + is selected and backtracking is allowed, value from table.
     178     *       ABST_NONE or ABST_NOPC otherwise.
     179     *
     180     *     It is the responsibility of the caller to free 'name' and 'int_name'.
     181     *     'metric' is a static string and shouldn't be freed.
     182     *     'emsg' will point to NULL
     183     *
     184     *   Failure:
     185     *     Frees all allocated elements.
     186     *     emsg will point to a string with an error message to print
     187     *     returns -1
     188     */
     189  
     190    extern char *hwc_validate_ctrs (int forKernel, Hwcentry *list[], unsigned listsz);
     191    /* Validates that the vector of specified HW counters can be loaded (more-or-less)
     192     *   Some invalid combinations, especially on Linux will not be detected
     193     */
     194  
     195    extern int hwc_get_cpc_cpuver ();
     196    /* Return the cpc_cpuver for this system.  Other possible values:
     197     *   CPUVER_GENERIC=0,           CPU could not be determined, but HWCs are ok.
     198     *   CPUVER_UNDEFINED=-1,        HWCs are not available.
     199     */
     200  
     201    extern char *hwc_get_docref (char *buf, size_t buflen);
     202    /* Return a CPU HWC document reference, or NULL. */
     203  
     204    // TBR
     205    extern char *hwc_get_default_cntrs ();
     206    /* Return a default HW counter string; may be NULL, or zero-length */
     207    /* NULL means none is defined in the table; or zero-length means string defined could not be loaded */
     208  
     209    extern char *hwc_get_default_cntrs2 (int forKernel, int style);
     210    /* like hwc_get_default_cntrs() for style==1 */
     211    /* but allows other styles of formatting as well */
     212    /* deprecate and eventually remove hwc_get_default_cntrs() */
     213  
     214    extern char *hwc_get_orig_default_cntrs ();
     215    /* Get the default HW counter string as set in the table */
     216    /* NULL means none is defined in the table */
     217  
     218    extern void hwc_update_val (Hwcentry *ctr);
     219    /* Check time-based intervals and update Hwcentry.val as needed */
     220  
     221    extern char *hwc_get_cpuname (char *buf, size_t buflen);
     222    /* Return the cpc cpu name for this system, or NULL. */
     223  
     224    extern unsigned hwc_get_max_regs ();
     225    /* Return number of counters registers for this system. */
     226  
     227    extern unsigned hwc_get_max_concurrent (int forKernel);
     228    /* Return the max number of simultaneous counters for this system. */
     229  
     230    extern char **hwc_get_attrs (int forKernel);
     231    /* Return:
     232     *   Array of attributes (strings) supported by this system.
     233     *   Last element in array is null.
     234     *   Array and its elements should NOT be freed by the caller.
     235     */
     236  
     237    extern unsigned hwc_scan_attrs (void (*action)(const char *attr,
     238  						 const char *desc));
     239    /* Scan the HW counter attributes, and call function for each attribute.
     240     * Input:
     241     *   <action>:
     242     *     If NULL, no action is performed, but count is still returned.
     243     *     Otherwise called for each type of attributes, or if none exist,
     244     *       called once with NULL parameter.
     245     * Return: count of times <action> would have been called w/ non-NULL data.
     246     */
     247  
     248    extern Hwcentry *hwc_post_lookup (Hwcentry * pret_ctr, char *uname,
     249  				    char * int_name, int cpc_cpuver);
     250    /* When post-processing a run, look up a Hwcentry for given type of system.
     251     * Input:
     252     *   <pret_ctr>: storage for counter definition
     253     *   <uname>: well-known name, convenience name, or complete HWC defintion.
     254     *   <int_name>: Hwcentry->int_name or NULL for don't care
     255     *   <cpc_cpuver>: version of cpu used for experiment.
     256     * Return:
     257     *   <pret_ctr>'s elements set as follows:
     258     *
     259     *     <pret_ctr->name>:
     260     *       Copy of <uname> with the following modifications:
     261     *         1) + and /<regnum> will be stripped off
     262     *         2) attributes will be sorted and values will shown in hex.
     263     *     <pret_ctr->int_name>:
     264     *       For well-known/convenience counters, the internal HWC specification
     265     *         from the table, e.g. BSQ_cache_reference~emask=0x0100.
     266     *       Otherwise, a copy of <uname>.
     267     *     <pret_ctr->reg_num>:
     268     *       Register number if specified by user or table,
     269     *       REGNO_ANY othewise.
     270     *     <pret_ctr->metric>:
     271     *       For well-known counters, descriptive name, e.g. "D$ Read Misses".
     272     *       NULL otherwise.
     273     *     <pret_ctr->timecvt>:
     274     *       For well-known/convenience/hidden counters, value from table.
     275     *       0 otherwise.
     276     *     <pret_ctr->memop>:
     277     *       For well-known/convenience/hidden counters, value from table.
     278     *       ABST_NONE otherwise.
     279     *     <pret_ctr->sort_order>:
     280     *       Set to 0.
     281     *
     282     *     It is the responsibility of the caller to free 'name' and 'int_name'.
     283     *     'metric' is a static string and shouldn't be freed.
     284     */
     285  
     286    extern Hwcentry **hwc_get_std_ctrs (int forKernel);
     287    /* Return:
     288     *   Array of well-known counters supported by this system.
     289     *   Last element in array will be NULL.
     290     *   Array and its elements should NOT be freed by the caller.
     291     */
     292  
     293    extern unsigned hwc_scan_std_ctrs (void (*action)(const Hwcentry *));
     294    /* Call <action> for each well-known counter.
     295     * Input:
     296     *   <action>:
     297     *     If NULL, no action is performed, but count is still returned.
     298     *     Otherwise called for each type of attributes, or if none exist,
     299     *       called once with NULL parameter.
     300     * Return:
     301     *   Count of times <action> would have been called w/ non-NULL data.
     302     *   If <action> is not NULL, Hwcentry fields will be set as follows:
     303     *     <ctr->name>:
     304     *       HWC alias name, e.g. dcrm.
     305     *     <ctr->int_name>:
     306     *       The internal HWC specification, e.g. BSQ_cache_reference~emask=0x0100.
     307     *     <ctr->reg_num>:
     308     *       Register number if specified by the table, REGNO_ANY otherwise.
     309     *     <ctr->metric>:
     310     *       Descriptive name, e.g. "D$ Read Misses".
     311     *     <ctr->lval>:
     312     *       Low-resolution overflow value.
     313     *     <ctr->val>:
     314     *       Default overflow value.
     315     *     <ctr->hval>:
     316     *       High-resolution overflow value.
     317     *     <ctr->timecvt>:
     318     *       multiplier to convert metric to time, 0 otherwise.
     319     *     <ctr->memop>:
     320     *       ABST_* type for this counter.
     321     *     <ctr->reg_list>:
     322     *       Array of legal <reg_num> values.  Terminated by REGNO_ANY.
     323     *
     324     *     Note: All fields point to static data, none should be freed.
     325     */
     326  
     327    extern Hwcentry **hwc_get_raw_ctrs (int forKernel);
     328    /* Return:
     329     *   Table of raw (not well-known) counters supported by this system.
     330     *   Last element in array will be NULL.
     331     *   Table and its elements should NOT be freed by the caller.
     332     */
     333  
     334    extern unsigned hwc_scan_raw_ctrs (void (*action)(const Hwcentry *));
     335    /* Call <action> for each raw counter.
     336     * Input:
     337     *   <action>:
     338     *     If NULL, no action is performed, but count is still returned.
     339     *     Otherwise called for each type of attributes, or if none exist,
     340     *       called once with NULL parameter.
     341     * Return:
     342     *   Count of times <action> would have been called w/ non-NULL data.
     343     *   If <action> is not NULL, Hwcentry fields will be set as follows:
     344     *     <ctr->name>:
     345     *       HWC raw name without attributes, e.g. BSQ_cache_reference.
     346     *     <ctr->int_name>:
     347     *       NULL.
     348     *     <ctr->metric>:
     349     *       NULL.
     350     *     The remainder of the fields are the same as for
     351     *       hwc_scan_std_ctrs().
     352     *
     353     *     Note: All fields point to static data, none should be freed.
     354     */
     355  
     356    extern void
     357    hwc_usage (int forKernel, const char *cmd, const char *dataspace_msg);
     358    /* Print an i18n'd description of "-h" usage, used by collect and er_kernel.
     359     */
     360  
     361    extern void hwc_usage_f (int forKernel, FILE *f, const char *cmd,
     362  			   const char *dataspace_msg, int show_syntax,
     363  			   int show_short_desc);
     364    /* Print an i18n'd description of "-h" usage to a FILE.  Used by GUI. */
     365  
     366    extern char *hwc_rate_string (const Hwcentry *pctr, int force_numeric_format);
     367    /* Returns {"on"|"hi"|"lo"|""|<value>}.  Return value must be freed by caller. */
     368  
     369    extern char *hwc_i18n_metric (const Hwcentry *ctr);
     370    /* Get a basic lable for a counter, properly i18n'd.
     371     *   Note: NOT MT SAFE.
     372     * Examples:
     373     *   CPU Cycles
     374     *   DC_rd Events
     375     * Pseudocode:
     376     *   if(ctr->metric != NULL) {
     377     *	    sprintf(metricbuf, PTXT(ctr->metric) );
     378     *   } else if (ctr->name != NULL) {
     379     *	    sprintf(metricbuf, GTXT("%s Events"), ctr->name );
     380     *   } else if (ctr->int_name != NULL) {
     381     *	    sprintf(metricbuf, GTXT("%s Events"), ctr->int_name );
     382     *   }
     383     * Return: pointer to a buffer containing the above description.
     384     */
     385  
     386    extern char *hwc_hwcentry_string (char *buf, size_t buflen, const Hwcentry *ctr);
     387    /* Get a i18n'd description of a HW counter's options.
     388     *   Examples of well-known counters:
     389     *     cycles[/{0|1}],9999991 ('CPU Cycles', alias for Cycle_cnt; CPU-cycles)
     390     *     dcr[/0],1000003 ('D$ Read Refs', alias for DC_rd; load events)
     391     *   Examples of raw counters:
     392     *     Cycle_cnt[/{0|1}],1000003 (CPU-cycles)
     393     *     DC_rd[/0],1000003 (load events)
     394     * Return: <buf>, filled in.
     395     */
     396  
     397    extern char *hwc_hwcentry_specd_string (char *buf, size_t buflen, const Hwcentry *ctr);
     398    /* Get a i18n'd description of a HW counter's specific configuration.
     399     *   Examples of well-known counters:
     400     *     cycles,9999991 ('CPU Cycles')
     401     *     +dcr/0,1000003 ('D$ Read Refs')
     402     *   Examples of raw counters:
     403     *     Cycle_cnt,1000003
     404     *     +DC_rd/0,1000003
     405     * Return: <buf>, filled in.
     406     */
     407  
     408    extern const char *hwc_memop_string (ABST_type memop);
     409    /* Get a i18n'd description of a variable of type ABST_type.
     410     * Return: pointer to static string.
     411     */
     412  
     413  #ifdef __cplusplus
     414  }
     415  #endif
     416  
     417  #endif