X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=arch%2Fparisc%2Fkernel%2Ftraps.c;h=0ba1d3dbca2a83d00a8ff18f1b52f8e828c13af2;hb=7022672e4046fac4699aa5f8ff2a5213b7ec4ff9;hp=77b28cb8aca6f1cecab831f219308c787869e729;hpb=c0bc8721b8d0380ec69fa97578c91201201b05a9;p=linux-2.6 diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index 77b28cb8ac..0ba1d3dbca 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -16,15 +16,16 @@ #include #include #include +#include #include #include #include -#include #include #include #include #include #include +#include #include #include @@ -38,6 +39,8 @@ #include #include #include +#include +#include #include "../math-emu/math-emu.h" /* for handle_fpe() */ @@ -48,7 +51,7 @@ DEFINE_SPINLOCK(pa_dbit_lock); #endif -int printbinary(char *buf, unsigned long x, int nbits) +static int printbinary(char *buf, unsigned long x, int nbits) { unsigned long mask = 1UL << (nbits - 1); while (mask != 0) { @@ -60,7 +63,7 @@ int printbinary(char *buf, unsigned long x, int nbits) return nbits; } -#ifdef __LP64__ +#ifdef CONFIG_64BIT #define RFMT "%016lx" #else #define RFMT "%08lx" @@ -159,13 +162,13 @@ static void do_show_stack(struct unwind_frame_info *info) { int i = 1; - printk("Backtrace:\n"); + printk(KERN_CRIT "Backtrace:\n"); while (i <= 16) { if (unwind_once(info) < 0 || info->ip == 0) break; if (__kernel_text_address(info->ip)) { - printk(" [<" RFMT ">] ", info->ip); + printk("%s [<" RFMT ">] ", (i&0x3)==1 ? KERN_CRIT : "", info->ip); #ifdef CONFIG_KALLSYMS print_symbol("%s\n", info->ip); #else @@ -184,18 +187,19 @@ void show_stack(struct task_struct *task, unsigned long *s) if (!task) { unsigned long sp; - struct pt_regs *r; HERE: asm volatile ("copy %%r30, %0" : "=r"(sp)); - r = kzalloc(sizeof(struct pt_regs), GFP_KERNEL); - if (!r) - return; - r->iaoq[0] = (unsigned long)&&HERE; - r->gr[2] = (unsigned long)__builtin_return_address(0); - r->gr[30] = sp; - unwind_frame_init(&info, current, r); - kfree(r); + { + struct pt_regs r; + + memset(&r, 0, sizeof(struct pt_regs)); + r.iaoq[0] = (unsigned long)&&HERE; + r.gr[2] = (unsigned long)__builtin_return_address(0); + r.gr[30] = sp; + + unwind_frame_init(&info, current, &r); + } } else { unwind_frame_init_from_blocked_task(&info, task); } @@ -203,6 +207,11 @@ HERE: do_show_stack(&info); } +int is_valid_bugaddr(unsigned long iaoq) +{ + return 1; +} + void die_if_kernel(char *str, struct pt_regs *regs, long err) { if (user_mode(regs)) { @@ -221,15 +230,15 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err) oops_in_progress = 1; /* Amuse the user in a SPARC fashion */ - printk( -" _______________________________ \n" -" < Your System ate a SPARC! Gah! >\n" -" ------------------------------- \n" -" \\ ^__^\n" -" \\ (xx)\\_______\n" -" (__)\\ )\\/\\\n" -" U ||----w |\n" -" || ||\n"); + if (err) printk( +KERN_CRIT " _______________________________ \n" +KERN_CRIT " < Your System ate a SPARC! Gah! >\n" +KERN_CRIT " ------------------------------- \n" +KERN_CRIT " \\ ^__^\n" +KERN_CRIT " \\ (xx)\\_______\n" +KERN_CRIT " (__)\\ )\\/\\\n" +KERN_CRIT " U ||----w |\n" +KERN_CRIT " || ||\n"); /* unlock the pdc lock if necessary */ pdc_emergency_unlock(); @@ -241,9 +250,9 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err) if (!console_drivers) pdc_console_restart(); - printk(KERN_CRIT "%s (pid %d): %s (code %ld)\n", - current->comm, current->pid, str, err); - show_regs(regs); + if (err) + printk(KERN_CRIT "%s (pid %d): %s (code %ld)\n", + current->comm, current->pid, str, err); /* Wot's wrong wif bein' racy? */ if (current->thread.flags & PARISC_KERNEL_DEATH) { @@ -251,8 +260,20 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err) local_irq_enable(); while (1); } - current->thread.flags |= PARISC_KERNEL_DEATH; + + show_regs(regs); + dump_stack(); + + if (in_interrupt()) + panic("Fatal exception in interrupt"); + + if (panic_on_oops) { + printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n"); + ssleep(5); + panic("Fatal exception"); + } + do_exit(SIGSEGV); } @@ -263,61 +284,45 @@ int syscall_ipi(int (*syscall) (struct pt_regs *), struct pt_regs *regs) /* gdb uses break 4,8 */ #define GDB_BREAK_INSN 0x10004 -void handle_gdb_break(struct pt_regs *regs, int wot) +static void handle_gdb_break(struct pt_regs *regs, int wot) { struct siginfo si; - si.si_code = wot; - si.si_addr = (void __user *) (regs->iaoq[0] & ~3); si.si_signo = SIGTRAP; si.si_errno = 0; + si.si_code = wot; + si.si_addr = (void __user *) (regs->iaoq[0] & ~3); force_sig_info(SIGTRAP, &si, current); } -void handle_break(unsigned iir, struct pt_regs *regs) +static void handle_break(struct pt_regs *regs) { - struct siginfo si; - - switch(iir) { - case 0x00: -#ifdef PRINT_USER_FAULTS - printk(KERN_DEBUG "break 0,0: pid=%d command='%s'\n", - current->pid, current->comm); -#endif - die_if_kernel("Breakpoint", regs, 0); -#ifdef PRINT_USER_FAULTS - show_regs(regs); -#endif - si.si_code = TRAP_BRKPT; - si.si_addr = (void __user *) (regs->iaoq[0] & ~3); - si.si_signo = SIGTRAP; - force_sig_info(SIGTRAP, &si, current); - break; - - case GDB_BREAK_INSN: - die_if_kernel("Breakpoint", regs, 0); - handle_gdb_break(regs, TRAP_BRKPT); - break; + unsigned iir = regs->iir; + + if (unlikely(iir == PARISC_BUG_BREAK_INSN && !user_mode(regs))) { + /* check if a BUG() or WARN() trapped here. */ + enum bug_trap_type tt; + tt = report_bug(regs->iaoq[0] & ~3); + if (tt == BUG_TRAP_TYPE_WARN) { + regs->iaoq[0] += 4; + regs->iaoq[1] += 4; + return; /* return to next instruction when WARN_ON(). */ + } + die_if_kernel("Unknown kernel breakpoint", regs, + (tt == BUG_TRAP_TYPE_NONE) ? 9 : 0); + } - default: #ifdef PRINT_USER_FAULTS - printk(KERN_DEBUG "break %#08x: pid=%d command='%s'\n", - iir, current->pid, current->comm); + if (unlikely(iir != GDB_BREAK_INSN)) { + printk(KERN_DEBUG "break %d,%d: pid=%d command='%s'\n", + iir & 31, (iir>>13) & ((1<<13)-1), + current->pid, current->comm); show_regs(regs); -#endif - si.si_signo = SIGTRAP; - si.si_code = TRAP_BRKPT; - si.si_addr = (void __user *) (regs->iaoq[0] & ~3); - force_sig_info(SIGTRAP, &si, current); - return; } -} - +#endif -int handle_toc(void) -{ - printk(KERN_CRIT "TOC call.\n"); - return 0; + /* send standard GDB signal */ + handle_gdb_break(regs, TRAP_BRKPT); } static void default_trap(int code, struct pt_regs *regs) @@ -326,7 +331,7 @@ static void default_trap(int code, struct pt_regs *regs) show_regs(regs); } -void (*cpu_lpmc) (int code, struct pt_regs *regs) = default_trap; +void (*cpu_lpmc) (int code, struct pt_regs *regs) __read_mostly = default_trap; void transfer_pim_to_trap_frame(struct pt_regs *regs) @@ -544,7 +549,8 @@ void handle_interruption(int code, struct pt_regs *regs) /* Low-priority machine check */ pdc_chassis_send_status(PDC_CHASSIS_DIRECT_LPMC); - flush_all_caches(); + flush_cache_all(); + flush_tlb_all(); cpu_lpmc(5, regs); return; @@ -562,7 +568,7 @@ void handle_interruption(int code, struct pt_regs *regs) case 9: /* Break instruction trap */ - handle_break(regs->iir,regs); + handle_break(regs); return; case 10: @@ -609,7 +615,7 @@ void handle_interruption(int code, struct pt_regs *regs) case 13: /* Conditional Trap - The condition succees in an instruction which traps + The condition succeeds in an instruction which traps on condition */ if(user_mode(regs)){ si.si_signo = SIGFPE; @@ -830,7 +836,7 @@ int __init check_ivt(void *iva) return 0; } -#ifndef __LP64__ +#ifndef CONFIG_64BIT extern const void fault_vector_11; #endif extern const void fault_vector_20; @@ -842,7 +848,7 @@ void __init trap_init(void) if (boot_cpu_data.cpu_type >= pcxu) iva = (void *) &fault_vector_20; else -#ifdef __LP64__ +#ifdef CONFIG_64BIT panic("Can't boot 64-bit OS on PA1.1 processor!"); #else iva = (void *) &fault_vector_11;