]> git.baikalelectronics.ru Git - kernel.git/commitdiff
perf/arch: Remove perf_sample_data::regs_user_copy
authorPeter Zijlstra <peterz@infradead.org>
Fri, 30 Oct 2020 11:14:21 +0000 (12:14 +0100)
committerPeter Zijlstra <peterz@infradead.org>
Mon, 9 Nov 2020 17:12:34 +0000 (18:12 +0100)
struct perf_sample_data lives on-stack, we should be careful about it's
size. Furthermore, the pt_regs copy in there is only because x86_64 is a
trainwreck, solve it differently.

Reported-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Tested-by: Steven Rostedt <rostedt@goodmis.org>
Link: https://lkml.kernel.org/r/20201030151955.258178461@infradead.org
arch/arm/kernel/perf_regs.c
arch/arm64/kernel/perf_regs.c
arch/csky/kernel/perf_regs.c
arch/powerpc/perf/perf_regs.c
arch/riscv/kernel/perf_regs.c
arch/s390/kernel/perf_regs.c
arch/x86/kernel/perf_regs.c
include/linux/perf_event.h
include/linux/perf_regs.h
kernel/events/core.c

index 05fe92aa7d989e2a4207f3269c9caa1b0a2dfd06..0529f90395c94d82611a406d540a450d537dad13 100644 (file)
@@ -32,8 +32,7 @@ u64 perf_reg_abi(struct task_struct *task)
 }
 
 void perf_get_regs_user(struct perf_regs *regs_user,
-                       struct pt_regs *regs,
-                       struct pt_regs *regs_user_copy)
+                       struct pt_regs *regs)
 {
        regs_user->regs = task_pt_regs(current);
        regs_user->abi = perf_reg_abi(current);
index 94e8718e722900fa7208e42ec08ee686864ea4bc..f6f58e6265df89d8c1ce7a49ff052728cbdb9c8c 100644 (file)
@@ -73,8 +73,7 @@ u64 perf_reg_abi(struct task_struct *task)
 }
 
 void perf_get_regs_user(struct perf_regs *regs_user,
-                       struct pt_regs *regs,
-                       struct pt_regs *regs_user_copy)
+                       struct pt_regs *regs)
 {
        regs_user->regs = task_pt_regs(current);
        regs_user->abi = perf_reg_abi(current);
index eb32838b8210f8a43bf4b2a335c43760d46f91ef..09b7f88a2d6ad42184b664141c9672262b6b4b38 100644 (file)
@@ -32,8 +32,7 @@ u64 perf_reg_abi(struct task_struct *task)
 }
 
 void perf_get_regs_user(struct perf_regs *regs_user,
-                       struct pt_regs *regs,
-                       struct pt_regs *regs_user_copy)
+                       struct pt_regs *regs)
 {
        regs_user->regs = task_pt_regs(current);
        regs_user->abi = perf_reg_abi(current);
index 8e53f2fc3fe07f3e5b782f067094e50bb94fa33d..6f681b105eec21bb1d0375f136aaea0e6a71da1a 100644 (file)
@@ -144,8 +144,7 @@ u64 perf_reg_abi(struct task_struct *task)
 }
 
 void perf_get_regs_user(struct perf_regs *regs_user,
-                       struct pt_regs *regs,
-                       struct pt_regs *regs_user_copy)
+                       struct pt_regs *regs)
 {
        regs_user->regs = task_pt_regs(current);
        regs_user->abi = (regs_user->regs) ? perf_reg_abi(current) :
index 04a38fbeb9c7a1e3322abceb9ce7c739faf48a55..fd304a248de68a02c8dcd3ceb58fc8bb4ea8b83f 100644 (file)
@@ -36,8 +36,7 @@ u64 perf_reg_abi(struct task_struct *task)
 }
 
 void perf_get_regs_user(struct perf_regs *regs_user,
-                       struct pt_regs *regs,
-                       struct pt_regs *regs_user_copy)
+                       struct pt_regs *regs)
 {
        regs_user->regs = task_pt_regs(current);
        regs_user->abi = perf_reg_abi(current);
index 4352a504f2354fe04a5730736958f24c709c7428..6e9e5d5e927ef51cb50d9564277f2130396c8b12 100644 (file)
@@ -53,8 +53,7 @@ u64 perf_reg_abi(struct task_struct *task)
 }
 
 void perf_get_regs_user(struct perf_regs *regs_user,
-                       struct pt_regs *regs,
-                       struct pt_regs *regs_user_copy)
+                       struct pt_regs *regs)
 {
        /*
         * Use the regs from the first interruption and let
index bb7e1132290b0073b0ff3b0ac68d69d48016d2a8..f9e5352b3bef9b1b99153c9cb0392f9c50048aea 100644 (file)
@@ -101,8 +101,7 @@ u64 perf_reg_abi(struct task_struct *task)
 }
 
 void perf_get_regs_user(struct perf_regs *regs_user,
-                       struct pt_regs *regs,
-                       struct pt_regs *regs_user_copy)
+                       struct pt_regs *regs)
 {
        regs_user->regs = task_pt_regs(current);
        regs_user->abi = perf_reg_abi(current);
@@ -129,12 +128,20 @@ u64 perf_reg_abi(struct task_struct *task)
                return PERF_SAMPLE_REGS_ABI_64;
 }
 
+static DEFINE_PER_CPU(struct pt_regs, nmi_user_regs);
+
 void perf_get_regs_user(struct perf_regs *regs_user,
-                       struct pt_regs *regs,
-                       struct pt_regs *regs_user_copy)
+                       struct pt_regs *regs)
 {
+       struct pt_regs *regs_user_copy = this_cpu_ptr(&nmi_user_regs);
        struct pt_regs *user_regs = task_pt_regs(current);
 
+       if (!in_nmi()) {
+               regs_user->regs = user_regs;
+               regs_user->abi = perf_reg_abi(current);
+               return;
+       }
+
        /*
         * If we're in an NMI that interrupted task_pt_regs setup, then
         * we can't sample user regs at all.  This check isn't really
index b775ae0a8c870ffb97fc070fdb294b2abffaecb1..96450f6fb1de888ed1135303c4a4387308656771 100644 (file)
@@ -1022,13 +1022,7 @@ struct perf_sample_data {
        struct perf_callchain_entry     *callchain;
        u64                             aux_size;
 
-       /*
-        * regs_user may point to task_pt_regs or to regs_user_copy, depending
-        * on arch details.
-        */
        struct perf_regs                regs_user;
-       struct pt_regs                  regs_user_copy;
-
        struct perf_regs                regs_intr;
        u64                             stack_user_size;
 
index 2d12e97d5e7bc16a3edf1c9a39e177f7b73e5874..f632c5725f162f723fd3536f64c0eaf64b7ae391 100644 (file)
@@ -20,8 +20,7 @@ u64 perf_reg_value(struct pt_regs *regs, int idx);
 int perf_reg_validate(u64 mask);
 u64 perf_reg_abi(struct task_struct *task);
 void perf_get_regs_user(struct perf_regs *regs_user,
-                       struct pt_regs *regs,
-                       struct pt_regs *regs_user_copy);
+                       struct pt_regs *regs);
 #else
 
 #define PERF_REG_EXTENDED_MASK 0
