static int hipe_perfctr_open(unsigned int user) { struct perfctr_info info; if (!vperfctr) { vperfctr = vperfctr_open(); if (!vperfctr) return -1; if (vperfctr_info(vperfctr, &info) >= 0) { tsc_to_ms = (double)(info.tsc_to_cpu_mult ? : 1) / (double)info.cpu_khz; have_rdtsc = (info.cpu_features & PERFCTR_FEATURE_RDTSC) ? 1 : 0; }
int _perfctr_init_component( int cidx ) { int retval; struct perfctr_info info; char abiv[PAPI_MIN_STR_LEN]; #if defined(PERFCTR26) int fd; #else struct vperfctr *dev; #endif #if defined(PERFCTR26) /* Get info from the kernel */ /* Use lower level calls per Mikael to get the perfctr info without actually creating a new kernel-side state. Also, close the fd immediately after retrieving the info. This is much lighter weight and doesn't reserve the counter resources. Also compatible with perfctr 2.6.14. */ fd = _vperfctr_open( 0 ); if ( fd < 0 ) { strncpy(_perfctr_vector.cmp_info.disabled_reason, VOPEN_ERROR,PAPI_MAX_STR_LEN); return PAPI_ESYS; } retval = perfctr_info( fd, &info ); close( fd ); if ( retval < 0 ) { strncpy(_perfctr_vector.cmp_info.disabled_reason, VINFO_ERROR,PAPI_MAX_STR_LEN); return PAPI_ESYS; } /* copy tsc multiplier to local variable */ /* this field appears in perfctr 2.6 and higher */ tb_scale_factor = ( long long ) info.tsc_to_cpu_mult; #else /* Opened once for all threads. */ if ( ( dev = vperfctr_open( ) ) == NULL ) { strncpy(_perfctr_vector.cmp_info.disabled_reason, VOPEN_ERROR,PAPI_MAX_STR_LEN); return PAPI_ESYS; } SUBDBG( "_perfctr_init_component vperfctr_open = %p\n", dev ); /* Get info from the kernel */ retval = vperfctr_info( dev, &info ); if ( retval < 0 ) { strncpy(_perfctr_vector.cmp_info.disabled_reason, VINFO_ERROR,PAPI_MAX_STR_LEN); return ( PAPI_ESYS ); } vperfctr_close( dev ); #endif /* Fill in what we can of the papi_system_info. */ retval = _papi_os_vector.get_system_info( &_papi_hwi_system_info ); if ( retval != PAPI_OK ) return ( retval ); /* Setup memory info */ retval = _papi_os_vector.get_memory_info( &_papi_hwi_system_info.hw_info, ( int ) info.cpu_type ); if ( retval ) return ( retval ); strcpy( _perfctr_vector.cmp_info.name,"perfctr.c" ); strcpy( _perfctr_vector.cmp_info.version, "$Revision$" ); sprintf( abiv, "0x%08X", info.abi_version ); strcpy( _perfctr_vector.cmp_info.support_version, abiv ); strcpy( _perfctr_vector.cmp_info.kernel_version, info.driver_version ); _perfctr_vector.cmp_info.CmpIdx = cidx; _perfctr_vector.cmp_info.num_cntrs = ( int ) PERFCTR_CPU_NRCTRS( &info ); _perfctr_vector.cmp_info.num_mpx_cntrs=_perfctr_vector.cmp_info.num_cntrs; if ( info.cpu_features & PERFCTR_FEATURE_RDPMC ) _perfctr_vector.cmp_info.fast_counter_read = 1; else _perfctr_vector.cmp_info.fast_counter_read = 0; _perfctr_vector.cmp_info.fast_real_timer = 1; _perfctr_vector.cmp_info.fast_virtual_timer = 1; _perfctr_vector.cmp_info.attach = 1; _perfctr_vector.cmp_info.attach_must_ptrace = 1; _perfctr_vector.cmp_info.default_domain = PAPI_DOM_USER; #if !defined(PPC64) /* AMD and Intel ia386 processors all support unit mask bits */ _perfctr_vector.cmp_info.cntr_umasks = 1; #endif #if defined(PPC64) _perfctr_vector.cmp_info.available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL | PAPI_DOM_SUPERVISOR; #else _perfctr_vector.cmp_info.available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL; #endif _perfctr_vector.cmp_info.default_granularity = PAPI_GRN_THR; _perfctr_vector.cmp_info.available_granularities = PAPI_GRN_THR; if ( info.cpu_features & PERFCTR_FEATURE_PCINT ) _perfctr_vector.cmp_info.hardware_intr = 1; else _perfctr_vector.cmp_info.hardware_intr = 0; SUBDBG( "Hardware/OS %s support counter generated interrupts\n", _perfctr_vector.cmp_info.hardware_intr ? "does" : "does not" ); strcpy( _papi_hwi_system_info.hw_info.model_string, PERFCTR_CPU_NAME( &info ) ); _papi_hwi_system_info.hw_info.model = ( int ) info.cpu_type; #if defined(PPC64) _papi_hwi_system_info.hw_info.vendor = PAPI_VENDOR_IBM; if ( strlen( _papi_hwi_system_info.hw_info.vendor_string ) == 0 ) strcpy( _papi_hwi_system_info.hw_info.vendor_string, "IBM" ); #else _papi_hwi_system_info.hw_info.vendor = xlate_cpu_type_to_vendor( info.cpu_type ); #endif /* Setup presets last. Some platforms depend on earlier info */ #if !defined(PPC64) // retval = setup_p3_vector_table(vtable); if ( !retval ) retval = setup_x86_presets( ( int ) info.cpu_type ); #else /* Setup native and preset events */ // retval = ppc64_setup_vector_table(vtable); if ( !retval ) retval = perfctr_ppc64_setup_native_table( ); if ( !retval ) retval = setup_ppc64_presets( info.cpu_type ); #endif if ( retval ) return ( retval ); return ( PAPI_OK ); }
static void init_perfctr() { unsigned int tsc_on = 1; unsigned int nractrs = 1; unsigned int pmc_map0 = 0; unsigned int evntsel0 = 0; self = vperfctr_open(); clock_perfctr = self; if( !self ) { char *str = "vperfctr_open() failed!!\n"; syscall(SYS_write, 2, str, strlen(str)); exit(1); } if( vperfctr_info(clock_perfctr, &info) < 0 ) { char *str = "vperfctr_info() failed!!\n"; syscall(SYS_write, 2, str, strlen(str)); exit(1); } memset(&control, 0, sizeof control); /* Attempt to set up control to count clocks via the TSC and retired instructions via PMC0. */ switch( info.cpu_type ) { case PERFCTR_X86_GENERIC: nractrs = 0; /* no PMCs available */ break; case PERFCTR_X86_INTEL_P5: case PERFCTR_X86_INTEL_P5MMX: case PERFCTR_X86_CYRIX_MII: /* event 0x16 (INSTRUCTIONS_EXECUTED), count at CPL 3 */ evntsel0 = 0x16 | (2 << 6); break; case PERFCTR_X86_INTEL_P6: case PERFCTR_X86_INTEL_PII: case PERFCTR_X86_INTEL_PIII: case PERFCTR_X86_AMD_K7: case PERFCTR_X86_AMD_K8: /* event 0xC0 (INST_RETIRED), count at CPL > 0, Enable */ evntsel0 = 0xC0 | (1 << 16) | (1 << 22); break; case PERFCTR_X86_WINCHIP_C6: tsc_on = 0; /* no working TSC available */ evntsel0 = 0x02; /* X86_INSTRUCTIONS */ break; case PERFCTR_X86_WINCHIP_2: tsc_on = 0; /* no working TSC available */ evntsel0 = 0x16; /* INSTRUCTIONS_EXECUTED */ break; case PERFCTR_X86_VIA_C3: pmc_map0 = 1; /* redirect PMC0 to PERFCTR1 */ evntsel0 = 0xC0; /* INSTRUCTIONS_EXECUTED */ break; case PERFCTR_X86_INTEL_P4: case PERFCTR_X86_INTEL_P4M2: /* PMC0: IQ_COUNTER0 with fast RDPMC */ pmc_map0 = 0x0C | (1 << 31); /* IQ_CCCR0: required flags, ESCR 4 (CRU_ESCR0), Enable */ evntsel0 = (0x3 << 16) | (4 << 13) | (1 << 12); /* CRU_ESCR0: event 2 (instr_retired), NBOGUSNTAG, CPL>0 */ control.cpu_control.p4.escr[0] = (2 << 25) | (1 << 9) | (1 << 2); break; default: { char *str = "cpu type not supported - perfctr init failed!!\n"; syscall(SYS_write, 2, str, strlen(str)); exit(1); } } control.cpu_control.tsc_on = tsc_on; control.cpu_control.nractrs = nractrs; control.cpu_control.pmc_map[0] = pmc_map0; control.cpu_control.evntsel[0] = evntsel0; if (!nractrs) { //output("error: your CPU (%s) doesn't support PMC timing\n", perfctr_info_cpu_name(&info)); char *str = "error: your CPU doesn't support PMC timing\n"; syscall(SYS_write, 2, str, strlen(str)); exit(1); } // start the perfctr if( vperfctr_control(clock_perfctr, &control) < 0 ) { char *str = "vperfctr_control failed!!!\n"; syscall(SYS_write, 2, str, strlen(str)); exit(1); } }