aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2014-06-05 05:18:03 -0400
committerIngo Molnar <mingo@kernel.org>2014-06-05 06:26:27 -0400
commitc56d34064b6eb9f9cde9e35bbfe16eedf3d81f94 (patch)
tree9877ef9e1b238e14a1878f10d51ea55fbca5f619
parentb13fa91421213a8d1fd05086050f05e994f3b72d (diff)
parenta03b1e1c372b60183b8141cdd161316429fab5ac (diff)
Merge branch 'perf/uprobes' into perf/core
These bits from Oleg are fully cooked, ship them to Linus. Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/include/asm/traps.h1
-rw-r--r--arch/x86/include/asm/uprobes.h10
-rw-r--r--arch/x86/kernel/process_64.c7
-rw-r--r--arch/x86/kernel/traps.c110
-rw-r--r--arch/x86/kernel/uprobes.c506
-rw-r--r--include/linux/uprobes.h4
-rw-r--r--kernel/events/uprobes.c35
-rw-r--r--kernel/trace/trace_uprobe.c46
8 files changed, 402 insertions, 317 deletions
<
diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h
index 58d66fe06b61..a7b212db9e04 100644
--- a/arch/x86/include/asm/traps.h
+++ b/arch/x86/include/asm/traps.h
@@ -98,7 +98,6 @@ static inline int get_si_code(unsigned long condition)
98 98
99extern int panic_on_unrecovered_nmi; 99extern int panic_on_unrecovered_nmi;
100 100
101void math_error(struct pt_regs *, int, int);
102void math_emulate(struct math_emu_info *); 101void math_emulate(struct math_emu_info *);
103#ifndef CONFIG_X86_32 102#ifndef CONFIG_X86_32
104asmlinkage void smp_thermal_interrupt(void); 103asmlinkage void smp_thermal_interrupt(void);
diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h
index 93bee7b93854..7be3c079e389 100644
--- a/arch/x86/include/asm/uprobes.h
+++ b/arch/x86/include/asm/uprobes.h
@@ -41,18 +41,18 @@ struct arch_uprobe {
41 u8 ixol[MAX_UINSN_BYTES]; 41 u8 ixol[MAX_UINSN_BYTES];
42 }; 42 };
43 43
44 u16 fixups;
45 const struct uprobe_xol_ops *ops; 44 const struct uprobe_xol_ops *ops;
46 45
47 union { 46 union {
48#ifdef CONFIG_X86_64
49 unsigned long rip_rela_target_address;
50#endif
51 struct { 47 struct {
52 s32 offs; 48 s32 offs;
53 u8 ilen; 49 u8 ilen;
54 u8 opc1; 50 u8 opc1;
55 } branch; 51 } branch;
52 struct {
53 u8 fixups;
54 u8 ilen;
55 } def;
56 }; 56 };
57}; 57};
58 58
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 9c0280f93d05..9b53940981b7 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -413,12 +413,11 @@ void set_personality_ia32(bool x32)
413 set_thread_flag(TIF_ADDR32); 413 set_thread_flag(TIF_ADDR32);
414 414
415 /* Mark the associated mm as containing 32-bit tasks. */ 415 /* Mark the associated mm as containing 32-bit tasks. */
416 if (current->mm)
417 current->mm->context.ia32_compat = 1;
418
419 if (x32) { 416 if (x32) {
420 clear_thread_flag(TIF_IA32); 417 clear_thread_flag(TIF_IA32);
421 set_thread_flag(TIF_X32); 418 set_thread_flag(TIF_X32);
419 if (current->mm)
420 current->mm->context.ia32_compat = TIF_X32;
422 current->personality &= ~READ_IMPLIES_EXEC; 421 current->personality &= ~READ_IMPLIES_EXEC;
423 /* is_compat_task() uses the presence of the x32 422 /* is_compat_task() uses the presence of the x32
424 syscall bit flag to determine compat status */ 423 syscall bit flag to determine compat status */
@@ -426,6 +425,8 @@ void set_personality_ia32(bool x32)
426 } else { 425 } else {
427 set_thread_flag(TIF_IA32); 426 set_thread_flag(TIF_IA32);
428 clear_thread_flag(TIF_X32); 427 clear_thread_flag(TIF_X32);
428 if (current->mm)
429 current->mm->context.ia32_compat = TIF_IA32;
429 current->personality |= force_personality32; 430 current->personality |= force_personality32;
430 /* Prepare the first "return" to user space */ 431 /* Prepare the first "return" to user space */
431 current_thread_info()->status |= TS_COMPAT; 432 current_thread_info()->status |= TS_COMPAT;
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 57409f6b8c62..3fdb20548c4b 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -23,6 +23,7 @@
23#include <linux/kernel.h> 23#include <linux/kernel.h>
24#include <linux/module.h> 24#include <linux/module.h>
25#include <linux/ptrace.h> 25#include <linux/ptrace.h>
26#include <linux/uprobes.h>
26#include <linux/string.h> 27#include <linux/string.h>
27#include <linux/delay.h> 28#include <linux/delay.h>
28#include <linux/errno.h> 29#include <linux/errno.h>
@@ -136,6 +137,37 @@ do_trap_no_signal(struct task_struct *tsk, int trapnr, char *str,
136 return -1; 137 return -1;
137} 138}
138 139
140static siginfo_t *fill_trap_info(struct pt_regs *regs, int signr, int trapnr,
141 siginfo_t *info)
142{
143 unsigned long siaddr;
144 int sicode;
145
146 switch (trapnr) {
147 default:
148 return SEND_SIG_PRIV;
149
150 case X86_TRAP_DE:
151 sicode = FPE_INTDIV;
152 siaddr = uprobe_get_trap_addr(regs);
153 break;
154 case X86_TRAP_UD:
155 sicode = ILL_ILLOPN;
156 siaddr = uprobe_get_trap_addr(regs);
157 break;
158 case X86_TRAP_AC:
159 sicode = BUS_ADRALN;
160 siaddr = 0;
161 break;
162 }
163
164 info->si_signo = signr;
165 info->si_errno = 0;
166 info->si_code = sicode;
167 info->si_addr = (void __user *)siaddr;
168 return info;
169}
170
139static void __kprobes 171static void __kprobes
140do_trap(int trapnr, int signr, char *str, struct pt_regs *regs, 172do_trap(int trapnr, int signr, char *str, struct pt_regs *regs,
141 long error_code, siginfo_t *info) 173 long error_code, siginfo_t *info)
@@ -168,60 +200,42 @@ do_trap(int trapnr, int signr, char *str, struct pt_regs *regs,
168 } 200 }
169#endif 201#endif
170 202
171 if (info) 203 force_sig_info(signr, info ?: SEND_SIG_PRIV, tsk);
172 force_sig_info(signr, info, tsk);
173 else
174 force_sig(signr, tsk);
175} 204}
176 205
177#define DO_ERROR(trapnr, signr, str, name) \ 206static void do_error_trap(struct pt_regs *regs, long error_code, char *str,
178dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \ 207 unsigned long trapnr, int signr)
179{ \ 208{
180 enum ctx_state prev_state; \ 209 enum ctx_state prev_state = exception_enter();
181 \ 210 siginfo_t info;
182 prev_state = exception_enter(); \ 211
183 if (notify_die(DIE_TRAP, str, regs, error_code, \ 212 if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) !=
184 trapnr, signr) == NOTIFY_STOP) { \ 213 NOTIFY_STOP) {
185 exception_exit(prev_state); \ 214 conditional_sti(regs);
186 return; \ 215 do_trap(trapnr, signr, str, regs, error_code,
187 } \ 216 fill_trap_info(regs, signr, trapnr, &info));
188 conditional_sti(regs); \ 217 }
189 do_trap(trapnr, signr, str, regs, error_code, NULL); \ 218
190 exception_exit(prev_state); \ 219 exception_exit(prev_state);
191} 220}
192 221
193#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ 222#define DO_ERROR(trapnr, signr, str, name) \
194dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \ 223dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \
195{ \ 224{ \
196 siginfo_t info; \