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