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