/*
* 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 <common/bgp_personality_inlines.h>
#include <spi/bgp_SPI.h>
#include <ucontext.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/time.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/utsname.h>
/* 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,
};