diff options
Diffstat (limited to 'arch/blackfin/kernel/traps.c')
-rw-r--r-- | arch/blackfin/kernel/traps.c | 115 |
1 files changed, 53 insertions, 62 deletions
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index bf2b2d1f8ae..6b7325d634a 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -1,30 +1,7 @@ /* - * File: arch/blackfin/kernel/traps.c - * Based on: - * Author: Hamish Macdonald + * Copyright 2004-2009 Analog Devices Inc. * - * Created: - * Description: uses S/W interrupt 15 for the system calls - * - * Modified: - * Copyright 2004-2006 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * Licensed under the GPL-2 or later */ #include <linux/bug.h> @@ -100,7 +77,11 @@ static void decode_address(char *buf, unsigned long address) char *modname; char *delim = ":"; char namebuf[128]; +#endif + buf += sprintf(buf, "<0x%08lx> ", address); + +#ifdef CONFIG_KALLSYMS /* look up the address and see if we are in kernel space */ symname = kallsyms_lookup(address, &symsize, &offset, &modname, namebuf); @@ -108,23 +89,33 @@ static void decode_address(char *buf, unsigned long address) /* yeah! kernel space! */ if (!modname) modname = delim = ""; - sprintf(buf, "<0x%p> { %s%s%s%s + 0x%lx }", - (void *)address, delim, modname, delim, symname, - (unsigned long)offset); + sprintf(buf, "{ %s%s%s%s + 0x%lx }", + delim, modname, delim, symname, + (unsigned long)offset); return; - } #endif - /* Problem in fixed code section? */ if (address >= FIXED_CODE_START && address < FIXED_CODE_END) { - sprintf(buf, "<0x%p> /* Maybe fixed code section */", (void *)address); + /* Problem in fixed code section? */ + strcat(buf, "/* Maybe fixed code section */"); + return; + + } else if (address < CONFIG_BOOT_LOAD) { + /* Problem somewhere before the kernel start address */ + strcat(buf, "/* Maybe null pointer? */"); + return; + + } else if (address >= COREMMR_BASE) { + strcat(buf, "/* core mmrs */"); return; - } - /* Problem somewhere before the kernel start address */ - if (address < CONFIG_BOOT_LOAD) { - sprintf(buf, "<0x%p> /* Maybe null pointer? */", (void *)address); + } else if (address >= SYSMMR_BASE) { + strcat(buf, "/* system mmrs */"); + return; + + } else if (address >= L1_ROM_START && address < L1_ROM_START + L1_ROM_LENGTH) { + strcat(buf, "/* on-chip L1 ROM */"); return; } @@ -172,18 +163,16 @@ static void decode_address(char *buf, unsigned long address) offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT); - sprintf(buf, "<0x%p> [ %s + 0x%lx ]", - (void *)address, name, offset); + sprintf(buf, "[ %s + 0x%lx ]", name, offset); } else - sprintf(buf, "<0x%p> [ %s vma:0x%lx-0x%lx]", - (void *)address, name, - vma->vm_start, vma->vm_end); + sprintf(buf, "[ %s vma:0x%lx-0x%lx]", + name, vma->vm_start, vma->vm_end); if (!in_atomic) mmput(mm); - if (!strlen(buf)) - sprintf(buf, "<0x%p> [ %s ] dynamic memory", (void *)address, name); + if (buf[0] == '\0') + sprintf(buf, "[ %s ] dynamic memory", name); goto done; } @@ -193,7 +182,7 @@ static void decode_address(char *buf, unsigned long address) } /* we were unable to find this address anywhere */ - sprintf(buf, "<0x%p> /* kernel dynamic memory */", (void *)address); + sprintf(buf, "/* kernel dynamic memory */"); done: write_unlock_irqrestore(&tasklist_lock, flags); @@ -215,14 +204,14 @@ asmlinkage void double_fault_c(struct pt_regs *fp) printk(KERN_EMERG "Double Fault\n"); #ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT if (((long)fp->seqstat & SEQSTAT_EXCAUSE) == VEC_UNCOV) { - unsigned int cpu = smp_processor_id(); + unsigned int cpu = raw_smp_processor_id(); char buf[150]; - decode_address(buf, cpu_pda[cpu].retx); + decode_address(buf, cpu_pda[cpu].retx_doublefault); printk(KERN_EMERG "While handling exception (EXCAUSE = 0x%x) at %s:\n", - (unsigned int)cpu_pda[cpu].seqstat & SEQSTAT_EXCAUSE, buf); - decode_address(buf, cpu_pda[cpu].dcplb_fault_addr); + (unsigned int)cpu_pda[cpu].seqstat_doublefault & SEQSTAT_EXCAUSE, buf); + decode_address(buf, cpu_pda[cpu].dcplb_doublefault_addr); printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %s\n", buf); - decode_address(buf, cpu_pda[cpu].icplb_fault_addr); + decode_address(buf, cpu_pda[cpu].icplb_doublefault_addr); printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %s\n", buf); decode_address(buf, fp->retx); @@ -245,13 +234,13 @@ static int kernel_mode_regs(struct pt_regs *regs) return regs->ipend & 0xffc0; } -asmlinkage void trap_c(struct pt_regs *fp) +asmlinkage notrace void trap_c(struct pt_regs *fp) { #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON int j; #endif #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO - unsigned int cpu = smp_processor_id(); + unsigned int cpu = raw_smp_processor_id(); #endif const char *strerror = NULL; int sig = 0; @@ -267,11 +256,6 @@ asmlinkage void trap_c(struct pt_regs *fp) * double faults if the stack has become corrupt */ -#ifndef CONFIG_KGDB - /* IPEND is skipped if KGDB isn't enabled (see entry code) */ - fp->ipend = bfin_read_IPEND(); -#endif - /* trap_c() will be called for exceptions. During exceptions * processing, the pc value should be set with retx value. * With this change we can cleanup some code in signal.c- TODO @@ -404,7 +388,7 @@ asmlinkage void trap_c(struct pt_regs *fp) /* 0x23 - Data CPLB protection violation, handled here */ case VEC_CPLB_VL: info.si_code = ILL_CPLB_VI; - sig = SIGBUS; + sig = SIGSEGV; strerror = KERN_NOTICE EXC_0x23(KERN_NOTICE); CHK_DEBUGGER_TRAP_MAYBE(); break; @@ -904,7 +888,7 @@ void show_stack(struct task_struct *task, unsigned long *stack) frame_no = 0; for (addr = (unsigned int *)((unsigned int)stack & ~0xF), i = 0; - addr <= endstack; addr++, i++) { + addr < endstack; addr++, i++) { ret_addr = 0; if (!j && i % 8 == 0) @@ -949,6 +933,7 @@ void show_stack(struct task_struct *task, unsigned long *stack) } #endif } +EXPORT_SYMBOL(show_stack); void dump_stack(void) { @@ -1090,7 +1075,7 @@ void show_regs(struct pt_regs *fp) struct irqaction *action; unsigned int i; unsigned long flags = 0; - unsigned int cpu = smp_processor_id(); + unsigned int cpu = raw_smp_processor_id(); unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic(); verbose_printk(KERN_NOTICE "\n"); @@ -1116,10 +1101,16 @@ void show_regs(struct pt_regs *fp) verbose_printk(KERN_NOTICE "%s", linux_banner); - verbose_printk(KERN_NOTICE "\nSEQUENCER STATUS:\t\t%s\n", - print_tainted()); - verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", - (long)fp->seqstat, fp->ipend, fp->syscfg); + verbose_printk(KERN_NOTICE "\nSEQUENCER STATUS:\t\t%s\n", print_tainted()); + verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx IMASK: %04lx SYSCFG: %04lx\n", + (long)fp->seqstat, fp->ipend, cpu_pda[raw_smp_processor_id()].ex_imask, fp->syscfg); + if (fp->ipend & EVT_IRPTEN) + verbose_printk(KERN_NOTICE " Global Interrupts Disabled (IPEND[4])\n"); + if (!(cpu_pda[raw_smp_processor_id()].ex_imask & (EVT_IVG13 | EVT_IVG12 | EVT_IVG11 | + EVT_IVG10 | EVT_IVG9 | EVT_IVG8 | EVT_IVG7 | EVT_IVTMR))) + verbose_printk(KERN_NOTICE " Peripheral interrupts masked off\n"); + if (!(cpu_pda[raw_smp_processor_id()].ex_imask & (EVT_IVG15 | EVT_IVG14))) + verbose_printk(KERN_NOTICE " Kernel interrupts masked off\n"); if ((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) { verbose_printk(KERN_NOTICE " HWERRCAUSE: 0x%lx\n", (fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14); |