|
PAPI
5.1.0.2
|
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