Blame src/components/perfmon2/perfmon.c

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
};