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