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