Thread (17 messages) 17 messages, 5 authors, 2021-02-23

Re: [PATCH RFC 3/4] perf/core: Add support for SIGTRAP on perf events

flat view

From: Dmitry Vyukov <dvyukov@google.com>
Date: 2021-02-23 18:14:55
Also in: linux-fsdevel, linux-m68k, lkml

On Tue, Feb 23, 2021 at 3:34 PM Marco Elver [off-list ref] wrote:
quoted hunk ↗ jump to hunk
Adds bit perf_event_attr::sigtrap, which can be set to cause events to
send SIGTRAP (with si_code TRAP_PERF) to the task where the event
occurred. To distinguish perf events and allow user space to decode
si_perf (if set), the event type is set in si_errno.

The primary motivation is to support synchronous signals on perf events
in the task where an event (such as breakpoints) triggered.

Link: https://lore.kernel.org/lkml/YBv3rAT566k+6zjg@hirez.programming.kicks-ass.net/ (local)
Suggested-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Marco Elver <elver@google.com>
---
 include/uapi/linux/perf_event.h |  3 ++-
 kernel/events/core.c            | 21 +++++++++++++++++++++
 2 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index ad15e40d7f5d..b9cc6829a40c 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -389,7 +389,8 @@ struct perf_event_attr {
                                cgroup         :  1, /* include cgroup events */
                                text_poke      :  1, /* include text poke events */
                                build_id       :  1, /* use build id in mmap2 events */
-                               __reserved_1   : 29;
+                               sigtrap        :  1, /* send synchronous SIGTRAP on event */
+                               __reserved_1   : 28;

        union {
                __u32           wakeup_events;    /* wakeup every n events */
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 37a8297be164..8718763045fd 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -6288,6 +6288,17 @@ void perf_event_wakeup(struct perf_event *event)
        }
 }

+static void perf_sigtrap(struct perf_event *event)
+{
+       struct kernel_siginfo info;
+
+       clear_siginfo(&info);
+       info.si_signo = SIGTRAP;
+       info.si_code = TRAP_PERF;
+       info.si_errno = event->attr.type;
+       force_sig_info(&info);
+}
+
 static void perf_pending_event_disable(struct perf_event *event)
 {
        int cpu = READ_ONCE(event->pending_disable);
@@ -6297,6 +6308,13 @@ static void perf_pending_event_disable(struct perf_event *event)

        if (cpu == smp_processor_id()) {
                WRITE_ONCE(event->pending_disable, -1);
+
+               if (event->attr.sigtrap) {
+                       atomic_inc(&event->event_limit); /* rearm event */
We send the signal to the current task. Can this fire outside of the
current task context? E.g. in interrupt/softirq/etc? And then we will
send the signal to the current task. Watchpoint can be set to
userspace address and then something asynchronous (some IO completion)
that does not belong to this task access the userspace address (is
this possible?). But watchpoints can also be set to kernel addresses,
then another context can definitely access it.
(1) can this happen? maybe perf context is somehow disabled when !in_task()?
(2) if yes, what is the desired behavior?



quoted hunk ↗ jump to hunk
+                       perf_sigtrap(event);
+                       return;
+               }
+
                perf_event_disable_local(event);
                return;
        }
@@ -11325,6 +11343,9 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,

        event->state            = PERF_EVENT_STATE_INACTIVE;

+       if (event->attr.sigtrap)
+               atomic_set(&event->event_limit, 1);
+
        if (task) {
                event->attach_state = PERF_ATTACH_TASK;
                /*
--
2.30.0.617.g56c4b15f3c-goog
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help