Blame src/solaris-ultra.c

Packit 577717
/* 
Packit 577717
* File:    solaris-ultra.c
Packit 577717
* Author:  Philip Mucci
Packit 577717
*          mucci@cs.utk.edu
Packit 577717
* Mods:    Kevin London
Packit 577717
*          london@cs.utk.edu
Packit 577717
* Mods:    Min Zhou
Packit 577717
*          min@cs.utk.edu
Packit 577717
* Mods:    Larry Meadows(helped us to build the native table dynamically) 
Packit 577717
* Mods:    Brian Sheely
Packit 577717
*          bsheely@eecs.utk.edu 
Packit 577717
* Mods:    Vince Weaver
Packit 577717
*          vweaver1@eecs.utk.edu 
Packit 577717
*/
Packit 577717
Packit 577717
/* to understand this program, first you should read the user's manual
Packit 577717
   about UltraSparc II and UltraSparc III, then the man pages
Packit 577717
   about cpc_take_sample(cpc_event_t *event)
Packit 577717
*/
Packit 577717
Packit 577717
#include "papi.h"
Packit 577717
#include "papi_internal.h"
Packit 577717
#include "papi_vector.h"
Packit 577717
#include "papi_memory.h"
Packit 577717
#include <sys/utsname.h>
Packit 577717
Packit 577717
#include "solaris-common.h"
Packit 577717
#include "solaris-memory.h"
Packit 577717
Packit 577717
#ifdef CPC_ULTRA3_I
Packit 577717
#define LASTULTRA3 CPC_ULTRA3_I
Packit 577717
#else
Packit 577717
#define LASTULTRA3 CPC_ULTRA3_PLUS
Packit 577717
#endif
Packit 577717
Packit 577717
#define MAX_ENAME 40
Packit 577717
Packit 577717
static void action( void *arg, int regno, const char *name, uint8_t bits );
Packit 577717
Packit 577717
/* Probably could dispense with this and just use native_table */
Packit 577717
typedef struct ctr_info
Packit 577717
{
Packit 577717
	char *name;						   /* Counter name */
Packit 577717
	int bits[2];					   /* bits for register */
Packit 577717
	int bitmask;					   /* 1 = pic0; 2 = pic1; 3 = both */
Packit 577717
} ctr_info_t;
Packit 577717
Packit 577717
typedef struct einfo
Packit 577717
{
Packit 577717
	unsigned int papi_event;
Packit 577717
	char *event_str;
Packit 577717
} einfo_t;
Packit 577717
static einfo_t us3info[] = {
Packit 577717
	{PAPI_FP_INS, "FA_pipe_completion+FM_pipe_completion"},
Packit 577717
	{PAPI_FAD_INS, "FA_pipe_completion"},
Packit 577717
	{PAPI_FML_INS, "FM_pipe_completion"},
Packit 577717
	{PAPI_TLB_IM, "ITLB_miss"},
Packit 577717
	{PAPI_TLB_DM, "DTLB_miss"},
Packit 577717
	{PAPI_TOT_CYC, "Cycle_cnt"},
Packit 577717
	{PAPI_TOT_IIS, "Instr_cnt"},
Packit 577717
	{PAPI_TOT_INS, "Instr_cnt"},
Packit 577717
	{PAPI_L2_TCM, "EC_misses"},
Packit 577717
	{PAPI_L2_ICM, "EC_ic_miss"},
Packit 577717
	{PAPI_L1_ICM, "IC_miss"},
Packit 577717
	{PAPI_L1_LDM, "DC_rd_miss"},
Packit 577717
	{PAPI_L1_STM, "DC_wr_miss"},
Packit 577717
	{PAPI_L2_LDM, "EC_rd_miss"},
Packit 577717
	{PAPI_BR_MSP, "IU_Stat_Br_miss_taken+IU_Stat_Br_miss_untaken"},
Packit 577717
	{PAPI_L1_DCR, "DC_rd"},
Packit 577717
	{PAPI_L1_DCW, "DC_wr"},
Packit 577717
	{PAPI_L1_ICH, "IC_ref-IC_miss"},	/* Is this really hits only? */
Packit 577717
	{PAPI_L1_ICA, "IC_ref"}, /* Ditto? */
Packit 577717
	{PAPI_L2_TCH, "EC_ref-EC_misses"},
Packit 577717
	{PAPI_L2_TCA, "EC_ref"},
Packit 577717
};
Packit 577717
Packit 577717
static einfo_t us2info[] = {
Packit 577717
	{PAPI_L1_ICM, "IC_ref-IC_hit"},
Packit 577717
	{PAPI_L2_TCM, "EC_ref-EC_hit"},
Packit 577717
	{PAPI_CA_SNP, "EC_snoop_cb"},
Packit 577717
	{PAPI_CA_INV, "EC_snoop_inv"},
Packit 577717
	{PAPI_L1_LDM, "DC_rd-DC_rd_hit"},
Packit 577717
	{PAPI_L1_STM, "DC_wr-DC_wr_hit"},
Packit 577717
	{PAPI_L2_LDM, "EC_rd_miss"},
Packit 577717
	{PAPI_BR_MSP, "Dispatch0_mispred"},
Packit 577717
	{PAPI_TOT_IIS, "Instr_cnt"},
Packit 577717
	{PAPI_TOT_INS, "Instr_cnt"},
Packit 577717
	{PAPI_LD_INS, "DC_rd"},
Packit 577717
	{PAPI_SR_INS, "DC_wr"},
Packit 577717
	{PAPI_TOT_CYC, "Cycle_cnt"},
Packit 577717
	{PAPI_L1_DCR, "DC_rd"},
Packit 577717
	{PAPI_L1_DCW, "DC_wr"},
Packit 577717
	{PAPI_L1_ICH, "IC_hit"},
Packit 577717
	{PAPI_L2_ICH, "EC_ic_hit"},
Packit 577717
	{PAPI_L1_ICA, "IC_ref"},
Packit 577717
	{PAPI_L2_TCH, "EC_hit"},
Packit 577717
	{PAPI_L2_TCA, "EC_ref"},
Packit 577717
};
Packit 577717
Packit 577717
papi_vector_t _solaris_vector;
Packit 577717
Packit 577717
static native_info_t *native_table;
Packit 577717
static hwi_search_t *preset_table;
Packit 577717
Packit 577717
static struct ctr_info *ctrs;
Packit 577717
static int nctrs;
Packit 577717
Packit 577717
static int build_tables( void );
Packit 577717
static void add_preset( hwi_search_t * tab, int *np, einfo_t e );
Packit 577717
Packit 577717
/* Globals used to access the counter registers. */
Packit 577717
Packit 577717
static int cpuver;
Packit 577717
static int pcr_shift[2];
Packit 577717
Packit 577717
hwi_search_t *preset_search_map;
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
static void
Packit 577717
dump_cmd( papi_cpc_event_t * t )
Packit 577717
{
Packit 577717
	SUBDBG( "cpc_event_t.ce_cpuver %d\n", t->cmd.ce_cpuver );
Packit 577717
	SUBDBG( "ce_tick %llu\n", t->cmd.ce_tick );
Packit 577717
	SUBDBG( "ce_pic[0] %llu ce_pic[1] %llu\n", t->cmd.ce_pic[0],
Packit 577717
			t->cmd.ce_pic[1] );
Packit 577717
	SUBDBG( "ce_pcr %#llx\n", t->cmd.ce_pcr );
Packit 577717
	SUBDBG( "flags %#x\n", t->flags );
Packit 577717
}
Packit 577717
#endif
Packit 577717
Packit 577717
static void
Packit 577717
dispatch_emt( int signal, siginfo_t * sip, void *arg )
Packit 577717
{
Packit 577717
	int event_counter;
Packit 577717
	_papi_hwi_context_t ctx;
Packit 577717
	caddr_t address;
Packit 577717
	ctx.si = sip;
Packit 577717
	ctx.ucontext = arg;
Packit 577717
	SUBDBG( "%d, %p, %p\n", signal, sip, arg );
Packit 577717
Packit 577717
	if ( sip->si_code == EMT_CPCOVF ) {
Packit 577717
		papi_cpc_event_t *sample;
Packit 577717
		EventSetInfo_t *ESI;
Packit 577717
		ThreadInfo_t *thread = NULL;
Packit 577717
		int t, overflow_vector, readvalue;
Packit 577717
Packit 577717
		thread = _papi_hwi_lookup_thread( 0 );
Packit 577717
		ESI = ( EventSetInfo_t * ) thread->running_eventset;
Packit 577717
		int cidx = ESI->CmpIdx;
Packit 577717
Packit 577717
		if ( ( ESI == NULL ) || ( ( ESI->state & PAPI_OVERFLOWING ) == 0 ) ) {
Packit 577717
			OVFDBG( "Either no eventset or eventset not set to overflow.\n" );
Packit 577717
			return;
Packit 577717
		}
Packit 577717
Packit 577717
		if ( ESI->master != thread ) {
Packit 577717
			PAPIERROR
Packit 577717
				( "eventset->thread %%lx vs. current thread %#lx mismatch",
Packit 577717
				  ESI->master, thread );
Packit 577717
			return;
Packit 577717
		}
Packit 577717
Packit 577717
		event_counter = ESI->overflow.event_counter;
Packit 577717
		sample = &( ESI->ctl_state->counter_cmd );
Packit 577717
Packit 577717
		/* GROSS! This is a hack to 'push' the correct values 
Packit 577717
		   back into the hardware, such that when PAPI handles
Packit 577717
		   the overflow and reads the values, it gets the correct ones.
Packit 577717
		 */
Packit 577717
Packit 577717
		/* Find which HW counter overflowed */
Packit 577717
Packit 577717
		if ( ESI->EventInfoArray[ESI->overflow.EventIndex[0]].pos[0] == 0 )
Packit 577717
			t = 0;
Packit 577717
		else
Packit 577717
			t = 1;
Packit 577717
Packit 577717
		if ( cpc_take_sample( &sample->cmd ) == -1 )
Packit 577717
			return;
Packit 577717
		if ( event_counter == 1 ) {
Packit 577717
			/* only one event is set to be the overflow monitor */
Packit 577717
Packit 577717
			/* generate the overflow vector */
Packit 577717
			overflow_vector = 1 << t;
Packit 577717
			/* reset the threshold */
Packit 577717
			sample->cmd.ce_pic[t] = UINT64_MAX - ESI->overflow.threshold[0];
Packit 577717
		} else {
Packit 577717
			/* two events are set to be the overflow monitors */
Packit 577717
			overflow_vector = 0;
Packit 577717
			readvalue = sample->cmd.ce_pic[0];
Packit 577717
			if ( readvalue >= 0 ) {
Packit 577717
				/* the first counter overflowed */
Packit 577717
Packit 577717
				/* generate the overflow vector */
Packit 577717
				overflow_vector = 1;
Packit 577717
				/* reset the threshold */
Packit 577717
				if ( t == 0 )
Packit 577717
					sample->cmd.ce_pic[0] =
Packit 577717
						UINT64_MAX - ESI->overflow.threshold[0];
Packit 577717
				else
Packit 577717
					sample->cmd.ce_pic[0] =
Packit 577717
						UINT64_MAX - ESI->overflow.threshold[1];
Packit 577717
			}
Packit 577717
			readvalue = sample->cmd.ce_pic[1];
Packit 577717
			if ( readvalue >= 0 ) {
Packit 577717
				/* the second counter overflowed */
Packit 577717
Packit 577717
				/* generate the overflow vector */
Packit 577717
				overflow_vector ^= 1 << 1;
Packit 577717
				/* reset the threshold */
Packit 577717
				if ( t == 0 )
Packit 577717
					sample->cmd.ce_pic[1] =
Packit 577717
						UINT64_MAX - ESI->overflow.threshold[1];
Packit 577717
				else
Packit 577717
					sample->cmd.ce_pic[1] =
Packit 577717
						UINT64_MAX - ESI->overflow.threshold[0];
Packit 577717
			}
Packit 577717
			SUBDBG( "overflow_vector, = %d\n", overflow_vector );
Packit 577717
			/* something is wrong here */
Packit 577717
			if ( overflow_vector == 0 ) {
Packit 577717
				PAPIERROR( "BUG! overflow_vector is 0, dropping interrupt" );
Packit 577717
				return;
Packit 577717
			}
Packit 577717
		}
Packit 577717
Packit 577717
		/* Call the regular overflow function in extras.c */
Packit 577717
		if ( thread->running_eventset[cidx]->overflow.
Packit 577717
			 flags & PAPI_OVERFLOW_FORCE_SW ) {
Packit 577717
			address = GET_OVERFLOW_ADDRESS(ctx);
Packit 577717
			_papi_hwi_dispatch_overflow_signal( ( void * ) &ctx, address, NULL,
Packit 577717
												overflow_vector, 0, &thread,
Packit 577717
												cidx );
Packit 577717
		} else {
Packit 577717
			PAPIERROR( "Additional implementation needed in dispatch_emt!" );
Packit 577717
		}
Packit 577717
Packit 577717
#if DEBUG
Packit 577717
		dump_cmd( sample );
Packit 577717
#endif
Packit 577717
		/* push back the correct values and start counting again */
Packit 577717
		if ( cpc_bind_event( &sample->cmd, sample->flags ) == -1 )
Packit 577717
			return;
Packit 577717
	} else {
Packit 577717
		SUBDBG( "dispatch_emt() dropped, si_code = %d\n", sip->si_code );
Packit 577717
		return;
Packit 577717
	}
Packit 577717
}
Packit 577717
Packit 577717
static int
Packit 577717
scan_prtconf( char *cpuname, int len_cpuname, int *hz, int *ver )
Packit 577717
{
Packit 577717
	/* This code courtesy of our friends in Germany. Thanks Rudolph Berrendorf! */
Packit 577717
	/* See the PCL home page for the German version of PAPI. */
Packit 577717
	/* Modified by Nils Smeds, all new bugs are my fault */
Packit 577717
	/*    The routine now looks for the first "Node" with the following: */
Packit 577717
	/*           "device_type"     = 'cpu'                    */
Packit 577717
	/*           "name"            = (Any value)              */
Packit 577717
	/*           "sparc-version"   = (Any value)              */
Packit 577717
	/*           "clock-frequency" = (Any value)              */
Packit 577717
	int ihz, version;
Packit 577717
	char line[256], cmd[80], name[256];
Packit 577717
	FILE *f = NULL;
Packit 577717
	char cmd_line[PAPI_HUGE_STR_LEN + PAPI_HUGE_STR_LEN], fname[L_tmpnam];
Packit 577717
	unsigned int matched;
Packit 577717
Packit 577717
	/*??? system call takes very long */
Packit 577717
	/* get system configuration and put output into file */
Packit 577717
Packit 577717
	tmpnam( fname );
Packit 577717
	SUBDBG( "Temporary name %s\n", fname );
Packit 577717
Packit 577717
	sprintf( cmd_line, "/usr/sbin/prtconf -vp > %s", fname );
Packit 577717
	SUBDBG( "Executing %s\n", cmd_line );
Packit 577717
	if ( system( cmd_line ) == -1 ) {
Packit 577717
		remove( fname );
Packit 577717
		return -1;
Packit 577717
	}
Packit 577717
Packit 577717
	f = fopen( fname, "r" );
Packit 577717
	/* open output file */
Packit 577717
	if ( f == NULL ) {
Packit 577717
		remove( fname );
Packit 577717
		return -1;
Packit 577717
	}
Packit 577717
Packit 577717
	/* ignore all lines until we reach something with a sparc line */
Packit 577717
	matched = 0x0;
Packit 577717
	ihz = -1;
Packit 577717
	while ( fgets( line, 256, f ) != NULL ) {
Packit 577717
		/*SUBDBG(">>> %s",line); */
Packit 577717
		if ( ( sscanf( line, "%s", cmd ) == 1 )
Packit 577717
			 && strstr( line, "Node 0x" ) ) {
Packit 577717
			matched = 0x0;
Packit 577717
			/*SUBDBG("Found 'Node' -- search reset. (%#2.2x)\n",matched); */
Packit 577717
		} else {
Packit 577717
			if ( strstr( cmd, "device_type:" ) && strstr( line, "'cpu'" ) ) {
Packit 577717
				matched |= 0x1;
Packit 577717
				SUBDBG( "Found 'cpu'. (%#2.2x)\n", matched );
Packit 577717
			} else if ( !strcmp( cmd, "sparc-version:" ) &&
Packit 577717
						( sscanf( line, "%s %#x", cmd, &version ) == 2 ) ) {
Packit 577717
				matched |= 0x2;
Packit 577717
				SUBDBG( "Found version=%d. (%#2.2x)\n", version, matched );
Packit 577717
			} else if ( !strcmp( cmd, "clock-frequency:" ) &&
Packit 577717
						( sscanf( line, "%s %#x", cmd, &ihz ) == 2 ) ) {
Packit 577717
				matched |= 0x4;
Packit 577717
				SUBDBG( "Found ihz=%d. (%#2.2x)\n", ihz, matched );
Packit 577717
			} else if ( !strcmp( cmd, "name:" ) &&
Packit 577717
						( sscanf( line, "%s %s", cmd, name ) == 2 ) ) {
Packit 577717
				matched |= 0x8;
Packit 577717
				SUBDBG( "Found name: %s. (%#2.2x)\n", name, matched );
Packit 577717
			}
Packit 577717
		}
Packit 577717
		if ( ( matched & 0xF ) == 0xF )
Packit 577717
			break;
Packit 577717
	}
Packit 577717
	SUBDBG( "Parsing found name=%s, speed=%dHz, version=%d\n", name, ihz,
Packit 577717
			version );
Packit 577717
Packit 577717
	if ( matched ^ 0x0F )
Packit 577717
		ihz = -1;
Packit 577717
	else {
Packit 577717
		*hz = ( float ) ihz;
Packit 577717
		*ver = version;
Packit 577717
		strncpy( cpuname, name, len_cpuname );
Packit 577717
	}
Packit 577717
Packit 577717
	return ihz;
Packit 577717
Packit 577717
	/* End stolen code */
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_ultra_set_domain( hwd_control_state_t * this_state, int domain )
Packit 577717
{
Packit 577717
	papi_cpc_event_t *command = &this_state->counter_cmd;
Packit 577717
	cpc_event_t *event = &command->cmd;
Packit 577717
	uint64_t pcr = event->ce_pcr;
Packit 577717
	int did = 0;
Packit 577717
Packit 577717
	pcr = pcr | 0x7;
Packit 577717
	pcr = pcr ^ 0x7;
Packit 577717
Packit 577717
	if ( domain & PAPI_DOM_USER ) {
Packit 577717
		pcr = pcr | 1 << CPC_ULTRA_PCR_USR;
Packit 577717
		did = 1;
Packit 577717
	}
Packit 577717
	if ( domain & PAPI_DOM_KERNEL ) {
Packit 577717
		pcr = pcr | 1 << CPC_ULTRA_PCR_SYS;
Packit 577717
		did = 1;
Packit 577717
	}
Packit 577717
	/* DOMAIN ERROR */
Packit 577717
	if ( !did ) {
Packit 577717
		return ( PAPI_EINVAL );
Packit 577717
	}
Packit 577717
Packit 577717
	event->ce_pcr = pcr;
Packit 577717
Packit 577717
	return ( PAPI_OK );
Packit 577717
}
Packit 577717
Packit 577717
static int
Packit 577717
set_granularity( hwd_control_state_t * this_state, int domain )
Packit 577717
{
Packit 577717
	switch ( domain ) {
Packit 577717
	case PAPI_GRN_PROCG:
Packit 577717
	case PAPI_GRN_SYS:
Packit 577717
	case PAPI_GRN_SYS_CPU:
Packit 577717
	case PAPI_GRN_PROC:
Packit 577717
		return PAPI_ECMP;
Packit 577717
	case PAPI_GRN_THR:
Packit 577717
		break;
Packit 577717
	default:
Packit 577717
		return ( PAPI_EINVAL );
Packit 577717
	}
Packit 577717
	return ( PAPI_OK );
Packit 577717
}
Packit 577717
Packit 577717
/* Utility functions */
Packit 577717
Packit 577717
/* This is a wrapper arount fprintf(stderr,...) for cpc_walk_events() */
Packit 577717
void
Packit 577717
print_walk_names( void *arg, int regno, const char *name, uint8_t bits )
Packit 577717
{
Packit 577717
	SUBDBG( arg, regno, name, bits );
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
static int
Packit 577717
build_tables( void )
Packit 577717
{
Packit 577717
	int i;
Packit 577717
	int regno;
Packit 577717
	int npic;
Packit 577717
	einfo_t *ep;
Packit 577717
	int n;
Packit 577717
	int npresets;
Packit 577717
	npic = cpc_getnpic( cpuver );
Packit 577717
	nctrs = 0;
Packit 577717
	for ( regno = 0; regno < npic; ++regno ) {
Packit 577717
		cpc_walk_names( cpuver, regno, 0, action );
Packit 577717
	}
Packit 577717
	SUBDBG( "%d counters\n", nctrs );
Packit 577717
	if ( ( ctrs = papi_malloc( nctrs * sizeof ( struct ctr_info ) ) ) == 0 ) {
Packit 577717
		return PAPI_ENOMEM;
Packit 577717
	}
Packit 577717
	nctrs = 0;
Packit 577717
	for ( regno = 0; regno < npic; ++regno ) {
Packit 577717
		cpc_walk_names( cpuver, regno, ( void * ) 1, action );
Packit 577717
	}
Packit 577717
	SUBDBG( "%d counters\n", nctrs );
Packit 577717
#if DEBUG
Packit 577717
	if ( ISLEVEL( DEBUG_SUBSTRATE ) ) {
Packit 577717
		for ( i = 0; i < nctrs; ++i ) {
Packit 577717
			SUBDBG( "%s: bits (%#x,%#x) pics %#x\n", ctrs[i].name, ctrs[i].bits[0],
Packit 577717
					ctrs[i].bits[1], ctrs[i].bitmask );
Packit 577717
		}
Packit 577717
	}
Packit 577717
#endif
Packit 577717
	/* Build the native event table */
Packit 577717
	if ( ( native_table =
Packit 577717
		   papi_malloc( nctrs * sizeof ( native_info_t ) ) ) == 0 ) {
Packit 577717
		papi_free( ctrs );
Packit 577717
		return PAPI_ENOMEM;
Packit 577717
	}
Packit 577717
	for ( i = 0; i < nctrs; ++i ) {
Packit 577717
		native_table[i].name[39] = 0;
Packit 577717
		strncpy( native_table[i].name, ctrs[i].name, 39 );
Packit 577717
		if ( ctrs[i].bitmask & 1 )
Packit 577717
			native_table[i].encoding[0] = ctrs[i].bits[0];
Packit 577717
		else
Packit 577717
			native_table[i].encoding[0] = -1;
Packit 577717
		if ( ctrs[i].bitmask & 2 )
Packit 577717
			native_table[i].encoding[1] = ctrs[i].bits[1];
Packit 577717
		else
Packit 577717
			native_table[i].encoding[1] = -1;
Packit 577717
	}
Packit 577717
	papi_free( ctrs );
Packit 577717
Packit 577717
	/* Build the preset table */
Packit 577717
	if ( cpuver <= CPC_ULTRA2 ) {
Packit 577717
		n = sizeof ( us2info ) / sizeof ( einfo_t );
Packit 577717
		ep = us2info;
Packit 577717
	} else if ( cpuver <= LASTULTRA3 ) {
Packit 577717
		n = sizeof ( us3info ) / sizeof ( einfo_t );
Packit 577717
		ep = us3info;
Packit 577717
	} else
Packit 577717
		return PAPI_ECMP;
Packit 577717
	preset_table = papi_malloc( ( n + 1 ) * sizeof ( hwi_search_t ) );
Packit 577717
	npresets = 0;
Packit 577717
	for ( i = 0; i < n; ++i ) {
Packit 577717
		add_preset( preset_table, &npresets, ep[i] );
Packit 577717
	}
Packit 577717
	memset( &preset_table[npresets], 0, sizeof ( hwi_search_t ) );
Packit 577717
Packit 577717
#ifdef DEBUG
Packit 577717
	if ( ISLEVEL( DEBUG_SUBSTRATE ) ) {
Packit 577717
		SUBDBG( "Native table: %d\n", nctrs );
Packit 577717
		for ( i = 0; i < nctrs; ++i ) {
Packit 577717
			SUBDBG( "%40s: %8x %8x\n", native_table[i].name,
Packit 577717
					native_table[i].encoding[0], native_table[i].encoding[1] );
Packit 577717
		}
Packit 577717
		SUBDBG( "\nPreset table: %d\n", npresets );
Packit 577717
		for ( i = 0; preset_table[i].event_code != 0; ++i ) {
Packit 577717
			SUBDBG( "%8x: op %2d e0 %8x e1 %8x\n",
Packit 577717
					preset_table[i].event_code,
Packit 577717
					preset_table[i].data.derived,
Packit 577717
					preset_table[i].data.native[0],
Packit 577717
					preset_table[i].data.native[1] );
Packit 577717
		}
Packit 577717
	}
Packit 577717
#endif
Packit 577717
Packit 577717
	_solaris_vector.cmp_info.num_native_events = nctrs;
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
static int
Packit 577717
srch_event( char *e1 )
Packit 577717
{
Packit 577717
	int i;
Packit 577717
Packit 577717
	for ( i = 0; i < nctrs; ++i ) {
Packit 577717
		if ( strcmp( e1, native_table[i].name ) == 0 )
Packit 577717
			break;
Packit 577717
	}
Packit 577717
	if ( i >= nctrs )
Packit 577717
		return -1;
Packit 577717
	return i;
Packit 577717
}
Packit 577717
Packit 577717
/* we should read from the CSV file and make this all unnecessary */
Packit 577717
Packit 577717
static void
Packit 577717
add_preset( hwi_search_t * tab, int *np, einfo_t e )
Packit 577717
{
Packit 577717
	/* Parse the event info string and build the PAPI preset.
Packit 577717
	 * If parse fails, just return, otherwise increment the table
Packit 577717
	 * size. We assume that the table is big enough.
Packit 577717
	 */
Packit 577717
	char *p;
Packit 577717
	char *q;
Packit 577717
	char op;
Packit 577717
	char e1[MAX_ENAME], e2[MAX_ENAME];
Packit 577717
	int i;
Packit 577717
	int ne;
Packit 577717
	int ne2;
Packit 577717
Packit 577717
	p = e.event_str;
Packit 577717
	/* Assume p is the name of a native event, the sum of two
Packit 577717
	 * native events, or the difference of two native events.
Packit 577717
	 * This could be extended with a real parser (hint).
Packit 577717
	 */
Packit 577717
	while ( isspace( *p ) )
Packit 577717
		++p;
Packit 577717
	q = p;
Packit 577717
	i = 0;
Packit 577717
	while ( isalnum( *p ) || ( *p == '_' ) ) {
Packit 577717
		if ( i >= MAX_ENAME - 1 )
Packit 577717
			break;
Packit 577717
		e1[i] = *p++;
Packit 577717
		++i;
Packit 577717
	}
Packit 577717
	e1[i] = 0;
Packit 577717
	if ( *p == '+' || *p == '-' )
Packit 577717
		op = *p++;
Packit 577717
	else
Packit 577717
		op = 0;
Packit 577717
	while ( isspace( *p ) )
Packit 577717
		++p;
Packit 577717
	q = p;
Packit 577717
	i = 0;
Packit 577717
	while ( isalnum( *p ) || ( *p == '_' ) ) {
Packit 577717
		if ( i >= MAX_ENAME - 1 )
Packit 577717
			break;
Packit 577717
		e2[i] = *p++;
Packit 577717
		++i;
Packit 577717
	}
Packit 577717
	e2[i] = 0;
Packit 577717
Packit 577717
	if ( e2[0] == 0 && e1[0] == 0 ) {
Packit 577717
		return;
Packit 577717
	}
Packit 577717
	if ( e2[0] == 0 || op == 0 ) {
Packit 577717
		ne = srch_event( e1 );
Packit 577717
		if ( ne == -1 )
Packit 577717
			return;
Packit 577717
		tab[*np].event_code = e.papi_event;
Packit 577717
		tab[*np].data.derived = 0;
Packit 577717
		tab[*np].data.native[0] = PAPI_NATIVE_MASK | ne;
Packit 577717
		tab[*np].data.native[1] = PAPI_NULL;
Packit 577717
		memset( tab[*np].data.operation, 0,
Packit 577717
				sizeof ( tab[*np].data.operation ) );
Packit 577717
		++*np;
Packit 577717
		return;
Packit 577717
	}
Packit 577717
	ne = srch_event( e1 );
Packit 577717
	ne2 = srch_event( e2 );
Packit 577717
	if ( ne == -1 || ne2 == -1 )
Packit 577717
		return;
Packit 577717
	tab[*np].event_code = e.papi_event;
Packit 577717
	tab[*np].data.derived = ( op == '-' ) ? DERIVED_SUB : DERIVED_ADD;
Packit 577717
	tab[*np].data.native[0] = PAPI_NATIVE_MASK | ne;
Packit 577717
	tab[*np].data.native[1] = PAPI_NATIVE_MASK | ne2;
Packit 577717
	tab[*np].data.native[2] = PAPI_NULL;
Packit 577717
	memset( tab[*np].data.operation, 0, sizeof ( tab[*np].data.operation ) );
Packit 577717
	++*np;
Packit 577717
}
Packit 577717
Packit 577717
void
Packit 577717
action( void *arg, int regno, const char *name, uint8_t bits )
Packit 577717
{
Packit 577717
	int i;
Packit 577717
Packit 577717
	if ( arg == 0 ) {
Packit 577717
		++nctrs;
Packit 577717
		return;
Packit 577717
	}
Packit 577717
	assert( regno == 0 || regno == 1 );
Packit 577717
	for ( i = 0; i < nctrs; ++i ) {
Packit 577717
		if ( strcmp( ctrs[i].name, name ) == 0 ) {
Packit 577717
			ctrs[i].bits[regno] = bits;
Packit 577717
			ctrs[i].bitmask |= ( 1 << regno );
Packit 577717
			return;
Packit 577717
		}
Packit 577717
	}
Packit 577717
	memset( &ctrs[i], 0, sizeof ( ctrs[i] ) );
Packit 577717
	ctrs[i].name = papi_strdup( name );
Packit 577717
	ctrs[i].bits[regno] = bits;
Packit 577717
	ctrs[i].bitmask = ( 1 << regno );
Packit 577717
	++nctrs;
Packit 577717
}
Packit 577717
Packit 577717
/* This function should tell your kernel extension that your children
Packit 577717
   inherit performance register information and propagate the values up
Packit 577717
   upon child exit and parent wait. */
Packit 577717
Packit 577717
static int
Packit 577717
set_inherit( EventSetInfo_t * global, int arg )
Packit 577717
{
Packit 577717
	return PAPI_ECMP;
Packit 577717
Packit 577717
/*
Packit 577717
  hwd_control_state_t *machdep = (hwd_control_state_t *)global->machdep;
Packit 577717
  papi_cpc_event_t *command= &machdep->counter_cmd;
Packit 577717
Packit 577717
  return(PAPI_EINVAL);
Packit 577717
*/
Packit 577717
Packit 577717
#if 0
Packit 577717
	if ( arg == 0 ) {
Packit 577717
		if ( command->flags & CPC_BIND_LWP_INHERIT )
Packit 577717
			command->flags = command->flags ^ CPC_BIND_LWP_INHERIT;
Packit 577717
	} else if ( arg == 1 ) {
Packit 577717
		command->flags = command->flags | CPC_BIND_LWP_INHERIT;
Packit 577717
	} else
Packit 577717
		return ( PAPI_EINVAL );
Packit 577717
Packit 577717
	return ( PAPI_OK );
Packit 577717
#endif
Packit 577717
}
Packit 577717
Packit 577717
static int
Packit 577717
set_default_domain( hwd_control_state_t * ctrl_state, int domain )
Packit 577717
{
Packit 577717
	/* This doesn't exist on this platform */
Packit 577717
Packit 577717
	if ( domain == PAPI_DOM_OTHER )
Packit 577717
		return ( PAPI_EINVAL );
Packit 577717
Packit 577717
	return ( _ultra_set_domain( ctrl_state, domain ) );
Packit 577717
}
Packit 577717
Packit 577717
static int
Packit 577717
set_default_granularity( hwd_control_state_t * current_state, int granularity )
Packit 577717
{
Packit 577717
	return ( set_granularity( current_state, granularity ) );
Packit 577717
}
Packit 577717
Packit 577717
rwlock_t lock[PAPI_MAX_LOCK];
Packit 577717
Packit 577717
static void
Packit 577717
lock_init( void )
Packit 577717
{
Packit 577717
	memset( lock, 0x0, sizeof ( rwlock_t ) * PAPI_MAX_LOCK );
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_ultra_hwd_shutdown_component( void )
Packit 577717
{
Packit 577717
	( void ) cpc_rele(  );
Packit 577717
	return ( PAPI_OK );
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_ultra_hwd_init_component( int cidx )
Packit 577717
{
Packit 577717
	int retval;
Packit 577717
 /* retval = _papi_hwi_setup_vector_table(vtable, _solaris_ultra_table);
Packit 577717
	if ( retval != PAPI_OK ) return(retval); */
Packit 577717
Packit 577717
	/* Fill in what we can of the papi_system_info. */
Packit 577717
	retval = _solaris_get_system_info( &_papi_hwi_system_info );
Packit 577717
	if ( retval )
Packit 577717
		return ( retval );
Packit 577717
Packit 577717
	/* Setup memory info */
Packit 577717
        retval = _papi_os_vector.get_memory_info( &_papi_hwi_system_info.hw_info,
Packit 577717
				     0 );
Packit 577717
        if ( retval )
Packit 577717
	  return ( retval );
Packit 577717
Packit 577717
Packit 577717
	lock_init(  );
Packit 577717
Packit 577717
	SUBDBG( "Found %d %s %s CPUs at %d Mhz.\n",
Packit 577717
			_papi_hwi_system_info.hw_info.totalcpus,
Packit 577717
			_papi_hwi_system_info.hw_info.vendor_string,
Packit 577717
			_papi_hwi_system_info.hw_info.model_string,
Packit 577717
			_papi_hwi_system_info.hw_info.cpu_max_mhz );
Packit 577717
Packit 577717
	return ( PAPI_OK );
Packit 577717
}
Packit 577717
Packit 577717
/* reset the hardware counter */
Packit 577717
int
Packit 577717
_ultra_hwd_reset( hwd_context_t * ctx, hwd_control_state_t * ctrl )
Packit 577717
{
Packit 577717
	int retval;
Packit 577717
Packit 577717
	/* reset the hardware counter */
Packit 577717
	ctrl->counter_cmd.cmd.ce_pic[0] = 0;
Packit 577717
	ctrl->counter_cmd.cmd.ce_pic[1] = 0;
Packit 577717
	/* let's rock and roll */
Packit 577717
	retval = cpc_bind_event( &ctrl->counter_cmd.cmd, ctrl->counter_cmd.flags );
Packit 577717
	if ( retval == -1 )
Packit 577717
		return ( PAPI_ESYS );
Packit 577717
Packit 577717
	return ( PAPI_OK );
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
int
Packit 577717
_ultra_hwd_read( hwd_context_t * ctx, hwd_control_state_t * ctrl,
Packit 577717
				long long **events, int flags )
Packit 577717
{
Packit 577717
	int retval;
Packit 577717
Packit 577717
	retval = cpc_take_sample( &ctrl->counter_cmd.cmd );
Packit 577717
	if ( retval == -1 )
Packit 577717
		return ( PAPI_ESYS );
Packit 577717
Packit 577717
	*events = ( long long * ) ctrl->counter_cmd.cmd.ce_pic;
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_ultra_hwd_ctl( hwd_context_t * ctx, int code, _papi_int_option_t * option )
Packit 577717
{
Packit 577717
Packit 577717
	switch ( code ) {
Packit 577717
	case PAPI_DEFDOM:
Packit 577717
		return ( set_default_domain
Packit 577717
				 ( option->domain.ESI->ctl_state, option->domain.domain ) );
Packit 577717
	case PAPI_DOMAIN:
Packit 577717
		return ( _ultra_set_domain
Packit 577717
				 ( option->domain.ESI->ctl_state, option->domain.domain ) );
Packit 577717
	case PAPI_DEFGRN:
Packit 577717
		return ( set_default_granularity
Packit 577717
				 ( option->domain.ESI->ctl_state,
Packit 577717
				   option->granularity.granularity ) );
Packit 577717
	case PAPI_GRANUL:
Packit 577717
		return ( set_granularity
Packit 577717
				 ( option->granularity.ESI->ctl_state,
Packit 577717
				   option->granularity.granularity ) );
Packit 577717
	default:
Packit 577717
		return ( PAPI_EINVAL );
Packit 577717
	}
Packit 577717
}
Packit 577717
Packit 577717
void
Packit 577717
_ultra_hwd_dispatch_timer( int signal, siginfo_t * si, void *context )
Packit 577717
{
Packit 577717
Packit 577717
  _papi_hwi_context_t ctx;
Packit 577717
  ThreadInfo_t *master = NULL;
Packit 577717
  int isHardware = 0;
Packit 577717
  caddr_t address;
Packit 577717
  int cidx = _solaris_vector.cmp_info.CmpIdx;
Packit 577717
Packit 577717
  ctx.si = si;
Packit 577717
  ctx.ucontext = ( ucontext_t * ) context;
Packit 577717
Packit 577717
  address = GET_OVERFLOW_ADDRESS( ctx );
Packit 577717
  _papi_hwi_dispatch_overflow_signal( ( void * ) &ctx, address, &isHardware,
Packit 577717
				      0, 0, &master, _solaris_vector.cmp_info.CmpIdx );
Packit 577717
Packit 577717
  /* We are done, resume interrupting counters */
Packit 577717
  if ( isHardware ) {
Packit 577717
    //    errno = vperfctr_iresume( master->context[cidx]->perfctr );
Packit 577717
    //if ( errno < 0 ) {
Packit 577717
    //  PAPIERROR( "vperfctr_iresume errno %d", errno );
Packit 577717
    //}
Packit 577717
  }
Packit 577717
Packit 577717
Packit 577717
#if 0
Packit 577717
        EventSetInfo_t *ESI = NULL;
Packit 577717
        ThreadInfo_t *thread = NULL;
Packit 577717
        int overflow_vector = 0;
Packit 577717
        hwd_control_state_t *ctrl = NULL;
Packit 577717
        long_long results[MAX_COUNTERS];
Packit 577717
        int i;
Packit 577717
        _papi_hwi_context_t ctx;
Packit 577717
	caddr_t address;
Packit 577717
	int cidx = _solaris_vector.cmp_info.CmpIdx;
Packit 577717
Packit 577717
        ctx.si = si;
Packit 577717
        ctx.ucontext = ( hwd_ucontext_t * ) info;
Packit 577717
Packit 577717
	thread = _papi_hwi_lookup_thread( 0 );
Packit 577717
Packit 577717
	if ( thread == NULL ) {
Packit 577717
		PAPIERROR( "thread == NULL in _papi_hwd_dispatch_timer");
Packit 577717
		return;
Packit 577717
	}
Packit 577717
Packit 577717
        ESI = ( EventSetInfo_t * ) thread->running_eventset[cidx];
Packit 577717
Packit 577717
Packit 577717
	if ( ESI == NULL || ESI->master != thread || ESI->ctl_state == NULL ||
Packit 577717
	     ( ( ESI->state & PAPI_OVERFLOWING ) == 0 ) ) {
Packit 577717
Packit 577717
	  if ( ESI == NULL )
Packit 577717
	     PAPIERROR( "ESI is NULL\n");
Packit 577717
Packit 577717
	  if ( ESI->master != thread )
Packit 577717
	     PAPIERROR( "Thread mismatch, ESI->master=%#x thread=%#x\n",
Packit 577717
		        ESI->master, thread );
Packit 577717
Packit 577717
	  if ( ESI->ctl_state == NULL )
Packit 577717
	     PAPIERROR( "Counter state invalid\n");
Packit 577717
Packit 577717
	  if ( ( ( ESI->state & PAPI_OVERFLOWING ) == 0 ) )
Packit 577717
	    PAPIERROR( "Overflow flag missing");
Packit 577717
	}
Packit 577717
Packit 577717
	ctrl = ESI->ctl_state;
Packit 577717
Packit 577717
	if ( thread->running_eventset[cidx]->overflow.flags & PAPI_OVERFLOW_FORCE_SW ) {
Packit 577717
		address = GET_OVERFLOW_ADDRESS( ctx );
Packit 577717
		_papi_hwi_dispatch_overflow_signal( ( void * ) &ctx, address, NULL, 0,
Packit 577717
											0, &thread, cidx );
Packit 577717
       } else {
Packit 577717
	     PAPIERROR ( "Need to implement additional code in _papi_hwd_dispatch_timer!" );
Packit 577717
       }
Packit 577717
#endif
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_ultra_hwd_set_overflow( EventSetInfo_t * ESI, int EventIndex, int threshold )
Packit 577717
{
Packit 577717
	hwd_control_state_t *this_state = ESI->ctl_state;
Packit 577717
	papi_cpc_event_t *arg = &this_state->counter_cmd;
Packit 577717
	int hwcntr;
Packit 577717
Packit 577717
	if ( threshold == 0 ) {
Packit 577717
		if ( this_state->overflow_num == 1 ) {
Packit 577717
			arg->flags ^= CPC_BIND_EMT_OVF;
Packit 577717
			if ( sigaction
Packit 577717
				 ( _solaris_vector.cmp_info.hardware_intr_sig, NULL,
Packit 577717
				   NULL ) == -1 )
Packit 577717
				return ( PAPI_ESYS );
Packit 577717
			this_state->overflow_num = 0;
Packit 577717
		} else
Packit 577717
			this_state->overflow_num--;
Packit 577717
Packit 577717
	} else {
Packit 577717
		struct sigaction act;
Packit 577717
		/* increase the counter for overflow events */
Packit 577717
		this_state->overflow_num++;
Packit 577717
Packit 577717
		act.sa_sigaction = dispatch_emt;
Packit 577717
		memset( &act.sa_mask, 0x0, sizeof ( act.sa_mask ) );
Packit 577717
		act.sa_flags = SA_RESTART | SA_SIGINFO;
Packit 577717
		if ( sigaction
Packit 577717
			 ( _solaris_vector.cmp_info.hardware_intr_sig, &act,
Packit 577717
			   NULL ) == -1 )
Packit 577717
			return ( PAPI_ESYS );
Packit 577717
Packit 577717
		arg->flags |= CPC_BIND_EMT_OVF;
Packit 577717
		hwcntr = ESI->EventInfoArray[EventIndex].pos[0];
Packit 577717
		if ( hwcntr == 0 )
Packit 577717
			arg->cmd.ce_pic[0] = UINT64_MAX - ( uint64_t ) threshold;
Packit 577717
		else if ( hwcntr == 1 )
Packit 577717
			arg->cmd.ce_pic[1] = UINT64_MAX - ( uint64_t ) threshold;
Packit 577717
	}
Packit 577717
Packit 577717
	return ( PAPI_OK );
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
_ultra_shutdown( hwd_context_t * ctx )
Packit 577717
{
Packit 577717
Packit 577717
  return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
/*
Packit 577717
int _papi_hwd_stop_profiling(ThreadInfo_t * master, EventSetInfo_t * ESI)
Packit 577717
{
Packit 577717
   ESI->profile.overflowcount = 0;
Packit 577717
   return (PAPI_OK);
Packit 577717
}
Packit 577717
*/
Packit 577717
Packit 577717
void *
Packit 577717
_ultra_hwd_get_overflow_address( void *context )
Packit 577717
{
Packit 577717
	void *location;
Packit 577717
	ucontext_t *info = ( ucontext_t * ) context;
Packit 577717
	location = ( void * ) info->uc_mcontext.gregs[REG_PC];
Packit 577717
Packit 577717
	return ( location );
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_ultra_hwd_start( hwd_context_t * ctx, hwd_control_state_t * ctrl )
Packit 577717
{
Packit 577717
	int retval;
Packit 577717
Packit 577717
	/* reset the hardware counter */
Packit 577717
	if ( ctrl->overflow_num == 0 ) {
Packit 577717
		ctrl->counter_cmd.cmd.ce_pic[0] = 0;
Packit 577717
		ctrl->counter_cmd.cmd.ce_pic[1] = 0;
Packit 577717
	}
Packit 577717
	/* let's rock and roll */
Packit 577717
	retval = cpc_bind_event( &ctrl->counter_cmd.cmd, ctrl->counter_cmd.flags );
Packit 577717
	if ( retval == -1 )
Packit 577717
		return ( PAPI_ESYS );
Packit 577717
Packit 577717
	return ( PAPI_OK );
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_ultra_hwd_stop( hwd_context_t * ctx, hwd_control_state_t * ctrl )
Packit 577717
{
Packit 577717
	cpc_bind_event( NULL, 0 );
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_ultra_hwd_remove_event( hwd_register_map_t * chosen,
Packit 577717
						unsigned int hardware_index, hwd_control_state_t * out )
Packit 577717
{
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_ultra_hwd_encode_native( char *name, int *code )
Packit 577717
{
Packit 577717
	return ( PAPI_OK );
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_ultra_hwd_ntv_enum_events( unsigned int *EventCode, int modifier )
Packit 577717
{
Packit 577717
	int index = *EventCode & PAPI_NATIVE_AND_MASK;
Packit 577717
Packit 577717
	if ( modifier == PAPI_ENUM_FIRST ) {
Packit 577717
	   *EventCode = PAPI_NATIVE_MASK + 1;
Packit 577717
Packit 577717
	   return PAPI_OK;
Packit 577717
	}
Packit 577717
Packit 577717
	if ( cpuver <= CPC_ULTRA2 ) {
Packit 577717
		if ( index < MAX_NATIVE_EVENT_USII - 1 ) {
Packit 577717
			*EventCode = *EventCode + 1;
Packit 577717
			return ( PAPI_OK );
Packit 577717
		} else
Packit 577717
			return ( PAPI_ENOEVNT );
Packit 577717
	} else if ( cpuver <= LASTULTRA3 ) {
Packit 577717
		if ( index < MAX_NATIVE_EVENT - 1 ) {
Packit 577717
			*EventCode = *EventCode + 1;
Packit 577717
			return ( PAPI_OK );
Packit 577717
		} else
Packit 577717
			return ( PAPI_ENOEVNT );
Packit 577717
	};
Packit 577717
	return ( PAPI_ENOEVNT );
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_ultra_hwd_ntv_code_to_name( unsigned int EventCode, char *ntv_name, int len )
Packit 577717
{
Packit 577717
Packit 577717
        int event_code = EventCode & PAPI_NATIVE_AND_MASK;
Packit 577717
Packit 577717
	if ( event_code >= 0 && event_code < nctrs ) {
Packit 577717
	  strlcpy( ntv_name, native_table[event_code].name, len );
Packit 577717
	  return PAPI_OK;
Packit 577717
	}
Packit 577717
	return PAPI_ENOEVNT;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
int
Packit 577717
_ultra_hwd_ntv_code_to_descr( unsigned int EventCode, char *hwd_descr, int len )
Packit 577717
{
Packit 577717
	return ( _ultra_hwd_ntv_code_to_name( EventCode, hwd_descr, len ) );
Packit 577717
}
Packit 577717
Packit 577717
static void
Packit 577717
copy_value( unsigned int val, char *nam, char *names, unsigned int *values,
Packit 577717
			int len )
Packit 577717
{
Packit 577717
	*values = val;
Packit 577717
	strncpy( names, nam, len );
Packit 577717
	names[len - 1] = 0;
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_ultra_hwd_ntv_code_to_bits( unsigned int EventCode, hwd_register_t * bits )
Packit 577717
{
Packit 577717
	int index = EventCode & PAPI_NATIVE_AND_MASK;
Packit 577717
Packit 577717
	if ( cpuver <= CPC_ULTRA2 ) {
Packit 577717
		if ( index >= MAX_NATIVE_EVENT_USII ) {
Packit 577717
			return ( PAPI_ENOEVNT );
Packit 577717
		}
Packit 577717
	} else if ( cpuver <= LASTULTRA3 ) {
Packit 577717
		if ( index >= MAX_NATIVE_EVENT ) {
Packit 577717
			return ( PAPI_ENOEVNT );
Packit 577717
		}
Packit 577717
	} else
Packit 577717
		return ( PAPI_ENOEVNT );
Packit 577717
Packit 577717
	bits->event[0] = native_table[index].encoding[0];
Packit 577717
	bits->event[1] = native_table[index].encoding[1];
Packit 577717
	return ( PAPI_OK );
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_ultra_hwd_init_control_state( hwd_control_state_t * ptr )
Packit 577717
{
Packit 577717
	ptr->counter_cmd.flags = 0x0;
Packit 577717
	ptr->counter_cmd.cmd.ce_cpuver = cpuver;
Packit 577717
	ptr->counter_cmd.cmd.ce_pcr = 0x0;
Packit 577717
	ptr->counter_cmd.cmd.ce_pic[0] = 0;
Packit 577717
	ptr->counter_cmd.cmd.ce_pic[1] = 0;
Packit 577717
Packit 577717
	_ultra_set_domain( ptr, _solaris_vector.cmp_info.default_domain );
Packit 577717
	set_granularity( ptr, _solaris_vector.cmp_info.default_granularity );
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_ultra_hwd_update_control_state( hwd_control_state_t * this_state,
Packit 577717
								NativeInfo_t * native, int count,
Packit 577717
								hwd_context_t * zero )
Packit 577717
{
Packit 577717
	int nidx1, nidx2, hwcntr;
Packit 577717
	uint64_t tmp = 0;
Packit 577717
	uint64_t pcr;
Packit 577717
	int64_t cmd0, cmd1;
Packit 577717
Packit 577717
/* save the last three bits */
Packit 577717
	pcr = this_state->counter_cmd.cmd.ce_pcr & 0x7;
Packit 577717
Packit 577717
/* clear the control register */
Packit 577717
	this_state->counter_cmd.cmd.ce_pcr = pcr;
Packit 577717
Packit 577717
/* no native events left */
Packit 577717
	if ( count == 0 )
Packit 577717
		return ( PAPI_OK );
Packit 577717
Packit 577717
	cmd0 = -1;
Packit 577717
	cmd1 = -1;
Packit 577717
/* one native event */
Packit 577717
	if ( count == 1 ) {
Packit 577717
		nidx1 = native[0].ni_event & PAPI_NATIVE_AND_MASK;
Packit 577717
		hwcntr = 0;
Packit 577717
		cmd0 = native_table[nidx1].encoding[0];
Packit 577717
		native[0].ni_position = 0;
Packit 577717
		if ( cmd0 == -1 ) {
Packit 577717
			cmd1 = native_table[nidx1].encoding[1];
Packit 577717
			native[0].ni_position = 1;
Packit 577717
		}
Packit 577717
	}
Packit 577717
Packit 577717
/* two native events */
Packit 577717
	if ( count == 2 ) {
Packit 577717
		int avail1, avail2;
Packit 577717
Packit 577717
		avail1 = 0;
Packit 577717
		avail2 = 0;
Packit 577717
		nidx1 = native[0].ni_event & PAPI_NATIVE_AND_MASK;
Packit 577717
		nidx2 = native[1].ni_event & PAPI_NATIVE_AND_MASK;
Packit 577717
		if ( native_table[nidx1].encoding[0] != -1 )
Packit 577717
			avail1 = 0x1;
Packit 577717
		if ( native_table[nidx1].encoding[1] != -1 )
Packit 577717
			avail1 += 0x2;
Packit 577717
		if ( native_table[nidx2].encoding[0] != -1 )
Packit 577717
			avail2 = 0x1;
Packit 577717
		if ( native_table[nidx2].encoding[1] != -1 )
Packit 577717
			avail2 += 0x2;
Packit 577717
		if ( ( avail1 | avail2 ) != 0x3 )
Packit 577717
			return ( PAPI_ECNFLCT );
Packit 577717
		if ( avail1 == 0x3 ) {
Packit 577717
			if ( avail2 == 0x1 ) {
Packit 577717
				cmd0 = native_table[nidx2].encoding[0];
Packit 577717
				cmd1 = native_table[nidx1].encoding[1];
Packit 577717
				native[0].ni_position = 1;
Packit 577717
				native[1].ni_position = 0;
Packit 577717
			} else {
Packit 577717
				cmd1 = native_table[nidx2].encoding[1];
Packit 577717
				cmd0 = native_table[nidx1].encoding[0];
Packit 577717
				native[0].ni_position = 0;
Packit 577717
				native[1].ni_position = 1;
Packit 577717
			}
Packit 577717
		} else {
Packit 577717
			if ( avail1 == 0x1 ) {
Packit 577717
				cmd0 = native_table[nidx1].encoding[0];
Packit 577717
				cmd1 = native_table[nidx2].encoding[1];
Packit 577717
				native[0].ni_position = 0;
Packit 577717
				native[1].ni_position = 1;
Packit 577717
			} else {
Packit 577717
				cmd0 = native_table[nidx2].encoding[0];
Packit 577717
				cmd1 = native_table[nidx1].encoding[1];
Packit 577717
				native[0].ni_position = 1;
Packit 577717
				native[1].ni_position = 0;
Packit 577717
			}
Packit 577717
		}
Packit 577717
	}
Packit 577717
Packit 577717
/* set the control register */
Packit 577717
	if ( cmd0 != -1 ) {
Packit 577717
		tmp = ( ( uint64_t ) cmd0 << pcr_shift[0] );
Packit 577717
	}
Packit 577717
	if ( cmd1 != -1 ) {
Packit 577717
		tmp = tmp | ( ( uint64_t ) cmd1 << pcr_shift[1] );
Packit 577717
	}
Packit 577717
	this_state->counter_cmd.cmd.ce_pcr = tmp | pcr;
Packit 577717
#if DEBUG
Packit 577717
	dump_cmd( &this_state->counter_cmd );
Packit 577717
#endif
Packit 577717
Packit 577717
	return ( PAPI_OK );
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
Packit 577717
Packit 577717
papi_vector_t _solaris_vector = {
Packit 577717
	.cmp_info = {
Packit 577717
                                 .name = "solaris.ultra",
Packit 577717
                                 .description = "Solaris CPU counters",
Packit 577717
				 .num_cntrs = MAX_COUNTERS,
Packit 577717
				 .num_mpx_cntrs = MAX_COUNTERS,
Packit 577717
				 .default_domain = PAPI_DOM_USER,
Packit 577717
				 .available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL,
Packit 577717
				 .default_granularity = PAPI_GRN_THR,
Packit 577717
				 .available_granularities = PAPI_GRN_THR,
Packit 577717
				 .fast_real_timer = 1,
Packit 577717
				 .fast_virtual_timer = 1,
Packit 577717
				 .attach = 1,
Packit 577717
				 .attach_must_ptrace = 1,
Packit 577717
				 .hardware_intr = 0,
Packit 577717
				 .hardware_intr_sig = PAPI_INT_SIGNAL,
Packit 577717
				 .precise_intr = 0,
Packit 577717
				 }
Packit 577717
	,
Packit 577717
Packit 577717
	/* component data structure sizes */
Packit 577717
	.size = {
Packit 577717
			 .context = sizeof ( hwd_context_t ),
Packit 577717
			 .control_state = sizeof ( hwd_control_state_t ),
Packit 577717
			 .reg_value = sizeof ( hwd_register_t ),
Packit 577717
			 .reg_alloc = sizeof ( hwd_reg_alloc_t ),
Packit 577717
			 }
Packit 577717
	,
Packit 577717
Packit 577717
	/* component interface functions */
Packit 577717
	.init_control_state = _ultra_hwd_init_control_state,
Packit 577717
	.start = _ultra_hwd_start,
Packit 577717
	.stop = _ultra_hwd_stop,
Packit 577717
	.read = _ultra_hwd_read,
Packit 577717
        .shutdown = _ultra_shutdown,
Packit 577717
	.shutdown_component = _ultra_hwd_shutdown_component,
Packit 577717
	.ctl = _ultra_hwd_ctl,
Packit 577717
	.update_control_state = _ultra_hwd_update_control_state,
Packit 577717
        .set_domain = _ultra_set_domain,
Packit 577717
	.reset = _ultra_hwd_reset,
Packit 577717
	.set_overflow = _ultra_hwd_set_overflow,
Packit 577717
	/* .set_profile */
Packit 577717
	/* .stop_profiling = _papi_hwd_stop_profiling, */
Packit 577717
	.ntv_enum_events = _ultra_hwd_ntv_enum_events,
Packit 577717
        /* .ntv_name_to_code */
Packit 577717
	.ntv_code_to_name = _ultra_hwd_ntv_code_to_name,
Packit 577717
	.ntv_code_to_descr = _ultra_hwd_ntv_code_to_descr,
Packit 577717
	.ntv_code_to_bits = _ultra_hwd_ntv_code_to_bits,
Packit 577717
	.init_component = _ultra_hwd_init_component,
Packit 577717
	.dispatch_timer = _ultra_hwd_dispatch_timer,
Packit 577717
Packit 577717
};
Packit 577717
Packit 577717
papi_os_vector_t _papi_os_vector = {
Packit 577717
Packit 577717
	/* OS dependent local routines */
Packit 577717
        .get_memory_info =    _solaris_get_memory_info,
Packit 577717
        .get_dmem_info =      _solaris_get_dmem_info,
Packit 577717
	.update_shlib_info =  _solaris_update_shlib_info,
Packit 577717
	.get_system_info =    _solaris_get_system_info,
Packit 577717
	.get_real_usec =      _solaris_get_real_usec,
Packit 577717
	.get_real_cycles =    _solaris_get_real_cycles,
Packit 577717
	.get_virt_usec =      _solaris_get_virt_usec,
Packit 577717
};