aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/perf_event.h9
-rw-r--r--include/linux/sched.h1
-rw-r--r--kernel/hw_breakpoint.c2
-rw-r--r--kernel/perf_event.c40
4 files changed, 33 insertions, 19 deletions
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 9ecfd856ce6e..c1173520f14d 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -952,14 +952,7 @@ extern int perf_event_overflow(struct perf_event *event, int nmi,
952 */ 952 */
953static inline int is_software_event(struct perf_event *event) 953static inline int is_software_event(struct perf_event *event)
954{ 954{
955 switch (event->attr.type) { 955 return event->pmu->task_ctx_nr == perf_sw_context;
956 case PERF_TYPE_SOFTWARE:
957 case PERF_TYPE_TRACEPOINT:
958 /* for now the breakpoint stuff also works as software event */
959 case PERF_TYPE_BREAKPOINT:
960 return 1;
961 }
962 return 0;
963} 956}
964 957
965extern atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX]; 958extern atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX];
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 89d6023c6f82..eb3c1ceec06e 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1163,6 +1163,7 @@ struct rcu_node;
1163enum perf_event_task_context { 1163enum perf_event_task_context {
1164 perf_invalid_context = -1, 1164 perf_invalid_context = -1,
1165 perf_hw_context = 0, 1165 perf_hw_context = 0,
1166 perf_sw_context,
1166 perf_nr_task_contexts, 1167 perf_nr_task_contexts,
1167}; 1168};
1168 1169
diff --git a/kernel/hw_breakpoint.c b/kernel/hw_breakpoint.c
index 6f150095cafe..3b2aaffb65f0 100644
--- a/kernel/hw_breakpoint.c
+++ b/kernel/hw_breakpoint.c
@@ -610,6 +610,8 @@ static void hw_breakpoint_stop(struct perf_event *bp, int flags)
610} 610}
611 611
612static struct pmu perf_breakpoint = { 612static struct pmu perf_breakpoint = {
613 .task_ctx_nr = perf_sw_context, /* could eventually get its own */
614
613 .event_init = hw_breakpoint_event_init, 615 .event_init = hw_breakpoint_event_init,
614 .add = hw_breakpoint_add, 616 .add = hw_breakpoint_add,
615 .del = hw_breakpoint_del, 617 .del = hw_breakpoint_del,
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index 7223ea875861..357ee8d5e8ae 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -4709,6 +4709,8 @@ static int perf_swevent_init(struct perf_event *event)
4709} 4709}
4710 4710
4711static struct pmu perf_swevent = { 4711static struct pmu perf_swevent = {
4712 .task_ctx_nr = perf_sw_context,
4713
4712 .event_init = perf_swevent_init, 4714 .event_init = perf_swevent_init,
4713 .add = perf_swevent_add, 4715 .add = perf_swevent_add,
4714 .del = perf_swevent_del, 4716 .del = perf_swevent_del,
@@ -4800,6 +4802,8 @@ static int perf_tp_event_init(struct perf_event *event)
4800} 4802}
4801 4803
4802static struct pmu perf_tracepoint = { 4804static struct pmu perf_tracepoint = {
4805 .task_ctx_nr = perf_sw_context,
4806
4803 .event_init = perf_tp_event_init, 4807 .event_init = perf_tp_event_init,
4804 .add = perf_trace_add, 4808 .add = perf_trace_add,
4805 .del = perf_trace_del, 4809 .del = perf_trace_del,
@@ -4988,6 +4992,8 @@ static int cpu_clock_event_init(struct perf_event *event)
4988} 4992}
4989 4993
4990static struct pmu perf_cpu_clock = { 4994static struct pmu perf_cpu_clock = {
4995 .task_ctx_nr = perf_sw_context,
4996
4991 .event_init = cpu_clock_event_init, 4997 .event_init = cpu_clock_event_init,
4992 .add = cpu_clock_event_add, 4998 .add = cpu_clock_event_add,
4993 .del = cpu_clock_event_del, 4999 .del = cpu_clock_event_del,
@@ -5063,6 +5069,8 @@ static int task_clock_event_init(struct perf_event *event)
5063} 5069}
5064 5070
5065static struct pmu perf_task_clock = { 5071static struct pmu perf_task_clock = {
5072 .task_ctx_nr = perf_sw_context,
5073
5066 .event_init = task_clock_event_init, 5074 .event_init = task_clock_event_init,
5067 .add = task_clock_event_add, 5075 .add = task_clock_event_add,
5068 .del = task_clock_event_del, 5076 .del = task_clock_event_del,
@@ -5490,6 +5498,7 @@ SYSCALL_DEFINE5(perf_event_open,
5490 struct perf_event_context *ctx; 5498 struct perf_event_context *ctx;
5491 struct file *event_file = NULL; 5499 struct file *event_file = NULL;
5492 struct file *group_file = NULL; 5500 struct file *group_file = NULL;
5501 struct pmu *pmu;
5493 int event_fd; 5502 int event_fd;
5494 int fput_needed = 0; 5503 int fput_needed = 0;
5495 int err; 5504 int err;
@@ -5522,20 +5531,11 @@ SYSCALL_DEFINE5(perf_event_open,
5522 goto err_fd; 5531 goto err_fd;
5523 } 5532 }
5524 5533
5525 /*
5526 * Get the target context (task or percpu):
5527 */
5528 ctx = find_get_context(event->pmu, pid, cpu);
5529 if (IS_ERR(ctx)) {
5530 err = PTR_ERR(ctx);
5531 goto err_alloc;
5532 }
5533
5534 if (group_fd != -1) { 5534 if (group_fd != -1) {
5535 group_leader = perf_fget_light(group_fd, &fput_needed); 5535 group_leader = perf_fget_light(group_fd, &fput_needed);
5536 if (IS_ERR(group_leader)) { 5536 if (IS_ERR(group_leader)) {
5537 err = PTR_ERR(group_leader); 5537 err = PTR_ERR(group_leader);
5538 goto err_context; 5538 goto err_alloc;
5539 } 5539 }
5540 group_file = group_leader->filp; 5540 group_file = group_leader->filp;
5541 if (flags & PERF_FLAG_FD_OUTPUT) 5541 if (flags & PERF_FLAG_FD_OUTPUT)
@@ -5545,6 +5545,23 @@ SYSCALL_DEFINE5(perf_event_open,
5545 } 5545 }
5546 5546
5547 /* 5547 /*
5548 * Special case software events and allow them to be part of
5549 * any hardware group.
5550 */
5551 pmu = event->pmu;
5552 if ((pmu->task_ctx_nr == perf_sw_context) && group_leader)
5553 pmu = group_leader->pmu;
5554
5555 /*
5556 * Get the target context (task or percpu):
5557 */
5558 ctx = find_get_context(pmu, pid, cpu);
5559 if (IS_ERR(ctx)) {
5560 err = PTR_ERR(ctx);
5561 goto err_group_fd;
5562 }
5563
5564 /*
5548 * Look up the group leader (we will attach this event to it): 5565 * Look up the group leader (we will attach this event to it):
5549 */ 5566 */
5550 if (group_leader) { 5567 if (group_leader) {
@@ -5605,8 +5622,9 @@ SYSCALL_DEFINE5(perf_event_open,
5605 return event_fd; 5622 return event_fd;
5606 5623
5607err_context: 5624err_context:
5608 fput_light(group_file, fput_needed);
5609 put_ctx(ctx); 5625 put_ctx(ctx);
5626err_group_fd:
5627 fput_light(group_file, fput_needed);
5610err_alloc: 5628err_alloc:
5611 free_event(event); 5629 free_event(event);
5612err_fd: 5630err_fd: