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