Blame src/papi_libpfm3_events.c

Packit 577717
/*
Packit 577717
* File:    papi_libpfm3_events.c
Packit 577717
* Author:  Dan Terpstra: blantantly extracted from Phil's perfmon.c
Packit 577717
*          mucci@cs.utk.edu
Packit 577717
*
Packit 577717
*/
Packit 577717
Packit 577717
#include <ctype.h>
Packit 577717
#include <string.h>
Packit 577717
#include <errno.h>
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
Packit 577717
#include "perfmon/perfmon.h"
Packit 577717
#include "perfmon/pfmlib.h"
Packit 577717
Packit 577717
#include "papi_libpfm_events.h"
Packit 577717
Packit 577717
/* Native events consist of a flag field, an event field, and a unit mask field.
Packit 577717
 * These variables define the characteristics of the event and unit mask fields.
Packit 577717
 */
Packit 577717
unsigned int PAPI_NATIVE_EVENT_AND_MASK = 0x000003ff;
Packit 577717
unsigned int PAPI_NATIVE_EVENT_SHIFT = 0;
Packit 577717
unsigned int PAPI_NATIVE_UMASK_AND_MASK = 0x03fffc00;
Packit 577717
unsigned int PAPI_NATIVE_UMASK_MAX = 16;
Packit 577717
unsigned int PAPI_NATIVE_UMASK_SHIFT = 10;
Packit 577717
Packit 577717
/* Globals */
Packit 577717
int num_native_events=0;
Packit 577717
Packit 577717
Packit 577717
/* NOTE: PAPI stores umask info in a variable sized (16 bit?) bitfield.
Packit 577717
    Perfmon2 stores umask info in a large (48 element?) array of values.
Packit 577717
    Native event encodings for perfmon2 contain array indices
Packit 577717
    encoded as bits in this bitfield. These indices must be converted
Packit 577717
    into a umask value before programming the counters. For Perfmon,
Packit 577717
    this is done by converting back to an array of values; for 
Packit 577717
    perfctr, it must be done by looking up the values.
Packit 577717
*/
Packit 577717
Packit 577717
/* This routine is used to step through all possible combinations of umask
Packit 577717
    values. It assumes that mask contains a valid combination of array indices
Packit 577717
    for this event. */
Packit 577717
static inline int
Packit 577717
encode_native_event_raw( unsigned int event, unsigned int mask )
Packit 577717
{
Packit 577717
	unsigned int tmp = event << PAPI_NATIVE_EVENT_SHIFT;
Packit 577717
	SUBDBG( "Old native index was %#08x with %#08x mask\n", tmp, mask );
Packit 577717
	tmp = tmp | ( mask << PAPI_NATIVE_UMASK_SHIFT );
Packit 577717
	SUBDBG( "New encoding is %#08x\n", tmp | PAPI_NATIVE_MASK );
Packit 577717
	return ( int ) ( tmp | PAPI_NATIVE_MASK );
Packit 577717
}
Packit 577717
Packit 577717
/* This routine converts array indices contained in the mask_values array
Packit 577717
    into bits in the umask field that is OR'd into the native event code.
Packit 577717
    These bits are NOT the mask values themselves, but indices into an array
Packit 577717
    of mask values contained in the native event table. */
Packit 577717
static inline int
Packit 577717
encode_native_event( unsigned int event, unsigned int num_mask,
Packit 577717
					 unsigned int *mask_values )
