static int _x86_start( hwd_context_t * ctx, hwd_control_state_t * state ) { int error; #ifdef DEBUG print_control( &state->control.cpu_control ); #endif if ( state->rvperfctr != NULL ) { if ( ( error = rvperfctr_control( state->rvperfctr, &state->control ) ) < 0 ) { SUBDBG( "rvperfctr_control returns: %d\n", error ); PAPIERROR( RCNTRL_ERROR ); return ( PAPI_ESYS ); } return ( PAPI_OK ); } if ( ( error = vperfctr_control( ctx->perfctr, &state->control ) ) < 0 ) { SUBDBG( "vperfctr_control returns: %d\n", error ); PAPIERROR( VCNTRL_ERROR ); return ( PAPI_ESYS ); } return ( PAPI_OK ); }
int _perfctr_init( hwd_context_t * ctx ) { struct vperfctr_control tmp; int error; /* Initialize our thread/process pointer. */ if ( ( ctx->perfctr = vperfctr_open( ) ) == NULL ) { #ifdef VPERFCTR_OPEN_CREAT_EXCL /* New versions of perfctr have this, which allows us to get a previously created context, i.e. one created after a fork and now we're inside a new process that has been exec'd */ if ( errno ) { if ( ( ctx->perfctr = vperfctr_open_mode( 0 ) ) == NULL ) { PAPIERROR( VOPEN_ERROR ); return ( PAPI_ESYS ); } } else { PAPIERROR( VOPEN_ERROR ); return ( PAPI_ESYS ); } #else PAPIERROR( VOPEN_ERROR ); return ( PAPI_ESYS ); #endif } SUBDBG( "_papi_hwd_init vperfctr_open() = %p\n", ctx->perfctr ); /* Initialize the per thread/process virtualized TSC */ memset( &tmp, 0x0, sizeof ( tmp ) ); tmp.cpu_control.tsc_on = 1; #ifdef VPERFCTR_CONTROL_CLOEXEC tmp.flags = VPERFCTR_CONTROL_CLOEXEC; SUBDBG( "close on exec\t\t\t%u\n", tmp.flags ); #endif /* Start the per thread/process virtualized TSC */ error = vperfctr_control( ctx->perfctr, &tmp ); if ( error < 0 ) { SUBDBG( "starting virtualized TSC; vperfctr_control returns %d\n", error ); PAPIERROR( VCNTRL_ERROR ); return ( PAPI_ESYS ); } return ( PAPI_OK ); }
int _papi_hwd_start( hwd_context_t * ctx, hwd_control_state_t * state ) { int error; /* clear_unused_pmcsel_bits(this_state); moved to update_control_state */ #ifdef DEBUG print_control( &state->control.cpu_control ); #endif if ( state->rvperfctr != NULL ) { if ( ( error = rvperfctr_control( state->rvperfctr, &state->control ) ) < 0 ) { SUBDBG( "rvperfctr_control returns: %d\n", error ); PAPIERROR( RCNTRL_ERROR ); return ( PAPI_ESYS ); } return ( PAPI_OK ); } if ( ( error = vperfctr_control( ctx->perfctr, &state->control ) ) < 0 ) { SUBDBG( "vperfctr_control returns: %d\n", error ); PAPIERROR( VCNTRL_ERROR ); return ( PAPI_ESYS ); } 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); } }