| .. | .. |
|---|
| 30 | 30 | #include <linux/init.h> |
|---|
| 31 | 31 | #include <linux/ptrace.h> |
|---|
| 32 | 32 | #include <linux/kallsyms.h> |
|---|
| 33 | +#include <linux/extable.h> |
|---|
| 33 | 34 | |
|---|
| 34 | 35 | #include <asm/setup.h> |
|---|
| 35 | 36 | #include <asm/fpu.h> |
|---|
| 36 | 37 | #include <linux/uaccess.h> |
|---|
| 37 | 38 | #include <asm/traps.h> |
|---|
| 38 | | -#include <asm/pgalloc.h> |
|---|
| 39 | 39 | #include <asm/machdep.h> |
|---|
| 40 | 40 | #include <asm/siginfo.h> |
|---|
| 41 | | - |
|---|
| 41 | +#include <asm/tlbflush.h> |
|---|
| 42 | 42 | |
|---|
| 43 | 43 | static const char *vec_names[] = { |
|---|
| 44 | 44 | [VEC_RESETSP] = "RESET SP", |
|---|
| .. | .. |
|---|
| 431 | 431 | pr_err("BAD KERNEL BUSERR\n"); |
|---|
| 432 | 432 | |
|---|
| 433 | 433 | die_if_kernel("Oops", &fp->ptregs,0); |
|---|
| 434 | | - force_sig(SIGKILL, current); |
|---|
| 434 | + force_sig(SIGKILL); |
|---|
| 435 | 435 | return; |
|---|
| 436 | 436 | } |
|---|
| 437 | 437 | } else { |
|---|
| .. | .. |
|---|
| 463 | 463 | !(ssw & RW) ? "write" : "read", addr, |
|---|
| 464 | 464 | fp->ptregs.pc); |
|---|
| 465 | 465 | die_if_kernel ("Oops", &fp->ptregs, buserr_type); |
|---|
| 466 | | - force_sig (SIGBUS, current); |
|---|
| 466 | + force_sig (SIGBUS); |
|---|
| 467 | 467 | return; |
|---|
| 468 | 468 | } |
|---|
| 469 | 469 | |
|---|
| .. | .. |
|---|
| 493 | 493 | do_page_fault (&fp->ptregs, addr, 0); |
|---|
| 494 | 494 | } else { |
|---|
| 495 | 495 | pr_debug("protection fault on insn access (segv).\n"); |
|---|
| 496 | | - force_sig (SIGSEGV, current); |
|---|
| 496 | + force_sig (SIGSEGV); |
|---|
| 497 | 497 | } |
|---|
| 498 | 498 | } |
|---|
| 499 | 499 | #else |
|---|
| .. | .. |
|---|
| 550 | 550 | errorcode |= 2; |
|---|
| 551 | 551 | |
|---|
| 552 | 552 | if (mmusr & (MMU_I | MMU_WP)) { |
|---|
| 553 | | - if (ssw & 4) { |
|---|
| 553 | + /* We might have an exception table for this PC */ |
|---|
| 554 | + if (ssw & 4 && !search_exception_tables(fp->ptregs.pc)) { |
|---|
| 554 | 555 | pr_err("Data %s fault at %#010lx in %s (pc=%#lx)\n", |
|---|
| 555 | 556 | ssw & RW ? "read" : "write", |
|---|
| 556 | 557 | fp->un.fmtb.daddr, |
|---|
| .. | .. |
|---|
| 571 | 572 | !(ssw & RW) ? "write" : "read", addr, |
|---|
| 572 | 573 | fp->ptregs.pc); |
|---|
| 573 | 574 | die_if_kernel("Oops",&fp->ptregs,mmusr); |
|---|
| 574 | | - force_sig(SIGSEGV, current); |
|---|
| 575 | + force_sig(SIGSEGV); |
|---|
| 575 | 576 | return; |
|---|
| 576 | 577 | } else { |
|---|
| 577 | 578 | #if 0 |
|---|
| .. | .. |
|---|
| 598 | 599 | #endif |
|---|
| 599 | 600 | pr_debug("Unknown SIGSEGV - 1\n"); |
|---|
| 600 | 601 | die_if_kernel("Oops",&fp->ptregs,mmusr); |
|---|
| 601 | | - force_sig(SIGSEGV, current); |
|---|
| 602 | + force_sig(SIGSEGV); |
|---|
| 602 | 603 | return; |
|---|
| 603 | 604 | } |
|---|
| 604 | 605 | |
|---|
| .. | .. |
|---|
| 621 | 622 | buserr: |
|---|
| 622 | 623 | pr_err("BAD KERNEL BUSERR\n"); |
|---|
| 623 | 624 | die_if_kernel("Oops",&fp->ptregs,0); |
|---|
| 624 | | - force_sig(SIGKILL, current); |
|---|
| 625 | + force_sig(SIGKILL); |
|---|
| 625 | 626 | return; |
|---|
| 626 | 627 | } |
|---|
| 627 | 628 | |
|---|
| .. | .. |
|---|
| 660 | 661 | addr, fp->ptregs.pc); |
|---|
| 661 | 662 | pr_debug("Unknown SIGSEGV - 2\n"); |
|---|
| 662 | 663 | die_if_kernel("Oops",&fp->ptregs,mmusr); |
|---|
| 663 | | - force_sig(SIGSEGV, current); |
|---|
| 664 | + force_sig(SIGSEGV); |
|---|
| 664 | 665 | return; |
|---|
| 665 | 666 | } |
|---|
| 666 | 667 | |
|---|
| .. | .. |
|---|
| 804 | 805 | default: |
|---|
| 805 | 806 | die_if_kernel("bad frame format",&fp->ptregs,0); |
|---|
| 806 | 807 | pr_debug("Unknown SIGSEGV - 4\n"); |
|---|
| 807 | | - force_sig(SIGSEGV, current); |
|---|
| 808 | + force_sig(SIGSEGV); |
|---|
| 808 | 809 | } |
|---|
| 809 | 810 | } |
|---|
| 810 | 811 | |
|---|
| 811 | 812 | |
|---|
| 812 | 813 | static int kstack_depth_to_print = 48; |
|---|
| 813 | 814 | |
|---|
| 814 | | -void show_trace(unsigned long *stack) |
|---|
| 815 | +static void show_trace(unsigned long *stack, const char *loglvl) |
|---|
| 815 | 816 | { |
|---|
| 816 | 817 | unsigned long *endstack; |
|---|
| 817 | 818 | unsigned long addr; |
|---|
| 818 | 819 | int i; |
|---|
| 819 | 820 | |
|---|
| 820 | | - pr_info("Call Trace:"); |
|---|
| 821 | + printk("%sCall Trace:", loglvl); |
|---|
| 821 | 822 | addr = (unsigned long)stack + THREAD_SIZE - 1; |
|---|
| 822 | 823 | endstack = (unsigned long *)(addr & -THREAD_SIZE); |
|---|
| 823 | 824 | i = 0; |
|---|
| .. | .. |
|---|
| 846 | 847 | void show_registers(struct pt_regs *regs) |
|---|
| 847 | 848 | { |
|---|
| 848 | 849 | struct frame *fp = (struct frame *)regs; |
|---|
| 849 | | - mm_segment_t old_fs = get_fs(); |
|---|
| 850 | 850 | u16 c, *cp; |
|---|
| 851 | 851 | unsigned long addr; |
|---|
| 852 | 852 | int i; |
|---|
| .. | .. |
|---|
| 916 | 916 | default: |
|---|
| 917 | 917 | pr_cont("\n"); |
|---|
| 918 | 918 | } |
|---|
| 919 | | - show_stack(NULL, (unsigned long *)addr); |
|---|
| 919 | + show_stack(NULL, (unsigned long *)addr, KERN_INFO); |
|---|
| 920 | 920 | |
|---|
| 921 | 921 | pr_info("Code:"); |
|---|
| 922 | | - set_fs(KERNEL_DS); |
|---|
| 923 | 922 | cp = (u16 *)regs->pc; |
|---|
| 924 | 923 | for (i = -8; i < 16; i++) { |
|---|
| 925 | | - if (get_user(c, cp + i) && i >= 0) { |
|---|
| 924 | + if (get_kernel_nofault(c, cp + i) && i >= 0) { |
|---|
| 926 | 925 | pr_cont(" Bad PC value."); |
|---|
| 927 | 926 | break; |
|---|
| 928 | 927 | } |
|---|
| .. | .. |
|---|
| 931 | 930 | else |
|---|
| 932 | 931 | pr_cont(" <%04x>", c); |
|---|
| 933 | 932 | } |
|---|
| 934 | | - set_fs(old_fs); |
|---|
| 935 | 933 | pr_cont("\n"); |
|---|
| 936 | 934 | } |
|---|
| 937 | 935 | |
|---|
| 938 | | -void show_stack(struct task_struct *task, unsigned long *stack) |
|---|
| 936 | +void show_stack(struct task_struct *task, unsigned long *stack, |
|---|
| 937 | + const char *loglvl) |
|---|
| 939 | 938 | { |
|---|
| 940 | 939 | unsigned long *p; |
|---|
| 941 | 940 | unsigned long *endstack; |
|---|
| .. | .. |
|---|
| 949 | 948 | } |
|---|
| 950 | 949 | endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE); |
|---|
| 951 | 950 | |
|---|
| 952 | | - pr_info("Stack from %08lx:", (unsigned long)stack); |
|---|
| 951 | + printk("%sStack from %08lx:", loglvl, (unsigned long)stack); |
|---|
| 953 | 952 | p = stack; |
|---|
| 954 | 953 | for (i = 0; i < kstack_depth_to_print; i++) { |
|---|
| 955 | 954 | if (p + 1 > endstack) |
|---|
| .. | .. |
|---|
| 959 | 958 | pr_cont(" %08lx", *p++); |
|---|
| 960 | 959 | } |
|---|
| 961 | 960 | pr_cont("\n"); |
|---|
| 962 | | - show_trace(stack); |
|---|
| 961 | + show_trace(stack, loglvl); |
|---|
| 963 | 962 | } |
|---|
| 964 | 963 | |
|---|
| 965 | 964 | /* |
|---|
| .. | .. |
|---|
| 1127 | 1126 | addr = (void __user*) fp->un.fmtb.daddr; |
|---|
| 1128 | 1127 | break; |
|---|
| 1129 | 1128 | } |
|---|
| 1130 | | - force_sig_fault(sig, si_code, addr, current); |
|---|
| 1129 | + force_sig_fault(sig, si_code, addr); |
|---|
| 1131 | 1130 | } |
|---|
| 1132 | 1131 | |
|---|
| 1133 | 1132 | void die_if_kernel (char *str, struct pt_regs *fp, int nr) |
|---|
| .. | .. |
|---|
| 1139 | 1138 | pr_crit("%s: %08x\n", str, nr); |
|---|
| 1140 | 1139 | show_registers(fp); |
|---|
| 1141 | 1140 | add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE); |
|---|
| 1142 | | - do_exit(SIGSEGV); |
|---|
| 1141 | + make_task_dead(SIGSEGV); |
|---|
| 1143 | 1142 | } |
|---|
| 1144 | 1143 | |
|---|
| 1145 | 1144 | asmlinkage void set_esp0(unsigned long ssp) |
|---|
| .. | .. |
|---|
| 1159 | 1158 | #ifdef CONFIG_M68KFPU_EMU |
|---|
| 1160 | 1159 | asmlinkage void fpemu_signal(int signal, int code, void *addr) |
|---|
| 1161 | 1160 | { |
|---|
| 1162 | | - force_sig_fault(signal, code, addr, current); |
|---|
| 1161 | + force_sig_fault(signal, code, addr); |
|---|
| 1163 | 1162 | } |
|---|
| 1164 | 1163 | #endif |
|---|