[PATCH 05/21] perf: Add TIF_PERF_USER_DATA bit

Jiri Olsa
2018-01-24T11:52:01Z

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/tip-by32kqjb8rhjc0gdnzftur83@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
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