@@ -42,8 +41,7 @@ static inline u64 perf_reg_abi(struct task_struct *task)
 }
 
 static inline void perf_get_regs_user(struct perf_regs *regs_user,
-                                     struct pt_regs *regs,
-                                     struct pt_regs *regs_user_copy)
+                                     struct pt_regs *regs)
 {
        regs_user->regs = task_pt_regs(current);
        regs_user->abi = perf_reg_abi(current);
index fc681c7c1e0351298059b4ef82f53d209bdac93a..d67c9cbb0f6a41caedf518a5ee34b1f1db1d4baa 100644 (file)
@@ -6374,14 +6374,13 @@ perf_output_sample_regs(struct perf_output_handle *handle,
 }
 
 static void perf_sample_regs_user(struct perf_regs *regs_user,
-                                 struct pt_regs *regs,
-                                 struct pt_regs *regs_user_copy)
+                                 struct pt_regs *regs)
 {
        if (user_mode(regs)) {
                regs_user->abi = perf_reg_abi(current);
                regs_user->regs = regs;
        } else if (!(current->flags & PF_KTHREAD)) {
-               perf_get_regs_user(regs_user, regs, regs_user_copy);
+               perf_get_regs_user(regs_user, regs);
        } else {
                regs_user->abi = PERF_SAMPLE_REGS_ABI_NONE;
                regs_user->regs = NULL;
@@ -7083,8 +7082,7 @@ void perf_prepare_sample(struct perf_event_header *header,
        }
 
        if (sample_type & (PERF_SAMPLE_REGS_USER | PERF_SAMPLE_STACK_USER))
-               perf_sample_regs_user(&data->regs_user, regs,
-                                     &data->regs_user_copy);
+               perf_sample_regs_user(&data->regs_user, regs);
 
        if (sample_type & PERF_SAMPLE_REGS_USER) {
                /* regs dump ABI info */