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  /* Hardware counter profiling */
      22  
      23  #ifndef __HWCFUNCS_H
      24  #define __HWCFUNCS_H
      25  
      26  #ifdef LIBCOLLECTOR_SRC /* running in libcollector */
      27  #define hwcfuncs_int_logerr         __collector_hwcfuncs_int_logerr
      28  #define hwcfuncs_parse_ctr          __collector_hwcfuncs_parse_ctr
      29  #define hwcfuncs_parse_attrs        __collector_hwcfuncs_parse_attrs
      30  #define hwcfuncs_bind_descriptor    __collector_hwcfuncs_bind_descriptor
      31  #define hwcfuncs_bind_hwcentry      __collector_hwcfuncs_bind_hwcentry
      32  #define hwcfuncs_assign_regnos      __collector_hwcfuncs_assign_regnos
      33  #define regno_is_valid              __collector_regno_is_valid
      34  #define hwcfuncs_get_ctrs           __collector_hwcfuncs_get_ctrs
      35  #define hwcfuncs_errmsg_get         __collector_hwcfuncs_errmsg_get
      36  #endif  /* --- LIBCOLLECTOR_SRC --- */
      37  
      38  #include <signal.h>     /* siginfo_t */
      39  #include <limits.h>     /* UINT64_t */
      40  #include <sys/types.h>
      41  #include <stdint.h>
      42  
      43  #include "hwcentry.h"   /* for Hwcentry type */
      44  #include "gp-time.h"
      45  
      46  typedef unsigned int uint_t;
      47  
      48  #ifdef	__cplusplus
      49  extern "C" {
      50  #endif
      51  
      52  /*---------------------------------------------------------------------------*/
      53  /* compile options */
      54  
      55  #define HWC_DEBUG   0 /* 0/1 to enable extra HWC debug */
      56  
      57  /*---------------------------------------------------------------------------*/
      58  /* typedefs */
      59  /* generic hw event */
      60    typedef struct _hwc_event_t
      61    { /* generalized counter event */
      62      hrtime_t ce_hrt;            /* gethrtime() */
      63      uint64_t ce_pic[MAX_PICS];  /* counter samples or start values */
      64    } hwc_event_t;
      65  
      66    /* supplementary data that accompanies some hw events */
      67    typedef struct
      68    { /* supplementary data fields */
      69      uint64_t smpl_pc;           /* pc related to event */
      70      uint64_t smpl_data_source;  /* chip-specific data source encoding */
      71      uint64_t smpl_latency;      /* latency related to event */
      72      uint64_t smpl_mem_addr;     /* memory address related to event */
      73    } hwc_sample_t;
      74  #define HWCFUNCS_INVALID_U64 0xFEEDBEEFDEADBEEFllu /* identifies fields as unused */
      75  
      76  typedef struct {                                /* supplementary data fields */
      77      hwc_sample_t sample[MAX_PICS];  /* counter samples or start values */
      78  } hwc_event_samples_t;
      79  
      80  #define HWCFUNCS_SAMPLE_RESET(sample) \
      81  	do { \
      82  	    (sample)->smpl_pc          =HWCFUNCS_INVALID_U64; \
      83  	    (sample)->smpl_data_source =HWCFUNCS_INVALID_U64; \
      84  	    (sample)->smpl_latency     =HWCFUNCS_INVALID_U64; \
      85  	    (sample)->smpl_mem_addr    =HWCFUNCS_INVALID_U64; \
      86  	} while(0)
      87  
      88  #define HWCFUNCS_SAMPLE_IS_RESET(sample) \
      89  	( \
      90  	    (sample)->smpl_pc         ==HWCFUNCS_INVALID_U64 && \
      91  	    (sample)->smpl_data_source==HWCFUNCS_INVALID_U64 && \
      92  	    (sample)->smpl_latency    ==HWCFUNCS_INVALID_U64 && \
      93  	    (sample)->smpl_mem_addr   ==HWCFUNCS_INVALID_U64 \
      94  	)
      95  
      96  /*---------------------------------------------------------------------------*/
      97  /* macros */
      98  
      99  #define HW_INTERVAL_MAX         UINT64_MAX
     100  #define HW_INTERVAL_PRESET(x)   (HW_INTERVAL_MAX - ((uint64_t)(x) - 1))
     101  #define HW_INTERVAL_TYPE(x)     ((uint64_t) (x)
     102  
     103  /* parsing */
     104  #define HWCFUNCS_MAX_ATTRS              20
     105  #define HWCFUNCS_PARSE_ATTR             '~'
     106  #define HWCFUNCS_PARSE_EQUAL            '='
     107  #define HWCFUNCS_PARSE_BACKTRACK        '+'
     108  #define HWCFUNCS_PARSE_BACKTRACK_OFF    '-'
     109  #define HWCFUNCS_PARSE_REGNUM           '/'
     110  #define HWCFUNCS_PARSE_VALUE            ','
     111  
     112  /* error codes */
     113  #define HWCFUNCS_ERROR_GENERIC          (-1)
     114  #define HWCFUNCS_ERROR_NOT_SUPPORTED    (-2)
     115  #define HWCFUNCS_ERROR_ALREADY_CALLED   (-3)
     116  #define HWCFUNCS_ERROR_HWCINIT          (-4)
     117  #define HWCFUNCS_ERROR_HWCARGS          (-5)
     118  #define HWCFUNCS_ERROR_MEMORY           (-6)
     119  #define HWCFUNCS_ERROR_UNAVAIL          (-7)
     120  #define HWCFUNCS_ERROR_ERRNO_ZERO       (-8)
     121  #define HWCFUNCS_ERROR_UNEXPECTED       (-99)
     122  
     123  /*---------------------------------------------------------------------------*/
     124  /* prototypes */
     125  
     126  typedef void (*hwcfuncs_abort_fn_t) (int errnum, const char *msg);
     127  
     128  extern void hwcfuncs_int_logerr(const char *format,...);
     129  /* Log an error to the internal error buffer. See hwcfuncs_errmsg_get().
     130       Note: Not MT-safe; don't even enable logging in an MT environment.
     131         Recommend using this call only during init.
     132       Note: when a libcpc call fails, it may automatically call
     133         cpcN_capture_errmsg() to log the error message in the same internal buffer.
     134         Recommend using this call only for non-cpc failures.
     135   */
     136  
     137  #define HWCFUNCS_SUPPORT_OVERFLOW_PROFILING 0x01llu
     138  #define HWCFUNCS_SUPPORT_PEBS_SAMPLING      0x02llu
     139  #define HWCFUNCS_SUPPORT_OVERFLOW_CTR_ID    0x04llu // OS identifies which counter overflowed
     140    /* get info about session
     141       Input:
     142         <cpuver>: if not NULL, returns value of CPC cpu version
     143         <cciname>: if not NULL, returns name of CPU
     144         <npics>: if not NULL, returns maximum # of HWCs
     145         <docref>: if not NULL, returns documentation reference
     146         <support>: if not NULL, returns bitmask (see above) of hwc support
     147       Return: none
     148     */
     149  
     150    typedef void* (*hwcfuncs_tsd_get_fn_t) (void);
     151    typedef void (hwcf_hwc_cb_t) (uint_t cpcregno, const char *name);
     152    typedef void (hwcf_attr_cb_t) (const char *attr);
     153  
     154    extern void
     155    hwcfuncs_parse_ctr (const char *counter_def, int *pplus, char **pnameOnly,
     156  		      char **pattrs, char **pregstr, regno_t *pregno);
     157  /* Parse a counter definition string (value must already be stripped off).
     158       Input:
     159         <counter_def>: input whose format is
     160  	 [+|-]<countername>[~attrs...][/<regno>]
     161         pointers to return values:  Any can be NULL.
     162       Return:
     163         <plus>: 1 if [+] is found, -1 if [-] is found, 0 otherwise
     164         <pnameonly>: strdup(<countername>)
     165         <pattrs>: strdup([~attrs...]) if specified, NULL otherwise.
     166         <pregstr>: strdup(/<regno>) if specified, NULL otherwise.
     167         <pregno>: <regno> if readable, REGNO_ANY if not specd, or -2 otherwise.
     168     */
     169  
     170    typedef struct
     171    {
     172      char *ca_name;
     173      uint64_t ca_val;
     174    } hwcfuncs_attr_t; /* matches cpc_attr_t */
     175  
     176    void * hwcfuncs_parse_attrs (const char *countername,
     177  			       hwcfuncs_attr_t attrs[], unsigned max_attrs,
     178  			       uint_t *pnum_attrs, char **errstring);
     179    /* Extract the attribute fields from <countername>.
     180         Input:
     181  	 <countername>: string whose format is
     182  	    [+]<ctrname>[~attributes...][/<regno>][,...]
     183  	 <attrs>: array of attributes to be returned
     184  	 <max_attrs>: number of elements in <attrs>
     185  	 <pnum_attrs>: if not NULL, will return how many attrs were found.
     186  	 <errstring>: pointer to a buffer for storing error info, or NULL.
     187         Return: upon success, a pointer to an allocated copy of <countername>, or
     188  	   NULL if there's a failure.  (A copy is made in order to provide storage
     189  	   for the ca_name fields in the <attrs> array.)
     190  
     191  	   The pointer should be freed when <attrs> is no longer in use.
     192  	   <attrs> will be filled in data from countername.
     193  	 <pnum_attrs> will have the number of elements in <attrs>.  May be
     194  	   non-zero even if return value indicates an error.
     195  	 <errstring> NULL if no error, otherwise, a malloc'd GTXT string.
     196     */
     197  
     198    extern int hwcfuncs_bind_descriptor (const char *defstring);
     199    /* Bind counters to resources.
     200       Input:
     201         <defstring>: string whose format is
     202  	  :%s:%s:0x%x:%d:%d,0x%x[:%s...repeat for each ctr]
     203  	 where the fields are:
     204  	  :<userName>:<internalCtr>:<register>:<timeoutVal>:<tag>:<memop>
     205       Return: 0 if successful
     206  	HWCFUNCS_ERROR_HWCINIT if resources unavailable
     207  	HWCFUNCS_ERROR_HWCARGS if counters were not specified correctly
     208     */
     209  
     210    extern int hwcfuncs_bind_hwcentry (const Hwcentry *entries[],
     211  				     unsigned numctrs);
     212    /* Bind counters to resources.
     213       Input:
     214         <entries>: array of counters
     215         <numctrs>: number of items in <entries>
     216       Return: 0 if successful
     217  	HWCFUNCS_ERROR_HWCINIT if resources unavailable
     218  	HWCFUNCS_ERROR_HWCARGS if counters were not specified correctly
     219     */
     220  
     221    extern int hwcfuncs_assign_regnos (Hwcentry *entries[], unsigned numctrs);
     222    /* Assign entries[]->reg_num values as needed by platform
     223         Note: modifies <entries> by supplying a regno to each counter
     224       Input:
     225         <entries>: array of counters
     226         <numctrs>: number of items in <entries>
     227       Output:
     228         <entries>: array of counters is modified
     229       Return: 0 if successful
     230  	HWCFUNCS_ERROR_HWCINIT if resources unavailable
     231  	HWCFUNCS_ERROR_HWCARGS if counters were not specified correctly
     232     */
     233  
     234    extern int regno_is_valid (const Hwcentry *pctr, regno_t regno);
     235    /* return 1 if <regno> is in Hwcentry's list
     236       Input:
     237         <pctr>: counter definition, reg_list[] should be initialized
     238         <regno>: register to check
     239       Return: 1 if <regno> is in Hwcentry's list, 0 otherwise
     240     */
     241  
     242    extern Hwcentry **hwcfuncs_get_ctrs (unsigned *defcnt);
     243    /* Get descriptions of the currently bound counters.
     244       Input:
     245         <defcnt>: if not NULL, returns number of counter definitions.
     246       Return:
     247         table of counter definition pointers
     248     */
     249  
     250    extern char *hwcfuncs_errmsg_get (char * buf, size_t bufsize,
     251  				    int enable_capture);
     252    /* Gets a recent HWC error message.
     253         To clear previous error messages and insure error message is enabled,
     254         call hwcfuncs_errmsg_get(NULL,0,1).
     255         Once enabled, one error is stored in an internal buffer.  A call to this
     256         function will clear the buffer and allow a new message to be captured.
     257         Note: Not MT-safe - don't enable this feature in an MT environment.
     258       Input:
     259         <buf>: pointer to buffer or NULL.
     260         <bufsize>: size of <buf>
     261         <enable_capture>: 0 - disable buffering, 1 - enable buffering.
     262       Return: error string or an empty string.
     263     */
     264  
     265  #ifdef	__cplusplus
     266  }
     267  #endif
     268  
     269  #endif /* ! __HWCFUNCS_H */