X-Git-Url: https://git.kernelconcepts.de/?a=blobdiff_plain;f=arch%2Fmips%2Fkernel%2Ftraps.c;h=f9165d1a17bfbccec9d64a9a07148696fcf1784c;hb=10220c884444a1866bb070e207d84fc18188e2a7;hp=88185cd40c3b5eb04c1c6f2318df575f4db1400c;hpb=39b8d5254246ac56342b72f812255c8f7a74dca9;p=karo-tx-linux.git diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 88185cd40c3b..f9165d1a17bf 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -88,15 +88,17 @@ static void show_raw_backtrace(unsigned long reg29) #ifdef CONFIG_KALLSYMS printk("\n"); #endif -#define IS_KVA01(a) ((((unsigned int)a) & 0xc0000000) == 0x80000000) - if (IS_KVA01(sp)) { - while (!kstack_end(sp)) { - addr = *sp++; - if (__kernel_text_address(addr)) - print_ip_sym(addr); + while (!kstack_end(sp)) { + unsigned long __user *p = + (unsigned long __user *)(unsigned long)sp++; + if (__get_user(addr, p)) { + printk(" (Bad stack address)"); + break; } - printk("\n"); + if (__kernel_text_address(addr)) + print_ip_sym(addr); } + printk("\n"); } #ifdef CONFIG_KALLSYMS @@ -675,35 +677,24 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) force_sig_info(SIGFPE, &info, current); } -asmlinkage void do_bp(struct pt_regs *regs) +static void do_trap_or_bp(struct pt_regs *regs, unsigned int code, + const char *str) { - unsigned int opcode, bcode; siginfo_t info; - - if (__get_user(opcode, (unsigned int __user *) exception_epc(regs))) - goto out_sigsegv; - - /* - * There is the ancient bug in the MIPS assemblers that the break - * code starts left to bit 16 instead to bit 6 in the opcode. - * Gas is bug-compatible, but not always, grrr... - * We handle both cases with a simple heuristics. --macro - */ - bcode = ((opcode >> 6) & ((1 << 20) - 1)); - if (bcode < (1 << 10)) - bcode <<= 10; + char b[40]; /* - * (A short test says that IRIX 5.3 sends SIGTRAP for all break - * insns, even for break codes that indicate arithmetic failures. - * Weird ...) + * A short test says that IRIX 5.3 sends SIGTRAP for all trap + * insns, even for trap and break codes that indicate arithmetic + * failures. Weird ... * But should we continue the brokenness??? --macro */ - switch (bcode) { - case BRK_OVERFLOW << 10: - case BRK_DIVZERO << 10: - die_if_kernel("Break instruction in kernel code", regs); - if (bcode == (BRK_DIVZERO << 10)) + switch (code) { + case BRK_OVERFLOW: + case BRK_DIVZERO: + scnprintf(b, sizeof(b), "%s instruction in kernel code", str); + die_if_kernel(b, regs); + if (code == BRK_DIVZERO) info.si_code = FPE_INTDIV; else info.si_code = FPE_INTOVF; @@ -713,12 +704,34 @@ asmlinkage void do_bp(struct pt_regs *regs) force_sig_info(SIGFPE, &info, current); break; case BRK_BUG: - die("Kernel bug detected", regs); + die_if_kernel("Kernel bug detected", regs); + force_sig(SIGTRAP, current); break; default: - die_if_kernel("Break instruction in kernel code", regs); + scnprintf(b, sizeof(b), "%s instruction in kernel code", str); + die_if_kernel(b, regs); force_sig(SIGTRAP, current); } +} + +asmlinkage void do_bp(struct pt_regs *regs) +{ + unsigned int opcode, bcode; + + if (__get_user(opcode, (unsigned int __user *) exception_epc(regs))) + goto out_sigsegv; + + /* + * There is the ancient bug in the MIPS assemblers that the break + * code starts left to bit 16 instead to bit 6 in the opcode. + * Gas is bug-compatible, but not always, grrr... + * We handle both cases with a simple heuristics. --macro + */ + bcode = ((opcode >> 6) & ((1 << 20) - 1)); + if (bcode >= (1 << 10)) + bcode >>= 10; + + do_trap_or_bp(regs, bcode, "Break"); return; out_sigsegv: @@ -728,7 +741,6 @@ out_sigsegv: asmlinkage void do_tr(struct pt_regs *regs) { unsigned int opcode, tcode = 0; - siginfo_t info; if (__get_user(opcode, (unsigned int __user *) exception_epc(regs))) goto out_sigsegv; @@ -737,32 +749,7 @@ asmlinkage void do_tr(struct pt_regs *regs) if (!(opcode & OPCODE)) tcode = ((opcode >> 6) & ((1 << 10) - 1)); - /* - * (A short test says that IRIX 5.3 sends SIGTRAP for all trap - * insns, even for trap codes that indicate arithmetic failures. - * Weird ...) - * But should we continue the brokenness??? --macro - */ - switch (tcode) { - case BRK_OVERFLOW: - case BRK_DIVZERO: - die_if_kernel("Trap instruction in kernel code", regs); - if (tcode == BRK_DIVZERO) - info.si_code = FPE_INTDIV; - else - info.si_code = FPE_INTOVF; - info.si_signo = SIGFPE; - info.si_errno = 0; - info.si_addr = (void __user *) regs->cp0_epc; - force_sig_info(SIGFPE, &info, current); - break; - case BRK_BUG: - die("Kernel bug detected", regs); - break; - default: - die_if_kernel("Trap instruction in kernel code", regs); - force_sig(SIGTRAP, current); - } + do_trap_or_bp(regs, tcode, "Trap"); return; out_sigsegv: