|
Packit Service |
a1973e |
/*
|
|
Packit Service |
a1973e |
* File: perfmon.c
|
|
Packit Service |
a1973e |
* Author: Philip Mucci
|
|
Packit Service |
a1973e |
* mucci@cs.utk.edu
|
|
Packit Service |
a1973e |
* Mods: Brian Sheely
|
|
Packit Service |
a1973e |
* bsheely@eecs.utk.edu
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* TODO LIST:
|
|
Packit Service |
a1973e |
- Events for all platforms
|
|
Packit Service |
a1973e |
- Derived events for all platforms
|
|
Packit Service |
a1973e |
- Latency profiling
|
|
Packit Service |
a1973e |
- BTB/IPIEAR sampling
|
|
Packit Service |
a1973e |
- Test on ITA2, Pentium 4
|
|
Packit Service |
a1973e |
- hwd_ntv_code_to_name
|
|
Packit Service |
a1973e |
- Make native map carry major events, not umasks
|
|
Packit Service |
a1973e |
- Enum event uses native_map not pfm()
|
|
Packit Service |
a1973e |
- Hook up globals to be freed to sub_info
|
|
Packit Service |
a1973e |
- Better feature bit support for IEAR
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#include "papi.h"
|
|
Packit Service |
a1973e |
#include "papi_internal.h"
|
|
Packit Service |
a1973e |
#include "papi_vector.h"
|
|
Packit Service |
a1973e |
#include "papi_memory.h"
|
|
Packit Service |
a1973e |
#include "papi_libpfm_events.h"
|
|
Packit Service |
a1973e |
#include "extras.h"
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#include "perfmon.h"
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#include "linux-memory.h"
|
|
Packit Service |
a1973e |
#include "linux-timer.h"
|
|
Packit Service |
a1973e |
#include "linux-common.h"
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#ifdef __ia64__
|
|
Packit Service |
a1973e |
#include "perfmon/pfmlib_itanium2.h"
|
|
Packit Service |
a1973e |
#include "perfmon/pfmlib_montecito.h"
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
typedef unsigned uint;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Advance declarations */
|
|
Packit Service |
a1973e |
static int _papi_pfm_set_overflow( EventSetInfo_t * ESI, int EventIndex,
|
|
Packit Service |
a1973e |
int threshold );
|
|
Packit Service |
a1973e |
papi_vector_t _perfmon2_vector;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Static locals */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static int _perfmon2_pfm_pmu_type = -1;
|
|
Packit Service |
a1973e |
static pfmlib_regmask_t _perfmon2_pfm_unavailable_pmcs;
|
|
Packit Service |
a1973e |
static pfmlib_regmask_t _perfmon2_pfm_unavailable_pmds;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Debug functions */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#ifdef DEBUG
|
|
Packit Service |
a1973e |
static void
|
|
Packit Service |
a1973e |
dump_smpl_arg( pfm_dfl_smpl_arg_t * arg )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
SUBDBG( "SMPL_ARG.buf_size = %llu\n",
|
|
Packit Service |
a1973e |
( unsigned long long ) arg->buf_size );
|
|
Packit Service |
a1973e |
SUBDBG( "SMPL_ARG.buf_flags = %d\n", arg->buf_flags );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static void
|
|
Packit Service |
a1973e |
dump_sets( pfarg_setdesc_t * set, int num_sets )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
int i;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for ( i = 0; i < num_sets; i++ ) {
|
|
Packit Service |
a1973e |
SUBDBG( "SET[%d]\n", i );
|
|
Packit Service |
a1973e |
SUBDBG( "SET[%d].set_id = %d\n", i, set[i].set_id );
|
|
Packit Service |
a1973e |
// SUBDBG("SET[%d].set_id_next = %d\n",i,set[i].set_id_next);
|
|
Packit Service |
a1973e |
SUBDBG( "SET[%d].set_flags = %d\n", i, set[i].set_flags );
|
|
Packit Service |
a1973e |
SUBDBG( "SET[%d].set_timeout = %llu\n", i,
|
|
Packit Service |
a1973e |
( unsigned long long ) set[i].set_timeout );
|
|
Packit Service |
a1973e |
// SUBDBG("SET[%d].set_mmap_offset = %#016llx\n",i,(unsigned long long)set[i].set_mmap_offset);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static void
|
|
Packit Service |
a1973e |
dump_setinfo( pfarg_setinfo_t * setinfo, int num_sets )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
int i;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for ( i = 0; i < num_sets; i++ ) {
|
|
Packit Service |
a1973e |
SUBDBG( "SETINFO[%d]\n", i );
|
|
Packit Service |
a1973e |
SUBDBG( "SETINFO[%d].set_id = %d\n", i, setinfo[i].set_id );
|
|
Packit Service |
a1973e |
// SUBDBG("SETINFO[%d].set_id_next = %d\n",i,setinfo[i].set_id_next);
|
|
Packit Service |
a1973e |
SUBDBG( "SETINFO[%d].set_flags = %d\n", i, setinfo[i].set_flags );
|
|
Packit Service |
a1973e |
SUBDBG( "SETINFO[%d].set_ovfl_pmds[0] = %#016llx\n", i,
|
|
Packit Service |
a1973e |
( unsigned long long ) setinfo[i].set_ovfl_pmds[0] );
|
|
Packit Service |
a1973e |
SUBDBG( "SETINFO[%d].set_runs = %llu\n", i,
|
|
Packit Service |
a1973e |
( unsigned long long ) setinfo[i].set_runs );
|
|
Packit Service |
a1973e |
SUBDBG( "SETINFO[%d].set_timeout = %llu\n", i,
|
|
Packit Service |
a1973e |
( unsigned long long ) setinfo[i].set_timeout );
|
|
Packit Service |
a1973e |
SUBDBG( "SETINFO[%d].set_act_duration = %llu\n", i,
|
|
Packit Service |
a1973e |
( unsigned long long ) setinfo[i].set_act_duration );
|
|
Packit Service |
a1973e |
// SUBDBG("SETINFO[%d].set_mmap_offset = %#016llx\n",i,(unsigned long long)setinfo[i].set_mmap_offset);
|
|
Packit Service |
a1973e |
SUBDBG( "SETINFO[%d].set_avail_pmcs[0] = %#016llx\n", i,
|
|
Packit Service |
a1973e |
( unsigned long long ) setinfo[i].set_avail_pmcs[0] );
|
|
Packit Service |
a1973e |
SUBDBG( "SETINFO[%d].set_avail_pmds[0] = %#016llx\n", i,
|
|
Packit Service |
a1973e |
( unsigned long long ) setinfo[i].set_avail_pmds[0] );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static void
|
|
Packit Service |
a1973e |
dump_pmc( pfm_control_state_t * ctl )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
unsigned int i;
|
|
Packit Service |
a1973e |
pfarg_pmc_t *pc = ctl->pc;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for ( i = 0; i < ctl->out.pfp_pmc_count; i++ ) {
|
|
Packit Service |
a1973e |
SUBDBG( "PC[%d]\n", i );
|
|
Packit Service |
a1973e |
SUBDBG( "PC[%d].reg_num = %d\n", i, pc[i].reg_num );
|
|
Packit Service |
a1973e |
SUBDBG( "PC[%d].reg_set = %d\n", i, pc[i].reg_set );
|
|
Packit Service |
a1973e |
SUBDBG( "PC[%d].reg_flags = %#08x\n", i, pc[i].reg_flags );
|
|
Packit Service |
a1973e |
SUBDBG( "PC[%d].reg_value = %#016llx\n", i,
|
|
Packit Service |
a1973e |
( unsigned long long ) pc[i].reg_value );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static void
|
|
Packit Service |
a1973e |
dump_pmd( pfm_control_state_t * ctl )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
unsigned int i;
|
|
Packit Service |
a1973e |
pfarg_pmd_t *pd = ctl->pd;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for ( i = 0; i < ctl->in.pfp_event_count; i++ ) {
|
|
Packit Service |
a1973e |
SUBDBG( "PD[%d]\n", i );
|
|
Packit Service |
a1973e |
SUBDBG( "PD[%d].reg_num = %d\n", i, pd[i].reg_num );
|
|
Packit Service |
a1973e |
SUBDBG( "PD[%d].reg_set = %d\n", i, pd[i].reg_set );
|
|
Packit Service |
a1973e |
SUBDBG( "PD[%d].reg_flags = %#08x\n", i, pd[i].reg_flags );
|
|
Packit Service |
a1973e |
SUBDBG( "PD[%d].reg_value = %#016llx\n", i,
|
|
Packit Service |
a1973e |
( unsigned long long ) pd[i].reg_value );
|
|
Packit Service |
a1973e |
SUBDBG( "PD[%d].reg_long_reset = %llu\n", i,
|
|
Packit Service |
a1973e |
( unsigned long long ) pd[i].reg_long_reset );
|
|
Packit Service |
a1973e |
SUBDBG( "PD[%d].reg_short_reset = %llu\n", i,
|
|
Packit Service |
a1973e |
( unsigned long long ) pd[i].reg_short_reset );
|
|
Packit Service |
a1973e |
SUBDBG( "PD[%d].reg_last_reset_val = %llu\n", i,
|
|
Packit Service |
a1973e |
( unsigned long long ) pd[i].reg_last_reset_val );
|
|
Packit Service |
a1973e |
SUBDBG( "PD[%d].reg_ovfl_switch_cnt = %llu\n", i,
|
|
Packit Service |
a1973e |
( unsigned long long ) pd[i].reg_ovfl_switch_cnt );
|
|
Packit Service |
a1973e |
SUBDBG( "PD[%d].reg_reset_pmds[0] = %#016llx\n", i,
|
|
Packit Service |
a1973e |
( unsigned long long ) pd[i].reg_reset_pmds[0] );
|
|
Packit Service |
a1973e |
SUBDBG( "PD[%d].reg_smpl_pmds[0] = %#016llx\n", i,
|
|
Packit Service |
a1973e |
( unsigned long long ) pd[i].reg_smpl_pmds[0] );
|
|
Packit Service |
a1973e |
SUBDBG( "PD[%d].reg_smpl_eventid = %llu\n", i,
|
|
Packit Service |
a1973e |
( unsigned long long ) pd[i].reg_smpl_eventid );
|
|
Packit Service |
a1973e |
SUBDBG( "PD[%d].reg_random_mask = %llu\n", i,
|
|
Packit Service |
a1973e |
( unsigned long long ) pd[i].reg_random_mask );
|
|
Packit Service |
a1973e |
SUBDBG( "PD[%d].reg_random_seed = %d\n", i, pd[i].reg_random_seed );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static void
|
|
Packit Service |
a1973e |
dump_smpl_hdr( pfm_dfl_smpl_hdr_t * hdr )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
SUBDBG( "SMPL_HDR.hdr_count = %llu\n",
|
|
Packit Service |
a1973e |
( unsigned long long ) hdr->hdr_count );
|
|
Packit Service |
a1973e |
SUBDBG( "SMPL_HDR.hdr_cur_offs = %llu\n",
|
|
Packit Service |
a1973e |
( unsigned long long ) hdr->hdr_cur_offs );
|
|
Packit Service |
a1973e |
SUBDBG( "SMPL_HDR.hdr_overflows = %llu\n",
|
|
Packit Service |
a1973e |
( unsigned long long ) hdr->hdr_overflows );
|
|
Packit Service |
a1973e |
SUBDBG( "SMPL_HDR.hdr_buf_size = %llu\n",
|
|
Packit Service |
a1973e |
( unsigned long long ) hdr->hdr_buf_size );
|
|
Packit Service |
a1973e |
SUBDBG( "SMPL_HDR.hdr_min_buf_space = %llu\n",
|
|
Packit Service |
a1973e |
( unsigned long long ) hdr->hdr_min_buf_space );
|
|
Packit Service |
a1973e |
SUBDBG( "SMPL_HDR.hdr_version = %d\n", hdr->hdr_version );
|
|
Packit Service |
a1973e |
SUBDBG( "SMPL_HDR.hdr_buf_flags = %d\n", hdr->hdr_buf_flags );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static void
|
|
Packit Service |
a1973e |
dump_smpl( pfm_dfl_smpl_entry_t * entry )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
SUBDBG( "SMPL.pid = %d\n", entry->pid );
|
|
Packit Service |
a1973e |
SUBDBG( "SMPL.ovfl_pmd = %d\n", entry->ovfl_pmd );
|
|
Packit Service |
a1973e |
SUBDBG( "SMPL.last_reset_val = %llu\n",
|
|
Packit Service |
a1973e |
( unsigned long long ) entry->last_reset_val );
|
|
Packit Service |
a1973e |
SUBDBG( "SMPL.ip = %#llx\n", ( unsigned long long ) entry->ip );
|
|
Packit Service |
a1973e |
SUBDBG( "SMPL.tstamp = %llu\n", ( unsigned long long ) entry->tstamp );
|
|
Packit Service |
a1973e |
SUBDBG( "SMPL.cpu = %d\n", entry->cpu );
|
|
Packit Service |
a1973e |
SUBDBG( "SMPL.set = %d\n", entry->set );
|
|
Packit Service |
a1973e |
SUBDBG( "SMPL.tgid = %d\n", entry->tgid );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#define PFM_MAX_PMCDS 20
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
_papi_pfm_write_pmcs( pfm_context_t * ctx, pfm_control_state_t * ctl )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
( void ) ctx; /*unused */
|
|
Packit Service |
a1973e |
unsigned int i = 0;
|
|
Packit Service |
a1973e |
int ret;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG( "PFM_WRITE_PMCS(%d,%p,%d)\n", ctl->ctx_fd, ctl->pc,
|
|
Packit Service |
a1973e |
ctl->out.pfp_pmc_count );
|
|
Packit Service |
a1973e |
if ( ctl->out.pfp_pmc_count > PFM_MAX_PMCDS ) {
|
|
Packit Service |
a1973e |
for ( i = 0; i < ctl->out.pfp_pmc_count - PFM_MAX_PMCDS;
|
|
Packit Service |
a1973e |
i += PFM_MAX_PMCDS ) {
|
|
Packit Service |
a1973e |
if ( ( ret =
|
|
Packit Service |
a1973e |
pfm_write_pmcs( ctl->ctx_fd, ctl->pc + i,
|
|
Packit Service |
a1973e |
PFM_MAX_PMCDS ) ) ) {
|
|
Packit Service |
a1973e |
DEBUGCALL( DEBUG_SUBSTRATE, dump_pmc( ctl ) );
|
|
Packit Service |
a1973e |
PAPIERROR( "pfm_write_pmcs(%d,%p,%d): %s", ctl->ctx_fd, ctl->pc,
|
|
Packit Service |
a1973e |
ctl->out.pfp_pmc_count, strerror( ret ) );
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
DEBUGCALL( DEBUG_SUBSTRATE, dump_pmc( ctl ) );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
if ( ( ret =
|
|
Packit Service |
a1973e |
pfm_write_pmcs( ctl->ctx_fd, ctl->pc + i,
|
|
Packit Service |
a1973e |
ctl->out.pfp_pmc_count - i ) ) ) {
|
|
Packit Service |
a1973e |
DEBUGCALL( DEBUG_SUBSTRATE, dump_pmc( ctl ) );
|
|
Packit Service |
a1973e |
PAPIERROR( "pfm_write_pmcs(%d,%p,%d): %s", ctl->ctx_fd, ctl->pc,
|
|
Packit Service |
a1973e |
ctl->out.pfp_pmc_count, strerror( ret ) );
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
DEBUGCALL( DEBUG_SUBSTRATE, dump_pmc( ctl ) );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return PAPI_OK;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
_papi_pfm_write_pmds( pfm_context_t * ctx, pfm_control_state_t * ctl )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
( void ) ctx; /*unused */
|
|
Packit Service |
a1973e |
unsigned int i = 0;
|
|
Packit Service |
a1973e |
int ret;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG( "PFM_WRITE_PMDS(%d,%p,%d)\n", ctl->ctx_fd, ctl->pd,
|
|
Packit Service |
a1973e |
ctl->in.pfp_event_count );
|
|
Packit Service |
a1973e |
if ( ctl->in.pfp_event_count > PFM_MAX_PMCDS ) {
|
|
Packit Service |
a1973e |
for ( i = 0; i < ctl->in.pfp_event_count - PFM_MAX_PMCDS;
|
|
Packit Service |
a1973e |
i += PFM_MAX_PMCDS ) {
|
|
Packit Service |
a1973e |
if ( ( ret =
|
|
Packit Service |
a1973e |
pfm_write_pmds( ctl->ctx_fd, ctl->pd + i,
|
|
Packit Service |
a1973e |
PFM_MAX_PMCDS ) ) ) {
|
|
Packit Service |
a1973e |
DEBUGCALL( DEBUG_SUBSTRATE, dump_pmd( ctl ) );
|
|
Packit Service |
a1973e |
PAPIERROR( "pfm_write_pmds(%d,%p,%d): errno=%d %s", ctl->ctx_fd,
|
|
Packit Service |
a1973e |
ctl->pd, ctl->in.pfp_event_count, errno,
|
|
Packit Service |
a1973e |
strerror( ret ) );
|
|
Packit Service |
a1973e |
perror( "pfm_write_pmds" );
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
DEBUGCALL( DEBUG_SUBSTRATE, dump_pmd( ctl ) );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
if ( ( ret =
|
|
Packit Service |
a1973e |
pfm_write_pmds( ctl->ctx_fd, ctl->pd + i,
|
|
Packit Service |
a1973e |
ctl->in.pfp_event_count - i ) ) ) {
|
|
Packit Service |
a1973e |
DEBUGCALL( DEBUG_SUBSTRATE, dump_pmd( ctl ) );
|
|
Packit Service |
a1973e |
PAPIERROR( "pfm_write_pmds(%d,%p,%d): errno=%d %s", ctl->ctx_fd,
|
|
Packit Service |
a1973e |
ctl->pd, ctl->in.pfp_event_count, errno, strerror( ret ) );
|
|
Packit Service |
a1973e |
perror( "pfm_write_pmds" );
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
DEBUGCALL( DEBUG_SUBSTRATE, dump_pmd( ctl ) );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return PAPI_OK;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
_papi_pfm_read_pmds( pfm_context_t * ctx, pfm_control_state_t * ctl )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
( void ) ctx; /*unused */
|
|
Packit Service |
a1973e |
unsigned int i = 0;
|
|
Packit Service |
a1973e |
int ret;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG( "PFM_READ_PMDS(%d,%p,%d)\n", ctl->ctx_fd, ctl->pd,
|
|
Packit Service |
a1973e |
ctl->in.pfp_event_count );
|
|
Packit Service |
a1973e |
if ( ctl->in.pfp_event_count > PFM_MAX_PMCDS ) {
|
|
Packit Service |
a1973e |
for ( i = 0; i < ctl->in.pfp_event_count - PFM_MAX_PMCDS;
|
|
Packit Service |
a1973e |
i += PFM_MAX_PMCDS ) {
|
|
Packit Service |
a1973e |
if ( ( ret =
|
|
Packit Service |
a1973e |
pfm_read_pmds( ctl->ctx_fd, ctl->pd + i,
|
|
Packit Service |
a1973e |
PFM_MAX_PMCDS ) ) ) {
|
|
Packit Service |
a1973e |
DEBUGCALL( DEBUG_SUBSTRATE, dump_pmd( ctl ) );
|
|
Packit Service |
a1973e |
PAPIERROR( "pfm_read_pmds(%d,%p,%d): %s", ctl->ctx_fd, ctl->pd,
|
|
Packit Service |
a1973e |
ctl->in.pfp_event_count, strerror( ret ) );
|
|
Packit Service |
a1973e |
return ( ( errno == EBADF ) ? PAPI_ECLOST : PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
DEBUGCALL( DEBUG_SUBSTRATE, dump_pmd( ctl ) );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
if ( ( ret =
|
|
Packit Service |
a1973e |
pfm_read_pmds( ctl->ctx_fd, ctl->pd + i,
|
|
Packit Service |
a1973e |
ctl->in.pfp_event_count - i ) ) ) {
|
|
Packit Service |
a1973e |
DEBUGCALL( DEBUG_SUBSTRATE, dump_pmd( ctl ) );
|
|
Packit Service |
a1973e |
PAPIERROR( "pfm_read_pmds(%d,%p,%d): %s", ctl->ctx_fd, ctl->pd,
|
|
Packit Service |
a1973e |
ctl->in.pfp_event_count, strerror( ret ) );
|
|
Packit Service |
a1973e |
return ( ( errno == EBADF ) ? PAPI_ECLOST : PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
DEBUGCALL( DEBUG_SUBSTRATE, dump_pmd( ctl ) );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return PAPI_OK;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* This routine effectively does argument checking as the real magic will happen
|
|
Packit Service |
a1973e |
in compute_kernel_args. This just gets the value back from the kernel. */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static int
|
|
Packit Service |
a1973e |
check_multiplex_timeout( int ctx_fd, unsigned long *timeout_ns )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
int ret;
|
|
Packit Service |
a1973e |
pfarg_setdesc_t set[2];
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
memset( set, 0, sizeof ( pfarg_setdesc_t ) * 2 );
|
|
Packit Service |
a1973e |
set[1].set_id = 1;
|
|
Packit Service |
a1973e |
set[1].set_flags = PFM_SETFL_TIME_SWITCH;
|
|
Packit Service |
a1973e |
set[1].set_timeout = *timeout_ns;
|
|
Packit Service |
a1973e |
SUBDBG( "Multiplexing interval requested is %llu ns.\n",
|
|
Packit Service |
a1973e |
( unsigned long long ) set[1].set_timeout );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Create a test eventset */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG( "PFM_CREATE_EVTSETS(%d,%p,1)\n", ctx_fd, &set[1] );
|
|
Packit Service |
a1973e |
if ( ( ret = pfm_create_evtsets( ctx_fd, &set[1], 1 ) ) != PFMLIB_SUCCESS ) {
|
|
Packit Service |
a1973e |
DEBUGCALL( DEBUG_SUBSTRATE, dump_sets( &set[1], 1 ) );
|
|
Packit Service |
a1973e |
PAPIERROR( "pfm_create_evtsets(%d,%p,%d): %s", ctx_fd, &set[1], 1,
|
|
Packit Service |
a1973e |
strerror( ret ) );
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG( "Multiplexing interval returned is %llu ns.\n",
|
|
Packit Service |
a1973e |
( unsigned long long ) set[1].set_timeout );
|
|
Packit Service |
a1973e |
*timeout_ns = set[1].set_timeout;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Delete the second eventset */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
pfm_delete_evtsets( ctx_fd, &set[1], 1 );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* The below function is stolen from libpfm from Stephane Eranian */
|
|
Packit Service |
a1973e |
static int
|
|
Packit Service |
a1973e |
detect_timeout_and_unavail_pmu_regs( pfmlib_regmask_t * r_pmcs,
|
|
Packit Service |
a1973e |
pfmlib_regmask_t * r_pmds,
|
|
Packit Service |
a1973e |
unsigned long *timeout_ns )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
pfarg_ctx_t ctx;
|
|
Packit Service |
a1973e |
pfarg_setinfo_t setf;
|
|
Packit Service |
a1973e |
unsigned int i;
|
|
Packit Service |
a1973e |
int ret, j, myfd;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
memset( r_pmcs, 0, sizeof ( *r_pmcs ) );
|
|
Packit Service |
a1973e |
memset( r_pmds, 0, sizeof ( *r_pmds ) );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
memset( &ctx, 0, sizeof ( ctx ) );
|
|
Packit Service |
a1973e |
memset( &setf, 0, sizeof ( setf ) );
|
|
Packit Service |
a1973e |
/*
|
|
Packit Service |
a1973e |
* if no context descriptor is passed, then create
|
|
Packit Service |
a1973e |
* a temporary context
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
SUBDBG( "PFM_CREATE_CONTEXT(%p,%p,%p,%d)\n", &ctx, NULL, NULL, 0 );
|
|
Packit Service |
a1973e |
myfd = pfm_create_context( &ctx, NULL, NULL, 0 );
|
|
Packit Service |
a1973e |
if ( myfd == -1 ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "detect_unavail_pmu_regs:pfm_create_context(): %s",
|
|
Packit Service |
a1973e |
strerror( errno ) );
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
SUBDBG( "PFM_CREATE_CONTEXT returned fd %d\n", myfd );
|
|
Packit Service |
a1973e |
/*
|
|
Packit Service |
a1973e |
* retrieve available register bitmasks from set0
|
|
Packit Service |
a1973e |
* which is guaranteed to exist for every context
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
ret = pfm_getinfo_evtsets( myfd, &setf, 1 );
|
|
Packit Service |
a1973e |
if ( ret != PFMLIB_SUCCESS ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "pfm_getinfo_evtsets(): %s", strerror( ret ) );
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
DEBUGCALL( DEBUG_SUBSTRATE, dump_setinfo( &setf, 1 ) );
|
|
Packit Service |
a1973e |
if ( r_pmcs )
|
|
Packit Service |
a1973e |
for ( i = 0; i < PFM_PMC_BV; i++ ) {
|
|
Packit Service |
a1973e |
for ( j = 0; j < 64; j++ ) {
|
|
Packit Service |
a1973e |
if ( ( setf.set_avail_pmcs[i] & ( 1ULL << j ) ) == 0 )
|
|
Packit Service |
a1973e |
pfm_regmask_set( r_pmcs, ( i << 6 ) + j );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
if ( r_pmds )
|
|
Packit Service |
a1973e |
for ( i = 0; i < PFM_PMD_BV; i++ ) {
|
|
Packit Service |
a1973e |
for ( j = 0; j < 64; j++ ) {
|
|
Packit Service |
a1973e |
if ( ( setf.set_avail_pmds[i] & ( 1ULL << j ) ) == 0 )
|
|
Packit Service |
a1973e |
pfm_regmask_set( r_pmds, ( i << 6 ) + j );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
check_multiplex_timeout( myfd, timeout_ns );
|
|
Packit Service |
a1973e |
i = close( myfd );
|
|
Packit Service |
a1973e |
SUBDBG( "CLOSE fd %d returned %d\n", myfd, i );
|
|
Packit Service |
a1973e |
return PAPI_OK;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* BEGIN COMMON CODE */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static inline int
|
|
Packit Service |
a1973e |
compute_kernel_args( hwd_control_state_t * ctl0 )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
pfm_control_state_t *ctl = ( pfm_control_state_t * ) ctl0;
|
|
Packit Service |
a1973e |
pfmlib_input_param_t *inp = &ctl->in;
|
|
Packit Service |
a1973e |
pfmlib_output_param_t *outp = &ctl->out;
|
|
Packit Service |
a1973e |
pfmlib_input_param_t tmpin;
|
|
Packit Service |
a1973e |
pfmlib_output_param_t tmpout;
|
|
Packit Service |
a1973e |
#if 0
|
|
Packit Service |
a1973e |
/* This will be used to fixup the overflow and sample args after re-allocation */
|
|
Packit Service |
a1973e |
pfarg_pmd_t oldpd;
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
pfarg_pmd_t *pd = ctl->pd;
|
|
Packit Service |
a1973e |
pfarg_pmc_t *pc = ctl->pc;
|
|
Packit Service |
a1973e |
pfarg_setdesc_t *sets = ctl->set;
|
|
Packit Service |
a1973e |
pfarg_setinfo_t *setinfos = ctl->setinfo;
|
|
Packit Service |
a1973e |
int *num_sets = &ctl->num_sets;
|
|
Packit Service |
a1973e |
unsigned int set = 0;
|
|
Packit Service |
a1973e |
int donepc = 0, donepd = 0, ret, j;
|
|
Packit Service |
a1973e |
unsigned int i, dispatch_count = inp->pfp_event_count;
|
|
Packit Service |
a1973e |
int togo = inp->pfp_event_count, done = 0;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Save old PD array so we can reconstruct certain flags. */
|
|
Packit Service |
a1973e |
/* This can be removed when we have higher level code call */
|
|
Packit Service |
a1973e |
/* set_profile,set_overflow etc when there is hardware */
|
|
Packit Service |
a1973e |
/* (component) support, but this change won't happen for PAPI 3.5 */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG
|
|
Packit Service |
a1973e |
( "entry multiplexed %d, pfp_event_count %d, num_cntrs %d, num_sets %d\n",
|
|
Packit Service |
a1973e |
ctl->multiplexed, inp->pfp_event_count, _perfmon2_vector.cmp_info.num_cntrs,
|
|
Packit Service |
a1973e |
*num_sets );
|
|
Packit Service |
a1973e |
if ( ( ctl->multiplexed ) &&
|
|
Packit Service |
a1973e |
( inp->pfp_event_count >
|
|
Packit Service |
a1973e |
( unsigned int ) _perfmon2_vector.cmp_info.num_cntrs ) ) {
|
|
Packit Service |
a1973e |
dispatch_count = _perfmon2_vector.cmp_info.num_cntrs;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
while ( togo ) {
|
|
Packit Service |
a1973e |
again:
|
|
Packit Service |
a1973e |
memset( &tmpin, 0x0, sizeof ( tmpin ) );
|
|
Packit Service |
a1973e |
memset( &tmpout, 0x0, sizeof ( tmpout ) );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG( "togo %d, done %d, dispatch_count %d, num_cntrs %d\n", togo,
|
|
Packit Service |
a1973e |
done, dispatch_count, _perfmon2_vector.cmp_info.num_cntrs );
|
|
Packit Service |
a1973e |
tmpin.pfp_event_count = dispatch_count;
|
|
Packit Service |
a1973e |
tmpin.pfp_dfl_plm = inp->pfp_dfl_plm;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Make sure we tell dispatch that these PMC's are not available */
|
|
Packit Service |
a1973e |
memcpy( &tmpin.pfp_unavail_pmcs, &_perfmon2_pfm_unavailable_pmcs,
|
|
Packit Service |
a1973e |
sizeof ( _perfmon2_pfm_unavailable_pmcs ) );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for ( i = 0, j = done; i < dispatch_count; i++, j++ ) {
|
|
Packit Service |
a1973e |
memcpy( tmpin.pfp_events + i, inp->pfp_events + j,
|
|
Packit Service |
a1973e |
sizeof ( pfmlib_event_t ) );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ( ret =
|
|
Packit Service |
a1973e |
pfm_dispatch_events( &tmpin, NULL, &tmpout,
|
|
Packit Service |
a1973e |
NULL ) ) != PFMLIB_SUCCESS ) {
|
|
Packit Service |
a1973e |
if ( ctl->multiplexed ) {
|
|
Packit Service |
a1973e |
dispatch_count--;
|
|
Packit Service |
a1973e |
if ( dispatch_count == 0 ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "pfm_dispatch_events(): %s",
|
|
Packit Service |
a1973e |
pfm_strerror( ret ) );
|
|
Packit Service |
a1973e |
return ( _papi_libpfm_error( ret ) );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
SUBDBG
|
|
Packit Service |
a1973e |
( "Dispatch failed because of counter conflict, trying again with %d counters.\n",
|
|
Packit Service |
a1973e |
dispatch_count );
|
|
Packit Service |
a1973e |
goto again;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
PAPIERROR( "pfm_dispatch_events(): %s", pfm_strerror( ret ) );
|
|
Packit Service |
a1973e |
return ( _papi_libpfm_error( ret ) );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/*
|
|
Packit Service |
a1973e |
* Now prepare the argument to initialize the PMDs and PMCS.
|
|
Packit Service |
a1973e |
* We must pfp_pmc_count to determine the number of PMC to intialize.
|
|
Packit Service |
a1973e |
* We must use pfp_event_count to determine the number of PMD to initialize.
|
|
Packit Service |
a1973e |
* Some events causes extra PMCs to be used, so pfp_pmc_count may be >= pfp_event_count.
|
|
Packit Service |
a1973e |
*
|
|
Packit Service |
a1973e |
* This step is new compared to libpfm-2.x. It is necessary because the library no
|
|
Packit Service |
a1973e |
* longer knows about the kernel data structures.
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for ( i = 0; i < tmpout.pfp_pmc_count; i++, donepc++ ) {
|
|
Packit Service |
a1973e |
pc[donepc].reg_num = tmpout.pfp_pmcs[i].reg_num;
|
|
Packit Service |
a1973e |
pc[donepc].reg_value = tmpout.pfp_pmcs[i].reg_value;
|
|
Packit Service |
a1973e |
pc[donepc].reg_set = set;
|
|
Packit Service |
a1973e |
SUBDBG( "PC%d (i%d) is reg num %d, value %llx, set %d\n", donepc, i,
|
|
Packit Service |
a1973e |
pc[donepc].reg_num,
|
|
Packit Service |
a1973e |
( unsigned long long ) pc[donepc].reg_value,
|
|
Packit Service |
a1973e |
pc[donepc].reg_set );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* figure out pmd mapping from output pmc */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#if defined(HAVE_PFM_REG_EVT_IDX)
|
|
Packit Service |
a1973e |
for ( i = 0, j = 0; i < tmpin.pfp_event_count; i++, donepd++ ) {
|
|
Packit Service |
a1973e |
pd[donepd].reg_num = tmpout.pfp_pmcs[j].reg_pmd_num;
|
|
Packit Service |
a1973e |
pd[donepd].reg_set = set;
|
|
Packit Service |
a1973e |
SUBDBG( "PD%d (i%d,j%d) is reg num %d, set %d\n", donepd, i, j,
|
|
Packit Service |
a1973e |
pd[donepd].reg_num, pd[donepd].reg_set );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Skip over entries that map to the same PMD,
|
|
Packit Service |
a1973e |
PIV has 2 PMCS for every PMD */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for ( ; j < tmpout.pfp_pmc_count; j++ )
|
|
Packit Service |
a1973e |
if ( tmpout.pfp_pmcs[j].reg_evt_idx != i )
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
#else
|
|
Packit Service |
a1973e |
for ( i = 0; i < tmpout.pfp_pmd_count; i++, donepd++ ) {
|
|
Packit Service |
a1973e |
pd[donepd].reg_num = tmpout.pfp_pmds[i].reg_num;
|
|
Packit Service |
a1973e |
pd[donepd].reg_set = set;
|
|
Packit Service |
a1973e |
SUBDBG( "PD%d (i%d) is reg num %d, set %d\n", donepd, i,
|
|
Packit Service |
a1973e |
pd[donepd].reg_num, pd[donepd].reg_set );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
togo -= dispatch_count;
|
|
Packit Service |
a1973e |
done += dispatch_count;
|
|
Packit Service |
a1973e |
if ( togo > _perfmon2_vector.cmp_info.num_cntrs )
|
|
Packit Service |
a1973e |
dispatch_count = _perfmon2_vector.cmp_info.num_cntrs;
|
|
Packit Service |
a1973e |
else
|
|
Packit Service |
a1973e |
dispatch_count = togo;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
setinfos[set].set_id = set;
|
|
Packit Service |
a1973e |
sets[set].set_id = set;
|
|
Packit Service |
a1973e |
set++;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
*num_sets = set;
|
|
Packit Service |
a1973e |
outp->pfp_pmc_count = donepc;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ctl->multiplexed && ( set > 1 ) ) {
|
|
Packit Service |
a1973e |
for ( i = 0; i < set; i++ ) {
|
|
Packit Service |
a1973e |
sets[i].set_flags = PFM_SETFL_TIME_SWITCH;
|
|
Packit Service |
a1973e |
sets[i].set_timeout = ctl->multiplexed;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
SUBDBG
|
|
Packit Service |
a1973e |
( "exit multiplexed %d (ns switch time), pfp_pmc_count %d, num_sets %d\n",
|
|
Packit Service |
a1973e |
ctl->multiplexed, outp->pfp_pmc_count, *num_sets );
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
tune_up_fd( int ctx_fd )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
int ret;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* set close-on-exec to ensure we will be getting the PFM_END_MSG, i.e.,
|
|
Packit Service |
a1973e |
* fd not visible to child. */
|
|
Packit Service |
a1973e |
ret = fcntl( ctx_fd, F_SETFD, FD_CLOEXEC );
|
|
Packit Service |
a1973e |
if ( ret == -1 ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "cannot fcntl(FD_CLOEXEC) on %d: %s", ctx_fd,
|
|
Packit Service |
a1973e |
strerror( errno ) );
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
/* setup asynchronous notification on the file descriptor */
|
|
Packit Service |
a1973e |
ret = fcntl( ctx_fd, F_SETFL, fcntl( ctx_fd, F_GETFL, 0 ) | O_ASYNC );
|
|
Packit Service |
a1973e |
if ( ret == -1 ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "cannot fcntl(O_ASYNC) on %d: %s", ctx_fd,
|
|
Packit Service |
a1973e |
strerror( errno ) );
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
/* get ownership of the descriptor */
|
|
Packit Service |
a1973e |
ret = fcntl( ctx_fd, F_SETOWN, mygettid( ) );
|
|
Packit Service |
a1973e |
if ( ret == -1 ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "cannot fcntl(F_SETOWN) on %d: %s", ctx_fd,
|
|
Packit Service |
a1973e |
strerror( errno ) );
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
/*
|
|
Packit Service |
a1973e |
* when you explicitely declare that you want a particular signal,
|
|
Packit Service |
a1973e |
* even with you use the default signal, the kernel will send more
|
|
Packit Service |
a1973e |
* information concerning the event to the signal handler.
|
|
Packit Service |
a1973e |
*
|
|
Packit Service |
a1973e |
* In particular, it will send the file descriptor from which the
|
|
Packit Service |
a1973e |
* event is originating which can be quite useful when monitoring
|
|
Packit Service |
a1973e |
* multiple tasks from a single thread.
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
ret = fcntl( ctx_fd, F_SETSIG, _perfmon2_vector.cmp_info.hardware_intr_sig );
|
|
Packit Service |
a1973e |
if ( ret == -1 ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "cannot fcntl(F_SETSIG,%d) on %d: %s",
|
|
Packit Service |
a1973e |
_perfmon2_vector.cmp_info.hardware_intr_sig, ctx_fd,
|
|
Packit Service |
a1973e |
strerror( errno ) );
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static int
|
|
Packit Service |
a1973e |
attach( hwd_control_state_t * ctl, unsigned long tid )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
pfarg_ctx_t *newctx = ( pfarg_ctx_t * ) malloc( sizeof ( pfarg_ctx_t ) );
|
|
Packit Service |
a1973e |
pfarg_load_t *load_args =
|
|
Packit Service |
a1973e |
( pfarg_load_t * ) malloc( sizeof ( pfarg_load_t ) );
|
|
Packit Service |
a1973e |
int ret;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ( newctx == NULL ) || ( load_args == NULL ) )
|
|
Packit Service |
a1973e |
return ( PAPI_ENOMEM );
|
|
Packit Service |
a1973e |
memset( newctx, 0x0, sizeof ( *newctx ) );
|
|
Packit Service |
a1973e |
memset( load_args, 0, sizeof ( *load_args ) );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Make sure the process exists and is being ptraced() */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
ret = ptrace( PTRACE_ATTACH, tid, NULL, NULL );
|
|
Packit Service |
a1973e |
if ( ret == 0 ) {
|
|
Packit Service |
a1973e |
ptrace( PTRACE_DETACH, tid, NULL, NULL );
|
|
Packit Service |
a1973e |
PAPIERROR( "Process/thread %d is not being ptraced", tid );
|
|
Packit Service |
a1973e |
free( newctx );
|
|
Packit Service |
a1973e |
free( load_args );
|
|
Packit Service |
a1973e |
return ( PAPI_EINVAL );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
/* If we get here, then we should hope that the process is being
|
|
Packit Service |
a1973e |
ptraced, if not, then we probably can't attach to it. */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ( ret == -1 ) && ( errno != EPERM ) ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "Process/thread %d cannot be ptraced: %s", tid,
|
|
Packit Service |
a1973e |
strerror( errno ) );
|
|
Packit Service |
a1973e |
free( newctx );
|
|
Packit Service |
a1973e |
free( load_args );
|
|
Packit Service |
a1973e |
return ( PAPI_EINVAL );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG( "PFM_CREATE_CONTEXT(%p,%p,%p,%d)\n", newctx, NULL, NULL, 0 );
|
|
Packit Service |
a1973e |
if ( ( ret = pfm_create_context( newctx, NULL, NULL, 0 ) ) == -1 ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "attach:pfm_create_context(): %s", strerror( errno ) );
|
|
Packit Service |
a1973e |
free( newctx );
|
|
Packit Service |
a1973e |
free( load_args );
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
SUBDBG( "PFM_CREATE_CONTEXT returned fd %d\n", ret );
|
|
Packit Service |
a1973e |
tune_up_fd( ret );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
( ( pfm_control_state_t * ) ctl )->ctx_fd = ret;
|
|
Packit Service |
a1973e |
( ( pfm_control_state_t * ) ctl )->ctx = newctx;
|
|
Packit Service |
a1973e |
load_args->load_pid = tid;
|
|
Packit Service |
a1973e |
( ( pfm_control_state_t * ) ctl )->load = load_args;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static int
|
|
Packit Service |
a1973e |
detach( hwd_context_t * ctx, hwd_control_state_t * ctl )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
int i;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
i = close( ( ( pfm_control_state_t * ) ctl )->ctx_fd );
|
|
Packit Service |
a1973e |
SUBDBG( "CLOSE fd %d returned %d\n",
|
|
Packit Service |
a1973e |
( ( pfm_control_state_t * ) ctl )->ctx_fd, i );
|
|
Packit Service |
a1973e |
(void) i;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Restore to main threads context */
|
|
Packit Service |
a1973e |
free( ( ( pfm_control_state_t * ) ctl )->ctx );
|
|
Packit Service |
a1973e |
( ( pfm_control_state_t * ) ctl )->ctx = &( ( pfm_context_t * ) ctx )->ctx;
|
|
Packit Service |
a1973e |
( ( pfm_control_state_t * ) ctl )->ctx_fd =
|
|
Packit Service |
a1973e |
( ( pfm_context_t * ) ctx )->ctx_fd;
|
|
Packit Service |
a1973e |
free( ( ( pfm_control_state_t * ) ctl )->load );
|
|
Packit Service |
a1973e |
( ( pfm_control_state_t * ) ctl )->load =
|
|
Packit Service |
a1973e |
&( ( pfm_context_t * ) ctx )->load;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static inline int
|
|
Packit Service |
a1973e |
set_domain( hwd_control_state_t * ctl0, int domain )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
pfm_control_state_t *ctl = ( pfm_control_state_t * ) ctl0;
|
|
Packit Service |
a1973e |
int mode = 0, did = 0;
|
|
Packit Service |
a1973e |
pfmlib_input_param_t *inp = &ctl->in;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( domain & PAPI_DOM_USER ) {
|
|
Packit Service |
a1973e |
did = 1;
|
|
Packit Service |
a1973e |
mode |= PFM_PLM3;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( domain & PAPI_DOM_KERNEL ) {
|
|
Packit Service |
a1973e |
did = 1;
|
|
Packit Service |
a1973e |
mode |= PFM_PLM0;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( domain & PAPI_DOM_SUPERVISOR ) {
|
|
Packit Service |
a1973e |
did = 1;
|
|
Packit Service |
a1973e |
mode |= PFM_PLM1;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( domain & PAPI_DOM_OTHER ) {
|
|
Packit Service |
a1973e |
did = 1;
|
|
Packit Service |
a1973e |
mode |= PFM_PLM2;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( !did )
|
|
Packit Service |
a1973e |
return ( PAPI_EINVAL );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
inp->pfp_dfl_plm = mode;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return ( compute_kernel_args( ctl ) );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static inline int
|
|
Packit Service |
a1973e |
set_granularity( hwd_control_state_t * this_state, int domain )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
( void ) this_state; /*unused */
|
|
Packit Service |
a1973e |
switch ( domain ) {
|
|
Packit Service |
a1973e |
case PAPI_GRN_PROCG:
|
|
Packit Service |
a1973e |
case PAPI_GRN_SYS:
|
|
Packit Service |
a1973e |
case PAPI_GRN_SYS_CPU:
|
|
Packit Service |
a1973e |
case PAPI_GRN_PROC:
|
|
Packit Service |
a1973e |
return PAPI_ECMP;
|
|
Packit Service |
a1973e |
case PAPI_GRN_THR:
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
default:
|
|
Packit Service |
a1973e |
return PAPI_EINVAL;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
return PAPI_OK;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* This function should tell your kernel extension that your children
|
|
Packit Service |
a1973e |
inherit performance register information and propagate the values up
|
|
Packit Service |
a1973e |
upon child exit and parent wait. */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static inline int
|
|
Packit Service |
a1973e |
set_inherit( int arg )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
( void ) arg; /*unused */
|
|
Packit Service |
a1973e |
return PAPI_ECMP;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static int
|
|
Packit Service |
a1973e |
get_string_from_file( char *file, char *str, int len )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
FILE *f = fopen( file, "r" );
|
|
Packit Service |
a1973e |
char buf[PAPI_HUGE_STR_LEN];
|
|
Packit Service |
a1973e |
if ( f == NULL ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "fopen(%s): %s", file, strerror( errno ) );
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
if ( fscanf( f, "%s\n", buf ) != 1 ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "fscanf(%s, %%s\\n): Unable to scan 1 token", file );
|
|
Packit Service |
a1973e |
fclose( f );
|
|
Packit Service |
a1973e |
return PAPI_ESYS;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
strncpy( str, buf, ( len > PAPI_HUGE_STR_LEN ? PAPI_HUGE_STR_LEN : len ) );
|
|
Packit Service |
a1973e |
fclose( f );
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
_papi_pfm_init_component( int cidx )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
int retval;
|
|
Packit Service |
a1973e |
char buf[PAPI_HUGE_STR_LEN];
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* The following checks the PFMLIB version
|
|
Packit Service |
a1973e |
against the perfmon2 kernel version... */
|
|
Packit Service |
a1973e |
strncpy( _perfmon2_vector.cmp_info.support_version, buf,
|
|
Packit Service |
a1973e |
sizeof ( _perfmon2_vector.cmp_info.support_version ) );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
retval = get_string_from_file( "/sys/kernel/perfmon/version",
|
|
Packit Service |
a1973e |
_perfmon2_vector.cmp_info.kernel_version,
|
|
Packit Service |
a1973e |
sizeof ( _perfmon2_vector.cmp_info.kernel_version ) );
|
|
Packit Service |
a1973e |
if ( retval != PAPI_OK ) {
|
|
Packit Service |
a1973e |
strncpy(_perfmon2_vector.cmp_info.disabled_reason,
|
|
Packit Service |
a1973e |
"/sys/kernel/perfmon/version not found",PAPI_MAX_STR_LEN);
|
|
Packit Service |
a1973e |
return retval;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#ifdef PFM_VERSION
|
|
Packit Service |
a1973e |
sprintf( buf, "%d.%d", PFM_VERSION_MAJOR( PFM_VERSION ),
|
|
Packit Service |
a1973e |
PFM_VERSION_MINOR( PFM_VERSION ) );
|
|
Packit Service |
a1973e |
SUBDBG( "Perfmon2 library versions...kernel: %s library: %s\n",
|
|
Packit Service |
a1973e |
_perfmon2_vector.cmp_info.kernel_version, buf );
|
|
Packit Service |
a1973e |
if ( strcmp( _perfmon2_vector.cmp_info.kernel_version, buf ) != 0 ) {
|
|
Packit Service |
a1973e |
/* do a little exception processing; 81 is compatible with 80 */
|
|
Packit Service |
a1973e |
if ( !( ( PFM_VERSION_MINOR( PFM_VERSION ) == 81 ) &&
|
|
Packit Service |
a1973e |
( strncmp( _perfmon2_vector.cmp_info.kernel_version, "2.8", 3 ) ==
|
|
Packit Service |
a1973e |
0 ) ) ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "Version mismatch of libpfm: compiled %s "
|
|
Packit Service |
a1973e |
"vs. installed %s\n",
|
|
Packit Service |
a1973e |
buf, _perfmon2_vector.cmp_info.kernel_version );
|
|
Packit Service |
a1973e |
return PAPI_ESYS;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
_perfmon2_vector.cmp_info.hardware_intr_sig = SIGRTMIN + 2,
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Run the libpfm-specific setup */
|
|
Packit Service |
a1973e |
retval=_papi_libpfm_init(&_perfmon2_vector, cidx);
|
|
Packit Service |
a1973e |
if (retval) return retval;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Load the module, find out if any PMC's/PMD's are off limits */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Perfmon2 timeouts are based on the clock tick, we need to check
|
|
Packit Service |
a1973e |
them otherwise it will complain at us when we multiplex */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
unsigned long min_timeout_ns;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
struct timespec ts;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( syscall( __NR_clock_getres, CLOCK_REALTIME, &ts ) == -1 ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "Could not detect proper HZ rate, multiplexing may fail\n" );
|
|
Packit Service |
a1973e |
min_timeout_ns = 10000000;
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
min_timeout_ns = ts.tv_nsec;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* This will fail if we've done timeout detection wrong */
|
|
Packit Service |
a1973e |
retval=detect_timeout_and_unavail_pmu_regs( &_perfmon2_pfm_unavailable_pmcs,
|
|
Packit Service |
a1973e |
&_perfmon2_pfm_unavailable_pmds,
|
|
Packit Service |
a1973e |
&min_timeout_ns );
|
|
Packit Service |
a1973e |
if ( retval != PAPI_OK ) {
|
|
Packit Service |
a1973e |
return ( retval );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( _papi_hwi_system_info.hw_info.vendor == PAPI_VENDOR_IBM ) {
|
|
Packit Service |
a1973e |
/* powerpc */
|
|
Packit Service |
a1973e |
_perfmon2_vector.cmp_info.available_domains |= PAPI_DOM_KERNEL |
|
|
Packit Service |
a1973e |
PAPI_DOM_SUPERVISOR;
|
|
Packit Service |
a1973e |
if (strcmp(_papi_hwi_system_info.hw_info.model_string, "POWER6" ) == 0) {
|
|
Packit Service |
a1973e |
_perfmon2_vector.cmp_info.default_domain = PAPI_DOM_USER |
|
|
Packit Service |
a1973e |
PAPI_DOM_KERNEL |
|
|
Packit Service |
a1973e |
PAPI_DOM_SUPERVISOR;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
_perfmon2_vector.cmp_info.available_domains |= PAPI_DOM_KERNEL;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( _papi_hwi_system_info.hw_info.vendor == PAPI_VENDOR_SUN ) {
|
|
Packit Service |
a1973e |
switch ( _perfmon2_pfm_pmu_type ) {
|
|
Packit Service |
a1973e |
#ifdef PFMLIB_SPARC_ULTRA12_PMU
|
|
Packit Service |
a1973e |
case PFMLIB_SPARC_ULTRA12_PMU:
|
|
Packit Service |
a1973e |
case PFMLIB_SPARC_ULTRA3_PMU:
|
|
Packit Service |
a1973e |
case PFMLIB_SPARC_ULTRA3I_PMU:
|
|
Packit Service |
a1973e |
case PFMLIB_SPARC_ULTRA3PLUS_PMU:
|
|
Packit Service |
a1973e |
case PFMLIB_SPARC_ULTRA4PLUS_PMU:
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
default:
|
|
Packit Service |
a1973e |
_perfmon2_vector.cmp_info.available_domains |=
|
|
Packit Service |
a1973e |
PAPI_DOM_SUPERVISOR;
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( _papi_hwi_system_info.hw_info.vendor == PAPI_VENDOR_CRAY ) {
|
|
Packit Service |
a1973e |
_perfmon2_vector.cmp_info.available_domains |= PAPI_DOM_OTHER;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ( _papi_hwi_system_info.hw_info.vendor == PAPI_VENDOR_INTEL ) ||
|
|
Packit Service |
a1973e |
( _papi_hwi_system_info.hw_info.vendor == PAPI_VENDOR_AMD ) ) {
|
|
Packit Service |
a1973e |
_perfmon2_vector.cmp_info.fast_counter_read = 1;
|
|
Packit Service |
a1973e |
_perfmon2_vector.cmp_info.fast_real_timer = 1;
|
|
Packit Service |
a1973e |
_perfmon2_vector.cmp_info.cntr_umasks = 1;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return PAPI_OK;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
_papi_pfm_shutdown_component( )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
return PAPI_OK;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static int
|
|
Packit Service |
a1973e |
_papi_pfm_init_thread( hwd_context_t * thr_ctx )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
pfarg_load_t load_args;
|
|
Packit Service |
a1973e |
pfarg_ctx_t newctx;
|
|
Packit Service |
a1973e |
int ret, ctx_fd;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#if defined(USE_PROC_PTTIMER)
|
|
Packit Service |
a1973e |
ret = init_proc_thread_timer( thr_ctx );
|
|
Packit Service |
a1973e |
if ( ret != PAPI_OK )
|
|
Packit Service |
a1973e |
return ( ret );
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
memset( &newctx, 0, sizeof ( newctx ) );
|
|
Packit Service |
a1973e |
memset( &load_args, 0, sizeof ( load_args ) );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ( ret = pfm_create_context( &newctx, NULL, NULL, 0 ) ) == -1 ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "pfm_create_context(): %s",
|
|
Packit Service |
a1973e |
strerror( errno ) );
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
SUBDBG( "PFM_CREATE_CONTEXT returned fd %d\n", ret );
|
|
Packit Service |
a1973e |
tune_up_fd( ret );
|
|
Packit Service |
a1973e |
ctx_fd = ret;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
memcpy( &( ( pfm_context_t * ) thr_ctx )->ctx, &newctx, sizeof ( newctx ) );
|
|
Packit Service |
a1973e |
( ( pfm_context_t * ) thr_ctx )->ctx_fd = ctx_fd;
|
|
Packit Service |
a1973e |
load_args.load_pid = mygettid( );
|
|
Packit Service |
a1973e |
memcpy( &( ( pfm_context_t * ) thr_ctx )->load, &load_args,
|
|
Packit Service |
a1973e |
sizeof ( load_args ) );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* reset the hardware counters */
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
_papi_pfm_reset( hwd_context_t * ctx, hwd_control_state_t * ctl )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
unsigned int i;
|
|
Packit Service |
a1973e |
int ret;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Read could have clobbered the values */
|
|
Packit Service |
a1973e |
for ( i = 0; i < ( ( pfm_control_state_t * ) ctl )->in.pfp_event_count;
|
|
Packit Service |
a1973e |
i++ ) {
|
|
Packit Service |
a1973e |
if ( ( ( pfm_control_state_t * ) ctl )->pd[i].
|
|
Packit Service |
a1973e |
reg_flags & PFM_REGFL_OVFL_NOTIFY )
|
|
Packit Service |
a1973e |
( ( pfm_control_state_t * ) ctl )->pd[i].reg_value =
|
|
Packit Service |
a1973e |
( ( pfm_control_state_t * ) ctl )->pd[i].reg_long_reset;
|
|
Packit Service |
a1973e |
else
|
|
Packit Service |
a1973e |
( ( pfm_control_state_t * ) ctl )->pd[i].reg_value = 0ULL;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
ret =
|
|
Packit Service |
a1973e |
_papi_pfm_write_pmds( ( pfm_context_t * ) ctx,
|
|
Packit Service |
a1973e |
( pfm_control_state_t * ) ctl );
|
|
Packit Service |
a1973e |
if ( ret != PAPI_OK )
|
|
Packit Service |
a1973e |
return PAPI_ESYS;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* write(set) the hardware counters */
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
_papi_pfm_write( hwd_context_t * ctx, hwd_control_state_t * ctl,
|
|
Packit Service |
a1973e |
long long *from )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
unsigned int i;
|
|
Packit Service |
a1973e |
int ret;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Read could have clobbered the values */
|
|
Packit Service |
a1973e |
for ( i = 0; i < ( ( pfm_control_state_t * ) ctl )->in.pfp_event_count;
|
|
Packit Service |
a1973e |
i++ ) {
|
|
Packit Service |
a1973e |
if ( ( ( pfm_control_state_t * ) ctl )->pd[i].
|
|
Packit Service |
a1973e |
reg_flags & PFM_REGFL_OVFL_NOTIFY )
|
|
Packit Service |
a1973e |
( ( pfm_control_state_t * ) ctl )->pd[i].reg_value =
|
|
Packit Service |
a1973e |
from[i] +
|
|
Packit Service |
a1973e |
( ( pfm_control_state_t * ) ctl )->pd[i].reg_long_reset;
|
|
Packit Service |
a1973e |
else
|
|
Packit Service |
a1973e |
( ( pfm_control_state_t * ) ctl )->pd[i].reg_value = from[i];
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
ret =
|
|
Packit Service |
a1973e |
_papi_pfm_write_pmds( ( pfm_context_t * ) ctx,
|
|
Packit Service |
a1973e |
( pfm_control_state_t * ) ctl );
|
|
Packit Service |
a1973e |
if ( ret != PAPI_OK )
|
|
Packit Service |
a1973e |
return PAPI_ESYS;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
_papi_pfm_read( hwd_context_t * ctx0, hwd_control_state_t * ctl0,
|
|
Packit Service |
a1973e |
long long **events, int flags )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
( void ) flags; /*unused */
|
|
Packit Service |
a1973e |
unsigned int i;
|
|
Packit Service |
a1973e |
int ret;
|
|
Packit Service |
a1973e |
long long tot_runs = 0LL;
|
|
Packit Service |
a1973e |
pfm_control_state_t *ctl = ( pfm_control_state_t * ) ctl0;
|
|
Packit Service |
a1973e |
pfm_context_t *ctx = ( pfm_context_t * ) ctx0;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
ret = _papi_pfm_read_pmds( ctx, ctl );
|
|
Packit Service |
a1973e |
if ( ret != PAPI_OK )
|
|
Packit Service |
a1973e |
return PAPI_ESYS;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Copy the values over */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for ( i = 0; i < ctl->in.pfp_event_count; i++ ) {
|
|
Packit Service |
a1973e |
if ( ctl->pd[i].reg_flags & PFM_REGFL_OVFL_NOTIFY )
|
|
Packit Service |
a1973e |
ctl->counts[i] = ctl->pd[i].reg_value - ctl->pd[i].reg_long_reset;
|
|
Packit Service |
a1973e |
else
|
|
Packit Service |
a1973e |
ctl->counts[i] = ctl->pd[i].reg_value;
|
|
Packit Service |
a1973e |
SUBDBG( "PMD[%d] = %lld (LLD),%llu (LLU)\n", i,
|
|
Packit Service |
a1973e |
( unsigned long long ) ctl->counts[i],
|
|
Packit Service |
a1973e |
( unsigned long long ) ctl->pd[i].reg_value );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
*events = ctl->counts;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* If we're not multiplexing, bail now */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ctl->num_sets == 1 )
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* If we're multiplexing, get the scaling information */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG( "PFM_GETINFO_EVTSETS(%d,%p,%d)\n", ctl->ctx_fd, ctl->setinfo,
|
|
Packit Service |
a1973e |
ctl->num_sets );
|
|
Packit Service |
a1973e |
if ( ( ret =
|
|
Packit Service |
a1973e |
pfm_getinfo_evtsets( ctl->ctx_fd, ctl->setinfo, ctl->num_sets ) ) ) {
|
|
Packit Service |
a1973e |
DEBUGCALL( DEBUG_SUBSTRATE,
|
|
Packit Service |
a1973e |
dump_setinfo( ctl->setinfo, ctl->num_sets ) );
|
|
Packit Service |
a1973e |
PAPIERROR( "pfm_getinfo_evtsets(%d,%p,%d): %s", ctl->ctx_fd,
|
|
Packit Service |
a1973e |
ctl->setinfo, ctl->num_sets, strerror( ret ) );
|
|
Packit Service |
a1973e |
*events = NULL;
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
DEBUGCALL( DEBUG_SUBSTRATE, dump_setinfo( ctl->setinfo, ctl->num_sets ) );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Add up the number of total runs */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for ( i = 0; i < ( unsigned int ) ctl->num_sets; i++ )
|
|
Packit Service |
a1973e |
tot_runs += ctl->setinfo[i].set_runs;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Now scale the values */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for ( i = 0; i < ctl->in.pfp_event_count; i++ ) {
|
|
Packit Service |
a1973e |
SUBDBG
|
|
Packit Service |
a1973e |
( "Counter %d is in set %d ran %llu of %llu times, old count %lld.\n",
|
|
Packit Service |
a1973e |
i, ctl->pd[i].reg_set,
|
|
Packit Service |
a1973e |
( unsigned long long ) ctl->setinfo[ctl->pd[i].reg_set].set_runs,
|
|
Packit Service |
a1973e |
( unsigned long long ) tot_runs, ctl->counts[i] );
|
|
Packit Service |
a1973e |
if ( ctl->setinfo[ctl->pd[i].reg_set].set_runs )
|
|
Packit Service |
a1973e |
ctl->counts[i] =
|
|
Packit Service |
a1973e |
( ctl->counts[i] * tot_runs ) /
|
|
Packit Service |
a1973e |
ctl->setinfo[ctl->pd[i].reg_set].set_runs;
|
|
Packit Service |
a1973e |
else {
|
|
Packit Service |
a1973e |
ctl->counts[i] = 0;
|
|
Packit Service |
a1973e |
SUBDBG( "Set %lld didn't run!!!!\n",
|
|
Packit Service |
a1973e |
( unsigned long long ) ctl->pd[i].reg_set );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
SUBDBG( "Counter %d, new count %lld.\n", i, ctl->counts[i] );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return PAPI_OK;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#if defined(__crayxt)
|
|
Packit Service |
a1973e |
int _papi_hwd_start_create_context = 0; /* CrayPat checkpoint support */
|
|
Packit Service |
a1973e |
#endif /* XT */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
_papi_pfm_start( hwd_context_t * ctx0, hwd_control_state_t * ctl0 )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
unsigned int i;
|
|
Packit Service |
a1973e |
int ret;
|
|
Packit Service |
a1973e |
pfm_control_state_t *ctl = ( pfm_control_state_t * ) ctl0;
|
|
Packit Service |
a1973e |
pfm_context_t *ctx = ( pfm_context_t * ) ctx0;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#if defined(__crayxt)
|
|
Packit Service |
a1973e |
if ( _papi_hwd_start_create_context ) {
|
|
Packit Service |
a1973e |
pfarg_ctx_t tmp;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
memset( &tmp, 0, sizeof ( tmp ) );
|
|
Packit Service |
a1973e |
if ( ( ret = pfm_create_context( &tmp, NULL, NULL, 0 ) ) == -1 ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "_papi_hwd_init:pfm_create_context(): %s",
|
|
Packit Service |
a1973e |
strerror( errno ) );
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
tune_up_fd( ret );
|
|
Packit Service |
a1973e |
ctl->ctx_fd = ctx->ctx_fd = ret;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
#endif /* XT */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ctl->num_sets > 1 ) {
|
|
Packit Service |
a1973e |
SUBDBG( "PFM_CREATE_EVTSETS(%d,%p,%d)\n", ctl->ctx_fd, ctl->set,
|
|
Packit Service |
a1973e |
ctl->num_sets );
|
|
Packit Service |
a1973e |
if ( ( ret =
|
|
Packit Service |
a1973e |
pfm_create_evtsets( ctl->ctx_fd, ctl->set,
|
|
Packit Service |
a1973e |
ctl->num_sets ) ) != PFMLIB_SUCCESS ) {
|
|
Packit Service |
a1973e |
DEBUGCALL( DEBUG_SUBSTRATE, dump_sets( ctl->set, ctl->num_sets ) );
|
|
Packit Service |
a1973e |
PAPIERROR( "pfm_create_evtsets(%d,%p,%d): errno=%d %s",
|
|
Packit Service |
a1973e |
ctl->ctx_fd, ctl->set, ctl->num_sets, errno,
|
|
Packit Service |
a1973e |
strerror( ret ) );
|
|
Packit Service |
a1973e |
perror( "pfm_create_evtsets" );
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
DEBUGCALL( DEBUG_SUBSTRATE, dump_sets( ctl->set, ctl->num_sets ) );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/*
|
|
Packit Service |
a1973e |
* Now program the registers
|
|
Packit Service |
a1973e |
*
|
|
Packit Service |
a1973e |
* We don't use the same variable to indicate the number of elements passed to
|
|
Packit Service |
a1973e |
* the kernel because, as we said earlier, pc may contain more elements than
|
|
Packit Service |
a1973e |
* the number of events (pmd) we specified, i.e., contains more than counting
|
|
Packit Service |
a1973e |
* monitors.
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
ret = _papi_pfm_write_pmcs( ctx, ctl );
|
|
Packit Service |
a1973e |
if ( ret != PAPI_OK )
|
|
Packit Service |
a1973e |
return PAPI_ESYS;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Set counters to zero as per PAPI_start man page, unless it is set to overflow */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for ( i = 0; i < ctl->in.pfp_event_count; i++ )
|
|
Packit Service |
a1973e |
if ( !( ctl->pd[i].reg_flags & PFM_REGFL_OVFL_NOTIFY ) )
|
|
Packit Service |
a1973e |
ctl->pd[i].reg_value = 0ULL;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/*
|
|
Packit Service |
a1973e |
* To be read, each PMD must be either written or declared
|
|
Packit Service |
a1973e |
* as being part of a sample (reg_smpl_pmds)
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
ret = _papi_pfm_write_pmds( ctx, ctl );
|
|
Packit Service |
a1973e |
if ( ret != PAPI_OK )
|
|
Packit Service |
a1973e |
return PAPI_ESYS;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG( "PFM_LOAD_CONTEXT(%d,%p(%u))\n", ctl->ctx_fd, ctl->load,
|
|
Packit Service |
a1973e |
ctl->load->load_pid );
|
|
Packit Service |
a1973e |
if ( ( ret = pfm_load_context( ctl->ctx_fd, ctl->load ) ) ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "pfm_load_context(%d,%p(%u)): %s", ctl->ctx_fd, ctl->load,
|
|
Packit Service |
a1973e |
ctl->load->load_pid, strerror( ret ) );
|
|
Packit Service |
a1973e |
return PAPI_ESYS;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG( "PFM_START(%d,%p)\n", ctl->ctx_fd, NULL );
|
|
Packit Service |
a1973e |
if ( ( ret = pfm_start( ctl->ctx_fd, NULL ) ) ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "pfm_start(%d): %s", ctl->ctx_fd, strerror( ret ) );
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
return PAPI_OK;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
_papi_pfm_stop( hwd_context_t * ctx0, hwd_control_state_t * ctl0 )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
( void ) ctx0; /*unused */
|
|
Packit Service |
a1973e |
int ret;
|
|
Packit Service |
a1973e |
pfm_control_state_t *ctl = ( pfm_control_state_t * ) ctl0;
|
|
Packit Service |
a1973e |
// pfm_context_t *ctx = (pfm_context_t *)ctx0;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG( "PFM_STOP(%d)\n", ctl->ctx_fd );
|
|
Packit Service |
a1973e |
if ( ( ret = pfm_stop( ctl->ctx_fd ) ) ) {
|
|
Packit Service |
a1973e |
/* If this thread is attached to another thread, and that thread
|
|
Packit Service |
a1973e |
has exited, we can safely discard the error here. */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ( ret == PFMLIB_ERR_NOTSUPP ) &&
|
|
Packit Service |
a1973e |
( ctl->load->load_pid != ( unsigned int ) mygettid( ) ) )
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
PAPIERROR( "pfm_stop(%d): %s", ctl->ctx_fd, strerror( ret ) );
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG( "PFM_UNLOAD_CONTEXT(%d) (tid %u)\n", ctl->ctx_fd,
|
|
Packit Service |
a1973e |
ctl->load->load_pid );
|
|
Packit Service |
a1973e |
if ( ( ret = pfm_unload_context( ctl->ctx_fd ) ) ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "pfm_unload_context(%d): %s", ctl->ctx_fd, strerror( ret ) );
|
|
Packit Service |
a1973e |
return PAPI_ESYS;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ctl->num_sets > 1 ) {
|
|
Packit Service |
a1973e |
static pfarg_setdesc_t set = { 0, 0, 0, 0, {0, 0, 0, 0, 0, 0} };
|
|
Packit Service |
a1973e |
/* Delete the high sets */
|
|
Packit Service |
a1973e |
SUBDBG( "PFM_DELETE_EVTSETS(%d,%p,%d)\n", ctl->ctx_fd, &ctl->set[1],
|
|
Packit Service |
a1973e |
ctl->num_sets - 1 );
|
|
Packit Service |
a1973e |
if ( ( ret =
|
|
Packit Service |
a1973e |
pfm_delete_evtsets( ctl->ctx_fd, &ctl->set[1],
|
|
Packit Service |
a1973e |
ctl->num_sets - 1 ) ) != PFMLIB_SUCCESS ) {
|
|
Packit Service |
a1973e |
DEBUGCALL( DEBUG_SUBSTRATE,
|
|
Packit Service |
a1973e |
dump_sets( &ctl->set[1], ctl->num_sets - 1 ) );
|
|
Packit Service |
a1973e |
PAPIERROR( "pfm_delete_evtsets(%d,%p,%d): %s", ctl->ctx_fd,
|
|
Packit Service |
a1973e |
&ctl->set[1], ctl->num_sets - 1, strerror( ret ) );
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
DEBUGCALL( DEBUG_SUBSTRATE,
|
|
Packit Service |
a1973e |
dump_sets( &ctl->set[1], ctl->num_sets - 1 ) );
|
|
Packit Service |
a1973e |
/* Reprogram the 0 set */
|
|
Packit Service |
a1973e |
SUBDBG( "PFM_CREATE_EVTSETS(%d,%p,%d)\n", ctl->ctx_fd, &set, 1 );
|
|
Packit Service |
a1973e |
if ( ( ret =
|
|
Packit Service |
a1973e |
pfm_create_evtsets( ctl->ctx_fd, &set,
|
|
Packit Service |
a1973e |
1 ) ) != PFMLIB_SUCCESS ) {
|
|
Packit Service |
a1973e |
DEBUGCALL( DEBUG_SUBSTRATE, dump_sets( &set, 1 ) );
|
|
Packit Service |
a1973e |
PAPIERROR( "pfm_create_evtsets(%d,%p,%d): %s", ctl->ctx_fd, &set,
|
|
Packit Service |
a1973e |
ctl->num_sets, strerror( ret ) );
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
DEBUGCALL( DEBUG_SUBSTRATE, dump_sets( &set, 1 ) );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return PAPI_OK;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static inline int
|
|
Packit Service |
a1973e |
round_requested_ns( int ns )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
if ( ns <= _papi_os_info.itimer_res_ns ) {
|
|
Packit Service |
a1973e |
return _papi_os_info.itimer_res_ns;
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
int leftover_ns = ns % _papi_os_info.itimer_res_ns;
|
|
Packit Service |
a1973e |
return ( ns - leftover_ns + _papi_os_info.itimer_res_ns );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
_papi_pfm_ctl( hwd_context_t * ctx, int code, _papi_int_option_t * option )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
switch ( code ) {
|
|
Packit Service |
a1973e |
case PAPI_MULTIPLEX:
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
option->multiplex.ns = round_requested_ns( option->multiplex.ns );
|
|
Packit Service |
a1973e |
( ( pfm_control_state_t * ) ( option->multiplex.ESI->ctl_state ) )->
|
|
Packit Service |
a1973e |
multiplexed = option->multiplex.ns;
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
case PAPI_ATTACH:
|
|
Packit Service |
a1973e |
return ( attach
|
|
Packit Service |
a1973e |
( ( pfm_control_state_t * ) ( option->attach.ESI->ctl_state ),
|
|
Packit Service |
a1973e |
option->attach.tid ) );
|
|
Packit Service |
a1973e |
case PAPI_DETACH:
|
|
Packit Service |
a1973e |
return ( detach
|
|
Packit Service |
a1973e |
( ctx,
|
|
Packit Service |
a1973e |
( pfm_control_state_t * ) ( option->attach.ESI->
|
|
Packit Service |
a1973e |
ctl_state ) ) );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
case PAPI_DOMAIN:
|
|
Packit Service |
a1973e |
return ( set_domain
|
|
Packit Service |
a1973e |
( ( pfm_control_state_t * ) ( option->domain.ESI->ctl_state ),
|
|
Packit Service |
a1973e |
option->domain.domain ) );
|
|
Packit Service |
a1973e |
case PAPI_GRANUL:
|
|
Packit Service |
a1973e |
return ( set_granularity
|
|
Packit Service |
a1973e |
( ( pfm_control_state_t * ) ( option->granularity.ESI->
|
|
Packit Service |
a1973e |
ctl_state ),
|
|
Packit Service |
a1973e |
option->granularity.granularity ) );
|
|
Packit Service |
a1973e |
#if 0
|
|
Packit Service |
a1973e |
case PAPI_DATA_ADDRESS:
|
|
Packit Service |
a1973e |
ret =
|
|
Packit Service |
a1973e |
set_default_domain( ( pfm_control_state_t * ) ( option->
|
|
Packit Service |
a1973e |
address_range.ESI->
|
|
Packit Service |
a1973e |
ctl_state ),
|
|
Packit Service |
a1973e |
option->address_range.domain );
|
|
Packit Service |
a1973e |
if ( ret != PAPI_OK )
|
|
Packit Service |
a1973e |
return ( ret );
|
|
Packit Service |
a1973e |
set_drange( ctx,
|
|
Packit Service |
a1973e |
( pfm_control_state_t * ) ( option->address_range.ESI->
|
|
Packit Service |
a1973e |
ctl_state ), option );
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
case PAPI_INSTR_ADDRESS:
|
|
Packit Service |
a1973e |
ret =
|
|
Packit Service |
a1973e |
set_default_domain( ( pfm_control_state_t * ) ( option->
|
|
Packit Service |
a1973e |
address_range.ESI->
|
|
Packit Service |
a1973e |
ctl_state ),
|
|
Packit Service |
a1973e |
option->address_range.domain );
|
|
Packit Service |
a1973e |
if ( ret != PAPI_OK )
|
|
Packit Service |
a1973e |
return ( ret );
|
|
Packit Service |
a1973e |
set_irange( ctx,
|
|
Packit Service |
a1973e |
( pfm_control_state_t * ) ( option->address_range.ESI->
|
|
Packit Service |
a1973e |
ctl_state ), option );
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
case PAPI_DEF_ITIMER:
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
/* flags are currently ignored, eventually the flags will be able
|
|
Packit Service |
a1973e |
to specify whether or not we use POSIX itimers (clock_gettimer) */
|
|
Packit Service |
a1973e |
if ( ( option->itimer.itimer_num == ITIMER_REAL ) &&
|
|
Packit Service |
a1973e |
( option->itimer.itimer_sig != SIGALRM ) )
|
|
Packit Service |
a1973e |
return PAPI_EINVAL;
|
|
Packit Service |
a1973e |
if ( ( option->itimer.itimer_num == ITIMER_VIRTUAL ) &&
|
|
Packit Service |
a1973e |
( option->itimer.itimer_sig != SIGVTALRM ) )
|
|
Packit Service |
a1973e |
return PAPI_EINVAL;
|
|
Packit Service |
a1973e |
if ( ( option->itimer.itimer_num == ITIMER_PROF ) &&
|
|
Packit Service |
a1973e |
( option->itimer.itimer_sig != SIGPROF ) )
|
|
Packit Service |
a1973e |
return PAPI_EINVAL;
|
|
Packit Service |
a1973e |
if ( option->itimer.ns > 0 )
|
|
Packit Service |
a1973e |
option->itimer.ns = round_requested_ns( option->itimer.ns );
|
|
Packit Service |
a1973e |
/* At this point, we assume the user knows what he or
|
|
Packit Service |
a1973e |
she is doing, they maybe doing something arch specific */
|
|
Packit Service |
a1973e |
return PAPI_OK;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
case PAPI_DEF_MPX_NS:
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
option->multiplex.ns = round_requested_ns( option->multiplex.ns );
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
case PAPI_DEF_ITIMER_NS:
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
option->itimer.ns = round_requested_ns( option->itimer.ns );
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
default:
|
|
Packit Service |
a1973e |
return ( PAPI_ENOSUPP );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
_papi_pfm_shutdown( hwd_context_t * ctx0 )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
pfm_context_t *ctx = ( pfm_context_t * ) ctx0;
|
|
Packit Service |
a1973e |
int ret;
|
|
Packit Service |
a1973e |
#if defined(USE_PROC_PTTIMER)
|
|
Packit Service |
a1973e |
close( ctx->stat_fd );
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
ret = close( ctx->ctx_fd );
|
|
Packit Service |
a1973e |
SUBDBG( "CLOSE fd %d returned %d\n", ctx->ctx_fd, ret );
|
|
Packit Service |
a1973e |
(void) ret;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* This will need to be modified for the Pentium IV */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static inline int
|
|
Packit Service |
a1973e |
find_profile_index( EventSetInfo_t * ESI, int pmd, int *flags,
|
|
Packit Service |
a1973e |
unsigned int *native_index, int *profile_index )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
int pos, esi_index, count;
|
|
Packit Service |
a1973e |
pfm_control_state_t *ctl = ( pfm_control_state_t * ) ESI->ctl_state;
|
|
Packit Service |
a1973e |
pfarg_pmd_t *pd;
|
|
Packit Service |
a1973e |
unsigned int i;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
pd = ctl->pd;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Find virtual PMD index, the one we actually read from the physical PMD number that
|
|
Packit Service |
a1973e |
overflowed. This index is the one related to the profile buffer. */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for ( i = 0; i < ctl->in.pfp_event_count; i++ ) {
|
|
Packit Service |
a1973e |
if ( pd[i].reg_num == pmd ) {
|
|
Packit Service |
a1973e |
SUBDBG( "Physical PMD %d is Virtual PMD %d\n", pmd, i );
|
|
Packit Service |
a1973e |
pmd = i;
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG( "(%p,%d,%p)\n", ESI, pmd, index );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for ( count = 0; count < ESI->profile.event_counter; count++ ) {
|
|
Packit Service |
a1973e |
/* Find offset of PMD that gets read from the kernel */
|
|
Packit Service |
a1973e |
esi_index = ESI->profile.EventIndex[count];
|
|
Packit Service |
a1973e |
pos = ESI->EventInfoArray[esi_index].pos[0];
|
|
Packit Service |
a1973e |
SUBDBG( "Examining event at ESI index %d, PMD position %d\n", esi_index,
|
|
Packit Service |
a1973e |
pos );
|
|
Packit Service |
a1973e |
// PMU_FIRST_COUNTER
|
|
Packit Service |
a1973e |
if ( pos == pmd ) {
|
|
Packit Service |
a1973e |
*profile_index = count;
|
|
Packit Service |
a1973e |
*native_index =
|
|
Packit Service |
a1973e |
ESI->NativeInfoArray[pos].ni_event & PAPI_NATIVE_AND_MASK;
|
|
Packit Service |
a1973e |
*flags = ESI->profile.flags;
|
|
Packit Service |
a1973e |
SUBDBG( "Native event %d is at profile index %d, flags %d\n",
|
|
Packit Service |
a1973e |
*native_index, *profile_index, *flags );
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
PAPIERROR( "wrong count: %d vs. ESI->profile.event_counter %d", count,
|
|
Packit Service |
a1973e |
ESI->profile.event_counter );
|
|
Packit Service |
a1973e |
return ( PAPI_EBUG );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#if defined(__ia64__)
|
|
Packit Service |
a1973e |
static inline int
|
|
Packit Service |
a1973e |
is_montecito_and_dear( unsigned int native_index )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
if ( _perfmon2_pfm_pmu_type == PFMLIB_MONTECITO_PMU ) {
|
|
Packit Service |
a1973e |
if ( pfm_mont_is_dear( native_index ) )
|
|
Packit Service |
a1973e |
return ( 1 );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
return ( 0 );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
static inline int
|
|
Packit Service |
a1973e |
is_montecito_and_iear( unsigned int native_index )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
if ( _perfmon2_pfm_pmu_type == PFMLIB_MONTECITO_PMU ) {
|
|
Packit Service |
a1973e |
if ( pfm_mont_is_iear( native_index ) )
|
|
Packit Service |
a1973e |
return ( 1 );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
return ( 0 );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
static inline int
|
|
Packit Service |
a1973e |
is_itanium2_and_dear( unsigned int native_index )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
if ( _perfmon2_pfm_pmu_type == PFMLIB_ITANIUM2_PMU ) {
|
|
Packit Service |
a1973e |
if ( pfm_ita2_is_dear( native_index ) )
|
|
Packit Service |
a1973e |
return ( 1 );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
return ( 0 );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
static inline int
|
|
Packit Service |
a1973e |
is_itanium2_and_iear( unsigned int native_index )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
if ( _perfmon2_pfm_pmu_type == PFMLIB_ITANIUM2_PMU ) {
|
|
Packit Service |
a1973e |
if ( pfm_ita2_is_iear( native_index ) )
|
|
Packit Service |
a1973e |
return ( 1 );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
return ( 0 );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#define BPL (sizeof(uint64_t)<<3)
|
|
Packit Service |
a1973e |
#define LBPL 6
|
|
Packit Service |
a1973e |
static inline void
|
|
Packit Service |
a1973e |
pfm_bv_set( uint64_t * bv, uint16_t rnum )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
bv[rnum >> LBPL] |= 1UL << ( rnum & ( BPL - 1 ) );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static inline int
|
|
Packit Service |
a1973e |
setup_ear_event( unsigned int native_index, pfarg_pmd_t * pd, int flags )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
( void ) flags; /*unused */
|
|
Packit Service |
a1973e |
#if defined(__ia64__)
|
|
Packit Service |
a1973e |
if ( _perfmon2_pfm_pmu_type == PFMLIB_MONTECITO_PMU ) {
|
|
Packit Service |
a1973e |
if ( pfm_mont_is_dear( native_index ) ) { /* 2,3,17 */
|
|
Packit Service |
a1973e |
pfm_bv_set( pd[0].reg_smpl_pmds, 32 );
|
|
Packit Service |
a1973e |
pfm_bv_set( pd[0].reg_smpl_pmds, 33 );
|
|
Packit Service |
a1973e |
pfm_bv_set( pd[0].reg_smpl_pmds, 36 );
|
|
Packit Service |
a1973e |
pfm_bv_set( pd[0].reg_reset_pmds, 36 );
|
|
Packit Service |
a1973e |
return ( 1 );
|
|
Packit Service |
a1973e |
} else if ( pfm_mont_is_iear( native_index ) ) { /* O,1 MK */
|
|
Packit Service |
a1973e |
pfm_bv_set( pd[0].reg_smpl_pmds, 34 );
|
|
Packit Service |
a1973e |
pfm_bv_set( pd[0].reg_smpl_pmds, 35 );
|
|
Packit Service |
a1973e |
pfm_bv_set( pd[0].reg_reset_pmds, 34 );
|
|
Packit Service |
a1973e |
return ( 1 );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
return ( 0 );
|
|
Packit Service |
a1973e |
} else if ( _perfmon2_pfm_pmu_type == PFMLIB_ITANIUM2_PMU ) {
|
|
Packit Service |
a1973e |
if ( pfm_mont_is_dear( native_index ) ) { /* 2,3,17 */
|
|
Packit Service |
a1973e |
pfm_bv_set( pd[0].reg_smpl_pmds, 2 );
|
|
Packit Service |
a1973e |
pfm_bv_set( pd[0].reg_smpl_pmds, 3 );
|
|
Packit Service |
a1973e |
pfm_bv_set( pd[0].reg_smpl_pmds, 17 );
|
|
Packit Service |
a1973e |
pfm_bv_set( pd[0].reg_reset_pmds, 17 );
|
|
Packit Service |
a1973e |
return ( 1 );
|
|
Packit Service |
a1973e |
} else if ( pfm_mont_is_iear( native_index ) ) { /* O,1 MK */
|
|
Packit Service |
a1973e |
pfm_bv_set( pd[0].reg_smpl_pmds, 0 );
|
|
Packit Service |
a1973e |
pfm_bv_set( pd[0].reg_smpl_pmds, 1 );
|
|
Packit Service |
a1973e |
pfm_bv_set( pd[0].reg_reset_pmds, 0 );
|
|
Packit Service |
a1973e |
return ( 1 );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
return ( 0 );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
#else
|
|
Packit Service |
a1973e |
( void ) native_index; /*unused */
|
|
Packit Service |
a1973e |
( void ) pd; /*unused */
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
return ( 0 );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static inline int
|
|
Packit Service |
a1973e |
process_smpl_entry( unsigned int native_pfm_index, int flags,
|
|
Packit Service |
a1973e |
pfm_dfl_smpl_entry_t ** ent, caddr_t * pc )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
#ifndef __ia64__
|
|
Packit Service |
a1973e |
( void ) native_pfm_index; /*unused */
|
|
Packit Service |
a1973e |
( void ) flags; /*unused */
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
SUBDBG( "process_smpl_entry(%d,%d,%p,%p)\n", native_pfm_index, flags, ent,
|
|
Packit Service |
a1973e |
pc );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#ifdef __ia64__
|
|
Packit Service |
a1973e |
/* Fixup EAR stuff here */
|
|
Packit Service |
a1973e |
if ( is_montecito_and_dear( native_pfm_index ) ) {
|
|
Packit Service |
a1973e |
pfm_mont_pmd_reg_t data_addr;
|
|
Packit Service |
a1973e |
pfm_mont_pmd_reg_t latency;
|
|
Packit Service |
a1973e |
pfm_mont_pmd_reg_t load_addr;
|
|
Packit Service |
a1973e |
unsigned long newent;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ( flags & ( PAPI_PROFIL_DATA_EAR | PAPI_PROFIL_INST_EAR ) ) == 0 )
|
|
Packit Service |
a1973e |
goto safety;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Skip the header */
|
|
Packit Service |
a1973e |
++( *ent );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// PMD32 has data address on Montecito
|
|
Packit Service |
a1973e |
// PMD33 has latency on Montecito
|
|
Packit Service |
a1973e |
// PMD36 has instruction address on Montecito
|
|
Packit Service |
a1973e |
data_addr = *( pfm_mont_pmd_reg_t * ) * ent;
|
|
Packit Service |
a1973e |
latency =
|
|
Packit Service |
a1973e |
*( pfm_mont_pmd_reg_t * ) ( ( unsigned long ) *ent +
|
|
Packit Service |
a1973e |
sizeof ( data_addr ) );
|
|
Packit Service |
a1973e |
load_addr =
|
|
Packit Service |
a1973e |
*( pfm_mont_pmd_reg_t * ) ( ( unsigned long ) *ent +
|
|
Packit Service |
a1973e |
sizeof ( data_addr ) +
|
|
Packit Service |
a1973e |
sizeof ( latency ) );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG( "PMD[32]: %#016llx\n",
|
|
Packit Service |
a1973e |
( unsigned long long ) data_addr.pmd_val );
|
|
Packit Service |
a1973e |
SUBDBG( "PMD[33]: %#016llx\n",
|
|
Packit Service |
a1973e |
( unsigned long long ) latency.pmd_val );
|
|
Packit Service |
a1973e |
SUBDBG( "PMD[36]: %#016llx\n",
|
|
Packit Service |
a1973e |
( unsigned long long ) load_addr.pmd_val );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ( !load_addr.pmd36_mont_reg.dear_vl ) ||
|
|
Packit Service |
a1973e |
( !load_addr.pmd33_mont_reg.dear_stat ) ) {
|
|
Packit Service |
a1973e |
SUBDBG
|
|
Packit Service |
a1973e |
( "Invalid DEAR sample found, dear_vl = %d, dear_stat = %#x\n",
|
|
Packit Service |
a1973e |
load_addr.pmd36_mont_reg.dear_vl,
|
|
Packit Service |
a1973e |
load_addr.pmd33_mont_reg.dear_stat );
|
|
Packit Service |
a1973e |
bail1:
|
|
Packit Service |
a1973e |
newent = ( unsigned long ) *ent;
|
|
Packit Service |
a1973e |
newent += 3 * sizeof ( pfm_mont_pmd_reg_t );
|
|
Packit Service |
a1973e |
*ent = ( pfm_dfl_smpl_entry_t * ) newent;
|
|
Packit Service |
a1973e |
return 0;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( flags & PAPI_PROFIL_DATA_EAR )
|
|
Packit Service |
a1973e |
*pc = ( caddr_t ) data_addr.pmd_val;
|
|
Packit Service |
a1973e |
else if ( flags & PAPI_PROFIL_INST_EAR ) {
|
|
Packit Service |
a1973e |
unsigned long tmp =
|
|
Packit Service |
a1973e |
( ( load_addr.pmd36_mont_reg.dear_iaddr +
|
|
Packit Service |
a1973e |
( unsigned long ) load_addr.pmd36_mont_reg.
|
|
Packit Service |
a1973e |
dear_bn ) << 4 ) | ( unsigned long ) load_addr.
|
|
Packit Service |
a1973e |
pmd36_mont_reg.dear_slot;
|
|
Packit Service |
a1973e |
*pc = ( caddr_t ) tmp;
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
PAPIERROR( "BUG!" );
|
|
Packit Service |
a1973e |
goto bail1;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
newent = ( unsigned long ) *ent;
|
|
Packit Service |
a1973e |
newent += 3 * sizeof ( pfm_mont_pmd_reg_t );
|
|
Packit Service |
a1973e |
*ent = ( pfm_dfl_smpl_entry_t * ) newent;
|
|
Packit Service |
a1973e |
return 0;
|
|
Packit Service |
a1973e |
} else if ( is_montecito_and_iear( native_pfm_index ) ) {
|
|
Packit Service |
a1973e |
pfm_mont_pmd_reg_t latency;
|
|
Packit Service |
a1973e |
pfm_mont_pmd_reg_t icache_line_addr;
|
|
Packit Service |
a1973e |
unsigned long newent;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ( flags & PAPI_PROFIL_INST_EAR ) == 0 )
|
|
Packit Service |
a1973e |
goto safety;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Skip the header */
|
|
Packit Service |
a1973e |
++( *ent );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// PMD34 has data address on Montecito
|
|
Packit Service |
a1973e |
// PMD35 has latency on Montecito
|
|
Packit Service |
a1973e |
icache_line_addr = *( pfm_mont_pmd_reg_t * ) * ent;
|
|
Packit Service |
a1973e |
latency =
|
|
Packit Service |
a1973e |
*( pfm_mont_pmd_reg_t * ) ( ( unsigned long ) *ent +
|
|
Packit Service |
a1973e |
sizeof ( icache_line_addr ) );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG( "PMD[34]: %#016llx\n",
|
|
Packit Service |
a1973e |
( unsigned long long ) icache_line_addr.pmd_val );
|
|
Packit Service |
a1973e |
SUBDBG( "PMD[35]: %#016llx\n",
|
|
Packit Service |
a1973e |
( unsigned long long ) latency.pmd_val );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ( icache_line_addr.pmd34_mont_reg.iear_stat & 0x1 ) == 0 ) {
|
|
Packit Service |
a1973e |
SUBDBG( "Invalid IEAR sample found, iear_stat = %#x\n",
|
|
Packit Service |
a1973e |
icache_line_addr.pmd34_mont_reg.iear_stat );
|
|
Packit Service |
a1973e |
bail2:
|
|
Packit Service |
a1973e |
newent = ( unsigned long ) *ent;
|
|
Packit Service |
a1973e |
newent += 2 * sizeof ( pfm_mont_pmd_reg_t );
|
|
Packit Service |
a1973e |
*ent = ( pfm_dfl_smpl_entry_t * ) newent;
|
|
Packit Service |
a1973e |
return ( 0 );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( flags & PAPI_PROFIL_INST_EAR ) {
|
|
Packit Service |
a1973e |
unsigned long tmp = icache_line_addr.pmd34_mont_reg.iear_iaddr << 5;
|
|
Packit Service |
a1973e |
*pc = ( caddr_t ) tmp;
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
PAPIERROR( "BUG!" );
|
|
Packit Service |
a1973e |
goto bail2;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
newent = ( unsigned long ) *ent;
|
|
Packit Service |
a1973e |
newent += 2 * sizeof ( pfm_mont_pmd_reg_t );
|
|
Packit Service |
a1973e |
*ent = ( pfm_dfl_smpl_entry_t * ) newent;
|
|
Packit Service |
a1973e |
return 0;
|
|
Packit Service |
a1973e |
} else if ( is_itanium2_and_dear( native_pfm_index ) ) {
|
|
Packit Service |
a1973e |
pfm_ita2_pmd_reg_t data_addr;
|
|
Packit Service |
a1973e |
pfm_ita2_pmd_reg_t latency;
|
|
Packit Service |
a1973e |
pfm_ita2_pmd_reg_t load_addr;
|
|
Packit Service |
a1973e |
unsigned long newent;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ( flags & ( PAPI_PROFIL_DATA_EAR | PAPI_PROFIL_INST_EAR ) ) == 0 )
|
|
Packit Service |
a1973e |
goto safety;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Skip the header */
|
|
Packit Service |
a1973e |
++( *ent );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// PMD2 has data address on Itanium 2
|
|
Packit Service |
a1973e |
// PMD3 has latency on Itanium 2
|
|
Packit Service |
a1973e |
// PMD17 has instruction address on Itanium 2
|
|
Packit Service |
a1973e |
data_addr = *( pfm_ita2_pmd_reg_t * ) * ent;
|
|
Packit Service |
a1973e |
latency =
|
|
Packit Service |
a1973e |
*( pfm_ita2_pmd_reg_t * ) ( ( unsigned long ) *ent +
|
|
Packit Service |
a1973e |
sizeof ( data_addr ) );
|
|
Packit Service |
a1973e |
load_addr =
|
|
Packit Service |
a1973e |
*( pfm_ita2_pmd_reg_t * ) ( ( unsigned long ) *ent +
|
|
Packit Service |
a1973e |
sizeof ( data_addr ) +
|
|
Packit Service |
a1973e |
sizeof ( latency ) );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG( "PMD[2]: %#016llx\n",
|
|
Packit Service |
a1973e |
( unsigned long long ) data_addr.pmd_val );
|
|
Packit Service |
a1973e |
SUBDBG( "PMD[3]: %#016llx\n", ( unsigned long long ) latency.pmd_val );
|
|
Packit Service |
a1973e |
SUBDBG( "PMD[17]: %#016llx\n",
|
|
Packit Service |
a1973e |
( unsigned long long ) load_addr.pmd_val );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ( !load_addr.pmd17_ita2_reg.dear_vl ) ||
|
|
Packit Service |
a1973e |
( !load_addr.pmd3_ita2_reg.dear_stat ) ) {
|
|
Packit Service |
a1973e |
SUBDBG
|
|
Packit Service |
a1973e |
( "Invalid DEAR sample found, dear_vl = %d, dear_stat = %#x\n",
|
|
Packit Service |
a1973e |
load_addr.pmd17_ita2_reg.dear_vl,
|
|
Packit Service |
a1973e |
load_addr.pmd3_ita2_reg.dear_stat );
|
|
Packit Service |
a1973e |
bail3:
|
|
Packit Service |
a1973e |
newent = ( unsigned long ) *ent;
|
|
Packit Service |
a1973e |
newent += 3 * sizeof ( pfm_mont_pmd_reg_t );
|
|
Packit Service |
a1973e |
*ent = ( pfm_dfl_smpl_entry_t * ) newent;
|
|
Packit Service |
a1973e |
return 0;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( flags & PAPI_PROFIL_DATA_EAR )
|
|
Packit Service |
a1973e |
*pc = ( caddr_t ) data_addr.pmd_val;
|
|
Packit Service |
a1973e |
else if ( flags & PAPI_PROFIL_INST_EAR ) {
|
|
Packit Service |
a1973e |
unsigned long tmp =
|
|
Packit Service |
a1973e |
( ( load_addr.pmd17_ita2_reg.dear_iaddr +
|
|
Packit Service |
a1973e |
( unsigned long ) load_addr.pmd17_ita2_reg.
|
|
Packit Service |
a1973e |
dear_bn ) << 4 ) | ( unsigned long ) load_addr.
|
|
Packit Service |
a1973e |
pmd17_ita2_reg.dear_slot;
|
|
Packit Service |
a1973e |
*pc = ( caddr_t ) tmp;
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
PAPIERROR( "BUG!" );
|
|
Packit Service |
a1973e |
goto bail3;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
newent = ( unsigned long ) *ent;
|
|
Packit Service |
a1973e |
newent += 3 * sizeof ( pfm_ita2_pmd_reg_t );
|
|
Packit Service |
a1973e |
*ent = ( pfm_dfl_smpl_entry_t * ) newent;
|
|
Packit Service |
a1973e |
return 0;
|
|
Packit Service |
a1973e |
} else if ( is_itanium2_and_iear( native_pfm_index ) ) {
|
|
Packit Service |
a1973e |
pfm_ita2_pmd_reg_t latency;
|
|
Packit Service |
a1973e |
pfm_ita2_pmd_reg_t icache_line_addr;
|
|
Packit Service |
a1973e |
unsigned long newent;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ( flags & PAPI_PROFIL_INST_EAR ) == 0 )
|
|
Packit Service |
a1973e |
goto safety;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Skip the header */
|
|
Packit Service |
a1973e |
++( *ent );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// PMD0 has address on Itanium 2
|
|
Packit Service |
a1973e |
// PMD1 has latency on Itanium 2
|
|
Packit Service |
a1973e |
icache_line_addr = *( pfm_ita2_pmd_reg_t * ) * ent;
|
|
Packit Service |
a1973e |
latency =
|
|
Packit Service |
a1973e |
*( pfm_ita2_pmd_reg_t * ) ( ( unsigned long ) *ent +
|
|
Packit Service |
a1973e |
sizeof ( icache_line_addr ) );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG( "PMD[0]: %#016llx\n",
|
|
Packit Service |
a1973e |
( unsigned long long ) icache_line_addr.pmd_val );
|
|
Packit Service |
a1973e |
SUBDBG( "PMD[1]: %#016llx\n", ( unsigned long long ) latency.pmd_val );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ( icache_line_addr.pmd0_ita2_reg.iear_stat & 0x1 ) == 0 ) {
|
|
Packit Service |
a1973e |
SUBDBG( "Invalid IEAR sample found, iear_stat = %#x\n",
|
|
Packit Service |
a1973e |
icache_line_addr.pmd0_ita2_reg.iear_stat );
|
|
Packit Service |
a1973e |
bail4:
|
|
Packit Service |
a1973e |
newent = ( unsigned long ) *ent;
|
|
Packit Service |
a1973e |
newent += 2 * sizeof ( pfm_mont_pmd_reg_t );
|
|
Packit Service |
a1973e |
*ent = ( pfm_dfl_smpl_entry_t * ) newent;
|
|
Packit Service |
a1973e |
return ( 0 );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( flags & PAPI_PROFIL_INST_EAR ) {
|
|
Packit Service |
a1973e |
unsigned long tmp = icache_line_addr.pmd0_ita2_reg.iear_iaddr << 5;
|
|
Packit Service |
a1973e |
*pc = ( caddr_t ) tmp;
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
PAPIERROR( "BUG!" );
|
|
Packit Service |
a1973e |
goto bail4;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
newent = ( unsigned long ) *ent;
|
|
Packit Service |
a1973e |
newent += 2 * sizeof ( pfm_ita2_pmd_reg_t );
|
|
Packit Service |
a1973e |
*ent = ( pfm_dfl_smpl_entry_t * ) newent;
|
|
Packit Service |
a1973e |
return 0;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
#if 0
|
|
Packit Service |
a1973e |
( is_btb( native_pfm_index ) ) {
|
|
Packit Service |
a1973e |
// PMD48-63,39 on Montecito
|
|
Packit Service |
a1973e |
// PMD8-15,16 on Itanium 2
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
else
|
|
Packit Service |
a1973e |
safety:
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
*pc = ( caddr_t ) ( ( size_t ) ( ( *ent )->ip ) );
|
|
Packit Service |
a1973e |
++( *ent );
|
|
Packit Service |
a1973e |
return ( 0 );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static inline int
|
|
Packit Service |
a1973e |
process_smpl_buf( int num_smpl_pmds, int entry_size, ThreadInfo_t ** thr )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
( void ) num_smpl_pmds; /*unused */
|
|
Packit Service |
a1973e |
( void ) entry_size; /*unused */
|
|
Packit Service |
a1973e |
int cidx = _perfmon2_vector.cmp_info.CmpIdx;
|
|
Packit Service |
a1973e |
pfm_dfl_smpl_entry_t *ent;
|
|
Packit Service |
a1973e |
uint64_t entry, count;
|
|
Packit Service |
a1973e |
pfm_dfl_smpl_hdr_t *hdr =
|
|
Packit Service |
a1973e |
( ( pfm_context_t * ) ( *thr )->context[cidx] )->smpl_buf;
|
|
Packit Service |
a1973e |
int ret, profile_index, flags;
|
|
Packit Service |
a1973e |
unsigned int native_pfm_index;
|
|
Packit Service |
a1973e |
caddr_t pc = NULL;
|
|
Packit Service |
a1973e |
long long weight;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
DEBUGCALL( DEBUG_SUBSTRATE, dump_smpl_hdr( hdr ) );
|
|
Packit Service |
a1973e |
count = hdr->hdr_count;
|
|
Packit Service |
a1973e |
ent = ( pfm_dfl_smpl_entry_t * ) ( hdr + 1 );
|
|
Packit Service |
a1973e |
entry = 0;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG( "This buffer has %llu samples in it.\n",
|
|
Packit Service |
a1973e |
( unsigned long long ) count );
|
|
Packit Service |
a1973e |
while ( count-- ) {
|
|
Packit Service |
a1973e |
SUBDBG( "Processing sample entry %llu\n",
|
|
Packit Service |
a1973e |
( unsigned long long ) entry );
|
|
Packit Service |
a1973e |
DEBUGCALL( DEBUG_SUBSTRATE, dump_smpl( ent ) );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Find the index of the profile buffers if we are profiling on many events */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
ret =
|
|
Packit Service |
a1973e |
find_profile_index( ( *thr )->running_eventset[cidx], ent->ovfl_pmd,
|
|
Packit Service |
a1973e |
&flags, &native_pfm_index, &profile_index );
|
|
Packit Service |
a1973e |
if ( ret != PAPI_OK )
|
|
Packit Service |
a1973e |
return ( ret );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
weight = process_smpl_entry( native_pfm_index, flags, &ent, &pc );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
_papi_hwi_dispatch_profile( ( *thr )->running_eventset[cidx], pc,
|
|
Packit Service |
a1973e |
weight, profile_index );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
entry++;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* This function used when hardware overflows ARE working
|
|
Packit Service |
a1973e |
or when software overflows are forced */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static void
|
|
Packit Service |
a1973e |
_papi_pfm_dispatch_timer( int n, hwd_siginfo_t * info, void *uc )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
_papi_hwi_context_t ctx;
|
|
Packit Service |
a1973e |
#ifdef HAVE_PFM_MSG_TYPE
|
|
Packit Service |
a1973e |
pfm_msg_t msg;
|
|
Packit Service |
a1973e |
#else
|
|
Packit Service |
a1973e |
pfarg_msg_t msg;
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
int ret, wanted_fd, fd = info->si_fd;
|
|
Packit Service |
a1973e |
caddr_t address;
|
|
Packit Service |
a1973e |
ThreadInfo_t *thread = _papi_hwi_lookup_thread( 0 );
|
|
Packit Service |
a1973e |
int cidx = _perfmon2_vector.cmp_info.CmpIdx;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( thread == NULL ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "thread == NULL in _papi_pfm_dispatch_timer!" );
|
|
Packit Service |
a1973e |
if ( n == _perfmon2_vector.cmp_info.hardware_intr_sig ) {
|
|
Packit Service |
a1973e |
ret = read( fd, &msg, sizeof ( msg ) );
|
|
Packit Service |
a1973e |
pfm_restart( fd );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
return;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( thread->running_eventset[cidx] == NULL ) {
|
|
Packit Service |
a1973e |
PAPIERROR
|
|
Packit Service |
a1973e |
( "thread->running_eventset == NULL in _papi_pfm_dispatch_timer!" );
|
|
Packit Service |
a1973e |
if ( n == _perfmon2_vector.cmp_info.hardware_intr_sig ) {
|
|
Packit Service |
a1973e |
ret = read( fd, &msg, sizeof ( msg ) );
|
|
Packit Service |
a1973e |
pfm_restart( fd );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
return;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( thread->running_eventset[cidx]->overflow.flags == 0 ) {
|
|
Packit Service |
a1973e |
PAPIERROR
|
|
Packit Service |
a1973e |
( "thread->running_eventset->overflow.flags == 0 in _papi_pfm_dispatch_timer!" );
|
|
Packit Service |
a1973e |
if ( n == _perfmon2_vector.cmp_info.hardware_intr_sig ) {
|
|
Packit Service |
a1973e |
ret = read( fd, &msg, sizeof ( msg ) );
|
|
Packit Service |
a1973e |
pfm_restart( fd );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
return;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
ctx.si = info;
|
|
Packit Service |
a1973e |
ctx.ucontext = ( hwd_ucontext_t * ) uc;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( thread->running_eventset[cidx]->overflow.
|
|
Packit Service |
a1973e |
flags & PAPI_OVERFLOW_FORCE_SW ) {
|
|
Packit Service |
a1973e |
address = GET_OVERFLOW_ADDRESS( ctx );
|
|
Packit Service |
a1973e |
_papi_hwi_dispatch_overflow_signal( ( void * ) &ctx, address, NULL,
|
|
Packit Service |
a1973e |
0, 0, &thread, cidx );
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
if ( thread->running_eventset[cidx]->overflow.flags ==
|
|
Packit Service |
a1973e |
PAPI_OVERFLOW_HARDWARE ) {
|
|
Packit Service |
a1973e |
wanted_fd =
|
|
Packit Service |
a1973e |
( ( pfm_control_state_t * ) ( thread->running_eventset[cidx]->
|
|
Packit Service |
a1973e |
ctl_state ) )->ctx_fd;
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
wanted_fd = ( ( pfm_context_t * ) thread->context[cidx] )->ctx_fd;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
if ( wanted_fd != fd ) {
|
|
Packit Service |
a1973e |
SUBDBG( "expected fd %d, got %d in _papi_hwi_dispatch_timer!",
|
|
Packit Service |
a1973e |
wanted_fd, fd );
|
|
Packit Service |
a1973e |
if ( n == _perfmon2_vector.cmp_info.hardware_intr_sig ) {
|
|
Packit Service |
a1973e |
ret = read( fd, &msg, sizeof ( msg ) );
|
|
Packit Service |
a1973e |
pfm_restart( fd );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
return;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
retry:
|
|
Packit Service |
a1973e |
ret = read( fd, &msg, sizeof ( msg ) );
|
|
Packit Service |
a1973e |
if ( ret == -1 ) {
|
|
Packit Service |
a1973e |
if ( errno == EINTR ) {
|
|
Packit Service |
a1973e |
SUBDBG( "read(%d) interrupted, retrying\n", fd );
|
|
Packit Service |
a1973e |
goto retry;
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
PAPIERROR( "read(%d): errno %d", fd, errno );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
} else if ( ret != sizeof ( msg ) ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "read(%d): short %d vs. %d bytes", fd, ret,
|
|
Packit Service |
a1973e |
sizeof ( msg ) );
|
|
Packit Service |
a1973e |
ret = -1;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( msg.type != PFM_MSG_OVFL ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "unexpected msg type %d", msg.type );
|
|
Packit Service |
a1973e |
ret = -1;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
#if 0
|
|
Packit Service |
a1973e |
if ( msg.pfm_ovfl_msg.msg_ovfl_tid != mygettid( ) ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "unmatched thread id %lx vs. %lx",
|
|
Packit Service |
a1973e |
msg.pfm_ovfl_msg.msg_ovfl_tid, mygettid( ) );
|
|
Packit Service |
a1973e |
ret = -1;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ret != -1 ) {
|
|
Packit Service |
a1973e |
if ( ( thread->running_eventset[cidx]->state & PAPI_PROFILING ) &&
|
|
Packit Service |
a1973e |
!( thread->running_eventset[cidx]->profile.
|
|
Packit Service |
a1973e |
flags & PAPI_PROFIL_FORCE_SW ) )
|
|
Packit Service |
a1973e |
process_smpl_buf( 0, sizeof ( pfm_dfl_smpl_entry_t ), &thread );
|
|
Packit Service |
a1973e |
else {
|
|
Packit Service |
a1973e |
/* PAPI assumes that the overflow vector contains the register index of the
|
|
Packit Service |
a1973e |
overflowing native event. That is generally true, but Stephane used some
|
|
Packit Service |
a1973e |
tricks to offset the fixed counters on Core2 (Core? i7?) by 16. This hack
|
|
Packit Service |
a1973e |
corrects for that hack in a (hopefully) transparent manner */
|
|
Packit Service |
a1973e |
unsigned long i, vector = msg.pfm_ovfl_msg.msg_ovfl_pmds[0];
|
|
Packit Service |
a1973e |
pfm_control_state_t *ctl =
|
|
Packit Service |
a1973e |
( pfm_control_state_t * ) thread->running_eventset[cidx]->
|
|
Packit Service |
a1973e |
ctl_state;
|
|
Packit Service |
a1973e |
for ( i = 0; i < ctl->in.pfp_event_count; i++ ) {
|
|
Packit Service |
a1973e |
/* We're only comparing to pmds[0]. A more robust implementation would
|
|
Packit Service |
a1973e |
compare to pmds[0-3]. The bit mask must be converted to an index
|
|
Packit Service |
a1973e |
for the comparison to work */
|
|
Packit Service |
a1973e |
if ( ctl->pd[i].reg_num ==
|
|
Packit Service |
a1973e |
ffsl( msg.pfm_ovfl_msg.msg_ovfl_pmds[0] ) - 1 ) {
|
|
Packit Service |
a1973e |
/* if a match is found, convert the index back to a bitmask */
|
|
Packit Service |
a1973e |
vector = 1 << i;
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
_papi_hwi_dispatch_overflow_signal( ( void * ) &ctx,
|
|
Packit Service |
a1973e |
( caddr_t ) ( ( size_t )
|
|
Packit Service |
a1973e |
msg.
|
|
Packit Service |
a1973e |
pfm_ovfl_msg.
|
|
Packit Service |
a1973e |
msg_ovfl_ip ),
|
|
Packit Service |
a1973e |
NULL, vector, 0, &thread,
|
|
Packit Service |
a1973e |
cidx );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ( ret = pfm_restart( fd ) ) ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "pfm_restart(%d): %s", fd, strerror( ret ) );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static int
|
|
Packit Service |
a1973e |
_papi_pfm_stop_profiling( ThreadInfo_t * thread, EventSetInfo_t * ESI )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
( void ) ESI; /*unused */
|
|
Packit Service |
a1973e |
/* Process any remaining samples in the sample buffer */
|
|
Packit Service |
a1973e |
return ( process_smpl_buf( 0, sizeof ( pfm_dfl_smpl_entry_t ), &thread ) );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static int
|
|
Packit Service |
a1973e |
_papi_pfm_set_profile( EventSetInfo_t * ESI, int EventIndex, int threshold )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
int cidx = _perfmon2_vector.cmp_info.CmpIdx;
|
|
Packit Service |
a1973e |
pfm_control_state_t *ctl = ( pfm_control_state_t * ) ( ESI->ctl_state );
|
|
Packit Service |
a1973e |
pfm_context_t *ctx = ( pfm_context_t * ) ( ESI->master->context[cidx] );
|
|
Packit Service |
a1973e |
pfarg_ctx_t newctx;
|
|
Packit Service |
a1973e |
void *buf_addr = NULL;
|
|
Packit Service |
a1973e |
pfm_dfl_smpl_arg_t buf_arg;
|
|
Packit Service |
a1973e |
pfm_dfl_smpl_hdr_t *hdr;
|
|
Packit Service |
a1973e |
int i, ret, ctx_fd;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
memset( &newctx, 0, sizeof ( newctx ) );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( threshold == 0 ) {
|
|
Packit Service |
a1973e |
SUBDBG( "MUNMAP(%p,%lld)\n", ctx->smpl_buf,
|
|
Packit Service |
a1973e |
( unsigned long long ) ctx->smpl.buf_size );
|
|
Packit Service |
a1973e |
munmap( ctx->smpl_buf, ctx->smpl.buf_size );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
i = close( ctl->ctx_fd );
|
|
Packit Service |
a1973e |
SUBDBG( "CLOSE fd %d returned %d\n", ctl->ctx_fd, i );
|
|
Packit Service |
a1973e |
(void) i;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Thread has master context */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
ctl->ctx_fd = ctx->ctx_fd;
|
|
Packit Service |
a1973e |
ctl->ctx = &ctx->ctx;
|
|
Packit Service |
a1973e |
memset( &ctx->smpl, 0, sizeof ( buf_arg ) );
|
|
Packit Service |
a1973e |
ctx->smpl_buf = NULL;
|
|
Packit Service |
a1973e |
ret = _papi_pfm_set_overflow( ESI, EventIndex, threshold );
|
|
Packit Service |
a1973e |
//#warning "This should be handled somewhere else"
|
|
Packit Service |
a1973e |
ESI->state &= ~( PAPI_OVERFLOWING );
|
|
Packit Service |
a1973e |
ESI->overflow.flags &= ~( PAPI_OVERFLOW_HARDWARE );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return ( ret );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
memset( &buf_arg, 0, sizeof ( buf_arg ) );
|
|
Packit Service |
a1973e |
buf_arg.buf_size = 2 * getpagesize( );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG( "PFM_CREATE_CONTEXT(%p,%s,%p,%d)\n", &newctx, PFM_DFL_SMPL_NAME,
|
|
Packit Service |
a1973e |
&buf_arg, ( int ) sizeof ( buf_arg ) );
|
|
Packit Service |
a1973e |
if ( ( ret =
|
|
Packit Service |
a1973e |
pfm_create_context( &newctx, PFM_DFL_SMPL_NAME, &buf_arg,
|
|
Packit Service |
a1973e |
sizeof ( buf_arg ) ) ) == -1 ) {
|
|
Packit Service |
a1973e |
DEBUGCALL( DEBUG_SUBSTRATE, dump_smpl_arg( &buf_arg ) );
|
|
Packit Service |
a1973e |
PAPIERROR( "_papi_hwd_set_profile:pfm_create_context(): %s",
|
|
Packit Service |
a1973e |
strerror( errno ) );
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
ctx_fd = ret;
|
|
Packit Service |
a1973e |
SUBDBG( "PFM_CREATE_CONTEXT returned fd %d\n", ctx_fd );
|
|
Packit Service |
a1973e |
tune_up_fd( ret );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
SUBDBG( "MMAP(NULL,%lld,%d,%d,%d,0)\n",
|
|
Packit Service |
a1973e |
( unsigned long long ) buf_arg.buf_size, PROT_READ, MAP_PRIVATE,
|
|
Packit Service |
a1973e |
ctx_fd );
|
|
Packit Service |
a1973e |
buf_addr =
|
|
Packit Service |
a1973e |
mmap( NULL, ( size_t ) buf_arg.buf_size, PROT_READ, MAP_PRIVATE, ctx_fd,
|
|
Packit Service |
a1973e |
0 );
|
|
Packit Service |
a1973e |
if ( buf_addr == MAP_FAILED ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "mmap(NULL,%d,%d,%d,%d,0): %s", buf_arg.buf_size, PROT_READ,
|
|
Packit Service |
a1973e |
MAP_PRIVATE, ctx_fd, strerror( errno ) );
|
|
Packit Service |
a1973e |
close( ctx_fd );
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
SUBDBG( "Sample buffer is located at %p\n", buf_addr );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
hdr = ( pfm_dfl_smpl_hdr_t * ) buf_addr;
|
|
Packit Service |
a1973e |
SUBDBG( "hdr_cur_offs=%llu version=%u.%u\n",
|
|
Packit Service |
a1973e |
( unsigned long long ) hdr->hdr_cur_offs,
|
|
Packit Service |
a1973e |
PFM_VERSION_MAJOR( hdr->hdr_version ),
|
|
Packit Service |
a1973e |
PFM_VERSION_MINOR( hdr->hdr_version ) );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( PFM_VERSION_MAJOR( hdr->hdr_version ) < 1 ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "invalid buffer format version %d",
|
|
Packit Service |
a1973e |
PFM_VERSION_MAJOR( hdr->hdr_version ) );
|
|
Packit Service |
a1973e |
munmap( buf_addr, buf_arg.buf_size );
|
|
Packit Service |
a1973e |
close( ctx_fd );
|
|
Packit Service |
a1973e |
return PAPI_ESYS;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
ret = _papi_pfm_set_overflow( ESI, EventIndex, threshold );
|
|
Packit Service |
a1973e |
if ( ret != PAPI_OK ) {
|
|
Packit Service |
a1973e |
munmap( buf_addr, buf_arg.buf_size );
|
|
Packit Service |
a1973e |
close( ctx_fd );
|
|
Packit Service |
a1973e |
return ( ret );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Look up the native event code */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ESI->profile.flags & ( PAPI_PROFIL_DATA_EAR | PAPI_PROFIL_INST_EAR ) ) {
|
|
Packit Service |
a1973e |
pfarg_pmd_t *pd;
|
|
Packit Service |
a1973e |
int pos, native_index;
|
|
Packit Service |
a1973e |
pd = ctl->pd;
|
|
Packit Service |
a1973e |
pos = ESI->EventInfoArray[EventIndex].pos[0];
|
|
Packit Service |
a1973e |
native_index =
|
|
Packit Service |
a1973e |
( ( pfm_register_t * ) ( ESI->NativeInfoArray[pos].ni_bits ) )->
|
|
Packit Service |
a1973e |
event;
|
|
Packit Service |
a1973e |
setup_ear_event( native_index, &pd[pos], ESI->profile.flags );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ESI->profile.flags & PAPI_PROFIL_RANDOM ) {
|
|
Packit Service |
a1973e |
pfarg_pmd_t *pd;
|
|
Packit Service |
a1973e |
int pos;
|
|
Packit Service |
a1973e |
pd = ctl->pd;
|
|
Packit Service |
a1973e |
pos = ESI->EventInfoArray[EventIndex].pos[0];
|
|
Packit Service |
a1973e |
pd[pos].reg_random_seed = 5;
|
|
Packit Service |
a1973e |
pd[pos].reg_random_mask = 0xff;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Now close our context it is safe */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
// close(ctx->ctx_fd);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Copy the new data to the threads context control block */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
ctl->ctx_fd = ctx_fd;
|
|
Packit Service |
a1973e |
memcpy( &ctx->smpl, &buf_arg, sizeof ( buf_arg ) );
|
|
Packit Service |
a1973e |
ctx->smpl_buf = buf_addr;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static int
|
|
Packit Service |
a1973e |
_papi_pfm_set_overflow( EventSetInfo_t * ESI, int EventIndex, int threshold )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
pfm_control_state_t *this_state =
|
|
Packit Service |
a1973e |
( pfm_control_state_t * ) ( ESI->ctl_state );
|
|
Packit Service |
a1973e |
int j, retval = PAPI_OK, *pos;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Which counter are we on, this looks suspicious because of the pos[0],
|
|
Packit Service |
a1973e |
but this could be because of derived events. We should do more here
|
|
Packit Service |
a1973e |
to figure out exactly what the position is, because the event may
|
|
Packit Service |
a1973e |
actually have more than one position. */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
pos = ESI->EventInfoArray[EventIndex].pos;
|
|
Packit Service |
a1973e |
j = pos[0];
|
|
Packit Service |
a1973e |
SUBDBG( "Hardware counter %d used in overflow, threshold %d\n", j,
|
|
Packit Service |
a1973e |
threshold );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( threshold == 0 ) {
|
|
Packit Service |
a1973e |
/* If this counter isn't set to overflow */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ( this_state->pd[j].reg_flags & PFM_REGFL_OVFL_NOTIFY ) == 0 )
|
|
Packit Service |
a1973e |
return ( PAPI_EINVAL );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Remove the signal handler */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
retval = _papi_hwi_stop_signal( _perfmon2_vector.cmp_info.hardware_intr_sig );
|
|
Packit Service |
a1973e |
if ( retval != PAPI_OK )
|
|
Packit Service |
a1973e |
return ( retval );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Disable overflow */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
this_state->pd[j].reg_flags ^= PFM_REGFL_OVFL_NOTIFY;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/*
|
|
Packit Service |
a1973e |
* we may want to reset the other PMDs on
|
|
Packit Service |
a1973e |
* every overflow. If we do not set
|
|
Packit Service |
a1973e |
* this, the non-overflowed counters
|
|
Packit Service |
a1973e |
* will be untouched.
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if (inp.pfp_event_count > 1)
|
|
Packit Service |
a1973e |
this_state->pd[j].reg_reset_pmds[0] ^= 1UL << counter_to_reset */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Clear the overflow period */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
this_state->pd[j].reg_value = 0;
|
|
Packit Service |
a1973e |
this_state->pd[j].reg_long_reset = 0;
|
|
Packit Service |
a1973e |
this_state->pd[j].reg_short_reset = 0;
|
|
Packit Service |
a1973e |
this_state->pd[j].reg_random_seed = 0;
|
|
Packit Service |
a1973e |
this_state->pd[j].reg_random_mask = 0;
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
/* Enable the signal handler */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
retval =
|
|
Packit Service |
a1973e |
_papi_hwi_start_signal( _perfmon2_vector.cmp_info.hardware_intr_sig, 1,
|
|
Packit Service |
a1973e |
_perfmon2_vector.cmp_info.CmpIdx );
|
|
Packit Service |
a1973e |
if ( retval != PAPI_OK )
|
|
Packit Service |
a1973e |
return ( retval );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Set it to overflow */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
this_state->pd[j].reg_flags |= PFM_REGFL_OVFL_NOTIFY;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/*
|
|
Packit Service |
a1973e |
* we may want to reset the other PMDs on
|
|
Packit Service |
a1973e |
* every overflow. If we do not set
|
|
Packit Service |
a1973e |
* this, the non-overflowed counters
|
|
Packit Service |
a1973e |
* will be untouched.
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if (inp.pfp_event_count > 1)
|
|
Packit Service |
a1973e |
this_state->pd[j].reg_reset_pmds[0] |= 1UL << counter_to_reset */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Set the overflow period */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
this_state->pd[j].reg_value = -( unsigned long long ) threshold + 1;
|
|
Packit Service |
a1973e |
this_state->pd[j].reg_short_reset =
|
|
Packit Service |
a1973e |
-( unsigned long long ) threshold + 1;
|
|
Packit Service |
a1973e |
this_state->pd[j].reg_long_reset =
|
|
Packit Service |
a1973e |
-( unsigned long long ) threshold + 1;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
return ( retval );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static int
|
|
Packit Service |
a1973e |
_papi_pfm_init_control_state( hwd_control_state_t * ctl0 )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
pfm_control_state_t *ctl = ( pfm_control_state_t * ) ctl0;
|
|
Packit Service |
a1973e |
pfmlib_input_param_t *inp = &ctl->in;
|
|
Packit Service |
a1973e |
pfmlib_output_param_t *outp = &ctl->out;
|
|
Packit Service |
a1973e |
pfarg_pmd_t *pd = ctl->pd;
|
|
Packit Service |
a1973e |
pfarg_pmc_t *pc = ctl->pc;
|
|
Packit Service |
a1973e |
pfarg_setdesc_t *set = ctl->set;
|
|
Packit Service |
a1973e |
pfarg_setinfo_t *setinfo = ctl->setinfo;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
memset( inp, 0, sizeof ( *inp ) );
|
|
Packit Service |
a1973e |
memset( outp, 0, sizeof ( *inp ) );
|
|
Packit Service |
a1973e |
memset( pc, 0, sizeof ( ctl->pc ) );
|
|
Packit Service |
a1973e |
memset( pd, 0, sizeof ( ctl->pd ) );
|
|
Packit Service |
a1973e |
memset( set, 0, sizeof ( ctl->set ) );
|
|
Packit Service |
a1973e |
memset( setinfo, 0, sizeof ( ctl->setinfo ) );
|
|
Packit Service |
a1973e |
/* Will be filled by update now...until this gets another arg */
|
|
Packit Service |
a1973e |
ctl->ctx = NULL;
|
|
Packit Service |
a1973e |
ctl->ctx_fd = -1;
|
|
Packit Service |
a1973e |
ctl->load = NULL;
|
|
Packit Service |
a1973e |
set_domain( ctl, _perfmon2_vector.cmp_info.default_domain );
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static int
|
|
Packit Service |
a1973e |
_papi_pfm_allocate_registers( EventSetInfo_t * ESI )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
int i, j;
|
|
Packit Service |
a1973e |
for ( i = 0; i < ESI->NativeCount; i++ ) {
|
|
Packit Service |
a1973e |
if ( _papi_libpfm_ntv_code_to_bits
|
|
Packit Service |
a1973e |
( ESI->NativeInfoArray[i].ni_event,
|
|
Packit Service |
a1973e |
ESI->NativeInfoArray[i].ni_bits ) != PAPI_OK )
|
|
Packit Service |
a1973e |
goto bail;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
return PAPI_OK;
|
|
Packit Service |
a1973e |
bail:
|
|
Packit Service |
a1973e |
for ( j = 0; j < i; j++ )
|
|
Packit Service |
a1973e |
memset( ESI->NativeInfoArray[j].ni_bits, 0x0,
|
|
Packit Service |
a1973e |
sizeof ( pfm_register_t ) );
|
|
Packit Service |
a1973e |
return PAPI_ECNFLCT;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* This function clears the current contents of the control structure and
|
|
Packit Service |
a1973e |
updates it with whatever resources are allocated for all the native events
|
|
Packit Service |
a1973e |
in the native info structure array. */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static int
|
|
Packit Service |
a1973e |
_papi_pfm_update_control_state( hwd_control_state_t * ctl0,
|
|
Packit Service |
a1973e |
NativeInfo_t * native, int count,
|
|
Packit Service |
a1973e |
hwd_context_t * ctx0 )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
pfm_control_state_t *ctl = ( pfm_control_state_t * ) ctl0;
|
|
Packit Service |
a1973e |
pfm_context_t *ctx = ( pfm_context_t * ) ctx0;
|
|
Packit Service |
a1973e |
int i = 0, ret;
|
|
Packit Service |
a1973e |
int last_reg_set = 0, reg_set_done = 0, offset = 0;
|
|
Packit Service |
a1973e |
pfmlib_input_param_t tmpin, *inp = &ctl->in;
|
|
Packit Service |
a1973e |
pfmlib_output_param_t tmpout, *outp = &ctl->out;
|
|
Packit Service |
a1973e |
pfarg_pmd_t *pd = ctl->pd;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( count == 0 ) {
|
|
Packit Service |
a1973e |
SUBDBG( "Called with count == 0\n" );
|
|
Packit Service |
a1973e |
inp->pfp_event_count = 0;
|
|
Packit Service |
a1973e |
outp->pfp_pmc_count = 0;
|
|
Packit Service |
a1973e |
memset( inp->pfp_events, 0x0, sizeof ( inp->pfp_events ) );
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
memcpy( &tmpin, inp, sizeof ( tmpin ) );
|
|
Packit Service |
a1973e |
memcpy( &tmpout, outp, sizeof ( tmpout ) );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for ( i = 0; i < count; i++ ) {
|
|
Packit Service |
a1973e |
SUBDBG
|
|
Packit Service |
a1973e |
( "Stuffing native event index %d (code %#x) into input structure.\n",
|
|
Packit Service |
a1973e |
i, ( ( pfm_register_t * ) native[i].ni_bits )->event );
|
|
Packit Service |
a1973e |
memcpy( inp->pfp_events + i, native[i].ni_bits,
|
|
Packit Service |
a1973e |
sizeof ( pfmlib_event_t ) );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
inp->pfp_event_count = count;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* let the library figure out the values for the PMCS */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
ret = compute_kernel_args( ctl );
|
|
Packit Service |
a1973e |
if ( ret != PAPI_OK ) {
|
|
Packit Service |
a1973e |
/* Restore values */
|
|
Packit Service |
a1973e |
memcpy( inp, &tmpin, sizeof ( tmpin ) );
|
|
Packit Service |
a1973e |
memcpy( outp, &tmpout, sizeof ( tmpout ) );
|
|
Packit Service |
a1973e |
return ( ret );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* Update the native structure, because the allocation is done here. */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
last_reg_set = pd[0].reg_set;
|
|
Packit Service |
a1973e |
for ( i = 0; i < count; i++ ) {
|
|
Packit Service |
a1973e |
if ( pd[i].reg_set != last_reg_set ) {
|
|
Packit Service |
a1973e |
offset += reg_set_done;
|
|
Packit Service |
a1973e |
reg_set_done = 0;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
reg_set_done++;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
native[i].ni_position = i;
|
|
Packit Service |
a1973e |
SUBDBG( "native event index %d (code %#x) is at PMD offset %d\n", i,
|
|
Packit Service |
a1973e |
( ( pfm_register_t * ) native[i].ni_bits )->event,
|
|
Packit Service |
a1973e |
native[i].ni_position );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* If structure has not yet been filled with a context, fill it
|
|
Packit Service |
a1973e |
from the thread's context. This should happen in init_control_state
|
|
Packit Service |
a1973e |
when we give that a *ctx argument */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ctl->ctx == NULL ) {
|
|
Packit Service |
a1973e |
ctl->ctx = &ctx->ctx;
|
|
Packit Service |
a1973e |
ctl->ctx_fd = ctx->ctx_fd;
|
|
Packit Service |
a1973e |
ctl->load = &ctx->load;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
papi_vector_t _perfmon2_vector = {
|
|
Packit Service |
a1973e |
.cmp_info = {
|
|
Packit Service |
a1973e |
/* default component information (unspecified values initialized to 0) */
|
|
Packit Service |
a1973e |
.name = "perfmon",
|
|
Packit Service |
a1973e |
.description = "Linux perfmon2 CPU counters",
|
|
Packit Service |
a1973e |
.version = "3.8",
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
.default_domain = PAPI_DOM_USER,
|
|
Packit Service |
a1973e |
.available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL,
|
|
Packit Service |
a1973e |
.default_granularity = PAPI_GRN_THR,
|
|
Packit Service |
a1973e |
.available_granularities = PAPI_GRN_THR,
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
.hardware_intr = 1,
|
|
Packit Service |
a1973e |
.kernel_multiplex = 1,
|
|
Packit Service |
a1973e |
.kernel_profile = 1,
|
|
Packit Service |
a1973e |
.num_mpx_cntrs = PFMLIB_MAX_PMDS,
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* component specific cmp_info initializations */
|
|
Packit Service |
a1973e |
.fast_real_timer = 1,
|
|
Packit Service |
a1973e |
.fast_virtual_timer = 0,
|
|
Packit Service |
a1973e |
.attach = 1,
|
|
Packit Service |
a1973e |
.attach_must_ptrace = 1,
|
|
Packit Service |
a1973e |
},
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* sizes of framework-opaque component-private structures */
|
|
Packit Service |
a1973e |
.size = {
|
|
Packit Service |
a1973e |
.context = sizeof ( pfm_context_t ),
|
|
Packit Service |
a1973e |
.control_state = sizeof ( pfm_control_state_t ),
|
|
Packit Service |
a1973e |
.reg_value = sizeof ( pfm_register_t ),
|
|
Packit Service |
a1973e |
.reg_alloc = sizeof ( pfm_reg_alloc_t ),
|
|
Packit Service |
a1973e |
},
|
|
Packit Service |
a1973e |
/* function pointers in this component */
|
|
Packit Service |
a1973e |
.init_control_state = _papi_pfm_init_control_state,
|
|
Packit Service |
a1973e |
.start = _papi_pfm_start,
|
|
Packit Service |
a1973e |
.stop = _papi_pfm_stop,
|
|
Packit Service |
a1973e |
.read = _papi_pfm_read,
|
|
Packit Service |
a1973e |
.shutdown_thread = _papi_pfm_shutdown,
|
|
Packit Service |
a1973e |
.shutdown_component = _papi_pfm_shutdown_component,
|
|
Packit Service |
a1973e |
.ctl = _papi_pfm_ctl,
|
|
Packit Service |
a1973e |
.update_control_state = _papi_pfm_update_control_state,
|
|
Packit Service |
a1973e |
.set_domain = set_domain,
|
|
Packit Service |
a1973e |
.reset = _papi_pfm_reset,
|
|
Packit Service |
a1973e |
.set_overflow = _papi_pfm_set_overflow,
|
|
Packit Service |
a1973e |
.set_profile = _papi_pfm_set_profile,
|
|
Packit Service |
a1973e |
.stop_profiling = _papi_pfm_stop_profiling,
|
|
Packit Service |
a1973e |
.init_component = _papi_pfm_init_component,
|
|
Packit Service |
a1973e |
.dispatch_timer = _papi_pfm_dispatch_timer,
|
|
Packit Service |
a1973e |
.init_thread = _papi_pfm_init_thread,
|
|
Packit Service |
a1973e |
.allocate_registers = _papi_pfm_allocate_registers,
|
|
Packit Service |
a1973e |
.write = _papi_pfm_write,
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* from the counter name library */
|
|
Packit Service |
a1973e |
.ntv_enum_events = _papi_libpfm_ntv_enum_events,
|
|
Packit Service |
a1973e |
.ntv_name_to_code = _papi_libpfm_ntv_name_to_code,
|
|
Packit Service |
a1973e |
.ntv_code_to_name = _papi_libpfm_ntv_code_to_name,
|
|
Packit Service |
a1973e |
.ntv_code_to_descr = _papi_libpfm_ntv_code_to_descr,
|
|
Packit Service |
a1973e |
.ntv_code_to_bits = _papi_libpfm_ntv_code_to_bits,
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
};
|