Blame src/components/perf_event_uncore/perf_event_uncore.c

Packit 577717
/*
Packit 577717
* File:    perf_event_uncore.c
Packit 577717
*
Packit 577717
* Author:  Vince Weaver
Packit 577717
*          vincent.weaver@maine.edu
Packit 577717
* Mods:    Gary Mohr
Packit 577717
*          gary.mohr@bull.com
Packit 577717
*          Modified the perf_event_uncore component to use PFM_OS_PERF_EVENT_EXT mode in libpfm4.
Packit 577717
*          This adds several new event masks, including cpu=, u=, and k= which give the user
Packit 577717
*          the ability to set cpu number to use or control the domain (user, kernel, or both)
Packit 577717
*          in which the counter should be incremented.  These are event masks so it is now
Packit 577717
*          possible to have multiple events in the same event set that count activity from
Packit 577717
*          differennt cpu's or count activity in different domains.
Packit 577717
*/
Packit 577717
Packit 577717
#include <stdio.h>
Packit 577717
#include <fcntl.h>
Packit 577717
#include <string.h>
Packit 577717
#include <errno.h>
Packit 577717
#include <signal.h>
Packit 577717
#include <syscall.h>
Packit 577717
#include <sys/utsname.h>
Packit 577717
#include <sys/mman.h>
Packit 577717
#include <sys/ioctl.h>
Packit 577717
Packit 577717
/* PAPI-specific includes */
Packit 577717
#include "papi.h"
Packit 577717
#include "papi_memory.h"
Packit 577717
#include "papi_internal.h"
Packit 577717
#include "papi_vector.h"
Packit 577717
#include "extras.h"
Packit 577717
Packit 577717
/* libpfm4 includes */
Packit 577717
#include "papi_libpfm4_events.h"
Packit 577717
#include "components/perf_event/pe_libpfm4_events.h"
Packit 577717
#include "perfmon/pfmlib.h"
Packit 577717
#include PEINCLUDE
Packit 577717
Packit 577717
/* Linux-specific includes */
Packit 577717
#include "mb.h"
Packit 577717
#include "linux-memory.h"
Packit 577717
#include "linux-timer.h"
Packit 577717
#include "linux-common.h"
Packit 577717
#include "linux-context.h"
Packit 577717
Packit 577717
#include "components/perf_event/perf_event_lib.h"
Packit 577717
Packit 577717
/* Forward declaration */
Packit 577717
papi_vector_t _perf_event_uncore_vector;
Packit 577717
Packit 577717
/* Globals */
Packit 577717
struct native_event_table_t uncore_native_event_table;
Packit 577717
static int our_cidx;
Packit 577717
//int
Packit 577717
//_peu_libpfm4_get_cidx() {
Packit 577717
//	return our_cidx;
Packit 577717
//}
Packit 577717
Packit 577717
/* Defines for ctx->state */
Packit 577717
#define PERF_EVENTS_OPENED  0x01
Packit 577717
#define PERF_EVENTS_RUNNING 0x02
Packit 577717
Packit 577717
static int _peu_set_domain( hwd_control_state_t *ctl, int domain);
Packit 577717
Packit 577717
Packit 577717
Packit 577717
/******************************************************************/
Packit 577717
/******** Kernel Version Dependent Routines  **********************/
Packit 577717
/******************************************************************/
Packit 577717
Packit 577717
/* The read format on perf_event varies based on various flags that */
Packit 577717
/* are passed into it.  This helper avoids copying this logic       */
Packit 577717
/* multiple places.                                                 */
Packit 577717
static unsigned int
Packit 577717
get_read_format( unsigned int multiplex,
Packit 577717
		 unsigned int inherit,
Packit 577717
		 int format_group )
Packit 577717
{
Packit 577717
   unsigned int format = 0;
Packit 577717
Packit 577717
   /* if we need read format options for multiplexing, add them now */
Packit 577717
   if (multiplex) {
Packit 577717
      format |= PERF_FORMAT_TOTAL_TIME_ENABLED;
Packit 577717
      format |= PERF_FORMAT_TOTAL_TIME_RUNNING;
Packit 577717
   }
Packit 577717
Packit 577717
   /* If we are not using inherit, add the group read options     */
Packit 577717
   if (!inherit) {
Packit 577717
      if (format_group) {
Packit 577717
	 format |= PERF_FORMAT_GROUP;
Packit 577717
      }
Packit 577717
   }
Packit 577717
Packit 577717
   SUBDBG("multiplex: %d, inherit: %d, group_leader: %d, format: %#x\n",
Packit 577717
	  multiplex, inherit, format_group, format);
Packit 577717
Packit 577717
   return format;
Packit 577717
}
Packit 577717
Packit 577717
/*****************************************************************/
Packit 577717
/********* End Kernel-version Dependent Routines  ****************/
Packit 577717
/*****************************************************************/
Packit 577717
Packit 577717
/********************************************************************/
Packit 577717
/* Low-level perf_event calls                                       */
Packit 577717
/********************************************************************/
Packit 577717
Packit 577717
/* In case headers aren't new enough to have __NR_perf_event_open */
Packit 577717
#ifndef __NR_perf_event_open
Packit 577717
Packit 577717
#ifdef __powerpc__
Packit 577717
#define __NR_perf_event_open	319
Packit 577717
#elif defined(__x86_64__)
Packit 577717
#define __NR_perf_event_open	298
Packit 577717
#elif defined(__i386__)
Packit 577717
#define __NR_perf_event_open	336
Packit 577717
#elif defined(__arm__)          366+0x900000
Packit 577717
#define __NR_perf_event_open
Packit 577717
#endif
Packit 577717
Packit 577717
#endif
Packit 577717
Packit 577717
static long
Packit 577717
sys_perf_event_open( struct perf_event_attr *hw_event, pid_t pid, int cpu,
Packit 577717
					   int group_fd, unsigned long flags )
