From 62799805b7750fd4147abab466936339b4c8bc0b Mon Sep 17 00:00:00 2001
From: Mihai Renea <mihairenea@llanberis.imp.fu-berlin.de>
Date: Mon, 18 Mar 2019 11:38:55 +0100
Subject: [PATCH] Switched to kernel internal calls for perf.

---
 kernel/sched/pb.c                           | 38 ++++++++++-----
 kernel/sched/perf_error_detection.c         | 53 ++++++++-------------
 kernel/sched/perf_error_detection.h         |  6 +--
 kernel/sched/sched.h                        |  9 ++--
 tools/testing/selftests/powerpc/pmu/event.c |  4 +-
 5 files changed, 58 insertions(+), 52 deletions(-)

diff --git a/kernel/sched/pb.c b/kernel/sched/pb.c
index 68b41ef95da8..e5492c36c1cd 100644
--- a/kernel/sched/pb.c
+++ b/kernel/sched/pb.c
@@ -4,6 +4,9 @@
 #include <linux/kthread.h>
 #include "perf_error_detection.h"
 
+/*
+ * Kelvin's Testcode
+ */
 void set_pb_measure_on(struct pb_rq *pb)
 {
 	pb->measure_k = PB_MEASURE_K_ON;
@@ -14,6 +17,9 @@ void set_pb_measure_on(struct pb_rq *pb)
 
 EXPORT_SYMBOL(set_pb_measure_on);
 
+/*
+ * Kelvin's Testcode
+ */
 void set_pb_measure_off(struct pb_rq *pb_rq)
 {
 	u64 runtime;
@@ -60,10 +66,7 @@ void init_pb_rq(struct pb_rq *pb_rq)
 	pb_rq->c_entry = 0;
 	pb_rq->proxy_task = NULL;
 	pb_rq->size = 0;
-
-	//init perf fd as invalid, since it is not initialized
-	pb_rq->fd = -1;
-
+	pb_rq->pevent = NULL;
 	pb_rq->measure_k = PB_MEASURE_K_OFF;
 	pb_rq->kstart = 0;
 	pb_rq->ktime = 0;
@@ -112,32 +115,43 @@ static struct task_struct * pick_next_task_pb(struct rq *rq,
 	next_mode = determine_next_mode_pb(rq);
 	pb->mode = next_mode;
 
+	int perf_init_res;
 
 	// The mode does not change --> no behavior change is needed
 	if (next_mode == PB_EXEC_MODE)
 	{
 		if (current_mode == PB_EXEC_MODE){
-			int perf_counter = terminate_perf_event(pb->fd,pb->plan[pb->c_entry].task_id);
+			int perf_counter = terminate_perf_event(pb->pevent, pb->plan[pb->c_entry].task_id);
 			//error detection
 			if (perf_counter < pb->plan[pb->c_entry].n_instr){
-				printk(KERN_WARNING "task %llu ran too short\n",pb->plan[pb->c_entry].task_id);
+				printk(KERN_WARNING "PB TASK %llu RAN TOO SHORT\n",pb->plan[pb->c_entry].task_id);
 			}
 			pb->c_entry++;
 			if (pb->c_entry >= pb->size){
 				printk(KERN_DEBUG "PLAN DONE\n");
 				pb->mode = PB_DISABLED_MODE;
 			}else{
-				init_perf_event(pb->plan[pb->c_entry]);
-				printk(KERN_DEBUG "EXEC,START,%u,%llu\n", pb->c_entry, sched_clock());
+				perf_init_res = init_perf_event(pb->plan[pb->c_entry], &pb->pevent);
+				if(perf_init_res < 0){
+					//initialization error detection/handling could happen here
+					printk(KERN_WARNING "PB EXEC,START,%u,%llu: FAILED OPEN PERF EVENT\n", pb->c_entry, sched_clock());
+				} else {
+					printk(KERN_DEBUG "PB EXEC,START,%u,%llu\n", pb->c_entry, sched_clock());
+
+				}
 			}
 		}else if(current_mode == PB_ADMIN_MODE){
-			printk(KERN_DEBUG "ADMIN,STOP,%u,%llu\n", pb->c_entry, sched_clock());
+			printk(KERN_DEBUG "PB ADMIN,STOP,%u,%llu\n", pb->c_entry, sched_clock());
 		}else{
-			pb->fd = init_perf_event(pb->plan[pb->c_entry]);
-			if(pb->fd < 0){
+			perf_init_res = init_perf_event(pb->plan[pb->c_entry], &pb->pevent);
+
+			if(perf_init_res < 0){
 				//initialization error detection/handling could happen here
+				printk(KERN_WARNING "PB INIT,%u,%llu: FAILED OPEN PERF EVENT\n", pb->c_entry, sched_clock());
+			} else {
+				printk(KERN_DEBUG "PB INIT,%u,%llu\n", pb->c_entry, sched_clock());
+
 			}
-			printk(KERN_DEBUG "PB INIT,%u,%llu\n", pb->c_entry, sched_clock());
 		}
 		//TODO: pick next task from taskarray
 		picked = pb->proxy_task;
diff --git a/kernel/sched/perf_error_detection.c b/kernel/sched/perf_error_detection.c
index cfea90319221..a96b57aa69a0 100644
--- a/kernel/sched/perf_error_detection.c
+++ b/kernel/sched/perf_error_detection.c
@@ -2,30 +2,28 @@
 #include <linux/smp.h>
 
 //initialize perf event for new task
-int init_perf_event(struct plan_entry plan_entry){
+int init_perf_event(struct plan_entry plan_entry, struct perf_event **pevent){
 	struct perf_event_attr pe;
-	struct perf_event *event;
 
 	//set perf_event_attr for init perf event
-	memset(&pe,0,sizeof(struct perf_event_attr));
-	pe.type=PERF_TYPE_HARDWARE;
-	pe.size=sizeof(struct perf_event_attr);
-	pe.config=PERF_COUNT_HW_INSTRUCTIONS;
-	pe.sample_period=plan_entry.n_instr;
-	pe.disabled=1;
-	pe.pinned=1;
-	pe.exclude_kernel=1;
-	pe.exclude_hv=1;
+	memset(&pe, 0, sizeof(struct perf_event_attr));
+	pe.type = PERF_TYPE_HARDWARE;
+	pe.size = sizeof(struct perf_event_attr);
+	pe.config = PERF_COUNT_HW_INSTRUCTIONS;
+	pe.sample_period = plan_entry.n_instr;
+	pe.disabled = 1;
+	pe.pinned = 1;
+	pe.exclude_kernel = 1;
+	pe.exclude_hv = 1;
 
 	/* Not needed on 3.2? */
-	pe.wakeup_events=1;
+	pe.wakeup_events = 1;
 
-	//perf_event_open(perf_event_attr,pid,cpu,groupfd,flags=0)
 	// cpu = -1 -> cpu indepented (assumed to be regulated by plan)
-	event = perf_event_open(&pe, smp_processor_id());
+	*pevent = perf_event_create(&pe, smp_processor_id());
 
 	if (IS_ERR(event)) {
-			printk(KERN_WARNING "Error initializing perf event \n");
+			printk(KERN_WARNING "PB ERROR INITIALISING PERF EVENT\n");
 			return -1;
 	}
 
@@ -33,14 +31,10 @@ int init_perf_event(struct plan_entry plan_entry){
 }
 
 //terminate perf event - return performance counter value
-long long terminate_perf_event(int fd, u64 task_id){
-//	if (ioctl(fd, PERF_EVENT_IOC_DISABLE, 0) != 0){
-//		printk(KERN_WARNING "could not disable perf event for task %llu",task_id);
-//	}
-	long long count;
-//	read(fd, &count, sizeof(long long));
-//	close(fd);
-	return count;
+long long terminate_perf_event(struct perf_event *pevent, u64 task_id){
+
+	return perf_event_release_kernel(pevent);
+
 }
 
 
@@ -53,21 +47,16 @@ void overflow_handler(
 {
 	struct pb_rq *pb_rq;
 	int cpu;
-//	int fd;
 
 	cpu = smp_processor_id();
-//	pb_rq = cpu_rq(cpu)->pb;
-	pb_rq = &cpu_rq(cpu)->pb; /* der compiler meckert: error: incompatible types when assigning to type ‘struct pb_rq *’ from type ‘struct pb_rq’ */
-//	fd =pb_rq->fd;
+	pb_rq = &cpu_rq(cpu)->pb;
+
 
-	printk(KERN_WARNING "task %llu ran too long\n",pb_rq->plan[pb_rq->c_entry].task_id);
+	printk(KERN_WARNING "PB TASK %llu RAN TOO LONG\n",pb_rq->plan[pb_rq->c_entry].task_id);
 
-//	if (ioctl(fd, PERF_EVENT_IOC_DISABLE, 0) != 0){
-//		printk(KERN_WARNING "could not disable perf event for cpu %d",cpu);
-//	}
 }
 
-struct perf_event* perf_event_open(struct perf_event_attr *hw_event_uptr, int cpu)
+struct perf_event* perf_event_create(struct perf_event_attr *hw_event_uptr, int cpu)
 {
 	return perf_event_create_kernel_counter(
 			hw_event_uptr,
diff --git a/kernel/sched/perf_error_detection.h b/kernel/sched/perf_error_detection.h
index 7d93b245829a..06b0767616b0 100644
--- a/kernel/sched/perf_error_detection.h
+++ b/kernel/sched/perf_error_detection.h
@@ -10,13 +10,13 @@
 //#include <include/linux/smp.h>
 #endif
 
-int init_perf_event(struct plan_entry);
+int init_perf_event(struct plan_entry, struct perf_event **pevent);
 
-long long terminate_perf_event(int fd, u64 task_id);
+long long terminate_perf_event(struct perf_event *pevent, u64 task_id);
 
 void overflow_handler(
 		struct perf_event *,
 		struct perf_sample_data *,
 		struct pt_regs *regs);
 
-struct perf_event *perf_event_open(struct perf_event_attr *hw_event_uptr, int);
+struct perf_event *perf_event_create(struct perf_event_attr *hw_event_uptr, int);
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index cca9e07f1047..dbbb652ab019 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -29,6 +29,7 @@
 #include <linux/irq_work.h>
 #include <linux/tick.h>
 #include <linux/slab.h>
+#include <linux/perf_event.h>
 
 #ifdef CONFIG_PARAVIRT
 #include <asm/paravirt.h>
@@ -551,13 +552,15 @@ struct pb_rq {
 	// one of PB_DISABLED_MODE, PB_EXEC_MODE, PB_ADMIN_MODE
 	int mode;
 
-	//file descriptor for perf event
-	int fd;
-
 	int measure_k;
 	u64 kstart;
 	u64 ktime;
 	u64 start;
+
+	/*
+	 * Per Core, nicht per Task
+	 */
+	struct perf_event *pevent;
 };
 
 /* Real-Time classes' related field in a runqueue: */
diff --git a/tools/testing/selftests/powerpc/pmu/event.c b/tools/testing/selftests/powerpc/pmu/event.c
index 184b36807d48..7e01810ee6e7 100644
--- a/tools/testing/selftests/powerpc/pmu/event.c
+++ b/tools/testing/selftests/powerpc/pmu/event.c
@@ -13,7 +13,7 @@
 #include "event.h"
 
 
-int perf_event_open(struct perf_event_attr *attr, pid_t pid, int cpu,
+int perf_event_create(struct perf_event_attr *attr, pid_t pid, int cpu,
 		int group_fd, unsigned long flags)
 {
 	return syscall(__NR_perf_event_open, attr, pid, cpu,
@@ -51,7 +51,7 @@ void event_init(struct event *e, u64 config)
 
 int event_open_with_options(struct event *e, pid_t pid, int cpu, int group_fd)
 {
-	e->fd = perf_event_open(&e->attr, pid, cpu, group_fd, 0);
+	e->fd = perf_event_create(&e->attr, pid, cpu, group_fd, 0);
 	if (e->fd == -1) {
 		perror("perf_event_open");
 		return -1;
-- 
GitLab