/* * File: linux-bgp.c * Author: Dave Hermsmeier * dlherms@us.ibm.com */ /* * PAPI stuff */ #include "papi.h" #include "papi_internal.h" #include "papi_vector.h" #include "papi_memory.h" #include "extras.h" #include "linux-bgp.h" /* * BG/P specific 'stuff' */ /* BG/P includes */ #include #include #include #include #include #include #include #include #include #include /* BG/P macros */ #define get_cycles _bgp_GetTimeBase /* BG/P external structures/functions */ papi_vector_t _bgp_vectors; /* Defined in linux-bgp-memory.c */ extern int _bgp_get_memory_info( PAPI_hw_info_t * pHwInfo, int pCPU_Type ); extern int _bgp_get_dmem_info( PAPI_dmem_info_t * pDmemInfo ); /* BG/P globals */ hwi_search_t *preset_search_map; volatile unsigned int lock[PAPI_MAX_LOCK]; const char *BGP_NATIVE_RESERVED_EVENTID = "Reserved"; PAPI_os_info_t _papi_os_info; /* * Get BGP Native Event Id from PAPI Event Id */ inline BGP_UPC_Event_Id_t get_bgp_native_event_id( int pEventId ) { return ( BGP_UPC_Event_Id_t ) ( pEventId & PAPI_NATIVE_AND_MASK ); } /* * Lock initialization */ void _papi_hwd_lock_init( void ) { /* PAPI on BG/P does not need locks. */ return; } /* * Lock */ void _papi_hwd_lock( int lock ) { /* PAPI on BG/P does not need locks. */ return; } /* * Unlock */ void _papi_hwd_unlock( int lock ) { /* PAPI on BG/P does not need locks. */ return; } /* * Get System Information * * Initialize system information structure */ int _bgp_get_system_info( papi_mdi_t *mdi ) { _BGP_Personality_t bgp; int tmp; unsigned utmp; char chipID[64]; /* Hardware info */ if ( ( tmp = Kernel_GetPersonality( &bgp, sizeof bgp ) ) ) { #include "error.h" fprintf( stdout, "Kernel_GetPersonality returned %d (sys error=%d).\n" "\t%s\n", tmp, errno, strerror( errno ) ); return PAPI_ESYS; } _papi_hwi_system_info.hw_info.ncpu = Kernel_ProcessorCount( ); _papi_hwi_system_info.hw_info.nnodes = ( int ) BGP_Personality_numComputeNodes( &bgp ); _papi_hwi_system_info.hw_info.totalcpus = _papi_hwi_system_info.hw_info.ncpu * _papi_hwi_system_info.hw_info.nnodes; utmp = Kernel_GetProcessorVersion( ); _papi_hwi_system_info.hw_info.model = ( int ) utmp; _papi_hwi_system_info.hw_info.vendor = ( utmp >> ( 31 - 11 ) ) & 0xFFF; _papi_hwi_system_info.hw_info.revision = ( ( float ) ( ( utmp >> ( 31 - 15 ) ) & 0xFFFF ) ) + 0.00001 * ( ( float ) ( utmp & 0xFFFF ) ); strcpy( _papi_hwi_system_info.hw_info.vendor_string, "IBM" ); tmp = snprintf( _papi_hwi_system_info.hw_info.model_string, sizeof _papi_hwi_system_info.hw_info.model_string, "PVR=%#4.4x:%#4.4x", ( utmp >> ( 31 - 15 ) ) & 0xFFFF, ( utmp & 0xFFFF ) ); BGP_Personality_getLocationString( &bgp, chipID ); tmp += 12 + sizeof ( chipID ); if ( sizeof ( _papi_hwi_system_info.hw_info.model_string ) > tmp ) { strcat( _papi_hwi_system_info.hw_info.model_string, " Serial=" ); strncat( _papi_hwi_system_info.hw_info.model_string, chipID, sizeof ( chipID ) ); } _papi_hwi_system_info.hw_info.mhz = ( float ) BGP_Personality_clockMHz( &bgp ); SUBDBG( "_bgp_get_system_info: Detected MHZ is %f\n", _papi_hwi_system_info.hw_info.mhz ); _papi_hwi_system_info.hw_info.cpu_max_mhz=_papi_hwi_system_info.hw_info.mhz; _papi_hwi_system_info.hw_info.cpu_min_mhz=_papi_hwi_system_info.hw_info.mhz; // Memory information structure not filled in - same as BG/L // _papi_hwi_system_info.hw_info.mem_hierarchy = ???; // The mpx_info structure disappeared in PAPI-C //_papi_hwi_system_info.mpx_info.timer_sig = PAPI_NULL; return PAPI_OK; } /* * Initialize Control State * * All state is kept in BG/P UPC structures */ int _bgp_init_control_state( hwd_control_state_t *ctl ) { int i; //bgp_control_state_t *bgp_ctl = (bgp_control_state_t *)ctl; for ( i = 1; i < BGP_UPC_MAX_MONITORED_EVENTS; i++ ) ctl->counters[i] = 0; return PAPI_OK; } /* * Set Domain * * All state is kept in BG/P UPC structures */ int _bgp_set_domain( hwd_control_state_t * cntrl, int domain ) { return ( PAPI_OK ); } /* * PAPI Initialization * * All state is kept in BG/P UPC structures */ int _bgp_init_thread( hwd_context_t * ctx ) { return PAPI_OK; } /* * PAPI Global Initialization * * Global initialization - does initial PAPI setup and * calls BGP_UPC_Initialize() */ int _bgp_init_global( void ) { int retval; int cidx = _bgp_vectors.cmp_info.CmpIdx; /* * Fill in what we can of the papi_system_info */ SUBDBG( "Before _bgp_get_system_info()...\n" ); retval = _bgp_get_system_info( &_papi_hwi_system_info ); SUBDBG( "After _bgp_get_system_info(), retval=%d...\n", retval ); if ( retval != PAPI_OK ) return ( retval ); /* * Setup presets */ SUBDBG( "Before setup_bgp_presets, _papi_hwi_system_info.hw_info.model=%d...\n", _papi_hwi_system_info.hw_info.model ); retval = _papi_load_preset_table( "BGP", 0, cidx ); SUBDBG( "After setup_bgp_presets, retval=%d...\n", retval ); if ( retval ) return ( retval ); /* * Setup memory info */ SUBDBG( "Before _bgp_get_memory_info...\n" ); retval = _bgp_get_memory_info( &_papi_hwi_system_info.hw_info, ( int ) _papi_hwi_system_info.hw_info. model ); SUBDBG( "After _bgp_get_memory_info, retval=%d...\n", retval ); if ( retval ) return ( retval ); /* * Initialize BG/P global variables... * NOTE: If the BG/P SPI interface is to be used, then this * initialize routine must be called from each process for the * application. It does not matter if this routine is called more * than once per process, but must be called by each process at * least once, preferably at the beginning of the application. */ SUBDBG( "Before BGP_UPC_Initialize()...\n" ); BGP_UPC_Initialize( ); SUBDBG( "After BGP_UPC_Initialize()...\n" ); return PAPI_OK; } /* * PAPI Shutdown Global * * Called once per process - nothing to do */ int _bgp_shutdown_global( void ) { return PAPI_OK; } /* * Register Allocation * * Sets up the UPC configuration to monitor those events * as identified in the event set. */ int _bgp_allocate_registers( EventSetInfo_t * ESI ) { int i, natNum; BGP_UPC_Event_Id_t xEventId; /* * If an active UPC unit, return error */ if ( BGP_UPC_Check_Active( ) ) { SUBDBG( "_bgp_allocate_registers: UPC is active...\n" ); return PAPI_ESYS; } /* * If a counter mode of 1, return error */ if ( BGP_UPC_Get_Counter_Mode( ) ) { SUBDBG( "_bgp_allocate_registers: Inconsistent counter mode...\n" ); return PAPI_ESYS; } /* * Start monitoring the events... */ natNum = ESI->NativeCount; // printf("_bgp_allocate_registers: natNum=%d\n", natNum); for ( i = 0; i < natNum; i++ ) { xEventId = get_bgp_native_event_id( ESI->NativeInfoArray[i].ni_event ); // printf("_bgp_allocate_registers: xEventId = %d\n", xEventId); if ( !BGP_UPC_Check_Active_Event( xEventId ) ) { // NOTE: We do not have to start monitoring for elapsed time... It is always being // monitored at location 255... if ( ( xEventId % BGP_UPC_MAX_MONITORED_EVENTS ) != 255 ) { /* * The event is not already being monitored by the UPC, start monitoring * for the event. This will automatically zero the counter and turn off any * threshold value... */ // printf("_bgp_allocate_registers: Event id %d not being monitored...\n", xEventId); if ( BGP_UPC_Monitor_Event( xEventId, BGP_UPC_CFG_EDGE_DEFAULT ) < 0 ) { // printf("_bgp_allocate_registers: Monitor_Event failed...\n"); return PAPI_ECMP; } } /* here is if we are event 255 */ else { } } else { /* * The event is already being monitored by the UPC. This is a normal * case where the UPC is monitoring all events for a particular user * mode. We are in this leg because the PAPI event set has not yet * started monitoring the event. So, simply zero the counter and turn * off any threshold value... */ // printf("_bgp_allocate_registers: Event id %d is already being monitored...\n", xEventId); // NOTE: Can't zero the counter or reset the threshold for the timestamp counter... if ( ESI->NativeInfoArray[i].ni_event != PNE_BGP_IC_TIMESTAMP ) { if ( BGP_UPC_Zero_Counter_Value( xEventId ) < 0 ) { // printf("_bgp_allocate_registers: Zero_Counter failed...\n"); return PAPI_ECMP; } if ( BGP_UPC_Set_Counter_Threshold_Value( xEventId, 0 ) < 0 ) { // printf("_bgp_allocate_registers: Set_Counter_Threshold_Value failed...\n"); return PAPI_ECMP; } } } ESI->NativeInfoArray[i].ni_position = xEventId % BGP_UPC_MAX_MONITORED_EVENTS; // printf("_bgp_allocate_registers: ESI->NativeInfoArray[i].ni_position=%d\n", ESI->NativeInfoArray[i].ni_position); } // printf("_bgp_allocate_registers: Exiting normally...\n"); return PAPI_OK; } /* * Update Control State * * This function clears the current contents of the control * structure and updates it with whatever resources are allocated * for all the native events in the native info structure array. * * Since no BGP specific state is kept at the PAPI level, there is * nothing to update and we simply return. */ int _bgp_update_control_state( hwd_control_state_t *ctl, NativeInfo_t *native, int count, hwd_context_t *ctx ) { return PAPI_OK; } /* Hack to get cycle count */ static long_long begin_cycles; /* * PAPI Start * * Start UPC unit(s) */ int _bgp_start( hwd_context_t * ctx, hwd_control_state_t * ctrlstate ) { sigset_t mask_set; sigset_t old_set; sigemptyset( &mask_set ); sigaddset( &mask_set, SIGXCPU ); sigprocmask( SIG_BLOCK, &mask_set, &old_set ); begin_cycles=_bgp_GetTimeBase(); BGP_UPC_Start( BGP_UPC_NO_RESET_COUNTERS ); sigprocmask( SIG_UNBLOCK, &mask_set, NULL ); return ( PAPI_OK ); } /* * PAPI Stop * * Stop UPC unit(s) */ int _bgp_stop( hwd_context_t * ctx, hwd_control_state_t * state ) { sigset_t mask_set; sigset_t old_set; sigemptyset( &mask_set ); sigaddset( &mask_set, SIGXCPU ); sigprocmask( SIG_BLOCK, &mask_set, &old_set ); BGP_UPC_Stop( ); sigprocmask( SIG_UNBLOCK, &mask_set, NULL ); return PAPI_OK; } /* * PAPI Read Counters * * Read the counters into local storage */ int _bgp_read( hwd_context_t *ctx, hwd_control_state_t *ctl, long_long ** dp, int flags ) { // printf("_bgp_read: this_state* = %p\n", this_state); // printf("_bgp_read: (long_long*)&this_state->counters[0] = %p\n", (long_long*)&this_state->counters[0]); // printf("_bgp_read: (long_long*)&this_state->counters[1] = %p\n", (long_long*)&this_state->counters[1]); sigset_t mask_set; sigset_t old_set; sigemptyset( &mask_set ); sigaddset( &mask_set, SIGXCPU ); sigprocmask( SIG_BLOCK, &mask_set, &old_set ); if ( BGP_UPC_Read_Counters ( ( long_long * ) & ctl->counters[0], BGP_UPC_MAXIMUM_LENGTH_READ_COUNTERS_ONLY, BGP_UPC_READ_EXCLUSIVE ) < 0 ) { sigprocmask( SIG_UNBLOCK, &mask_set, NULL ); return PAPI_ECMP; } sigprocmask( SIG_UNBLOCK, &mask_set, NULL ); /* hack to emulate BGP_MISC_ELAPSED_TIME counter */ ctl->counters[255]=_bgp_GetTimeBase()-begin_cycles; *dp = ( long_long * ) & ctl->counters[0]; // printf("_bgp_read: dp = %p\n", dp); // printf("_bgp_read: *dp = %p\n", *dp); // printf("_bgp_read: (*dp)[0]* = %p\n", &((*dp)[0])); // printf("_bgp_read: (*dp)[1]* = %p\n", &((*dp)[1])); // printf("_bgp_read: (*dp)[2]* = %p\n", &((*dp)[2])); // int i; // for (i=0; i<256; i++) // if ((*dp)[i]) // printf("_bgp_read: i=%d, (*dp)[i]=%lld\n", i, (*dp)[i]); return PAPI_OK; } /* * PAPI Reset * * Zero the counter values */ int _bgp_reset( hwd_context_t * ctx, hwd_control_state_t * ctrlstate ) { // NOTE: PAPI can reset the counters with the UPC running. One way it happens // is with PAPI_accum. In that case, stop and restart the UPC, resetting // the counters. sigset_t mask_set; sigset_t old_set; sigemptyset( &mask_set ); sigaddset( &mask_set, SIGXCPU ); sigprocmask( SIG_BLOCK, &mask_set, &old_set ); if ( BGP_UPC_Check_Active( ) ) { // printf("_bgp_reset: BGP_UPC_Stop()\n"); BGP_UPC_Stop( ); // printf("_bgp_reset: BGP_UPC_Start(BGP_UPC_RESET_COUNTERS)\n"); BGP_UPC_Start( BGP_UPC_RESET_COUNTERS ); } else { // printf("_bgp_reset: BGP_UPC_Zero_Counter_Values()\n"); BGP_UPC_Zero_Counter_Values( ); } sigprocmask( SIG_UNBLOCK, &mask_set, NULL ); return ( PAPI_OK ); } /* * PAPI Shutdown * * This routine is for shutting down threads, * including the master thread. * Effectively a no-op, same as BG/L... */ int _bgp_shutdown( hwd_context_t * ctx ) { return ( PAPI_OK ); } /* * PAPI Write * * Write counter values * NOTE: Could possible support, but signal error as BG/L does... */ int _bgp_write( hwd_context_t * ctx, hwd_control_state_t * cntrl, long_long * from ) { return PAPI_ECMP; } /* * Dispatch Timer * * Same as BG/L - simple return */ void _bgp_dispatch_timer( int signal, hwd_siginfo_t * si, void *context ) { return; } void user_signal_handler( int signum, hwd_siginfo_t * siginfo, void *mycontext ) { EventSetInfo_t *ESI; ThreadInfo_t *thread = NULL; int isHardware = 1; caddr_t pc; _papi_hwi_context_t ctx; BGP_UPC_Event_Id_t xEventId = 0; // int thresh; int event_index, i; long_long overflow_bit = 0; int64_t threshold; ctx.si = siginfo; ctx.ucontext = ( ucontext_t * ) mycontext; ucontext_t *context = ( ucontext_t * ) mycontext; pc = ( caddr_t ) context->uc_mcontext.regs->nip; thread = _papi_hwi_lookup_thread( 0 ); //int cidx = (int) &thread; ESI = thread->running_eventset[0]; //ESI = (EventSetInfo_t *) thread->running_eventset; if ( ESI == NULL ) { //printf("ESI is null\n"); return; } else { BGP_UPC_Stop( ); //xEventId = get_bgp_native_event_id(ESI->NativeInfoArray[0].ni_event); //*ESI->overflow.EventIndex].ni_event); event_index = *ESI->overflow.EventIndex; //printf("event index %d\n", event_index); for ( i = 0; i <= event_index; i++ ) { xEventId = get_bgp_native_event_id( ESI->NativeInfoArray[i].ni_event ); if ( BGP_UPC_Read_Counter( xEventId, 1 ) >= BGP_UPC_Get_Counter_Threshold_Value( xEventId ) && BGP_UPC_Get_Counter_Threshold_Value( xEventId ) != 0 ) { break; } } overflow_bit ^= 1 << xEventId; //ESI->overflow.handler(ESI->EventSetIndex, pc, 0, (void *) &ctx); _papi_hwi_dispatch_overflow_signal( ( void * ) &ctx, pc, &isHardware, overflow_bit, 0, &thread, 0 ); //thresh = (int)(*ESI->overflow.threshold + BGP_UPC_Read_Counter_Value(xEventId, 1)); //(int)BGP_UPC_Get_Counter_Threshold_Value(xEventId)); //printf("thresh %llu val %llu\n", (int64_t)*ESI->overflow.threshold, BGP_UPC_Read_Counter_Value(xEventId, 1)); threshold = ( int64_t ) * ESI->overflow.threshold + BGP_UPC_Read_Counter_Value( xEventId, 1 ); //printf("threshold %llu\n", threshold); BGP_UPC_Set_Counter_Threshold_Value( xEventId, threshold ); BGP_UPC_Start( 0 ); } } /* * Set Overflow * * This is commented out in BG/L - need to explore and complete... * However, with true 64-bit counters in BG/P and all counters for PAPI * always starting from a true zero (we don't allow write...), the possibility * for overflow is remote at best... * * Commented out code is carry-over from BG/L... */ int _bgp_set_overflow( EventSetInfo_t * ESI, int EventIndex, int threshold ) { int rc = 0; BGP_UPC_Event_Id_t xEventId; // = get_bgp_native_event_id(EventCode); xEventId = get_bgp_native_event_id( ESI->NativeInfoArray[EventIndex].ni_event ); //rc = BGP_UPC_Monitor_Event(xEventId, BGP_UPC_CFG_LEVEL_HIGH); rc = BGP_UPC_Set_Counter_Threshold_Value( xEventId, threshold ); //printf("setting up sigactioni %d\n", xEventId); //ESI->NativeInfoArray[EventIndex].ni_event); /*struct sigaction act; act.sa_sigaction = user_signal_handler; memset(&act.sa_mask, 0x0, sizeof(act.sa_mask)); act.sa_flags = SA_RESTART | SA_SIGINFO; if (sigaction(SIGXCPU, &act, NULL) == -1) { return (PAPI_ESYS); } */ struct sigaction new_action; sigemptyset( &new_action.sa_mask ); new_action.sa_sigaction = ( void * ) user_signal_handler; new_action.sa_flags = SA_RESTART | SA_SIGINFO; sigaction( SIGXCPU, &new_action, NULL ); return PAPI_OK; } /* * Set Profile * * Same as for BG/L, routine not used and returns error */ int _bgp_set_profile( EventSetInfo_t * ESI, int EventIndex, int threshold ) { /* This function is not used and shouldn't be called. */ return PAPI_ECMP; } /* * Stop Profiling * * Same as for BG/L... */ int _bgp_stop_profiling( ThreadInfo_t * master, EventSetInfo_t * ESI ) { return PAPI_OK; } /* * PAPI Control * * Same as for BG/L - initialize the domain */ int _bgp_ctl( hwd_context_t * ctx, int code, _papi_int_option_t * option ) { // extern int _bgp_set_domain(hwd_control_state_t * cntrl, int domain); switch ( code ) { case PAPI_DOMAIN: case PAPI_DEFDOM: // Simply return PAPI_OK, as no state is kept. return PAPI_OK; case PAPI_GRANUL: case PAPI_DEFGRN: return PAPI_ECMP; default: return PAPI_EINVAL; } } /* * Get Real Micro-seconds */ long long _bgp_get_real_usec( void ) { /* * NOTE: _papi_hwi_system_info.hw_info.mhz is really a representation of unit of time per cycle. * On BG/P, it's value is 8.5e-4. Therefore, to get cycles per sec, we have to multiply * by 1.0e12. To then convert to usec, we have to divide by 1.0e-3. */ // SUBDBG("_bgp_get_real_usec: _papi_hwi_system_info.hw_info.mhz=%e\n",(_papi_hwi_system_info.hw_info.mhz)); // float x = (float)get_cycles(); // float y = (_papi_hwi_system_info.hw_info.mhz)*(1.0e9); // SUBDBG("_bgp_get_real_usec: _papi_hwi_system_info.hw_info.mhz=%e, x=%e, y=%e, x/y=%e, (long long)(x/y) = %lld\n", // (_papi_hwi_system_info.hw_info.mhz), x, y, x/y, (long long)(x/y)); // return (long long)(x/y); return ( ( long long ) ( ( ( float ) get_cycles( ) ) / ( ( _papi_hwi_system_info.hw_info.cpu_max_mhz ) ) ) ); } /* * Get Real Cycles * * Same for BG/L, using native function... */ long long _bgp_get_real_cycles( void ) { return ( get_cycles( ) ); } /* * Get Virtual Micro-seconds * * Same calc as for BG/L, returns real usec... */ long long _bgp_get_virt_usec( void ) { return _bgp_get_real_usec( ); } /* * Get Virtual Cycles * * Same calc as for BG/L, returns real cycles... */ long long _bgp_get_virt_cycles( void ) { return _bgp_get_real_cycles( ); } /* * Component setup and shutdown * * Initialize hardware counters, setup the function vector table * and get hardware information, this routine is called when the * PAPI process is initialized (IE PAPI_library_init) */ int _bgp_init_component( int cidx ) { int retval; _bgp_vectors.cmp_info.CmpIdx = cidx; retval = _bgp_init_global( ); return ( retval ); } /*************************************/ /* CODE TO SUPPORT OPAQUE NATIVE MAP */ /*************************************/ /* * Native Code to Event Name * * Given a native event code, returns the short text label */ int _bgp_ntv_code_to_name( unsigned int EventCode, char *name, int len ) { char xNativeEventName[BGP_UPC_MAXIMUM_LENGTH_EVENT_NAME]; BGP_UPC_Event_Id_t xEventId = get_bgp_native_event_id( EventCode ); /* * NOTE: We do not return the event name for a user mode 2 or 3 event... */ if ( ( int ) xEventId < 0 || ( int ) xEventId > 511 ) return ( PAPI_ENOEVNT ); if ( BGP_UPC_Get_Event_Name ( xEventId, BGP_UPC_MAXIMUM_LENGTH_EVENT_NAME, xNativeEventName ) != BGP_UPC_SUCCESS ) return ( PAPI_ENOEVNT ); SUBDBG( "_bgp_ntv_code_to_name: EventCode = %d\n, xEventName = %s\n", EventCode, xEventName ); strncpy( name, "PNE_", len ); strncat( name, xNativeEventName, len - strlen( name ) ); return ( PAPI_OK ); } /* * Native Code to Event Description * * Given a native event code, returns the longer native event description */ int _bgp_ntv_code_to_descr( unsigned int EventCode, char *name, int len ) { char xNativeEventDesc[BGP_UPC_MAXIMUM_LENGTH_EVENT_DESCRIPTION]; BGP_UPC_Event_Id_t xEventId = get_bgp_native_event_id( EventCode ); /* * NOTE: We do not return the event name for a user mode 2 or 3 event... */ if ( ( int ) xEventId < 0 || ( int ) xEventId > 511 ) return ( PAPI_ENOEVNT ); else if ( BGP_UPC_Get_Event_Description ( xEventId, BGP_UPC_MAXIMUM_LENGTH_EVENT_DESCRIPTION, xNativeEventDesc ) != BGP_UPC_SUCCESS ) return ( PAPI_ENOEVNT ); strncpy( name, xNativeEventDesc, len ); return ( PAPI_OK ); } /* * Native Code to Bit Configuration * * Given a native event code, assigns the native event's * information to a given pointer. * NOTE: The info must be COPIED to location addressed by * the provided pointer, not just referenced! * NOTE: For BG/P, the bit configuration is not needed, * as the native SPI is used to configure events. */ int _bgp_ntv_code_to_bits( unsigned int EventCode, hwd_register_t * bits ) { return ( PAPI_OK ); } /* * Native ENUM Events * * Given a native event code, looks for next MOESI bit if applicable. * If not, looks for the next event in the table if the next one exists. * If not, returns the proper error code. * * For BG/P, we simply we simply return the native event id to the * to the next logical non-reserved event id. * * We only support enumerating all or available events. */ int _bgp_ntv_enum_events( unsigned int *EventCode, int modifier ) { /* * Check for a valid EventCode and we only process a modifier of 'all events'... */ // printf("_bgp_ntv_enum_events: EventCode=%8.8x\n", *EventCode); if ( *EventCode < 0x40000000 || *EventCode > 0x400001FF || ( modifier != PAPI_ENUM_ALL && modifier != PAPI_PRESET_ENUM_AVAIL ) ) return PAPI_ECMP; char xNativeEventName[BGP_UPC_MAXIMUM_LENGTH_EVENT_NAME]; BGP_UPC_RC_t xRC; // NOTE: We turn off the PAPI_NATIVE bit here... int32_t xNativeEventId = ( ( *EventCode ) & PAPI_NATIVE_AND_MASK ) + 0x00000001; while ( xNativeEventId <= 0x000001FF ) { xRC = BGP_UPC_Get_Event_Name( xNativeEventId, BGP_UPC_MAXIMUM_LENGTH_EVENT_NAME, xNativeEventName ); // printf("_bgp_ntv_enum_events: xNativeEventId = %8.8x, xRC=%d\n", xNativeEventId, xRC); if ( ( xRC == BGP_UPC_SUCCESS ) && ( strlen( xNativeEventName ) > 0 ) ) { // printf("_bgp_ntv_enum_events: len(xNativeEventName)=%d, xNativeEventName=%s\n", strlen(xNativeEventName), xNativeEventName); break; } xNativeEventId++; } if ( xNativeEventId > 0x000001FF ) return ( PAPI_ENOEVNT ); else { // NOTE: We turn the PAPI_NATIVE bit back on here... *EventCode = xNativeEventId | PAPI_NATIVE_MASK; return ( PAPI_OK ); } } int _papi_hwi_init_os(void) { struct utsname uname_buffer; uname(&uname_buffer); strncpy(_papi_os_info.name,uname_buffer.sysname,PAPI_MAX_STR_LEN); strncpy(_papi_os_info.version,uname_buffer.release,PAPI_MAX_STR_LEN); _papi_os_info.itimer_sig = PAPI_INT_MPX_SIGNAL; _papi_os_info.itimer_num = PAPI_INT_ITIMER; _papi_os_info.itimer_res_ns = 1; return PAPI_OK; } /* * PAPI Vector Table for BG/P */ papi_vector_t _bgp_vectors = { .cmp_info = { .name = "linux-bgp", .short_name = "bgp", .description = "BlueGene/P component", .num_cntrs = BGP_UPC_MAX_MONITORED_EVENTS, .num_mpx_cntrs = BGP_UPC_MAX_MONITORED_EVENTS, .default_domain = PAPI_DOM_USER, .available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL, .default_granularity = PAPI_GRN_THR, .available_granularities = PAPI_GRN_THR, .hardware_intr_sig = PAPI_INT_SIGNAL, .hardware_intr = 1, .fast_real_timer = 1, .fast_virtual_timer = 0, }, /* Sizes of framework-opaque component-private structures */ .size = { .context = sizeof ( hwd_context_t ), .control_state = sizeof ( hwd_control_state_t ), .reg_value = sizeof ( hwd_register_t ), .reg_alloc = sizeof ( hwd_reg_alloc_t ), }, /* Function pointers in this component */ .dispatch_timer = _bgp_dispatch_timer, .start = _bgp_start, .stop = _bgp_stop, .read = _bgp_read, .reset = _bgp_reset, .write = _bgp_write, .stop_profiling = _bgp_stop_profiling, .init_component = _bgp_init_component, .init_thread = _bgp_init_thread, .init_control_state = _bgp_init_control_state, .update_control_state = _bgp_update_control_state, .ctl = _bgp_ctl, .set_overflow = _bgp_set_overflow, .set_profile = _bgp_set_profile, .set_domain = _bgp_set_domain, .ntv_enum_events = _bgp_ntv_enum_events, .ntv_code_to_name = _bgp_ntv_code_to_name, .ntv_code_to_descr = _bgp_ntv_code_to_descr, .ntv_code_to_bits = _bgp_ntv_code_to_bits, .allocate_registers = _bgp_allocate_registers, .shutdown_thread = _bgp_shutdown }; papi_os_vector_t _papi_os_vector = { .get_memory_info = _bgp_get_memory_info, .get_dmem_info = _bgp_get_dmem_info, .get_real_cycles = _bgp_get_real_cycles, .get_real_usec = _bgp_get_real_usec, .get_virt_cycles = _bgp_get_virt_cycles, .get_virt_usec = _bgp_get_virt_usec, .get_system_info = _bgp_get_system_info, };