|
PAPI
5.1.0.2
|
00001 /****************************/ 00002 /* THIS IS OPEN SOURCE CODE */ 00003 /****************************/ 00004 00020 #include "linux-IOunit.h" 00021 00022 /* Declare our vector in advance */ 00023 papi_vector_t _IOunit_vector; 00024 00025 /* prototypes */ 00026 void user_signal_handler_IOUNIT( int hEvtSet, uint64_t address, uint64_t ovfVector, const ucontext_t *pContext ); 00027 00028 /***************************************************************************** 00029 ******************* BEGIN PAPI's COMPONENT REQUIRED FUNCTIONS ************* 00030 *****************************************************************************/ 00031 00032 /* 00033 * This is called whenever a thread is initialized 00034 */ 00035 int 00036 IOUNIT_init_thread( hwd_context_t * ctx ) 00037 { 00038 #ifdef DEBUG_BGQ 00039 printf( "IOUNIT_init_thread\n" ); 00040 #endif 00041 00042 ( void ) ctx; 00043 return PAPI_OK; 00044 } 00045 00046 00047 /* Initialize hardware counters, setup the function vector table 00048 * and get hardware information, this routine is called when the 00049 * PAPI process is initialized (IE PAPI_library_init) 00050 */ 00051 int 00052 IOUNIT_init_component( int cidx ) 00053 { 00054 #ifdef DEBUG_BGQ 00055 printf( "IOUNIT_init_component\n" ); 00056 #endif 00057 00058 _IOunit_vector.cmp_info.CmpIdx = cidx; 00059 #ifdef DEBUG_BGQ 00060 printf( "IOUNIT_init_component cidx = %d\n", cidx ); 00061 #endif 00062 00063 return ( PAPI_OK ); 00064 } 00065 00066 00067 /* 00068 * Control of counters (Reading/Writing/Starting/Stopping/Setup) 00069 * functions 00070 */ 00071 int 00072 IOUNIT_init_control_state( hwd_control_state_t * ptr ) 00073 { 00074 #ifdef DEBUG_BGQ 00075 printf( "IOUNIT_init_control_state\n" ); 00076 #endif 00077 00078 IOUNIT_control_state_t * this_state = ( IOUNIT_control_state_t * ) ptr; 00079 00080 this_state->EventGroup = Bgpm_CreateEventSet(); 00081 CHECK_BGPM_ERROR( this_state->EventGroup, "Bgpm_CreateEventSet" ); 00082 00083 // initialize overflow flag to OFF (0) 00084 this_state->overflow = 0; 00085 this_state->overflow_threshold = 0; 00086 this_state->overflow_EventIndex = 0; 00087 00088 return PAPI_OK; 00089 } 00090 00091 00092 /* 00093 * 00094 */ 00095 int 00096 IOUNIT_start( hwd_context_t * ctx, hwd_control_state_t * ptr ) 00097 { 00098 #ifdef DEBUG_BGQ 00099 printf( "IOUNIT_start\n" ); 00100 #endif 00101 ( void ) ctx; 00102 int retval; 00103 IOUNIT_control_state_t * this_state = ( IOUNIT_control_state_t * ) ptr; 00104 00105 retval = Bgpm_ResetStart( this_state->EventGroup ); 00106 CHECK_BGPM_ERROR( retval, "Bgpm_ResetStart" ); 00107 00108 return ( PAPI_OK ); 00109 } 00110 00111 00112 /* 00113 * 00114 */ 00115 int 00116 IOUNIT_stop( hwd_context_t * ctx, hwd_control_state_t * ptr ) 00117 { 00118 #ifdef DEBUG_BGQ 00119 printf( "IOUNIT_stop\n" ); 00120 #endif 00121 ( void ) ctx; 00122 int retval; 00123 IOUNIT_control_state_t * this_state = ( IOUNIT_control_state_t * ) ptr; 00124 00125 retval = Bgpm_Stop( this_state->EventGroup ); 00126 CHECK_BGPM_ERROR( retval, "Bgpm_Stop" ); 00127 00128 return ( PAPI_OK ); 00129 } 00130 00131 00132 /* 00133 * 00134 */ 00135 int 00136 IOUNIT_read( hwd_context_t * ctx, hwd_control_state_t * ptr, 00137 long_long ** events, int flags ) 00138 { 00139 #ifdef DEBUG_BGQ 00140 printf( "IOUNIT_read\n" ); 00141 #endif 00142 ( void ) ctx; 00143 ( void ) flags; 00144 int i, numEvts; 00145 IOUNIT_control_state_t * this_state = ( IOUNIT_control_state_t * ) ptr; 00146 00147 numEvts = Bgpm_NumEvents( this_state->EventGroup ); 00148 if ( numEvts == 0 ) { 00149 #ifdef DEBUG_BGPM 00150 printf ("Error: ret value is %d for BGPM API function Bgpm_NumEvents.\n", numEvts ); 00151 #endif 00152 //return ( EXIT_FAILURE ); 00153 } 00154 00155 for ( i = 0; i < numEvts; i++ ) 00156 this_state->counts[i] = _common_getEventValue( i, this_state->EventGroup ); 00157 00158 *events = this_state->counts; 00159 00160 return ( PAPI_OK ); 00161 } 00162 00163 00164 /* 00165 * 00166 */ 00167 int 00168 IOUNIT_shutdown_thread( hwd_context_t * ctx ) 00169 { 00170 #ifdef DEBUG_BGQ 00171 printf( "IOUNIT_shutdown_thread\n" ); 00172 #endif 00173 00174 ( void ) ctx; 00175 return ( PAPI_OK ); 00176 } 00177 00178 00179 /* 00180 * user_signal_handler 00181 * 00182 * This function is used when hardware overflows are working or when 00183 * software overflows are forced 00184 */ 00185 void 00186 user_signal_handler_IOUNIT( int hEvtSet, uint64_t address, uint64_t ovfVector, const ucontext_t *pContext ) 00187 { 00188 #ifdef DEBUG_BGQ 00189 printf( "user_signal_handler_IOUNIT\n" ); 00190 #endif 00191 ( void ) address; 00192 int retval; 00193 unsigned i; 00194 int isHardware = 1; 00195 int cidx = _IOunit_vector.cmp_info.CmpIdx; 00196 long_long overflow_bit = 0; 00197 caddr_t address1; 00198 _papi_hwi_context_t ctx; 00199 ctx.ucontext = ( hwd_ucontext_t * ) pContext; 00200 ThreadInfo_t *thread = _papi_hwi_lookup_thread( 0 ); 00201 EventSetInfo_t *ESI; 00202 ESI = thread->running_eventset[cidx]; 00203 // Get the indices of all events which have overflowed. 00204 unsigned ovfIdxs[BGPM_MAX_OVERFLOW_EVENTS]; 00205 unsigned len = BGPM_MAX_OVERFLOW_EVENTS; 00206 00207 retval = Bgpm_GetOverflowEventIndices( hEvtSet, ovfVector, ovfIdxs, &len ); 00208 if ( retval < 0 ) { 00209 #ifdef DEBUG_BGPM 00210 printf ( "Error: ret value is %d for BGPM API function Bgpm_GetOverflowEventIndices.\n", 00211 retval ); 00212 #endif 00213 return; 00214 } 00215 00216 if ( thread == NULL ) { 00217 PAPIERROR( "thread == NULL in user_signal_handler!" ); 00218 return; 00219 } 00220 00221 if ( ESI == NULL ) { 00222 PAPIERROR( "ESI == NULL in user_signal_handler!"); 00223 return; 00224 } 00225 00226 if ( ESI->overflow.flags == 0 ) { 00227 PAPIERROR( "ESI->overflow.flags == 0 in user_signal_handler!"); 00228 return; 00229 } 00230 00231 for ( i = 0; i < len; i++ ) { 00232 uint64_t hProf; 00233 Bgpm_GetEventUser1( hEvtSet, ovfIdxs[i], &hProf ); 00234 if ( hProf ) { 00235 overflow_bit ^= 1 << ovfIdxs[i]; 00236 break; 00237 } 00238 00239 } 00240 00241 if ( ESI->overflow.flags & PAPI_OVERFLOW_FORCE_SW ) { 00242 #ifdef DEBUG_BGQ 00243 printf("OVERFLOW_SOFTWARE\n"); 00244 #endif 00245 address1 = GET_OVERFLOW_ADDRESS( ctx ); 00246 _papi_hwi_dispatch_overflow_signal( ( void * ) &ctx, address1, NULL, 0, 0, &thread, cidx ); 00247 return; 00248 } 00249 else if ( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) { 00250 #ifdef DEBUG_BGQ 00251 printf("OVERFLOW_HARDWARE\n"); 00252 #endif 00253 address1 = GET_OVERFLOW_ADDRESS( ctx ); 00254 _papi_hwi_dispatch_overflow_signal( ( void * ) &ctx, address1, &isHardware, overflow_bit, 0, &thread, cidx ); 00255 } 00256 else { 00257 #ifdef DEBUG_BGQ 00258 printf("OVERFLOW_NONE\n"); 00259 #endif 00260 PAPIERROR( "ESI->overflow.flags is set to something other than PAPI_OVERFLOW_HARDWARE or PAPI_OVERFLOW_FORCE_SW (%x)", thread->running_eventset[cidx]->overflow.flags); 00261 } 00262 } 00263 00264 00265 /* 00266 * Set Overflow 00267 * 00268 * This is commented out in BG/L/P - need to explore and complete... 00269 * However, with true 64-bit counters in BG/Q and all counters for PAPI 00270 * always starting from a true zero (we don't allow write...), the possibility 00271 * for overflow is remote at best... 00272 */ 00273 int 00274 IOUNIT_set_overflow( EventSetInfo_t * ESI, int EventIndex, int threshold ) 00275 { 00276 #ifdef DEBUG_BGQ 00277 printf("BEGIN IOUNIT_set_overflow\n"); 00278 #endif 00279 IOUNIT_control_state_t * this_state = ( IOUNIT_control_state_t * ) ESI->ctl_state; 00280 int retval; 00281 int evt_idx; 00282 00283 evt_idx = ESI->EventInfoArray[EventIndex].pos[0]; 00284 SUBDBG( "Hardware counter %d (vs %d) used in overflow, threshold %d\n", 00285 evt_idx, EventIndex, threshold ); 00286 #ifdef DEBUG_BGQ 00287 printf( "Hardware counter %d (vs %d) used in overflow, threshold %d\n", 00288 evt_idx, EventIndex, threshold ); 00289 #endif 00290 /* If this counter isn't set to overflow, it's an error */ 00291 if ( threshold == 0 ) { 00292 /* Remove the signal handler */ 00293 retval = _papi_hwi_stop_signal( _IOunit_vector.cmp_info.hardware_intr_sig ); 00294 if ( retval != PAPI_OK ) 00295 return ( retval ); 00296 } 00297 else { 00298 this_state->overflow = 1; 00299 this_state->overflow_threshold = threshold; 00300 this_state->overflow_EventIndex = evt_idx; 00301 00302 #ifdef DEBUG_BGQ 00303 printf( "IOUNIT_set_overflow: Enable the signal handler\n" ); 00304 #endif 00305 /* Enable the signal handler */ 00306 retval = _papi_hwi_start_signal( _IOunit_vector.cmp_info.hardware_intr_sig, 00307 NEED_CONTEXT, 00308 _IOunit_vector.cmp_info.CmpIdx ); 00309 if ( retval != PAPI_OK ) 00310 return ( retval ); 00311 00312 _common_set_overflow_BGPM( this_state->EventGroup, 00313 this_state->overflow_EventIndex, 00314 this_state->overflow_threshold, 00315 user_signal_handler_IOUNIT ); 00316 } 00317 00318 return ( PAPI_OK ); 00319 } 00320 00321 00322 /* This function sets various options in the component 00323 * The valid codes being passed in are PAPI_SET_DEFDOM, 00324 * PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL * and PAPI_SET_INHERIT 00325 */ 00326 int 00327 IOUNIT_ctl( hwd_context_t * ctx, int code, _papi_int_option_t * option ) 00328 { 00329 #ifdef DEBUG_BGQ 00330 printf( "IOUNIT_ctl\n" ); 00331 #endif 00332 00333 ( void ) ctx; 00334 ( void ) code; 00335 ( void ) option; 00336 return ( PAPI_OK ); 00337 } 00338 00339 00340 /* 00341 * 00342 */ 00343 int 00344 IOUNIT_update_control_state( hwd_control_state_t * ptr, 00345 NativeInfo_t * native, int count, 00346 hwd_context_t * ctx ) 00347 { 00348 #ifdef DEBUG_BGQ 00349 printf( "IOUNIT_update_control_state: count = %d\n", count ); 00350 #endif 00351 ( void ) ctx; 00352 int retval, index, i; 00353 IOUNIT_control_state_t * this_state = ( IOUNIT_control_state_t * ) ptr; 00354 00355 // Delete and re-create BGPM eventset 00356 _common_deleteRecreate( &this_state->EventGroup ); 00357 00358 #ifdef DEBUG_BGQ 00359 printf( "IOUNIT_update_control_state: EventGroup=%d, overflow = %d\n", 00360 this_state->EventGroup, this_state->overflow ); 00361 #endif 00362 00363 // otherwise, add the events to the eventset 00364 for ( i = 0; i < count; i++ ) { 00365 index = ( native[i].ni_event ) + OFFSET; 00366 00367 native[i].ni_position = i; 00368 00369 #ifdef DEBUG_BGQ 00370 printf("IOUNIT_update_control_state: ADD event: i = %d, index = %d\n", i, index ); 00371 #endif 00372 00373 /* Add events to the BGPM eventGroup */ 00374 retval = Bgpm_AddEvent( this_state->EventGroup, index ); 00375 CHECK_BGPM_ERROR( retval, "Bgpm_AddEvent" ); 00376 } 00377 00378 00379 // since update_control_state trashes overflow settings, this puts things 00380 // back into balance for BGPM 00381 if ( 1 == this_state->overflow ) { 00382 _common_set_overflow_BGPM( this_state->EventGroup, 00383 this_state->overflow_EventIndex, 00384 this_state->overflow_threshold, 00385 user_signal_handler_IOUNIT ); 00386 } 00387 00388 return ( PAPI_OK ); 00389 } 00390 00391 00392 /* 00393 * This function has to set the bits needed to count different domains 00394 * In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER 00395 * By default return PAPI_EINVAL if none of those are specified 00396 * and PAPI_OK with success 00397 * PAPI_DOM_USER is only user context is counted 00398 * PAPI_DOM_KERNEL is only the Kernel/OS context is counted 00399 * PAPI_DOM_OTHER is Exception/transient mode (like user TLB misses) 00400 * PAPI_DOM_ALL is all of the domains 00401 */ 00402 int 00403 IOUNIT_set_domain( hwd_control_state_t * cntrl, int domain ) 00404 { 00405 #ifdef DEBUG_BGQ 00406 printf( "IOUNIT_set_domain\n" ); 00407 #endif 00408 int found = 0; 00409 ( void ) cntrl; 00410 00411 if ( PAPI_DOM_USER & domain ) 00412 found = 1; 00413 00414 if ( PAPI_DOM_KERNEL & domain ) 00415 found = 1; 00416 00417 if ( PAPI_DOM_OTHER & domain ) 00418 found = 1; 00419 00420 if ( !found ) 00421 return ( PAPI_EINVAL ); 00422 00423 return ( PAPI_OK ); 00424 } 00425 00426 00427 /* 00428 * 00429 */ 00430 int 00431 IOUNIT_reset( hwd_context_t * ctx, hwd_control_state_t * ptr ) 00432 { 00433 #ifdef DEBUG_BGQ 00434 printf( "IOUNIT_reset\n" ); 00435 #endif 00436 ( void ) ctx; 00437 int retval; 00438 IOUNIT_control_state_t * this_state = ( IOUNIT_control_state_t * ) ptr; 00439 00440 /* we can't simply call Bgpm_Reset() since PAPI doesn't have the 00441 restriction that an EventSet has to be stopped before resetting is 00442 possible. However, BGPM does have this restriction. 00443 Hence we need to stop, reset and start */ 00444 retval = Bgpm_Stop( this_state->EventGroup ); 00445 CHECK_BGPM_ERROR( retval, "Bgpm_Stop" ); 00446 00447 retval = Bgpm_ResetStart( this_state->EventGroup ); 00448 CHECK_BGPM_ERROR( retval, "Bgpm_ResetStart" ); 00449 00450 return ( PAPI_OK ); 00451 } 00452 00453 00454 /* 00455 * PAPI Cleanup Eventset 00456 * 00457 * Destroy and re-create the BGPM / IOunit EventSet 00458 */ 00459 int 00460 IOUNIT_cleanup_eventset( hwd_control_state_t * ctrl ) 00461 { 00462 #ifdef DEBUG_BGQ 00463 printf( "IOUNIT_cleanup_eventset\n" ); 00464 #endif 00465 00466 IOUNIT_control_state_t * this_state = ( IOUNIT_control_state_t * ) ctrl; 00467 00468 // create a new empty bgpm eventset 00469 // reason: bgpm doesn't permit to remove events from an eventset; 00470 // hence we delete the old eventset and create a new one 00471 _common_deleteRecreate( &this_state->EventGroup ); // HJ try to use delete() only 00472 00473 // set overflow flag to OFF (0) 00474 this_state->overflow = 0; 00475 this_state->overflow_threshold = 0; 00476 this_state->overflow_EventIndex = 0; 00477 00478 return ( PAPI_OK ); 00479 } 00480 00481 00482 /* 00483 * Native Event functions 00484 */ 00485 int 00486 IOUNIT_ntv_enum_events( unsigned int *EventCode, int modifier ) 00487 { 00488 #ifdef DEBUG_BGQ 00489 //printf( "IOUNIT_ntv_enum_events\n" ); 00490 #endif 00491 00492 switch ( modifier ) { 00493 case PAPI_ENUM_FIRST: 00494 *EventCode = 0; 00495 00496 return ( PAPI_OK ); 00497 break; 00498 00499 case PAPI_ENUM_EVENTS: 00500 { 00501 int index = ( *EventCode ) + OFFSET; 00502 00503 if ( index < IOUNIT_MAX_COUNTERS ) { 00504 *EventCode = *EventCode + 1; 00505 return ( PAPI_OK ); 00506 } else 00507 return ( PAPI_ENOEVNT ); 00508 00509 break; 00510 } 00511 default: 00512 return ( PAPI_EINVAL ); 00513 } 00514 return ( PAPI_EINVAL ); 00515 } 00516 00517 00518 /* 00519 * 00520 */ 00521 int 00522 IOUNIT_ntv_name_to_code( char *name, unsigned int *event_code ) 00523 { 00524 #ifdef DEBUG_BGQ 00525 printf( "IOUNIT_ntv_name_to_code\n" ); 00526 #endif 00527 int ret; 00528 00529 /* Return event id matching a given event label string */ 00530 ret = Bgpm_GetEventIdFromLabel ( name ); 00531 00532 if ( ret <= 0 ) { 00533 #ifdef DEBUG_BGPM 00534 printf ("Error: ret value is %d for BGPM API function '%s'.\n", 00535 ret, "Bgpm_GetEventIdFromLabel" ); 00536 #endif 00537 return PAPI_ENOEVNT; 00538 } 00539 else if ( ret < OFFSET || ret > IOUNIT_MAX_COUNTERS ) // not an IOUnit event 00540 return PAPI_ENOEVNT; 00541 else 00542 *event_code = ( ret - OFFSET ) ; 00543 00544 return PAPI_OK; 00545 } 00546 00547 00548 /* 00549 * 00550 */ 00551 int 00552 IOUNIT_ntv_code_to_name( unsigned int EventCode, char *name, int len ) 00553 { 00554 #ifdef DEBUG_BGQ 00555 //printf( "IOUNIT_ntv_code_to_name\n" ); 00556 #endif 00557 int index; 00558 00559 index = ( EventCode ) + OFFSET; 00560 00561 if ( index >= MAX_COUNTERS ) 00562 return PAPI_ENOEVNT; 00563 00564 strncpy( name, Bgpm_GetEventIdLabel( index ), len ); 00565 00566 if ( name == NULL ) { 00567 #ifdef DEBUG_BGPM 00568 printf ("Error: ret value is NULL for BGPM API function Bgpm_GetEventIdLabel.\n" ); 00569 #endif 00570 return PAPI_ENOEVNT; 00571 } 00572 00573 return ( PAPI_OK ); 00574 } 00575 00576 00577 /* 00578 * 00579 */ 00580 int 00581 IOUNIT_ntv_code_to_descr( unsigned int EventCode, char *name, int len ) 00582 { 00583 #ifdef DEBUG_BGQ 00584 //printf( "IOUNIT_ntv_code_to_descr\n" ); 00585 #endif 00586 int retval, index; 00587 00588 index = ( EventCode ) + OFFSET; 00589 00590 retval = Bgpm_GetLongDesc( index, name, &len ); 00591 CHECK_BGPM_ERROR( retval, "Bgpm_GetLongDesc" ); 00592 00593 return ( PAPI_OK ); 00594 } 00595 00596 00597 /* 00598 * 00599 */ 00600 int 00601 IOUNIT_ntv_code_to_bits( unsigned int EventCode, hwd_register_t * bits ) 00602 { 00603 #ifdef DEBUG_BGQ 00604 printf( "IOUNIT_ntv_code_to_bits\n" ); 00605 #endif 00606 ( void ) EventCode; 00607 ( void ) bits; 00608 return ( PAPI_OK ); 00609 } 00610 00611 00612 /* 00613 * 00614 */ 00615 papi_vector_t _IOunit_vector = { 00616 .cmp_info = { 00617 /* default component information (unspecified values are initialized to 0) */ 00618 .name = "bgpm/IOUnit", 00619 .short_name = "IOUnit", 00620 .description = "Blue Gene/Q IOUnit component", 00621 .num_cntrs = IOUNIT_MAX_COUNTERS, 00622 .num_mpx_cntrs = IOUNIT_MAX_COUNTERS, 00623 .default_domain = PAPI_DOM_USER, 00624 .available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL, 00625 .default_granularity = PAPI_GRN_THR, 00626 .available_granularities = PAPI_GRN_THR, 00627 00628 .hardware_intr_sig = PAPI_INT_SIGNAL, 00629 .hardware_intr = 1, 00630 00631 .kernel_multiplex = 0, 00632 00633 /* component specific cmp_info initializations */ 00634 .fast_real_timer = 0, 00635 .fast_virtual_timer = 0, 00636 .attach = 0, 00637 .attach_must_ptrace = 0, 00638 } 00639 , 00640 00641 /* sizes of framework-opaque component-private structures */ 00642 .size = { 00643 .context = sizeof ( IOUNIT_context_t ), 00644 .control_state = sizeof ( IOUNIT_control_state_t ), 00645 .reg_value = sizeof ( IOUNIT_register_t ), 00646 .reg_alloc = sizeof ( IOUNIT_reg_alloc_t ), 00647 } 00648 , 00649 /* function pointers in this component */ 00650 .init_thread = IOUNIT_init_thread, 00651 .init_component = IOUNIT_init_component, 00652 .init_control_state = IOUNIT_init_control_state, 00653 .start = IOUNIT_start, 00654 .stop = IOUNIT_stop, 00655 .read = IOUNIT_read, 00656 .shutdown_thread = IOUNIT_shutdown_thread, 00657 .set_overflow = IOUNIT_set_overflow, 00658 .cleanup_eventset = IOUNIT_cleanup_eventset, 00659 .ctl = IOUNIT_ctl, 00660 00661 .update_control_state = IOUNIT_update_control_state, 00662 .set_domain = IOUNIT_set_domain, 00663 .reset = IOUNIT_reset, 00664 00665 .ntv_name_to_code = IOUNIT_ntv_name_to_code, 00666 .ntv_enum_events = IOUNIT_ntv_enum_events, 00667 .ntv_code_to_name = IOUNIT_ntv_code_to_name, 00668 .ntv_code_to_descr = IOUNIT_ntv_code_to_descr, 00669 .ntv_code_to_bits = IOUNIT_ntv_code_to_bits 00670 };