|
PAPI
5.0.1.0
|
00001 /* 00002 * File: perfmon-ia64.c 00003 * Author: Philip Mucci 00004 * mucci@cs.utk.edu 00005 * Mods: Kevin London 00006 * london@cs.utk.edu 00007 * Per Ekman 00008 * pek@pdc.kth.se 00009 * Zhou Min 00010 * min@cs.utk.edu 00011 */ 00012 00013 00014 #include "papi.h" 00015 #include "papi_internal.h" 00016 #include "papi_vector.h" 00017 #include "threads.h" 00018 #include "papi_memory.h" 00019 #include "papi_lock.h" 00020 00021 #include "linux-memory.h" 00022 #include "linux-timer.h" 00023 #include "linux-common.h" 00024 00025 #if defined(__INTEL_COMPILER) 00026 00027 #define hweight64(x) _m64_popcnt(x) 00028 00029 #elif defined(__GNUC__) 00030 00031 static inline int 00032 hweight64( unsigned long x ) 00033 { 00034 unsigned long result; 00035 __asm__( "popcnt %0=%1": "=r"( result ):"r"( x ) ); 00036 return ( int ) result; 00037 } 00038 00039 #else 00040 #error "you need to provide inline assembly from your compiler" 00041 #endif 00042 00043 extern int _perfmon2_pfm_pmu_type; 00044 extern papi_vector_t _ia64_vector; 00045 00046 #define OVFL_SIGNAL SIGPROF 00047 #define PFMW_PEVT_EVTCOUNT(evt) (evt->inp.pfp_event_count) 00048 #define PFMW_PEVT_EVENT(evt,idx) (evt->inp.pfp_events[idx].event) 00049 #define PFMW_PEVT_PLM(evt,idx) (evt->inp.pfp_events[idx].plm) 00050 #define PFMW_PEVT_DFLPLM(evt) (evt->inp.pfp_dfl_plm) 00051 #define PFMW_PEVT_PFPPC(evt) (evt->pc) 00052 #define PFMW_PEVT_PFPPD(evt) (evt->pd) 00053 #define PFMW_PEVT_PFPPC_COUNT(evt) (evt->outp.pfp_pmc_count) 00054 #define PFMW_PEVT_PFPPC_REG_NUM(evt,idx) (evt->outp.pfp_pmcs[idx].reg_num) 00055 #define PFMW_PEVT_PFPPC_REG_VAL(evt,idx) (evt->pc[idx].reg_value) 00056 #define PFMW_PEVT_PFPPC_REG_FLG(evt,idx) (evt->pc[idx].reg_flags) 00057 #define PFMW_ARCH_REG_PMCVAL(reg) (reg.pmc_val) 00058 #define PFMW_ARCH_REG_PMDVAL(reg) (reg.pmd_val) 00059 00060 #define PFMON_MONT_MAX_IBRS 8 00061 #define PFMON_MONT_MAX_DBRS 8 00062 00063 #define PFMON_ITA2_MAX_IBRS 8 00064 #define PFMON_ITA2_MAX_DBRS 8 00065 /* 00066 #if defined(ITANIUM3) 00067 #define PFMW_ARCH_REG_PMCPLM(reg) (reg.pmc_mont_counter_reg.pmc_plm) 00068 #define PFMW_ARCH_REG_PMCES(reg) (reg.pmc_mont_counter_reg.pmc_es) 00069 typedef pfm_mont_pmc_reg_t pfmw_arch_pmc_reg_t; 00070 typedef pfm_mont_pmd_reg_t pfmw_arch_pmd_reg_t; 00071 #elif defined(ITANIUM2) 00072 #define PFMW_ARCH_REG_PMCPLM(reg) (reg.pmc_ita2_counter_reg.pmc_plm) 00073 #define PFMW_ARCH_REG_PMCES(reg) (reg.pmc_ita2_counter_reg.pmc_es) 00074 typedef pfm_ita2_pmc_reg_t pfmw_arch_pmc_reg_t; 00075 typedef pfm_ita2_pmd_reg_t pfmw_arch_pmd_reg_t; 00076 #else 00077 #define PFMW_ARCH_REG_PMCPLM(reg) (reg.pmc_ita_count_reg.pmc_plm) 00078 #define PFMW_ARCH_REG_PMCES(reg) (reg.pmc_ita_count_reg.pmc_es) 00079 typedef pfm_ita_pmc_reg_t pfmw_arch_pmc_reg_t; 00080 typedef pfm_ita_pmd_reg_t pfmw_arch_pmd_reg_t; 00081 #endif 00082 */ 00083 typedef pfm_default_smpl_hdr_t pfmw_smpl_hdr_t; 00084 typedef pfm_default_smpl_entry_t pfmw_smpl_entry_t; 00085 00086 static void 00087 pfmw_start( hwd_context_t * ctx ) 00088 { 00089 pfm_self_start( ( ( ia64_context_t * ) ctx )->fd ); 00090 } 00091 00092 static void 00093 pfmw_stop( hwd_context_t * ctx ) 00094 { 00095 pfm_self_stop( ( ( ia64_context_t * ) ctx )->fd ); 00096 } 00097 00098 static int 00099 pfmw_perfmonctl( pid_t tid, int fd, int cmd, void *arg, int narg ) 00100 { 00101 ( void ) tid; /*unused */ 00102 return ( perfmonctl( fd, cmd, arg, narg ) ); 00103 } 00104 00105 static int 00106 pfmw_destroy_context( hwd_context_t * thr_ctx ) 00107 { 00108 int ret; 00109 ret = close( ( ( ia64_context_t * ) thr_ctx )->fd ); 00110 if ( ret ) 00111 return PAPI_ESYS; 00112 else 00113 return PAPI_OK; 00114 } 00115 00116 static int 00117 pfmw_dispatch_events( pfmw_param_t * evt ) 00118 { 00119 int ret; 00120 unsigned int i; 00121 /* 00122 PFMW_PEVT_DFLPLM(evt) = PFM_PLM3; 00123 */ 00124 #ifdef PFMLIB_MONTECITO_PMU 00125 if ( _perfmon2_pfm_pmu_type == PFMLIB_MONTECITO_PMU ) 00126 ret = 00127 pfm_dispatch_events( &evt->inp, 00128 ( pfmlib_mont_input_param_t * ) evt->mod_inp, 00129 &evt->outp, 00130 ( pfmlib_mont_output_param_t * ) evt-> 00131 mod_outp ); 00132 else 00133 #endif 00134 ret = 00135 pfm_dispatch_events( &evt->inp, 00136 ( pfmlib_ita2_input_param_t * ) evt->mod_inp, 00137 &evt->outp, 00138 ( pfmlib_ita2_output_param_t * ) evt-> 00139 mod_outp ); 00140 if ( ret ) { 00141 return PAPI_ESYS; 00142 } else { 00143 for ( i = 0; i < evt->outp.pfp_pmc_count; i++ ) { 00144 evt->pc[i].reg_num = evt->outp.pfp_pmcs[i].reg_num; 00145 evt->pc[i].reg_value = evt->outp.pfp_pmcs[i].reg_value; 00146 } 00147 #if defined(HAVE_PFMLIB_OUTPUT_PFP_PMD_COUNT) 00148 for ( i = 0; i < evt->outp.pfp_pmd_count; i++ ) { 00149 evt->pd[i].reg_num = evt->outp.pfp_pmds[i].reg_num; 00150 } 00151 #else 00152 /* This is really broken */ 00153 for ( i = 0; i < evt->inp.pfp_event_count; i++ ) { 00154 evt->pd[i].reg_num = evt->pc[i].reg_num; 00155 } 00156 #endif 00157 return PAPI_OK; 00158 } 00159 } 00160 00161 static int 00162 pfmw_create_ctx_common( hwd_context_t * ctx ) 00163 { 00164 pfarg_load_t load_args; 00165 int ret; 00166 00167 memset( &load_args, 0, sizeof ( load_args ) ); 00168 /* 00169 * we want to monitor ourself 00170 */ 00171 00172 load_args.load_pid = ( ( ia64_context_t * ) ctx )->tid; 00173 00174 SUBDBG( "PFM_LOAD_CONTEXT FD %d, PID %d\n", 00175 ( ( ia64_context_t * ) ctx )->fd, 00176 ( ( ia64_context_t * ) ctx )->tid ); 00177 if ( perfmonctl 00178 ( ( ( ia64_context_t * ) ctx )->fd, PFM_LOAD_CONTEXT, &load_args, 00179 1 ) == -1 ) { 00180 PAPIERROR( "perfmonctl(PFM_LOAD_CONTEXT) errno %d", errno ); 00181 return ( PAPI_ESYS ); 00182 } 00183 /* 00184 * setup asynchronous notification on the file descriptor 00185 */ 00186 ret = 00187 fcntl( ( ( ia64_context_t * ) ctx )->fd, F_SETFL, 00188 fcntl( ( ( ia64_context_t * ) ctx )->fd, F_GETFL, 00189 0 ) | O_ASYNC ); 00190 if ( ret == -1 ) { 00191 PAPIERROR( "fcntl(%d,F_SETFL,O_ASYNC) errno %d", 00192 ( ( ia64_context_t * ) ctx )->fd, errno ); 00193 return ( PAPI_ESYS ); 00194 } 00195 00196 /* 00197 * get ownership of the descriptor 00198 */ 00199 00200 ret = 00201 fcntl( ( ( ia64_context_t * ) ctx )->fd, F_SETOWN, 00202 ( ( ia64_context_t * ) ctx )->tid ); 00203 if ( ret == -1 ) { 00204 PAPIERROR( "fcntl(%d,F_SETOWN) errno %d", 00205 ( ( ia64_context_t * ) ctx )->fd, errno ); 00206 return ( PAPI_ESYS ); 00207 } 00208 00209 ret = 00210 fcntl( ( ( ia64_context_t * ) ctx )->fd, F_SETSIG, 00211 _ia64_vector.cmp_info.hardware_intr_sig ); 00212 if ( ret == -1 ) { 00213 PAPIERROR( "fcntl(%d,F_SETSIG) errno %d", 00214 ( ( ia64_context_t * ) ctx )->fd, errno ); 00215 return ( PAPI_ESYS ); 00216 } 00217 00218 /* set close-on-exec to ensure we will be getting the PFM_END_MSG, i.e., 00219 * fd not visible to child. */ 00220 00221 ret = fcntl( ( ( ia64_context_t * ) ctx )->fd, F_SETFD, FD_CLOEXEC ); 00222 if ( ret == -1 ) { 00223 PAPIERROR( "fcntl(%d,FD_CLOEXEC) errno %d", 00224 ( ( ia64_context_t * ) ctx )->fd, errno ); 00225 return ( PAPI_ESYS ); 00226 } 00227 00228 return ( PAPI_OK ); 00229 00230 } 00231 00232 static int 00233 pfmw_create_context( hwd_context_t * thr_ctx ) 00234 { 00235 pfarg_context_t ctx; 00236 memset( &ctx, 0, sizeof ( ctx ) ); 00237 00238 SUBDBG( "PFM_CREATE_CONTEXT on 0\n" ); 00239 if ( perfmonctl( 0, PFM_CREATE_CONTEXT, &ctx, 1 ) == -1 ) { 00240 PAPIERROR( "perfmonctl(PFM_CREATE_CONTEXT) errno %d", errno ); 00241 return ( PAPI_ESYS ); 00242 } 00243 ( ( ia64_context_t * ) thr_ctx )->fd = ctx.ctx_fd; 00244 ( ( ia64_context_t * ) thr_ctx )->tid = mygettid( ); 00245 SUBDBG( "PFM_CREATE_CONTEXT returns FD %d, TID %d\n", 00246 ( int ) ( ( ia64_context_t * ) thr_ctx )->fd, 00247 ( int ) ( ( ia64_context_t * ) thr_ctx )->tid ); 00248 00249 return ( pfmw_create_ctx_common( thr_ctx ) ); 00250 } 00251 00252 static int 00253 set_pmds_to_write( EventSetInfo_t * ESI, int index, unsigned long value ) 00254 { 00255 int *pos, count, i; 00256 unsigned int hwcntr; 00257 ia64_control_state_t *this_state = 00258 ( ia64_control_state_t * ) ESI->ctl_state; 00259 pfmw_param_t *pevt = &( this_state->evt ); 00260 00261 pos = ESI->EventInfoArray[index].pos; 00262 count = 0; 00263 while ( pos[count] != -1 && count < MAX_COUNTERS ) { 00264 hwcntr = pos[count] + PMU_FIRST_COUNTER; 00265 for ( i = 0; i < MAX_COUNTERS; i++ ) { 00266 if ( PFMW_PEVT_PFPPC_REG_NUM( pevt, i ) == hwcntr ) { 00267 this_state->evt.pc[i].reg_smpl_pmds[0] = value; 00268 break; 00269 } 00270 } 00271 count++; 00272 } 00273 return ( PAPI_OK ); 00274 } 00275 00276 static int 00277 _pfm_decode_native_event( unsigned int EventCode, unsigned int *event, 00278 unsigned int *umask ); 00279 00280 static int 00281 pfmw_recreate_context( EventSetInfo_t * ESI, hwd_context_t * thr_ctx, 00282 void **smpl_vaddr, int EventIndex ) 00283 { 00284 pfm_default_smpl_ctx_arg_t ctx; 00285 pfm_uuid_t buf_fmt_id = PFM_DEFAULT_SMPL_UUID; 00286 int ctx_fd; 00287 unsigned int native_index, EventCode; 00288 int pos; 00289 //hwd_context_t *thr_ctx = (hwd_context_t *) &ESI->master->context; 00290 #ifdef PFMLIB_MONTECITO_PMU 00291 unsigned int umask; 00292 #endif 00293 00294 pos = ESI->EventInfoArray[EventIndex].pos[0]; 00295 EventCode = ESI->EventInfoArray[EventIndex].event_code; 00296 #ifdef PFMLIB_MONTECITO_PMU 00297 if ( _perfmon2_pfm_pmu_type == PFMLIB_MONTECITO_PMU ) { 00298 if ( _pfm_decode_native_event 00299 ( ESI->NativeInfoArray[pos].ni_event, &native_index, 00300 &umask ) != PAPI_OK ) 00301 return ( PAPI_ENOEVNT ); 00302 } else 00303 #endif 00304 native_index = 00305 ESI->NativeInfoArray[pos].ni_event & PAPI_NATIVE_AND_MASK; 00306 00307 memset( &ctx, 0, sizeof ( ctx ) ); 00308 /* 00309 * We initialize the format specific information. 00310 * The format is identified by its UUID which must be copied 00311 * into the ctx_buf_fmt_id field. 00312 */ 00313 memcpy( ctx.ctx_arg.ctx_smpl_buf_id, buf_fmt_id, sizeof ( pfm_uuid_t ) ); 00314 /* 00315 * the size of the buffer is indicated in bytes (not entries). 00316 * The kernel will record into the buffer up to a certain point. 00317 * No partial samples are ever recorded. 00318 */ 00319 ctx.buf_arg.buf_size = 4096; 00320 /* 00321 * now create the context for self monitoring/per-task 00322 */ 00323 SUBDBG( "PFM_CREATE_CONTEXT on 0\n" ); 00324 if ( perfmonctl( 0, PFM_CREATE_CONTEXT, &ctx, 1 ) == -1 ) { 00325 if ( errno == ENOSYS ) 00326 PAPIERROR 00327 ( "Your kernel does not have performance monitoring support" ); 00328 else 00329 PAPIERROR( "perfmonctl(PFM_CREATE_CONTEXT) errno %d", errno ); 00330 return ( PAPI_ESYS ); 00331 } 00332 /* 00333 * extract the file descriptor we will use to 00334 * identify this newly created context 00335 */ 00336 ctx_fd = ctx.ctx_arg.ctx_fd; 00337 /* save the fd into the thread context struct */ 00338 ( ( ia64_context_t * ) thr_ctx )->fd = ctx_fd; 00339 ( ( ia64_context_t * ) thr_ctx )->tid = mygettid( ); 00340 SUBDBG( "PFM_CREATE_CONTEXT returns FD %d, TID %d\n", 00341 ( int ) ( ( ia64_context_t * ) thr_ctx )->fd, 00342 ( int ) ( ( ia64_context_t * ) thr_ctx )->tid ); 00343 /* indicate which PMD to include in the sample */ 00344 /* DEAR and BTB events */ 00345 switch ( _perfmon2_pfm_pmu_type ) { 00346 case PFMLIB_ITANIUM_PMU: 00347 if ( pfm_ita_is_dear( native_index ) ) 00348 set_pmds_to_write( ESI, EventIndex, DEAR_REGS_MASK ); 00349 else if ( pfm_ita_is_btb( native_index ) 00350 || EventCode == ( unsigned int ) PAPI_BR_INS ) 00351 set_pmds_to_write( ESI, EventIndex, BTB_REGS_MASK ); 00352 break; 00353 case PFMLIB_ITANIUM2_PMU: 00354 if ( pfm_ita2_is_dear( native_index ) ) 00355 set_pmds_to_write( ESI, EventIndex, DEAR_REGS_MASK ); 00356 else if ( pfm_ita2_is_btb( native_index ) 00357 || EventCode == ( unsigned int ) PAPI_BR_INS ) 00358 set_pmds_to_write( ESI, EventIndex, BTB_REGS_MASK ); 00359 break; 00360 case PFMLIB_MONTECITO_PMU: 00361 if ( pfm_mont_is_dear( native_index ) ) 00362 set_pmds_to_write( ESI, EventIndex, MONT_DEAR_REGS_MASK ); 00363 else if ( pfm_mont_is_etb( native_index ) || 00364 EventCode == ( unsigned int ) PAPI_BR_INS ) 00365 set_pmds_to_write( ESI, EventIndex, MONT_ETB_REGS_MASK ); 00366 break; 00367 default: 00368 PAPIERROR( "PMU type %d is not supported by this component", 00369 _perfmon2_pfm_pmu_type ); 00370 return ( PAPI_EBUG ); 00371 } 00372 00373 *smpl_vaddr = ctx.ctx_arg.ctx_smpl_vaddr; 00374 00375 return ( pfmw_create_ctx_common( thr_ctx ) ); 00376 } 00377 00378 static int 00379 pfmw_get_event_name( char *name, unsigned int idx ) 00380 { 00381 unsigned int total; 00382 00383 pfm_get_num_events( &total ); 00384 if ( idx >= total ) 00385 return PAPI_ENOEVNT; 00386 if ( pfm_get_event_name( idx, name, PAPI_MAX_STR_LEN ) == PFMLIB_SUCCESS ) 00387 return PAPI_OK; 00388 else 00389 return PAPI_ENOEVNT; 00390 } 00391 00392 static void 00393 pfmw_get_event_description( unsigned int idx, char *dest, int len ) 00394 { 00395 char *descr; 00396 00397 if ( pfm_get_event_description( idx, &descr ) == PFMLIB_SUCCESS ) { 00398 strncpy( dest, descr, len ); 00399 free( descr ); 00400 } else 00401 *dest = '\0'; 00402 } 00403 00404 static int 00405 pfmw_is_dear( unsigned int i ) 00406 { 00407 switch ( _perfmon2_pfm_pmu_type ) { 00408 case PFMLIB_ITANIUM_PMU: 00409 return ( pfm_ita_is_dear( i ) ); 00410 break; 00411 case PFMLIB_ITANIUM2_PMU: 00412 return ( pfm_ita2_is_dear( i ) ); 00413 break; 00414 case PFMLIB_MONTECITO_PMU: 00415 return ( pfm_mont_is_dear( i ) ); 00416 break; 00417 default: 00418 PAPIERROR( "PMU type %d is not supported by this component", 00419 _perfmon2_pfm_pmu_type ); 00420 return ( PAPI_EBUG ); 00421 } 00422 } 00423 00424 static int 00425 pfmw_is_iear( unsigned int i ) 00426 { 00427 switch ( _perfmon2_pfm_pmu_type ) { 00428 case PFMLIB_ITANIUM_PMU: 00429 return ( pfm_ita_is_iear( i ) ); 00430 break; 00431 case PFMLIB_ITANIUM2_PMU: 00432 return ( pfm_ita2_is_iear( i ) ); 00433 break; 00434 case PFMLIB_MONTECITO_PMU: 00435 return ( pfm_mont_is_iear( i ) ); 00436 break; 00437 default: 00438 PAPIERROR( "PMU type %d is not supported by this component", 00439 _perfmon2_pfm_pmu_type ); 00440 return ( PAPI_EBUG ); 00441 } 00442 } 00443 00444 static int 00445 pfmw_support_darr( unsigned int i ) 00446 { 00447 switch ( _perfmon2_pfm_pmu_type ) { 00448 case PFMLIB_ITANIUM_PMU: 00449 return ( pfm_ita_support_darr( i ) ); 00450 break; 00451 case PFMLIB_ITANIUM2_PMU: 00452 return ( pfm_ita2_support_darr( i ) ); 00453 break; 00454 case PFMLIB_MONTECITO_PMU: 00455 return ( pfm_mont_support_darr( i ) ); 00456 break; 00457 default: 00458 PAPIERROR( "PMU type %d is not supported by this component", 00459 _perfmon2_pfm_pmu_type ); 00460 return ( PAPI_EBUG ); 00461 } 00462 } 00463 00464 static int 00465 pfmw_support_iarr( unsigned int i ) 00466 { 00467 switch ( _perfmon2_pfm_pmu_type ) { 00468 case PFMLIB_ITANIUM_PMU: 00469 return ( pfm_ita_support_iarr( i ) ); 00470 break; 00471 case PFMLIB_ITANIUM2_PMU: 00472 return ( pfm_ita2_support_iarr( i ) ); 00473 break; 00474 case PFMLIB_MONTECITO_PMU: 00475 return ( pfm_mont_support_iarr( i ) ); 00476 break; 00477 default: 00478 PAPIERROR( "PMU type %d is not supported by this component", 00479 _perfmon2_pfm_pmu_type ); 00480 return ( PAPI_EBUG ); 00481 } 00482 } 00483 00484 static int 00485 pfmw_support_opcm( unsigned int i ) 00486 { 00487 switch ( _perfmon2_pfm_pmu_type ) { 00488 case PFMLIB_ITANIUM_PMU: 00489 return ( pfm_ita_support_opcm( i ) ); 00490 break; 00491 case PFMLIB_ITANIUM2_PMU: 00492 return ( pfm_ita2_support_opcm( i ) ); 00493 break; 00494 case PFMLIB_MONTECITO_PMU: 00495 return ( pfm_mont_support_opcm( i ) ); 00496 break; 00497 default: 00498 PAPIERROR( "PMU type %d is not supported by this component", 00499 _perfmon2_pfm_pmu_type ); 00500 return ( PAPI_EBUG ); 00501 } 00502 } 00503 00504 static void 00505 check_ibrp_events( hwd_control_state_t * current_state ) 00506 { 00507 ia64_control_state_t *this_state = ( ia64_control_state_t * ) current_state; 00508 pfmw_param_t *evt = &( this_state->evt ); 00509 unsigned long umasks_retired[4]; 00510 unsigned long umask; 00511 unsigned int j, i, seen_retired, ibrp, idx; 00512 int code; 00513 int retired_code, incr; 00514 pfmlib_ita2_output_param_t *ita2_output_param; 00515 pfmlib_mont_output_param_t *mont_output_param; 00516 00517 #if defined(PFMLIB_ITANIUM2_PMU) || defined(PFMLIB_MONTECITO_PMU) 00518 char *retired_events[] = { 00519 "IA64_TAGGED_INST_RETIRED_IBRP0_PMC8", 00520 "IA64_TAGGED_INST_RETIRED_IBRP1_PMC9", 00521 "IA64_TAGGED_INST_RETIRED_IBRP2_PMC8", 00522 "IA64_TAGGED_INST_RETIRED_IBRP3_PMC9", 00523 NULL 00524 }; 00525 #endif 00526 00527 switch ( _perfmon2_pfm_pmu_type ) { 00528 case PFMLIB_ITANIUM2_PMU: 00529 ita2_output_param = 00530 &( this_state->ita_lib_param.ita2_param.ita2_output_param ); 00531 /* 00532 * in fine mode, it is enough to use the event 00533 * which only monitors the first debug register 00534 * pair. The two pairs making up the range 00535 * are guaranteed to be consecutive in rr_br[]. 00536 */ 00537 incr = pfm_ita2_irange_is_fine( &evt->outp, ita2_output_param ) ? 4 : 2; 00538 00539 for ( i = 0; retired_events[i]; i++ ) { 00540 pfm_find_event( retired_events[i], &idx ); 00541 pfm_ita2_get_event_umask( idx, umasks_retired + i ); 00542 } 00543 00544 pfm_get_event_code( idx, &retired_code ); 00545 00546 /* 00547 * print a warning message when the using IA64_TAGGED_INST_RETIRED_IBRP* which does 00548 * not completely cover the all the debug register pairs used to make up the range. 00549 * This could otherwise lead to misinterpretation of the results. 00550 */ 00551 for ( i = 0; i < ita2_output_param->pfp_ita2_irange.rr_nbr_used; 00552 i += incr ) { 00553 00554 ibrp = ita2_output_param->pfp_ita2_irange.rr_br[i].reg_num >> 1; 00555 00556 seen_retired = 0; 00557 for ( j = 0; j < evt->inp.pfp_event_count; j++ ) { 00558 pfm_get_event_code( evt->inp.pfp_events[j].event, &code ); 00559 if ( code != retired_code ) 00560 continue; 00561 seen_retired = 1; 00562 pfm_ita2_get_event_umask( evt->inp.pfp_events[j].event, 00563 &umask ); 00564 if ( umask == umasks_retired[ibrp] ) 00565 break; 00566 } 00567 if ( seen_retired && j == evt->inp.pfp_event_count ) 00568 printf 00569 ( "warning: code range uses IBR pair %d which is not monitored using %s\n", 00570 ibrp, retired_events[ibrp] ); 00571 } 00572 00573 break; 00574 case PFMLIB_MONTECITO_PMU: 00575 mont_output_param = 00576 &( this_state->ita_lib_param.mont_param.mont_output_param ); 00577 /* 00578 * in fine mode, it is enough to use the event 00579 * which only monitors the first debug register 00580 * pair. The two pairs making up the range 00581 * are guaranteed to be consecutive in rr_br[]. 00582 */ 00583 incr = pfm_mont_irange_is_fine( &evt->outp, mont_output_param ) ? 4 : 2; 00584 00585 for ( i = 0; retired_events[i]; i++ ) { 00586 pfm_find_event( retired_events[i], &idx ); 00587 pfm_mont_get_event_umask( idx, umasks_retired + i ); 00588 } 00589 00590 pfm_get_event_code( idx, &retired_code ); 00591 00592 /* 00593 * print a warning message when the using IA64_TAGGED_INST_RETIRED_IBRP* which does 00594 * not completely cover the all the debug register pairs used to make up the range. 00595 * This could otherwise lead to misinterpretation of the results. 00596 */ 00597 for ( i = 0; i < mont_output_param->pfp_mont_irange.rr_nbr_used; 00598 i += incr ) { 00599 00600 ibrp = mont_output_param->pfp_mont_irange.rr_br[i].reg_num >> 1; 00601 00602 seen_retired = 0; 00603 for ( j = 0; j < evt->inp.pfp_event_count; j++ ) { 00604 pfm_get_event_code( evt->inp.pfp_events[j].event, &code ); 00605 if ( code != retired_code ) 00606 continue; 00607 seen_retired = 1; 00608 pfm_mont_get_event_umask( evt->inp.pfp_events[j].event, 00609 &umask ); 00610 if ( umask == umasks_retired[ibrp] ) 00611 break; 00612 } 00613 if ( seen_retired && j == evt->inp.pfp_event_count ) 00614 printf 00615 ( "warning: code range uses IBR pair %d which is not monitored using %s\n", 00616 ibrp, retired_events[ibrp] ); 00617 } 00618 break; 00619 default: 00620 PAPIERROR( "PMU type %d is not supported by this component", 00621 _perfmon2_pfm_pmu_type ); 00622 } 00623 } 00624 00625 static int 00626 install_irange( hwd_context_t * pctx, hwd_control_state_t * current_state ) 00627 { 00628 ia64_control_state_t *this_state = ( ia64_control_state_t * ) current_state; 00629 unsigned int i, used_dbr; 00630 int r; 00631 int pid = ( ( ia64_context_t * ) pctx )->fd; 00632 00633 pfmlib_ita2_output_param_t *ita2_output_param; 00634 pfarg_dbreg_t ita2_dbreg[PFMON_ITA2_MAX_IBRS]; 00635 pfmlib_mont_output_param_t *mont_output_param; 00636 pfarg_dbreg_t mont_dbreg[PFMON_MONT_MAX_IBRS]; 00637 00638 memset( mont_dbreg, 0, sizeof ( mont_dbreg ) ); 00639 memset( ita2_dbreg, 0, sizeof ( ita2_dbreg ) ); 00640 check_ibrp_events( current_state ); 00641 00642 switch ( _perfmon2_pfm_pmu_type ) { 00643 case PFMLIB_ITANIUM2_PMU: 00644 ita2_output_param = 00645 &( this_state->ita_lib_param.ita2_param.ita2_output_param ); 00646 used_dbr = ita2_output_param->pfp_ita2_irange.rr_nbr_used; 00647 00648 for ( i = 0; i < used_dbr; i++ ) { 00649 ita2_dbreg[i].dbreg_num = 00650 ita2_output_param->pfp_ita2_irange.rr_br[i].reg_num; 00651 ita2_dbreg[i].dbreg_value = 00652 ita2_output_param->pfp_ita2_irange.rr_br[i].reg_value; 00653 } 00654 00655 r = perfmonctl( pid, PFM_WRITE_IBRS, ita2_dbreg, 00656 ita2_output_param->pfp_ita2_irange.rr_nbr_used ); 00657 if ( r == -1 ) { 00658 SUBDBG( "cannot install code range restriction: %s\n", 00659 strerror( errno ) ); 00660 return ( PAPI_ESYS ); 00661 } 00662 return ( PAPI_OK ); 00663 break; 00664 case PFMLIB_MONTECITO_PMU: 00665 mont_output_param = 00666 &( this_state->ita_lib_param.mont_param.mont_output_param ); 00667 00668 used_dbr = mont_output_param->pfp_mont_irange.rr_nbr_used; 00669 00670 for ( i = 0; i < used_dbr; i++ ) { 00671 mont_dbreg[i].dbreg_num = 00672 mont_output_param->pfp_mont_irange.rr_br[i].reg_num; 00673 mont_dbreg[i].dbreg_value = 00674 mont_output_param->pfp_mont_irange.rr_br[i].reg_value; 00675 } 00676 00677 r = perfmonctl( pid, PFM_WRITE_IBRS, mont_dbreg, 00678 mont_output_param->pfp_mont_irange.rr_nbr_used ); 00679 if ( r == -1 ) { 00680 SUBDBG( "cannot install code range restriction: %s\n", 00681 strerror( errno ) ); 00682 return ( PAPI_ESYS ); 00683 } 00684 return ( PAPI_OK ); 00685 break; 00686 default: 00687 PAPIERROR( "PMU type %d is not supported by this component", 00688 _perfmon2_pfm_pmu_type ); 00689 return PAPI_ENOIMPL; 00690 } 00691 } 00692 00693 static int 00694 install_drange( hwd_context_t * pctx, hwd_control_state_t * current_state ) 00695 { 00696 ia64_control_state_t *this_state = ( ia64_control_state_t * ) current_state; 00697 unsigned int i, used_dbr; 00698 int r; 00699 int pid = ( ( ia64_context_t * ) pctx )->fd; 00700 00701 pfmlib_ita2_output_param_t *ita2_output_param; 00702 pfarg_dbreg_t ita2_dbreg[PFMON_ITA2_MAX_IBRS]; 00703 pfmlib_mont_output_param_t *mont_output_param; 00704 pfarg_dbreg_t mont_dbreg[PFMON_MONT_MAX_IBRS]; 00705 00706 memset( mont_dbreg, 0, sizeof ( mont_dbreg ) ); 00707 memset( ita2_dbreg, 0, sizeof ( ita2_dbreg ) ); 00708 00709 switch ( _perfmon2_pfm_pmu_type ) { 00710 case PFMLIB_ITANIUM2_PMU: 00711 ita2_output_param = 00712 &( this_state->ita_lib_param.ita2_param.ita2_output_param ); 00713 used_dbr = ita2_output_param->pfp_ita2_drange.rr_nbr_used; 00714 00715 for ( i = 0; i < used_dbr; i++ ) { 00716 ita2_dbreg[i].dbreg_num = 00717 ita2_output_param->pfp_ita2_drange.rr_br[i].reg_num; 00718 ita2_dbreg[i].dbreg_value = 00719 ita2_output_param->pfp_ita2_drange.rr_br[i].reg_value; 00720 } 00721 00722 r = perfmonctl( pid, PFM_WRITE_DBRS, ita2_dbreg, 00723 ita2_output_param->pfp_ita2_drange.rr_nbr_used ); 00724 if ( r == -1 ) { 00725 SUBDBG( "cannot install data range restriction: %s\n", 00726 strerror( errno ) ); 00727 return ( PAPI_ESYS ); 00728 } 00729 return ( PAPI_OK ); 00730 break; 00731 case PFMLIB_MONTECITO_PMU: 00732 mont_output_param = 00733 &( this_state->ita_lib_param.mont_param.mont_output_param ); 00734 used_dbr = mont_output_param->pfp_mont_drange.rr_nbr_used; 00735 00736 for ( i = 0; i < used_dbr; i++ ) { 00737 mont_dbreg[i].dbreg_num = 00738 mont_output_param->pfp_mont_drange.rr_br[i].reg_num; 00739 mont_dbreg[i].dbreg_value = 00740 mont_output_param->pfp_mont_drange.rr_br[i].reg_value; 00741 } 00742 00743 r = perfmonctl( pid, PFM_WRITE_DBRS, mont_dbreg, 00744 mont_output_param->pfp_mont_drange.rr_nbr_used ); 00745 if ( r == -1 ) { 00746 SUBDBG( "cannot install data range restriction: %s\n", 00747 strerror( errno ) ); 00748 return PAPI_ESYS; 00749 } 00750 return PAPI_OK; 00751 break; 00752 default: 00753 PAPIERROR( "PMU type %d is not supported by this component", 00754 _perfmon2_pfm_pmu_type ); 00755 return PAPI_ENOIMPL; 00756 } 00757 } 00758 00759 /* The routines set_{d,i}range() provide places to install the data and / or 00760 instruction address range restrictions for counting qualified events. 00761 These routines must set up or clear the appropriate local static data structures. 00762 The actual work of loading the hardware registers must be done in update_ctl_state(). 00763 Both drange and irange can be set on the same eventset. 00764 If start=end=0, the feature is disabled. 00765 */ 00766 static int 00767 set_drange( hwd_context_t * ctx, hwd_control_state_t * current_state, 00768 _papi_int_option_t * option ) 00769 { 00770 int ret = PAPI_OK; 00771 ia64_control_state_t *this_state = ( ia64_control_state_t * ) current_state; 00772 pfmw_param_t *evt = &( this_state->evt ); 00773 pfmlib_input_param_t *inp = &evt->inp; 00774 pfmlib_ita2_input_param_t *ita2_inp = 00775 &( this_state->ita_lib_param.ita2_param.ita2_input_param ); 00776 pfmlib_ita2_output_param_t *ita2_outp = 00777 &( this_state->ita_lib_param.ita2_param.ita2_output_param ); 00778 pfmlib_mont_input_param_t *mont_inp = 00779 &( this_state->ita_lib_param.mont_param.mont_input_param ); 00780 pfmlib_mont_output_param_t *mont_outp = 00781 &( this_state->ita_lib_param.mont_param.mont_output_param ); 00782 00783 switch ( _perfmon2_pfm_pmu_type ) { 00784 case PFMLIB_ITANIUM2_PMU: 00785 00786 if ( ( unsigned long ) option->address_range.start == 00787 ( unsigned long ) option->address_range.end || 00788 ( ( unsigned long ) option->address_range.start == 0 && 00789 ( unsigned long ) option->address_range.end == 0 ) ) 00790 return ( PAPI_EINVAL ); 00791 /* 00792 * set the privilege mode: 00793 * PFM_PLM3 : user level only 00794 */ 00795 memset( &ita2_inp->pfp_ita2_drange, 0, 00796 sizeof ( pfmlib_ita2_input_rr_t ) ); 00797 memset( ita2_outp, 0, sizeof ( pfmlib_ita2_output_param_t ) ); 00798 inp->pfp_dfl_plm = PFM_PLM3; 00799 ita2_inp->pfp_ita2_drange.rr_used = 1; 00800 ita2_inp->pfp_ita2_drange.rr_limits[0].rr_start = 00801 ( unsigned long ) option->address_range.start; 00802 ita2_inp->pfp_ita2_drange.rr_limits[0].rr_end = 00803 ( unsigned long ) option->address_range.end; 00804 SUBDBG 00805 ( "++++ before data range : [0x%016lx-0x%016lx=%ld]: %d pair of debug registers used\n" 00806 " start_offset:-0x%lx end_offset:+0x%lx\n", 00807 ita2_inp->pfp_ita2_drange.rr_limits[0].rr_start, 00808 ita2_inp->pfp_ita2_drange.rr_limits[0].rr_end, 00809 ita2_inp->pfp_ita2_drange.rr_limits[0].rr_end - 00810 ita2_inp->pfp_ita2_drange.rr_limits[0].rr_start, 00811 ita2_outp->pfp_ita2_drange.rr_nbr_used >> 1, 00812 ita2_outp->pfp_ita2_drange.rr_infos[0].rr_soff, 00813 ita2_outp->pfp_ita2_drange.rr_infos[0].rr_eoff ); 00814 00815 /* 00816 * let the library figure out the values for the PMCS 00817 */ 00818 if ( ( ret = pfmw_dispatch_events( evt ) ) != PFMLIB_SUCCESS ) { 00819 SUBDBG( "cannot configure events: %s\n", pfm_strerror( ret ) ); 00820 } 00821 00822 SUBDBG 00823 ( "++++ data range : [0x%016lx-0x%016lx=%ld]: %d pair of debug registers used\n" 00824 " start_offset:-0x%lx end_offset:+0x%lx\n", 00825 ita2_inp->pfp_ita2_drange.rr_limits[0].rr_start, 00826 ita2_inp->pfp_ita2_drange.rr_limits[0].rr_end, 00827 ita2_inp->pfp_ita2_drange.rr_limits[0].rr_end - 00828 ita2_inp->pfp_ita2_drange.rr_limits[0].rr_start, 00829 ita2_outp->pfp_ita2_drange.rr_nbr_used >> 1, 00830 ita2_outp->pfp_ita2_drange.rr_infos[0].rr_soff, 00831 ita2_outp->pfp_ita2_drange.rr_infos[0].rr_eoff ); 00832 00833 /* if( ita2_inp->pfp_ita2_irange.rr_limits[0].rr_start!=0 || ita2_inp->pfp_ita2_irange.rr_limits[0].rr_end!=0 ) 00834 if((ret=install_irange(ctx, current_state)) ==PAPI_OK){ 00835 option->address_range.start_off=ita2_outp->pfp_ita2_irange.rr_infos[0].rr_soff; 00836 option->address_range.end_off=ita2_outp->pfp_ita2_irange.rr_infos[0].rr_eoff; 00837 } 00838 */ 00839 if ( ( ret = install_drange( ctx, current_state ) ) == PAPI_OK ) { 00840 option->address_range.start_off = 00841 ita2_outp->pfp_ita2_drange.rr_infos[0].rr_soff; 00842 option->address_range.end_off = 00843 ita2_outp->pfp_ita2_drange.rr_infos[0].rr_eoff; 00844 } 00845 return ( ret ); 00846 00847 break; 00848 case PFMLIB_MONTECITO_PMU: 00849 00850 if ( ( unsigned long ) option->address_range.start == 00851 ( unsigned long ) option->address_range.end || 00852 ( ( unsigned long ) option->address_range.start == 0 && 00853 ( unsigned long ) option->address_range.end == 0 ) ) 00854 return ( PAPI_EINVAL ); 00855 /* 00856 * set the privilege mode: 00857 * PFM_PLM3 : user level only 00858 */ 00859 memset( &mont_inp->pfp_mont_drange, 0, 00860 sizeof ( pfmlib_mont_input_rr_t ) ); 00861 memset( mont_outp, 0, sizeof ( pfmlib_mont_output_param_t ) ); 00862 inp->pfp_dfl_plm = PFM_PLM3; 00863 mont_inp->pfp_mont_drange.rr_used = 1; 00864 mont_inp->pfp_mont_drange.rr_limits[0].rr_start = 00865 ( unsigned long ) option->address_range.start; 00866 mont_inp->pfp_mont_drange.rr_limits[0].rr_end = 00867 ( unsigned long ) option->address_range.end; 00868 SUBDBG 00869 ( "++++ before data range : [0x%016lx-0x%016lx=%ld]: %d pair of debug registers used\n" 00870 " start_offset:-0x%lx end_offset:+0x%lx\n", 00871 mont_inp->pfp_mont_drange.rr_limits[0].rr_start, 00872 mont_inp->pfp_mont_drange.rr_limits[0].rr_end, 00873 mont_inp->pfp_mont_drange.rr_limits[0].rr_end - 00874 mont_inp->pfp_mont_drange.rr_limits[0].rr_start, 00875 mont_outp->pfp_mont_drange.rr_nbr_used >> 1, 00876 mont_outp->pfp_mont_drange.rr_infos[0].rr_soff, 00877 mont_outp->pfp_mont_drange.rr_infos[0].rr_eoff ); 00878 /* 00879 * let the library figure out the values for the PMCS 00880 */ 00881 if ( ( ret = pfmw_dispatch_events( evt ) ) != PFMLIB_SUCCESS ) { 00882 SUBDBG( "cannot configure events: %s\n", pfm_strerror( ret ) ); 00883 } 00884 00885 SUBDBG 00886 ( "++++ data range : [0x%016lx-0x%016lx=%ld]: %d pair of debug registers used\n" 00887 " start_offset:-0x%lx end_offset:+0x%lx\n", 00888 mont_inp->pfp_mont_drange.rr_limits[0].rr_start, 00889 mont_inp->pfp_mont_drange.rr_limits[0].rr_end, 00890 mont_inp->pfp_mont_drange.rr_limits[0].rr_end - 00891 mont_inp->pfp_mont_drange.rr_limits[0].rr_start, 00892 mont_outp->pfp_mont_drange.rr_nbr_used >> 1, 00893 mont_outp->pfp_mont_drange.rr_infos[0].rr_soff, 00894 mont_outp->pfp_mont_drange.rr_infos[0].rr_eoff ); 00895 00896 /* if( ita2_inp->pfp_ita2_irange.rr_limits[0].rr_start!=0 || ita2_inp->pfp_ita2_irange.rr_limits[0].rr_end!=0 ) 00897 if((ret=install_irange(ctx, current_state)) ==PAPI_OK){ 00898 option->address_range.start_off=ita2_outp->pfp_ita2_irange.rr_infos[0].rr_soff; 00899 option->address_range.end_off=ita2_outp->pfp_ita2_irange.rr_infos[0].rr_eoff; 00900 } 00901 */ 00902 if ( ( ret = install_drange( ctx, current_state ) ) == PAPI_OK ) { 00903 option->address_range.start_off = 00904 mont_outp->pfp_mont_drange.rr_infos[0].rr_soff; 00905 option->address_range.end_off = 00906 mont_outp->pfp_mont_drange.rr_infos[0].rr_eoff; 00907 } 00908 return ( ret ); 00909 00910 break; 00911 default: 00912 PAPIERROR( "PMU type %d is not supported by this component", 00913 _perfmon2_pfm_pmu_type ); 00914 return PAPI_ENOIMPL; 00915 } 00916 } 00917 00918 static int 00919 set_irange( hwd_context_t * ctx, hwd_control_state_t * current_state, 00920 _papi_int_option_t * option ) 00921 { 00922 int ret = PAPI_OK; 00923 ia64_control_state_t *this_state = ( ia64_control_state_t * ) current_state; 00924 pfmw_param_t *evt = &( this_state->evt ); 00925 pfmlib_input_param_t *inp = &evt->inp; 00926 pfmlib_ita2_input_param_t *ita2_inp = 00927 &( this_state->ita_lib_param.ita2_param.ita2_input_param ); 00928 pfmlib_ita2_output_param_t *ita2_outp = 00929 &( this_state->ita_lib_param.ita2_param.ita2_output_param ); 00930 pfmlib_mont_input_param_t *mont_inp = 00931 &( this_state->ita_lib_param.mont_param.mont_input_param ); 00932 pfmlib_mont_output_param_t *mont_outp = 00933 &( this_state->ita_lib_param.mont_param.mont_output_param ); 00934 00935 switch ( _perfmon2_pfm_pmu_type ) { 00936 case PFMLIB_ITANIUM2_PMU: 00937 00938 if ( ( unsigned long ) option->address_range.start == 00939 ( unsigned long ) option->address_range.end || 00940 ( ( unsigned long ) option->address_range.start == 0 && 00941 ( unsigned long ) option->address_range.end == 0 ) ) 00942 return ( PAPI_EINVAL ); 00943 /* 00944 * set the privilege mode: 00945 * PFM_PLM3 : user level only 00946 */ 00947 memset( &ita2_inp->pfp_ita2_irange, 0, 00948 sizeof ( pfmlib_ita2_input_rr_t ) ); 00949 memset( ita2_outp, 0, sizeof ( pfmlib_ita2_output_param_t ) ); 00950 inp->pfp_dfl_plm = PFM_PLM3; 00951 ita2_inp->pfp_ita2_irange.rr_used = 1; 00952 ita2_inp->pfp_ita2_irange.rr_limits[0].rr_start = 00953 ( unsigned long ) option->address_range.start; 00954 ita2_inp->pfp_ita2_irange.rr_limits[0].rr_end = 00955 ( unsigned long ) option->address_range.end; 00956 SUBDBG 00957 ( "++++ before code range : [0x%016lx-0x%016lx=%ld]: %d pair of debug registers used\n" 00958 " start_offset:-0x%lx end_offset:+0x%lx\n", 00959 ita2_inp->pfp_ita2_irange.rr_limits[0].rr_start, 00960 ita2_inp->pfp_ita2_irange.rr_limits[0].rr_end, 00961 ita2_inp->pfp_ita2_irange.rr_limits[0].rr_end - 00962 ita2_inp->pfp_ita2_irange.rr_limits[0].rr_start, 00963 ita2_outp->pfp_ita2_irange.rr_nbr_used >> 1, 00964 ita2_outp->pfp_ita2_irange.rr_infos[0].rr_soff, 00965 ita2_outp->pfp_ita2_irange.rr_infos[0].rr_eoff ); 00966 00967 /* 00968 * let the library figure out the values for the PMCS 00969 */ 00970 if ( ( ret = pfmw_dispatch_events( evt ) ) != PFMLIB_SUCCESS ) { 00971 SUBDBG( "cannot configure events: %s\n", pfm_strerror( ret ) ); 00972 } 00973 00974 SUBDBG 00975 ( "++++ code range : [0x%016lx-0x%016lx=%ld]: %d pair of debug registers used\n" 00976 " start_offset:-0x%lx end_offset:+0x%lx\n", 00977 ita2_inp->pfp_ita2_irange.rr_limits[0].rr_start, 00978 ita2_inp->pfp_ita2_irange.rr_limits[0].rr_end, 00979 ita2_inp->pfp_ita2_irange.rr_limits[0].rr_end - 00980 ita2_inp->pfp_ita2_irange.rr_limits[0].rr_start, 00981 ita2_outp->pfp_ita2_irange.rr_nbr_used >> 1, 00982 ita2_outp->pfp_ita2_irange.rr_infos[0].rr_soff, 00983 ita2_outp->pfp_ita2_irange.rr_infos[0].rr_eoff ); 00984 if ( ( ret = install_irange( ctx, current_state ) ) == PAPI_OK ) { 00985 option->address_range.start_off = 00986 ita2_outp->pfp_ita2_irange.rr_infos[0].rr_soff; 00987 option->address_range.end_off = 00988 ita2_outp->pfp_ita2_irange.rr_infos[0].rr_eoff; 00989 } 00990 00991 break; 00992 case PFMLIB_MONTECITO_PMU: 00993 00994 if ( ( unsigned long ) option->address_range.start == 00995 ( unsigned long ) option->address_range.end || 00996 ( ( unsigned long ) option->address_range.start == 0 && 00997 ( unsigned long ) option->address_range.end == 0 ) ) 00998 return ( PAPI_EINVAL ); 00999 /* 01000 * set the privilege mode: 01001 * PFM_PLM3 : user level only 01002 */ 01003 memset( &mont_inp->pfp_mont_irange, 0, 01004 sizeof ( pfmlib_mont_input_rr_t ) ); 01005 memset( mont_outp, 0, sizeof ( pfmlib_mont_output_param_t ) ); 01006 inp->pfp_dfl_plm = PFM_PLM3; 01007 mont_inp->pfp_mont_irange.rr_used = 1; 01008 mont_inp->pfp_mont_irange.rr_limits[0].rr_start = 01009 ( unsigned long ) option->address_range.start; 01010 mont_inp->pfp_mont_irange.rr_limits[0].rr_end = 01011 ( unsigned long ) option->address_range.end; 01012 SUBDBG 01013 ( "++++ before code range : [0x%016lx-0x%016lx=%ld]: %d pair of debug registers used\n" 01014 " start_offset:-0x%lx end_offset:+0x%lx\n", 01015 mont_inp->pfp_mont_irange.rr_limits[0].rr_start, 01016 mont_inp->pfp_mont_irange.rr_limits[0].rr_end, 01017 mont_inp->pfp_mont_irange.rr_limits[0].rr_end - 01018 mont_inp->pfp_mont_irange.rr_limits[0].rr_start, 01019 mont_outp->pfp_mont_irange.rr_nbr_used >> 1, 01020 mont_outp->pfp_mont_irange.rr_infos[0].rr_soff, 01021 mont_outp->pfp_mont_irange.rr_infos[0].rr_eoff ); 01022 01023 /* 01024 * let the library figure out the values for the PMCS 01025 */ 01026 if ( ( ret = pfmw_dispatch_events( evt ) ) != PFMLIB_SUCCESS ) { 01027 SUBDBG( "cannot configure events: %s\n", pfm_strerror( ret ) ); 01028 } 01029 01030 SUBDBG 01031 ( "++++ code range : [0x%016lx-0x%016lx=%ld]: %d pair of debug registers used\n" 01032 " start_offset:-0x%lx end_offset:+0x%lx\n", 01033 mont_inp->pfp_mont_irange.rr_limits[0].rr_start, 01034 mont_inp->pfp_mont_irange.rr_limits[0].rr_end, 01035 mont_inp->pfp_mont_irange.rr_limits[0].rr_end - 01036 mont_inp->pfp_mont_irange.rr_limits[0].rr_start, 01037 mont_outp->pfp_mont_irange.rr_nbr_used >> 1, 01038 mont_outp->pfp_mont_irange.rr_infos[0].rr_soff, 01039 mont_outp->pfp_mont_irange.rr_infos[0].rr_eoff ); 01040 if ( ( ret = install_irange( ctx, current_state ) ) == PAPI_OK ) { 01041 option->address_range.start_off = 01042 mont_outp->pfp_mont_irange.rr_infos[0].rr_soff; 01043 option->address_range.end_off = 01044 mont_outp->pfp_mont_irange.rr_infos[0].rr_eoff; 01045 } 01046 01047 break; 01048 default: 01049 PAPIERROR( "PMU type %d is not supported by this component", 01050 _perfmon2_pfm_pmu_type ); 01051 return PAPI_ENOIMPL; 01052 } 01053 01054 return ret; 01055 } 01056 01057 static int 01058 pfmw_get_num_counters( int *num ) 01059 { 01060 unsigned int tmp; 01061 if ( pfm_get_num_counters( &tmp ) != PFMLIB_SUCCESS ) 01062 return ( PAPI_ESYS ); 01063 *num = tmp; 01064 return ( PAPI_OK ); 01065 } 01066 01067 static int 01068 pfmw_get_num_events( int *num ) 01069 { 01070 unsigned int tmp; 01071 if ( pfm_get_num_events( &tmp ) != PFMLIB_SUCCESS ) 01072 return ( PAPI_ESYS ); 01073 *num = tmp; 01074 return ( PAPI_OK ); 01075 } 01076 01077 01078 /* Globals declared extern elsewhere */ 01079 01080 hwi_search_t *preset_search_map; 01081 extern papi_vector_t _ia64_vector; 01082 01083 unsigned int PAPI_NATIVE_EVENT_AND_MASK = 0x000003ff; 01084 unsigned int PAPI_NATIVE_EVENT_SHIFT = 0; 01085 unsigned int PAPI_NATIVE_UMASK_AND_MASK = 0x03fffc00; 01086 unsigned int PAPI_NATIVE_UMASK_MAX = 16; 01087 unsigned int PAPI_NATIVE_UMASK_SHIFT = 10; 01088 01089 /* Static locals */ 01090 01091 int _perfmon2_pfm_pmu_type = -1; 01092 01093 /* 01094 static papi_svector_t _linux_ia64_table[] = { 01095 {(void (*)())_papi_hwd_update_shlib_info, VEC_PAPI_HWD_UPDATE_SHLIB_INFO}, 01096 {(void (*)())_papi_hwd_init, VEC_PAPI_HWD_INIT}, 01097 {(void (*)())_papi_hwd_init_control_state, VEC_PAPI_HWD_INIT_CONTROL_STATE}, 01098 {(void (*)())_papi_hwd_dispatch_timer, VEC_PAPI_HWD_DISPATCH_TIMER}, 01099 {(void (*)())_papi_hwd_ctl, VEC_PAPI_HWD_CTL}, 01100 {(void (*)())_papi_hwd_get_real_usec, VEC_PAPI_HWD_GET_REAL_USEC}, 01101 {(void (*)())_papi_hwd_get_real_cycles, VEC_PAPI_HWD_GET_REAL_CYCLES}, 01102 {(void (*)())_papi_hwd_get_virt_cycles, VEC_PAPI_HWD_GET_VIRT_CYCLES}, 01103 {(void (*)())_papi_hwd_get_virt_usec, VEC_PAPI_HWD_GET_VIRT_USEC}, 01104 {(void (*)())_papi_hwd_update_control_state,VEC_PAPI_HWD_UPDATE_CONTROL_STATE}, 01105 {(void (*)())_papi_hwd_start, VEC_PAPI_HWD_START }, 01106 {(void (*)())_papi_hwd_stop, VEC_PAPI_HWD_STOP }, 01107 {(void (*)())_papi_hwd_read, VEC_PAPI_HWD_READ }, 01108 {(void (*)())_papi_hwd_shutdown, VEC_PAPI_HWD_SHUTDOWN }, 01109 {(void (*)())_papi_hwd_reset, VEC_PAPI_HWD_RESET}, 01110 {(void (*)())_papi_hwd_set_profile, VEC_PAPI_HWD_SET_PROFILE}, 01111 {(void (*)())_papi_hwd_stop_profiling, VEC_PAPI_HWD_STOP_PROFILING}, 01112 {(void (*)())_papi_hwd_get_dmem_info, VEC_PAPI_HWD_GET_DMEM_INFO}, 01113 {(void (*)())_papi_hwd_set_overflow, VEC_PAPI_HWD_SET_OVERFLOW}, 01114 {(void (*)())_papi_hwd_ntv_enum_events, VEC_PAPI_HWD_NTV_ENUM_EVENTS}, 01115 {(void (*)())_papi_hwd_ntv_code_to_name, VEC_PAPI_HWD_NTV_CODE_TO_NAME}, 01116 {(void (*)())_papi_hwd_ntv_code_to_descr, VEC_PAPI_HWD_NTV_CODE_TO_DESCR}, 01117 {NULL, VEC_PAPI_END} 01118 }; 01119 */ 01120 01121 static itanium_preset_search_t ia1_preset_search_map[] = { 01122 {PAPI_L1_TCM, DERIVED_ADD, 01123 {"L1D_READ_MISSES_RETIRED", "L2_INST_DEMAND_READS"}, {0}}, 01124 {PAPI_L1_ICM, 0, {"L2_INST_DEMAND_READS"}, {0}}, 01125 {PAPI_L1_DCM, 0, {"L1D_READ_MISSES_RETIRED"}, {0}}, 01126 {PAPI_L2_TCM, 0, {"L2_MISSES"}, {0}}, 01127 {PAPI_L2_DCM, DERIVED_SUB, {"L2_MISSES", "L3_READS_INST_READS_ALL"}, {0}}, 01128 {PAPI_L2_ICM, 0, {"L3_READS_INST_READS_ALL"}, {0}}, 01129 {PAPI_L3_TCM, 0, {"L3_MISSES"}, {0}}, 01130 {PAPI_L3_ICM, 0, {"L3_READS_INST_READS_MISS"}, {0}}, 01131 {PAPI_L3_DCM, DERIVED_ADD, 01132 {"L3_READS_DATA_READS_MISS", "L3_WRITES_DATA_WRITES_MISS"}, {0}}, 01133 {PAPI_L3_LDM, 0, {"L3_READS_DATA_READS_MISS"}, {0}}, 01134 {PAPI_L3_STM, 0, {"L3_WRITES_DATA_WRITES_MISS"}, {0}}, 01135 {PAPI_L1_LDM, 0, {"L1D_READ_MISSES_RETIRED"}, {0}}, 01136 {PAPI_L2_LDM, 0, {"L3_READS_DATA_READS_ALL"}, {0}}, 01137 {PAPI_L2_STM, 0, {"L3_WRITES_ALL_WRITES_ALL"}, {0}}, 01138 {PAPI_L3_DCH, DERIVED_ADD, 01139 {"L3_READS_DATA_READS_HIT", "L3_WRITES_DATA_WRITES_HIT"}, {0}}, 01140 {PAPI_L1_DCH, DERIVED_SUB, {"L1D_READS_RETIRED", "L1D_READ_MISSES_RETIRED"}, 01141 {0}}, 01142 {PAPI_L1_DCA, 0, {"L1D_READS_RETIRED"}, {0}}, 01143 {PAPI_L2_DCA, 0, {"L2_DATA_REFERENCES_ALL"}, {0}}, 01144 {PAPI_L3_DCA, DERIVED_ADD, 01145 {"L3_READS_DATA_READS_ALL", "L3_WRITES_DATA_WRITES_ALL"}, {0}}, 01146 {PAPI_L2_DCR, 0, {"L2_DATA_REFERENCES_READS"}, {0}}, 01147 {PAPI_L3_DCR, 0, {"L3_READS_DATA_READS_ALL"}, {0}}, 01148 {PAPI_L2_DCW, 0, {"L2_DATA_REFERENCES_WRITES"}, {0}}, 01149 {PAPI_L3_DCW, 0, {"L3_WRITES_DATA_WRITES_ALL"}, {0}}, 01150 {PAPI_L3_ICH, 0, {"L3_READS_INST_READS_HIT"}, {0}}, 01151 {PAPI_L1_ICR, DERIVED_ADD, {"L1I_PREFETCH_READS", "L1I_DEMAND_READS"}, {0}}, 01152 {PAPI_L2_ICR, DERIVED_ADD, 01153 {"L2_INST_DEMAND_READS", "L2_INST_PREFETCH_READS"}, {0}}, 01154 {PAPI_L3_ICR, 0, {"L3_READS_INST_READS_ALL"}, {0}}, 01155 {PAPI_TLB_DM, 0, {"DTLB_MISSES"}, {0}}, 01156 {PAPI_TLB_IM, 0, {"ITLB_MISSES_FETCH"}, {0}}, 01157 {PAPI_MEM_SCY, 0, {"MEMORY_CYCLE"}, {0}}, 01158 {PAPI_STL_ICY, 0, {"UNSTALLED_BACKEND_CYCLE"}, {0}}, 01159 {PAPI_BR_INS, 0, {"BRANCH_EVENT"}, {0}}, 01160 {PAPI_BR_PRC, 0, {"BRANCH_PREDICTOR_ALL_CORRECT_PREDICTIONS"}, {0}}, 01161 {PAPI_BR_MSP, DERIVED_ADD, 01162 {"BRANCH_PREDICTOR_ALL_WRONG_PATH", "BRANCH_PREDICTOR_ALL_WRONG_TARGET"}, 01163 {0}}, 01164 {PAPI_TOT_CYC, 0, {"CPU_CYCLES"}, {0}}, 01165 {PAPI_FP_OPS, DERIVED_ADD, {"FP_OPS_RETIRED_HI", "FP_OPS_RETIRED_LO"}, {0}}, 01166 {PAPI_TOT_INS, 0, {"IA64_INST_RETIRED"}, {0}}, 01167 {PAPI_LD_INS, 0, {"LOADS_RETIRED"}, {0}}, 01168 {PAPI_SR_INS, 0, {"STORES_RETIRED"}, {0}}, 01169 {PAPI_LST_INS, DERIVED_ADD, {"LOADS_RETIRED", "STORES_RETIRED"}, {0}}, 01170 {0, 0, {0}, {0}} 01171 }; 01172 01173 static itanium_preset_search_t ia2_preset_search_map[] = { 01174 {PAPI_CA_SNP, 0, {"BUS_SNOOPS_SELF"}, {0}}, 01175 {PAPI_CA_INV, DERIVED_ADD, 01176 {"BUS_MEM_READ_BRIL_SELF", "BUS_MEM_READ_BIL_SELF"}, {0}}, 01177 {PAPI_TLB_TL, DERIVED_ADD, {"ITLB_MISSES_FETCH_L2ITLB", "L2DTLB_MISSES"}, 01178 {0}}, 01179 {PAPI_STL_ICY, 0, {"DISP_STALLED"}, {0}}, 01180 {PAPI_STL_CCY, 0, {"BACK_END_BUBBLE_ALL"}, {0}}, 01181 {PAPI_TOT_IIS, 0, {"INST_DISPERSED"}, {0}}, 01182 {PAPI_RES_STL, 0, {"BE_EXE_BUBBLE_ALL"}, {0}}, 01183 {PAPI_FP_STAL, 0, {"BE_EXE_BUBBLE_FRALL"}, {0}}, 01184 {PAPI_L2_TCR, DERIVED_ADD, 01185 {"L2_DATA_REFERENCES_L2_DATA_READS", "L2_INST_DEMAND_READS", 01186 "L2_INST_PREFETCHES"}, {0}}, 01187 {PAPI_L1_TCM, DERIVED_ADD, {"L2_INST_DEMAND_READS", "L1D_READ_MISSES_ALL"}, 01188 {0}}, 01189 {PAPI_L1_ICM, 0, {"L2_INST_DEMAND_READS"}, {0}}, 01190 {PAPI_L1_DCM, 0, {"L1D_READ_MISSES_ALL"}, {0}}, 01191 {PAPI_L2_TCM, 0, {"L2_MISSES"}, {0}}, 01192 {PAPI_L2_DCM, DERIVED_SUB, {"L2_MISSES", "L3_READS_INST_FETCH_ALL"}, {0}}, 01193 {PAPI_L2_ICM, 0, {"L3_READS_INST_FETCH_ALL"}, {0}}, 01194 {PAPI_L3_TCM, 0, {"L3_MISSES"}, {0}}, 01195 {PAPI_L3_ICM, 0, {"L3_READS_INST_FETCH_MISS"}, {0}}, 01196 {PAPI_L3_DCM, DERIVED_ADD, 01197 {"L3_READS_DATA_READ_MISS", "L3_WRITES_DATA_WRITE_MISS"}, {0}}, 01198 {PAPI_L3_LDM, 0, {"L3_READS_ALL_MISS"}, {0}}, 01199 {PAPI_L3_STM, 0, {"L3_WRITES_DATA_WRITE_MISS"}, {0}}, 01200 {PAPI_L1_LDM, DERIVED_ADD, {"L1D_READ_MISSES_ALL", "L2_INST_DEMAND_READS"}, 01201 {0}}, 01202 {PAPI_L2_LDM, 0, {"L3_READS_ALL_ALL"}, {0}}, 01203 {PAPI_L2_STM, 0, {"L3_WRITES_ALL_ALL"}, {0}}, 01204 {PAPI_L1_DCH, DERIVED_SUB, {"L1D_READS_SET1", "L1D_READ_MISSES_ALL"}, {0}}, 01205 {PAPI_L2_DCH, DERIVED_SUB, {"L2_DATA_REFERENCES_L2_ALL", "L2_MISSES"}, {0}}, 01206 {PAPI_L3_DCH, DERIVED_ADD, 01207 {"L3_READS_DATA_READ_HIT", "L3_WRITES_DATA_WRITE_HIT"}, {0}}, 01208 {PAPI_L1_DCA, 0, {"L1D_READS_SET1"}, {0}}, 01209 {PAPI_L2_DCA, 0, {"L2_DATA_REFERENCES_L2_ALL"}, {0}}, 01210 {PAPI_L3_DCA, DERIVED_ADD, 01211 {"L3_READS_DATA_READ_ALL", "L3_WRITES_DATA_WRITE_ALL"}, {0}}, 01212 {PAPI_L1_DCR, 0, {"L1D_READS_SET1"}, {0}}, 01213 {PAPI_L2_DCR, 0, {"L2_DATA_REFERENCES_L2_DATA_READS"}, {0}}, 01214 {PAPI_L3_DCR, 0, {"L3_READS_DATA_READ_ALL"}, {0}}, 01215 {PAPI_L2_DCW, 0, {"L2_DATA_REFERENCES_L2_DATA_WRITES"}, {0}}, 01216 {PAPI_L3_DCW, 0, {"L3_WRITES_DATA_WRITE_ALL"}, {0}}, 01217 {PAPI_L3_ICH, 0, {"L3_READS_DINST_FETCH_HIT"}, {0}}, 01218 {PAPI_L1_ICR, DERIVED_ADD, {"L1I_PREFETCHES", "L1I_READS"}, {0}}, 01219 {PAPI_L2_ICR, DERIVED_ADD, {"L2_INST_DEMAND_READS", "L2_INST_PREFETCHES"}, 01220 {0}}, 01221 {PAPI_L3_ICR, 0, {"L3_READS_INST_FETCH_ALL"}, {0}}, 01222 {PAPI_L1_ICA, DERIVED_ADD, {"L1I_PREFETCHES", "L1I_READS"}, {0}}, 01223 {PAPI_L2_TCH, DERIVED_SUB, {"L2_REFERENCES", "L2_MISSES"}, {0}}, 01224 {PAPI_L3_TCH, DERIVED_SUB, {"L3_REFERENCES", "L3_MISSES"}, {0}}, 01225 {PAPI_L2_TCA, 0, {"L2_REFERENCES"}, {0}}, 01226 {PAPI_L3_TCA, 0, {"L3_REFERENCES"}, {0}}, 01227 {PAPI_L3_TCR, 0, {"L3_READS_ALL_ALL"}, {0}}, 01228 {PAPI_L3_TCW, 0, {"L3_WRITES_ALL_ALL"}, {0}}, 01229 {PAPI_TLB_DM, 0, {"L2DTLB_MISSES"}, {0}}, 01230 {PAPI_TLB_IM, 0, {"ITLB_MISSES_FETCH_L2ITLB"}, {0}}, 01231 {PAPI_BR_INS, 0, {"BRANCH_EVENT"}, {0}}, 01232 {PAPI_BR_PRC, 0, {"BR_MISPRED_DETAIL_ALL_CORRECT_PRED"}, {0}}, 01233 {PAPI_BR_MSP, DERIVED_ADD, 01234 {"BR_MISPRED_DETAIL_ALL_WRONG_PATH", "BR_MISPRED_DETAIL_ALL_WRONG_TARGET"}, 01235 {0}}, 01236 {PAPI_TOT_CYC, 0, {"CPU_CYCLES"}, {0}}, 01237 {PAPI_FP_OPS, 0, {"FP_OPS_RETIRED"}, {0}}, 01238 {PAPI_TOT_INS, DERIVED_ADD, {"IA64_INST_RETIRED", "IA32_INST_RETIRED"}, 01239 {0}}, 01240 {PAPI_LD_INS, 0, {"LOADS_RETIRED"}, {0}}, 01241 {PAPI_SR_INS, 0, {"STORES_RETIRED"}, {0}}, 01242 {PAPI_L2_ICA, 0, {"L2_INST_DEMAND_READS"}, {0}}, 01243 {PAPI_L3_ICA, 0, {"L3_READS_INST_FETCH_ALL"}, {0}}, 01244 {PAPI_L1_TCR, DERIVED_ADD, {"L1D_READS_SET0", "L1I_READS"}, {0}}, 01245 {PAPI_L1_TCA, DERIVED_ADD, {"L1D_READS_SET0", "L1I_READS"}, {0}}, 01246 {PAPI_L2_TCW, 0, {"L2_DATA_REFERENCES_L2_DATA_WRITES"}, {0}}, 01247 {0, 0, {0}, {0}} 01248 }; 01249 01250 static itanium_preset_search_t ia3_preset_search_map[] = { 01251 /* not sure */ 01252 {PAPI_CA_SNP, 0, {"BUS_SNOOP_STALL_CYCLES_ANY"}, {0}}, 01253 {PAPI_CA_INV, DERIVED_ADD, 01254 {"BUS_MEM_READ_BRIL_SELF", "BUS_MEM_READ_BIL_SELF"}, {0}}, 01255 /* should be OK */ 01256 {PAPI_TLB_TL, DERIVED_ADD, {"ITLB_MISSES_FETCH_L2ITLB", "L2DTLB_MISSES"}, 01257 {0}}, 01258 {PAPI_STL_ICY, 0, {"DISP_STALLED"}, {0}}, 01259 {PAPI_STL_CCY, 0, {"BACK_END_BUBBLE_ALL"}, {0}}, 01260 {PAPI_TOT_IIS, 0, {"INST_DISPERSED"}, {0}}, 01261 {PAPI_RES_STL, 0, {"BE_EXE_BUBBLE_ALL"}, {0}}, 01262 {PAPI_FP_STAL, 0, {"BE_EXE_BUBBLE_FRALL"}, {0}}, 01263 /* should be OK */ 01264 {PAPI_L2_TCR, DERIVED_ADD, 01265 {"L2D_REFERENCES_READS", "L2I_READS_ALL_DMND", "L2I_READS_ALL_PFTCH"}, 01266 {0}}, 01267 /* what is the correct name here: L2I_READS_ALL_DMND or L2I_DEMANDS_READ ? 01268 * do not have papi_native_avail at this time, going to use L2I_READS_ALL_DMND always 01269 * just replace on demand 01270 */ 01271 {PAPI_L1_TCM, DERIVED_ADD, {"L2I_READS_ALL_DMND", "L1D_READ_MISSES_ALL"}, 01272 {0}}, 01273 {PAPI_L1_ICM, 0, {"L2I_READS_ALL_DMND"}, {0}}, 01274 {PAPI_L1_DCM, 0, {"L1D_READ_MISSES_ALL"}, {0}}, 01275 {PAPI_L2_TCM, 0, {"L2I_READS_MISS_ALL", "L2D_MISSES"}, {0}}, 01276 {PAPI_L2_DCM, DERIVED_SUB, {"L2D_MISSES"}, {0}}, 01277 {PAPI_L2_ICM, 0, {"L2I_READS_MISS_ALL"}, {0}}, 01278 {PAPI_L3_TCM, 0, {"L3_MISSES"}, {0}}, 01279 {PAPI_L3_ICM, 0, {"L3_READS_INST_FETCH_MISS:M:E:S:I"}, {0}}, 01280 {PAPI_L3_DCM, DERIVED_ADD, 01281 {"L3_READS_DATA_READ_MISS:M:E:S:I", "L3_WRITES_DATA_WRITE_MISS:M:E:S:I"}, 01282 {0}}, 01283 {PAPI_L3_LDM, 0, {"L3_READS_ALL_MISS:M:E:S:I"}, {0}}, 01284 {PAPI_L3_STM, 0, {"L3_WRITES_DATA_WRITE_MISS:M:E:S:I"}, {0}}, 01285 /* why L2_INST_DEMAND_READS has been added here for the Itanium II ? 01286 * OLD: {PAPI_L1_LDM, DERIVED_ADD, {"L1D_READ_MISSES_ALL", "L2_INST_DEMAND_READS", 0, 0}} 01287 */ 01288 {PAPI_L1_LDM, 0, {"L1D_READ_MISSES_ALL"}, {0}}, 01289 {PAPI_L2_LDM, 0, {"L3_READS_ALL_ALL:M:E:S:I"}, {0}}, 01290 {PAPI_L2_STM, 0, {"L3_WRITES_ALL_ALL:M:E:S:I"}, {0}}, 01291 {PAPI_L1_DCH, DERIVED_SUB, {"L1D_READS_SET1", "L1D_READ_MISSES_ALL"}, {0}}, 01292 {PAPI_L2_DCH, DERIVED_SUB, {"L2D_REFERENCES_ALL", "L2D_MISSES"}, {0}}, 01293 {PAPI_L3_DCH, DERIVED_ADD, 01294 {"L3_READS_DATA_READ_HIT:M:E:S:I", "L3_WRITES_DATA_WRITE_HIT:M:E:S:I"}, 01295 {0}}, 01296 {PAPI_L1_DCA, 0, {"L1D_READS_SET1"}, {0}}, 01297 {PAPI_L2_DCA, 0, {"L2D_REFERENCES_ALL"}, {0}}, 01298 {PAPI_L3_DCA, 0, {"L3_REFERENCES"}, {0}}, 01299 {PAPI_L1_DCR, 0, {"L1D_READS_SET1"}, {0}}, 01300 {PAPI_L2_DCR, 0, {"L2D_REFERENCES_READS"}, {0}}, 01301 {PAPI_L3_DCR, 0, {"L3_READS_DATA_READ_ALL:M:E:S:I"}, {0}}, 01302 {PAPI_L2_DCW, 0, {"L2D_REFERENCES_WRITES"}, {0}}, 01303 {PAPI_L3_DCW, 0, {"L3_WRITES_DATA_WRITE_ALL:M:E:S:I"}, {0}}, 01304 {PAPI_L3_ICH, 0, {"L3_READS_DINST_FETCH_HIT:M:E:S:I"}, {0}}, 01305 {PAPI_L1_ICR, DERIVED_ADD, {"L1I_PREFETCHES", "L1I_READS"}, {0}}, 01306 {PAPI_L2_ICR, DERIVED_ADD, {"L2I_READS_ALL_DMND", "L2I_PREFETCHES"}, {0}}, 01307 {PAPI_L3_ICR, 0, {"L3_READS_INST_FETCH_ALL:M:E:S:I"}, {0}}, 01308 {PAPI_L1_ICA, DERIVED_ADD, {"L1I_PREFETCHES", "L1I_READS"}, {0}}, 01309 {PAPI_L2_TCH, DERIVED_SUB, {"L2I_READS_HIT_ALL", "L2D_INSERT_HITS"}, {0}}, 01310 {PAPI_L3_TCH, DERIVED_SUB, {"L3_REFERENCES", "L3_MISSES"}, {0}}, 01311 {PAPI_L2_TCA, DERIVED_ADD, {"L2I_READS_ALL_ALL", "L2D_REFERENCES_ALL"}, 01312 {0}}, 01313 {PAPI_L3_TCA, 0, {"L3_REFERENCES"}, {0}}, 01314 {PAPI_L3_TCR, 0, {"L3_READS_ALL_ALL:M:E:S:I"}, {0}}, 01315 {PAPI_L3_TCW, 0, {"L3_WRITES_ALL_ALL:M:E:S:I"}, {0}}, 01316 {PAPI_TLB_DM, 0, {"L2DTLB_MISSES"}, {0}}, 01317 {PAPI_TLB_IM, 0, {"ITLB_MISSES_FETCH_L2ITLB"}, {0}}, 01318 {PAPI_BR_INS, 0, {"BRANCH_EVENT"}, {0}}, 01319 {PAPI_BR_PRC, 0, {"BR_MISPRED_DETAIL_ALL_CORRECT_PRED"}, {0}}, 01320 {PAPI_BR_MSP, DERIVED_ADD, 01321 {"BR_MISPRED_DETAIL_ALL_WRONG_PATH", "BR_MISPRED_DETAIL_ALL_WRONG_TARGET"}, 01322 {0}}, 01323 {PAPI_TOT_CYC, 0, {"CPU_OP_CYCLES_ALL"}, {0}}, 01324 {PAPI_FP_OPS, 0, {"FP_OPS_RETIRED"}, {0}}, 01325 // {PAPI_TOT_INS, DERIVED_ADD, {"IA64_INST_RETIRED", "IA32_INST_RETIRED"}, {0}}, 01326 {PAPI_TOT_INS, 0, {"IA64_INST_RETIRED"}, {0}}, 01327 {PAPI_LD_INS, 0, {"LOADS_RETIRED"}, {0}}, 01328 {PAPI_SR_INS, 0, {"STORES_RETIRED"}, {0}}, 01329 {PAPI_L2_ICA, 0, {"L2I_DEMAND_READS"}, {0}}, 01330 {PAPI_L3_ICA, 0, {"L3_READS_INST_FETCH_ALL:M:E:S:I"}, {0}}, 01331 {PAPI_L1_TCR, 0, {"L2I_READS_ALL_ALL"}, {0}}, 01332 /* Why are TCA READS+READS_SET0? I used the same as PAPI_L1_TCR, because its an write through cache 01333 * OLD: {PAPI_L1_TCA, DERIVED_ADD, {"L1D_READS_SET0", "L1I_READS"}, {0}}, 01334 */ 01335 {PAPI_L1_TCA, DERIVED_ADD, 01336 {"L1I_PREFETCHES", "L1I_READS", "L1D_READS_SET0"}, {0}}, 01337 {PAPI_L2_TCW, 0, {"L2D_REFERENCES_WRITES"}, {0}}, 01338 {0, 0, {0}, {0}} 01339 }; 01340 01341 /* This component should never malloc anything. All allocation should be 01342 done by the high level API. */ 01343 01344 01345 /***************************************************************************** 01346 * Code to support unit masks; only needed by Montecito and above * 01347 *****************************************************************************/ 01348 static int _ia64_modify_event( unsigned int event, int modifier ); 01349 01350 /* Break a PAPI native event code into its composite event code and pfm mask bits */ 01351 static int 01352 _pfm_decode_native_event( unsigned int EventCode, unsigned int *event, 01353 unsigned int *umask ) 01354 { 01355 unsigned int tevent, major, minor; 01356 01357 tevent = EventCode & PAPI_NATIVE_AND_MASK; 01358 major = ( tevent & PAPI_NATIVE_EVENT_AND_MASK ) >> PAPI_NATIVE_EVENT_SHIFT; 01359 if ( major >= ( unsigned int ) _ia64_vector.cmp_info.num_native_events ) 01360 return ( PAPI_ENOEVNT ); 01361 01362 minor = ( tevent & PAPI_NATIVE_UMASK_AND_MASK ) >> PAPI_NATIVE_UMASK_SHIFT; 01363 *event = major; 01364 *umask = minor; 01365 SUBDBG( "EventCode 0x%08x is event %d, umask 0x%x\n", EventCode, major, 01366 minor ); 01367 return ( PAPI_OK ); 01368 } 01369 01370 /* This routine is used to step through all possible combinations of umask 01371 values. It assumes that mask contains a valid combination of array indices 01372 for this event. */ 01373 static int 01374 encode_native_event_raw( unsigned int event, unsigned int mask ) 01375 { 01376 unsigned int tmp = event << PAPI_NATIVE_EVENT_SHIFT; 01377 SUBDBG( "Old native index was 0x%08x with 0x%08x mask\n", tmp, mask ); 01378 tmp = tmp | ( mask << PAPI_NATIVE_UMASK_SHIFT ); 01379 SUBDBG( "New encoding is 0x%08x\n", tmp | PAPI_NATIVE_MASK ); 01380 return ( tmp | PAPI_NATIVE_MASK ); 01381 } 01382 01383 /* convert a collection of pfm mask bits into an array of pfm mask indices */ 01384 static int 01385 prepare_umask( unsigned int foo, unsigned int *values ) 01386 { 01387 unsigned int tmp = foo, i, j = 0; 01388 01389 SUBDBG( "umask 0x%x\n", tmp ); 01390 if ( foo == 0 ) 01391 return 0; 01392 while ( ( i = ffs( tmp ) ) ) { 01393 tmp = tmp ^ ( 1 << ( i - 1 ) ); 01394 values[j] = i - 1; 01395 SUBDBG( "umask %d is %d\n", j, values[j] ); 01396 j++; 01397 } 01398 return ( j ); 01399 } 01400 01401 int 01402 _papi_pfm_ntv_enum_events( unsigned int *EventCode, int modifier ) 01403 { 01404 unsigned int event, umask, num_masks; 01405 int ret; 01406 01407 if ( modifier == PAPI_ENUM_FIRST ) { 01408 *EventCode = PAPI_NATIVE_MASK; /* assumes first native event is always 0x4000000 */ 01409 return ( PAPI_OK ); 01410 } 01411 01412 if ( _pfm_decode_native_event( *EventCode, &event, &umask ) != PAPI_OK ) 01413 return ( PAPI_ENOEVNT ); 01414 01415 ret = pfm_get_num_event_masks( event, &num_masks ); 01416 SUBDBG( "pfm_get_num_event_masks: event=%d num_masks=%d\n", event, 01417 num_masks ); 01418 if ( ret != PFMLIB_SUCCESS ) { 01419 PAPIERROR( "pfm_get_num_event_masks(%d,%p): %s", event, &num_masks, 01420 pfm_strerror( ret ) ); 01421 return ( PAPI_ENOEVNT ); 01422 } 01423 if ( num_masks > PAPI_NATIVE_UMASK_MAX ) 01424 num_masks = PAPI_NATIVE_UMASK_MAX; 01425 SUBDBG( "This is umask %d of %d\n", umask, num_masks ); 01426 01427 if ( modifier == PAPI_ENUM_EVENTS ) { 01428 if ( event < ( unsigned int ) _ia64_vector.cmp_info.num_native_events - 1 ) { 01429 *EventCode = encode_native_event_raw( event + 1, 0 ); 01430 return ( PAPI_OK ); 01431 } 01432 return ( PAPI_ENOEVNT ); 01433 } else if ( modifier == PAPI_NTV_ENUM_UMASK_COMBOS ) { 01434 if ( umask + 1 < ( unsigned ) ( 1 << num_masks ) ) { 01435 *EventCode = encode_native_event_raw( event, umask + 1 ); 01436 return ( PAPI_OK ); 01437 } 01438 return ( PAPI_ENOEVNT ); 01439 } else if ( modifier == PAPI_NTV_ENUM_UMASKS ) { 01440 int thisbit = ffs( umask ); 01441 01442 SUBDBG( "First bit is %d in %08x\b\n", thisbit - 1, umask ); 01443 thisbit = 1 << thisbit; 01444 01445 if ( thisbit & ( ( 1 << num_masks ) - 1 ) ) { 01446 *EventCode = encode_native_event_raw( event, thisbit ); 01447 return ( PAPI_OK ); 01448 } 01449 return ( PAPI_ENOEVNT ); 01450 } else { 01451 while ( event++ < 01452 ( unsigned int ) _ia64_vector.cmp_info.num_native_events - 1 ) { 01453 *EventCode = encode_native_event_raw( event + 1, 0 ); 01454 if ( _ia64_modify_event( event + 1, modifier ) ) 01455 return ( PAPI_OK ); 01456 } 01457 return ( PAPI_ENOEVNT ); 01458 } 01459 } 01460 01461 static int 01462 _papi_pfm_ntv_name_to_code( char *name, unsigned int *event_code ) 01463 { 01464 pfmlib_event_t event; 01465 unsigned int i, mask = 0; 01466 int ret; 01467 01468 SUBDBG( "pfm_find_full_event(%s,%p)\n", name, &event ); 01469 ret = pfm_find_full_event( name, &event ); 01470 if ( ret == PFMLIB_SUCCESS ) { 01471 /* we can only capture PAPI_NATIVE_UMASK_MAX or fewer masks */ 01472 if ( event.num_masks > PAPI_NATIVE_UMASK_MAX ) { 01473 SUBDBG( "num_masks (%d) > max masks (%d)\n", event.num_masks, 01474 PAPI_NATIVE_UMASK_MAX ); 01475 return ( PAPI_ENOEVNT ); 01476 } else { 01477 /* no mask index can exceed PAPI_NATIVE_UMASK_MAX */ 01478 for ( i = 0; i < event.num_masks; i++ ) { 01479 if ( event.unit_masks[i] > PAPI_NATIVE_UMASK_MAX ) { 01480 SUBDBG( "mask index (%d) > max masks (%d)\n", 01481 event.unit_masks[i], PAPI_NATIVE_UMASK_MAX ); 01482 return ( PAPI_ENOEVNT ); 01483 } 01484 mask |= 1 << event.unit_masks[i]; 01485 } 01486 *event_code = encode_native_event_raw( event.event, mask ); 01487 SUBDBG( "event_code: 0x%x event: %d num_masks: %d\n", *event_code, 01488 event.event, event.num_masks ); 01489 return ( PAPI_OK ); 01490 } 01491 } else if ( ret == PFMLIB_ERR_UMASK ) { 01492 ret = pfm_find_event( name, &event.event ); 01493 if ( ret == PFMLIB_SUCCESS ) { 01494 *event_code = encode_native_event_raw( event.event, 0 ); 01495 return ( PAPI_OK ); 01496 } 01497 } 01498 return ( PAPI_ENOEVNT ); 01499 } 01500 01501 int 01502 _papi_pfm_ntv_code_to_name( unsigned int EventCode, char *ntv_name, int len ) 01503 { 01504 int ret; 01505 unsigned int event, umask; 01506 pfmlib_event_t gete; 01507 01508 memset( &gete, 0, sizeof ( gete ) ); 01509 01510 if ( _pfm_decode_native_event( EventCode, &event, &umask ) != PAPI_OK ) 01511 return ( PAPI_ENOEVNT ); 01512 01513 gete.event = event; 01514 gete.num_masks = prepare_umask( umask, gete.unit_masks ); 01515 if ( gete.num_masks == 0 ) 01516 ret = pfm_get_event_name( gete.event, ntv_name, len ); 01517 else 01518 ret = pfm_get_full_event_name( &gete, ntv_name, len ); 01519 if ( ret != PFMLIB_SUCCESS ) { 01520 char tmp[PAPI_2MAX_STR_LEN]; 01521 pfm_get_event_name( gete.event, tmp, sizeof ( tmp ) ); 01522 PAPIERROR 01523 ( "pfm_get_full_event_name(%p(event %d,%s,%d masks),%p,%d): %d -- %s", 01524 &gete, gete.event, tmp, gete.num_masks, ntv_name, len, ret, 01525 pfm_strerror( ret ) ); 01526 if ( ret == PFMLIB_ERR_FULL ) 01527 return PAPI_EBUF; 01528 return PAPI_ECMP; 01529 } 01530 return PAPI_OK; 01531 } 01532 01533 int 01534 _papi_pfm_ntv_code_to_descr( unsigned int EventCode, char *ntv_descr, int len ) 01535 { 01536 unsigned int event, umask; 01537 char *eventd, **maskd, *tmp; 01538 int i, ret, total_len = 0; 01539 pfmlib_event_t gete; 01540 01541 memset( &gete, 0, sizeof ( gete ) ); 01542 01543 if ( _pfm_decode_native_event( EventCode, &event, &umask ) != PAPI_OK ) 01544 return ( PAPI_ENOEVNT ); 01545 01546 ret = pfm_get_event_description( event, &eventd ); 01547 if ( ret != PFMLIB_SUCCESS ) { 01548 PAPIERROR( "pfm_get_event_description(%d,%p): %s", 01549 event, &eventd, pfm_strerror( ret ) ); 01550 return ( PAPI_ENOEVNT ); 01551 } 01552 01553 if ( ( gete.num_masks = prepare_umask( umask, gete.unit_masks ) ) ) { 01554 maskd = ( char ** ) malloc( gete.num_masks * sizeof ( char * ) ); 01555 if ( maskd == NULL ) { 01556 free( eventd ); 01557 return ( PAPI_ENOMEM ); 01558 } 01559 for ( i = 0; i < ( int ) gete.num_masks; i++ ) { 01560 ret = 01561 pfm_get_event_mask_description( event, gete.unit_masks[i], 01562 &maskd[i] ); 01563 if ( ret != PFMLIB_SUCCESS ) { 01564 PAPIERROR( "pfm_get_event_mask_description(%d,%d,%p): %s", 01565 event, umask, &maskd, pfm_strerror( ret ) ); 01566 free( eventd ); 01567 for ( ; i >= 0; i-- ) 01568 free( maskd[i] ); 01569 free( maskd ); 01570 return ( PAPI_EINVAL ); 01571 } 01572 total_len += strlen( maskd[i] ); 01573 } 01574 tmp = 01575 ( char * ) malloc( strlen( eventd ) + strlen( ", masks:" ) + 01576 total_len + gete.num_masks + 1 ); 01577 if ( tmp == NULL ) { 01578 for ( i = gete.num_masks - 1; i >= 0; i-- ) 01579 free( maskd[i] ); 01580 free( maskd ); 01581 free( eventd ); 01582 } 01583 tmp[0] = '\0'; 01584 strcat( tmp, eventd ); 01585 strcat( tmp, ", masks:" ); 01586 for ( i = 0; i < ( int ) gete.num_masks; i++ ) { 01587 if ( i != 0 ) 01588 strcat( tmp, "," ); 01589 strcat( tmp, maskd[i] ); 01590 free( maskd[i] ); 01591 } 01592 free( maskd ); 01593 } else { 01594 tmp = ( char * ) malloc( strlen( eventd ) + 1 ); 01595 if ( tmp == NULL ) { 01596 free( eventd ); 01597 return ( PAPI_ENOMEM ); 01598 } 01599 tmp[0] = '\0'; 01600 strcat( tmp, eventd ); 01601 free( eventd ); 01602 } 01603 strncpy( ntv_descr, tmp, len ); 01604 if ( strlen( tmp ) > ( unsigned int ) len - 1 ) 01605 ret = PAPI_EBUF; 01606 else 01607 ret = PAPI_OK; 01608 free( tmp ); 01609 return ( ret ); 01610 } 01611 01612 /***************************************************************************** 01613 *****************************************************************************/ 01614 01615 /* The values defined in this file may be X86-specific (2 general 01616 purpose counters, 1 special purpose counter, etc.*/ 01617 01618 /* PAPI stuff */ 01619 01620 /* Low level functions, should not handle errors, just return codes. */ 01621 01622 /* I want to keep the old way to define the preset search map. 01623 In Itanium2, there are more than 400 native events, if I use the 01624 index directly, it will be difficult for people to debug, so I 01625 still keep the old way to define preset search table, but 01626 I add this function to generate the preset search map in papi3 01627 */ 01628 int 01629 generate_preset_search_map( hwi_search_t ** maploc, 01630 itanium_preset_search_t * oldmap, int num_cnt ) 01631 { 01632 ( void ) num_cnt; /*unused */ 01633 int pnum, i = 0, cnt; 01634 char **findme; 01635 hwi_search_t *psmap; 01636 01637 /* Count up the presets */ 01638 while ( oldmap[i].preset ) 01639 i++; 01640 /* Add null entry */ 01641 i++; 01642 01643 psmap = ( hwi_search_t * ) papi_malloc( i * sizeof ( hwi_search_t ) ); 01644 if ( psmap == NULL ) 01645 return ( PAPI_ENOMEM ); 01646 memset( psmap, 0x0, i * sizeof ( hwi_search_t ) ); 01647 01648 pnum = 0; /* preset event counter */ 01649 for ( i = 0; i <= PAPI_MAX_PRESET_EVENTS; i++ ) { 01650 if ( oldmap[i].preset == 0 ) 01651 break; 01652 pnum++; 01653 psmap[i].event_code = oldmap[i].preset; 01654 psmap[i].data.derived = oldmap[i].derived; 01655 strcpy( psmap[i].data.operation, oldmap[i].operation ); 01656 findme = oldmap[i].findme; 01657 cnt = 0; 01658 while ( *findme != NULL ) { 01659 if ( cnt == MAX_COUNTER_TERMS ) { 01660 PAPIERROR( "Count (%d) == MAX_COUNTER_TERMS (%d)\n", cnt, 01661 MAX_COUNTER_TERMS ); 01662 papi_free( psmap ); 01663 return ( PAPI_EBUG ); 01664 } 01665 if ( _perfmon2_pfm_pmu_type == PFMLIB_MONTECITO_PMU ) { 01666 if ( _papi_pfm_ntv_name_to_code 01667 ( *findme, 01668 ( unsigned int * ) &psmap[i].data.native[cnt] ) != 01669 PAPI_OK ) { 01670 PAPIERROR( "_papi_pfm_ntv_name_to_code(%s) failed\n", 01671 *findme ); 01672 papi_free( psmap ); 01673 return ( PAPI_EBUG ); 01674 } else 01675 psmap[i].data.native[cnt] ^= PAPI_NATIVE_MASK; 01676 } else { 01677 if ( pfm_find_event_byname 01678 ( *findme, 01679 ( unsigned int * ) &psmap[i].data.native[cnt] ) != 01680 PFMLIB_SUCCESS ) { 01681 PAPIERROR( "pfm_find_event_byname(%s) failed\n", *findme ); 01682 papi_free( psmap ); 01683 return ( PAPI_EBUG ); 01684 } else 01685 psmap[i].data.native[cnt] ^= PAPI_NATIVE_MASK; 01686 } 01687 01688 findme++; 01689 cnt++; 01690 } 01691 psmap[i].data.native[cnt] = PAPI_NULL; 01692 } 01693 01694 *maploc = psmap; 01695 return ( PAPI_OK ); 01696 } 01697 01698 01699 static char * 01700 search_cpu_info( FILE * f, char *search_str, char *line ) 01701 { 01702 /* This code courtesy of our friends in Germany. Thanks Rudolph Berrendorf! */ 01703 /* See the PCL home page for the German version of PAPI. */ 01704 01705 char *s; 01706 01707 while ( fgets( line, 256, f ) != NULL ) { 01708 if ( strstr( line, search_str ) != NULL ) { 01709 /* ignore all characters in line up to : */ 01710 for ( s = line; *s && ( *s != ':' ); ++s ); 01711 if ( *s ) 01712 return ( s ); 01713 } 01714 } 01715 return ( NULL ); 01716 01717 /* End stolen code */ 01718 } 01719 01720 int 01721 _ia64_ita_set_domain( hwd_control_state_t * this_state, int domain ) 01722 { 01723 int mode = 0, did = 0, i; 01724 pfmw_param_t *evt = &( ( ia64_control_state_t * ) this_state )->evt; 01725 01726 if ( domain & PAPI_DOM_USER ) { 01727 did = 1; 01728 mode |= PFM_PLM3; 01729 } 01730 01731 if ( domain & PAPI_DOM_KERNEL ) { 01732 did = 1; 01733 mode |= PFM_PLM0; 01734 } 01735 01736 if ( !did ) 01737 return ( PAPI_EINVAL ); 01738 01739 PFMW_PEVT_DFLPLM( evt ) = mode; 01740 01741 /* Bug fix in case we don't call pfmw_dispatch_events after this code */ 01742 /* Who did this? This sucks, we should always call it here -PJM */ 01743 01744 for ( i = 0; i < _ia64_vector.cmp_info.num_cntrs; i++ ) { 01745 if ( PFMW_PEVT_PFPPC_REG_NUM( evt, i ) ) { 01746 pfm_ita_pmc_reg_t value; 01747 SUBDBG( "slot %d, register %lud active, config value 0x%lx\n", 01748 i, ( unsigned long ) ( PFMW_PEVT_PFPPC_REG_NUM( evt, i ) ), 01749 PFMW_PEVT_PFPPC_REG_VAL( evt, i ) ); 01750 01751 PFMW_ARCH_REG_PMCVAL( value ) = PFMW_PEVT_PFPPC_REG_VAL( evt, i ); 01752 value.pmc_ita_count_reg.pmc_plm = mode; 01753 PFMW_PEVT_PFPPC_REG_VAL( evt, i ) = PFMW_ARCH_REG_PMCVAL( value ); 01754 01755 SUBDBG( "new config value 0x%lx\n", 01756 PFMW_PEVT_PFPPC_REG_VAL( evt, i ) ); 01757 } 01758 } 01759 01760 return PAPI_OK; 01761 } 01762 01763 int 01764 _ia64_ita2_set_domain( hwd_control_state_t * this_state, int domain ) 01765 { 01766 int mode = 0, did = 0, i; 01767 pfmw_param_t *evt = &this_state->evt; 01768 01769 if ( domain & PAPI_DOM_USER ) { 01770 did = 1; 01771 mode |= PFM_PLM3; 01772 } 01773 01774 if ( domain & PAPI_DOM_KERNEL ) { 01775 did = 1; 01776 mode |= PFM_PLM0; 01777 } 01778 01779 if ( !did ) 01780 return ( PAPI_EINVAL ); 01781 01782 PFMW_PEVT_DFLPLM( evt ) = mode; 01783 01784 /* Bug fix in case we don't call pfmw_dispatch_events after this code */ 01785 /* Who did this? This sucks, we should always call it here -PJM */ 01786 01787 for ( i = 0; i < _ia64_vector.cmp_info.num_cntrs; i++ ) { 01788 if ( PFMW_PEVT_PFPPC_REG_NUM( evt, i ) ) { 01789 pfm_ita2_pmc_reg_t value; 01790 SUBDBG( "slot %d, register %lud active, config value 0x%lx\n", 01791 i, ( unsigned long ) ( PFMW_PEVT_PFPPC_REG_NUM( evt, i ) ), 01792 PFMW_PEVT_PFPPC_REG_VAL( evt, i ) ); 01793 01794 PFMW_ARCH_REG_PMCVAL( value ) = PFMW_PEVT_PFPPC_REG_VAL( evt, i ); 01795 value.pmc_ita2_counter_reg.pmc_plm = mode; 01796 PFMW_PEVT_PFPPC_REG_VAL( evt, i ) = PFMW_ARCH_REG_PMCVAL( value ); 01797 01798 SUBDBG( "new config value 0x%lx\n", 01799 PFMW_PEVT_PFPPC_REG_VAL( evt, i ) ); 01800 } 01801 } 01802 01803 return ( PAPI_OK ); 01804 } 01805 01806 int 01807 _ia64_mont_set_domain( hwd_control_state_t * this_state, int domain ) 01808 { 01809 int mode = 0, did = 0, i; 01810 pfmw_param_t *evt = &( ( ia64_control_state_t * ) this_state )->evt; 01811 01812 if ( domain & PAPI_DOM_USER ) { 01813 did = 1; 01814 mode |= PFM_PLM3; 01815 } 01816 01817 if ( domain & PAPI_DOM_KERNEL ) { 01818 did = 1; 01819 mode |= PFM_PLM0; 01820 } 01821 01822 if ( !did ) 01823 return ( PAPI_EINVAL ); 01824 01825 PFMW_PEVT_DFLPLM( evt ) = mode; 01826 01827 /* Bug fix in case we don't call pfmw_dispatch_events after this code */ 01828 /* Who did this? This sucks, we should always call it here -PJM */ 01829 01830 for ( i = 0; i < _ia64_vector.cmp_info.num_cntrs; i++ ) { 01831 if ( PFMW_PEVT_PFPPC_REG_NUM( evt, i ) ) { 01832 pfm_mont_pmc_reg_t value; 01833 SUBDBG( "slot %d, register %lud active, config value 0x%lx\n", 01834 i, ( unsigned long ) ( PFMW_PEVT_PFPPC_REG_NUM( evt, i ) ), 01835 PFMW_PEVT_PFPPC_REG_VAL( evt, i ) ); 01836 01837 PFMW_ARCH_REG_PMCVAL( value ) = PFMW_PEVT_PFPPC_REG_VAL( evt, i ); 01838 value.pmc_mont_counter_reg.pmc_plm = mode; 01839 PFMW_PEVT_PFPPC_REG_VAL( evt, i ) = PFMW_ARCH_REG_PMCVAL( value ); 01840 01841 SUBDBG( "new config value 0x%lx\n", 01842 PFMW_PEVT_PFPPC_REG_VAL( evt, i ) ); 01843 } 01844 } 01845 01846 return ( PAPI_OK ); 01847 } 01848 01849 int 01850 _ia64_set_domain( hwd_control_state_t * this_state, int domain ) 01851 { 01852 switch ( _perfmon2_pfm_pmu_type ) { 01853 case PFMLIB_ITANIUM_PMU: 01854 return ( _ia64_ita_set_domain( this_state, domain ) ); 01855 break; 01856 case PFMLIB_ITANIUM2_PMU: 01857 return ( _ia64_ita2_set_domain( this_state, domain ) ); 01858 break; 01859 case PFMLIB_MONTECITO_PMU: 01860 return ( _ia64_mont_set_domain( this_state, domain ) ); 01861 break; 01862 default: 01863 PAPIERROR( "PMU type %d is not supported by this component", 01864 _perfmon2_pfm_pmu_type ); 01865 return ( PAPI_EBUG ); 01866 } 01867 } 01868 01869 static int 01870 set_granularity( hwd_control_state_t * this_state, int domain ) 01871 { 01872 ( void ) this_state; /*unused */ 01873 switch ( domain ) { 01874 case PAPI_GRN_PROCG: 01875 case PAPI_GRN_SYS: 01876 case PAPI_GRN_SYS_CPU: 01877 case PAPI_GRN_PROC: 01878 return PAPI_ECMP; 01879 case PAPI_GRN_THR: 01880 break; 01881 default: 01882 return PAPI_EINVAL; 01883 } 01884 return PAPI_OK; 01885 } 01886 01887 int 01888 _ia64_ita_read( hwd_context_t * ctx, hwd_control_state_t * machdep, 01889 long long **events, int flags ) 01890 { 01891 ( void ) flags; /*unused */ 01892 unsigned int i; 01893 pfarg_reg_t readem[_ia64_vector.cmp_info.num_cntrs]; 01894 01895 pfmw_stop( ( ia64_context_t * ) ctx ); 01896 memset( readem, 0x0, sizeof readem ); 01897 01898 /* read the 4 counters, the high level function will process the 01899 mapping for papi event to hardware counter 01900 */ 01901 for ( i = 0; i < ( unsigned int ) _ia64_vector.cmp_info.num_cntrs; i++ ) { 01902 readem[i].reg_num = PMU_FIRST_COUNTER + i; 01903 } 01904 01905 if ( pfmw_perfmonctl 01906 ( ( ( ia64_context_t * ) ctx )->tid, ( ( ia64_context_t * ) ctx )->fd, 01907 PFM_READ_PMDS, readem, _ia64_vector.cmp_info.num_cntrs ) == -1 ) { 01908 SUBDBG( "perfmonctl error READ_PMDS errno %d\n", errno ); 01909 pfmw_start( ( ia64_context_t * ) ctx ); 01910 return PAPI_ESYS; 01911 } 01912 01913 for ( i = 0; i < ( unsigned int ) _ia64_vector.cmp_info.num_cntrs; i++ ) { 01914 ( ( ia64_control_state_t * ) machdep )->counters[i] = 01915 readem[i].reg_value; 01916 SUBDBG( "read counters is %ld\n", readem[i].reg_value ); 01917 } 01918 01919 pfmw_param_t *pevt = &( ( ( ia64_control_state_t * ) machdep )->evt ); 01920 pfm_ita_pmc_reg_t flop_hack; 01921 /* special case, We need to scale FP_OPS_HI */ 01922 for ( i = 0; i < PFMW_PEVT_EVTCOUNT( pevt ); i++ ) { 01923 PFMW_ARCH_REG_PMCVAL( flop_hack ) = PFMW_PEVT_PFPPC_REG_VAL( pevt, i ); 01924 if ( flop_hack.pmc_ita_count_reg.pmc_es == 0xa ) 01925 ( ( ia64_control_state_t * ) machdep )->counters[i] *= 4; 01926 } 01927 01928 *events = ( ( ia64_control_state_t * ) machdep )->counters; 01929 pfmw_start( ( ia64_context_t * ) ctx ); 01930 return PAPI_OK; 01931 } 01932 01933 01934 int 01935 _ia64_ita23_read( hwd_context_t * ctx, hwd_control_state_t * machdep, 01936 long long **events, int flags ) 01937 { 01938 ( void ) flags; /*unused */ 01939 int i; 01940 pfarg_reg_t readem[_ia64_vector.cmp_info.num_cntrs]; 01941 01942 pfmw_stop( ( ia64_context_t * ) ctx ); 01943 memset( readem, 0x0, sizeof readem ); 01944 01945 /* read the 4 counters, the high level function will process the 01946 mapping for papi event to hardware counter 01947 */ 01948 for ( i = 0; i < _ia64_vector.cmp_info.num_cntrs; i++ ) { 01949 readem[i].reg_num = PMU_FIRST_COUNTER + i; 01950 } 01951 01952 if ( pfmw_perfmonctl 01953 ( ( ( ia64_context_t * ) ctx )->tid, ( ( ia64_context_t * ) ctx )->fd, 01954 PFM_READ_PMDS, readem, _ia64_vector.cmp_info.num_cntrs ) == -1 ) { 01955 SUBDBG( "perfmonctl error READ_PMDS errno %d\n", errno ); 01956 pfmw_start( ( ia64_context_t * ) ctx ); 01957 return PAPI_ESYS; 01958 } 01959 01960 for ( i = 0; i < _ia64_vector.cmp_info.num_cntrs; i++ ) { 01961 ( ( ia64_control_state_t * ) machdep )->counters[i] = 01962 readem[i].reg_value; 01963 SUBDBG( "read counters is %ld\n", readem[i].reg_value ); 01964 } 01965 01966 *events = ( ( ia64_control_state_t * ) machdep )->counters; 01967 pfmw_start( ( ia64_context_t * ) ctx ); 01968 return PAPI_OK; 01969 } 01970 01971 int 01972 _ia64_read( hwd_context_t * ctx, hwd_control_state_t * machdep, 01973 long long **events, int flags ) 01974 { 01975 switch ( _perfmon2_pfm_pmu_type ) { 01976 case PFMLIB_ITANIUM_PMU: 01977 return ( _ia64_ita_read( ctx, machdep, events, flags ) ); 01978 break; 01979 case PFMLIB_ITANIUM2_PMU: 01980 return ( _ia64_ita23_read( ctx, machdep, events, flags ) ); 01981 break; 01982 case PFMLIB_MONTECITO_PMU: 01983 return ( _ia64_ita23_read( ctx, machdep, events, flags ) ); 01984 break; 01985 default: 01986 PAPIERROR( "PMU type %d is not supported by this component", 01987 _perfmon2_pfm_pmu_type ); 01988 return ( PAPI_EBUG ); 01989 } 01990 } 01991 01992 /* This function should tell your kernel extension that your children 01993 inherit performance register information and propagate the values up 01994 upon child exit and parent wait. */ 01995 01996 static int 01997 set_inherit( int arg ) 01998 { 01999 ( void ) arg; /*unused */ 02000 return PAPI_ECMP; 02001 } 02002 02003 static int 02004 set_default_domain( hwd_control_state_t * this_state, int domain ) 02005 { 02006 return ( _ia64_set_domain( this_state, domain ) ); 02007 } 02008 02009 static int 02010 set_default_granularity( hwd_control_state_t * this_state, int granularity ) 02011 { 02012 return ( set_granularity( this_state, granularity ) ); 02013 } 02014 02015 02016 02017 02018 int 02019 _ia64_init_component( int cidx ) 02020 { 02021 ( void ) cidx; /*unused */ 02022 int i, retval, type; 02023 unsigned int version; 02024 pfmlib_options_t pfmlib_options; 02025 itanium_preset_search_t *ia_preset_search_map = NULL; 02026 02027 /* Always initialize globals dynamically to handle forks properly. */ 02028 02029 preset_search_map = NULL; 02030 02031 /* Opened once for all threads. */ 02032 if ( pfm_initialize( ) != PFMLIB_SUCCESS ) 02033 return ( PAPI_ESYS ); 02034 02035 if ( pfm_get_version( &version ) != PFMLIB_SUCCESS ) 02036 return PAPI_ECMP; 02037 02038 if ( PFM_VERSION_MAJOR( version ) != PFM_VERSION_MAJOR( PFMLIB_VERSION ) ) { 02039 PAPIERROR( "Version mismatch of libpfm: compiled %x vs. installed %x", 02040 PFM_VERSION_MAJOR( PFMLIB_VERSION ), 02041 PFM_VERSION_MAJOR( version ) ); 02042 return PAPI_ECMP; 02043 } 02044 02045 memset( &pfmlib_options, 0, sizeof ( pfmlib_options ) ); 02046 #ifdef DEBUG 02047 if ( ISLEVEL( DEBUG_SUBSTRATE ) ) { 02048 pfmlib_options.pfm_debug = 1; 02049 pfmlib_options.pfm_verbose = 1; 02050 } 02051 #endif 02052 02053 if ( pfm_set_options( &pfmlib_options ) ) 02054 return ( PAPI_ESYS ); 02055 02056 if ( pfm_get_pmu_type( &type ) != PFMLIB_SUCCESS ) 02057 return ( PAPI_ESYS ); 02058 02059 _perfmon2_pfm_pmu_type = type; 02060 02061 /* Setup presets */ 02062 02063 switch ( type ) { 02064 case PFMLIB_ITANIUM_PMU: 02065 ia_preset_search_map = ia1_preset_search_map; 02066 break; 02067 case PFMLIB_ITANIUM2_PMU: 02068 ia_preset_search_map = ia2_preset_search_map; 02069 break; 02070 case PFMLIB_MONTECITO_PMU: 02071 ia_preset_search_map = ia3_preset_search_map; 02072 break; 02073 default: 02074 PAPIERROR( "PMU type %d is not supported by this component", type ); 02075 return ( PAPI_EBUG ); 02076 } 02077 02078 int ncnt, nnev; 02079 02080 retval = pfmw_get_num_events( &nnev ); 02081 if ( retval != PAPI_OK ) 02082 return ( retval ); 02083 02084 retval = pfmw_get_num_counters( &ncnt ); 02085 if ( retval != PAPI_OK ) 02086 return ( retval ); 02087 02088 sprintf( _ia64_vector.cmp_info.support_version, 02089 "%08x", PFMLIB_VERSION ); 02090 sprintf( _ia64_vector.cmp_info.kernel_version, 02091 "%08x", 2 << 16 ); /* 2.0 */ 02092 02093 _ia64_vector.cmp_info.num_native_events = nnev; 02094 _ia64_vector.cmp_info.num_cntrs = ncnt; 02095 _ia64_vector.cmp_info.num_mpx_cntrs = ncnt; 02096 02097 _ia64_vector.cmp_info.clock_ticks = sysconf( _SC_CLK_TCK ); 02098 /* Put the signal handler in use to consume PFM_END_MSG's */ 02099 _papi_hwi_start_signal( _ia64_vector.cmp_info.hardware_intr_sig, 1, 02100 _ia64_vector.cmp_info.CmpIdx ); 02101 02102 retval = mmtimer_setup(); 02103 if ( retval ) 02104 return ( retval ); 02105 02106 retval = 02107 generate_preset_search_map( &preset_search_map, ia_preset_search_map, 02108 _ia64_vector.cmp_info.num_cntrs ); 02109 if ( retval ) 02110 return ( retval ); 02111 02112 retval = _papi_hwi_setup_all_presets( preset_search_map, NULL ); 02113 if ( retval ) 02114 return ( retval ); 02115 02116 /* get_memory_info has a CPU model argument that is not used, 02117 * faking it here with hw_info.model which is not set by this 02118 * component 02119 */ 02120 retval = _linux_get_memory_info( &_papi_hwi_system_info.hw_info, 02121 _papi_hwi_system_info.hw_info.model ); 02122 if ( retval ) 02123 return ( retval ); 02124 02125 return ( PAPI_OK ); 02126 } 02127 02128 int 02129 _ia64_init( hwd_context_t * zero ) 02130 { 02131 #if defined(USE_PROC_PTTIMER) 02132 { 02133 char buf[LINE_MAX]; 02134 int fd; 02135 sprintf( buf, "/proc/%d/task/%d/stat", getpid( ), mygettid( ) ); 02136 fd = open( buf, O_RDONLY ); 02137 if ( fd == -1 ) { 02138 PAPIERROR( "open(%s)", buf ); 02139 return ( PAPI_ESYS ); 02140 } 02141 zero->stat_fd = fd; 02142 } 02143 #endif 02144 return ( pfmw_create_context( zero ) ); 02145 } 02146 02147 /* reset the hardware counters */ 02148 int 02149 _ia64_reset( hwd_context_t * ctx, hwd_control_state_t * machdep ) 02150 { 02151 pfmw_param_t *pevt = &( machdep->evt ); 02152 pfarg_reg_t writeem[MAX_COUNTERS]; 02153 int i; 02154 02155 pfmw_stop( ctx ); 02156 memset( writeem, 0, sizeof writeem ); 02157 for ( i = 0; i < _ia64_vector.cmp_info.num_cntrs; i++ ) { 02158 /* Writing doesn't matter, we're just zeroing the counter. */ 02159 writeem[i].reg_num = PMU_FIRST_COUNTER + i; 02160 if ( PFMW_PEVT_PFPPC_REG_FLG( pevt, i ) & PFM_REGFL_OVFL_NOTIFY ) 02161 writeem[i].reg_value = machdep->pd[i].reg_long_reset; 02162 } 02163 if ( pfmw_perfmonctl 02164 ( ctx->tid, ctx->fd, PFM_WRITE_PMDS, writeem, 02165 _ia64_vector.cmp_info.num_cntrs ) == -1 ) { 02166 PAPIERROR( "perfmonctl(PFM_WRITE_PMDS) errno %d", errno ); 02167 return PAPI_ESYS; 02168 } 02169 pfmw_start( ctx ); 02170 return ( PAPI_OK ); 02171 } 02172 02173 int 02174 _ia64_start( hwd_context_t * ctx, hwd_control_state_t * current_state ) 02175 { 02176 int i; 02177 pfmw_param_t *pevt = &( current_state->evt ); 02178 02179 pfmw_stop( ctx ); 02180 02181 /* write PMCS */ 02182 if ( pfmw_perfmonctl( ctx->tid, ctx->fd, PFM_WRITE_PMCS, 02183 PFMW_PEVT_PFPPC( pevt ), 02184 PFMW_PEVT_PFPPC_COUNT( pevt ) ) == -1 ) { 02185 PAPIERROR( "perfmonctl(PFM_WRITE_PMCS) errno %d", errno ); 02186 return ( PAPI_ESYS ); 02187 } 02188 if ( pfmw_perfmonctl 02189 ( ctx->tid, ctx->fd, PFM_WRITE_PMDS, PFMW_PEVT_PFPPD( pevt ), 02190 PFMW_PEVT_EVTCOUNT( pevt ) ) == -1 ) { 02191 PAPIERROR( "perfmonctl(PFM_WRITE_PMDS) errno %d", errno ); 02192 return ( PAPI_ESYS ); 02193 } 02194 02195 /* set the initial value of the hardware counter , if PAPI_overflow or 02196 PAPI_profil are called, then the initial value is the threshold 02197 */ 02198 for ( i = 0; i < _ia64_vector.cmp_info.num_cntrs; i++ ) 02199 current_state->pd[i].reg_num = PMU_FIRST_COUNTER + i; 02200 02201 if ( pfmw_perfmonctl( ctx->tid, ctx->fd, 02202 PFM_WRITE_PMDS, current_state->pd, 02203 _ia64_vector.cmp_info.num_cntrs ) == -1 ) { 02204 PAPIERROR( "perfmonctl(WRITE_PMDS) errno %d", errno ); 02205 return ( PAPI_ESYS ); 02206 } 02207 02208 pfmw_start( ctx ); 02209 02210 return PAPI_OK; 02211 } 02212 02213 int 02214 _ia64_stop( hwd_context_t * ctx, hwd_control_state_t * zero ) 02215 { 02216 ( void ) zero; /*unused */ 02217 pfmw_stop( ctx ); 02218 return PAPI_OK; 02219 } 02220 02221 static int 02222 round_requested_ns( int ns ) 02223 { 02224 if ( ns < _papi_os_info.itimer_res_ns ) { 02225 return _papi_os_info.itimer_res_ns; 02226 } else { 02227 int leftover_ns = ns % _papi_os_info.itimer_res_ns; 02228 return ns + leftover_ns; 02229 } 02230 } 02231 02232 int 02233 _ia64_ctl( hwd_context_t * zero, int code, _papi_int_option_t * option ) 02234 { 02235 int ret; 02236 switch ( code ) { 02237 case PAPI_DEFDOM: 02238 return ( set_default_domain( option->domain.ESI->ctl_state, 02239 option->domain.domain ) ); 02240 case PAPI_DOMAIN: 02241 return ( _ia64_set_domain 02242 ( option->domain.ESI->ctl_state, option->domain.domain ) ); 02243 case PAPI_DEFGRN: 02244 return ( set_default_granularity 02245 ( option->granularity.ESI->ctl_state, 02246 option->granularity.granularity ) ); 02247 case PAPI_GRANUL: 02248 return ( set_granularity( option->granularity.ESI->ctl_state, 02249 option->granularity.granularity ) ); 02250 #if 0 02251 case PAPI_INHERIT: 02252 return ( set_inherit( option->inherit.inherit ) ); 02253 #endif 02254 case PAPI_DATA_ADDRESS: 02255 ret = 02256 set_default_domain( option->address_range.ESI->ctl_state, 02257 option->address_range.domain ); 02258 if ( ret != PAPI_OK ) 02259 return ( ret ); 02260 set_drange( zero, option->address_range.ESI->ctl_state, option ); 02261 return ( PAPI_OK ); 02262 case PAPI_INSTR_ADDRESS: 02263 ret = 02264 set_default_domain( option->address_range.ESI->ctl_state, 02265 option->address_range.domain ); 02266 if ( ret != PAPI_OK ) 02267 return ( ret ); 02268 set_irange( zero, option->address_range.ESI->ctl_state, option ); 02269 return ( PAPI_OK ); 02270 case PAPI_DEF_ITIMER:{ 02271 /* flags are currently ignored, eventually the flags will be able 02272 to specify whether or not we use POSIX itimers (clock_gettimer) */ 02273 if ( ( option->itimer.itimer_num == ITIMER_REAL ) && 02274 ( option->itimer.itimer_sig != SIGALRM ) ) 02275 return PAPI_EINVAL; 02276 if ( ( option->itimer.itimer_num == ITIMER_VIRTUAL ) && 02277 ( option->itimer.itimer_sig != SIGVTALRM ) ) 02278 return PAPI_EINVAL; 02279 if ( ( option->itimer.itimer_num == ITIMER_PROF ) && 02280 ( option->itimer.itimer_sig != SIGPROF ) ) 02281 return PAPI_EINVAL; 02282 if ( option->itimer.ns > 0 ) 02283 option->itimer.ns = round_requested_ns( option->itimer.ns ); 02284 /* At this point, we assume the user knows what he or 02285 she is doing, they maybe doing something arch specific */ 02286 return PAPI_OK; 02287 } 02288 case PAPI_DEF_MPX_NS:{ 02289 option->multiplex.ns = round_requested_ns( option->multiplex.ns ); 02290 return ( PAPI_OK ); 02291 } 02292 case PAPI_DEF_ITIMER_NS:{ 02293 option->itimer.ns = round_requested_ns( option->itimer.ns ); 02294 return ( PAPI_OK ); 02295 } 02296 default: 02297 return ( PAPI_EINVAL ); 02298 } 02299 } 02300 02301 int 02302 _ia64_shutdown( hwd_context_t * ctx ) 02303 { 02304 #if defined(USE_PROC_PTTIMER) 02305 close( ctx->stat_fd ); 02306 #endif 02307 02308 return ( pfmw_destroy_context( ctx ) ); 02309 } 02310 02311 static int 02312 ia64_ita_process_profile_buffer( ThreadInfo_t * thread, EventSetInfo_t * ESI ) 02313 { 02314 ( void ) thread; /*unused */ 02315 pfmw_smpl_hdr_t *hdr; 02316 pfmw_smpl_entry_t *ent; 02317 unsigned long buf_pos; 02318 unsigned long entry_size; 02319 int ret, reg_num, count, pos; 02320 unsigned int i, EventCode = 0, eventindex, native_index = 0; 02321 ia64_control_state_t *this_state; 02322 pfm_ita_pmd_reg_t *reg; 02323 unsigned long overflow_vector, pc; 02324 02325 02326 if ( ( ESI->state & PAPI_PROFILING ) == 0 ) 02327 return ( PAPI_EBUG ); 02328 02329 this_state = ( ia64_control_state_t * ) ( ESI->ctl_state ); 02330 hdr = ( pfmw_smpl_hdr_t * ) this_state->smpl_vaddr; 02331 02332 entry_size = sizeof ( pfmw_smpl_entry_t ); 02333 02334 /* 02335 * walk through all the entries recorded in the buffer 02336 */ 02337 buf_pos = ( unsigned long ) ( hdr + 1 ); 02338 for ( i = 0; i < hdr->hdr_count; i++ ) { 02339 ret = 0; 02340 ent = ( pfmw_smpl_entry_t * ) buf_pos; 02341 /* PFM30 only one PMD overflows in each sample */ 02342 overflow_vector = 1 << ent->ovfl_pmd; 02343 02344 SUBDBG( "Entry %d PID:%d CPU:%d ovfl_vector:0x%lx IIP:0x%016lx\n", 02345 i, ent->pid, ent->cpu, overflow_vector, ent->ip ); 02346 02347 while ( overflow_vector ) { 02348 reg_num = ffs( overflow_vector ) - 1; 02349 /* find the event code */ 02350 for ( count = 0; count < ESI->profile.event_counter; count++ ) { 02351 eventindex = ESI->profile.EventIndex[count]; 02352 pos = ESI->EventInfoArray[eventindex].pos[0]; 02353 if ( pos + PMU_FIRST_COUNTER == reg_num ) { 02354 EventCode = ESI->profile.EventCode[count]; 02355 native_index = 02356 ESI->NativeInfoArray[pos]. 02357 ni_event & PAPI_NATIVE_AND_MASK; 02358 break; 02359 } 02360 } 02361 /* something is wrong */ 02362 if ( count == ESI->profile.event_counter ) { 02363 PAPIERROR 02364 ( "wrong count: %d vs. ESI->profile.event_counter %d\n", 02365 count, ESI->profile.event_counter ); 02366 return ( PAPI_EBUG ); 02367 } 02368 02369 /* print entry header */ 02370 pc = ent->ip; 02371 if ( pfm_ita_is_dear( native_index ) ) { 02372 reg = ( pfm_ita_pmd_reg_t * ) ( ent + 1 ); 02373 reg++; 02374 reg++; 02375 pc = ( reg->pmd17_ita_reg.dear_iaddr << 4 ) | ( reg-> 02376 pmd17_ita_reg. 02377 dear_slot ); 02378 /* adjust pointer position */ 02379 buf_pos += ( hweight64( DEAR_REGS_MASK ) << 3 ); 02380 } 02381 02382 _papi_hwi_dispatch_profile( ESI, ( caddr_t ) pc, ( long long ) 0, 02383 count ); 02384 overflow_vector ^= ( unsigned long ) 1 << reg_num; 02385 } 02386 /* move to next entry */ 02387 buf_pos += entry_size; 02388 } /* end of if */ 02389 return ( PAPI_OK ); 02390 } 02391 02392 static int 02393 ia64_ita2_process_profile_buffer( ThreadInfo_t * thread, EventSetInfo_t * ESI ) 02394 { 02395 ( void ) thread; /*unused */ 02396 pfmw_smpl_hdr_t *hdr; 02397 pfmw_smpl_entry_t *ent; 02398 unsigned long buf_pos; 02399 unsigned long entry_size; 02400 int ret, reg_num, count, pos; 02401 unsigned int i, EventCode = 0, eventindex, native_index = 0; 02402 ia64_control_state_t *this_state; 02403 pfm_ita2_pmd_reg_t *reg; 02404 unsigned long overflow_vector, pc; 02405 02406 02407 if ( ( ESI->state & PAPI_PROFILING ) == 0 ) 02408 return ( PAPI_EBUG ); 02409 02410 this_state = ( ia64_control_state_t * ) ( ESI->ctl_state ); 02411 hdr = ( pfmw_smpl_hdr_t * ) ( this_state->smpl_vaddr ); 02412 02413 entry_size = sizeof ( pfmw_smpl_entry_t ); 02414 02415 /* 02416 * walk through all the entries recorded in the buffer 02417 */ 02418 buf_pos = ( unsigned long ) ( hdr + 1 ); 02419 for ( i = 0; i < hdr->hdr_count; i++ ) { 02420 ret = 0; 02421 ent = ( pfmw_smpl_entry_t * ) buf_pos; 02422 /* PFM30 only one PMD overflows in each sample */ 02423 overflow_vector = 1 << ent->ovfl_pmd; 02424 02425 SUBDBG( "Entry %d PID:%d CPU:%d ovfl_vector:0x%lx IIP:0x%016lx\n", 02426 i, ent->pid, ent->cpu, overflow_vector, ent->ip ); 02427 02428 while ( overflow_vector ) { 02429 reg_num = ffs( overflow_vector ) - 1; 02430 /* find the event code */ 02431 for ( count = 0; count < ESI->profile.event_counter; count++ ) { 02432 eventindex = ESI->profile.EventIndex[count]; 02433 pos = ESI->EventInfoArray[eventindex].pos[0]; 02434 if ( pos + PMU_FIRST_COUNTER == reg_num ) { 02435 EventCode = ESI->profile.EventCode[count]; 02436 native_index = 02437 ESI->NativeInfoArray[pos]. 02438 ni_event & PAPI_NATIVE_AND_MASK; 02439 break; 02440 } 02441 } 02442 /* something is wrong */ 02443 if ( count == ESI->profile.event_counter ) { 02444 PAPIERROR 02445 ( "wrong count: %d vs. ESI->profile.event_counter %d\n", 02446 count, ESI->profile.event_counter ); 02447 return ( PAPI_EBUG ); 02448 } 02449 02450 /* print entry header */ 02451 pc = ent->ip; 02452 if ( pfm_ita2_is_dear( native_index ) ) { 02453 reg = ( pfm_ita2_pmd_reg_t * ) ( ent + 1 ); 02454 reg++; 02455 reg++; 02456 pc = ( ( reg->pmd17_ita2_reg.dear_iaddr + 02457 reg->pmd17_ita2_reg.dear_bn ) << 4 ) 02458 | reg->pmd17_ita2_reg.dear_slot; 02459 02460 /* adjust pointer position */ 02461 buf_pos += ( hweight64( DEAR_REGS_MASK ) << 3 ); 02462 } 02463 02464 _papi_hwi_dispatch_profile( ESI, ( caddr_t ) pc, ( long long ) 0, 02465 count ); 02466 overflow_vector ^= ( unsigned long ) 1 << reg_num; 02467 } 02468 /* move to next entry */ 02469 buf_pos += entry_size; 02470 } /* end of if */ 02471 return ( PAPI_OK ); 02472 } 02473 02474 static int 02475 ia64_mont_process_profile_buffer( ThreadInfo_t * thread, EventSetInfo_t * ESI ) 02476 { 02477 ( void ) thread; /*unused */ 02478 pfmw_smpl_hdr_t *hdr; 02479 pfmw_smpl_entry_t *ent; 02480 unsigned long buf_pos; 02481 unsigned long entry_size; 02482 int ret, reg_num, count, pos; 02483 unsigned int i, EventCode = 0, eventindex, native_index = 0; 02484 ia64_control_state_t *this_state; 02485 pfm_mont_pmd_reg_t *reg; 02486 unsigned long overflow_vector, pc; 02487 unsigned int umask; 02488 02489 02490 if ( ( ESI->state & PAPI_PROFILING ) == 0 ) 02491 return ( PAPI_EBUG ); 02492 02493 this_state = ( ia64_control_state_t * ) ESI->ctl_state; 02494 hdr = ( pfmw_smpl_hdr_t * ) this_state->smpl_vaddr; 02495 02496 entry_size = sizeof ( pfmw_smpl_entry_t ); 02497 02498 /* 02499 * walk through all the entries recorded in the buffer 02500 */ 02501 buf_pos = ( unsigned long ) ( hdr + 1 ); 02502 for ( i = 0; i < hdr->hdr_count; i++ ) { 02503 ret = 0; 02504 ent = ( pfmw_smpl_entry_t * ) buf_pos; 02505 /* PFM30 only one PMD overflows in each sample */ 02506 overflow_vector = 1 << ent->ovfl_pmd; 02507 02508 SUBDBG( "Entry %d PID:%d CPU:%d ovfl_vector:0x%lx IIP:0x%016lx\n", 02509 i, ent->pid, ent->cpu, overflow_vector, ent->ip ); 02510 02511 while ( overflow_vector ) { 02512 reg_num = ffs( overflow_vector ) - 1; 02513 /* find the event code */ 02514 for ( count = 0; count < ESI->profile.event_counter; count++ ) { 02515 eventindex = ESI->profile.EventIndex[count]; 02516 pos = ESI->EventInfoArray[eventindex].pos[0]; 02517 if ( pos + PMU_FIRST_COUNTER == reg_num ) { 02518 EventCode = ESI->profile.EventCode[count]; 02519 if ( _pfm_decode_native_event 02520 ( ESI->NativeInfoArray[pos].ni_event, &native_index, 02521 &umask ) != PAPI_OK ) 02522 return ( PAPI_ENOEVNT ); 02523 break; 02524 } 02525 } 02526 /* something is wrong */ 02527 if ( count == ESI->profile.event_counter ) { 02528 PAPIERROR 02529 ( "wrong count: %d vs. ESI->profile.event_counter %d\n", 02530 count, ESI->profile.event_counter ); 02531 return ( PAPI_EBUG ); 02532 } 02533 02534 /* print entry header */ 02535 pc = ent->ip; 02536 if ( pfm_mont_is_dear( native_index ) ) { 02537 reg = ( pfm_mont_pmd_reg_t * ) ( ent + 1 ); 02538 reg++; 02539 reg++; 02540 pc = ( ( reg->pmd36_mont_reg.dear_iaddr + 02541 reg->pmd36_mont_reg.dear_bn ) << 4 ) 02542 | reg->pmd36_mont_reg.dear_slot; 02543 /* adjust pointer position */ 02544 buf_pos += ( hweight64( DEAR_REGS_MASK ) << 3 ); 02545 } 02546 02547 _papi_hwi_dispatch_profile( ESI, ( caddr_t ) pc, ( long long ) 0, 02548 count ); 02549 overflow_vector ^= ( unsigned long ) 1 << reg_num; 02550 } 02551 /* move to next entry */ 02552 buf_pos += entry_size; 02553 } /* end of if */ 02554 return ( PAPI_OK ); 02555 } 02556 02557 static int 02558 ia64_process_profile_buffer( ThreadInfo_t * thread, EventSetInfo_t * ESI ) 02559 { 02560 switch ( _perfmon2_pfm_pmu_type ) { 02561 case PFMLIB_ITANIUM_PMU: 02562 return ( ia64_ita_process_profile_buffer( thread, ESI ) ); 02563 break; 02564 case PFMLIB_ITANIUM2_PMU: 02565 return ( ia64_ita2_process_profile_buffer( thread, ESI ) ); 02566 break; 02567 case PFMLIB_MONTECITO_PMU: 02568 return ( ia64_mont_process_profile_buffer( thread, ESI ) ); 02569 break; 02570 default: 02571 PAPIERROR( "PMU type %d is not supported by this component", 02572 _perfmon2_pfm_pmu_type ); 02573 return ( PAPI_EBUG ); 02574 } 02575 } 02576 02577 static void 02578 ia64_dispatch_sigprof( int n, hwd_siginfo_t * info, hwd_ucontext_t *sc ) 02579 { 02580 ( void ) n; /*unused */ 02581 _papi_hwi_context_t ctx; 02582 ThreadInfo_t *thread = _papi_hwi_lookup_thread( 0 ); 02583 caddr_t address; 02584 int cidx = _ia64_vector.cmp_info.CmpIdx; 02585 02586 #if defined(DEBUG) 02587 if ( thread == NULL ) { 02588 PAPIERROR( "thread == NULL in _papi_hwd_dispatch_timer!" ); 02589 return; 02590 } 02591 #endif 02592 02593 ctx.si = info; 02594 ctx.ucontext = sc; 02595 address = GET_OVERFLOW_ADDRESS( ( ctx ) ); 02596 02597 if ( ( thread == NULL ) || ( thread->running_eventset[cidx] == NULL ) ) { 02598 SUBDBG( "%p, %p\n", thread, thread->running_eventset[cidx] ); 02599 return; 02600 } 02601 02602 if ( thread->running_eventset[cidx]->overflow. 02603 flags & PAPI_OVERFLOW_FORCE_SW ) { 02604 _papi_hwi_dispatch_overflow_signal( ( void * ) &ctx, address, NULL, 0, 02605 0, &thread, cidx ); 02606 return; 02607 } 02608 02609 pfm_msg_t msg; 02610 int ret, fd; 02611 fd = info->si_fd; 02612 retry: 02613 ret = read( fd, &msg, sizeof ( msg ) ); 02614 if ( ret == -1 ) { 02615 if ( errno == EINTR ) { 02616 SUBDBG( "read(%d) interrupted, retrying\n", fd ); 02617 goto retry; 02618 } else { 02619 PAPIERROR( "read(%d): errno %d", fd, errno ); 02620 } 02621 } else if ( ret != sizeof ( msg ) ) { 02622 PAPIERROR( "read(%d): short %d vs. %d bytes", fd, ret, sizeof ( msg ) ); 02623 ret = -1; 02624 } 02625 #if defined(HAVE_PFM_MSG_TYPE) 02626 if ( msg.type == PFM_MSG_END ) { 02627 SUBDBG( "PFM_MSG_END\n" ); 02628 return; 02629 } 02630 if ( msg.type != PFM_MSG_OVFL ) { 02631 PAPIERROR( "unexpected msg type %d", msg.type ); 02632 return; 02633 } 02634 #else 02635 if ( msg.pfm_gen_msg.msg_type == PFM_MSG_END ) { 02636 SUBDBG( "PFM_MSG_END\n" ); 02637 return; 02638 } 02639 if ( msg.pfm_gen_msg.msg_type != PFM_MSG_OVFL ) { 02640 PAPIERROR( "unexpected msg type %d", msg.pfm_gen_msg.msg_type ); 02641 return; 02642 } 02643 #endif 02644 if ( ret != -1 ) { 02645 if ( ( thread->running_eventset[cidx]->state & PAPI_PROFILING ) && 02646 !( thread->running_eventset[cidx]->profile. 02647 flags & PAPI_PROFIL_FORCE_SW ) ) 02648 ia64_process_profile_buffer( thread, 02649 thread->running_eventset[cidx] ); 02650 else 02651 _papi_hwi_dispatch_overflow_signal( ( void * ) &ctx, address, 02652 NULL, 02653 msg.pfm_ovfl_msg. 02654 msg_ovfl_pmds[0] >> 02655 PMU_FIRST_COUNTER, 0, 02656 &thread, cidx ); 02657 } 02658 if ( pfmw_perfmonctl( 0, fd, PFM_RESTART, 0, 0 ) == -1 ) { 02659 PAPIERROR( "perfmonctl(PFM_RESTART) errno %d, %s", errno, 02660 strerror( errno ) ); 02661 return; 02662 } 02663 } 02664 02665 void 02666 _ia64_dispatch_timer( int signal, hwd_siginfo_t * info, void *context ) 02667 { 02668 ia64_dispatch_sigprof( signal, info, context ); 02669 } 02670 02671 static int 02672 set_notify( EventSetInfo_t * ESI, int index, int value ) 02673 { 02674 int *pos, count, i; 02675 unsigned int hwcntr; 02676 pfmw_param_t *pevt = 02677 &( ( ( ia64_control_state_t * ) ESI->ctl_state )->evt ); 02678 02679 pos = ESI->EventInfoArray[index].pos; 02680 count = 0; 02681 while ( pos[count] != -1 && count < _ia64_vector.cmp_info.num_cntrs ) { 02682 hwcntr = pos[count] + PMU_FIRST_COUNTER; 02683 for ( i = 0; i < _ia64_vector.cmp_info.num_cntrs; i++ ) { 02684 if ( PFMW_PEVT_PFPPC_REG_NUM( pevt, i ) == hwcntr ) { 02685 SUBDBG( "Found hw counter %d in %d, flags %d\n", hwcntr, i, 02686 value ); 02687 PFMW_PEVT_PFPPC_REG_FLG( pevt, i ) = value; 02688 /* 02689 #ifdef PFM30 02690 if (value) 02691 pevt->pc[i].reg_reset_pmds[0] = 1UL << pevt->pc[i].reg_num; 02692 else 02693 pevt->pc[i].reg_reset_pmds[0] = 0; 02694 #endif 02695 */ 02696 break; 02697 } 02698 } 02699 count++; 02700 } 02701 return ( PAPI_OK ); 02702 } 02703 02704 int 02705 _ia64_stop_profiling( ThreadInfo_t * thread, EventSetInfo_t * ESI ) 02706 { 02707 int cidx = _ia64_vector.cmp_info.CmpIdx; 02708 02709 pfmw_stop( thread->context[cidx] ); 02710 return ( ia64_process_profile_buffer( thread, ESI ) ); 02711 } 02712 02713 02714 int 02715 _ia64_set_profile( EventSetInfo_t * ESI, int EventIndex, int threshold ) 02716 { 02717 int cidx = _ia64_vector.cmp_info.CmpIdx; 02718 hwd_control_state_t *this_state = ESI->ctl_state; 02719 hwd_context_t *ctx = ESI->master->context[cidx]; 02720 int ret; 02721 02722 ret = _ia64_vector.set_overflow( ESI, EventIndex, threshold ); 02723 if ( ret != PAPI_OK ) 02724 return ret; 02725 ret = pfmw_destroy_context( ctx ); 02726 if ( ret != PAPI_OK ) 02727 return ret; 02728 if ( threshold == 0 ) 02729 ret = pfmw_create_context( ctx ); 02730 else 02731 ret = 02732 pfmw_recreate_context( ESI, ctx, &this_state->smpl_vaddr, 02733 EventIndex ); 02734 02735 //#warning "This should be handled in the high level layers" 02736 ESI->state ^= PAPI_OVERFLOWING; 02737 ESI->overflow.flags ^= PAPI_OVERFLOW_HARDWARE; 02738 02739 return ( ret ); 02740 } 02741 02742 int 02743 _ia64_set_overflow( EventSetInfo_t * ESI, int EventIndex, int threshold ) 02744 { 02745 hwd_control_state_t *this_state = ESI->ctl_state; 02746 int j, retval = PAPI_OK, *pos; 02747 int cidx = _ia64_vector.cmp_info.CmpIdx; 02748 02749 pos = ESI->EventInfoArray[EventIndex].pos; 02750 j = pos[0]; 02751 SUBDBG( "Hardware counter %d used in overflow, threshold %d\n", j, 02752 threshold ); 02753 02754 if ( threshold == 0 ) { 02755 /* Remove the signal handler */ 02756 02757 retval = _papi_hwi_stop_signal( _ia64_vector.cmp_info.hardware_intr_sig ); 02758 if ( retval != PAPI_OK ) 02759 return ( retval ); 02760 02761 /* Remove the overflow notifier on the proper event. */ 02762 02763 set_notify( ESI, EventIndex, 0 ); 02764 02765 this_state->pd[j].reg_value = 0; 02766 this_state->pd[j].reg_long_reset = 0; 02767 this_state->pd[j].reg_short_reset = 0; 02768 } else { 02769 retval = 02770 _papi_hwi_start_signal( _ia64_vector.cmp_info.hardware_intr_sig, 1, 02771 cidx ); 02772 if ( retval != PAPI_OK ) 02773 return ( retval ); 02774 02775 /* Set the overflow notifier on the proper event. Remember that selector */ 02776 02777 set_notify( ESI, EventIndex, PFM_REGFL_OVFL_NOTIFY ); 02778 02779 this_state->pd[j].reg_value = 02780 ( ~0UL ) - ( unsigned long ) threshold + 1; 02781 this_state->pd[j].reg_short_reset = 02782 ( ~0UL ) - ( unsigned long ) threshold + 1; 02783 this_state->pd[j].reg_long_reset = 02784 ( ~0UL ) - ( unsigned long ) threshold + 1; 02785 02786 } 02787 return ( retval ); 02788 } 02789 02790 int 02791 _ia64_ntv_code_to_name( unsigned int EventCode, char *ntv_name, int len ) 02792 { 02793 if ( _perfmon2_pfm_pmu_type == PFMLIB_MONTECITO_PMU ) 02794 return ( _papi_pfm_ntv_code_to_name( EventCode, ntv_name, len ) ); 02795 else { 02796 char name[PAPI_MAX_STR_LEN]; 02797 int ret = 0; 02798 02799 pfmw_get_event_name( name, EventCode ^ PAPI_NATIVE_MASK ); 02800 02801 if ( ret != PAPI_OK ) 02802 return ( PAPI_ENOEVNT ); 02803 02804 strncpy( ntv_name, name, len ); 02805 return ( PAPI_OK ); 02806 } 02807 } 02808 02809 int 02810 _ia64_ntv_code_to_descr( unsigned int EventCode, char *ntv_descr, int len ) 02811 { 02812 if ( _perfmon2_pfm_pmu_type == PFMLIB_MONTECITO_PMU ) 02813 return ( _papi_pfm_ntv_code_to_descr( EventCode, ntv_descr, len ) ); 02814 else { 02815 #if defined(HAVE_PFM_GET_EVENT_DESCRIPTION) 02816 pfmw_get_event_description( EventCode ^ PAPI_NATIVE_MASK, ntv_descr, 02817 len ); 02818 return ( PAPI_OK ); 02819 #else 02820 return ( _ia64_ntv_code_to_name( EventCode, ntv_descr, len ) ); 02821 #endif 02822 } 02823 } 02824 02825 static int 02826 _ia64_modify_event( unsigned int event, int modifier ) 02827 { 02828 switch ( modifier ) { 02829 case PAPI_NTV_ENUM_IARR: 02830 return ( pfmw_support_iarr( event ) ); 02831 case PAPI_NTV_ENUM_DARR: 02832 return ( pfmw_support_darr( event ) ); 02833 case PAPI_NTV_ENUM_OPCM: 02834 return ( pfmw_support_opcm( event ) ); 02835 case PAPI_NTV_ENUM_DEAR: 02836 return ( pfmw_is_dear( event ) ); 02837 case PAPI_NTV_ENUM_IEAR: 02838 return ( pfmw_is_iear( event ) ); 02839 default: 02840 return ( 1 ); 02841 } 02842 } 02843 02844 int 02845 _ia64_ntv_enum_events( unsigned int *EventCode, int modifier ) 02846 { 02847 if ( _perfmon2_pfm_pmu_type == PFMLIB_MONTECITO_PMU ) 02848 return ( _papi_pfm_ntv_enum_events( EventCode, modifier ) ); 02849 else { 02850 int index = *EventCode & PAPI_NATIVE_AND_MASK; 02851 02852 if ( modifier == PAPI_ENUM_FIRST ) { 02853 *EventCode = PAPI_NATIVE_MASK; 02854 return ( PAPI_OK ); 02855 } 02856 02857 while ( index++ < _ia64_vector.cmp_info.num_native_events - 1 ) { 02858 *EventCode += 1; 02859 if ( _ia64_modify_event 02860 ( ( *EventCode ^ PAPI_NATIVE_MASK ), modifier ) ) 02861 return ( PAPI_OK ); 02862 } 02863 return ( PAPI_ENOEVNT ); 02864 } 02865 } 02866 02867 int 02868 _ia64_ita_init_control_state( hwd_control_state_t * this_state ) 02869 { 02870 pfmw_param_t *evt; 02871 pfmw_ita1_param_t *param; 02872 ia64_control_state_t *ptr; 02873 02874 ptr = ( ia64_control_state_t * ) this_state; 02875 evt = &( ptr->evt ); 02876 02877 param = &( ptr->ita_lib_param.ita_param ); 02878 memset( evt, 0, sizeof ( pfmw_param_t ) ); 02879 memset( param, 0, sizeof ( pfmw_ita1_param_t ) ); 02880 02881 _ia64_ita_set_domain( this_state, _ia64_vector.cmp_info.default_domain ); 02882 /* set library parameter pointer */ 02883 02884 return ( PAPI_OK ); 02885 } 02886 02887 int 02888 _ia64_ita2_init_control_state( hwd_control_state_t * this_state ) 02889 { 02890 pfmw_param_t *evt; 02891 pfmw_ita2_param_t *param; 02892 ia64_control_state_t *ptr; 02893 02894 ptr = ( ia64_control_state_t * ) this_state; 02895 evt = &( ptr->evt ); 02896 02897 param = &( ptr->ita_lib_param.ita2_param ); 02898 memset( evt, 0, sizeof ( pfmw_param_t ) ); 02899 memset( param, 0, sizeof ( pfmw_ita2_param_t ) ); 02900 02901 _ia64_ita2_set_domain( this_state, _ia64_vector.cmp_info.default_domain ); 02902 /* set library parameter pointer */ 02903 evt->mod_inp = &( param->ita2_input_param ); 02904 evt->mod_outp = &( param->ita2_output_param ); 02905 02906 return ( PAPI_OK ); 02907 } 02908 02909 int 02910 _ia64_mont_init_control_state( hwd_control_state_t * this_state ) 02911 { 02912 pfmw_param_t *evt; 02913 pfmw_mont_param_t *param; 02914 ia64_control_state_t *ptr; 02915 02916 ptr = ( ia64_control_state_t * ) this_state; 02917 evt = &( ptr->evt ); 02918 02919 param = &( ptr->ita_lib_param.mont_param ); 02920 memset( evt, 0, sizeof ( pfmw_param_t ) ); 02921 memset( param, 0, sizeof ( pfmw_mont_param_t ) ); 02922 02923 _ia64_mont_set_domain( this_state, _ia64_vector.cmp_info.default_domain ); 02924 /* set library parameter pointer */ 02925 evt->mod_inp = &( param->mont_input_param ); 02926 evt->mod_outp = &( param->mont_output_param ); 02927 02928 return ( PAPI_OK ); 02929 } 02930 02931 int 02932 _ia64_init_control_state( hwd_control_state_t * this_state ) 02933 { 02934 switch ( _perfmon2_pfm_pmu_type ) { 02935 case PFMLIB_ITANIUM_PMU: 02936 return ( _ia64_ita_init_control_state( this_state ) ); 02937 break; 02938 case PFMLIB_ITANIUM2_PMU: 02939 return ( _ia64_ita2_init_control_state( this_state ) ); 02940 break; 02941 case PFMLIB_MONTECITO_PMU: 02942 return ( _ia64_mont_init_control_state( this_state ) ); 02943 break; 02944 default: 02945 PAPIERROR( "PMU type %d is not supported by this component", 02946 _perfmon2_pfm_pmu_type ); 02947 return ( PAPI_EBUG ); 02948 } 02949 } 02950 02951 void 02952 _ia64_remove_native( hwd_control_state_t * this_state, 02953 NativeInfo_t * nativeInfo ) 02954 { 02955 ( void ) this_state; /*unused */ 02956 ( void ) nativeInfo; /*unused */ 02957 return; 02958 } 02959 02960 int 02961 _ia64_mont_update_control_state( hwd_control_state_t * this_state, 02962 NativeInfo_t * native, int count, 02963 hwd_context_t * zero ) 02964 { 02965 ( void ) zero; /*unused */ 02966 int org_cnt; 02967 pfmw_param_t *evt = &this_state->evt; 02968 pfmw_param_t copy_evt; 02969 unsigned int i, j, event, umask, EventCode; 02970 pfmlib_event_t gete; 02971 char name[128]; 02972 02973 if ( count == 0 ) { 02974 for ( i = 0; i < ( unsigned int ) _ia64_vector.cmp_info.num_cntrs; i++ ) 02975 PFMW_PEVT_EVENT( evt, i ) = 0; 02976 PFMW_PEVT_EVTCOUNT( evt ) = 0; 02977 memset( PFMW_PEVT_PFPPC( evt ), 0, sizeof ( PFMW_PEVT_PFPPC( evt ) ) ); 02978 memset( &evt->inp.pfp_unavail_pmcs, 0, sizeof ( pfmlib_regmask_t ) ); 02979 return ( PAPI_OK ); 02980 } 02981 02982 /* save the old data */ 02983 org_cnt = PFMW_PEVT_EVTCOUNT( evt ); 02984 02985 memcpy( ©_evt, evt, sizeof ( pfmw_param_t ) ); 02986 02987 for ( i = 0; i < ( unsigned int ) _ia64_vector.cmp_info.num_cntrs; i++ ) 02988 PFMW_PEVT_EVENT( evt, i ) = 0; 02989 PFMW_PEVT_EVTCOUNT( evt ) = 0; 02990 memset( PFMW_PEVT_PFPPC( evt ), 0, sizeof ( PFMW_PEVT_PFPPC( evt ) ) ); 02991 memset( &evt->inp.pfp_unavail_pmcs, 0, sizeof ( pfmlib_regmask_t ) ); 02992 02993 SUBDBG( " original count is %d\n", org_cnt ); 02994 02995 /* add new native events to the evt structure */ 02996 for ( i = 0; i < ( unsigned int ) count; i++ ) { 02997 memset( &gete, 0, sizeof ( gete ) ); 02998 EventCode = native[i].ni_event; 02999 _papi_pfm_ntv_code_to_name( EventCode, name, 128 ); 03000 if ( _pfm_decode_native_event( EventCode, &event, &umask ) != PAPI_OK ) 03001 return ( PAPI_ENOEVNT ); 03002 03003 SUBDBG( " evtcode=0x%x evtindex=%d name: %s\n", EventCode, event, 03004 name ); 03005 03006 PFMW_PEVT_EVENT( evt, i ) = event; 03007 evt->inp.pfp_events[i].num_masks = 0; 03008 gete.event = event; 03009 gete.num_masks = prepare_umask( umask, gete.unit_masks ); 03010 if ( gete.num_masks ) { 03011 evt->inp.pfp_events[i].num_masks = gete.num_masks; 03012 for ( j = 0; j < gete.num_masks; j++ ) 03013 evt->inp.pfp_events[i].unit_masks[j] = gete.unit_masks[j]; 03014 } 03015 } 03016 PFMW_PEVT_EVTCOUNT( evt ) = count; 03017 /* Recalcuate the pfmlib_param_t structure, may also signal conflict */ 03018 if ( pfmw_dispatch_events( evt ) ) { 03019 SUBDBG( "pfmw_dispatch_events fail\n" ); 03020 /* recover the old data */ 03021 PFMW_PEVT_EVTCOUNT( evt ) = org_cnt; 03022 /*for (i = 0; i < _ia64_vector.cmp_info.num_cntrs; i++) 03023 PFMW_PEVT_EVENT(evt,i) = events[i]; 03024 */ 03025 memcpy( evt, ©_evt, sizeof ( pfmw_param_t ) ); 03026 return ( PAPI_ECNFLCT ); 03027 } 03028 SUBDBG( "event_count=%d\n", PFMW_PEVT_EVTCOUNT( evt ) ); 03029 03030 for ( i = 0; i < PFMW_PEVT_EVTCOUNT( evt ); i++ ) { 03031 native[i].ni_position = PFMW_PEVT_PFPPC_REG_NUM( evt, i ) 03032 - PMU_FIRST_COUNTER; 03033 SUBDBG( "event_code is %d, reg_num is %d\n", 03034 native[i].ni_event & PAPI_NATIVE_AND_MASK, 03035 native[i].ni_position ); 03036 } 03037 03038 return ( PAPI_OK ); 03039 } 03040 03041 int 03042 _ia64_ita_update_control_state( hwd_control_state_t * this_state, 03043 NativeInfo_t * native, int count, 03044 hwd_context_t * zero ) 03045 { 03046 ( void ) zero; /*unused */ 03047 int index, org_cnt; 03048 unsigned int i; 03049 pfmw_param_t *evt = &this_state->evt; 03050 pfmw_param_t copy_evt; 03051 03052 if ( count == 0 ) { 03053 for ( i = 0; i < ( unsigned int ) _ia64_vector.cmp_info.num_cntrs; i++ ) 03054 PFMW_PEVT_EVENT( evt, i ) = 0; 03055 PFMW_PEVT_EVTCOUNT( evt ) = 0; 03056 memset( PFMW_PEVT_PFPPC( evt ), 0, sizeof ( PFMW_PEVT_PFPPC( evt ) ) ); 03057 memset( &evt->inp.pfp_unavail_pmcs, 0, sizeof ( pfmlib_regmask_t ) ); 03058 return ( PAPI_OK ); 03059 } 03060 03061 /* save the old data */ 03062 org_cnt = PFMW_PEVT_EVTCOUNT( evt ); 03063 03064 memcpy( ©_evt, evt, sizeof ( pfmw_param_t ) ); 03065 for ( i = 0; i < ( unsigned int ) _ia64_vector.cmp_info.num_cntrs; i++ ) 03066 PFMW_PEVT_EVENT( evt, i ) = 0; 03067 PFMW_PEVT_EVTCOUNT( evt ) = 0; 03068 memset( PFMW_PEVT_PFPPC( evt ), 0, sizeof ( PFMW_PEVT_PFPPC( evt ) ) ); 03069 memset( &evt->inp.pfp_unavail_pmcs, 0, sizeof ( pfmlib_regmask_t ) ); 03070 03071 SUBDBG( " original count is %d\n", org_cnt ); 03072 03073 /* add new native events to the evt structure */ 03074 for ( i = 0; i < ( unsigned int ) count; i++ ) { 03075 index = native[i].ni_event & PAPI_NATIVE_AND_MASK; 03076 PFMW_PEVT_EVENT( evt, i ) = index; 03077 } 03078 PFMW_PEVT_EVTCOUNT( evt ) = count; 03079 /* Recalcuate the pfmlib_param_t structure, may also signal conflict */ 03080 if ( pfmw_dispatch_events( evt ) ) { 03081 SUBDBG( "pfmw_dispatch_events fail\n" ); 03082 /* recover the old data */ 03083 PFMW_PEVT_EVTCOUNT( evt ) = org_cnt; 03084 /*for (i = 0; i < _ia64_vector.cmp_info.num_cntrs; i++) 03085 PFMW_PEVT_EVENT(evt,i) = events[i]; 03086 */ 03087 memcpy( evt, ©_evt, sizeof ( pfmw_param_t ) ); 03088 return ( PAPI_ECNFLCT ); 03089 } 03090 SUBDBG( "event_count=%d\n", PFMW_PEVT_EVTCOUNT( evt ) ); 03091 03092 for ( i = 0; i < PFMW_PEVT_EVTCOUNT( evt ); i++ ) { 03093 native[i].ni_position = PFMW_PEVT_PFPPC_REG_NUM( evt, i ) 03094 - PMU_FIRST_COUNTER; 03095 SUBDBG( "event_code is %d, reg_num is %d\n", 03096 native[i].ni_event & PAPI_NATIVE_AND_MASK, 03097 native[i].ni_position ); 03098 } 03099 03100 return ( PAPI_OK ); 03101 } 03102 03103 int 03104 _ia64_update_control_state( hwd_control_state_t * this_state, 03105 NativeInfo_t * native, int count, 03106 hwd_context_t * zero ) 03107 { 03108 switch ( _perfmon2_pfm_pmu_type ) { 03109 case PFMLIB_ITANIUM_PMU: 03110 return ( _ia64_ita_update_control_state 03111 ( this_state, native, count, zero ) ); 03112 break; 03113 case PFMLIB_ITANIUM2_PMU: 03114 return ( _ia64_ita_update_control_state 03115 ( this_state, native, count, zero ) ); 03116 break; 03117 case PFMLIB_MONTECITO_PMU: 03118 return ( _ia64_mont_update_control_state 03119 ( this_state, native, count, zero ) ); 03120 break; 03121 default: 03122 PAPIERROR( "PMU type %d is not supported by this component", 03123 _perfmon2_pfm_pmu_type ); 03124 return ( PAPI_EBUG ); 03125 } 03126 } 03127 03128 papi_vector_t _ia64_vector = { 03129 .cmp_info = { 03130 .name = "perfmon-ia64.c", 03131 .version = "5.0", 03132 03133 /* default component information (unspecified values initialized to 0) */ 03134 .default_domain = PAPI_DOM_USER, 03135 .available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL, 03136 .default_granularity = PAPI_GRN_THR, 03137 .available_granularities = PAPI_GRN_THR, 03138 .hardware_intr_sig = PAPI_INT_SIGNAL, 03139 .hardware_intr = 1, 03140 /* component specific cmp_info initializations */ 03141 .fast_real_timer = 1, 03142 .fast_virtual_timer = 0, 03143 .attach = 0, 03144 .attach_must_ptrace = 0, 03145 .kernel_profile = 1, 03146 .cntr_umasks = 1; 03147 }, 03148 03149 /* sizes of framework-opaque component-private structures */ 03150 .size = { 03151 .context = sizeof ( ia64_context_t ), 03152 .control_state = sizeof ( ia64_control_state_t ), 03153 .reg_value = sizeof ( ia64_register_t ), 03154 .reg_alloc = sizeof ( ia64_reg_alloc_t ), 03155 } 03156 , 03157 03158 /* function pointers in this component */ 03159 .init_control_state = _ia64_init_control_state, 03160 .start = _ia64_start, 03161 .stop = _ia64_stop, 03162 .read = _ia64_read, 03163 .shutdown_thread = _ia64_shutdown, 03164 .ctl = _ia64_ctl, 03165 .update_control_state = _ia64_update_control_state, 03166 .set_domain = _ia64_set_domain, 03167 .reset = _ia64_reset, 03168 .set_overflow = _ia64_set_overflow, 03169 .set_profile = _ia64_set_profile, 03170 .stop_profiling = _ia64_stop_profiling, 03171 .init_component = _ia64_init_component, 03172 .dispatch_timer = _ia64_dispatch_timer, 03173 .init_thread = _ia64_init, 03174 03175 .ntv_enum_events = _ia64_ntv_enum_events, 03176 .ntv_code_to_name = _ia64_ntv_code_to_name, 03177 .ntv_code_to_descr = _ia64_ntv_code_to_descr, 03178 03179 };