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 driver's header */
      22  
      23  #ifndef __HWCDRV_H
      24  #define __HWCDRV_H
      25  
      26  #include "hwcfuncs.h"
      27  
      28  #ifdef linux
      29  #define HWCFUNCS_SIGNAL         SIGIO
      30  #define HWCFUNCS_SIGNAL_STRING  "SIGIO"
      31  #else
      32  #define HWCFUNCS_SIGNAL         SIGEMT
      33  #define HWCFUNCS_SIGNAL_STRING  "SIGEMT"
      34  #endif
      35  
      36  #ifndef LIBCOLLECTOR_SRC /* not running in libcollector */
      37  #include <string.h>
      38  
      39  #else /* running in libcollector */
      40  #include "collector_module.h"
      41  #include "libcol_util.h"
      42  
      43  #define get_hwcdrv                  __collector_get_hwcdrv
      44  #define hwcdrv_drivers              __collector_hwcdrv_drivers
      45  #define hwcdrv_cpc1_api             __collector_hwcdrv_cpc1_api
      46  #define hwcdrv_cpc2_api             __collector_hwcdrv_cpc2_api
      47  #define hwcdrv_default              __collector_hwcdrv_default
      48  #define hwcdrv_driver               __collector_hwcdrv_driver
      49  #define hwcdrv_init                 __collector_hwcdrv_init
      50  #define hwcdrv_get_info             __collector_hwcdrv_get_info
      51  #define hwcdrv_enable_mt            __collector_hwcdrv_enable_mt
      52  #define hwcdrv_get_descriptions     __collector_hwcdrv_get_descriptions
      53  #define hwcdrv_assign_regnos        __collector_hwcdrv_assign_regnos
      54  #define hwcdrv_create_counters      __collector_hwcdrv_create_counters
      55  #define hwcdrv_start                __collector_hwcdrv_start
      56  #define hwcdrv_overflow             __collector_hwcdrv_overflow
      57  #define hwcdrv_read_events          __collector_hwcdrv_read_events
      58  #define hwcdrv_sighlr_restart       __collector_hwcdrv_sighlr_restart
      59  #define hwcdrv_lwp_suspend          __collector_hwcdrv_lwp_suspend
      60  #define hwcdrv_lwp_resume           __collector_hwcdrv_lwp_resume
      61  #define hwcdrv_free_counters        __collector_hwcdrv_free_counters
      62  #define hwcdrv_lwp_init             __collector_hwcdrv_lwp_init
      63  #define hwcdrv_lwp_fini             __collector_hwcdrv_lwp_fini
      64  #define hwcdrv_assign_all_regnos    __collector_hwcdrv_assign_all_regnos
      65  #define hwcdrv_lookup_cpuver        __collector_hwcdrv_lookup_cpuver
      66  #define hwcfuncs_int_capture_errmsg  __collector_hwcfuncs_int_capture_errmsg
      67  
      68  #define GTXT(x) x
      69  
      70  /* Implemented by libcollector */
      71  #define calloc          __collector_calloc
      72  #define close           CALL_UTIL(close)
      73  #define fcntl           CALL_UTIL(fcntl)
      74  #define fprintf         CALL_UTIL(fprintf)
      75  //#define free            __collector_free
      76  #define free(...)
      77  #define gethrtime       __collector_gethrtime
      78  #define ioctl           CALL_UTIL(ioctl)
      79  #define malloc          __collector_malloc
      80  #define memcpy          __collector_memcpy
      81  #define memset          CALL_UTIL(memset)
      82  #define mmap            CALL_UTIL(mmap)
      83  #define snprintf        CALL_UTIL(snprintf)
      84  #define strchr          CALL_UTIL(strchr)
      85  #define strcmp          CALL_UTIL(strcmp)
      86  #define strncmp         CALL_UTIL(strncmp)
      87  #define strcpy          CALL_UTIL(strcpy)
      88  #define strdup          __collector_strdup
      89  #define strncpy         CALL_UTIL(strncpy)
      90  #define strerror        CALL_UTIL(strerror)
      91  #define strlen          CALL_UTIL(strlen)
      92  #define strstr          CALL_UTIL(strstr)
      93  #define strtol          CALL_UTIL(strtol)
      94  #define strtoll         CALL_UTIL(strtoll)
      95  #define strtoul         CALL_UTIL(strtoul)
      96  #define strtoull        CALL_UTIL(strtoull)
      97  #define syscall         CALL_UTIL(syscall)
      98  #define sysconf         CALL_UTIL(sysconf)
      99  #define vsnprintf       CALL_UTIL(vsnprintf)
     100  
     101  #endif  /* --- LIBCOLLECTOR_SRC --- */
     102  
     103  /* TprintfT(<level>,...) definitions.  Adjust per module as needed */
     104  #define DBG_LT0 0 // for high-level configuration, unexpected errors/warnings
     105  #define DBG_LT1 1 // for configuration details, warnings
     106  #define DBG_LT2 2
     107  #define DBG_LT3 3
     108  #define DBG_LT4 4
     109  
     110  #ifdef __cplusplus
     111  extern "C"
     112  {
     113  #endif
     114  
     115    /* hwcdrv api */
     116    typedef struct
     117    {
     118      int (*hwcdrv_init)(hwcfuncs_abort_fn_t abort_ftn, int * tsd_sz);
     119      /* Initialize hwc counter library (do not call again after fork)
     120  	 Must be called before other functions.
     121         Input:
     122  	 <abort_ftn>: NULL or callback function to be used for fatal errors
     123  	 <tsd_sz>: If not NULL, returns size in bytes required for thread-specific storage
     124         Return: 0 if successful
     125       */
     126  
     127      void (*hwcdrv_get_info)(int *cpuver, const char **cciname, uint_t *npics,
     128  			    const char **docref, uint64_t *support);
     129      /* get info about session
     130         Input:
     131  	 <cpuver>: if not NULL, returns value of CPC cpu version
     132  	 <cciname>: if not NULL, returns name of CPU
     133  	 <npics>: if not NULL, returns maximum # of HWCs
     134  	 <docref>: if not NULL, returns documentation reference
     135  	 <support>: if not NULL, returns bitmask (see hwcfuncs.h) of hwc support
     136         Return: 0 if successful, nonzero otherwise
     137       */
     138  
     139      int (*hwcdrv_enable_mt)(hwcfuncs_tsd_get_fn_t tsd_ftn);
     140      /* Enables multi-threaded mode (do not need to call again after fork)
     141         Input:
     142  	 <tsd_ftn>: If <tsd_sz>==0, this parameter is ignored.
     143  		    Otherwise:
     144  		     tsd_ftn() must be able to return a pointer to thread-specific
     145  		     memory of <tsd_sz> bytes.
     146  		     For a given thread, tsd_ftn() must
     147  		     always return the same pointer.
     148         Return: none
     149       */
     150  
     151      int (*hwcdrv_get_descriptions)(hwcf_hwc_cb_t *hwc_find_action,
     152  				   hwcf_attr_cb_t *attr_find_action);
     153      /* Initiate callbacks with all available HWC names and and HWC attributes.
     154         Input:
     155  	 <hwc_find_action>: if not NULL, will be called once for each HWC
     156  	 <attr_find_action>: if not NULL, will be called once for each attribute
     157         Return: 0 if successful
     158  	  or a cpc return code upon error
     159       */
     160  
     161      int (*hwcdrv_assign_regnos)(Hwcentry* entries[], unsigned numctrs);
     162      /* Assign entries[]->reg_num values as needed by platform
     163         Input:
     164  	 <entries>: array of counters
     165  	 <numctrs>: number of items in <entries>
     166         Return: 0 if successful
     167  	  HWCFUNCS_ERROR_HWCINIT if resources unavailable
     168  	  HWCFUNCS_ERROR_HWCARGS if counters were not specified correctly
     169       */
     170  
     171      int (*hwcdrv_create_counters)(unsigned hwcdef_cnt, Hwcentry *hwcdef);
     172      /* Create the counters, but don't start them.
     173  	 call this once in main thread to create counters.
     174         Input:
     175  	 <defcnt>: number of counter definitions.
     176  	 <hwcdef>: counter definitions.
     177         Return: 0 if successful
     178  	  or a cpc return code upon error
     179       */
     180  
     181      int (*hwcdrv_start)(void);
     182      /* Start the counters.
     183  	 call this once in main thread to start counters.
     184         Return: 0 if successful
     185  	  or a cpc return code upon error
     186       */
     187  
     188      int (*hwcdrv_overflow)(siginfo_t *si, hwc_event_t *sample,
     189  			   hwc_event_t *lost_samples);
     190      /* Linux only.  Capture current counter values.
     191  	 This is intended to be called from SIGEMT handler;
     192         Input:
     193  	 <si>: signal handler context information
     194  	 <sample>: returns non-zero values for counters that overflowed
     195  	 <lost_samples>: returns non-zero values for counters that "lost" counts
     196         Return: 0 if successful
     197  	  or a cpc return code upon error.
     198       */
     199  
     200      int (*hwcdrv_read_events)(hwc_event_t *overflow_data,
     201  			      hwc_event_samples_t *sampled_data);
     202      /* Read current counter values and samples.  Read of samples is destructive.
     203         Note: hwcdrv_read_events is not supported on Linux.
     204         <overflow_data>: returns snapshot of counter values
     205         <sampled_data>: returns sampled data
     206         Return: 0 if successful
     207  	  HWCFUNCS_ERROR_UNAVAIL if resource unavailable(e.g. called before initted)
     208  	  (other values may be possible)
     209       */
     210  
     211      int (*hwcdrv_sighlr_restart)(const hwc_event_t* startVals);
     212      /* Restarts the counters at the given value.
     213  	 This is intended to be called from SIGEMT handler;
     214         Input:
     215  	 <startVals>: Solaris: new start values.
     216  		      Linux: pointer may be NULL; startVals is ignored.
     217         Return: 0 if successful
     218  	  or a cpc return code upon error.
     219       */
     220  
     221      int (*hwcdrv_lwp_suspend)(void);
     222      /* Attempt to stop counters on this lwp only.
     223  	 hwcdrv_lwp_resume() should be used to restart counters.
     224         Return: 0 if successful
     225  	  or a cpc return code upon error.
     226       */
     227  
     228      int (*hwcdrv_lwp_resume)(void);
     229      /* Attempt to restart counters on this lwp when counters were
     230  	 stopped with hwcdrv_lwp_suspend().
     231         Return: 0 if successful
     232  	  or a cpc return code upon error.
     233       */
     234  
     235      int (*hwcdrv_free_counters)(void);
     236      /* Stops counters on this lwp only and frees resources.
     237  	 This will fail w/ unpredictable results if other lwps's are
     238  	 still running.  After this call returns,
     239  	 hwcdrv_create_counters() may be called with new values.
     240         Return: 0 if successful
     241  	  or a cpc return code upon error.
     242       */
     243  
     244      int (*hwcdrv_lwp_init)(void);
     245      /* per-thread counter init.
     246  	 Solaris: nop.
     247  	 Linux: just after thread creation call this from inside thread
     248  	      to create context and start counters.
     249         Return: 0 if successful
     250  	  or a perfctr return code upon error
     251       */
     252  
     253      void (*hwcdrv_lwp_fini)(void);
     254      /* per-thread counter cleanup.
     255  	 Solaris: nop.
     256  	 Linux: call in each thread upon thread destruction.
     257       */
     258  
     259      int hwcdrv_init_status;
     260    } hwcdrv_api_t;
     261  
     262    extern hwcdrv_api_t *get_hwcdrv ();
     263    extern hwcdrv_api_t *__collector_get_hwcdrv ();
     264    extern int __collector_hwcfuncs_bind_descriptor (const char *defstring);
     265    extern Hwcentry **__collector_hwcfuncs_get_ctrs (unsigned *defcnt);
     266    extern hwcdrv_api_t *hwcdrv_drivers[]; // array of available drivers
     267  
     268    /* prototypes for internal use by hwcdrv drivers */
     269    typedef struct
     270    { // see hwcdrv_get_info() for field definitions
     271      int cpcN_cpuver;
     272      uint_t cpcN_npics;
     273      const char *cpcN_docref;
     274      const char *cpcN_cciname;
     275    } hwcdrv_about_t;
     276  
     277    extern int hwcdrv_assign_all_regnos (Hwcentry* entries[], unsigned numctrs);
     278    /* assign user's counters to specific CPU registers */
     279  
     280    extern int hwcdrv_lookup_cpuver (const char * cpcN_cciname);
     281    /* returns hwc_cpus.h ID for a given string. */
     282  
     283    extern void hwcfuncs_int_capture_errmsg (const char *fn, int subcode,
     284  					   const char *fmt, va_list ap);
     285  #define logerr  hwcfuncs_int_logerr
     286  
     287    /*---------------------------------------------------------------------------*/
     288    /* prototypes for internal use by linux hwcdrv drivers */
     289  #define PERFCTR_FIXED_MAGIC 0x40000000 /* tells perfctr to use intel fixed pmcs */
     290  #define PERFCTR_UMASK_SHIFT 8
     291  #define EXTENDED_EVNUM_2_EVSEL(evnum) \
     292    ( (((eventsel_t)(evnum) & 0x0f00ULL) << 24) | ((eventsel_t)(evnum) & ~0x0f00ULL) )
     293  
     294    typedef uint64_t eventsel_t;
     295    extern int  hwcfuncs_get_x86_eventsel (unsigned int regno, const char *int_name,
     296  			     eventsel_t *return_event, uint_t *return_pmc_sel);
     297  
     298    typedef int (hwcdrv_get_events_fn_t) (hwcf_hwc_cb_t *hwc_cb);
     299    typedef int (hwcdrv_get_eventnum_fn_t) (const char *eventname, uint_t pmc,
     300  					  eventsel_t *eventnum,
     301  					  eventsel_t *valid_umask, uint_t *pmc_sel);
     302    extern hwcdrv_get_eventnum_fn_t *hwcdrv_get_x86_eventnum;
     303  
     304    typedef struct
     305    {
     306      const char * attrname;  // user-visible name of attribute
     307      int is_inverted;        // nonzero means boolean attribute is inverted
     308      eventsel_t mask;        // which attribute bits can be set?
     309      eventsel_t shift;       // how far to shift bits for use in x86 register
     310    } attr_info_t;
     311    extern const attr_info_t *perfctr_attrs_table;
     312  
     313    /* hdrv_pcbe api: cpu-specific drivers for Linux */
     314    typedef struct
     315    {
     316      int (*hdrv_pcbe_init)(void);
     317      uint_t (*hdrv_pcbe_ncounters)(void);
     318      const char *(*hdrv_pcbe_impl_name)(void);
     319      const char *(*hdrv_pcbe_cpuref)(void);
     320      int (*hdrv_pcbe_get_events)(hwcf_hwc_cb_t *hwc_cb);
     321      int (*hdrv_pcbe_get_eventnum)(const char * eventname, uint_t pmc,
     322  				  eventsel_t *eventnum, eventsel_t *valid_umask,
     323  				  uint_t *pmc_sel);
     324    } hdrv_pcbe_api_t;
     325  
     326  #ifdef __cplusplus
     327  }
     328  #endif
     329  
     330  #endif