From 5d9ed8d5d9e9e28658dec1da8521a301eff7b086 Mon Sep 17 00:00:00 2001
From: James Ralph <ralph@icl.utk.edu>
Date: Wed, 30 Jul 2014 12:41:30 -0400
Subject: [PATCH 16/44] Libpfm4 update: catch the cpu= modifier update

Inline with:
commit c9482351a6ce2cf39433527fdad41a78fed2b6f2
Author: Stephane Eranian <eranian@gmail.com>
Date:   Fri Apr 18 14:11:36 2014 +0200

    activate perf_event_ext cpu= modifier

    Enable cpu=X  perf_events modifier on events.
    The cpu number is returned in the pfm_perf_encode_arg.cpu
    field. If modifier not set in event string, then field has
    value -1.

    This is an indicative information of where the user
    wants the event to be programmed. This is useful
    only in system-wide mode. The library does not
    program the event with perf_events. The
    user program still has to invoke the perf_event_open()
    syscall.
---
 src/libpfm4/include/perfmon/pfmlib_perf_event.h |  2 +-
 src/libpfm4/lib/pfmlib_perf_event.c             | 11 +++++++++++
 src/libpfm4/lib/pfmlib_perf_event_priv.h        |  2 ++
 src/libpfm4/perf_examples/perf_util.c           |  1 +
 src/libpfm4/perf_examples/perf_util.h           |  1 +
 5 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/src/libpfm4/include/perfmon/pfmlib_perf_event.h b/src/libpfm4/include/perfmon/pfmlib_perf_event.h
index d4620f2..8b3dae2 100644
--- a/src/libpfm4/include/perfmon/pfmlib_perf_event.h
+++ b/src/libpfm4/include/perfmon/pfmlib_perf_event.h
@@ -37,7 +37,7 @@ typedef struct {
 	char **fstr;			/* out/in: fully qualified event string */
 	size_t size;			/* sizeof struct */
 	int idx;			/* out: opaque event identifier */
-	int cpu;			/* out: cpu to program */
+	int cpu;			/* out: cpu to program, -1 = not set */
 	int flags;			/* out: perf_event_open() flags */
 	int pad0;			/* explicit 64-bit mode padding */
 } pfm_perf_encode_arg_t;
diff --git a/src/libpfm4/lib/pfmlib_perf_event.c b/src/libpfm4/lib/pfmlib_perf_event.c
index 4458d98..dbc5dd9 100644
--- a/src/libpfm4/lib/pfmlib_perf_event.c
+++ b/src/libpfm4/lib/pfmlib_perf_event.c
@@ -25,6 +25,7 @@
 #include <unistd.h>
 #include <string.h>
 #include <stdlib.h>
+#include <limits.h>
 #include <perfmon/pfmlib_perf_event.h>
 
 #include "pfmlib_priv.h"
@@ -67,6 +68,7 @@ static const pfmlib_attr_desc_t perf_event_ext_mods[]={
 	PFM_ATTR_B("excl", "exclusive access"),    	/* exclusive PMU access */
 	PFM_ATTR_B("mg", "monitor guest execution"),	/* monitor guest level */
 	PFM_ATTR_B("mh", "monitor host execution"),	/* monitor host level */
+	PFM_ATTR_I("cpu", "CPU to program"),		/* CPU to program */
 	PFM_ATTR_NULL /* end-marker to avoid exporting number of entries */
 };
 
@@ -84,6 +86,7 @@ pfmlib_perf_event_encode(void *this, const char *str, int dfl_plm, void *data)
 	uint64_t ival;
 	int has_plm = 0, has_vmx_plm = 0;
 	int i, plm = 0, ret, vmx_plm = 0;
+	int cpu = -1;
 
 	sz = pfmlib_check_struct(uarg, uarg->size, PFM_PERF_ENCODE_ABI0, sz);
 	if (!sz)
@@ -203,6 +206,11 @@ pfmlib_perf_event_encode(void *this, const char *str, int dfl_plm, void *data)
 			vmx_plm |= PFM_PLM0;
 			has_vmx_plm = 1;
 			break;
+		case PERF_ATTR_CPU:
+			if (ival >= INT_MAX)
+				return PFM_ERR_ATTR_VAL;
+			cpu = (int)ival;
+			break;
 		}
 	}
 	/*
@@ -251,6 +259,9 @@ pfmlib_perf_event_encode(void *this, const char *str, int dfl_plm, void *data)
 	 */
 	arg.idx = pfmlib_pidx2idx(e.pmu, e.event);
 
+	/* propagate cpu */
+	arg.cpu = cpu;
+
 	/* propagate our changes, that overwrites attr->size */
 	memcpy(uarg->attr, attr, asz);
 
diff --git a/src/libpfm4/lib/pfmlib_perf_event_priv.h b/src/libpfm4/lib/pfmlib_perf_event_priv.h
index 0063c77..ee2afc7 100644
--- a/src/libpfm4/lib/pfmlib_perf_event_priv.h
+++ b/src/libpfm4/lib/pfmlib_perf_event_priv.h
@@ -35,6 +35,7 @@
 #define PERF_ATTR_EX	6	/* exclusive event */
 #define PERF_ATTR_MG	7	/* monitor guest execution */
 #define PERF_ATTR_MH	8	/* monitor host execution */
+#define PERF_ATTR_CPU	9	/* CPU to program */
 
 #define _PERF_ATTR_U  (1 << PERF_ATTR_U)
 #define _PERF_ATTR_K  (1 << PERF_ATTR_K)
@@ -45,6 +46,7 @@
 #define _PERF_ATTR_EX (1 << PERF_ATTR_EX)
 #define _PERF_ATTR_MG (1 << PERF_ATTR_MG)
 #define _PERF_ATTR_MH (1 << PERF_ATTR_MH)
+#define _PERF_ATTR_CPU (1 << PERF_ATTR_CPU)
 
 #define PERF_PLM_ALL (PFM_PLM0|PFM_PLM3|PFM_PLMH)
 
diff --git a/src/libpfm4/perf_examples/perf_util.c b/src/libpfm4/perf_examples/perf_util.c
index a5635d5..2fb5d4a 100644
--- a/src/libpfm4/perf_examples/perf_util.c
+++ b/src/libpfm4/perf_examples/perf_util.c
@@ -97,6 +97,7 @@ perf_setup_argv_events(const char **argv, perf_event_desc_t **fds, int *num_fds)
 		fd[num].name = strdup(*argv);
 		fd[num].group_leader = group_leader;
 		fd[num].idx = arg.idx;
+		fd[num].cpu = arg.cpu;
 
 		num++;
 		argv++;
diff --git a/src/libpfm4/perf_examples/perf_util.h b/src/libpfm4/perf_examples/perf_util.h
index 04704bd..4571500 100644
--- a/src/libpfm4/perf_examples/perf_util.h
+++ b/src/libpfm4/perf_examples/perf_util.h
@@ -41,6 +41,7 @@ typedef struct {
 	int fd;
 	int max_fds;
 	int idx; /* opaque libpfm event identifier */
+	int cpu; /* cpu to program */
 	char *fstr; /* fstr from library, must be freed */
 } perf_event_desc_t;
 
-- 
2.1.1

