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  #include "config.h"
      24  #include <alloca.h>
      25  #include <dlfcn.h>
      26  #include <stdlib.h>
      27  #include <stdio.h>
      28  #include <unistd.h>
      29  #include <errno.h>
      30  #include <sys/syscall.h>
      31  #include <signal.h>
      32  
      33  #include "gp-defs.h"
      34  #define _STRING_H 1  /* XXX MEZ: temporary workaround */
      35  #include "hwcdrv.h"
      36  #include "collector_module.h"
      37  #include "gp-experiment.h"
      38  #include "libcol_util.h"
      39  #include "hwprofile.h"
      40  #include "ABS.h"
      41  #include "tsd.h"
      42  
      43  /* TprintfT(<level>,...) definitions.  Adjust per module as needed */
      44  #define DBG_LT0 0 // for high-level configuration, unexpected errors/warnings
      45  #define DBG_LT1 1 // for configuration details, warnings
      46  #define DBG_LT2 2
      47  #define DBG_LT3 3
      48  #define DBG_LT4 4
      49  #define DBG_LT5 5
      50  
      51  #define  SD_OFF 0       /* before start or after close she shut down process */
      52  #define  SD_PENDING 1   /* before running real_detach_experiment() */
      53  #define  SD_COMPLETE 2  /* after running real_detach_experiment() */
      54  
      55  static int init_interface (CollectorInterface*);
      56  static int open_experiment (const char *);
      57  static int start_data_collection (void);
      58  static int stop_data_collection (void);
      59  static int close_experiment (void);
      60  static int detach_experiment (void);
      61  static int real_detach_experiment (void);
      62  
      63  static ModuleInterface module_interface ={
      64    SP_HWCNTR_FILE,           /* description */
      65    init_interface,           /* initInterface */
      66    open_experiment,          /* openExperiment */
      67    start_data_collection,    /* startDataCollection */
      68    stop_data_collection,     /* stopDataCollection */
      69    close_experiment,         /* closeExperiment */
      70    detach_experiment         /* detachExperiment (fork child) */
      71  };
      72  
      73  static CollectorInterface *collector_interface = NULL;
      74  
      75  
      76  /*---------------------------------------------------------------------------*/
      77  /* compile options and workarounds */
      78  
      79  /* Solaris: We set ITIMER_REALPROF to ensure that counters get started on
      80   *      LWPs that existed before the collector initialization.
      81   *
      82   * In addition, if the appropriate #define's are set, we check for:
      83   *      lost-hw-overflow -- the HW counters rollover, but the overflow
      84   *	      interrupt is not generated (counters keep running)
      85   *      lost-sigemt -- the interrupt is received by the kernel,
      86   *	      which stops the counters, but the kernel fails
      87   *	      to deliver the signal.
      88   */
      89  
      90  /*---------------------------------------------------------------------------*/
      91  /* typedefs */
      92  
      93  typedef enum {
      94    HWCMODE_OFF,       /* before start or after close */
      95    HWCMODE_SUSPEND,  /* stop_data_collection called */
      96    HWCMODE_ACTIVE,   /* counters are defined and after start_data_collection() */
      97    HWCMODE_ABORT     /* fatal error occured. Log a message, stop recording */
      98  } hwc_mode_t;
      99  
     100  /*---------------------------------------------------------------------------*/
     101  /* prototypes */
     102  static void init_ucontexts (void);
     103  static int hwc_initialize_handlers (void);
     104  static void collector_record_counter (ucontext_t*,
     105  				      int timecvt,
     106  				      ABST_type, hrtime_t,
     107  				      unsigned, uint64_t);
     108  static void collector_hwc_ABORT (int errnum, const char *msg);
     109  static void hwclogwrite0 ();
     110  static void hwclogwrite (Hwcentry *);
     111  static void set_hwc_mode (hwc_mode_t);
     112  static void collector_sigemt_handler (int sig, siginfo_t *si, void *puc);
     113  
     114  /*---------------------------------------------------------------------------*/
     115  /* static variables */
     116  
     117  /* --- user counter selections and options */
     118  static int hwcdef_has_memspace;     /* true to indicate use of extened packets */
     119  static unsigned hwcdef_cnt;         /* number of *active* hardware counters */
     120  static unsigned hwcdef_num_sampling_ctrdefs; /* ctrs that use sampling */
     121  static unsigned hwcdef_num_overflow_ctrdefs; /* ctrs that use overflow */
     122  static Hwcentry **hwcdef;           /* HWC definitions */
     123  static int cpcN_cpuver = CPUVER_UNDEFINED;
     124  static int hwcdrv_inited;           /* Don't call hwcdrv_init() in fork_child */
     125  static hwcdrv_api_t *hwc_driver = NULL;
     126  static unsigned hwprofile_tsd_key = COLLECTOR_TSD_INVALID_KEY;
     127  static int hwprofile_tsd_sz = 0;
     128  static volatile hwc_mode_t hwc_mode = HWCMODE_OFF;
     129  static volatile unsigned int nthreads_in_sighandler = 0;
     130  static volatile unsigned int sd_state = SD_OFF;
     131  
     132  /* --- experiment logging state */
     133  static CollectorModule expr_hndl = COLLECTOR_MODULE_ERR;
     134  static ucontext_t expr_dummy_uc;        // used for hacked "collector" frames
     135  static ucontext_t expr_out_of_range_uc; // used for "out-of-range" frames
     136  static ucontext_t expr_frozen_uc;       // used for "frozen" frames
     137  static ucontext_t expr_nopc_uc;         // used for not-program-related frames
     138  static ucontext_t expr_lostcounts_uc;   // used for lost_counts frames
     139  
     140  /* --- signal handler state */
     141  static struct sigaction old_sigemt_handler;  //overwritten in fork-child
     142  
     143  /*---------------------------------------------------------------------------*/
     144  /* macros */
     145  #define COUNTERS_ENABLED()  (hwcdef_cnt)
     146  #define gethrtime           collector_interface->getHiResTime
     147  
     148  #ifdef DEBUG
     149  #define Tprintf(...)   if (collector_interface) collector_interface->writeDebugInfo( 0, __VA_ARGS__ )
     150  #define TprintfT(...)  if (collector_interface) collector_interface->writeDebugInfo( 1, __VA_ARGS__ )
     151  #else
     152  #define Tprintf(...)
     153  #define TprintfT(...)
     154  #endif
     155  
     156  
     157  /*---------------------------------------------------------------------------*/
     158  
     159  /* Initialization routines */
     160  static hwcdrv_api_t *
     161  get_hwc_driver ()
     162  {
     163    if (hwc_driver == NULL)
     164      hwc_driver = __collector_get_hwcdrv ();
     165    return hwc_driver;
     166  }
     167  
     168  static void init_module () __attribute__ ((constructor));
     169  static void
     170  init_module ()
     171  {
     172    __collector_dlsym_guard = 1;
     173    RegModuleFunc reg_module = (RegModuleFunc) dlsym (RTLD_DEFAULT, "__collector_register_module");
     174    __collector_dlsym_guard = 0;
     175    if (reg_module == NULL)
     176      {
     177        TprintfT (0, "hwprofile: init_module FAILED - reg_module = NULL\n");
     178        return;
     179      }
     180    expr_hndl = reg_module (&module_interface);
     181    if (expr_hndl == COLLECTOR_MODULE_ERR)
     182      {
     183        TprintfT (0, "hwprofile: ERROR: handle not created.\n");
     184        if (collector_interface)
     185  	collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">data handle not created</event>\n",
     186  				       SP_JCMD_CERROR, COL_ERROR_HWCINIT);
     187      }
     188  }
     189  
     190  static int
     191  init_interface (CollectorInterface *_collector_interface)
     192  {
     193    collector_interface = _collector_interface;
     194    return COL_ERROR_NONE;
     195  }
     196  
     197  static void *
     198  hwprofile_get_tsd ()
     199  {
     200    return collector_interface->getKey (hwprofile_tsd_key);
     201  }
     202  
     203  static int
     204  open_experiment (const char *exp)
     205  {
     206    if (collector_interface == NULL)
     207      {
     208        TprintfT (0, "hwprofile: ERROR: collector_interface is null.\n");
     209        return COL_ERROR_HWCINIT;
     210      }
     211    const char *params = collector_interface->getParams ();
     212    while (params)
     213      {
     214        if (__collector_strStartWith (params, "h:*") == 0)
     215  	{
     216  	  /* HWC counters set by default */
     217  	  collector_interface->writeLog ("<%s %s=\"1\"/>\n",
     218  					 SP_TAG_SETTING, SP_JCMD_HWC_DEFAULT);
     219  	  params += 3;
     220  	  break;
     221  	}
     222        else if (__collector_strStartWith (params, "h:") == 0)
     223  	{
     224  	  params += 2;
     225  	  break;
     226  	}
     227        params = CALL_UTIL (strchr)(params, ';');
     228        if (params)
     229  	params++;
     230      }
     231    if (params == NULL)  /* HWC profiling not specified */
     232      return COL_ERROR_HWCINIT;
     233    char *s = CALL_UTIL (strchr)(params, (int) ';');
     234    int sz = s ? s - params : CALL_UTIL (strlen)(params);
     235    char *defstring = (char*) alloca (sz + 1);
     236    CALL_UTIL (strlcpy)(defstring, params, sz + 1);
     237    TprintfT (0, "hwprofile: open_experiment %s -- %s\n", exp, defstring);
     238  
     239    int err = COL_ERROR_NONE;
     240    /* init counter library */
     241    if (!hwcdrv_inited)
     242      { /* do not call hwcdrv_init() from fork-child */
     243        hwcdrv_inited = 1;
     244        get_hwc_driver ();
     245        if (hwc_driver->hwcdrv_init (collector_hwc_ABORT, &hwprofile_tsd_sz) == 0)
     246  	{
     247  	  collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">%s</event>\n",
     248  					 SP_JCMD_CERROR, COL_ERROR_HWCINIT, defstring);
     249  	  TprintfT (0, "hwprofile: ERROR: hwcfuncs_init() failed\n");
     250  	  return COL_ERROR_HWCINIT;
     251  	}
     252  
     253        if (hwc_driver->hwcdrv_enable_mt (hwprofile_get_tsd))
     254  	{
     255  	  // It is OK to call hwcdrv_enable_mt() before tsd key is created
     256  	  collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">%s</event>\n",
     257  					 SP_JCMD_CERROR, COL_ERROR_HWCINIT, defstring);
     258  	  TprintfT (0, "hwprofile: ERROR: hwcdrv_enable_mt() failed\n");
     259  	  return COL_ERROR_HWCINIT;
     260  	}
     261  
     262        hwc_driver->hwcdrv_get_info (&cpcN_cpuver, NULL, NULL, NULL, NULL);
     263        if (cpcN_cpuver < 0)
     264  	{
     265  	  collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">%s</event>\n",
     266  					 SP_JCMD_CERROR, COL_ERROR_HWCINIT, defstring);
     267  	  TprintfT (0, "hwprofile: ERROR: hwcdrv_get_info() failed\n");
     268  	  return COL_ERROR_HWCINIT;
     269  	}
     270      }
     271  
     272    if (hwprofile_tsd_sz)
     273      {
     274        hwprofile_tsd_key = collector_interface->createKey (hwprofile_tsd_sz, NULL, NULL);
     275        if (hwprofile_tsd_key == COLLECTOR_TSD_INVALID_KEY)
     276  	{
     277  	  collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">%s</event>\n",
     278  					 SP_JCMD_CERROR, COL_ERROR_HWCINIT, defstring);
     279  	  TprintfT (0, "hwprofile: ERROR: TSD createKey failed\n");
     280  	  return COL_ERROR_HWCINIT;
     281  	}
     282      }
     283    hwcdef_cnt = 0;
     284    hwcdef_has_memspace = 0;
     285  
     286    /* create counters based on hwcdef[] */
     287    err = __collector_hwcfuncs_bind_descriptor (defstring);
     288    if (err)
     289      {
     290        err = err == HWCFUNCS_ERROR_HWCINIT ? COL_ERROR_HWCINIT : COL_ERROR_HWCARGS;
     291        collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">%s</event>\n",
     292  				     SP_JCMD_CERROR, err, defstring);
     293        TprintfT (0, "hwprofile: ERROR: open_experiment() failed, RC=%d \n", err);
     294        return err;
     295      }
     296  
     297    /* generate an array of counter structures for each requested counter */
     298    hwcdef = __collector_hwcfuncs_get_ctrs (&hwcdef_cnt);
     299    hwcdef_num_sampling_ctrdefs = hwcdef_num_overflow_ctrdefs = 0;
     300    int idx;
     301    for (idx = 0; idx < hwcdef_cnt; idx++)
     302      {
     303        if (HWCENTRY_USES_SAMPLING (hwcdef[idx]))
     304  	{
     305  	  hwcdef_num_sampling_ctrdefs++;
     306  	}
     307        else
     308  	{
     309  	  hwcdef_num_overflow_ctrdefs++;
     310  	}
     311      }
     312  
     313    init_ucontexts ();
     314  
     315    /* initialize the SIGEMT handler, and the periodic HWC checker */
     316    err = hwc_initialize_handlers ();
     317    if (err != COL_ERROR_NONE)
     318      {
     319        hwcdef_cnt = 0;
     320        TprintfT (0, "hwprofile: ERROR: open_experiment() failed, RC=%d \n", err);
     321        /* log written by hwc_initialize_handlers() */
     322        return err;
     323      }
     324  
     325    for (idx = 0; idx < hwcdef_cnt; idx++)
     326      if (ABST_BACKTRACK_ENABLED (hwcdef[idx]->memop))
     327        hwcdef_has_memspace = 1;
     328  
     329    /* record the hwc definitions in the log, based on the counter array */
     330    hwclogwrite0 ();
     331    for (idx = 0; idx < hwcdef_cnt; idx++)
     332      hwclogwrite (hwcdef[idx]);
     333    return COL_ERROR_NONE;
     334  }
     335  
     336  int
     337  __collector_ext_hwc_lwp_init ()
     338  {
     339    return get_hwc_driver ()->hwcdrv_lwp_init ();
     340  }
     341  
     342  void
     343  __collector_ext_hwc_lwp_fini ()
     344  {
     345    get_hwc_driver ()->hwcdrv_lwp_fini ();
     346  }
     347  
     348  int
     349  __collector_ext_hwc_lwp_suspend ()
     350  {
     351    return get_hwc_driver ()->hwcdrv_lwp_suspend ();
     352  }
     353  
     354  int
     355  __collector_ext_hwc_lwp_resume ()
     356  {
     357    return get_hwc_driver ()->hwcdrv_lwp_resume ();
     358  }
     359  
     360  /* Dummy routine, used to provide a context for non-program related profiles */
     361  void
     362  __collector_not_program_related () { }
     363  
     364  /* Dummy routine, used to provide a context for lost counts (perf_events) */
     365  void
     366  __collector_hwc_samples_lost () { }
     367  
     368  /* Dummy routine, used to provide a context */
     369  void
     370  __collector_hwcs_frozen () { }
     371  
     372  /* Dummy routine, used to provide a context */
     373  void
     374  __collector_hwcs_out_of_range () { }
     375  /* initialize some structures */
     376  static void
     377  init_ucontexts (void)
     378  {
     379    /* initialize dummy context for "collector" frames */
     380    CALL_UTIL (getcontext) (&expr_dummy_uc);
     381    SETFUNCTIONCONTEXT (&expr_dummy_uc, NULL);
     382  
     383    /* initialize dummy context for "out-of-range" frames */
     384    CALL_UTIL (getcontext) (&expr_out_of_range_uc);
     385    SETFUNCTIONCONTEXT (&expr_out_of_range_uc, &__collector_hwcs_out_of_range);
     386  
     387    /* initialize dummy context for "frozen" frames */
     388    CALL_UTIL (getcontext) (&expr_frozen_uc);
     389    SETFUNCTIONCONTEXT (&expr_frozen_uc, &__collector_hwcs_frozen);
     390  
     391    /* initialize dummy context for non-program-related frames */
     392    CALL_UTIL (getcontext) (&expr_nopc_uc);
     393    SETFUNCTIONCONTEXT (&expr_nopc_uc, &__collector_not_program_related);
     394  
     395    /* initialize dummy context for lost-counts-related frames */
     396    CALL_UTIL (getcontext) (&expr_lostcounts_uc);
     397    SETFUNCTIONCONTEXT (&expr_lostcounts_uc, &__collector_hwc_samples_lost);
     398  }
     399  /* initialize the signal handler */
     400  static int
     401  hwc_initialize_handlers (void)
     402  {
     403    /* install the signal handler for SIGEMT */
     404    struct sigaction oact;
     405    if (__collector_sigaction (HWCFUNCS_SIGNAL, NULL, &oact) != 0)
     406      {
     407        TprintfT (0, "hwc_initialize_handlers(): ERROR: hwc_initialize_handlers(): __collector_sigaction() failed to get oact\n");
     408        collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">old handler could not be determined</event>\n", SP_JCMD_CERROR, COL_ERROR_HWCINIT);
     409        return COL_ERROR_HWCINIT;
     410      }
     411    if (oact.sa_sigaction == collector_sigemt_handler)
     412      {
     413        /* signal handler is already in place; we are probably in a fork-child */
     414        TprintfT (DBG_LT1, "hwc_initialize_handlers(): hwc_initialize_handlers() collector_sigemt_handler already installed\n");
     415      }
     416    else
     417      {
     418        /* set our signal handler */
     419        struct sigaction c_act;
     420        CALL_UTIL (memset)(&c_act, 0, sizeof c_act);
     421        sigemptyset (&c_act.sa_mask);
     422        sigaddset (&c_act.sa_mask, SIGPROF); /* block SIGPROF delivery in handler */
     423        /* XXXX should probably also block sample_sig & pause_sig */
     424        c_act.sa_sigaction = collector_sigemt_handler;  /* note: used to set sa_handler instead */
     425        c_act.sa_flags = SA_RESTART | SA_SIGINFO;
     426        if (__collector_sigaction (HWCFUNCS_SIGNAL, &c_act, &old_sigemt_handler) != 0)
     427  	{
     428  	  TprintfT (0, "hwc_initialize_handlers(): ERROR: hwc_initialize_handlers(): __collector_sigaction() failed to set cact\n");
     429  	  collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">event handler could not be installed</event>\n", SP_JCMD_CERROR, COL_ERROR_HWCINIT);
     430  	  return COL_ERROR_HWCINIT;
     431  	}
     432      }
     433    return COL_ERROR_NONE;
     434  }
     435  
     436  static int
     437  close_experiment (void)
     438  {
     439    /* note: stop_data_collection() should have already been called by
     440     * collector_close_experiment()
     441     */
     442    if (!COUNTERS_ENABLED ())
     443      return COL_ERROR_NONE;
     444    detach_experiment ();
     445  
     446    /* cpc or libperfctr may still generate sigemts for a while */
     447    /* verify that SIGEMT handler is still installed */
     448    /* (still required with sigaction interposition and management,
     449       since interposition is not done for attach experiments)
     450     */
     451    struct sigaction curr;
     452    if (__collector_sigaction (HWCFUNCS_SIGNAL, NULL, &curr) == -1)
     453      {
     454        TprintfT (0, "hwprofile close_experiment: ERROR: hwc sigaction check failed: errno=%d\n", errno);
     455      }
     456    else if (curr.sa_sigaction != collector_sigemt_handler)
     457      {
     458        TprintfT (DBG_LT1, "hwprofile close_experiment: WARNING: collector sigemt handler replaced by 0x%p!\n", curr.sa_handler);
     459        (void) collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">0x%p</event>\n",
     460  					    SP_JCMD_CWARN, COL_WARN_SIGEMT, curr.sa_handler);
     461      }
     462    else
     463      TprintfT (DBG_LT1, "hwprofile close_experiment: collector sigemt handler integrity verified!\n");
     464    TprintfT (0, "hwprofile: close_experiment\n");
     465    return 0;
     466  }
     467  
     468  static int
     469  detach_experiment (void)
     470  {
     471    /* fork child.  Clean up state but don't write to experiment */
     472    /* note: stop_data_collection() has already been called by the fork_prologue */
     473    // detach_experiment() can be called asynchronously
     474    // from anywhere, even from within a sigemt handler
     475    // via DBX detach.
     476    // Important: stop_data_collection() _must_ be called
     477    // before detach_experiment() is called.
     478    if (!COUNTERS_ENABLED ())
     479      return COL_ERROR_NONE;
     480    TprintfT (0, "hwprofile: detach_experiment()\n");
     481    if (SD_OFF != __collector_cas_32 (&sd_state, SD_OFF, SD_PENDING))
     482      return 0;
     483    // one and only one call should ever make it here here.
     484    if (hwc_mode == HWCMODE_ACTIVE)
     485      {
     486        TprintfT (0, "hwprofile: ERROR: stop_data_collection() should have been called before detach_experiment()\n");
     487        stop_data_collection ();
     488      }
     489  
     490    // Assumption: The only calls to sigemt_handler
     491    // we should see at this point
     492    // will be those that were already in-flight before
     493    // stop_new_sigemts() was called.
     494    if (nthreads_in_sighandler > 0)
     495      {
     496        // sigemt handlers should see
     497        // SD_PENDING and should call real_detach_experiment()
     498        // when the last handler is finished.
     499        TprintfT (DBG_LT1, "hwprofile: detach in the middle of signal handler.\n");
     500        return 0;
     501      }
     502  
     503    // If we get here, there should be no remaining
     504    // sigemt handlers.  However,  we don't really know
     505    // if there were ever any in flight, so call
     506    // real_detach_experiment() here:
     507    return real_detach_experiment (); // multiple calls to this OK
     508  }
     509  
     510  static int
     511  real_detach_experiment (void)
     512  {
     513    /*multiple calls to this routine are OK.*/
     514    if (SD_PENDING != __collector_cas_32 (&sd_state, SD_PENDING, SD_COMPLETE))
     515      return 0;
     516    // only the first caller to this routine should get here.
     517    hwcdef_cnt = 0; /* since now deinstalled */
     518    hwcdef = NULL;
     519    set_hwc_mode (HWCMODE_OFF);
     520    if (SD_COMPLETE != __collector_cas_32 (&sd_state, SD_COMPLETE, SD_OFF))
     521      {
     522        TprintfT (0, "hwprofile: ERROR: unexpected sd_state in real_detach_experiment()\n");
     523        sd_state = SD_OFF;
     524      }
     525    hwprofile_tsd_key = COLLECTOR_TSD_INVALID_KEY;
     526    TprintfT (DBG_LT0, "hwprofile: real_detach_experiment() detached from experiment.\n");
     527    return 0;
     528  }
     529  
     530  /*---------------------------------------------------------------------------*/
     531  /* Record counter values. */
     532  
     533  /* <value> should already be adjusted to be "zero-based" (counting up from 0).*/
     534  static void
     535  collector_record_counter_internal (ucontext_t *ucp, int timecvt,
     536  				   ABST_type ABS_memop, hrtime_t time,
     537  				   unsigned tag, uint64_t value, uint64_t pc,
     538  				   uint64_t va, uint64_t latency,
     539  				   uint64_t data_source)
     540  {
     541    MHwcntr_packet pckt;
     542    CALL_UTIL (memset)(&pckt, 0, sizeof ( MHwcntr_packet));
     543    pckt.comm.tstamp = time;
     544    pckt.tag = tag;
     545    if (timecvt > 1)
     546      {
     547        if (HWCVAL_HAS_ERR (value))
     548  	{
     549  	  value = HWCVAL_CLR_ERR (value);
     550  	  value *= timecvt;
     551  	  value = HWCVAL_SET_ERR (value);
     552  	}
     553        else
     554  	value *= timecvt;
     555      }
     556    pckt.interval = value;
     557    pckt.comm.type = HW_PCKT;
     558    pckt.comm.tsize = sizeof (Hwcntr_packet);
     559    TprintfT (DBG_LT4, "hwprofile: %llu sample %lld tag %u recorded\n",
     560  	    (unsigned long long) time, (long long) value, tag);
     561    if (ABS_memop == ABST_NOPC)
     562      ucp = &expr_nopc_uc;
     563    pckt.comm.frinfo = collector_interface->getFrameInfo (expr_hndl, pckt.comm.tstamp, FRINFO_FROM_UC, ucp);
     564    collector_interface->writeDataRecord (expr_hndl, (Common_packet*) & pckt);
     565  }
     566  
     567  static void
     568  collector_record_counter (ucontext_t *ucp, int timecvt, ABST_type ABS_memop,
     569  			  hrtime_t time, unsigned tag, uint64_t value)
     570  {
     571    collector_record_counter_internal (ucp, timecvt, ABS_memop, time, tag, value,
     572  				     HWCFUNCS_INVALID_U64, HWCFUNCS_INVALID_U64,
     573  				     HWCFUNCS_INVALID_U64, HWCFUNCS_INVALID_U64);
     574  }
     575  
     576  
     577  /*---------------------------------------------------------------------------*/
     578  /* Signal handlers */
     579  
     580  /* SIGEMT -- relayed from libcpc, when the counter overflows */
     581  
     582  /*   Generates the appropriate event or events, and resets the counters */
     583  static void
     584  collector_sigemt_handler (int sig, siginfo_t *si, void *puc)
     585  {
     586    int rc;
     587    hwc_event_t sample, lost_samples;
     588    if (sig != HWCFUNCS_SIGNAL)
     589      {
     590        TprintfT (0, "hwprofile: ERROR: %s: unexpected signal %d\n", "collector_sigemt_handler", sig);
     591        return;
     592      }
     593    if (!COUNTERS_ENABLED ())
     594      { /* apparently deinstalled */
     595        TprintfT (0, "hwprofile: WARNING: SIGEMT detected after close_experiment()\n");
     596        /* kills future sigemts since hwcdrv_sighlr_restart() not called */
     597        return;
     598      }
     599  
     600    /* Typically, we expect HWC overflow signals to come from the kernel: si_code > 0.
     601     * On Linux, however, dbx might be "forwarding" a signal using tkill()/tgkill().
     602     * For more information on what si_code values can be expected on Linux, check:
     603     *     cmn_components/Collector_Interface/hwcdrv_pcl.c     hwcdrv_overflow()
     604     *     cmn_components/Collector_Interface/hwcdrv_perfctr.c hdrv_perfctr_overflow()
     605     */
     606    if (puc == NULL || si == NULL || (si->si_code <= 0 && si->si_code != SI_TKILL))
     607      {
     608        TprintfT (DBG_LT3, "hwprofile: collector_sigemt_handler SIG%02d\n", sig);
     609        if (old_sigemt_handler.sa_handler == SIG_DFL)
     610  	__collector_SIGDFL_handler (HWCFUNCS_SIGNAL);
     611        else if (old_sigemt_handler.sa_handler != SIG_IGN &&
     612  	 old_sigemt_handler.sa_sigaction != &collector_sigemt_handler)
     613  	{
     614  	  /* Redirect the signal to the previous signal handler */
     615  	  (old_sigemt_handler.sa_sigaction)(sig, si, puc);
     616  	  TprintfT (DBG_LT1, "hwprofile: collector_sigemt_handler SIG%02d redirected to original handler\n", sig);
     617  	}
     618        return;
     619      }
     620    rc = get_hwc_driver ()->hwcdrv_overflow (si, &sample, &lost_samples);
     621    if (rc)
     622      {
     623        /* hwcdrv_sighlr_restart() should not be called */
     624        TprintfT (0, "hwprofile: ERROR: collector_sigemt_handler: hwcdrv_overflow() failed\n");
     625        return;
     626      }
     627  
     628    if (hwc_mode == HWCMODE_ACTIVE)
     629      {
     630        /* record the event only if counters are active */
     631        /* The following has been copied from dispatcher.c */
     632  #if ARCH(SPARC)
     633        /* 23340823 signal handler third argument should point to a ucontext_t */
     634        /* Convert sigcontext to ucontext_t on sparc-Linux */
     635        ucontext_t uctxmem;
     636        struct sigcontext *sctx = (struct sigcontext*) puc;
     637        ucontext_t *uctx = &uctxmem;
     638        uctx->uc_link = NULL;
     639  #if WSIZE(32)
     640        uctx->uc_mcontext.gregs[REG_PC] = sctx->si_regs.pc;
     641        __collector_memcpy (&uctx->uc_mcontext.gregs[3],
     642  			  sctx->si_regs.u_regs,
     643  			  sizeof (sctx->si_regs.u_regs));
     644  #else
     645        uctx->uc_mcontext.mc_gregs[MC_PC] = sctx->sigc_regs.tpc;
     646        __collector_memcpy (&uctx->uc_mcontext.mc_gregs[3],
     647  			  sctx->sigc_regs.u_regs,
     648  			  sizeof (sctx->sigc_regs.u_regs));
     649  #endif /* WSIZE() */
     650  #else
     651        ucontext_t *uctx = (ucontext_t*) puc;
     652  #endif /* ARCH() */
     653  
     654        for (int ii = 0; ii < hwcdef_cnt; ii++)
     655  	if (lost_samples.ce_pic[ii])
     656  	  collector_record_counter (&expr_lostcounts_uc, hwcdef[ii]->timecvt,
     657  				    hwcdef[ii]->memop, lost_samples.ce_hrt,
     658  				    hwcdef[ii]->sort_order, lost_samples.ce_pic[ii]);
     659        for (int ii = 0; ii < hwcdef_cnt; ii++)
     660  	if (sample.ce_pic[ii])
     661  	  collector_record_counter (uctx, hwcdef[ii]->timecvt,
     662  				    hwcdef[ii]->memop, sample.ce_hrt,
     663  				    hwcdef[ii]->sort_order, sample.ce_pic[ii]);
     664      }
     665    rc = get_hwc_driver ()->hwcdrv_sighlr_restart (NULL);
     666  }
     667  /*	SIGPROF -- not installed as handler, but
     668   *      __collector_ext_hwc_check: called by (SIGPROF) dispatcher.
     669   *       Periodical check of integrity of HWC count/signal mechanism,
     670   *       as required for various chip/system bugs/workarounds.
     671   */
     672  void
     673  __collector_ext_hwc_check (siginfo_t *info, ucontext_t *vcontext) { }
     674  
     675  /*---------------------------------------------------------------------------*/
     676  int
     677  collector_sigemt_sigaction (const struct sigaction *nact,
     678  			    struct sigaction *oact)
     679  {
     680    struct sigaction oact_check;
     681    /* Error codes and messages that refer to HWC are tricky.
     682     * E.g., HWC profiling might not even be on;  we might
     683     * encounter an error here simply because the user is
     684     * trying to set a handler for a signal that happens to
     685     * be HWCFUNCS_SIGNAL, which we aren't even using.
     686     */
     687    if (__collector_sigaction (HWCFUNCS_SIGNAL, NULL, &oact_check) != 0)
     688      {
     689        TprintfT (0, "hwprofile: ERROR: collector_sigemt_sigaction(): request to set handler for signal %d, but check on existing handler failed\n", HWCFUNCS_SIGNAL);
     690        collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">old handler for signal %d could not be determined</event>\n", SP_JCMD_CERROR, COL_ERROR_HWCINIT, HWCFUNCS_SIGNAL);
     691        return COL_ERROR_HWCINIT;
     692      }
     693  
     694    if (oact_check.sa_sigaction == collector_sigemt_handler)
     695      {
     696        /* dispatcher is in place, so nact/oact apply to old_sigemt_handler */
     697        if (oact != NULL)
     698  	{
     699  	  oact->sa_handler = old_sigemt_handler.sa_handler;
     700  	  oact->sa_mask = old_sigemt_handler.sa_mask;
     701  	  oact->sa_flags = old_sigemt_handler.sa_flags;
     702  	}
     703        if (nact != NULL)
     704  	{
     705  	  old_sigemt_handler.sa_handler = nact->sa_handler;
     706  	  old_sigemt_handler.sa_mask = nact->sa_mask;
     707  	  old_sigemt_handler.sa_flags = nact->sa_flags;
     708  	}
     709        return COL_ERROR_NONE;
     710      }
     711    else /* no dispatcher in place, so just act like normal sigaction() */
     712      return __collector_sigaction (HWCFUNCS_SIGNAL, nact, oact);
     713  }
     714  
     715  static void
     716  collector_hwc_ABORT (int errnum, const char *msg)
     717  {
     718    TprintfT (0, "hwprofile: collector_hwc_ABORT: [%d] %s\n", errnum, msg);
     719    if (hwc_mode == HWCMODE_ABORT) /* HWC collection already aborted! */
     720      return;
     721    set_hwc_mode (HWCMODE_ABORT); /* set global flag to disable handlers and indicate abort */
     722  
     723    /* Write the error message to the experiment */
     724    collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">%s: errno=%d</event>\n",
     725  				 SP_JCMD_CERROR, COL_ERROR_HWCFAIL, msg, errnum);
     726  
     727  #ifdef REAL_DEBUG
     728    abort ();
     729  #else
     730    TprintfT (0, "hwprofile: Continuing without HWC collection...\n");
     731  #endif
     732  }
     733  
     734  static int
     735  start_data_collection (void)
     736  {
     737    hwc_mode_t old_mode = hwc_mode;
     738    if (!COUNTERS_ENABLED ())
     739      return COL_ERROR_NONE;
     740    TprintfT (0, "hwprofile: start_data_collection (hwc_mode=%d)\n", old_mode);
     741    switch (old_mode)
     742      {
     743      case HWCMODE_OFF:
     744        if (get_hwc_driver ()->hwcdrv_start ())
     745  	{
     746  	  TprintfT (0, "hwprofile: ERROR: start_data_collection() failed in hwcdrv_start()\n");
     747  	  collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">%s: errno=%d</event>\n",
     748  					 SP_JCMD_CERROR, COL_ERROR_HWCFAIL,
     749  					 "start_data_collection()", errno);
     750  	  return COL_ERROR_HWCINIT;
     751  	}
     752        set_hwc_mode (HWCMODE_ACTIVE); /* start handling events on signals */
     753        break;
     754      case HWCMODE_SUSPEND:
     755        if (get_hwc_driver ()->hwcdrv_lwp_resume ())
     756  	{
     757  	  TprintfT (0, "hwprofile: ERROR: start_data_collection() failed in hwcdrv_lwp_resume()\n");
     758  	  /* ignore errors from lwp_resume() */
     759  	}
     760        set_hwc_mode (HWCMODE_ACTIVE); /* start handling events on signals */
     761        break;
     762      default:
     763        TprintfT (0, "hwprofile: ERROR: start_data_collection() invalid mode\n");
     764        return COL_ERROR_HWCINIT;
     765      }
     766    return COL_ERROR_NONE;
     767  }
     768  
     769  static int
     770  stop_data_collection (void)
     771  {
     772    hwc_mode_t old_mode = hwc_mode;
     773    if (!COUNTERS_ENABLED ())
     774      return COL_ERROR_NONE;
     775    TprintfT (0, "hwprofile: stop_data_collection (hwc_mode=%d)\n", old_mode);
     776    switch (old_mode)
     777      {
     778      case HWCMODE_SUSPEND:
     779        return COL_ERROR_NONE;
     780      case HWCMODE_ACTIVE:
     781        set_hwc_mode (HWCMODE_SUSPEND); /* stop handling signals */
     782        break;
     783      default:
     784        /* Don't change the mode, but attempt to suspend anyway... */
     785        break;
     786      }
     787  
     788    if (get_hwc_driver ()->hwcdrv_lwp_suspend ())
     789      /* ignore errors from lwp_suspend() */
     790      TprintfT (0, "hwprofile: ERROR: stop_data_collection() failed in hwcdrv_lwp_suspend()\n");
     791  
     792    /*
     793     * hwcdrv_lwp_suspend() cannot guarantee that all SIGEMTs will stop
     794     * but hwc_mode will prevent logging and counters will overflow once
     795     * then stay frozen.
     796     */
     797    /*   There may still be pending SIGEMTs so don't reset the SIG_DFL handler.
     798     */
     799    /* see comment in dispatcher.c */
     800    /* ret = __collector_sigaction( SIGEMT, &old_sigemt_handler, NULL ); */
     801    return COL_ERROR_NONE;
     802  }
     803  
     804  /*---------------------------------------------------------------------------*/
     805  
     806  /* utilities */
     807  static void
     808  set_hwc_mode (hwc_mode_t md)
     809  {
     810    TprintfT (DBG_LT1, "hwprofile: set_hwc_mode(%d)\n", md);
     811    hwc_mode = md;
     812  }
     813  
     814  int
     815  __collector_ext_hwc_active ()
     816  {
     817    return (hwc_mode == HWCMODE_ACTIVE);
     818  }
     819  
     820  static void
     821  hwclogwrite0 ()
     822  {
     823    collector_interface->writeLog ("<profdata fname=\"%s\"/>\n",
     824  				 module_interface.description);
     825    /* Record Hwcntr_packet description */
     826    Hwcntr_packet *pp = NULL;
     827    collector_interface->writeLog ("<profpckt kind=\"%d\" uname=\"" STXT ("Hardware counter profiling data") "\">\n", HW_PCKT);
     828    collector_interface->writeLog ("    <field name=\"LWPID\" uname=\"" STXT ("Lightweight process id") "\" offset=\"%d\" type=\"%s\"/>\n",
     829  				 &pp->comm.lwp_id, sizeof (pp->comm.lwp_id) == 4 ? "INT32" : "INT64");
     830    collector_interface->writeLog ("    <field name=\"THRID\" uname=\"" STXT ("Thread number") "\" offset=\"%d\" type=\"%s\"/>\n",
     831  				 &pp->comm.thr_id, sizeof (pp->comm.thr_id) == 4 ? "INT32" : "INT64");
     832    collector_interface->writeLog ("    <field name=\"CPUID\" uname=\"" STXT ("CPU id") "\" offset=\"%d\" type=\"%s\"/>\n",
     833  				 &pp->comm.cpu_id, sizeof (pp->comm.cpu_id) == 4 ? "INT32" : "INT64");
     834    collector_interface->writeLog ("    <field name=\"TSTAMP\" uname=\"" STXT ("High resolution timestamp") "\" offset=\"%d\" type=\"%s\"/>\n",
     835  				 &pp->comm.tstamp, sizeof (pp->comm.tstamp) == 4 ? "INT32" : "INT64");
     836    collector_interface->writeLog ("    <field name=\"FRINFO\" offset=\"%d\" type=\"%s\"/>\n",
     837  				 &pp->comm.frinfo, sizeof (pp->comm.frinfo) == 4 ? "INT32" : "INT64");
     838    collector_interface->writeLog ("    <field name=\"HWCTAG\" uname=\"" STXT ("Hardware counter index") "\" offset=\"%d\" type=\"%s\"/>\n",
     839  				 &pp->tag, sizeof (pp->tag) == 4 ? "INT32" : "INT64");
     840    collector_interface->writeLog ("    <field name=\"HWCINT\" uname=\"" STXT ("Hardware counter interval") "\" offset=\"%d\" type=\"%s\"/>\n",
     841  				 &pp->interval, sizeof (pp->interval) == 4 ? "INT32" : "INT64");
     842    collector_interface->writeLog ("</profpckt>\n");
     843    if (hwcdef_has_memspace)
     844      {
     845        /* Record MHwcntr_packet description */
     846        MHwcntr_packet *xpp = NULL;
     847        collector_interface->writeLog ("<profpckt kind=\"%d\" uname=\"" STXT ("Hardware counter profiling data") "\">\n", MHWC_PCKT);
     848        collector_interface->writeLog ("    <field name=\"LWPID\" uname=\"" STXT ("Lightweight process id") "\" offset=\"%d\" type=\"%s\"/>\n",
     849  				     &xpp->comm.lwp_id, sizeof (xpp->comm.lwp_id) == 4 ? "INT32" : "INT64");
     850        collector_interface->writeLog ("    <field name=\"THRID\" uname=\"" STXT ("Thread number") "\" offset=\"%d\" type=\"%s\"/>\n",
     851  				     &xpp->comm.thr_id, sizeof (xpp->comm.thr_id) == 4 ? "INT32" : "INT64");
     852        collector_interface->writeLog ("    <field name=\"CPUID\" uname=\"" STXT ("CPU id") "\" offset=\"%d\" type=\"%s\"/>\n",
     853  				     &xpp->comm.cpu_id, sizeof (xpp->comm.cpu_id) == 4 ? "INT32" : "INT64");
     854        collector_interface->writeLog ("    <field name=\"TSTAMP\" uname=\"" STXT ("High resolution timestamp") "\" offset=\"%d\" type=\"%s\"/>\n",
     855  				     &xpp->comm.tstamp, sizeof (xpp->comm.tstamp) == 4 ? "INT32" : "INT64");
     856        collector_interface->writeLog ("    <field name=\"FRINFO\" offset=\"%d\" type=\"%s\"/>\n",
     857  				     &xpp->comm.frinfo, sizeof (xpp->comm.frinfo) == 4 ? "INT32" : "INT64");
     858        collector_interface->writeLog ("    <field name=\"HWCTAG\" uname=\"" STXT ("Hardware counter index") "\" offset=\"%d\" type=\"%s\"/>\n",
     859  				     &xpp->tag, sizeof (xpp->tag) == 4 ? "INT32" : "INT64");
     860        collector_interface->writeLog ("    <field name=\"HWCINT\" uname=\"" STXT ("Hardware counter interval") "\" offset=\"%d\" type=\"%s\"/>\n",
     861  				     &xpp->interval, sizeof (xpp->interval) == 4 ? "INT32" : "INT64");
     862        collector_interface->writeLog ("    <field name=\"VADDR\" uname=\"" STXT ("Virtual address (data)") "\" offset=\"%d\" type=\"%s\"/>\n",
     863  				     &xpp->ea_vaddr, sizeof (xpp->ea_vaddr) == 4 ? "UINT32" : "UINT64");
     864        collector_interface->writeLog ("    <field name=\"PADDR\" uname=\"" STXT ("Physical address (data)") "\" offset=\"%d\" type=\"%s\"/>\n",
     865  				     &xpp->ea_paddr, sizeof (xpp->ea_paddr) == 4 ? "UINT32" : "UINT64");
     866        collector_interface->writeLog ("    <field name=\"VIRTPC\" uname=\"" STXT ("Virtual address (instruction)") "\" offset=\"%d\" type=\"%s\"/>\n",
     867  				     &xpp->pc_vaddr, sizeof (xpp->pc_vaddr) == 4 ? "UINT32" : "UINT64");
     868        collector_interface->writeLog ("    <field name=\"PHYSPC\" uname=\"" STXT ("Physical address (instruction)") "\" offset=\"%d\" type=\"%s\"/>\n",
     869  				     &xpp->pc_paddr, sizeof (xpp->pc_paddr) == 4 ? "UINT32" : "UINT64");
     870        collector_interface->writeLog ("    <field name=\"EA_PAGESIZE\" uname=\"" STXT ("Page size (data)") "\" offset=\"%d\" type=\"%s\"/>\n",
     871  				     &xpp->ea_pagesz, sizeof (xpp->ea_pagesz) == 4 ? "INT32" : "INT64");
     872        collector_interface->writeLog ("    <field name=\"PC_PAGESIZE\" uname=\"" STXT ("Page size (instruction)") "\" offset=\"%d\" type=\"%s\"/>\n",
     873  				     &xpp->pc_pagesz, sizeof (xpp->pc_pagesz) == 4 ? "INT32" : "INT64");
     874        collector_interface->writeLog ("    <field name=\"EA_LGRP\" uname=\"" STXT ("Page locality group (data)") "\" offset=\"%d\" type=\"%s\"/>\n",
     875  				     &xpp->ea_lgrp, sizeof (xpp->ea_lgrp) == 4 ? "INT32" : "INT64");
     876        collector_interface->writeLog ("    <field name=\"PC_LGRP\" uname=\"" STXT ("Page locality group (instruction)") "\" offset=\"%d\" type=\"%s\"/>\n",
     877  				     &xpp->pc_lgrp, sizeof (xpp->pc_lgrp) == 4 ? "INT32" : "INT64");
     878        collector_interface->writeLog ("    <field name=\"LWP_LGRP_HOME\" uname=\"" STXT ("LWP home lgroup id") "\" offset=\"%d\" type=\"%s\"/>\n",
     879  				     &xpp->lgrp_lwp, sizeof (xpp->lgrp_lwp) == 4 ? "INT32" : "INT64");
     880        collector_interface->writeLog ("    <field name=\"PS_LGRP_HOME\" uname=\"" STXT ("Process home lgroup id") "\" offset=\"%d\" type=\"%s\"/>\n",
     881  				     &xpp->lgrp_ps, sizeof (xpp->lgrp_ps) == 4 ? "INT32" : "INT64");
     882        collector_interface->writeLog ("    <field name=\"MEM_LAT\" uname=\"" STXT ("Memory Latency Cycles") "\" offset=\"%d\" type=\"%s\"/>\n",
     883  				     &xpp->latency, sizeof (xpp->latency) == 4 ? "INT32" : "INT64");
     884        collector_interface->writeLog ("    <field name=\"MEM_SRC\" uname=\"" STXT ("Memory Data Source") "\" offset=\"%d\" type=\"%s\"/>\n",
     885  				     &xpp->data_source, sizeof (xpp->data_source) == 4 ? "INT32" : "INT64");
     886        collector_interface->writeLog ("</profpckt>\n");
     887      }
     888  }
     889  
     890  static void
     891  hwclogwrite (Hwcentry * ctr)
     892  {
     893    TprintfT (DBG_LT1, "hwprofile: writeLog(%s %u %s %d %u %d)\n",
     894  	    SP_JCMD_HW_COUNTER, cpcN_cpuver, ctr->name ? ctr->name : "NULL",
     895  	    ctr->val, ctr->sort_order, ctr->memop);
     896    collector_interface->writeLog ("<profile name=\"%s\"", SP_JCMD_HW_COUNTER);
     897    collector_interface->writeLog (" cpuver=\"%u\"", cpcN_cpuver);
     898    collector_interface->writeLog (" hwcname=\"%s\"", ctr->name);
     899    collector_interface->writeLog (" int_name=\"%s\"", ctr->int_name);
     900    collector_interface->writeLog (" interval=\"%d\"", ctr->val);
     901    collector_interface->writeLog (" tag=\"%u\"", ctr->sort_order);
     902    collector_interface->writeLog (" memop=\"%d\"", ctr->memop);
     903    collector_interface->writeLog ("/>\n");
     904  }