diff options
author | Michal Marek <mmarek@suse.cz> | 2010-10-12 09:09:06 -0400 |
---|---|---|
committer | Michal Marek <mmarek@suse.cz> | 2010-10-12 09:09:06 -0400 |
commit | 239060b93bb30a4ad55f1ecaa512464a035cc5ba (patch) | |
tree | 77f79810e57d4fc24356eca0cd6db463e8994128 /arch/mips/kernel/traps.c | |
parent | 1408b15b98635a13bad2e2a50b3c2ae2ccdf625b (diff) | |
parent | e9203c988234aa512bd45ca32b52e21c7bbfc414 (diff) |
Merge branch 'kbuild/rc-fixes' into kbuild/kconfig
We need to revert the temporary hack in 71ebc01, hence the merge.
Diffstat (limited to 'arch/mips/kernel/traps.c')
-rw-r--r-- | arch/mips/kernel/traps.c | 50 |
1 files changed, 35 insertions, 15 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 852780868fb4..03ec0019032b 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/ptrace.h> | 25 | #include <linux/ptrace.h> |
26 | #include <linux/kgdb.h> | 26 | #include <linux/kgdb.h> |
27 | #include <linux/kdebug.h> | 27 | #include <linux/kdebug.h> |
28 | #include <linux/kprobes.h> | ||
28 | #include <linux/notifier.h> | 29 | #include <linux/notifier.h> |
29 | #include <linux/kdb.h> | 30 | #include <linux/kdb.h> |
30 | 31 | ||
@@ -334,7 +335,7 @@ void show_regs(struct pt_regs *regs) | |||
334 | __show_regs((struct pt_regs *)regs); | 335 | __show_regs((struct pt_regs *)regs); |
335 | } | 336 | } |
336 | 337 | ||
337 | void show_registers(const struct pt_regs *regs) | 338 | void show_registers(struct pt_regs *regs) |
338 | { | 339 | { |
339 | const int field = 2 * sizeof(unsigned long); | 340 | const int field = 2 * sizeof(unsigned long); |
340 | 341 | ||
@@ -356,9 +357,14 @@ void show_registers(const struct pt_regs *regs) | |||
356 | printk("\n"); | 357 | printk("\n"); |
357 | } | 358 | } |
358 | 359 | ||
360 | static int regs_to_trapnr(struct pt_regs *regs) | ||
361 | { | ||
362 | return (regs->cp0_cause >> 2) & 0x1f; | ||
363 | } | ||
364 | |||
359 | static DEFINE_SPINLOCK(die_lock); | 365 | static DEFINE_SPINLOCK(die_lock); |
360 | 366 | ||
361 | void __noreturn die(const char * str, struct pt_regs * regs) | 367 | void __noreturn die(const char *str, struct pt_regs *regs) |
362 | { | 368 | { |
363 | static int die_counter; | 369 | static int die_counter; |
364 | int sig = SIGSEGV; | 370 | int sig = SIGSEGV; |
@@ -366,7 +372,7 @@ void __noreturn die(const char * str, struct pt_regs * regs) | |||
366 | unsigned long dvpret = dvpe(); | 372 | unsigned long dvpret = dvpe(); |
367 | #endif /* CONFIG_MIPS_MT_SMTC */ | 373 | #endif /* CONFIG_MIPS_MT_SMTC */ |
368 | 374 | ||
369 | notify_die(DIE_OOPS, str, (struct pt_regs *)regs, SIGSEGV, 0, 0); | 375 | notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs), SIGSEGV); |
370 | 376 | ||
371 | console_verbose(); | 377 | console_verbose(); |
372 | spin_lock_irq(&die_lock); | 378 | spin_lock_irq(&die_lock); |
@@ -375,7 +381,7 @@ void __noreturn die(const char * str, struct pt_regs * regs) | |||
375 | mips_mt_regdump(dvpret); | 381 | mips_mt_regdump(dvpret); |
376 | #endif /* CONFIG_MIPS_MT_SMTC */ | 382 | #endif /* CONFIG_MIPS_MT_SMTC */ |
377 | 383 | ||
378 | if (notify_die(DIE_OOPS, str, regs, 0, current->thread.trap_no, SIGSEGV) == NOTIFY_STOP) | 384 | if (notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs), SIGSEGV) == NOTIFY_STOP) |
379 | sig = 0; | 385 | sig = 0; |
380 | 386 | ||
381 | printk("%s[#%d]:\n", str, ++die_counter); | 387 | printk("%s[#%d]:\n", str, ++die_counter); |
@@ -449,7 +455,7 @@ asmlinkage void do_be(struct pt_regs *regs) | |||
449 | printk(KERN_ALERT "%s bus error, epc == %0*lx, ra == %0*lx\n", | 455 | printk(KERN_ALERT "%s bus error, epc == %0*lx, ra == %0*lx\n", |
450 | data ? "Data" : "Instruction", | 456 | data ? "Data" : "Instruction", |
451 | field, regs->cp0_epc, field, regs->regs[31]); | 457 | field, regs->cp0_epc, field, regs->regs[31]); |
452 | if (notify_die(DIE_OOPS, "bus error", regs, SIGBUS, 0, 0) | 458 | if (notify_die(DIE_OOPS, "bus error", regs, 0, regs_to_trapnr(regs), SIGBUS) |
453 | == NOTIFY_STOP) | 459 | == NOTIFY_STOP) |
454 | return; | 460 | return; |
455 | 461 | ||
@@ -650,7 +656,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) | |||
650 | { | 656 | { |
651 | siginfo_t info; | 657 | siginfo_t info; |
652 | 658 | ||
653 | if (notify_die(DIE_FP, "FP exception", regs, SIGFPE, 0, 0) | 659 | if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs), SIGFPE) |
654 | == NOTIFY_STOP) | 660 | == NOTIFY_STOP) |
655 | return; | 661 | return; |
656 | die_if_kernel("FP exception in kernel code", regs); | 662 | die_if_kernel("FP exception in kernel code", regs); |
@@ -713,11 +719,11 @@ static void do_trap_or_bp(struct pt_regs *regs, unsigned int code, | |||
713 | char b[40]; | 719 | char b[40]; |
714 | 720 | ||
715 | #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP | 721 | #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP |
716 | if (kgdb_ll_trap(DIE_TRAP, str, regs, code, 0, 0) == NOTIFY_STOP) | 722 | if (kgdb_ll_trap(DIE_TRAP, str, regs, code, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP) |
717 | return; | 723 | return; |
718 | #endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */ | 724 | #endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */ |
719 | 725 | ||
720 | if (notify_die(DIE_TRAP, str, regs, code, 0, 0) == NOTIFY_STOP) | 726 | if (notify_die(DIE_TRAP, str, regs, code, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP) |
721 | return; | 727 | return; |
722 | 728 | ||
723 | /* | 729 | /* |
@@ -783,6 +789,25 @@ asmlinkage void do_bp(struct pt_regs *regs) | |||
783 | if (bcode >= (1 << 10)) | 789 | if (bcode >= (1 << 10)) |
784 | bcode >>= 10; | 790 | bcode >>= 10; |
785 | 791 | ||
792 | /* | ||
793 | * notify the kprobe handlers, if instruction is likely to | ||
794 | * pertain to them. | ||
795 | */ | ||
796 | switch (bcode) { | ||
797 | case BRK_KPROBE_BP: | ||
798 | if (notify_die(DIE_BREAK, "debug", regs, bcode, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP) | ||
799 | return; | ||
800 | else | ||
801 | break; | ||
802 | case BRK_KPROBE_SSTEPBP: | ||
803 | if (notify_die(DIE_SSTEPBP, "single_step", regs, bcode, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP) | ||
804 | return; | ||
805 | else | ||
806 | break; | ||
807 | default: | ||
808 | break; | ||
809 | } | ||
810 | |||
786 | do_trap_or_bp(regs, bcode, "Break"); | 811 | do_trap_or_bp(regs, bcode, "Break"); |
787 | return; | 812 | return; |
788 | 813 | ||
@@ -815,7 +840,7 @@ asmlinkage void do_ri(struct pt_regs *regs) | |||
815 | unsigned int opcode = 0; | 840 | unsigned int opcode = 0; |
816 | int status = -1; | 841 | int status = -1; |
817 | 842 | ||
818 | if (notify_die(DIE_RI, "RI Fault", regs, SIGSEGV, 0, 0) | 843 | if (notify_die(DIE_RI, "RI Fault", regs, 0, regs_to_trapnr(regs), SIGILL) |
819 | == NOTIFY_STOP) | 844 | == NOTIFY_STOP) |
820 | return; | 845 | return; |
821 | 846 | ||
@@ -907,11 +932,6 @@ static int default_cu2_call(struct notifier_block *nfb, unsigned long action, | |||
907 | return NOTIFY_OK; | 932 | return NOTIFY_OK; |
908 | } | 933 | } |
909 | 934 | ||
910 | static struct notifier_block default_cu2_notifier = { | ||
911 | .notifier_call = default_cu2_call, | ||
912 | .priority = 0x80000000, /* Run last */ | ||
913 | }; | ||
914 | |||
915 | asmlinkage void do_cpu(struct pt_regs *regs) | 935 | asmlinkage void do_cpu(struct pt_regs *regs) |
916 | { | 936 | { |
917 | unsigned int __user *epc; | 937 | unsigned int __user *epc; |
@@ -1734,5 +1754,5 @@ void __init trap_init(void) | |||
1734 | 1754 | ||
1735 | sort_extable(__start___dbe_table, __stop___dbe_table); | 1755 | sort_extable(__start___dbe_table, __stop___dbe_table); |
1736 | 1756 | ||
1737 | register_cu2_notifier(&default_cu2_notifier); | 1757 | cu2_notifier(default_cu2_call, 0x80000000); /* Run last */ |
1738 | } | 1758 | } |