Packit 577717
{
Packit 577717
   int ret;
Packit 577717
Packit 577717
   SUBDBG("sys_perf_event_open(hw_event: %p, pid: %d, cpu: %d, group_fd: %d, flags: %lx\n",hw_event,pid,cpu,group_fd,flags);
Packit 577717
   SUBDBG("   type: %d\n",hw_event->type);
Packit 577717
   SUBDBG("   size: %d\n",hw_event->size);
Packit 577717
   SUBDBG("   config: %#"PRIx64" (%"PRIu64")\n",hw_event->config,
Packit 577717
	  hw_event->config);
Packit 577717
   SUBDBG("   sample_period: %"PRIu64"\n",hw_event->sample_period);
Packit 577717
   SUBDBG("   sample_type: %"PRIu64"\n",hw_event->sample_type);
Packit 577717
   SUBDBG("   read_format: %"PRIu64"\n",hw_event->read_format);
Packit 577717
   SUBDBG("   disabled: %d\n",hw_event->disabled);
Packit 577717
   SUBDBG("   inherit: %d\n",hw_event->inherit);
Packit 577717
   SUBDBG("   pinned: %d\n",hw_event->pinned);
Packit 577717
   SUBDBG("   exclusive: %d\n",hw_event->exclusive);
Packit 577717
   SUBDBG("   exclude_user: %d\n",hw_event->exclude_user);
Packit 577717
   SUBDBG("   exclude_kernel: %d\n",hw_event->exclude_kernel);
Packit 577717
   SUBDBG("   exclude_hv: %d\n",hw_event->exclude_hv);
Packit 577717
   SUBDBG("   exclude_idle: %d\n",hw_event->exclude_idle);
Packit 577717
   SUBDBG("   mmap: %d\n",hw_event->mmap);
Packit 577717
   SUBDBG("   comm: %d\n",hw_event->comm);
Packit 577717
   SUBDBG("   freq: %d\n",hw_event->freq);
Packit 577717
   SUBDBG("   inherit_stat: %d\n",hw_event->inherit_stat);
Packit 577717
   SUBDBG("   enable_on_exec: %d\n",hw_event->enable_on_exec);
Packit 577717
   SUBDBG("   task: %d\n",hw_event->task);
Packit 577717
   SUBDBG("   watermark: %d\n",hw_event->watermark);
Packit 577717
   SUBDBG("   precise_ip: %d\n",hw_event->precise_ip);
Packit 577717
   SUBDBG("   mmap_data: %d\n",hw_event->mmap_data);
Packit 577717
   SUBDBG("   sample_id_all: %d\n",hw_event->sample_id_all);
Packit 577717
   SUBDBG("   exclude_host: %d\n",hw_event->exclude_host);
Packit 577717
   SUBDBG("   exclude_guest: %d\n",hw_event->exclude_guest);
Packit 577717
   SUBDBG("   exclude_callchain_kernel: %d\n",hw_event->exclude_callchain_kernel);
Packit 577717
   SUBDBG("   exclude_callchain_user: %d\n",hw_event->exclude_callchain_user);
Packit 577717
   SUBDBG("   wakeup_watermark: %d\n",hw_event->wakeup_watermark);
Packit 577717
   SUBDBG("   bp_type: %d\n",hw_event->bp_type);
Packit 577717
   SUBDBG("   config1: %#lx (%lu)\n",hw_event->config1,hw_event->config1);
Packit 577717
   SUBDBG("   config2: %#lx (%lu)\n",hw_event->config2,hw_event->config2);
Packit 577717
   SUBDBG("   branch_sample_type: %lu\n",hw_event->branch_sample_type);
Packit 577717
   SUBDBG("   sample_regs_user: %lu\n",hw_event->sample_regs_user);
Packit 577717
   SUBDBG("   sample_stack_user: %d\n",hw_event->sample_stack_user);
Packit 577717
Packit 577717
	ret = syscall( __NR_perf_event_open, hw_event, pid, cpu, group_fd, flags );
Packit 577717
	SUBDBG("Returned %d %d %s\n",ret,
Packit 577717
	       ret<0?errno:0,
Packit 577717
	       ret<0?strerror(errno):" ");
Packit 577717
	return ret;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
static int map_perf_event_errors_to_papi(int perf_event_error) {
Packit 577717
Packit 577717
   int ret;
Packit 577717
Packit 577717
   /* These mappings are approximate.
Packit 577717
      EINVAL in particular can mean lots of different things */
Packit 577717
   switch(perf_event_error) {
Packit 577717
      case EPERM:
Packit 577717
      case EACCES:
Packit 577717
           ret = PAPI_EPERM;
Packit 577717
	   break;
Packit 577717
      case ENODEV:
Packit 577717
      case EOPNOTSUPP:
Packit 577717
	   ret = PAPI_ENOSUPP;
Packit 577717
           break;
Packit 577717
      case ENOENT:
Packit 577717
	   ret = PAPI_ENOEVNT;
Packit 577717
           break;
Packit 577717
      case ENOSYS:
Packit 577717
      case EAGAIN:
Packit 577717
      case EBUSY:
Packit 577717
      case E2BIG:
Packit 577717
	   ret = PAPI_ESYS;
Packit 577717
	   break;
Packit 577717
      case ENOMEM:
Packit 577717
	   ret = PAPI_ENOMEM;
Packit 577717
	   break;
Packit 577717
      case EINVAL:
Packit 577717
      default:
Packit 577717
	   ret = PAPI_EINVAL;
Packit 577717
           break;
Packit 577717
   }
Packit 577717
   return ret;
Packit 577717
}
Packit 577717
Packit 577717
/* Maximum size we ever expect to read from a perf_event fd   */
Packit 577717
/*  (this is the number of 64-bit values)                     */
Packit 577717
/* We use this to size the read buffers                       */
Packit 577717
/* The three is for event count, time_enabled, time_running   */
Packit 577717
/*  and the counter term is count value and count id for each */
Packit 577717
/*  possible counter value.                                   */
Packit 577717
#define READ_BUFFER_SIZE (3 + (2 * PERF_EVENT_MAX_MPX_COUNTERS))
Packit 577717
Packit 577717
Packit 577717
Packit 577717
/* KERNEL_CHECKS_SCHEDUABILITY_UPON_OPEN is a work-around for kernel arch */
Packit 577717
/* implementations (e.g. x86 before 2.6.33) which don't do a static event */
Packit 577717
/* scheduability check in sys_perf_event_open.  It is also needed if the  */
Packit 577717
/* kernel is stealing an event, such as when NMI watchdog is enabled.     */
Packit 577717
Packit 577717
static int
Packit 577717
check_scheduability( pe_context_t *ctx, pe_control_t *ctl)
Packit 577717
{
Packit 577717
   SUBDBG("ENTER: ctx: %p, ctl: %p\n", ctx, ctl);
Packit 577717
   int retval = 0, cnt = -1;
Packit 577717
   ( void ) ctx;	     /*unused */
Packit 577717
   long long papi_pe_buffer[READ_BUFFER_SIZE];
Packit 577717
   int i;
Packit 577717
Packit 577717
   /* If the kernel isn't tracking scheduability right       */
Packit 577717
   /* Then we need to start/stop/read to force the event     */
Packit 577717
   /* to be scheduled and see if an error condition happens. */
Packit 577717
Packit 577717
   /* start all events */
Packit 577717
   for( i = 0; i < ctl->num_events; i++) {
Packit 577717
      retval = ioctl( ctl->events[i].event_fd, PERF_EVENT_IOC_ENABLE, NULL );
Packit 577717
      if (retval == -1) {
Packit 577717
	 SUBDBG("EXIT: Enable failed event index: %d, num_events: %d, return PAPI_ESYS\n", i, ctl->num_events);
Packit 577717
	 return PAPI_ESYS;
Packit 577717
      }
Packit 577717
   }
Packit 577717
Packit 577717
   /* stop all events */
Packit 577717
   for( i = 0; i < ctl->num_events; i++) {
Packit 577717
      retval = ioctl(ctl->events[i].event_fd, PERF_EVENT_IOC_DISABLE, NULL );
Packit 577717
      if (retval == -1) {
Packit 577717
	 SUBDBG("EXIT: Disable failed: event index: %d, num_events: %d, return PAPI_ESYS\n", i, ctl->num_events);
Packit 577717
	 return PAPI_ESYS;
Packit 577717
      }
Packit 577717
   }
Packit 577717
Packit 577717
   /* See if a read of each event returns results */
Packit 577717
   for( i = 0; i < ctl->num_events; i++) {
Packit 577717
      cnt = read( ctl->events[i].event_fd, papi_pe_buffer, sizeof(papi_pe_buffer));
Packit 577717
      if ( cnt == -1 ) {
Packit 577717
	 SUBDBG( "EXIT: read failed: event index: %d, num_events: %d, return PAPI_ESYS.  Should never happen.\n", i, ctl->num_events);
Packit 577717
	 return PAPI_ESYS;
Packit 577717
      }
Packit 577717
Packit 577717
      if ( cnt == 0 ) {
Packit 577717
	 /* We read 0 bytes if we could not schedule the event */
Packit 577717
	 /* The kernel should have detected this at open       */
Packit 577717
	 /* but various bugs (including NMI watchdog)          */
Packit 577717
	 /* result in this behavior                            */
Packit 577717
Packit 577717
	 SUBDBG( "EXIT: read returned 0: event index: %d, num_events: %d, return PAPI_ECNFLCT.\n", i, ctl->num_events);
Packit 577717
	 return PAPI_ECNFLCT;
Packit 577717
      }
Packit 577717
   }
Packit 577717
Packit 577717
   /* Reset all of the counters (opened so far) back to zero      */
Packit 577717
   /* from the above brief enable/disable call pair.              */
Packit 577717
Packit 577717
   /* We have to reset all events because reset of group leader      */
Packit 577717
   /* does not reset all.                                            */
Packit 577717
   /* we assume that the events are being added one by one and that  */
Packit 577717
   /* we do not need to reset higher events (doing so may reset ones */
Packit 577717
   /* that have not been initialized yet.                            */
Packit 577717
Packit 577717
   /* Note... PERF_EVENT_IOC_RESET does not reset time running       */
Packit 577717
   /* info if multiplexing, so we should avoid coming here if        */
Packit 577717
   /* we are multiplexing the event.                                 */
Packit 577717
   for( i = 0; i < ctl->num_events; i++) {
Packit 577717
      retval=ioctl( ctl->events[i].event_fd, PERF_EVENT_IOC_RESET, NULL );
Packit 577717
      if (retval == -1) {
Packit 577717
	 SUBDBG("EXIT: Reset failed: event index: %d, num_events: %d, return PAPI_ESYS\n", i, ctl->num_events);
Packit 577717
	 return PAPI_ESYS;
Packit 577717
      }
Packit 577717
   }
Packit 577717
   SUBDBG("EXIT: return PAPI_OK\n");
Packit 577717
   return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
/* Open all events in the control state */
Packit 577717
static int
Packit 577717
open_pe_events( pe_context_t *ctx, pe_control_t *ctl )
Packit 577717
{
Packit 577717
Packit 577717
   int i, ret = PAPI_OK;
Packit 577717
   long pid;
Packit 577717
Packit 577717
   if (ctl->granularity==PAPI_GRN_SYS) {
Packit 577717
      pid = -1;
Packit 577717
   }
Packit 577717
   else {
Packit 577717
      pid = ctl->tid;
Packit 577717
   }
Packit 577717
Packit 577717
   for( i = 0; i < ctl->num_events; i++ ) {
Packit 577717
Packit 577717
      ctl->events[i].event_opened=0;
Packit 577717
Packit 577717
      /* set up the attr structure.  We don't set up all fields here */
Packit 577717
      /* as some have already been set up previously.                */
Packit 577717
Packit 577717
/*
Packit 577717
 * The following code controls how the uncore component interfaces with the 
Packit 577717
 * kernel for uncore events.  The code inside the ifdef will use grouping of 
Packit 577717
 * uncore events which can make the cost of reading the results more efficient.
Packit 577717
 * The problem with it is that the uncore component supports 20 different uncore 
Packit 577717
 * PMU's.  The kernel requires that all events in a group must be for the same PMU.
Packit 577717
 * This means that with grouping enabled papi applications can count events on only
Packit 577717
 * one of the 20 PMU's during a run.
Packit 577717
 * 
Packit 577717
 * The code inside the else clause treats each event in the event set as 
Packit 577717
 * independent.  When running in this mode the kernel allows the papi multiple 
Packit 577717
 * uncore PMU's at the same time.
Packit 577717
 * 
Packit 577717
 * Example:
Packit 577717
 *  An application wants to measure all the L3 cache write requests.
Packit 577717
 *  The event to do this is part of a cbox pmu (there are 8 cbox pmu's).
Packit 577717
 *  When built with the code in the ifdef, the application would have to be 
Packit 577717
 *    run 8 times and count write requests from one pmu at a time.
Packit 577717
 *  When built with the code in the else, the write requests in all 8 cbox 
Packit 577717
 *    pmu's could be counted in the same run.
Packit 577717
 * 
Packit 577717
 */
Packit 577717
// #define GROUPIT 1       // remove the comment on this line to force event grouping
Packit 577717
#ifdef GROUPIT
Packit 577717
      /* group leader (event 0) is special                */
Packit 577717
      /* If we're multiplexed, everyone is a group leader */
Packit 577717
      if (( i == 0 ) || (ctl->multiplexed)) {
Packit 577717
         ctl->events[i].attr.pinned = !ctl->multiplexed;
Packit 577717
	 ctl->events[i].attr.disabled = 1;
Packit 577717
	 ctl->events[i].group_leader_fd=-1;
Packit 577717
         ctl->events[i].attr.read_format = get_read_format(ctl->multiplexed,
Packit 577717
							   ctl->inherit,
Packit 577717
							   !ctl->multiplexed );
Packit 577717
      } else {
Packit 577717
	 ctl->events[i].attr.pinned=0;
Packit 577717
	 ctl->events[i].attr.disabled = 0;
Packit 577717
	 ctl->events[i].group_leader_fd=ctl->events[0].event_fd,
Packit 577717
         ctl->events[i].attr.read_format = get_read_format(ctl->multiplexed,
Packit 577717
							   ctl->inherit,
Packit 577717
							   0 );
Packit 577717
      }
Packit 577717
#else
Packit 577717
             ctl->events[i].attr.pinned = !ctl->multiplexed;
Packit 577717
         	 ctl->events[i].attr.disabled = 1;
Packit 577717
         	 ctl->inherit = 1;
Packit 577717
         	 ctl->events[i].group_leader_fd=-1;
Packit 577717
             ctl->events[i].attr.read_format = get_read_format(ctl->multiplexed, ctl->inherit, 0 );
Packit 577717
#endif
Packit 577717
Packit 577717
Packit 577717
      /* try to open */
Packit 577717
      ctl->events[i].event_fd = sys_perf_event_open( &ctl->events[i].attr,
Packit 577717
						     pid,
Packit 577717
						     ctl->events[i].cpu,
Packit 577717
			       ctl->events[i].group_leader_fd,
Packit 577717
						     0 /* flags */
Packit 577717
						     );
Packit 577717
Packit 577717
      /* Try to match Linux errors to PAPI errors */
Packit 577717
      if ( ctl->events[i].event_fd == -1 ) {
Packit 577717
	 SUBDBG("sys_perf_event_open returned error on event #%d."
Packit 577717
		"  Error: %s\n",
Packit 577717
		i, strerror( errno ) );
Packit 577717
         ret=map_perf_event_errors_to_papi(errno);
Packit 577717
Packit 577717
    goto open_peu_cleanup;
Packit 577717
      }
Packit 577717
Packit 577717
      SUBDBG ("sys_perf_event_open: tid: %ld, cpu_num: %d,"
Packit 577717
              " group_leader/fd: %d, event_fd: %d,"
Packit 577717
              " read_format: %"PRIu64"\n",
Packit 577717
	      pid, ctl->events[i].cpu, ctl->events[i].group_leader_fd,
Packit 577717
	      ctl->events[i].event_fd, ctl->events[i].attr.read_format);
Packit 577717
Packit 577717
      ctl->events[i].event_opened=1;
Packit 577717
   }
Packit 577717
Packit 577717
Packit 577717
   /* in many situations the kernel will indicate we opened fine */
Packit 577717
   /* yet things will fail later.  So we need to double check    */
Packit 577717
   /* we actually can use the events we've set up.               */
Packit 577717
Packit 577717
   /* This is not necessary if we are multiplexing, and in fact */
Packit 577717
   /* we cannot do this properly if multiplexed because         */
Packit 577717
   /* PERF_EVENT_IOC_RESET does not reset the time running info */
Packit 577717
   if (!ctl->multiplexed) {
Packit 577717
	ret = check_scheduability( ctx, ctl);
Packit 577717
Packit 577717
	if ( ret != PAPI_OK ) {
Packit 577717
	    /* the last event did open, so we need to bump the counter */
Packit 577717
	    /* before doing the cleanup                                */
Packit 577717
	    i++;
Packit 577717
	    goto open_peu_cleanup;
Packit 577717
	}
Packit 577717
   }
Packit 577717
Packit 577717
   /* Now that we've successfully opened all of the events, do whatever  */
Packit 577717
   /* "tune-up" is needed to attach the mmap'd buffers, signal handlers, */
Packit 577717
   /* and so on.                                                         */
Packit 577717
   for ( i = 0; i < ctl->num_events; i++ ) {
Packit 577717
Packit 577717
      /* No sampling if uncore */
Packit 577717
      ctl->events[i].mmap_buf = NULL;
Packit 577717
   }
Packit 577717
Packit 577717
   /* Set num_evts only if completely successful */
Packit 577717
   ctx->state |= PERF_EVENTS_OPENED;
Packit 577717
Packit 577717
   return PAPI_OK;
Packit 577717
Packit 577717
open_peu_cleanup:
Packit 577717
   /* We encountered an error, close up the fds we successfully opened.  */
Packit 577717
   /* We go backward in an attempt to close group leaders last, although */
Packit 577717
   /* That's probably not strictly necessary.                            */
Packit 577717
   while ( i > 0 ) {
Packit 577717
      i--;
Packit 577717
      if (ctl->events[i].event_fd>=0) {
Packit 577717
	 close( ctl->events[i].event_fd );
Packit 577717
	 ctl->events[i].event_opened=0;
Packit 577717
      }
Packit 577717
   }
Packit 577717
Packit 577717
   return ret;
Packit 577717
}
Packit 577717
Packit 577717
/* Close all of the opened events */
Packit 577717
static int
Packit 577717
close_pe_events( pe_context_t *ctx, pe_control_t *ctl )
Packit 577717
{
Packit 577717
   int i;
Packit 577717
   int num_closed=0;
Packit 577717
   int events_not_opened=0;
Packit 577717
Packit 577717
   /* should this be a more serious error? */
Packit 577717
   if ( ctx->state & PERF_EVENTS_RUNNING ) {
Packit 577717
      SUBDBG("Closing without stopping first\n");
Packit 577717
   }
Packit 577717
Packit 577717
   /* Close child events first */
Packit 577717
   for( i=0; i<ctl->num_events; i++ ) {
Packit 577717
Packit 577717
      if (ctl->events[i].event_opened) {
Packit 577717
Packit 577717
         if (ctl->events[i].group_leader_fd!=-1) {
Packit 577717
            if ( ctl->events[i].mmap_buf ) {
Packit 577717
	       if ( munmap ( ctl->events[i].mmap_buf,
Packit 577717
		             ctl->events[i].nr_mmap_pages * getpagesize() ) ) {
Packit 577717
	          PAPIERROR( "munmap of fd = %d returned error: %s",
Packit 577717
			     ctl->events[i].event_fd, strerror( errno ) );
Packit 577717
	          return PAPI_ESYS;
Packit 577717
	       }
Packit 577717
	    }
Packit 577717
Packit 577717
            if ( close( ctl->events[i].event_fd ) ) {
Packit 577717
	       PAPIERROR( "close of fd = %d returned error: %s",
Packit 577717
		       ctl->events[i].event_fd, strerror( errno ) );
Packit 577717
	       return PAPI_ESYS;
Packit 577717
	    } else {
Packit 577717
	       num_closed++;
Packit 577717
	    }
Packit 577717
	    ctl->events[i].event_opened=0;
Packit 577717
	 }
Packit 577717
      }
Packit 577717
      else {
Packit 577717
	events_not_opened++;
Packit 577717
      }
Packit 577717
   }
Packit 577717
Packit 577717
   /* Close the group leaders last */
Packit 577717
   for( i=0; i<ctl->num_events; i++ ) {
Packit 577717
Packit 577717
      if (ctl->events[i].event_opened) {
Packit 577717
Packit 577717
         if (ctl->events[i].group_leader_fd==-1) {
Packit 577717
            if ( ctl->events[i].mmap_buf ) {
Packit 577717
	       if ( munmap ( ctl->events[i].mmap_buf,
Packit 577717
		             ctl->events[i].nr_mmap_pages * getpagesize() ) ) {
Packit 577717
	          PAPIERROR( "munmap of fd = %d returned error: %s",
Packit 577717
			     ctl->events[i].event_fd, strerror( errno ) );
Packit 577717
	          return PAPI_ESYS;
Packit 577717
	       }
Packit 577717
	    }
Packit 577717
Packit 577717
Packit 577717
            if ( close( ctl->events[i].event_fd ) ) {
Packit 577717
	       PAPIERROR( "close of fd = %d returned error: %s",
Packit 577717
		       ctl->events[i].event_fd, strerror( errno ) );
Packit 577717
	       return PAPI_ESYS;
Packit 577717
	    } else {
Packit 577717
	       num_closed++;
Packit 577717
	    }
Packit 577717
	    ctl->events[i].event_opened=0;
Packit 577717
	 }
Packit 577717
      }
Packit 577717
   }
Packit 577717
Packit 577717
Packit 577717
   if (ctl->num_events!=num_closed) {
Packit 577717
      if (ctl->num_events!=(num_closed+events_not_opened)) {
Packit 577717
         PAPIERROR("Didn't close all events: "
Packit 577717
		   "Closed %d Not Opened: %d Expected %d\n",
Packit 577717
		   num_closed,events_not_opened,ctl->num_events);
Packit 577717
         return PAPI_EBUG;
Packit 577717
      }
Packit 577717
   }
Packit 577717
Packit 577717
   ctl->num_events=0;
Packit 577717
Packit 577717
   ctx->state &= ~PERF_EVENTS_OPENED;
Packit 577717
Packit 577717
   return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
Packit 577717
Packit 577717
/********************************************************************/
Packit 577717
/* Component Interface                                              */
Packit 577717
/********************************************************************/
Packit 577717
Packit 577717
Packit 577717
Packit 577717
/* Initialize a thread */
Packit 577717
static int
Packit 577717
_peu_init_thread( hwd_context_t *hwd_ctx )
Packit 577717
{
Packit 577717
Packit 577717
  pe_context_t *pe_ctx = ( pe_context_t *) hwd_ctx;
Packit 577717
Packit 577717
  /* clear the context structure and mark as initialized */
Packit 577717
  memset( pe_ctx, 0, sizeof ( pe_context_t ) );
Packit 577717
  pe_ctx->initialized=1;
Packit 577717
Packit 577717
  pe_ctx->event_table=&uncore_native_event_table;
Packit 577717
  pe_ctx->cidx=our_cidx;
Packit 577717
Packit 577717
  return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/* Initialize a new control state */
Packit 577717
static int
Packit 577717
_peu_init_control_state( hwd_control_state_t *ctl )
Packit 577717
{
Packit 577717
  pe_control_t *pe_ctl = ( pe_control_t *) ctl;
Packit 577717
Packit 577717
  /* clear the contents */
Packit 577717
  memset( pe_ctl, 0, sizeof ( pe_control_t ) );
Packit 577717
Packit 577717
  /* Set the default domain */
Packit 577717
  _peu_set_domain( ctl, _perf_event_uncore_vector.cmp_info.default_domain );
Packit 577717
Packit 577717
  /* Set the default granularity */
Packit 577717
  pe_ctl->granularity=_perf_event_uncore_vector.cmp_info.default_granularity;
Packit 577717
Packit 577717
  pe_ctl->cidx=our_cidx;
Packit 577717
Packit 577717
  /* Set cpu number in the control block to show events */
Packit 577717
  /* are not tied to specific cpu                       */
Packit 577717
  pe_ctl->cpu = -1;
Packit 577717
  return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
Packit 577717
/* Initialize the perf_event uncore component */
Packit 577717
static int
Packit 577717
_peu_init_component( int cidx )
Packit 577717
{
Packit 577717
Packit 577717
   int retval;
Packit 577717
   int paranoid_level;
Packit 577717
Packit 577717
   FILE *fff;
Packit 577717
Packit 577717
   our_cidx=cidx;
Packit 577717
Packit 577717
   /* The is the official way to detect if perf_event support exists */
Packit 577717
   /* The file is called perf_counter_paranoid on 2.6.31             */
Packit 577717
   /* currently we are lazy and do not support 2.6.31 kernels        */
Packit 577717
Packit 577717
   fff=fopen("/proc/sys/kernel/perf_event_paranoid","r");
Packit 577717
   if (fff==NULL) {
Packit 577717
     strncpy(_papi_hwd[cidx]->cmp_info.disabled_reason,
Packit 577717
	    "perf_event support not detected",PAPI_MAX_STR_LEN);
Packit 577717
     return PAPI_ENOCMP;
Packit 577717
   }
Packit 577717
   retval=fscanf(fff,"%d",&paranoid_level);
Packit 577717
   if (retval!=1) fprintf(stderr,"Error reading paranoid level\n");
Packit 577717
   fclose(fff);
Packit 577717
Packit 577717
Packit 577717
   /* Run the libpfm4-specific setup */
Packit 577717
Packit 577717
   retval = _papi_libpfm4_init(_papi_hwd[cidx]);
Packit 577717
   if (retval) {
Packit 577717
     strncpy(_papi_hwd[cidx]->cmp_info.disabled_reason,
Packit 577717
	     "Error initializing libpfm4",PAPI_MAX_STR_LEN);
Packit 577717
     return PAPI_ENOCMP;
Packit 577717
   }
Packit 577717
Packit 577717
Packit 577717
   /* Run the uncore specific libpfm4 setup */
Packit 577717
Packit 577717
   retval = _peu_libpfm4_init(_papi_hwd[cidx], our_cidx,
Packit 577717
			       &uncore_native_event_table,
Packit 577717
                               PMU_TYPE_UNCORE);
Packit 577717
   if (retval) {
Packit 577717
     strncpy(_papi_hwd[cidx]->cmp_info.disabled_reason,
Packit 577717
	     "Error setting up libpfm4",PAPI_MAX_STR_LEN);
Packit 577717
     return PAPI_ENOCMP;
Packit 577717
   }
Packit 577717
Packit 577717
   /* Check if no uncore events found */
Packit 577717
Packit 577717
   if (_papi_hwd[cidx]->cmp_info.num_native_events==0) {
Packit 577717
     strncpy(_papi_hwd[cidx]->cmp_info.disabled_reason,
Packit 577717
	     "No uncore PMUs or events found",PAPI_MAX_STR_LEN);
Packit 577717
     return PAPI_ENOCMP;
Packit 577717
   }
Packit 577717
Packit 577717
   /* Check if we have enough permissions for uncore */
Packit 577717
Packit 577717
   /* 2 means no kernel measurements allowed   */
Packit 577717
   /* 1 means normal counter access            */
Packit 577717
   /* 0 means you can access CPU-specific data */
Packit 577717
   /* -1 means no restrictions                 */
Packit 577717
Packit 577717
   if ((paranoid_level>0) && (getuid()!=0)) {
Packit 577717
      strncpy(_papi_hwd[cidx]->cmp_info.disabled_reason,
Packit 577717
	    "Insufficient permissions for uncore access.  Set /proc/sys/kernel/perf_event_paranoid to 0 or run as root.",
Packit 577717
	    PAPI_MAX_STR_LEN);
Packit 577717
     return PAPI_ENOCMP;
Packit 577717
   }
Packit 577717
Packit 577717
   return PAPI_OK;
Packit 577717
Packit 577717
}
Packit 577717
Packit 577717
/* Shutdown the perf_event component */
Packit 577717
static int
Packit 577717
_peu_shutdown_component( void ) {
Packit 577717
Packit 577717
	/* deallocate our event table */
Packit 577717
	_pe_libpfm4_shutdown(&_perf_event_uncore_vector,
Packit 577717
				&uncore_native_event_table);
Packit 577717
Packit 577717
	/* Shutdown libpfm4 */
Packit 577717
	_papi_libpfm4_shutdown(&_perf_event_uncore_vector);
Packit 577717
Packit 577717
	return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/* This function clears the current contents of the control structure and
Packit 577717
   updates it with whatever resources are allocated for all the native events
Packit 577717
   in the native info structure array. */
Packit 577717
Packit 577717
int
Packit 577717
_peu_update_control_state( hwd_control_state_t *ctl,
Packit 577717
			       NativeInfo_t *native,
Packit 577717
			       int count, hwd_context_t *ctx )
Packit 577717
{
Packit 577717
	int i;
Packit 577717
	int j;
Packit 577717
	int ret;
Packit 577717
	int skipped_events=0;
Packit 577717
	struct native_event_t *ntv_evt;
Packit 577717
   pe_context_t *pe_ctx = ( pe_context_t *) ctx;
Packit 577717
   pe_control_t *pe_ctl = ( pe_control_t *) ctl;
Packit 577717
Packit 577717
   /* close all of the existing fds and start over again */
Packit 577717
   /* In theory we could have finer-grained control and know if             */
Packit 577717
   /* things were changed, but it's easier to tear things down and rebuild. */
Packit 577717
   close_pe_events( pe_ctx, pe_ctl );
Packit 577717
Packit 577717
   /* Calling with count==0 should be OK, it's how things are deallocated */
Packit 577717
   /* when an eventset is destroyed.                                      */
Packit 577717
   if ( count == 0 ) {
Packit 577717
      SUBDBG( "Called with count == 0\n" );
Packit 577717
      return PAPI_OK;
Packit 577717
   }
Packit 577717
Packit 577717
   /* set up all the events */
Packit 577717
   for( i = 0; i < count; i++ ) {
Packit 577717
      if ( native ) {
Packit 577717
			// get the native event pointer used for this papi event
Packit 577717
			int ntv_idx = _papi_hwi_get_ntv_idx((unsigned)(native[i].ni_papi_code));
Packit 577717
			if (ntv_idx < -1) {
Packit 577717
				SUBDBG("papi_event_code: %#x known by papi but not by the component\n", native[i].ni_papi_code);
Packit 577717
				continue;
Packit 577717
			}
Packit 577717
			// if native index is -1, then we have an event without a mask and need to find the right native index to use
Packit 577717
			if (ntv_idx == -1) {
Packit 577717
				// find the native event index we want by matching for the right papi event code
Packit 577717
				for (j=0 ; j<pe_ctx->event_table->num_native_events ; j++) {
Packit 577717
					if (pe_ctx->event_table->native_events[j].papi_event_code == native[i].ni_papi_code) {
Packit 577717
						ntv_idx = j;
Packit 577717
					}
Packit 577717
				}
Packit 577717
			}
Packit 577717
Packit 577717
			// if native index is still negative, we did not find event we wanted so just return error
Packit 577717
			if (ntv_idx < 0) {
Packit 577717
				SUBDBG("papi_event_code: %#x not found in native event tables\n", native[i].ni_papi_code);
Packit 577717
				continue;
Packit 577717
			}
Packit 577717
Packit 577717
			// this native index is positive so there was a mask with the event, the ntv_idx identifies which native event to use
Packit 577717
			ntv_evt = (struct native_event_t *)(&(pe_ctx->event_table->native_events[ntv_idx]));
Packit 577717
Packit 577717
			SUBDBG("ntv_evt: %p\n", ntv_evt);
Packit 577717
Packit 577717
			SUBDBG("i: %d, pe_ctx->event_table->num_native_events: %d\n", i, pe_ctx->event_table->num_native_events);
Packit 577717
Packit 577717
	    	// Move this events hardware config values and other attributes to the perf_events attribute structure
Packit 577717
			memcpy (&pe_ctl->events[i].attr, &ntv_evt->attr, sizeof(perf_event_attr_t));
Packit 577717
Packit 577717
			// may need to update the attribute structure with information from event set level domain settings (values set by PAPI_set_domain)
Packit 577717
			// only done if the event mask which controls each counting domain was not provided
Packit 577717
Packit 577717
			// get pointer to allocated name, will be NULL when adding preset events to event set
Packit 577717
			char *aName = ntv_evt->allocated_name;
Packit 577717
			if ((aName == NULL)  ||  (strstr(aName, ":u=") == NULL)) {
Packit 577717
				SUBDBG("set exclude_user attribute from eventset level domain flags, encode: %d, eventset: %d\n", pe_ctl->events[i].attr.exclude_user, !(pe_ctl->domain & PAPI_DOM_USER));
Packit 577717
				pe_ctl->events[i].attr.exclude_user = !(pe_ctl->domain & PAPI_DOM_USER);
Packit 577717
			}
Packit 577717
			if ((aName == NULL)  ||  (strstr(aName, ":k=") == NULL)) {
Packit 577717
				SUBDBG("set exclude_kernel attribute from eventset level domain flags, encode: %d, eventset: %d\n", pe_ctl->events[i].attr.exclude_kernel, !(pe_ctl->domain & PAPI_DOM_KERNEL));
Packit 577717
				pe_ctl->events[i].attr.exclude_kernel = !(pe_ctl->domain & PAPI_DOM_KERNEL);
Packit 577717
			}
Packit 577717
Packit 577717
			// set the cpu number provided with an event mask if there was one (will be -1 if mask not provided)
Packit 577717
			pe_ctl->events[i].cpu = ntv_evt->cpu;
Packit 577717
			// if cpu event mask not provided, then set the cpu to use to what may have been set on call to PAPI_set_opt (will still be -1 if not called)
Packit 577717
			if (pe_ctl->events[i].cpu == -1) {
Packit 577717
				pe_ctl->events[i].cpu = pe_ctl->cpu;
Packit 577717
			}
Packit 577717
      } else {
Packit 577717
    	  // This case happens when called from _pe_set_overflow and _pe_ctl
Packit 577717
          // Those callers put things directly into the pe_ctl structure so it is already set for the open call
Packit 577717
      }
Packit 577717
Packit 577717
      // Copy the inherit flag into the attribute block that will be passed to the kernel
Packit 577717
      pe_ctl->events[i].attr.inherit = pe_ctl->inherit;
Packit 577717
Packit 577717
      /* Set the position in the native structure */
Packit 577717
      /* We just set up events linearly           */
Packit 577717
      if ( native ) {
Packit 577717
    	  native[i].ni_position = i;
Packit 577717
    	  SUBDBG( "&native[%d]: %p, ni_papi_code: %#x, ni_event: %#x, ni_position: %d, ni_owners: %d\n",
Packit 577717
			i, &(native[i]), native[i].ni_papi_code, native[i].ni_event, native[i].ni_position, native[i].ni_owners);
Packit 577717
      }
Packit 577717
   }
Packit 577717
Packit 577717
	if (count <= skipped_events) {
Packit 577717
		SUBDBG("EXIT: No events to count, they all contained invalid umasks\n");
Packit 577717
		return PAPI_ENOEVNT;
Packit 577717
	}
Packit 577717
Packit 577717
  pe_ctl->num_events = count - skipped_events;
Packit 577717
Packit 577717
   /* actuall open the events */
Packit 577717
   /* (why is this a separate function?) */
Packit 577717
   ret = open_pe_events( pe_ctx, pe_ctl );
Packit 577717
   if ( ret != PAPI_OK ) {
Packit 577717
      SUBDBG("open_pe_events failed\n");
Packit 577717
      /* Restore values ? */
Packit 577717
      return ret;
Packit 577717
   }
Packit 577717
Packit 577717
   SUBDBG( "EXIT: PAPI_OK\n" );
Packit 577717
   return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/********************************************************************/
Packit 577717
/********************************************************************/
Packit 577717
/* Start with functions that are exported via the module interface  */
Packit 577717
/********************************************************************/
Packit 577717
/********************************************************************/
Packit 577717
Packit 577717
Packit 577717
/* set the domain. perf_events allows per-event control of this, papi allows it to be set at the event level or at the event set level. */
Packit 577717
/* this will set the event set level domain values but they only get used if no event level domain mask (u= or k=) was specified. */
Packit 577717
static int
Packit 577717
_peu_set_domain( hwd_control_state_t *ctl, int domain)
Packit 577717
{
Packit 577717
   pe_control_t *pe_ctl = ( pe_control_t *) ctl;
Packit 577717
Packit 577717
   SUBDBG("old control domain %d, new domain %d\n",
Packit 577717
	  pe_ctl->domain,domain);
Packit 577717
Packit 577717
   pe_ctl->domain = domain;
Packit 577717
   return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/* Shutdown a thread */
Packit 577717
static int
Packit 577717
_peu_shutdown_thread( hwd_context_t *ctx )
Packit 577717
{
Packit 577717
    pe_context_t *pe_ctx = ( pe_context_t *) ctx;
Packit 577717
Packit 577717
    pe_ctx->initialized=0;
Packit 577717
Packit 577717
    return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
/* reset the hardware counters */
Packit 577717
/* Note: PAPI_reset() does not necessarily call this */
Packit 577717
/* unless the events are actually running.           */
Packit 577717
static int
Packit 577717
_peu_reset( hwd_context_t *ctx, hwd_control_state_t *ctl )
Packit 577717
{
Packit 577717
   int i, ret;
Packit 577717
   pe_control_t *pe_ctl = ( pe_control_t *) ctl;
Packit 577717
Packit 577717
   ( void ) ctx;			 /*unused */
Packit 577717
Packit 577717
   /* We need to reset all of the events, not just the group leaders */
Packit 577717
   for( i = 0; i < pe_ctl->num_events; i++ ) {
Packit 577717
      ret = ioctl( pe_ctl->events[i].event_fd, PERF_EVENT_IOC_RESET, NULL );
Packit 577717
      if ( ret == -1 ) {
Packit 577717
	 PAPIERROR("ioctl(%d, PERF_EVENT_IOC_RESET, NULL) "
Packit 577717
		   "returned error, Linux says: %s",
Packit 577717
		   pe_ctl->events[i].event_fd, strerror( errno ) );
Packit 577717
	 return PAPI_ESYS;
Packit 577717
      }
Packit 577717
   }
Packit 577717
Packit 577717
   return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
/* write (set) the hardware counters */
Packit 577717
/* Current we do not support this.   */
Packit 577717
static int
Packit 577717
_peu_write( hwd_context_t *ctx, hwd_control_state_t *ctl,
Packit 577717
		long long *from )
Packit 577717
{
Packit 577717
   ( void ) ctx;			 /*unused */
Packit 577717
   ( void ) ctl;			 /*unused */
Packit 577717
   ( void ) from;			 /*unused */
Packit 577717
   /*
Packit 577717
    * Counters cannot be written.  Do we need to virtualize the
Packit 577717
    * counters so that they can be written, or perhaps modify code so that
Packit 577717
    * they can be written? FIXME ?
Packit 577717
    */
Packit 577717
Packit 577717
    return PAPI_ENOSUPP;
Packit 577717
}
Packit 577717
Packit 577717
/*
Packit 577717
 * perf_event provides a complicated read interface.
Packit 577717
 *  the info returned by read() varies depending on whether
Packit 577717
 *  you have PERF_FORMAT_GROUP, PERF_FORMAT_TOTAL_TIME_ENABLED,
Packit 577717
 *  PERF_FORMAT_TOTAL_TIME_RUNNING, or PERF_FORMAT_ID set
Packit 577717
 *
Packit 577717
 * To simplify things we just always ask for everything.  This might
Packit 577717
 * lead to overhead when reading more than we need, but it makes the
Packit 577717
 * read code a lot simpler than the original implementation we had here.
Packit 577717
 *
Packit 577717
 * For more info on the layout see include/linux/perf_event.h
Packit 577717
 *
Packit 577717
 */
Packit 577717
Packit 577717
static int
Packit 577717
_peu_read( hwd_context_t *ctx, hwd_control_state_t *ctl,
Packit 577717
	       long long **events, int flags )
Packit 577717
{
Packit 577717
    SUBDBG("ENTER: ctx: %p, ctl: %p, events: %p, flags: %#x\n", ctx, ctl, events, flags);
Packit 577717
Packit 577717
   ( void ) flags;			 /*unused */
Packit 577717
   int i, ret = -1;
Packit 577717
   /* pe_context_t *pe_ctx = ( pe_context_t *) ctx; */ 
Packit 577717
   (void) ctx; /*unused*/
Packit 577717
   pe_control_t *pe_ctl = ( pe_control_t *) ctl;
Packit 577717
   long long papi_pe_buffer[READ_BUFFER_SIZE];
Packit 577717
   long long tot_time_running, tot_time_enabled, scale;
Packit 577717
Packit 577717
   /* Handle case where we are multiplexing */
Packit 577717
   if (pe_ctl->multiplexed) {
Packit 577717
Packit 577717
      /* currently we handle multiplexing by having individual events */
Packit 577717
      /* so we read from each in turn.                                */
Packit 577717
Packit 577717
      for ( i = 0; i < pe_ctl->num_events; i++ ) {
Packit 577717
Packit 577717
         ret = read( pe_ctl->events[i].event_fd, papi_pe_buffer,
Packit 577717
		    sizeof ( papi_pe_buffer ) );
Packit 577717
         if ( ret == -1 ) {
Packit 577717
	    PAPIERROR("read returned an error: ", strerror( errno ));
Packit 577717
       SUBDBG("EXIT: PAPI_ESYS\n");
Packit 577717
	    return PAPI_ESYS;
Packit 577717
	 }
Packit 577717
Packit 577717
	 /* We should read 3 64-bit values from the counter */
Packit 577717
	 if (ret<(signed)(3*sizeof(long long))) {
Packit 577717
	    PAPIERROR("Error!  short read!\n");
Packit 577717
       SUBDBG("EXIT: PAPI_ESYS\n");
Packit 577717
	    return PAPI_ESYS;
Packit 577717
	 }
Packit 577717
Packit 577717
         SUBDBG("read: fd: %2d, tid: %ld, cpu: %d, ret: %d\n",
Packit 577717
	        pe_ctl->events[i].event_fd,
Packit 577717
		(long)pe_ctl->tid, pe_ctl->events[i].cpu, ret);
Packit 577717
         SUBDBG("read: %lld %lld %lld\n",papi_pe_buffer[0],
Packit 577717
	        papi_pe_buffer[1],papi_pe_buffer[2]);
Packit 577717
Packit 577717
         tot_time_enabled = papi_pe_buffer[1];
Packit 577717
         tot_time_running = papi_pe_buffer[2];
Packit 577717
Packit 577717
         SUBDBG("count[%d] = (papi_pe_buffer[%d] %lld * "
Packit 577717
		"tot_time_enabled %lld) / tot_time_running %lld\n",
Packit 577717
		i, 0,papi_pe_buffer[0],
Packit 577717
		tot_time_enabled,tot_time_running);
Packit 577717
Packit 577717
         if (tot_time_running == tot_time_enabled) {
Packit 577717
	    /* No scaling needed */
Packit 577717
	    pe_ctl->counts[i] = papi_pe_buffer[0];
Packit 577717
         } else if (tot_time_running && tot_time_enabled) {
Packit 577717
	    /* Scale factor of 100 to avoid overflows when computing */
Packit 577717
	    /*enabled/running */
Packit 577717
Packit 577717
	    scale = (tot_time_enabled * 100LL) / tot_time_running;
Packit 577717
	    scale = scale * papi_pe_buffer[0];
Packit 577717
	    scale = scale / 100LL;
Packit 577717
	    pe_ctl->counts[i] = scale;
Packit 577717
	 } else {
Packit 577717
	   /* This should not happen, but Phil reports it sometime does. */
Packit 577717
	    SUBDBG("perf_event kernel bug(?) count, enabled, "
Packit 577717
		   "running: %lld, %lld, %lld\n",
Packit 577717
		   papi_pe_buffer[0],tot_time_enabled,
Packit 577717
		   tot_time_running);
Packit 577717
Packit 577717
	    pe_ctl->counts[i] = papi_pe_buffer[0];
Packit 577717
	 }
Packit 577717
      }
Packit 577717
   }
Packit 577717
Packit 577717
   /* Handle cases where we cannot use FORMAT GROUP */
Packit 577717
   else if (pe_ctl->inherit) {
Packit 577717
Packit 577717
      /* we must read each counter individually */
Packit 577717
      for ( i = 0; i < pe_ctl->num_events; i++ ) {
Packit 577717
Packit 577717
         ret = read( pe_ctl->events[i].event_fd, papi_pe_buffer, 
Packit 577717
		    sizeof ( papi_pe_buffer ) );
Packit 577717
         if ( ret == -1 ) {
Packit 577717
	    PAPIERROR("read returned an error: ", strerror( errno ));
Packit 577717
       SUBDBG("EXIT: PAPI_ESYS\n");
Packit 577717
	    return PAPI_ESYS;
Packit 577717
	 }
Packit 577717
Packit 577717
	 /* we should read one 64-bit value from each counter */
Packit 577717
	 if (ret!=sizeof(long long)) {
Packit 577717
	    PAPIERROR("Error!  short read!\n");
Packit 577717
	    PAPIERROR("read: fd: %2d, tid: %ld, cpu: %d, ret: %d\n",
Packit 577717
		   pe_ctl->events[i].event_fd,
Packit 577717
		   (long)pe_ctl->tid, pe_ctl->events[i].cpu, ret);
Packit 577717
       SUBDBG("EXIT: PAPI_ESYS\n");
Packit 577717
	    return PAPI_ESYS;
Packit 577717
	 }
Packit 577717
Packit 577717
         SUBDBG("read: fd: %2d, tid: %ld, cpu: %d, ret: %d\n",
Packit 577717
	        pe_ctl->events[i].event_fd, (long)pe_ctl->tid,
Packit 577717
		pe_ctl->events[i].cpu, ret);
Packit 577717
         SUBDBG("read: %lld\n",papi_pe_buffer[0]);
Packit 577717
Packit 577717
	 pe_ctl->counts[i] = papi_pe_buffer[0];
Packit 577717
      }
Packit 577717
   }
Packit 577717
Packit 577717
Packit 577717
   /* Handle cases where we are using FORMAT_GROUP   */
Packit 577717
   /* We assume only one group leader, in position 0 */
Packit 577717
Packit 577717
   else {
Packit 577717
      if (pe_ctl->events[0].group_leader_fd!=-1) {
Packit 577717
	 PAPIERROR("Was expecting group leader!\n");
Packit 577717
      }
Packit 577717
Packit 577717
      ret = read( pe_ctl->events[0].event_fd, papi_pe_buffer,
Packit 577717
		  sizeof ( papi_pe_buffer ) );
Packit 577717
Packit 577717
      if ( ret == -1 ) {
Packit 577717
	 PAPIERROR("read returned an error: ", strerror( errno ));
Packit 577717
       SUBDBG("EXIT: PAPI_ESYS\n");
Packit 577717
	 return PAPI_ESYS;
Packit 577717
      }
Packit 577717
Packit 577717
      /* we read 1 64-bit value (number of events) then     */
Packit 577717
      /* num_events more 64-bit values that hold the counts */
Packit 577717
      if (ret<(signed)((1+pe_ctl->num_events)*sizeof(long long))) {
Packit 577717
	 PAPIERROR("Error! short read!\n");
Packit 577717
       SUBDBG("EXIT: PAPI_ESYS\n");
Packit 577717
	 return PAPI_ESYS;
Packit 577717
      }
Packit 577717
Packit 577717
      SUBDBG("read: fd: %2d, tid: %ld, cpu: %d, ret: %d\n",
Packit 577717
	     pe_ctl->events[0].event_fd,
Packit 577717
	     (long)pe_ctl->tid, pe_ctl->events[0].cpu, ret);
Packit 577717
      {
Packit 577717
	 int j;
Packit 577717
	 for(j=0;j
Packit 577717
            SUBDBG("read %d: %lld\n",j,papi_pe_buffer[j]);
Packit 577717
	 }
Packit 577717
      }
Packit 577717
Packit 577717
      /* Make sure the kernel agrees with how many events we have */
Packit 577717
      if (papi_pe_buffer[0]!=pe_ctl->num_events) {
Packit 577717
	 PAPIERROR("Error!  Wrong number of events!\n");
Packit 577717
       SUBDBG("EXIT: PAPI_ESYS\n");
Packit 577717
	 return PAPI_ESYS;
Packit 577717
      }
Packit 577717
Packit 577717
      /* put the count values in their proper location */
Packit 577717
      for(i=0;i<pe_ctl->num_events;i++) {
Packit 577717
         pe_ctl->counts[i] = papi_pe_buffer[1+i];
Packit 577717
      }
Packit 577717
   }
Packit 577717
Packit 577717
   /* point PAPI to the values we read */
Packit 577717
   *events = pe_ctl->counts;
Packit 577717
Packit 577717
   SUBDBG("EXIT: PAPI_OK\n");
Packit 577717
   return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/* Start counting events */
Packit 577717
static int
Packit 577717
_peu_start( hwd_context_t *ctx, hwd_control_state_t *ctl )
Packit 577717
{
Packit 577717
   int ret;
Packit 577717
   int i;
Packit 577717
   int did_something = 0;
Packit 577717
   pe_context_t *pe_ctx = ( pe_context_t *) ctx;
Packit 577717
   pe_control_t *pe_ctl = ( pe_control_t *) ctl;
Packit 577717
Packit 577717
   /* Reset the counters first.  Is this necessary? */
Packit 577717
   ret = _peu_reset( pe_ctx, pe_ctl );
Packit 577717
   if ( ret ) {
Packit 577717
      return ret;
Packit 577717
   }
Packit 577717
Packit 577717
   /* Enable all of the group leaders                */
Packit 577717
   /* All group leaders have a group_leader_fd of -1 */
Packit 577717
   for( i = 0; i < pe_ctl->num_events; i++ ) {
Packit 577717
      if (pe_ctl->events[i].group_leader_fd == -1) {
Packit 577717
	 SUBDBG("ioctl(enable): fd: %d\n", pe_ctl->events[i].event_fd);
Packit 577717
	 ret=ioctl( pe_ctl->events[i].event_fd, PERF_EVENT_IOC_ENABLE, NULL) ; 
Packit 577717
Packit 577717
	 /* ioctls always return -1 on failure */
Packit 577717
         if (ret == -1) {
Packit 577717
            PAPIERROR("ioctl(PERF_EVENT_IOC_ENABLE) failed.\n");
Packit 577717
            return PAPI_ESYS;
Packit 577717
	 }
Packit 577717
Packit 577717
	 did_something++;
Packit 577717
      } 
Packit 577717
   }
Packit 577717
Packit 577717
   if (!did_something) {
Packit 577717
      PAPIERROR("Did not enable any counters.\n");
Packit 577717
      return PAPI_EBUG;
Packit 577717
   }
Packit 577717
Packit 577717
   pe_ctx->state |= PERF_EVENTS_RUNNING;
Packit 577717
Packit 577717
   return PAPI_OK;
Packit 577717
Packit 577717
}
Packit 577717
Packit 577717
/* Stop all of the counters */
Packit 577717
static int
Packit 577717
_peu_stop( hwd_context_t *ctx, hwd_control_state_t *ctl )
Packit 577717
{
Packit 577717
Packit 577717
   int ret;
Packit 577717
   int i;
Packit 577717
   pe_context_t *pe_ctx = ( pe_context_t *) ctx;
Packit 577717
   pe_control_t *pe_ctl = ( pe_control_t *) ctl;
Packit 577717
Packit 577717
   /* Just disable the group leaders */
Packit 577717
   for ( i = 0; i < pe_ctl->num_events; i++ ) {
Packit 577717
      if ( pe_ctl->events[i].group_leader_fd == -1 ) {
Packit 577717
	 ret=ioctl( pe_ctl->events[i].event_fd, PERF_EVENT_IOC_DISABLE, NULL);
Packit 577717
	 if ( ret == -1 ) {
Packit 577717
	    PAPIERROR( "ioctl(%d, PERF_EVENT_IOC_DISABLE, NULL) "
Packit 577717
		       "returned error, Linux says: %s",
Packit 577717
		       pe_ctl->events[i].event_fd, strerror( errno ) );
Packit 577717
	    return PAPI_EBUG;
Packit 577717
	 }
Packit 577717
      }
Packit 577717
   }
Packit 577717
Packit 577717
   pe_ctx->state &= ~PERF_EVENTS_RUNNING;
Packit 577717
Packit 577717
   return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/* Set various options on a control state */
Packit 577717
static int
Packit 577717
_peu_ctl( hwd_context_t *ctx, int code, _papi_int_option_t *option )
Packit 577717
{
Packit 577717
   int ret;
Packit 577717
   pe_context_t *pe_ctx = ( pe_context_t *) ctx;
Packit 577717
   pe_control_t *pe_ctl = NULL;
Packit 577717
Packit 577717
   switch ( code ) {
Packit 577717
      case PAPI_MULTIPLEX:
Packit 577717
	   pe_ctl = ( pe_control_t * ) ( option->multiplex.ESI->ctl_state );
Packit 577717
Packit 577717
	   pe_ctl->multiplexed = 1;
Packit 577717
	   ret = _peu_update_control_state( pe_ctl, NULL,
Packit 577717
						pe_ctl->num_events, pe_ctx );
Packit 577717
	   if (ret != PAPI_OK) {
Packit 577717
	      pe_ctl->multiplexed = 0;
Packit 577717
	   }
Packit 577717
	   return ret;
Packit 577717
Packit 577717
      case PAPI_ATTACH:
Packit 577717
	   pe_ctl = ( pe_control_t * ) ( option->attach.ESI->ctl_state );
Packit 577717
Packit 577717
	   pe_ctl->tid = option->attach.tid;
Packit 577717
Packit 577717
	   /* If events have been already been added, something may */
Packit 577717
	   /* have been done to the kernel, so update */
Packit 577717
	   ret =_peu_update_control_state( pe_ctl, NULL,
Packit 577717
						pe_ctl->num_events, pe_ctx);
Packit 577717
Packit 577717
	   return ret;
Packit 577717
Packit 577717
      case PAPI_DETACH:
Packit 577717
	   pe_ctl = ( pe_control_t *) ( option->attach.ESI->ctl_state );
Packit 577717
Packit 577717
	   pe_ctl->tid = 0;
Packit 577717
	   return PAPI_OK;
Packit 577717
Packit 577717
      case PAPI_CPU_ATTACH:
Packit 577717
	   pe_ctl = ( pe_control_t *) ( option->cpu.ESI->ctl_state );
Packit 577717
Packit 577717
	   /* this tells the kernel not to count for a thread   */
Packit 577717
	   /* should we warn if we try to set both?  perf_event */
Packit 577717
	   /* will reject it.                                   */
Packit 577717
	   pe_ctl->tid = -1;
Packit 577717
Packit 577717
	   pe_ctl->cpu = option->cpu.cpu_num;
Packit 577717
Packit 577717
	   return PAPI_OK;
Packit 577717
Packit 577717
      case PAPI_DOMAIN:
Packit 577717
	   pe_ctl = ( pe_control_t *) ( option->domain.ESI->ctl_state );
Packit 577717
Packit 577717
	   /* looks like we are allowed, so set event set level counting domains */
Packit 577717
       pe_ctl->domain = option->domain.domain;
Packit 577717
	   return PAPI_OK;
Packit 577717
Packit 577717
      case PAPI_GRANUL:
Packit 577717
	   pe_ctl = (pe_control_t *) ( option->granularity.ESI->ctl_state );
Packit 577717
Packit 577717
	   /* FIXME: we really don't support this yet */
Packit 577717
Packit 577717
           switch ( option->granularity.granularity  ) {
Packit 577717
              case PAPI_GRN_PROCG:
Packit 577717
              case PAPI_GRN_SYS_CPU:
Packit 577717
              case PAPI_GRN_PROC:
Packit 577717
		   return PAPI_ECMP;
Packit 577717
Packit 577717
	      /* Currently we only support thread and CPU granularity */
Packit 577717
              case PAPI_GRN_SYS:
Packit 577717
	 	   pe_ctl->granularity=PAPI_GRN_SYS;
Packit 577717
		   break;
Packit 577717
Packit 577717
              case PAPI_GRN_THR:
Packit 577717
	 	   pe_ctl->granularity=PAPI_GRN_THR;
Packit 577717
		   break;
Packit 577717
Packit 577717
Packit 577717
              default:
Packit 577717
		   return PAPI_EINVAL;
Packit 577717
	   }
Packit 577717
           return PAPI_OK;
Packit 577717
Packit 577717
      case PAPI_INHERIT:
Packit 577717
	   pe_ctl = (pe_control_t *) ( option->inherit.ESI->ctl_state );
Packit 577717
Packit 577717
	   if (option->inherit.inherit) {
Packit 577717
	      /* children will inherit counters */
Packit 577717
	      pe_ctl->inherit = 1;
Packit 577717
	   } else {
Packit 577717
	      /* children won't inherit counters */
Packit 577717
	      pe_ctl->inherit = 0;
Packit 577717
	   }
Packit 577717
	   return PAPI_OK;
Packit 577717
Packit 577717
      case PAPI_DATA_ADDRESS:
Packit 577717
	   return PAPI_ENOSUPP;
Packit 577717
Packit 577717
      case PAPI_INSTR_ADDRESS:
Packit 577717
	   return PAPI_ENOSUPP;
Packit 577717
Packit 577717
      case PAPI_DEF_ITIMER:
Packit 577717
	   return PAPI_ENOSUPP;
Packit 577717
Packit 577717
      case PAPI_DEF_MPX_NS:
Packit 577717
	   return PAPI_ENOSUPP;
Packit 577717
Packit 577717
      case PAPI_DEF_ITIMER_NS:
Packit 577717
	   return PAPI_ENOSUPP;
Packit 577717
Packit 577717
      default:
Packit 577717
	   return PAPI_ENOSUPP;
Packit 577717
   }
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
static int
Packit 577717
_peu_ntv_enum_events( unsigned int *PapiEventCode, int modifier )
Packit 577717
{
Packit 577717
Packit 577717
  if (_perf_event_uncore_vector.cmp_info.disabled) return PAPI_ENOEVNT;
Packit 577717
Packit 577717
Packit 577717
  return _pe_libpfm4_ntv_enum_events(PapiEventCode, modifier, our_cidx,
Packit 577717
                                       &uncore_native_event_table);
Packit 577717
}
Packit 577717
Packit 577717
static int
Packit 577717
_peu_ntv_name_to_code( const char *name, unsigned int *event_code) {
Packit 577717
Packit 577717
  if (_perf_event_uncore_vector.cmp_info.disabled) return PAPI_ENOEVNT;
Packit 577717
Packit 577717
  return _pe_libpfm4_ntv_name_to_code(name,event_code, our_cidx,
Packit 577717
                                        &uncore_native_event_table);
Packit 577717
}
Packit 577717
Packit 577717
static int
Packit 577717
_peu_ntv_code_to_name(unsigned int EventCode,
Packit 577717
                          char *ntv_name, int len) {
Packit 577717
Packit 577717
   if (_perf_event_uncore_vector.cmp_info.disabled) return PAPI_ENOEVNT;
Packit 577717
Packit 577717
   return _pe_libpfm4_ntv_code_to_name(EventCode,
Packit 577717
                                         ntv_name, len, 
Packit 577717
					 &uncore_native_event_table);
Packit 577717
}
Packit 577717
Packit 577717
static int
Packit 577717
_peu_ntv_code_to_descr( unsigned int EventCode,
Packit 577717
                            char *ntv_descr, int len) {
Packit 577717
Packit 577717
   if (_perf_event_uncore_vector.cmp_info.disabled) return PAPI_ENOEVNT;
Packit 577717
Packit 577717
   return _pe_libpfm4_ntv_code_to_descr(EventCode,ntv_descr,len,
Packit 577717
                                          &uncore_native_event_table);
Packit 577717
}
Packit 577717
Packit 577717
static int
Packit 577717
_peu_ntv_code_to_info(unsigned int EventCode,
Packit 577717
                          PAPI_event_info_t *info) {
Packit 577717
Packit 577717
  if (_perf_event_uncore_vector.cmp_info.disabled) return PAPI_ENOEVNT;
Packit 577717
Packit 577717
  return _pe_libpfm4_ntv_code_to_info(EventCode, info,
Packit 577717
                                        &uncore_native_event_table);
Packit 577717
}
Packit 577717
Packit 577717
/* Our component vector */
Packit 577717
Packit 577717
papi_vector_t _perf_event_uncore_vector = {
Packit 577717
   .cmp_info = {
Packit 577717
       /* component information (unspecified values initialized to 0) */
Packit 577717
      .name = "perf_event_uncore",
Packit 577717
      .short_name = "peu",
Packit 577717
      .version = "5.0",
Packit 577717
      .description = "Linux perf_event CPU uncore and northbridge",
Packit 577717
Packit 577717
      .default_domain = PAPI_DOM_ALL,
Packit 577717
      .available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL | PAPI_DOM_SUPERVISOR,
Packit 577717
      .default_granularity = PAPI_GRN_SYS,
Packit 577717
      .available_granularities = PAPI_GRN_SYS,
Packit 577717
Packit 577717
      .num_mpx_cntrs = PERF_EVENT_MAX_MPX_COUNTERS,
Packit 577717
Packit 577717
      /* component specific cmp_info initializations */
Packit 577717
      .fast_virtual_timer = 0,
Packit 577717
      .attach = 1,
Packit 577717
      .attach_must_ptrace = 1,
Packit 577717
      .cpu = 1,
Packit 577717
      .inherit = 1,
Packit 577717
      .cntr_umasks = 1,
Packit 577717
Packit 577717
  },
Packit 577717
Packit 577717
  /* sizes of framework-opaque component-private structures */
Packit 577717
  .size = {
Packit 577717
      .context = sizeof ( pe_context_t ),
Packit 577717
      .control_state = sizeof ( pe_control_t ),
Packit 577717
      .reg_value = sizeof ( int ),
Packit 577717
      .reg_alloc = sizeof ( int ),
Packit 577717
  },
Packit 577717
Packit 577717
  /* function pointers in this component */
Packit 577717
  .init_component =        _peu_init_component,
Packit 577717
  .shutdown_component =    _peu_shutdown_component,
Packit 577717
  .init_thread =           _peu_init_thread,
Packit 577717
  .init_control_state =    _peu_init_control_state,
Packit 577717
  .start =                 _peu_start,
Packit 577717
  .stop =                  _peu_stop,
Packit 577717
  .read =                  _peu_read,
Packit 577717
  .shutdown_thread =       _peu_shutdown_thread,
Packit 577717
  .ctl =                   _peu_ctl,
Packit 577717
  .update_control_state =  _peu_update_control_state,
Packit 577717
  .set_domain =            _peu_set_domain,
Packit 577717
  .reset =                 _peu_reset,
Packit 577717
  .write =                 _peu_write,
Packit 577717
Packit 577717
  /* from counter name mapper */
Packit 577717
  .ntv_enum_events =   _peu_ntv_enum_events,
Packit 577717
  .ntv_name_to_code =  _peu_ntv_name_to_code,
Packit 577717
  .ntv_code_to_name =  _peu_ntv_code_to_name,
Packit 577717
  .ntv_code_to_descr = _peu_ntv_code_to_descr,
Packit 577717
  .ntv_code_to_info =  _peu_ntv_code_to_info,
Packit 577717
};
Packit 577717
Packit 577717