From: Ingo Molnar Date: Thu, 22 May 2014 11:54:29 +0000 (+0200) Subject: manual merge of perf/uprobes X-Git-Tag: next-20140530~38^2~13 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=60ea7745de12721f83e3e6f3748f647376c379e4;p=karo-tx-linux.git manual merge of perf/uprobes Signed-off-by: Ingo Molnar --- 60ea7745de12721f83e3e6f3748f647376c379e4 diff --cc arch/x86/kernel/traps.c index fdbaa5a715f1,3fdb20548c4b..c6eb418c5627 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@@ -136,7 -137,38 +137,38 @@@ do_trap_no_signal(struct task_struct *t return -1; } + static siginfo_t *fill_trap_info(struct pt_regs *regs, int signr, int trapnr, + siginfo_t *info) + { + unsigned long siaddr; + int sicode; + + switch (trapnr) { + default: + return SEND_SIG_PRIV; + + case X86_TRAP_DE: + sicode = FPE_INTDIV; + siaddr = uprobe_get_trap_addr(regs); + break; + case X86_TRAP_UD: + sicode = ILL_ILLOPN; + siaddr = uprobe_get_trap_addr(regs); + break; + case X86_TRAP_AC: + sicode = BUS_ADRALN; + siaddr = 0; + break; + } + + info->si_signo = signr; + info->si_errno = 0; + info->si_code = sicode; + info->si_addr = (void __user *)siaddr; + return info; + } + -static void __kprobes +static void do_trap(int trapnr, int signr, char *str, struct pt_regs *regs, long error_code, siginfo_t *info) { @@@ -168,61 -200,42 +200,43 @@@ } #endif - if (info) - force_sig_info(signr, info, tsk); - else - force_sig(signr, tsk); + force_sig_info(signr, info ?: SEND_SIG_PRIV, tsk); } +NOKPROBE_SYMBOL(do_trap); - #define DO_ERROR(trapnr, signr, str, name) \ - dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \ - { \ - enum ctx_state prev_state; \ - \ - prev_state = exception_enter(); \ - if (notify_die(DIE_TRAP, str, regs, error_code, \ - trapnr, signr) == NOTIFY_STOP) { \ - exception_exit(prev_state); \ - return; \ - } \ - conditional_sti(regs); \ - do_trap(trapnr, signr, str, regs, error_code, NULL); \ - exception_exit(prev_state); \ + static void do_error_trap(struct pt_regs *regs, long error_code, char *str, + unsigned long trapnr, int signr) + { + enum ctx_state prev_state = exception_enter(); + siginfo_t info; + + if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) != + NOTIFY_STOP) { + conditional_sti(regs); + do_trap(trapnr, signr, str, regs, error_code, + fill_trap_info(regs, signr, trapnr, &info)); + } + + exception_exit(prev_state); } - #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ + #define DO_ERROR(trapnr, signr, str, name) \ dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \ { \ - siginfo_t info; \ - enum ctx_state prev_state; \ - \ - info.si_signo = signr; \ - info.si_errno = 0; \ - info.si_code = sicode; \ - info.si_addr = (void __user *)siaddr; \ - prev_state = exception_enter(); \ - if (notify_die(DIE_TRAP, str, regs, error_code, \ - trapnr, signr) == NOTIFY_STOP) { \ - exception_exit(prev_state); \ - return; \ - } \ - conditional_sti(regs); \ - do_trap(trapnr, signr, str, regs, error_code, &info); \ - exception_exit(prev_state); \ + do_error_trap(regs, error_code, str, trapnr, signr); \ } - DO_ERROR_INFO(X86_TRAP_DE, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->ip ) - DO_ERROR (X86_TRAP_OF, SIGSEGV, "overflow", overflow ) - DO_ERROR (X86_TRAP_BR, SIGSEGV, "bounds", bounds ) - DO_ERROR_INFO(X86_TRAP_UD, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip ) - DO_ERROR (X86_TRAP_OLD_MF, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun ) - DO_ERROR (X86_TRAP_TS, SIGSEGV, "invalid TSS", invalid_TSS ) - DO_ERROR (X86_TRAP_NP, SIGBUS, "segment not present", segment_not_present ) + DO_ERROR(X86_TRAP_DE, SIGFPE, "divide error", divide_error) + DO_ERROR(X86_TRAP_OF, SIGSEGV, "overflow", overflow) + DO_ERROR(X86_TRAP_BR, SIGSEGV, "bounds", bounds) + DO_ERROR(X86_TRAP_UD, SIGILL, "invalid opcode", invalid_op) + DO_ERROR(X86_TRAP_OLD_MF, SIGFPE, "coprocessor segment overrun",coprocessor_segment_overrun) + DO_ERROR(X86_TRAP_TS, SIGSEGV, "invalid TSS", invalid_TSS) + DO_ERROR(X86_TRAP_NP, SIGBUS, "segment not present", segment_not_present) #ifdef CONFIG_X86_32 - DO_ERROR (X86_TRAP_SS, SIGBUS, "stack segment", stack_segment ) + DO_ERROR(X86_TRAP_SS, SIGBUS, "stack segment", stack_segment) #endif - DO_ERROR_INFO(X86_TRAP_AC, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0 ) + DO_ERROR(X86_TRAP_AC, SIGBUS, "alignment check", alignment_check) #ifdef CONFIG_X86_64 /* Runs on IST stack */