PAPI  5.1.0.2
papi_libpfm3_events.c
Go to the documentation of this file.
00001 /*
00002 * File:    papi_libpfm3_events.c
00003 * Author:  Dan Terpstra: blantantly extracted from Phil's perfmon.c
00004 *          mucci@cs.utk.edu
00005 *
00006 */
00007 
00008 #include <ctype.h>
00009 #include <string.h>
00010 #include <errno.h>
00011 
00012 #include "papi.h"
00013 #include "papi_internal.h"
00014 #include "papi_vector.h"
00015 #include "papi_memory.h"
00016 
00017 #include "perfmon/perfmon.h"
00018 #include "perfmon/pfmlib.h"
00019 
00020 #include "papi_libpfm_events.h"
00021 
00022 /* Native events consist of a flag field, an event field, and a unit mask field.
00023  * These variables define the characteristics of the event and unit mask fields.
00024  */
00025 unsigned int PAPI_NATIVE_EVENT_AND_MASK = 0x000003ff;
00026 unsigned int PAPI_NATIVE_EVENT_SHIFT = 0;
00027 unsigned int PAPI_NATIVE_UMASK_AND_MASK = 0x03fffc00;
00028 unsigned int PAPI_NATIVE_UMASK_MAX = 16;
00029 unsigned int PAPI_NATIVE_UMASK_SHIFT = 10;
00030 
00031 /* Globals */
00032 int num_native_events=0;
00033 
00034 
00035 /* NOTE: PAPI stores umask info in a variable sized (16 bit?) bitfield.
00036     Perfmon2 stores umask info in a large (48 element?) array of values.
00037     Native event encodings for perfmon2 contain array indices
00038     encoded as bits in this bitfield. These indices must be converted
00039     into a umask value before programming the counters. For Perfmon,
00040     this is done by converting back to an array of values; for 
00041     perfctr, it must be done by looking up the values.
00042 */
00043 
00044 /* This routine is used to step through all possible combinations of umask
00045     values. It assumes that mask contains a valid combination of array indices
00046     for this event. */
00047 static inline int
00048 encode_native_event_raw( unsigned int event, unsigned int mask )
00049 {
00050     unsigned int tmp = event << PAPI_NATIVE_EVENT_SHIFT;
00051     SUBDBG( "Old native index was 0x%08x with 0x%08x mask\n", tmp, mask );
00052     tmp = tmp | ( mask << PAPI_NATIVE_UMASK_SHIFT );
00053     SUBDBG( "New encoding is 0x%08x\n", tmp | PAPI_NATIVE_MASK );
00054     return ( int ) ( tmp | PAPI_NATIVE_MASK );
00055 }
00056 
00057 /* This routine converts array indices contained in the mask_values array
00058     into bits in the umask field that is OR'd into the native event code.
00059     These bits are NOT the mask values themselves, but indices into an array
00060     of mask values contained in the native event table. */
00061 static inline int
00062 encode_native_event( unsigned int event, unsigned int num_mask,
00063                      unsigned int *mask_values )
00064 {
00065     unsigned int i;
00066     unsigned int tmp = event << PAPI_NATIVE_EVENT_SHIFT;
00067     SUBDBG( "Native base event is 0x%08x with %d masks\n", tmp, num_mask );
00068     for ( i = 0; i < num_mask; i++ ) {
00069         SUBDBG( "Mask index is 0x%08x\n", mask_values[i] );
00070         tmp = tmp | ( ( 1 << mask_values[i] ) << PAPI_NATIVE_UMASK_SHIFT );
00071     }
00072     SUBDBG( "Full native encoding is 0x%08x\n", tmp | PAPI_NATIVE_MASK );
00073     return ( int ) ( tmp | PAPI_NATIVE_MASK );
00074 }
00075 
00076 
00077 /* Break a PAPI native event code into its composite event code and pfm mask bits */
00078 int
00079 _pfm_decode_native_event( unsigned int EventCode, unsigned int *event,
00080                           unsigned int *umask )
00081 {
00082     unsigned int tevent, major, minor;
00083 
00084     tevent = EventCode & PAPI_NATIVE_AND_MASK;
00085     major = ( tevent & PAPI_NATIVE_EVENT_AND_MASK ) >> PAPI_NATIVE_EVENT_SHIFT;
00086     if ( ( int ) major >= num_native_events )
00087         return PAPI_ENOEVNT;
00088 
00089     minor = ( tevent & PAPI_NATIVE_UMASK_AND_MASK ) >> PAPI_NATIVE_UMASK_SHIFT;
00090     *event = major;
00091     *umask = minor;
00092     SUBDBG( "EventCode 0x%08x is event %d, umask 0x%x\n", EventCode, major,
00093             minor );
00094     return PAPI_OK;
00095 }
00096 
00097 /* convert a collection of pfm mask bits into an array of pfm mask indices */
00098 int
00099 prepare_umask( unsigned int foo, unsigned int *values )
00100 {
00101     unsigned int tmp = foo, i;
00102     int j = 0;
00103 
00104     SUBDBG( "umask 0x%x\n", tmp );
00105     while ( ( i = ( unsigned int ) ffs( ( int ) tmp ) ) ) {
00106         tmp = tmp ^ ( 1 << ( i - 1 ) );
00107         values[j] = i - 1;
00108         SUBDBG( "umask %d is %d\n", j, values[j] );
00109         j++;
00110     }
00111     return ( j );
00112 }
00113 
00114 /* convert the mask values in a pfm event structure into a PAPI unit mask */
00115 static inline unsigned int
00116 convert_pfm_masks( pfmlib_event_t * gete )
00117 {
00118     int ret;
00119     unsigned int i, code, tmp = 0;
00120 
00121     for ( i = 0; i < gete->num_masks; i++ ) {
00122         if ( ( ret =
00123                pfm_get_event_mask_code( gete->event, gete->unit_masks[i],
00124                                         &code ) ) == PFMLIB_SUCCESS ) {
00125             SUBDBG( "Mask value is 0x%08x\n", code );
00126             tmp |= code;
00127         } else {
00128             PAPIERROR( "pfm_get_event_mask_code(0x%x,%d,%p): %s", gete->event,
00129                        i, &code, pfm_strerror( ret ) );
00130         }
00131     }
00132     return ( tmp );
00133 }
00134 
00135 /* convert an event code and pfm unit mask into a PAPI unit mask */
00136 unsigned int
00137 _pfm_convert_umask( unsigned int event, unsigned int umask )
00138 {
00139     pfmlib_event_t gete;
00140     memset( &gete, 0, sizeof ( gete ) );
00141     gete.event = event;
00142     gete.num_masks = ( unsigned int ) prepare_umask( umask, gete.unit_masks );
00143     return ( convert_pfm_masks( &gete ) );
00144 }
00145 
00146 /* convert libpfm error codes to PAPI error codes for 
00147     more informative error reporting */
00148 int
00149 _papi_libpfm_error( int pfm_error )
00150 {
00151     switch ( pfm_error ) {
00152         case PFMLIB_SUCCESS:        return PAPI_OK;         /* success */
00153         case PFMLIB_ERR_NOTSUPP:    return PAPI_ENOSUPP;    /* function not supported */
00154         case PFMLIB_ERR_INVAL:      return PAPI_EINVAL;     /* invalid parameters */
00155         case PFMLIB_ERR_NOINIT:     return PAPI_ENOINIT;    /* library was not initialized */
00156         case PFMLIB_ERR_NOTFOUND:   return PAPI_ENOEVNT;    /* event not found */
00157         case PFMLIB_ERR_NOASSIGN:   return PAPI_ECNFLCT;    /* cannot assign events to counters */
00158         case PFMLIB_ERR_FULL:       return PAPI_EBUF;       /* buffer is full or too small */
00159         case PFMLIB_ERR_EVTMANY:    return PAPI_EMISC;      /* event used more than once */
00160         case PFMLIB_ERR_MAGIC:      return PAPI_EBUG;       /* invalid library magic number */
00161         case PFMLIB_ERR_FEATCOMB:   return PAPI_ECOMBO;     /* invalid combination of features */
00162         case PFMLIB_ERR_EVTSET:     return PAPI_ENOEVST;    /* incompatible event sets */
00163         case PFMLIB_ERR_EVTINCOMP:  return PAPI_ECNFLCT;    /* incompatible event combination */
00164         case PFMLIB_ERR_TOOMANY:    return PAPI_ECOUNT;     /* too many events or unit masks */
00165         case PFMLIB_ERR_BADHOST:    return PAPI_ESYS;       /* not supported by host CPU */
00166         case PFMLIB_ERR_UMASK:      return PAPI_EATTR;      /* invalid or missing unit mask */
00167         case PFMLIB_ERR_NOMEM:      return PAPI_ENOMEM;     /* out of memory */
00168 
00169         /* Itanium only */
00170         case PFMLIB_ERR_IRRTOOBIG:      /* code range too big */
00171         case PFMLIB_ERR_IRREMPTY:       /* empty code range */
00172         case PFMLIB_ERR_IRRINVAL:       /* invalid code range */
00173         case PFMLIB_ERR_IRRTOOMANY:     /* too many code ranges */
00174         case PFMLIB_ERR_DRRINVAL:       /* invalid data range */
00175         case PFMLIB_ERR_DRRTOOMANY:     /* too many data ranges */
00176         case PFMLIB_ERR_IRRALIGN:       /* bad alignment for code range */
00177         case PFMLIB_ERR_IRRFLAGS:       /* code range missing flags */
00178         default:
00179             return PAPI_EINVAL;
00180     }
00181 }
00182 
00183 int
00184 _papi_libpfm_ntv_name_to_code( char *name, unsigned int *event_code )
00185 {
00186     pfmlib_event_t event;
00187     unsigned int i;
00188     int ret;
00189 
00190     SUBDBG( "pfm_find_full_event(%s,%p)\n", name, &event );
00191     ret = pfm_find_full_event( name, &event );
00192     if ( ret == PFMLIB_SUCCESS ) {
00193         SUBDBG( "Full event name found\n" );
00194         /* we can only capture PAPI_NATIVE_UMASK_MAX or fewer masks */
00195         if ( event.num_masks > PAPI_NATIVE_UMASK_MAX ) {
00196             SUBDBG( "num_masks (%d) > max masks (%d)\n", event.num_masks,
00197                     PAPI_NATIVE_UMASK_MAX );
00198             return PAPI_ENOEVNT;
00199         } else {
00200             /* no mask index can exceed PAPI_NATIVE_UMASK_MAX */
00201             for ( i = 0; i < event.num_masks; i++ ) {
00202                 if ( event.unit_masks[i] > PAPI_NATIVE_UMASK_MAX ) {
00203                     SUBDBG( "mask index (%d) > max masks (%d)\n",
00204                             event.unit_masks[i], PAPI_NATIVE_UMASK_MAX );
00205                     return PAPI_ENOEVNT;
00206                 }
00207             }
00208             *event_code =
00209                 encode_native_event( event.event, event.num_masks,
00210                                      event.unit_masks );
00211             return PAPI_OK;
00212         }
00213     } else if ( ret == PFMLIB_ERR_UMASK ) {
00214         SUBDBG( "UMASK error, looking for base event only\n" );
00215         ret = pfm_find_event( name, &event.event );
00216         if ( ret == PFMLIB_SUCCESS ) {
00217             *event_code = encode_native_event( event.event, 0, 0 );
00218             return PAPI_EATTR;
00219         }
00220     }
00221     return PAPI_ENOEVNT;
00222 }
00223 
00224 int
00225 _papi_libpfm_ntv_code_to_name( unsigned int EventCode, char *ntv_name, int len )
00226 {
00227     int ret;
00228     unsigned int event, umask;
00229     pfmlib_event_t gete;
00230 
00231     memset( &gete, 0, sizeof ( gete ) );
00232 
00233     if ( _pfm_decode_native_event( EventCode, &event, &umask ) != PAPI_OK )
00234         return ( PAPI_ENOEVNT );
00235 
00236     gete.event = event;
00237     gete.num_masks = ( unsigned int ) prepare_umask( umask, gete.unit_masks );
00238     if ( gete.num_masks == 0 )
00239         ret = pfm_get_event_name( gete.event, ntv_name, ( size_t ) len );
00240     else
00241         ret = pfm_get_full_event_name( &gete, ntv_name, ( size_t ) len );
00242     if ( ret != PFMLIB_SUCCESS ) {
00243         char tmp[PAPI_2MAX_STR_LEN];
00244         pfm_get_event_name( gete.event, tmp, sizeof ( tmp ) );
00245         /* Skip error message if event is not supported by host cpu;
00246          * we don't need to give this info away for papi_native_avail util */
00247         if ( ret != PFMLIB_ERR_BADHOST )
00248             PAPIERROR
00249                 ( "pfm_get_full_event_name(%p(event %d,%s,%d masks),%p,%d): %d -- %s",
00250                   &gete, gete.event, tmp, gete.num_masks, ntv_name, len, ret,
00251                   pfm_strerror( ret ) );
00252         if ( ret == PFMLIB_ERR_FULL ) {
00253             return PAPI_EBUF;
00254         }
00255 
00256         return PAPI_EMISC;
00257     }
00258     return PAPI_OK;
00259 }
00260 
00261 int
00262 _papi_libpfm_ntv_code_to_descr( unsigned int EventCode, char *ntv_descr, int len )
00263 {
00264     unsigned int event, umask;
00265     char *eventd, **maskd, *tmp;
00266     int i, ret;
00267     pfmlib_event_t gete;
00268     size_t total_len = 0;
00269 
00270     memset( &gete, 0, sizeof ( gete ) );
00271 
00272     if ( _pfm_decode_native_event( EventCode, &event, &umask ) != PAPI_OK )
00273         return ( PAPI_ENOEVNT );
00274 
00275     ret = pfm_get_event_description( event, &eventd );
00276     if ( ret != PFMLIB_SUCCESS ) {
00277         PAPIERROR( "pfm_get_event_description(%d,%p): %s",
00278                    event, &eventd, pfm_strerror( ret ) );
00279         return ( PAPI_ENOEVNT );
00280     }
00281 
00282     if ( ( gete.num_masks =
00283            ( unsigned int ) prepare_umask( umask, gete.unit_masks ) ) ) {
00284         maskd = ( char ** ) malloc( gete.num_masks * sizeof ( char * ) );
00285         if ( maskd == NULL ) {
00286             free( eventd );
00287             return ( PAPI_ENOMEM );
00288         }
00289         for ( i = 0; i < ( int ) gete.num_masks; i++ ) {
00290             ret =
00291                 pfm_get_event_mask_description( event, gete.unit_masks[i],
00292                                                 &maskd[i] );
00293             if ( ret != PFMLIB_SUCCESS ) {
00294                 PAPIERROR( "pfm_get_event_mask_description(%d,%d,%p): %s",
00295                            event, umask, &maskd, pfm_strerror( ret ) );
00296                 free( eventd );
00297                 for ( ; i >= 0; i-- )
00298                     free( maskd[i] );
00299                 free( maskd );
00300                 return ( PAPI_EINVAL );
00301             }
00302             total_len += strlen( maskd[i] );
00303         }
00304         tmp =
00305             ( char * ) malloc( strlen( eventd ) + strlen( ", masks:" ) +
00306                                total_len + gete.num_masks + 1 );
00307         if ( tmp == NULL ) {
00308             for ( i = ( int ) gete.num_masks - 1; i >= 0; i-- )
00309                 free( maskd[i] );
00310             free( maskd );
00311             free( eventd );
00312         }
00313         tmp[0] = '\0';
00314         strcat( tmp, eventd );
00315         strcat( tmp, ", masks:" );
00316         for ( i = 0; i < ( int ) gete.num_masks; i++ ) {
00317             if ( i != 0 )
00318                 strcat( tmp, "," );
00319             strcat( tmp, maskd[i] );
00320             free( maskd[i] );
00321         }
00322         free( maskd );
00323     } else {
00324         tmp = ( char * ) malloc( strlen( eventd ) + 1 );
00325         if ( tmp == NULL ) {
00326             free( eventd );
00327             return ( PAPI_ENOMEM );
00328         }
00329         tmp[0] = '\0';
00330         strcat( tmp, eventd );
00331         free( eventd );
00332     }
00333     strncpy( ntv_descr, tmp, ( size_t ) len );
00334     if ( ( int ) strlen( tmp ) > len - 1 )
00335         ret = PAPI_EBUF;
00336     else
00337         ret = PAPI_OK;
00338     free( tmp );
00339     return ( ret );
00340 }
00341 
00342 
00343 int
00344 _papi_libpfm_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info)
00345 {
00346 
00347   SUBDBG("ENTER %x\n",EventCode);
00348 
00349   _papi_libpfm_ntv_code_to_name(EventCode,info->symbol,
00350                                  sizeof(info->symbol));
00351 
00352   _papi_libpfm_ntv_code_to_descr(EventCode,info->long_descr,
00353                                  sizeof(info->long_descr));
00354 
00355   return PAPI_OK;
00356 }
00357 
00358 
00359 int
00360 _papi_libpfm_ntv_enum_events( unsigned int *EventCode, int modifier )
00361 {
00362     unsigned int event, umask, num_masks;
00363     int ret;
00364 
00365     if ( modifier == PAPI_ENUM_FIRST ) {
00366         *EventCode = PAPI_NATIVE_MASK;  /* assumes first native event is always 0x4000000 */
00367         return ( PAPI_OK );
00368     }
00369 
00370     if ( _pfm_decode_native_event( *EventCode, &event, &umask ) != PAPI_OK )
00371         return ( PAPI_ENOEVNT );
00372 
00373     ret = pfm_get_num_event_masks( event, &num_masks );
00374     if ( ret != PFMLIB_SUCCESS ) {
00375         PAPIERROR( "pfm_get_num_event_masks(%d,%p): %s", event, &num_masks,
00376                    pfm_strerror( ret ) );
00377         return ( PAPI_ENOEVNT );
00378     }
00379     if ( num_masks > PAPI_NATIVE_UMASK_MAX )
00380         num_masks = PAPI_NATIVE_UMASK_MAX;
00381     SUBDBG( "This is umask %d of %d\n", umask, num_masks );
00382 
00383     if ( modifier == PAPI_ENUM_EVENTS ) {
00384         if ( event < ( unsigned int ) num_native_events - 1 ) {
00385             *EventCode =
00386                 ( unsigned int ) encode_native_event_raw( event + 1, 0 );
00387             return ( PAPI_OK );
00388         }
00389         return ( PAPI_ENOEVNT );
00390     } else if ( modifier == PAPI_NTV_ENUM_UMASK_COMBOS ) {
00391         if ( umask + 1 < ( unsigned int ) ( 1 << num_masks ) ) {
00392             *EventCode =
00393                 ( unsigned int ) encode_native_event_raw( event, umask + 1 );
00394             return ( PAPI_OK );
00395         }
00396         return ( PAPI_ENOEVNT );
00397     } else if ( modifier == PAPI_NTV_ENUM_UMASKS ) {
00398         int thisbit = ffs( ( int ) umask );
00399 
00400         SUBDBG( "First bit is %d in %08x\b\n", thisbit - 1, umask );
00401         thisbit = 1 << thisbit;
00402 
00403         if ( thisbit & ( ( 1 << num_masks ) - 1 ) ) {
00404             *EventCode =
00405                 ( unsigned int ) encode_native_event_raw( event,
00406                                                           ( unsigned int )
00407                                                           thisbit );
00408             return ( PAPI_OK );
00409         }
00410         return ( PAPI_ENOEVNT );
00411     } else
00412         return ( PAPI_EINVAL );
00413 }
00414 
00415 int
00416 _papi_libpfm_ntv_code_to_bits( unsigned int EventCode, hwd_register_t * bits )
00417 {
00418     unsigned int event, umask;
00419     pfmlib_event_t gete;
00420 
00421     /* For PFM & Perfmon, native info is just an index into PFM event table. */
00422     if ( _pfm_decode_native_event( EventCode, &event, &umask ) != PAPI_OK )
00423        return PAPI_ENOEVNT;
00424 
00425     memset( &gete, 0x0, sizeof ( pfmlib_event_t ) );
00426 
00427     gete.event = event;
00428     gete.num_masks = prepare_umask( umask, gete.unit_masks );
00429 
00430     memcpy( bits, &gete, sizeof ( pfmlib_event_t ) );
00431 
00432     return PAPI_OK;
00433 
00434 }
00435 
00436 
00437 /* used by linux-timer.c for ia64 */
00438 int _perfmon2_pfm_pmu_type = -1;
00439 
00440 
00441 int
00442 _papi_libpfm_init(papi_vector_t *my_vector, int cidx) {
00443 
00444    int retval;
00445    unsigned int ncnt;
00446    unsigned int version;
00447    char pmu_name[PAPI_MIN_STR_LEN];
00448 
00449 
00450    /* The following checks the version of the PFM library
00451       against the version PAPI linked to... */
00452    SUBDBG( "pfm_initialize()\n" );
00453    if ( ( retval = pfm_initialize(  ) ) != PFMLIB_SUCCESS ) {
00454       PAPIERROR( "pfm_initialize(): %s", pfm_strerror( retval ) );
00455       return PAPI_ESYS;
00456    }
00457 
00458    /* Get the libpfm3 version */
00459    SUBDBG( "pfm_get_version(%p)\n", &version );
00460    if ( pfm_get_version( &version ) != PFMLIB_SUCCESS ) {
00461       PAPIERROR( "pfm_get_version(%p): %s", version, pfm_strerror( retval ) );
00462       return PAPI_ESYS;
00463    }
00464 
00465    /* Set the version */
00466    sprintf( my_vector->cmp_info.support_version, "%d.%d",
00467         PFM_VERSION_MAJOR( version ), PFM_VERSION_MINOR( version ) );
00468 
00469    /* Complain if the compiled-against version doesn't match current version */
00470    if ( PFM_VERSION_MAJOR( version ) != PFM_VERSION_MAJOR( PFMLIB_VERSION ) ) {
00471       PAPIERROR( "Version mismatch of libpfm: compiled %x vs. installed %x\n",
00472                    PFM_VERSION_MAJOR( PFMLIB_VERSION ),
00473                    PFM_VERSION_MAJOR( version ) );
00474       return PAPI_ESYS;
00475    }
00476 
00477    /* Always initialize globals dynamically to handle forks properly. */
00478 
00479    _perfmon2_pfm_pmu_type = -1;
00480 
00481    /* Opened once for all threads. */
00482    SUBDBG( "pfm_get_pmu_type(%p)\n", &_perfmon2_pfm_pmu_type );
00483    if ( pfm_get_pmu_type( &_perfmon2_pfm_pmu_type ) != PFMLIB_SUCCESS ) {
00484       PAPIERROR( "pfm_get_pmu_type(%p): %s", _perfmon2_pfm_pmu_type,
00485                    pfm_strerror( retval ) );
00486       return PAPI_ESYS;
00487    }
00488 
00489    pmu_name[0] = '\0';
00490    if ( pfm_get_pmu_name( pmu_name, PAPI_MIN_STR_LEN ) != PFMLIB_SUCCESS ) {
00491       PAPIERROR( "pfm_get_pmu_name(%p,%d): %s", pmu_name, PAPI_MIN_STR_LEN,
00492                    pfm_strerror( retval ) );
00493       return PAPI_ESYS;
00494    }
00495    SUBDBG( "PMU is a %s, type %d\n", pmu_name, _perfmon2_pfm_pmu_type );
00496 
00497    /* Setup presets */
00498    retval = _papi_load_preset_table( pmu_name, _perfmon2_pfm_pmu_type, cidx );
00499    if ( retval )
00500       return retval;
00501 
00502    /* Fill in cmp_info */
00503 
00504    SUBDBG( "pfm_get_num_events(%p)\n", &ncnt );
00505    if ( ( retval = pfm_get_num_events( &ncnt ) ) != PFMLIB_SUCCESS ) {
00506       PAPIERROR( "pfm_get_num_events(%p): %s\n", &ncnt,
00507                    pfm_strerror( retval ) );
00508       return PAPI_ESYS;
00509    }
00510    SUBDBG( "pfm_get_num_events: %d\n", ncnt );
00511    my_vector->cmp_info.num_native_events = ncnt;
00512    num_native_events = ncnt;
00513 
00514    pfm_get_num_counters( ( unsigned int * ) &my_vector->cmp_info.num_cntrs );
00515    SUBDBG( "pfm_get_num_counters: %d\n", my_vector->cmp_info.num_cntrs );
00516 
00517 
00518    if ( _papi_hwi_system_info.hw_info.vendor == PAPI_VENDOR_INTEL ) {
00519      /* Pentium4 */
00520      if ( _papi_hwi_system_info.hw_info.cpuid_family == 15 ) {
00521        PAPI_NATIVE_EVENT_AND_MASK = 0x000000ff;
00522        PAPI_NATIVE_UMASK_AND_MASK = 0x0fffff00;
00523        PAPI_NATIVE_UMASK_SHIFT = 8;
00524        /* Itanium2 */
00525      } else if ( _papi_hwi_system_info.hw_info.cpuid_family == 31 ||
00526          _papi_hwi_system_info.hw_info.cpuid_family == 32 ) {
00527        PAPI_NATIVE_EVENT_AND_MASK = 0x00000fff;
00528        PAPI_NATIVE_UMASK_AND_MASK = 0x0ffff000;
00529        PAPI_NATIVE_UMASK_SHIFT = 12;
00530      }
00531    }
00532 
00533 
00534    return PAPI_OK;
00535 }
00536 
00537 long long generate_p4_event(long long escr,
00538                 long long cccr,
00539                 long long escr_addr) {
00540            
00541 /*
00542  * RAW events specification
00543  *
00544  * Bits                Meaning
00545  * -----       -------
00546  *  0-6        Metric value from enum P4_PEBS_METRIC (if needed)
00547  *  7-11       Reserved, set to 0
00548  * 12-31       Bits 12-31 of CCCR register (Intel SDM Vol 3)
00549  * 32-56       Bits  0-24 of ESCR register (Intel SDM Vol 3)
00550  * 57-62       Event key from enum P4_EVENTS
00551  *    63       Reserved, set to 0
00552  */
00553            
00554  enum P4_EVENTS {
00555       P4_EVENT_TC_DELIVER_MODE,
00556       P4_EVENT_BPU_FETCH_REQUEST,
00557       P4_EVENT_ITLB_REFERENCE,
00558       P4_EVENT_MEMORY_CANCEL,
00559       P4_EVENT_MEMORY_COMPLETE,
00560       P4_EVENT_LOAD_PORT_REPLAY,
00561       P4_EVENT_STORE_PORT_REPLAY,
00562       P4_EVENT_MOB_LOAD_REPLAY,
00563       P4_EVENT_PAGE_WALK_TYPE,
00564       P4_EVENT_BSQ_CACHE_REFERENCE,
00565       P4_EVENT_IOQ_ALLOCATION,
00566       P4_EVENT_IOQ_ACTIVE_ENTRIES,
00567       P4_EVENT_FSB_DATA_ACTIVITY,
00568       P4_EVENT_BSQ_ALLOCATION,
00569       P4_EVENT_BSQ_ACTIVE_ENTRIES,
00570       P4_EVENT_SSE_INPUT_ASSIST,
00571       P4_EVENT_PACKED_SP_UOP,
00572       P4_EVENT_PACKED_DP_UOP,
00573       P4_EVENT_SCALAR_SP_UOP,
00574       P4_EVENT_SCALAR_DP_UOP,
00575       P4_EVENT_64BIT_MMX_UOP,
00576       P4_EVENT_128BIT_MMX_UOP,
00577       P4_EVENT_X87_FP_UOP,
00578       P4_EVENT_TC_MISC,
00579       P4_EVENT_GLOBAL_POWER_EVENTS,
00580       P4_EVENT_TC_MS_XFER,
00581       P4_EVENT_UOP_QUEUE_WRITES,
00582       P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE,
00583       P4_EVENT_RETIRED_BRANCH_TYPE,
00584       P4_EVENT_RESOURCE_STALL,
00585       P4_EVENT_WC_BUFFER,
00586       P4_EVENT_B2B_CYCLES,
00587       P4_EVENT_BNR,
00588       P4_EVENT_SNOOP,
00589       P4_EVENT_RESPONSE,
00590       P4_EVENT_FRONT_END_EVENT,
00591       P4_EVENT_EXECUTION_EVENT,
00592       P4_EVENT_REPLAY_EVENT,
00593       P4_EVENT_INSTR_RETIRED,
00594       P4_EVENT_UOPS_RETIRED,
00595       P4_EVENT_UOP_TYPE,
00596       P4_EVENT_BRANCH_RETIRED,
00597       P4_EVENT_MISPRED_BRANCH_RETIRED,
00598       P4_EVENT_X87_ASSIST,
00599       P4_EVENT_MACHINE_CLEAR,
00600       P4_EVENT_INSTR_COMPLETED,
00601    };
00602            
00603                    
00604     int eventsel=(escr>>25)&0x3f;
00605     int cccrsel=(cccr>>13)&0x7;
00606     int event_key=-1;
00607     long long pe_event;
00608            
00609     switch(eventsel) {
00610        case 0x1: if (cccrsel==1) {
00611             if (escr_addr>0x3c8) {
00612                // tc_escr0,1 0x3c4 
00613                event_key=P4_EVENT_TC_DELIVER_MODE; 
00614             }
00615             else {
00616                // alf_escr0, 0x3ca    
00617                event_key=P4_EVENT_RESOURCE_STALL;
00618             }
00619          }
00620          if (cccrsel==4) {      
00621             if (escr_addr<0x3af) {
00622                // pmh_escr0,1 0x3ac
00623                event_key=P4_EVENT_PAGE_WALK_TYPE;
00624             }
00625             else {
00626                // cru_escr0, 3b8 cccr=04
00627                event_key=P4_EVENT_UOPS_RETIRED;
00628             }
00629          }
00630          break;
00631             case 0x2: if (cccrsel==5) {
00632                          if (escr_addr<0x3a8) { 
00633                             // MSR_DAC_ESCR0 / MSR_DAC_ESCR1
00634                             event_key=P4_EVENT_MEMORY_CANCEL; 
00635                  } else {
00636                    //MSR_CRU_ESCR2, MSR_CRU_ESCR3
00637                    event_key=P4_EVENT_MACHINE_CLEAR;
00638                  }
00639                   } else if (cccrsel==1) {
00640                          event_key=P4_EVENT_64BIT_MMX_UOP;
00641                   } else if (cccrsel==4) {
00642                      event_key=P4_EVENT_INSTR_RETIRED;
00643                   } else if (cccrsel==2) {
00644                      event_key=P4_EVENT_UOP_TYPE;
00645                   }
00646                   break;
00647             case 0x3: if (cccrsel==0) {
00648                          event_key=P4_EVENT_BPU_FETCH_REQUEST;
00649                       }
00650                               if (cccrsel==2) {
00651                          event_key=P4_EVENT_MOB_LOAD_REPLAY;
00652                   }
00653                       if (cccrsel==6) {
00654                      event_key=P4_EVENT_IOQ_ALLOCATION;
00655                   }
00656                       if (cccrsel==4) {
00657                      event_key=P4_EVENT_MISPRED_BRANCH_RETIRED;
00658                       }
00659                   if (cccrsel==5) { 
00660                  event_key=P4_EVENT_X87_ASSIST;
00661                       }
00662                   break;
00663             case 0x4: if (cccrsel==2) {
00664                          if (escr_addr<0x3b0) {
00665                     // saat, 0x3ae 
00666                             event_key=P4_EVENT_LOAD_PORT_REPLAY; 
00667                          }
00668                          else {
00669                     // tbpu 0x3c2
00670                             event_key=P4_EVENT_RETIRED_BRANCH_TYPE;
00671                  }
00672                       }
00673                       if (cccrsel==1) {
00674                          event_key=P4_EVENT_X87_FP_UOP;
00675                       }
00676                   if (cccrsel==3) {
00677                      event_key=P4_EVENT_RESPONSE;
00678                       }
00679                   break;
00680                     case 0x5: if (cccrsel==2) {
00681                          if (escr_addr<0x3b0) {
00682                             // saat, 0x3ae 
00683                             event_key=P4_EVENT_STORE_PORT_REPLAY;
00684                  }
00685                          else {
00686                             // tbpu, 0x3c2
00687                             event_key=P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE;
00688                  }
00689                       }
00690                       if (cccrsel==7) {
00691                          event_key=P4_EVENT_BSQ_ALLOCATION;
00692                       }
00693                       if (cccrsel==0) {
00694                      event_key=P4_EVENT_TC_MS_XFER;
00695                       }
00696                   if (cccrsel==5) {
00697                      event_key=P4_EVENT_WC_BUFFER;
00698                       }
00699                   break;
00700             case 0x6: if (cccrsel==7) {
00701                          event_key=P4_EVENT_BSQ_ACTIVE_ENTRIES; 
00702                       }
00703                       if (cccrsel==1) {
00704                          event_key=P4_EVENT_TC_MISC;
00705                   }
00706                   if (cccrsel==3) {
00707                  event_key=P4_EVENT_SNOOP;
00708                   }
00709                       if (cccrsel==5) {
00710                      event_key=P4_EVENT_BRANCH_RETIRED;
00711                   }
00712                   break;
00713             case 0x7: event_key=P4_EVENT_INSTR_COMPLETED; break;
00714             case 0x8: if (cccrsel==2) {
00715                          event_key=P4_EVENT_MEMORY_COMPLETE; 
00716                       }
00717                       if (cccrsel==1) {
00718                  event_key=P4_EVENT_PACKED_SP_UOP;
00719                   }
00720                   if (cccrsel==3) {
00721                  event_key=P4_EVENT_BNR;
00722                       }
00723                   if (cccrsel==5) {
00724                  event_key=P4_EVENT_FRONT_END_EVENT;
00725                       }
00726                   break;
00727                     case 0x9: if (cccrsel==0) {
00728                          event_key=P4_EVENT_UOP_QUEUE_WRITES; 
00729                       }
00730                       if (cccrsel==5) {
00731                  event_key=P4_EVENT_REPLAY_EVENT;
00732                   }
00733                   break;
00734                     case 0xa: event_key=P4_EVENT_SCALAR_SP_UOP; break;
00735                     case 0xc: if (cccrsel==7) {
00736                          event_key=P4_EVENT_BSQ_CACHE_REFERENCE; 
00737                       }
00738                       if (cccrsel==1) {
00739                          event_key=P4_EVENT_PACKED_DP_UOP;
00740                   }
00741                   if (cccrsel==5) {
00742                  event_key=P4_EVENT_EXECUTION_EVENT;
00743                   }
00744                   break;
00745             case 0xe: event_key=P4_EVENT_SCALAR_DP_UOP; break;
00746             case 0x13: event_key=P4_EVENT_GLOBAL_POWER_EVENTS; break;
00747                     case 0x16: event_key=P4_EVENT_B2B_CYCLES; break;
00748             case 0x17: event_key=P4_EVENT_FSB_DATA_ACTIVITY; break;
00749             case 0x18: event_key=P4_EVENT_ITLB_REFERENCE; break;
00750                     case 0x1a: if (cccrsel==6) {
00751                           event_key=P4_EVENT_IOQ_ACTIVE_ENTRIES; 
00752                        }
00753                        if (cccrsel==1) {
00754                       event_key=P4_EVENT_128BIT_MMX_UOP;
00755           }
00756           break;
00757        case 0x34: event_key= P4_EVENT_SSE_INPUT_ASSIST; break;
00758     }
00759            
00760     pe_event=(escr&0x1ffffff)<<32;
00761     pe_event|=(cccr&0xfffff000);            
00762     pe_event|=(((long long)(event_key))<<57);
00763    
00764     return pe_event;
00765 }
00766 
00767 typedef pfmlib_event_t pfm_register_t;
00768 
00769 int
00770 _papi_libpfm_setup_counters( struct perf_event_attr *attr, 
00771                hwd_register_t *ni_bits ) {
00772 
00773   int ret,pe_event;
00774   (void)ni_bits;
00775 
00776     /*
00777      * We need an event code that is common across all counters.
00778      * The implementation is required to know how to translate the supplied
00779      * code to whichever counter it ends up on.
00780      */
00781 
00782 #if defined(__powerpc__)
00783     int code;
00784     ret = pfm_get_event_code_counter( ( ( pfm_register_t * ) ni_bits )->event, 0, &code );
00785     if ( ret ) {
00786        /* Unrecognized code, but should never happen */
00787        return PAPI_EBUG;
00788     }
00789     pe_event = code;
00790     SUBDBG( "Stuffing native event index (code 0x%x, raw code 0x%x) into events array.\n",
00791                   ( ( pfm_register_t * ) ni_bits )->event, code );
00792 #else
00793 
00794    pfmlib_input_param_t inp;
00795    pfmlib_output_param_t outp;
00796 
00797    memset( &inp, 0, sizeof ( inp ) );
00798    memset( &outp, 0, sizeof ( outp ) );
00799    inp.pfp_event_count = 1;
00800    inp.pfp_dfl_plm = PAPI_DOM_USER;
00801    pfm_regmask_set( &inp.pfp_unavail_pmcs, 16 );    // mark fixed counters as unavailable
00802 
00803     inp.pfp_events[0] = *( ( pfm_register_t * ) ni_bits );
00804     ret = pfm_dispatch_events( &inp, NULL, &outp, NULL );
00805     if (ret != PFMLIB_SUCCESS) {
00806        SUBDBG( "Error: pfm_dispatch_events returned: %d\n", ret);
00807        return PAPI_ESYS;
00808     }
00809             
00810        /* Special case p4 */
00811     if (( _papi_hwi_system_info.hw_info.vendor == PAPI_VENDOR_INTEL ) && 
00812         ( _papi_hwi_system_info.hw_info.cpuid_family == 15)) {
00813 
00814     pe_event=generate_p4_event( outp.pfp_pmcs[0].reg_value, /* escr */  
00815                             outp.pfp_pmcs[1].reg_value, /* cccr */
00816                             outp.pfp_pmcs[0].reg_addr); /* escr_addr */
00817     }
00818     else {
00819         pe_event = outp.pfp_pmcs[0].reg_value;   
00820     }
00821     SUBDBG( "pe_event: 0x%llx\n", outp.pfp_pmcs[0].reg_value );
00822 #endif
00823 
00824     attr->config=pe_event;
00825 
00826     /* for libpfm3 we currently only handle RAW type */
00827     attr->type=PERF_TYPE_RAW;
00828 
00829     return PAPI_OK;
00830 }
00831 
00832 int 
00833 _papi_libpfm_shutdown(void) {
00834 
00835   SUBDBG("shutdown\n");
00836 
00837   return PAPI_OK;
00838 }
00839 
00840 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines