PAPI  5.0.1.0
perfmon-ia64.c
Go to the documentation of this file.
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( &copy_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, &copy_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( &copy_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, &copy_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 };
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines