Blame src/components/coretemp_freebsd/coretemp_freebsd.c

Packit 577717
/****************************/
Packit 577717
/* THIS IS OPEN SOURCE CODE */
Packit 577717
/****************************/
Packit 577717
Packit 577717
/**
Packit 577717
 * @file    coretemp_freebsd.c
Packit 577717
 * @author  Joachim Protze
Packit 577717
 *          joachim.protze@zih.tu-dresden.de
Packit 577717
 * @author  Vince Weaver
Packit 577717
 *          vweaver1@eecs.utk.edu
Packit 577717
 * @author  Harald Servat
Packit 577717
 *          harald.servat@gmail.com
Packit 577717
 *
Packit 577717
 * @ingroup papi_components
Packit 577717
 *
Packit 577717
 * @brief
Packit 577717
 *   This component is intended to access CPU On-Die Thermal Sensors in 
Packit 577717
 *   the Intel Core architecture in a FreeBSD machine using the coretemp.ko
Packit 577717
 *   kernel module.
Packit 577717
 */
Packit 577717
Packit 577717
#include <sys/types.h>
Packit 577717
#include <sys/resource.h>
Packit 577717
#include <sys/sysctl.h>
Packit 577717
Packit 577717
#include <stdio.h>
Packit 577717
#include <string.h>
Packit 577717
#include <stdlib.h>
Packit 577717
#include <inttypes.h>
Packit 577717
Packit 577717
/* Headers required by PAPI */
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
#define CORETEMP_MAX_COUNTERS 32 /* Can we tune this dynamically? */
Packit 577717
#define TRUE  (1==1)
Packit 577717
#define FALSE (1!=1)
Packit 577717
#define UNREFERENCED(x) (void)x
Packit 577717
Packit 577717
/* Structure that stores private information for each event */
Packit 577717
typedef struct coretemp_register
Packit 577717
{
Packit 577717
	int mib[4];
Packit 577717
	/* Access to registers through these MIBs + sysctl (3) call */
Packit 577717
	
Packit 577717
	unsigned int selector;
Packit 577717
	/**< Signifies which counter slot is being used */
Packit 577717
	/**< Indexed from 1 as 0 has a special meaning  */
Packit 577717
} coretemp_register_t;
Packit 577717
Packit 577717
/** This structure is used to build the table of events */
Packit 577717
typedef struct coretemp_native_event_entry
Packit 577717
{
Packit 577717
	coretemp_register_t resources;            /**< Per counter resources       */
Packit 577717
	char name[PAPI_MAX_STR_LEN];             /**< Name of the counter         */
Packit 577717
	char description[PAPI_MAX_STR_LEN];      /**< Description of the counter  */
Packit 577717
} coretemp_native_event_entry_t;
Packit 577717
Packit 577717
/* This structure is used when doing register allocation 
Packit 577717
   it possibly is not necessary when there are no 
Packit 577717
   register constraints */
Packit 577717
typedef struct coretemp_reg_alloc
Packit 577717
{
Packit 577717
	coretemp_register_t ra_bits;
Packit 577717
} coretemp_reg_alloc_t;
Packit 577717
Packit 577717
/* Holds control flags, usually out-of band configuration of the hardware */
Packit 577717
typedef struct coretemp_control_state
Packit 577717
{
Packit 577717
	int added[CORETEMP_MAX_COUNTERS];
Packit 577717
	long_long counters[CORETEMP_MAX_COUNTERS];	/**< Copy of counts, used for caching */
Packit 577717
} coretemp_control_state_t;
Packit 577717
Packit 577717
/* Holds per-thread information */
Packit 577717
typedef struct coretemp_context
Packit 577717
{
Packit 577717
	coretemp_control_state_t state;
Packit 577717
} coretemp_context_t;
Packit 577717
Packit 577717
/** This table contains the native events */
Packit 577717
static coretemp_native_event_entry_t *coretemp_native_table;
Packit 577717
Packit 577717
/** number of events in the table*/
Packit 577717
static int CORETEMP_NUM_EVENTS = 0;
Packit 577717
Packit 577717
Packit 577717
/********************************************************************/
Packit 577717
/* Below are the functions required by the PAPI component interface */
Packit 577717
/********************************************************************/
Packit 577717
Packit 577717
/** This is called whenever a thread is initialized */
Packit 577717
int coretemp_init_thread (hwd_context_t * ctx)
Packit 577717
{
Packit 577717
	int mib[4];
Packit 577717
	size_t len;
Packit 577717
	UNREFERENCED(ctx);
Packit 577717
Packit 577717
	SUBDBG("coretemp_init_thread %p...\n", ctx);
Packit 577717
Packit 577717
#if 0
Packit 577717
	/* what does this do?  VMW */
Packit 577717
Packit 577717
	len = 4;
Packit 577717
	if (sysctlnametomib ("dev.coretemp.0.%driver", mib, &len) == -1)
Packit 577717
		return PAPI_ECMP;
Packit 577717
#endif
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
/** Initialize hardware counters, setup the function vector table
Packit 577717
 * and get hardware information, this routine is called when the
Packit 577717
 * PAPI process is initialized (IE PAPI_library_init)
Packit 577717
 */
Packit 577717
int coretemp_init_component ()
Packit 577717
{
Packit 577717
	int ret;
Packit 577717
	int i;
Packit 577717
	int mib[4];
Packit 577717
	size_t len;
Packit 577717
	char tmp[128];
Packit 577717
Packit 577717
	SUBDBG("coretemp_init_component...\n");
Packit 577717
Packit 577717
	/* Count the number of cores (counters) that have sensors allocated */
Packit 577717
	i = 0;
Packit 577717
	CORETEMP_NUM_EVENTS = 0;
Packit 577717
	sprintf (tmp, "dev.coretemp.%d.%%driver", i);
Packit 577717
	len = 4;
Packit 577717
	ret = sysctlnametomib (tmp, mib, &len;;
Packit 577717
	while (ret != -1)
Packit 577717
	{
Packit 577717
		CORETEMP_NUM_EVENTS++;
Packit 577717
		i++;
Packit 577717
		sprintf (tmp, "dev.coretemp.%d.%%driver", i);
Packit 577717
		len = 4;
Packit 577717
		ret = sysctlnametomib (tmp, mib, &len;;
Packit 577717
	}
Packit 577717
Packit 577717
	if (CORETEMP_NUM_EVENTS == 0)
Packit 577717
		return PAPI_OK;
Packit 577717
Packit 577717
	/* Allocate memory for the our event table */
Packit 577717
	coretemp_native_table = (coretemp_native_event_entry_t *)
Packit 577717
		papi_malloc (sizeof (coretemp_native_event_entry_t) * CORETEMP_NUM_EVENTS);
Packit 577717
	if (coretemp_native_table == NULL)
Packit 577717
	{
Packit 577717
		perror( "malloc():Could not get memory for coretemp events table" );
Packit 577717
		return PAPI_ENOMEM;
Packit 577717
	}
Packit 577717
Packit 577717
	/* Allocate native events internal structures */
Packit 577717
	for (i = 0; i < CORETEMP_NUM_EVENTS; i++)
Packit 577717
	{
Packit 577717
		/* Event name */
Packit 577717
		sprintf (coretemp_native_table[i].name, "CORETEMP_CPU_%d", i);
Packit 577717
Packit 577717
		/* Event description */
Packit 577717
		sprintf (coretemp_native_table[i].description, "CPU On-Die Thermal Sensor #%d", i);
Packit 577717
Packit 577717
		/* Event extra bits -> save MIB to faster access later */
Packit 577717
		sprintf (tmp, "dev.cpu.%d.temperature", i);
Packit 577717
		len = 4;
Packit 577717
		if (sysctlnametomib (tmp, coretemp_native_table[i].resources.mib, &len) == -1)
Packit 577717
			return PAPI_ECMP;
Packit 577717
Packit 577717
		coretemp_native_table[i].resources.selector = i+1;
Packit 577717
	}
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
/** Setup the counter control structure */
Packit 577717
int coretemp_init_control_state (hwd_control_state_t * ctrl)
Packit 577717
{
Packit 577717
	int i;
Packit 577717
Packit 577717
	SUBDBG("coretemp_init_control_state... %p\n", ctrl);
Packit 577717
	coretemp_control_state_t *c = (coretemp_control_state_t *) ctrl;
Packit 577717
Packit 577717
	for (i = 0; i < CORETEMP_MAX_COUNTERS; i++)
Packit 577717
		c->added[i] = FALSE;
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
/** Enumerate Native Events 
Packit 577717
   @param EventCode is the event of interest
Packit 577717
   @param modifier is one of PAPI_ENUM_FIRST, PAPI_ENUM_EVENTS
Packit 577717
*/
Packit 577717
int coretemp_ntv_enum_events (unsigned int *EventCode, int modifier)
Packit 577717
{
Packit 577717
Packit 577717
	switch ( modifier )
Packit 577717
	{
Packit 577717
		/* return EventCode of first event */
Packit 577717
		case PAPI_ENUM_FIRST:
Packit 577717
		*EventCode = 0;
Packit 577717
		return PAPI_OK;
Packit 577717
		break;
Packit 577717
Packit 577717
		/* return EventCode of passed-in Event */
Packit 577717
		case PAPI_ENUM_EVENTS:
Packit 577717
		{
Packit 577717
			int index = *EventCode;
Packit 577717
Packit 577717
			if ( index < CORETEMP_NUM_EVENTS - 1 )
Packit 577717
			{
Packit 577717
				*EventCode = *EventCode + 1;
Packit 577717
				return PAPI_OK;
Packit 577717
			}
Packit 577717
			else
Packit 577717
				return PAPI_ENOEVNT;
Packit 577717
			break;
Packit 577717
		}
Packit 577717
Packit 577717
		default:
Packit 577717
			return PAPI_EINVAL;
Packit 577717
	}
Packit 577717
Packit 577717
	return PAPI_EINVAL;
Packit 577717
}
Packit 577717
Packit 577717
/** Takes a native event code and passes back the name 
Packit 577717
 @param EventCode is the native event code
Packit 577717
 @param name is a pointer for the name to be copied to
Packit 577717
 @param len is the size of the string
Packit 577717
 */
Packit 577717
int coretemp_ntv_code_to_name (unsigned int EventCode, char *name, int len)
Packit 577717
{
Packit 577717
	int index = EventCode;
Packit 577717
Packit 577717
	strncpy( name, coretemp_native_table[index].name, len );
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/** Takes a native event code and passes back the event description
Packit 577717
 @param EventCode is the native event code
Packit 577717
 @param name is a pointer for the description to be copied to
Packit 577717
 @param len is the size of the string
Packit 577717
 */
Packit 577717
int coretemp_ntv_code_to_descr (unsigned int EventCode, char *name, int len)
Packit 577717
{
Packit 577717
	int index = EventCode;
Packit 577717
Packit 577717
	strncpy( name, coretemp_native_table[index].description, len );
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/** This takes an event and returns the bits that would be written
Packit 577717
    out to the hardware device (this is very much tied to CPU-type support */
Packit 577717
int coretemp_ntv_code_to_bits (unsigned int EventCode, hwd_register_t * bits)
Packit 577717
{
Packit 577717
	UNREFERENCED(EventCode);
Packit 577717
	UNREFERENCED(bits);
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/** Triggered by eventset operations like add or remove */
Packit 577717
int coretemp_update_control_state( hwd_control_state_t * ptr,
Packit 577717
	NativeInfo_t * native, int count, hwd_context_t * ctx )
Packit 577717
{
Packit 577717
	int i, index;
Packit 577717
	coretemp_control_state_t *c = (coretemp_control_state_t *) ptr;
Packit 577717
	UNREFERENCED(ctx);
Packit 577717
Packit 577717
	SUBDBG("coretemp_update_control_state %p %p...\n", ptr, ctx);
Packit 577717
Packit 577717
	for (i = 0; i < count; i++)
Packit 577717
	{
Packit 577717
		index = native[i].ni_event;
Packit 577717
		native[i].ni_position = coretemp_native_table[index].resources.selector - 1;
Packit 577717
		c->added[native[i].ni_position] = TRUE;
Packit 577717
Packit 577717
		SUBDBG ("\nnative[%i].ni_position = coretemp_native_table[%i].resources.selector-1 = %i;\n",
Packit 577717
		  i, index, native[i].ni_position );
Packit 577717
	}
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/** Triggered by PAPI_start() */
Packit 577717
int coretemp_start (hwd_context_t * ctx, hwd_control_state_t * ctrl)
Packit 577717
{
Packit 577717
	UNREFERENCED(ctx);
Packit 577717
	UNREFERENCED(ctrl);
Packit 577717
Packit 577717
	SUBDBG( "coretemp_start %p %p...\n", ctx, ctrl );
Packit 577717
Packit 577717
	/* Nothing to be done */
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
/** Triggered by PAPI_stop() */
Packit 577717
int coretemp_stop (hwd_context_t * ctx, hwd_control_state_t * ctrl)
Packit 577717
{
Packit 577717
	UNREFERENCED(ctx);
Packit 577717
	UNREFERENCED(ctrl);
Packit 577717
Packit 577717
	SUBDBG("coretemp_stop %p %p...\n", ctx, ctrl);
Packit 577717
Packit 577717
	/* Nothing to be done */
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
/** Triggered by PAPI_read() */
Packit 577717
int coretemp_read (hwd_context_t * ctx, hwd_control_state_t * ctrl,
Packit 577717
	long_long ** events, int flags)
Packit 577717
{
Packit 577717
	int i;
Packit 577717
	coretemp_control_state_t *c = (coretemp_control_state_t *) ctrl;
Packit 577717
	UNREFERENCED(ctx);
Packit 577717
	UNREFERENCED(flags);
Packit 577717
Packit 577717
	SUBDBG("coretemp_read... %p %d\n", ctx, flags);
Packit 577717
Packit 577717
	for (i = 0; i < CORETEMP_MAX_COUNTERS; i++)
Packit 577717
		if (c->added[i])
Packit 577717
		{
Packit 577717
			int tmp;
Packit 577717
			size_t len = sizeof(tmp);
Packit 577717
Packit 577717
			if (sysctl (coretemp_native_table[i].resources.mib, 4, &tmp, &len, NULL, 0) == -1)
Packit 577717
				c->counters[i] = 0;
Packit 577717
			else
Packit 577717
				c->counters[i] = tmp/10;
Packit 577717
				/* Coretemp module returns temperature in tenths of kelvin 
Packit 577717
				   Kelvin are useful to avoid negative values... but will have
Packit 577717
				   negative temperatures ??? */
Packit 577717
		}
Packit 577717
Packit 577717
	*events = c->counters;
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/** Triggered by PAPI_write(), but only if the counters are running */
Packit 577717
/*    otherwise, the updated state is written to ESI->hw_start      */
Packit 577717
int coretemp_write (hwd_context_t * ctx, hwd_control_state_t * ctrl,
Packit 577717
	long_long events[] )
Packit 577717
{
Packit 577717
	UNREFERENCED(ctx);
Packit 577717
	UNREFERENCED(events);
Packit 577717
	UNREFERENCED(ctrl);
Packit 577717
Packit 577717
	SUBDBG("coretemp_write... %p %p\n", ctx, ctrl);
Packit 577717
Packit 577717
	/* These sensor counters cannot be writtn */
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
/** Triggered by PAPI_reset */
Packit 577717
int coretemp_reset(hwd_context_t * ctx, hwd_control_state_t * ctrl)
Packit 577717
{
Packit 577717
	UNREFERENCED(ctx);
Packit 577717
	UNREFERENCED(ctrl);
Packit 577717
Packit 577717
	SUBDBG("coretemp_reset ctx=%p ctrl=%p...\n", ctx, ctrl);
Packit 577717
Packit 577717
	/* These sensors cannot be reseted */
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/** Triggered by PAPI_shutdown() */
Packit 577717
int coretemp_shutdown_component (void)
Packit 577717
{
Packit 577717
Packit 577717
	SUBDBG( "coretemp_shutdown_component... %p\n");
Packit 577717
Packit 577717
	/* Last chance to clean up */
Packit 577717
	papi_free (coretemp_native_table);
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
Packit 577717
/** This function sets various options in the component
Packit 577717
  @param ctx unused
Packit 577717
  @param code valid are PAPI_SET_DEFDOM, PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL and PAPI_SET_INHERIT
Packit 577717
  @param option unused
Packit 577717
 */
Packit 577717
int coretemp_ctl (hwd_context_t * ctx, int code, _papi_int_option_t * option)
Packit 577717
{
Packit 577717
	UNREFERENCED(ctx);
Packit 577717
	UNREFERENCED(code);
Packit 577717
	UNREFERENCED(option);
Packit 577717
Packit 577717
	SUBDBG( "coretemp_ctl... %p %d %p\n", ctx, code, option );
Packit 577717
Packit 577717
	/* FIXME.  This should maybe set up more state, such as which counters are active and */
Packit 577717
	/*         counter mappings. */
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/** This function has to set the bits needed to count different domains
Packit 577717
    In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER
Packit 577717
    By default return PAPI_EINVAL if none of those are specified
Packit 577717
    and PAPI_OK with success
Packit 577717
    PAPI_DOM_USER is only user context is counted
Packit 577717
    PAPI_DOM_KERNEL is only the Kernel/OS context is counted
Packit 577717
    PAPI_DOM_OTHER  is Exception/transient mode (like user TLB misses)
Packit 577717
    PAPI_DOM_ALL   is all of the domains
Packit 577717
 */
Packit 577717
int coretemp_set_domain (hwd_control_state_t * cntrl, int domain)
Packit 577717
{
Packit 577717
	UNREFERENCED(cntrl);
Packit 577717
Packit 577717
	SUBDBG ("coretemp_set_domain... %p %d\n", cntrl, domain);
Packit 577717
Packit 577717
	if (PAPI_DOM_ALL & domain)
Packit 577717
	{
Packit 577717
		SUBDBG( " PAPI_DOM_ALL \n" );
Packit 577717
		return PAPI_OK;
Packit 577717
	}
Packit 577717
	return PAPI_EINVAL ;
Packit 577717
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
/** Vector that points to entry points for our component */
Packit 577717
papi_vector_t _coretemp_freebsd_vector = {
Packit 577717
	.cmp_info = {
Packit 577717
				 /* default component information (unspecified values are initialized to 0) */
Packit 577717
				 .name = "coretemp_freebsd",
Packit 577717
				 .short_name = "coretemp",
Packit 577717
				 .version = "5.0",
Packit 577717
				 .num_mpx_cntrs = CORETEMP_MAX_COUNTERS,
Packit 577717
				 .num_cntrs = CORETEMP_MAX_COUNTERS,
Packit 577717
				 .default_domain = PAPI_DOM_ALL,
Packit 577717
				 .available_domains = PAPI_DOM_ALL,
Packit 577717
				 .default_granularity = PAPI_GRN_SYS,
Packit 577717
				 .available_granularities = PAPI_GRN_SYS,
Packit 577717
				 .hardware_intr_sig = PAPI_INT_SIGNAL,
Packit 577717
Packit 577717
				 /* component specific cmp_info initializations */
Packit 577717
				 .fast_real_timer = 0,
Packit 577717
				 .fast_virtual_timer = 0,
Packit 577717
				 .attach = 0,
Packit 577717
				 .attach_must_ptrace = 0,
Packit 577717
				 }
Packit 577717
	,
Packit 577717
Packit 577717
	/* sizes of framework-opaque component-private structures */
Packit 577717
	.size = {
Packit 577717
			 .context = sizeof ( coretemp_context_t ),
Packit 577717
			 .control_state = sizeof ( coretemp_control_state_t ),
Packit 577717
			 .reg_value = sizeof ( coretemp_register_t ),
Packit 577717
			 .reg_alloc = sizeof ( coretemp_reg_alloc_t ),
Packit 577717
			 }
Packit 577717
	,
Packit 577717
	/* function pointers in this component */
Packit 577717
	.init_thread = coretemp_init_thread,
Packit 577717
	.init_component = coretemp_init_component,
Packit 577717
	.init_control_state = coretemp_init_control_state,
Packit 577717
	.start = coretemp_start,
Packit 577717
	.stop = coretemp_stop,
Packit 577717
	.read = coretemp_read,
Packit 577717
	.write = coretemp_write,
Packit 577717
	.shutdown_component = coretemp_shutdown_component,
Packit 577717
	.ctl = coretemp_ctl,
Packit 577717
Packit 577717
	.update_control_state = coretemp_update_control_state,
Packit 577717
	.set_domain = coretemp_set_domain,
Packit 577717
	.reset = coretemp_reset,
Packit 577717
Packit 577717
	.ntv_enum_events = coretemp_ntv_enum_events,
Packit 577717
	.ntv_code_to_name = coretemp_ntv_code_to_name,
Packit 577717
	.ntv_code_to_descr = coretemp_ntv_code_to_descr,
Packit 577717
	.ntv_code_to_bits = coretemp_ntv_code_to_bits,
Packit 577717
};
Packit 577717