Adding TIF_PERF_USER_DATA bit to be able to limit the code area
where the perf's delayed user data retrieval is possible.

Task which is marked with TIF_PERF_USER_DATA bit, will do the slow
syscall path and mark the 'safe area' to trigger user data harvest
through the task_work by setting up its perf_user_data_allowed bit.

Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Jiri Olsa <[email protected]>
---
 arch/x86/entry/common.c            | 6 ++++++
 arch/x86/include/asm/thread_info.h | 4 +++-
 include/linux/sched.h              | 3 +++
 3 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
index d7d3cc24baf4..29d9e5ef0c75 100644
--- a/arch/x86/entry/common.c
+++ b/arch/x86/entry/common.c
@@ -77,6 +77,9 @@ static long syscall_trace_enter(struct pt_regs *regs)
 
        work = READ_ONCE(ti->flags) & _TIF_WORK_SYSCALL_ENTRY;
 
+       if (unlikely(work & _TIF_PERF_USER_DATA))
+               current->perf_user_data_allowed = 1;
+
        if (unlikely(work & _TIF_SYSCALL_EMU))
                emulated = true;
 
@@ -191,6 +194,9 @@ __visible inline void prepare_exit_to_usermode(struct 
pt_regs *regs)
 
        cached_flags = READ_ONCE(ti->flags);
 
+       if (unlikely(cached_flags & _TIF_PERF_USER_DATA))
+               current->perf_user_data_allowed = 0;
+
        if (unlikely(cached_flags & EXIT_TO_USERMODE_LOOP_FLAGS))
                exit_to_usermode_loop(regs, cached_flags);
 
diff --git a/arch/x86/include/asm/thread_info.h 
b/arch/x86/include/asm/thread_info.h
index 00223333821a..f664f4bd25ac 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -80,6 +80,7 @@ struct thread_info {
 #define TIF_SIGPENDING         2       /* signal pending */
 #define TIF_NEED_RESCHED       3       /* rescheduling necessary */
 #define TIF_SINGLESTEP         4       /* reenable singlestep on user return*/
+#define TIF_PERF_USER_DATA     5       /* enable safe area for perf user data 
retrieval */
 #define TIF_SYSCALL_EMU                6       /* syscall emulation active */
 #define TIF_SYSCALL_AUDIT      7       /* syscall auditing active */
 #define TIF_SECCOMP            8       /* secure computing */
@@ -106,6 +107,7 @@ struct thread_info {
 #define _TIF_SIGPENDING                (1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
 #define _TIF_SINGLESTEP                (1 << TIF_SINGLESTEP)
+#define _TIF_PERF_USER_DATA    (1 << TIF_PERF_USER_DATA)
 #define _TIF_SYSCALL_EMU       (1 << TIF_SYSCALL_EMU)
 #define _TIF_SYSCALL_AUDIT     (1 << TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP           (1 << TIF_SECCOMP)
@@ -133,7 +135,7 @@ struct thread_info {
 #define _TIF_WORK_SYSCALL_ENTRY        \
        (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_EMU | _TIF_SYSCALL_AUDIT |   \
         _TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT |       \
-        _TIF_NOHZ)
+        _TIF_NOHZ | _TIF_PERF_USER_DATA)
 
 /* work to do on any return to user space */
 #define _TIF_ALLWORK_MASK                                              \
diff --git a/include/linux/sched.h b/include/linux/sched.h
index d2588263a989..6e8079524010 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -653,6 +653,9 @@ struct task_struct {
        /* disallow userland-initiated cgroup migration */
        unsigned                        no_cgroup_migration:1;
 #endif
+#ifdef CONFIG_PERF_EVENTS
+       unsigned                        perf_user_data_allowed:1;
+#endif
 
        unsigned long                   atomic_flags; /* Flags requiring atomic 
access. */
 
-- 
2.13.6

Reply via email to