Packit 577717
{
Packit 577717
	unsigned int i;
Packit 577717
	unsigned int tmp = event << PAPI_NATIVE_EVENT_SHIFT;
Packit 577717
	SUBDBG( "Native base event is %#08x with %d masks\n", tmp, num_mask );
Packit 577717
	for ( i = 0; i < num_mask; i++ ) {
Packit 577717
		SUBDBG( "Mask index is %#08x\n", mask_values[i] );
Packit 577717
		tmp = tmp | ( ( 1 << mask_values[i] ) << PAPI_NATIVE_UMASK_SHIFT );
Packit 577717
	}
Packit 577717
	SUBDBG( "Full native encoding is 0x%08x\n", tmp | PAPI_NATIVE_MASK );
Packit 577717
	return ( int ) ( tmp | PAPI_NATIVE_MASK );
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
/* Break a PAPI native event code into its composite event code and pfm mask bits */
Packit 577717
int
Packit 577717
_pfm_decode_native_event( unsigned int EventCode, unsigned int *event,
Packit 577717
						  unsigned int *umask )
Packit 577717
{
Packit 577717
	unsigned int tevent, major, minor;
Packit 577717
Packit 577717
	tevent = EventCode & PAPI_NATIVE_AND_MASK;
Packit 577717
	major = ( tevent & PAPI_NATIVE_EVENT_AND_MASK ) >> PAPI_NATIVE_EVENT_SHIFT;
Packit 577717
	if ( ( int ) major >= num_native_events )
Packit 577717
		return PAPI_ENOEVNT;
Packit 577717
Packit 577717
	minor = ( tevent & PAPI_NATIVE_UMASK_AND_MASK ) >> PAPI_NATIVE_UMASK_SHIFT;
Packit 577717
	*event = major;
Packit 577717
	*umask = minor;
Packit 577717
	SUBDBG( "EventCode %#08x is event %d, umask %#x\n", EventCode, major,
Packit 577717
			minor );
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/* convert a collection of pfm mask bits into an array of pfm mask indices */
Packit 577717
int
Packit 577717
prepare_umask( unsigned int foo, unsigned int *values )
Packit 577717
{
Packit 577717
	unsigned int tmp = foo, i;
Packit 577717
	int j = 0;
Packit 577717
Packit 577717
	SUBDBG( "umask %#x\n", tmp );
Packit 577717
	while ( ( i = ( unsigned int ) ffs( ( int ) tmp ) ) ) {
Packit 577717
		tmp = tmp ^ ( 1 << ( i - 1 ) );
Packit 577717
		values[j] = i - 1;
Packit 577717
		SUBDBG( "umask %d is %d\n", j, values[j] );
Packit 577717
		j++;
Packit 577717
	}
Packit 577717
	return ( j );
Packit 577717
}
Packit 577717
Packit 577717
/* convert the mask values in a pfm event structure into a PAPI unit mask */
Packit 577717
static inline unsigned int
Packit 577717
convert_pfm_masks( pfmlib_event_t * gete )
Packit 577717
{
Packit 577717
	int ret;
Packit 577717
	unsigned int i, code, tmp = 0;
Packit 577717
Packit 577717
	for ( i = 0; i < gete->num_masks; i++ ) {
Packit 577717
		if ( ( ret =
Packit 577717
			   pfm_get_event_mask_code( gete->event, gete->unit_masks[i],
Packit 577717
										&code ) ) == PFMLIB_SUCCESS ) {
Packit 577717
			SUBDBG( "Mask value is %#08x\n", code );
Packit 577717
			tmp |= code;
Packit 577717
		} else {
Packit 577717
			PAPIERROR( "pfm_get_event_mask_code(%#x,%d,%p): %s", gete->event,
Packit 577717
					   i, &code, pfm_strerror( ret ) );
Packit 577717
		}
Packit 577717
	}
Packit 577717
	return ( tmp );
Packit 577717
}
Packit 577717
Packit 577717
/* convert an event code and pfm unit mask into a PAPI unit mask */
Packit 577717
unsigned int
Packit 577717
_pfm_convert_umask( unsigned int event, unsigned int umask )
Packit 577717
{
Packit 577717
	pfmlib_event_t gete;
Packit 577717
	memset( &gete, 0, sizeof ( gete ) );
Packit 577717
	gete.event = event;
Packit 577717
	gete.num_masks = ( unsigned int ) prepare_umask( umask, gete.unit_masks );
Packit 577717
	return ( convert_pfm_masks( &gete ) );
Packit 577717
}
Packit 577717
Packit 577717
/* convert libpfm error codes to PAPI error codes for 
Packit 577717
	more informative error reporting */
Packit 577717
int
Packit 577717
_papi_libpfm_error( int pfm_error )
Packit 577717
{
Packit 577717
	switch ( pfm_error ) {
Packit 577717
		case PFMLIB_SUCCESS:		return PAPI_OK;			/* success */
Packit 577717
		case PFMLIB_ERR_NOTSUPP:	return PAPI_ENOSUPP;	/* function not supported */
Packit 577717
		case PFMLIB_ERR_INVAL:		return PAPI_EINVAL;		/* invalid parameters */
Packit 577717
		case PFMLIB_ERR_NOINIT:		return PAPI_ENOINIT;	/* library was not initialized */
Packit 577717
		case PFMLIB_ERR_NOTFOUND:	return PAPI_ENOEVNT;	/* event not found */
Packit 577717
		case PFMLIB_ERR_NOASSIGN:	return PAPI_ECNFLCT;	/* cannot assign events to counters */
Packit 577717
		case PFMLIB_ERR_FULL:		return PAPI_EBUF;		/* buffer is full or too small */
Packit 577717
		case PFMLIB_ERR_EVTMANY:	return PAPI_EMISC;		/* event used more than once */
Packit 577717
		case PFMLIB_ERR_MAGIC:		return PAPI_EBUG;		/* invalid library magic number */
Packit 577717
		case PFMLIB_ERR_FEATCOMB:	return PAPI_ECOMBO;		/* invalid combination of features */
Packit 577717
		case PFMLIB_ERR_EVTSET:		return PAPI_ENOEVST;	/* incompatible event sets */
Packit 577717
		case PFMLIB_ERR_EVTINCOMP:	return PAPI_ECNFLCT;	/* incompatible event combination */
Packit 577717
		case PFMLIB_ERR_TOOMANY:	return PAPI_ECOUNT;		/* too many events or unit masks */
Packit 577717
		case PFMLIB_ERR_BADHOST:	return PAPI_ESYS;		/* not supported by host CPU */
Packit 577717
		case PFMLIB_ERR_UMASK:		return PAPI_EATTR;		/* invalid or missing unit mask */
Packit 577717
		case PFMLIB_ERR_NOMEM:		return PAPI_ENOMEM;		/* out of memory */
Packit 577717
Packit 577717
		/* Itanium only */
Packit 577717
		case PFMLIB_ERR_IRRTOOBIG:		/* code range too big */
Packit 577717
		case PFMLIB_ERR_IRREMPTY:		/* empty code range */
Packit 577717
		case PFMLIB_ERR_IRRINVAL:		/* invalid code range */
Packit 577717
		case PFMLIB_ERR_IRRTOOMANY:		/* too many code ranges */
Packit 577717
		case PFMLIB_ERR_DRRINVAL:		/* invalid data range */
Packit 577717
		case PFMLIB_ERR_DRRTOOMANY:		/* too many data ranges */
Packit 577717
		case PFMLIB_ERR_IRRALIGN:		/* bad alignment for code range */
Packit 577717
		case PFMLIB_ERR_IRRFLAGS:		/* code range missing flags */
Packit 577717
		default:
Packit 577717
			return PAPI_EINVAL;
Packit 577717
	}
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_papi_libpfm_ntv_name_to_code( const char *name, unsigned int *event_code )
Packit 577717
{
Packit 577717
	pfmlib_event_t event;
Packit 577717
	unsigned int i;
Packit 577717
	int ret;
Packit 577717
Packit 577717
	SUBDBG( "pfm_find_full_event(%s,%p)\n", name, &event );
Packit 577717
	ret = pfm_find_full_event( name, &event );
Packit 577717
	if ( ret == PFMLIB_SUCCESS ) {
Packit 577717
		SUBDBG( "Full event name found\n" );
Packit 577717
		/* we can only capture PAPI_NATIVE_UMASK_MAX or fewer masks */
Packit 577717
		if ( event.num_masks > PAPI_NATIVE_UMASK_MAX ) {
Packit 577717
			SUBDBG( "num_masks (%d) > max masks (%d)\n", event.num_masks,
Packit 577717
					PAPI_NATIVE_UMASK_MAX );
Packit 577717
			return PAPI_ENOEVNT;
Packit 577717
		} else {
Packit 577717
			/* no mask index can exceed PAPI_NATIVE_UMASK_MAX */
Packit 577717
			for ( i = 0; i < event.num_masks; i++ ) {
Packit 577717
				if ( event.unit_masks[i] > PAPI_NATIVE_UMASK_MAX ) {
Packit 577717
					SUBDBG( "mask index (%d) > max masks (%d)\n",
Packit 577717
							event.unit_masks[i], PAPI_NATIVE_UMASK_MAX );
Packit 577717
					return PAPI_ENOEVNT;
Packit 577717
				}
Packit 577717
			}
Packit 577717
			*event_code =
Packit 577717
				encode_native_event( event.event, event.num_masks,
Packit 577717
									 event.unit_masks );
Packit 577717
			return PAPI_OK;
Packit 577717
		}
Packit 577717
	} else if ( ret == PFMLIB_ERR_UMASK ) {
Packit 577717
		SUBDBG( "UMASK error, looking for base event only\n" );
Packit 577717
		ret = pfm_find_event( name, &event.event );
Packit 577717
		if ( ret == PFMLIB_SUCCESS ) {
Packit 577717
			*event_code = encode_native_event( event.event, 0, 0 );
Packit 577717
			return PAPI_EATTR;
Packit 577717
		}
Packit 577717
	}
Packit 577717
	return PAPI_ENOEVNT;
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_papi_libpfm_ntv_code_to_name( unsigned int EventCode, char *ntv_name, int len )
Packit 577717
{
Packit 577717
	int ret;
Packit 577717
	unsigned int event, umask;
Packit 577717
	pfmlib_event_t gete;
Packit 577717
Packit 577717
	memset( &gete, 0, sizeof ( gete ) );
Packit 577717
Packit 577717
	if ( _pfm_decode_native_event( EventCode, &event, &umask ) != PAPI_OK )
Packit 577717
		return ( PAPI_ENOEVNT );
Packit 577717
Packit 577717
	gete.event = event;
Packit 577717
	gete.num_masks = ( unsigned int ) prepare_umask( umask, gete.unit_masks );
Packit 577717
	if ( gete.num_masks == 0 )
Packit 577717
		ret = pfm_get_event_name( gete.event, ntv_name, ( size_t ) len );
Packit 577717
	else
Packit 577717
		ret = pfm_get_full_event_name( &gete, ntv_name, ( size_t ) len );
Packit 577717
	if ( ret != PFMLIB_SUCCESS ) {
Packit 577717
		char tmp[PAPI_2MAX_STR_LEN];
Packit 577717
		pfm_get_event_name( gete.event, tmp, sizeof ( tmp ) );
Packit 577717
		/* Skip error message if event is not supported by host cpu;
Packit 577717
		 * we don't need to give this info away for papi_native_avail util */
Packit 577717
		if ( ret != PFMLIB_ERR_BADHOST )
Packit 577717
			PAPIERROR
Packit 577717
				( "pfm_get_full_event_name(%p(event %d,%s,%d masks),%p,%d): %d -- %s",
Packit 577717
				  &gete, gete.event, tmp, gete.num_masks, ntv_name, len, ret,
Packit 577717
				  pfm_strerror( ret ) );
Packit 577717
		if ( ret == PFMLIB_ERR_FULL ) {
Packit 577717
			return PAPI_EBUF;
Packit 577717
		}
Packit 577717
Packit 577717
		return PAPI_EMISC;
Packit 577717
	}
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_papi_libpfm_ntv_code_to_descr( unsigned int EventCode, char *ntv_descr, int len )
Packit 577717
{
Packit 577717
	unsigned int event, umask;
Packit 577717
	char *eventd, **maskd, *tmp;
Packit 577717
	int i, ret;
Packit 577717
	pfmlib_event_t gete;
Packit 577717
	size_t total_len = 0;
Packit 577717
Packit 577717
	memset( &gete, 0, sizeof ( gete ) );
Packit 577717
Packit 577717
	if ( _pfm_decode_native_event( EventCode, &event, &umask ) != PAPI_OK )
Packit 577717
		return ( PAPI_ENOEVNT );
Packit 577717
Packit 577717
	ret = pfm_get_event_description( event, &eventd );
Packit 577717
	if ( ret != PFMLIB_SUCCESS ) {
Packit 577717
		PAPIERROR( "pfm_get_event_description(%d,%p): %s",
Packit 577717
				   event, &eventd, pfm_strerror( ret ) );
Packit 577717
		return ( PAPI_ENOEVNT );
Packit 577717
	}
Packit 577717
Packit 577717
	if ( ( gete.num_masks =
Packit 577717
		   ( unsigned int ) prepare_umask( umask, gete.unit_masks ) ) ) {
Packit 577717
		maskd = ( char ** ) malloc( gete.num_masks * sizeof ( char * ) );
Packit 577717
		if ( maskd == NULL ) {
Packit 577717
			free( eventd );
Packit 577717
			return ( PAPI_ENOMEM );
Packit 577717
		}
Packit 577717
		for ( i = 0; i < ( int ) gete.num_masks; i++ ) {
Packit 577717
			ret =
Packit 577717
				pfm_get_event_mask_description( event, gete.unit_masks[i],
Packit 577717
												&maskd[i] );
Packit 577717
			if ( ret != PFMLIB_SUCCESS ) {
Packit 577717
				PAPIERROR( "pfm_get_event_mask_description(%d,%d,%p): %s",
Packit 577717
						   event, umask, &maskd, pfm_strerror( ret ) );
Packit 577717
				free( eventd );
Packit 577717
				for ( ; i >= 0; i-- )
Packit 577717
					free( maskd[i] );
Packit 577717
				free( maskd );
Packit 577717
				return ( PAPI_EINVAL );
Packit 577717
			}
Packit 577717
			total_len += strlen( maskd[i] );
Packit 577717
		}
Packit 577717
		tmp =
Packit 577717
			( char * ) malloc( strlen( eventd ) + strlen( ", masks:" ) +
Packit 577717
							   total_len + gete.num_masks + 1 );
Packit 577717
		if ( tmp == NULL ) {
Packit 577717
			for ( i = ( int ) gete.num_masks - 1; i >= 0; i-- )
Packit 577717
				free( maskd[i] );
Packit 577717
			free( maskd );
Packit 577717
			free( eventd );
Packit 577717
		}
Packit 577717
		tmp[0] = '\0';
Packit 577717
		strcat( tmp, eventd );
Packit 577717
		strcat( tmp, ", masks:" );
Packit 577717
		for ( i = 0; i < ( int ) gete.num_masks; i++ ) {
Packit 577717
			if ( i != 0 )
Packit 577717
				strcat( tmp, "," );
Packit 577717
			strcat( tmp, maskd[i] );
Packit 577717
			free( maskd[i] );
Packit 577717
		}
Packit 577717
		free( maskd );
Packit 577717
	} else {
Packit 577717
		tmp = ( char * ) malloc( strlen( eventd ) + 1 );
Packit 577717
		if ( tmp == NULL ) {
Packit 577717
			free( eventd );
Packit 577717
			return ( PAPI_ENOMEM );
Packit 577717
		}
Packit 577717
		tmp[0] = '\0';
Packit 577717
		strcat( tmp, eventd );
Packit 577717
		free( eventd );
Packit 577717
	}
Packit 577717
	strncpy( ntv_descr, tmp, ( size_t ) len );
Packit 577717
	if ( ( int ) strlen( tmp ) > len - 1 )
Packit 577717
		ret = PAPI_EBUF;
Packit 577717
	else
Packit 577717
		ret = PAPI_OK;
Packit 577717
	free( tmp );
Packit 577717
	return ( ret );
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
int
Packit 577717
_papi_libpfm_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info)
Packit 577717
{
Packit 577717
Packit 577717
  SUBDBG("ENTER %#x\n",EventCode);
Packit 577717
Packit 577717
  _papi_libpfm_ntv_code_to_name(EventCode,info->symbol,
Packit 577717
                                 sizeof(info->symbol));
Packit 577717
Packit 577717
  _papi_libpfm_ntv_code_to_descr(EventCode,info->long_descr,
Packit 577717
                                 sizeof(info->long_descr));
Packit 577717
Packit 577717
  return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
int
Packit 577717
_papi_libpfm_ntv_enum_events( unsigned int *EventCode, int modifier )
Packit 577717
{
Packit 577717
	unsigned int event, umask, num_masks;
Packit 577717
	int ret;
Packit 577717
Packit 577717
	if ( modifier == PAPI_ENUM_FIRST ) {
Packit 577717
		*EventCode = PAPI_NATIVE_MASK;	/* assumes first native event is always 0x4000000 */
Packit 577717
		return ( PAPI_OK );
Packit 577717
	}
Packit 577717
Packit 577717
	if ( _pfm_decode_native_event( *EventCode, &event, &umask ) != PAPI_OK )
Packit 577717
		return ( PAPI_ENOEVNT );
Packit 577717
Packit 577717
	ret = pfm_get_num_event_masks( event, &num_masks );
Packit 577717
	if ( ret != PFMLIB_SUCCESS ) {
Packit 577717
		PAPIERROR( "pfm_get_num_event_masks(%d,%p): %s", event, &num_masks,
Packit 577717
				   pfm_strerror( ret ) );
Packit 577717
		return ( PAPI_ENOEVNT );
Packit 577717
	}
Packit 577717
	if ( num_masks > PAPI_NATIVE_UMASK_MAX )
Packit 577717
		num_masks = PAPI_NATIVE_UMASK_MAX;
Packit 577717
	SUBDBG( "This is umask %d of %d\n", umask, num_masks );
Packit 577717
Packit 577717
	if ( modifier == PAPI_ENUM_EVENTS ) {
Packit 577717
		if ( event < ( unsigned int ) num_native_events - 1 ) {
Packit 577717
			*EventCode =
Packit 577717
				( unsigned int ) encode_native_event_raw( event + 1, 0 );
Packit 577717
			return ( PAPI_OK );
Packit 577717
		}
Packit 577717
		return ( PAPI_ENOEVNT );
Packit 577717
	} else if ( modifier == PAPI_NTV_ENUM_UMASK_COMBOS ) {
Packit 577717
		if ( umask + 1 < ( unsigned int ) ( 1 << num_masks ) ) {
Packit 577717
			*EventCode =
Packit 577717
				( unsigned int ) encode_native_event_raw( event, umask + 1 );
Packit 577717
			return ( PAPI_OK );
Packit 577717
		}
Packit 577717
		return ( PAPI_ENOEVNT );
Packit 577717
	} else if ( modifier == PAPI_NTV_ENUM_UMASKS ) {
Packit 577717
		int thisbit = ffs( ( int ) umask );
Packit 577717
Packit 577717
		SUBDBG( "First bit is %d in %08x\b\n", thisbit - 1, umask );
Packit 577717
		thisbit = 1 << thisbit;
Packit 577717
Packit 577717
		if ( thisbit & ( ( 1 << num_masks ) - 1 ) ) {
Packit 577717
			*EventCode =
Packit 577717
				( unsigned int ) encode_native_event_raw( event,
Packit 577717
														  ( unsigned int )
Packit 577717
														  thisbit );
Packit 577717
			return ( PAPI_OK );
Packit 577717
		}
Packit 577717
		return ( PAPI_ENOEVNT );
Packit 577717
	} else
Packit 577717
		return ( PAPI_EINVAL );
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
_papi_libpfm_ntv_code_to_bits( unsigned int EventCode, hwd_register_t * bits )
Packit 577717
{
Packit 577717
    unsigned int event, umask;
Packit 577717
    pfmlib_event_t gete;
Packit 577717
Packit 577717
    /* For PFM & Perfmon, native info is just an index into PFM event table. */
Packit 577717
    if ( _pfm_decode_native_event( EventCode, &event, &umask ) != PAPI_OK )
Packit 577717
       return PAPI_ENOEVNT;
Packit 577717
Packit 577717
    memset( &gete, 0x0, sizeof ( pfmlib_event_t ) );
Packit 577717
Packit 577717
    gete.event = event;
Packit 577717
    gete.num_masks = prepare_umask( umask, gete.unit_masks );
Packit 577717
Packit 577717
    memcpy( bits, &gete, sizeof ( pfmlib_event_t ) );
Packit 577717
Packit 577717
    return PAPI_OK;
Packit 577717
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
/* used by linux-timer.c for ia64 */
Packit 577717
int _perfmon2_pfm_pmu_type = -1;
Packit 577717
Packit 577717
Packit 577717
int
Packit 577717
_papi_libpfm_init(papi_vector_t *my_vector, int cidx) {
Packit 577717
Packit 577717
   int retval;
Packit 577717
   unsigned int ncnt;
Packit 577717
   unsigned int version;
Packit 577717
   char pmu_name[PAPI_MIN_STR_LEN];
Packit 577717
Packit 577717
Packit 577717
   /* The following checks the version of the PFM library
Packit 577717
      against the version PAPI linked to... */
Packit 577717
   SUBDBG( "pfm_initialize()\n" );
Packit 577717
   if ( ( retval = pfm_initialize(  ) ) != PFMLIB_SUCCESS ) {
Packit 577717
      PAPIERROR( "pfm_initialize(): %s", pfm_strerror( retval ) );
Packit 577717
      return PAPI_ESYS;
Packit 577717
   }
Packit 577717
Packit 577717
   /* Get the libpfm3 version */
Packit 577717
   SUBDBG( "pfm_get_version(%p)\n", &version );
Packit 577717
   if ( pfm_get_version( &version ) != PFMLIB_SUCCESS ) {
Packit 577717
      PAPIERROR( "pfm_get_version(%p): %s", version, pfm_strerror( retval ) );
Packit 577717
      return PAPI_ESYS;
Packit 577717
   }
Packit 577717
Packit 577717
   /* Set the version */
Packit 577717
   sprintf( my_vector->cmp_info.support_version, "%d.%d",
Packit 577717
	    PFM_VERSION_MAJOR( version ), PFM_VERSION_MINOR( version ) );
Packit 577717
Packit 577717
   /* Complain if the compiled-against version doesn't match current version */
Packit 577717
   if ( PFM_VERSION_MAJOR( version ) != PFM_VERSION_MAJOR( PFMLIB_VERSION ) ) {
Packit 577717
      PAPIERROR( "Version mismatch of libpfm: compiled %#x vs. installed %#x\n",
Packit 577717
				   PFM_VERSION_MAJOR( PFMLIB_VERSION ),
Packit 577717
				   PFM_VERSION_MAJOR( version ) );
Packit 577717
      return PAPI_ESYS;
Packit 577717
   }
Packit 577717
Packit 577717
   /* Always initialize globals dynamically to handle forks properly. */
Packit 577717
Packit 577717
   _perfmon2_pfm_pmu_type = -1;
Packit 577717
Packit 577717
   /* Opened once for all threads. */
Packit 577717
   SUBDBG( "pfm_get_pmu_type(%p)\n", &_perfmon2_pfm_pmu_type );
Packit 577717
   if ( pfm_get_pmu_type( &_perfmon2_pfm_pmu_type ) != PFMLIB_SUCCESS ) {
Packit 577717
      PAPIERROR( "pfm_get_pmu_type(%p): %s", _perfmon2_pfm_pmu_type,
Packit 577717
				   pfm_strerror( retval ) );
Packit 577717
      return PAPI_ESYS;
Packit 577717
   }
Packit 577717
Packit 577717
   pmu_name[0] = '\0';
Packit 577717
   if ( pfm_get_pmu_name( pmu_name, PAPI_MIN_STR_LEN ) != PFMLIB_SUCCESS ) {
Packit 577717
      PAPIERROR( "pfm_get_pmu_name(%p,%d): %s", pmu_name, PAPI_MIN_STR_LEN,
Packit 577717
				   pfm_strerror( retval ) );
Packit 577717
      return PAPI_ESYS;
Packit 577717
   }
Packit 577717
   SUBDBG( "PMU is a %s, type %d\n", pmu_name, _perfmon2_pfm_pmu_type );
Packit 577717
Packit 577717
   /* Setup presets */
Packit 577717
   retval = _papi_load_preset_table( pmu_name, _perfmon2_pfm_pmu_type, cidx );
Packit 577717
   if ( retval )
Packit 577717
      return retval;
Packit 577717
Packit 577717
   /* Fill in cmp_info */
Packit 577717
Packit 577717
   SUBDBG( "pfm_get_num_events(%p)\n", &ncnt );
Packit 577717
   if ( ( retval = pfm_get_num_events( &ncnt ) ) != PFMLIB_SUCCESS ) {
Packit 577717
      PAPIERROR( "pfm_get_num_events(%p): %s\n", &ncnt,
Packit 577717
				   pfm_strerror( retval ) );
Packit 577717
      return PAPI_ESYS;
Packit 577717
   }
Packit 577717
   SUBDBG( "pfm_get_num_events: %d\n", ncnt );
Packit 577717
   my_vector->cmp_info.num_native_events = ncnt;
Packit 577717
   num_native_events = ncnt;
Packit 577717
Packit 577717
   pfm_get_num_counters( ( unsigned int * ) &my_vector->cmp_info.num_cntrs );
Packit 577717
   SUBDBG( "pfm_get_num_counters: %d\n", my_vector->cmp_info.num_cntrs );
Packit 577717
Packit 577717
Packit 577717
   if ( _papi_hwi_system_info.hw_info.vendor == PAPI_VENDOR_INTEL ) {
Packit 577717
     /* Pentium4 */
Packit 577717
     if ( _papi_hwi_system_info.hw_info.cpuid_family == 15 ) {
Packit 577717
       PAPI_NATIVE_EVENT_AND_MASK = 0x000000ff;
Packit 577717
       PAPI_NATIVE_UMASK_AND_MASK = 0x0fffff00;
Packit 577717
       PAPI_NATIVE_UMASK_SHIFT = 8;
Packit 577717
       /* Itanium2 */
Packit 577717
     } else if ( _papi_hwi_system_info.hw_info.cpuid_family == 31 ||
Packit 577717
		 _papi_hwi_system_info.hw_info.cpuid_family == 32 ) {
Packit 577717
       PAPI_NATIVE_EVENT_AND_MASK = 0x00000fff;
Packit 577717
       PAPI_NATIVE_UMASK_AND_MASK = 0x0ffff000;
Packit 577717
       PAPI_NATIVE_UMASK_SHIFT = 12;
Packit 577717
     }
Packit 577717
   }
Packit 577717
Packit 577717
Packit 577717
   return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
long long generate_p4_event(long long escr,
Packit 577717
			    long long cccr,
Packit 577717
			    long long escr_addr) {
Packit 577717
		   
Packit 577717
/*
Packit 577717
 * RAW events specification
Packit 577717
 *
Packit 577717
 * Bits                Meaning
Packit 577717
 * -----       -------
Packit 577717
 *  0-6        Metric value from enum P4_PEBS_METRIC (if needed)
Packit 577717
 *  7-11       Reserved, set to 0
Packit 577717
 * 12-31       Bits 12-31 of CCCR register (Intel SDM Vol 3)
Packit 577717
 * 32-56       Bits  0-24 of ESCR register (Intel SDM Vol 3)
Packit 577717
 * 57-62       Event key from enum P4_EVENTS
Packit 577717
 *    63       Reserved, set to 0
Packit 577717
 */
Packit 577717
		   
Packit 577717
 enum P4_EVENTS {
Packit 577717
      P4_EVENT_TC_DELIVER_MODE,
Packit 577717
      P4_EVENT_BPU_FETCH_REQUEST,
Packit 577717
      P4_EVENT_ITLB_REFERENCE,
Packit 577717
      P4_EVENT_MEMORY_CANCEL,
Packit 577717
      P4_EVENT_MEMORY_COMPLETE,
Packit 577717
      P4_EVENT_LOAD_PORT_REPLAY,
Packit 577717
      P4_EVENT_STORE_PORT_REPLAY,
Packit 577717
      P4_EVENT_MOB_LOAD_REPLAY,
Packit 577717
      P4_EVENT_PAGE_WALK_TYPE,
Packit 577717
      P4_EVENT_BSQ_CACHE_REFERENCE,
Packit 577717
      P4_EVENT_IOQ_ALLOCATION,
Packit 577717
      P4_EVENT_IOQ_ACTIVE_ENTRIES,
Packit 577717
      P4_EVENT_FSB_DATA_ACTIVITY,
Packit 577717
      P4_EVENT_BSQ_ALLOCATION,
Packit 577717
      P4_EVENT_BSQ_ACTIVE_ENTRIES,
Packit 577717
      P4_EVENT_SSE_INPUT_ASSIST,
Packit 577717
      P4_EVENT_PACKED_SP_UOP,
Packit 577717
      P4_EVENT_PACKED_DP_UOP,
Packit 577717
      P4_EVENT_SCALAR_SP_UOP,
Packit 577717
      P4_EVENT_SCALAR_DP_UOP,
Packit 577717
      P4_EVENT_64BIT_MMX_UOP,
Packit 577717
      P4_EVENT_128BIT_MMX_UOP,
Packit 577717
      P4_EVENT_X87_FP_UOP,
Packit 577717
      P4_EVENT_TC_MISC,
Packit 577717
      P4_EVENT_GLOBAL_POWER_EVENTS,
Packit 577717
      P4_EVENT_TC_MS_XFER,
Packit 577717
      P4_EVENT_UOP_QUEUE_WRITES,
Packit 577717
      P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE,
Packit 577717
      P4_EVENT_RETIRED_BRANCH_TYPE,
Packit 577717
      P4_EVENT_RESOURCE_STALL,
Packit 577717
      P4_EVENT_WC_BUFFER,
Packit 577717
      P4_EVENT_B2B_CYCLES,
Packit 577717
      P4_EVENT_BNR,
Packit 577717
      P4_EVENT_SNOOP,
Packit 577717
      P4_EVENT_RESPONSE,
Packit 577717
      P4_EVENT_FRONT_END_EVENT,
Packit 577717
      P4_EVENT_EXECUTION_EVENT,
Packit 577717
      P4_EVENT_REPLAY_EVENT,
Packit 577717
      P4_EVENT_INSTR_RETIRED,
Packit 577717
      P4_EVENT_UOPS_RETIRED,
Packit 577717
      P4_EVENT_UOP_TYPE,
Packit 577717
      P4_EVENT_BRANCH_RETIRED,
Packit 577717
      P4_EVENT_MISPRED_BRANCH_RETIRED,
Packit 577717
      P4_EVENT_X87_ASSIST,
Packit 577717
      P4_EVENT_MACHINE_CLEAR,
Packit 577717
      P4_EVENT_INSTR_COMPLETED,
Packit 577717
   };
Packit 577717
		   
Packit 577717
		  		   
Packit 577717
    int eventsel=(escr>>25)&0x3f;
Packit 577717
    int cccrsel=(cccr>>13)&0x7;
Packit 577717
    int event_key=-1;
Packit 577717
    long long pe_event;
Packit 577717
		   
Packit 577717
    switch(eventsel) {
Packit 577717
       case 0x1: if (cccrsel==1) {
Packit 577717
		    if (escr_addr>0x3c8) {
Packit 577717
		       // tc_escr0,1 0x3c4 
Packit 577717
		       event_key=P4_EVENT_TC_DELIVER_MODE; 
Packit 577717
		    }
Packit 577717
		    else {
Packit 577717
		       // alf_escr0, 0x3ca    
Packit 577717
		       event_key=P4_EVENT_RESOURCE_STALL;
Packit 577717
		    }
Packit 577717
		 }
Packit 577717
		 if (cccrsel==4) {	    
Packit 577717
		    if (escr_addr<0x3af) {
Packit 577717
		       // pmh_escr0,1 0x3ac
Packit 577717
		       event_key=P4_EVENT_PAGE_WALK_TYPE;
Packit 577717
		    }
Packit 577717
		    else {
Packit 577717
		       // cru_escr0, 3b8 cccr=04
Packit 577717
		       event_key=P4_EVENT_UOPS_RETIRED;
Packit 577717
		    }
Packit 577717
		 }
Packit 577717
		 break;
Packit 577717
		    case 0x2: if (cccrsel==5) {
Packit 577717
		                 if (escr_addr<0x3a8) { 
Packit 577717
		                    // MSR_DAC_ESCR0 / MSR_DAC_ESCR1
Packit 577717
		                    event_key=P4_EVENT_MEMORY_CANCEL; 
Packit 577717
				 } else {
Packit 577717
				   //MSR_CRU_ESCR2, MSR_CRU_ESCR3
Packit 577717
				   event_key=P4_EVENT_MACHINE_CLEAR;
Packit 577717
				 }
Packit 577717
			      } else if (cccrsel==1) {
Packit 577717
		      	         event_key=P4_EVENT_64BIT_MMX_UOP;
Packit 577717
			      } else if (cccrsel==4) {
Packit 577717
			         event_key=P4_EVENT_INSTR_RETIRED;
Packit 577717
			      } else if (cccrsel==2) {
Packit 577717
			         event_key=P4_EVENT_UOP_TYPE;
Packit 577717
			      }
Packit 577717
			      break;
Packit 577717
		    case 0x3: if (cccrsel==0) {
Packit 577717
		                 event_key=P4_EVENT_BPU_FETCH_REQUEST;
Packit 577717
		              }
Packit 577717
                              if (cccrsel==2) {
Packit 577717
		                 event_key=P4_EVENT_MOB_LOAD_REPLAY;
Packit 577717
			      }
Packit 577717
		              if (cccrsel==6) {
Packit 577717
			         event_key=P4_EVENT_IOQ_ALLOCATION;
Packit 577717
			      }
Packit 577717
		              if (cccrsel==4) {
Packit 577717
			         event_key=P4_EVENT_MISPRED_BRANCH_RETIRED;
Packit 577717
		              }
Packit 577717
			      if (cccrsel==5) { 
Packit 577717
				 event_key=P4_EVENT_X87_ASSIST;
Packit 577717
		              }
Packit 577717
			      break;
Packit 577717
		    case 0x4: if (cccrsel==2) {
Packit 577717
		                 if (escr_addr<0x3b0) {
Packit 577717
				    // saat, 0x3ae 
Packit 577717
		                    event_key=P4_EVENT_LOAD_PORT_REPLAY; 
Packit 577717
		                 }
Packit 577717
		                 else {
Packit 577717
				    // tbpu 0x3c2
Packit 577717
		                    event_key=P4_EVENT_RETIRED_BRANCH_TYPE;
Packit 577717
				 }
Packit 577717
		              }
Packit 577717
		              if (cccrsel==1) {
Packit 577717
		      	         event_key=P4_EVENT_X87_FP_UOP;
Packit 577717
		              }
Packit 577717
			      if (cccrsel==3) {
Packit 577717
			         event_key=P4_EVENT_RESPONSE;
Packit 577717
		              }
Packit 577717
			      break;
Packit 577717
                    case 0x5: if (cccrsel==2) {
Packit 577717
		                 if (escr_addr<0x3b0) {
Packit 577717
		                    // saat, 0x3ae 
Packit 577717
		                    event_key=P4_EVENT_STORE_PORT_REPLAY;
Packit 577717
				 }
Packit 577717
		                 else {
Packit 577717
		                    // tbpu, 0x3c2
Packit 577717
		                    event_key=P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE;
Packit 577717
				 }
Packit 577717
		              }
Packit 577717
		              if (cccrsel==7) {
Packit 577717
		      	         event_key=P4_EVENT_BSQ_ALLOCATION;
Packit 577717
		              }
Packit 577717
		              if (cccrsel==0) {
Packit 577717
			         event_key=P4_EVENT_TC_MS_XFER;
Packit 577717
		              }
Packit 577717
			      if (cccrsel==5) {
Packit 577717
			         event_key=P4_EVENT_WC_BUFFER;
Packit 577717
		              }
Packit 577717
			      break;
Packit 577717
		    case 0x6: if (cccrsel==7) {
Packit 577717
		                 event_key=P4_EVENT_BSQ_ACTIVE_ENTRIES; 
Packit 577717
		              }
Packit 577717
		              if (cccrsel==1) {
Packit 577717
		      	         event_key=P4_EVENT_TC_MISC;
Packit 577717
			      }
Packit 577717
			      if (cccrsel==3) {
Packit 577717
				 event_key=P4_EVENT_SNOOP;
Packit 577717
			      }
Packit 577717
		              if (cccrsel==5) {
Packit 577717
			         event_key=P4_EVENT_BRANCH_RETIRED;
Packit 577717
			      }
Packit 577717
			      break;
Packit 577717
		    case 0x7: event_key=P4_EVENT_INSTR_COMPLETED; break;
Packit 577717
		    case 0x8: if (cccrsel==2) {
Packit 577717
		                 event_key=P4_EVENT_MEMORY_COMPLETE; 
Packit 577717
		              }
Packit 577717
		      	      if (cccrsel==1) {
Packit 577717
				 event_key=P4_EVENT_PACKED_SP_UOP;
Packit 577717
			      }
Packit 577717
			      if (cccrsel==3) {
Packit 577717
				 event_key=P4_EVENT_BNR;
Packit 577717
		              }
Packit 577717
			      if (cccrsel==5) {
Packit 577717
				 event_key=P4_EVENT_FRONT_END_EVENT;
Packit 577717
		              }
Packit 577717
			      break;
Packit 577717
                    case 0x9: if (cccrsel==0) {
Packit 577717
		                 event_key=P4_EVENT_UOP_QUEUE_WRITES; 
Packit 577717
		              }
Packit 577717
		      	      if (cccrsel==5) {
Packit 577717
				 event_key=P4_EVENT_REPLAY_EVENT;
Packit 577717
			      }
Packit 577717
			      break;
Packit 577717
                    case 0xa: event_key=P4_EVENT_SCALAR_SP_UOP; break;
Packit 577717
                    case 0xc: if (cccrsel==7) {
Packit 577717
		                 event_key=P4_EVENT_BSQ_CACHE_REFERENCE; 
Packit 577717
		              }
Packit 577717
		              if (cccrsel==1) {
Packit 577717
		      	         event_key=P4_EVENT_PACKED_DP_UOP;
Packit 577717
			      }
Packit 577717
			      if (cccrsel==5) {
Packit 577717
				 event_key=P4_EVENT_EXECUTION_EVENT;
Packit 577717
			      }
Packit 577717
			      break;
Packit 577717
		    case 0xe: event_key=P4_EVENT_SCALAR_DP_UOP; break;
Packit 577717
		    case 0x13: event_key=P4_EVENT_GLOBAL_POWER_EVENTS; break;
Packit 577717
                    case 0x16: event_key=P4_EVENT_B2B_CYCLES; break;
Packit 577717
		    case 0x17: event_key=P4_EVENT_FSB_DATA_ACTIVITY; break;
Packit 577717
		    case 0x18: event_key=P4_EVENT_ITLB_REFERENCE; break;
Packit 577717
                    case 0x1a: if (cccrsel==6) {
Packit 577717
		                  event_key=P4_EVENT_IOQ_ACTIVE_ENTRIES; 
Packit 577717
		               }
Packit 577717
		               if (cccrsel==1) {
Packit 577717
			          event_key=P4_EVENT_128BIT_MMX_UOP;
Packit 577717
		  }
Packit 577717
		  break;
Packit 577717
       case 0x34: event_key= P4_EVENT_SSE_INPUT_ASSIST; break;
Packit 577717
    }
Packit 577717
		   
Packit 577717
    pe_event=(escr&0x1ffffff)<<32;
Packit 577717
    pe_event|=(cccr&0xfffff000);		    
Packit 577717
    pe_event|=(((long long)(event_key))<<57);
Packit 577717
   
Packit 577717
    return pe_event;
Packit 577717
}
Packit 577717
Packit 577717
typedef pfmlib_event_t pfm_register_t;
Packit 577717
Packit 577717
int
Packit 577717
_papi_libpfm_setup_counters( struct perf_event_attr *attr, 
Packit 577717
			   hwd_register_t *ni_bits ) {
Packit 577717
Packit 577717
  int ret,pe_event;
Packit 577717
  (void)ni_bits;
Packit 577717
Packit 577717
    /*
Packit 577717
     * We need an event code that is common across all counters.
Packit 577717
     * The implementation is required to know how to translate the supplied
Packit 577717
     * code to whichever counter it ends up on.
Packit 577717
     */
Packit 577717
Packit 577717
#if defined(__powerpc__)
Packit 577717
    int code;
Packit 577717
    ret = pfm_get_event_code_counter( ( ( pfm_register_t * ) ni_bits )->event, 0, &code );
Packit 577717
    if ( ret ) {
Packit 577717
       /* Unrecognized code, but should never happen */
Packit 577717
       return PAPI_EBUG;
Packit 577717
    }
Packit 577717
    pe_event = code;
Packit 577717
    SUBDBG( "Stuffing native event index (code %#x, raw code %#x) into events array.\n",
Packit 577717
				  ( ( pfm_register_t * ) ni_bits )->event, code );
Packit 577717
#else
Packit 577717
Packit 577717
   pfmlib_input_param_t inp;
Packit 577717
   pfmlib_output_param_t outp;
Packit 577717
Packit 577717
   memset( &inp, 0, sizeof ( inp ) );
Packit 577717
   memset( &outp, 0, sizeof ( outp ) );
Packit 577717
   inp.pfp_event_count = 1;
Packit 577717
   inp.pfp_dfl_plm = PAPI_DOM_USER;
Packit 577717
   pfm_regmask_set( &inp.pfp_unavail_pmcs, 16 );	// mark fixed counters as unavailable
Packit 577717
Packit 577717
    inp.pfp_events[0] = *( ( pfm_register_t * ) ni_bits );
Packit 577717
    ret = pfm_dispatch_events( &inp, NULL, &outp, NULL );
Packit 577717
    if (ret != PFMLIB_SUCCESS) {
Packit 577717
       SUBDBG( "Error: pfm_dispatch_events returned: %d\n", ret);
Packit 577717
       return PAPI_ESYS;
Packit 577717
    }
Packit 577717
		   	
Packit 577717
       /* Special case p4 */
Packit 577717
    if (( _papi_hwi_system_info.hw_info.vendor == PAPI_VENDOR_INTEL ) && 
Packit 577717
        ( _papi_hwi_system_info.hw_info.cpuid_family == 15)) {
Packit 577717
Packit 577717
	pe_event=generate_p4_event( outp.pfp_pmcs[0].reg_value, /* escr */  
Packit 577717
		                    outp.pfp_pmcs[1].reg_value, /* cccr */
Packit 577717
		                    outp.pfp_pmcs[0].reg_addr); /* escr_addr */
Packit 577717
    }
Packit 577717
    else {
Packit 577717
        pe_event = outp.pfp_pmcs[0].reg_value;   
Packit 577717
    }
Packit 577717
    SUBDBG( "pe_event: %#llx\n", outp.pfp_pmcs[0].reg_value );
Packit 577717
#endif
Packit 577717
Packit 577717
    attr->config=pe_event;
Packit 577717
Packit 577717
    /* for libpfm3 we currently only handle RAW type */
Packit 577717
    attr->type=PERF_TYPE_RAW;
Packit 577717
Packit 577717
    return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
int 
Packit 577717
_papi_libpfm_shutdown(void) {
Packit 577717
Packit 577717
  SUBDBG("shutdown\n");
Packit 577717
Packit 577717
  return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717