Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf/arch: Remove perf_sample_data::regs_user_copy

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

+22 -31
+1 -2
arch/arm/kernel/perf_regs.c
··· 32 32 } 33 33 34 34 void perf_get_regs_user(struct perf_regs *regs_user, 35 - struct pt_regs *regs, 36 - struct pt_regs *regs_user_copy) 35 + struct pt_regs *regs) 37 36 { 38 37 regs_user->regs = task_pt_regs(current); 39 38 regs_user->abi = perf_reg_abi(current);
+1 -2
arch/arm64/kernel/perf_regs.c
··· 73 73 } 74 74 75 75 void perf_get_regs_user(struct perf_regs *regs_user, 76 - struct pt_regs *regs, 77 - struct pt_regs *regs_user_copy) 76 + struct pt_regs *regs) 78 77 { 79 78 regs_user->regs = task_pt_regs(current); 80 79 regs_user->abi = perf_reg_abi(current);
+1 -2
arch/csky/kernel/perf_regs.c
··· 32 32 } 33 33 34 34 void perf_get_regs_user(struct perf_regs *regs_user, 35 - struct pt_regs *regs, 36 - struct pt_regs *regs_user_copy) 35 + struct pt_regs *regs) 37 36 { 38 37 regs_user->regs = task_pt_regs(current); 39 38 regs_user->abi = perf_reg_abi(current);
+1 -2
arch/powerpc/perf/perf_regs.c
··· 144 144 } 145 145 146 146 void perf_get_regs_user(struct perf_regs *regs_user, 147 - struct pt_regs *regs, 148 - struct pt_regs *regs_user_copy) 147 + struct pt_regs *regs) 149 148 { 150 149 regs_user->regs = task_pt_regs(current); 151 150 regs_user->abi = (regs_user->regs) ? perf_reg_abi(current) :
+1 -2
arch/riscv/kernel/perf_regs.c
··· 36 36 } 37 37 38 38 void perf_get_regs_user(struct perf_regs *regs_user, 39 - struct pt_regs *regs, 40 - struct pt_regs *regs_user_copy) 39 + struct pt_regs *regs) 41 40 { 42 41 regs_user->regs = task_pt_regs(current); 43 42 regs_user->abi = perf_reg_abi(current);
+1 -2
arch/s390/kernel/perf_regs.c
··· 53 53 } 54 54 55 55 void perf_get_regs_user(struct perf_regs *regs_user, 56 - struct pt_regs *regs, 57 - struct pt_regs *regs_user_copy) 56 + struct pt_regs *regs) 58 57 { 59 58 /* 60 59 * Use the regs from the first interruption and let
+11 -4
arch/x86/kernel/perf_regs.c
··· 101 101 } 102 102 103 103 void perf_get_regs_user(struct perf_regs *regs_user, 104 - struct pt_regs *regs, 105 - struct pt_regs *regs_user_copy) 104 + struct pt_regs *regs) 106 105 { 107 106 regs_user->regs = task_pt_regs(current); 108 107 regs_user->abi = perf_reg_abi(current); ··· 128 129 return PERF_SAMPLE_REGS_ABI_64; 129 130 } 130 131 132 + static DEFINE_PER_CPU(struct pt_regs, nmi_user_regs); 133 + 131 134 void perf_get_regs_user(struct perf_regs *regs_user, 132 - struct pt_regs *regs, 133 - struct pt_regs *regs_user_copy) 135 + struct pt_regs *regs) 134 136 { 137 + struct pt_regs *regs_user_copy = this_cpu_ptr(&nmi_user_regs); 135 138 struct pt_regs *user_regs = task_pt_regs(current); 139 + 140 + if (!in_nmi()) { 141 + regs_user->regs = user_regs; 142 + regs_user->abi = perf_reg_abi(current); 143 + return; 144 + } 136 145 137 146 /* 138 147 * If we're in an NMI that interrupted task_pt_regs setup, then
-6
include/linux/perf_event.h
··· 1022 1022 struct perf_callchain_entry *callchain; 1023 1023 u64 aux_size; 1024 1024 1025 - /* 1026 - * regs_user may point to task_pt_regs or to regs_user_copy, depending 1027 - * on arch details. 1028 - */ 1029 1025 struct perf_regs regs_user; 1030 - struct pt_regs regs_user_copy; 1031 - 1032 1026 struct perf_regs regs_intr; 1033 1027 u64 stack_user_size; 1034 1028
+2 -4
include/linux/perf_regs.h
··· 20 20 int perf_reg_validate(u64 mask); 21 21 u64 perf_reg_abi(struct task_struct *task); 22 22 void perf_get_regs_user(struct perf_regs *regs_user, 23 - struct pt_regs *regs, 24 - struct pt_regs *regs_user_copy); 23 + struct pt_regs *regs); 25 24 #else 26 25 27 26 #define PERF_REG_EXTENDED_MASK 0 ··· 41 42 } 42 43 43 44 static inline void perf_get_regs_user(struct perf_regs *regs_user, 44 - struct pt_regs *regs, 45 - struct pt_regs *regs_user_copy) 45 + struct pt_regs *regs) 46 46 { 47 47 regs_user->regs = task_pt_regs(current); 48 48 regs_user->abi = perf_reg_abi(current);
+3 -5
kernel/events/core.c
··· 6374 6374 } 6375 6375 6376 6376 static void perf_sample_regs_user(struct perf_regs *regs_user, 6377 - struct pt_regs *regs, 6378 - struct pt_regs *regs_user_copy) 6377 + struct pt_regs *regs) 6379 6378 { 6380 6379 if (user_mode(regs)) { 6381 6380 regs_user->abi = perf_reg_abi(current); 6382 6381 regs_user->regs = regs; 6383 6382 } else if (!(current->flags & PF_KTHREAD)) { 6384 - perf_get_regs_user(regs_user, regs, regs_user_copy); 6383 + perf_get_regs_user(regs_user, regs); 6385 6384 } else { 6386 6385 regs_user->abi = PERF_SAMPLE_REGS_ABI_NONE; 6387 6386 regs_user->regs = NULL; ··· 7082 7083 } 7083 7084 7084 7085 if (sample_type & (PERF_SAMPLE_REGS_USER | PERF_SAMPLE_STACK_USER)) 7085 - perf_sample_regs_user(&data->regs_user, regs, 7086 - &data->regs_user_copy); 7086 + perf_sample_regs_user(&data->regs_user, regs); 7087 7087 7088 7088 if (sample_type & PERF_SAMPLE_REGS_USER) { 7089 7089 /* regs dump ABI info */