Commit 623b0355 authored by Haavard Skinnemoen's avatar Haavard Skinnemoen

[AVR32] Clean up exception handling code

  * Use generic BUG() handling
  * Remove some useless debug statements
  * Use a common function _exception() to send signals or oops when
    an exception can't be handled. This makes sure init doesn't
    enter an infinite exception loop as well. Borrowed from powerpc.
  * Add some basic exception tracing support to the page fault code.
  * Rework dump_stack(), show_regs() and friends and move everything
    into process.c
  * Print information about configuration options and chip type when
    oopsing
Signed-off-by: default avatarHaavard Skinnemoen <hskinnemoen@atmel.com>
parent 3b328c98
...@@ -68,6 +68,11 @@ config GENERIC_CALIBRATE_DELAY ...@@ -68,6 +68,11 @@ config GENERIC_CALIBRATE_DELAY
bool bool
default y default y
config GENERIC_BUG
bool
default y
depends on BUG
source "init/Kconfig" source "init/Kconfig"
menu "System Type and features" menu "System Type and features"
......
...@@ -12,10 +12,11 @@ ...@@ -12,10 +12,11 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#include <linux/moduleloader.h> #include <linux/bug.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/elf.h> #include <linux/elf.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleloader.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
void *module_alloc(unsigned long size) void *module_alloc(unsigned long size)
...@@ -315,10 +316,10 @@ int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, ...@@ -315,10 +316,10 @@ int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
vfree(module->arch.syminfo); vfree(module->arch.syminfo);
module->arch.syminfo = NULL; module->arch.syminfo = NULL;
return 0; return module_bug_finalize(hdr, sechdrs, module);
} }
void module_arch_cleanup(struct module *module) void module_arch_cleanup(struct module *module)
{ {
module_bug_cleanup(module);
} }
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/uaccess.h>
#include <linux/unistd.h> #include <linux/unistd.h>
#include <asm/sysreg.h> #include <asm/sysreg.h>
...@@ -115,39 +116,178 @@ void release_thread(struct task_struct *dead_task) ...@@ -115,39 +116,178 @@ void release_thread(struct task_struct *dead_task)
/* do nothing */ /* do nothing */
} }
static void dump_mem(const char *str, const char *log_lvl,
unsigned long bottom, unsigned long top)
{
unsigned long p;
int i;
printk("%s%s(0x%08lx to 0x%08lx)\n", log_lvl, str, bottom, top);
for (p = bottom & ~31; p < top; ) {
printk("%s%04lx: ", log_lvl, p & 0xffff);
for (i = 0; i < 8; i++, p += 4) {
unsigned int val;
if (p < bottom || p >= top)
printk(" ");
else {
if (__get_user(val, (unsigned int __user *)p)) {
printk("\n");
goto out;
}
printk("%08x ", val);
}
}
printk("\n");
}
out:
return;
}
static inline int valid_stack_ptr(struct thread_info *tinfo, unsigned long p)
{
return (p > (unsigned long)tinfo)
&& (p < (unsigned long)tinfo + THREAD_SIZE - 3);
}
#ifdef CONFIG_FRAME_POINTER
static void show_trace_log_lvl(struct task_struct *tsk, unsigned long *sp,
struct pt_regs *regs, const char *log_lvl)
{
unsigned long lr, fp;
struct thread_info *tinfo;
if (regs)
fp = regs->r7;
else if (tsk == current)
asm("mov %0, r7" : "=r"(fp));
else
fp = tsk->thread.cpu_context.r7;
/*
* Walk the stack as long as the frame pointer (a) is within
* the kernel stack of the task, and (b) it doesn't move
* downwards.
*/
tinfo = task_thread_info(tsk);
printk("%sCall trace:\n", log_lvl);
while (valid_stack_ptr(tinfo, fp)) {
unsigned long new_fp;
lr = *(unsigned long *)fp;
#ifdef CONFIG_KALLSYMS
printk("%s [<%08lx>] ", log_lvl, lr);
#else
printk(" [<%08lx>] ", lr);
#endif
print_symbol("%s\n", lr);
new_fp = *(unsigned long *)(fp + 4);
if (new_fp <= fp)
break;
fp = new_fp;
}
printk("\n");
}
#else
static void show_trace_log_lvl(struct task_struct *tsk, unsigned long *sp,
struct pt_regs *regs, const char *log_lvl)
{
unsigned long addr;
printk("%sCall trace:\n", log_lvl);
while (!kstack_end(sp)) {
addr = *sp++;
if (kernel_text_address(addr)) {
#ifdef CONFIG_KALLSYMS
printk("%s [<%08lx>] ", log_lvl, addr);
#else
printk(" [<%08lx>] ", addr);
#endif
print_symbol("%s\n", addr);
}
}
printk("\n");
}
#endif
void show_stack_log_lvl(struct task_struct *tsk, unsigned long sp,
struct pt_regs *regs, const char *log_lvl)
{
struct thread_info *tinfo;
if (sp == 0) {
if (tsk)
sp = tsk->thread.cpu_context.ksp;
else
sp = (unsigned long)&tinfo;
}
if (!tsk)
tsk = current;
tinfo = task_thread_info(tsk);
if (valid_stack_ptr(tinfo, sp)) {
dump_mem("Stack: ", log_lvl, sp,
THREAD_SIZE + (unsigned long)tinfo);
show_trace_log_lvl(tsk, (unsigned long *)sp, regs, log_lvl);
}
}
void show_stack(struct task_struct *tsk, unsigned long *stack)
{
show_stack_log_lvl(tsk, (unsigned long)stack, NULL, "");
}
void dump_stack(void)
{
unsigned long stack;
show_trace_log_lvl(current, &stack, NULL, "");
}
EXPORT_SYMBOL(dump_stack);
static const char *cpu_modes[] = { static const char *cpu_modes[] = {
"Application", "Supervisor", "Interrupt level 0", "Interrupt level 1", "Application", "Supervisor", "Interrupt level 0", "Interrupt level 1",
"Interrupt level 2", "Interrupt level 3", "Exception", "NMI" "Interrupt level 2", "Interrupt level 3", "Exception", "NMI"
}; };
void show_regs(struct pt_regs *regs) void show_regs_log_lvl(struct pt_regs *regs, const char *log_lvl)
{ {
unsigned long sp = regs->sp; unsigned long sp = regs->sp;
unsigned long lr = regs->lr; unsigned long lr = regs->lr;
unsigned long mode = (regs->sr & MODE_MASK) >> MODE_SHIFT; unsigned long mode = (regs->sr & MODE_MASK) >> MODE_SHIFT;
if (!user_mode(regs)) if (!user_mode(regs)) {
sp = (unsigned long)regs + FRAME_SIZE_FULL; sp = (unsigned long)regs + FRAME_SIZE_FULL;
printk("%s", log_lvl);
print_symbol("PC is at %s\n", instruction_pointer(regs)); print_symbol("PC is at %s\n", instruction_pointer(regs));
printk("%s", log_lvl);
print_symbol("LR is at %s\n", lr); print_symbol("LR is at %s\n", lr);
printk("pc : [<%08lx>] lr : [<%08lx>] %s\n" }
"sp : %08lx r12: %08lx r11: %08lx\n",
instruction_pointer(regs), printk("%spc : [<%08lx>] lr : [<%08lx>] %s\n"
lr, print_tainted(), sp, regs->r12, regs->r11); "%ssp : %08lx r12: %08lx r11: %08lx\n",
printk("r10: %08lx r9 : %08lx r8 : %08lx\n", log_lvl, instruction_pointer(regs), lr, print_tainted(),
regs->r10, regs->r9, regs->r8); log_lvl, sp, regs->r12, regs->r11);
printk("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n", printk("%sr10: %08lx r9 : %08lx r8 : %08lx\n",
regs->r7, regs->r6, regs->r5, regs->r4); log_lvl, regs->r10, regs->r9, regs->r8);
printk("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n", printk("%sr7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n",
regs->r3, regs->r2, regs->r1, regs->r0); log_lvl, regs->r7, regs->r6, regs->r5, regs->r4);
printk("Flags: %c%c%c%c%c\n", printk("%sr3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n",
log_lvl, regs->r3, regs->r2, regs->r1, regs->r0);
printk("%sFlags: %c%c%c%c%c\n", log_lvl,
regs->sr & SR_Q ? 'Q' : 'q', regs->sr & SR_Q ? 'Q' : 'q',
regs->sr & SR_V ? 'V' : 'v', regs->sr & SR_V ? 'V' : 'v',
regs->sr & SR_N ? 'N' : 'n', regs->sr & SR_N ? 'N' : 'n',
regs->sr & SR_Z ? 'Z' : 'z', regs->sr & SR_Z ? 'Z' : 'z',
regs->sr & SR_C ? 'C' : 'c'); regs->sr & SR_C ? 'C' : 'c');
printk("Mode bits: %c%c%c%c%c%c%c%c%c\n", printk("%sMode bits: %c%c%c%c%c%c%c%c%c\n", log_lvl,
regs->sr & SR_H ? 'H' : 'h', regs->sr & SR_H ? 'H' : 'h',
regs->sr & SR_R ? 'R' : 'r', regs->sr & SR_R ? 'R' : 'r',
regs->sr & SR_J ? 'J' : 'j', regs->sr & SR_J ? 'J' : 'j',
...@@ -157,9 +297,21 @@ void show_regs(struct pt_regs *regs) ...@@ -157,9 +297,21 @@ void show_regs(struct pt_regs *regs)
regs->sr & SR_I1M ? '1' : '.', regs->sr & SR_I1M ? '1' : '.',
regs->sr & SR_I0M ? '0' : '.', regs->sr & SR_I0M ? '0' : '.',
regs->sr & SR_GM ? 'G' : 'g'); regs->sr & SR_GM ? 'G' : 'g');
printk("CPU Mode: %s\n", cpu_modes[mode]); printk("%sCPU Mode: %s\n", log_lvl, cpu_modes[mode]);
printk("%sProcess: %s [%d] (task: %p thread: %p)\n",
log_lvl, current->comm, current->pid, current,
task_thread_info(current));
}
void show_regs(struct pt_regs *regs)
{
unsigned long sp = regs->sp;
if (!user_mode(regs))
sp = (unsigned long)regs + FRAME_SIZE_FULL;
show_trace(NULL, (unsigned long *)sp, regs); show_regs_log_lvl(regs, "");
show_trace_log_lvl(current, (unsigned long *)sp, regs, "");
} }
EXPORT_SYMBOL(show_regs); EXPORT_SYMBOL(show_regs);
......
This diff is collapsed.
...@@ -26,6 +26,12 @@ SECTIONS ...@@ -26,6 +26,12 @@ SECTIONS
_sinittext = .; _sinittext = .;
*(.text.reset) *(.text.reset)
*(.init.text) *(.init.text)
/*
* .exit.text is discarded at runtime, not
* link time, to deal with references from
* __bug_table
*/
*(.exit.text)
_einittext = .; _einittext = .;
. = ALIGN(4); . = ALIGN(4);
__tagtable_begin = .; __tagtable_begin = .;
...@@ -86,6 +92,8 @@ SECTIONS ...@@ -86,6 +92,8 @@ SECTIONS
__stop___ex_table = .; __stop___ex_table = .;
} }
BUG_TABLE
RODATA RODATA
. = ALIGN(8192); . = ALIGN(8192);
...@@ -126,7 +134,6 @@ SECTIONS ...@@ -126,7 +134,6 @@ SECTIONS
* thrown away, as cleanup code is never called unless it's a module. * thrown away, as cleanup code is never called unless it's a module.
*/ */
/DISCARD/ : { /DISCARD/ : {
*(.exit.text)
*(.exit.data) *(.exit.data)
*(.exitcall.exit) *(.exitcall.exit)
} }
......
...@@ -16,26 +16,8 @@ ...@@ -16,26 +16,8 @@
#include <asm/kdebug.h> #include <asm/kdebug.h>
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
#include <asm/sysreg.h> #include <asm/sysreg.h>
#include <asm/uaccess.h>
#include <asm/tlb.h> #include <asm/tlb.h>
#include <asm/uaccess.h>
#ifdef DEBUG
static void dump_code(unsigned long pc)
{
char *p = (char *)pc;
char val;
int i;
printk(KERN_DEBUG "Code:");
for (i = 0; i < 16; i++) {
if (__get_user(val, p + i))
break;
printk(" %02x", val);
}
printk("\n");
}
#endif
#ifdef CONFIG_KPROBES #ifdef CONFIG_KPROBES
ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
...@@ -68,17 +50,19 @@ static inline int notify_page_fault(enum die_val val, struct pt_regs *regs, ...@@ -68,17 +50,19 @@ static inline int notify_page_fault(enum die_val val, struct pt_regs *regs,
} }
#endif #endif
int exception_trace = 1;
/* /*
* This routine handles page faults. It determines the address and the * This routine handles page faults. It determines the address and the
* problem, and then passes it off to one of the appropriate routines. * problem, and then passes it off to one of the appropriate routines.
* *
* ecr is the Exception Cause Register. Possible values are: * ecr is the Exception Cause Register. Possible values are:
* 5: Page not found (instruction access)
* 6: Protection fault (instruction access) * 6: Protection fault (instruction access)
* 12: Page not found (read access) * 15: Protection fault (read access)
* 13: Page not found (write access) * 16: Protection fault (write access)
* 14: Protection fault (read access) * 20: Page not found (instruction access)
* 15: Protection fault (write access) * 24: Page not found (read access)
* 28: Page not found (write access)
*/ */
asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs) asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs)
{ {
...@@ -88,7 +72,9 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs) ...@@ -88,7 +72,9 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs)
const struct exception_table_entry *fixup; const struct exception_table_entry *fixup;
unsigned long address; unsigned long address;
unsigned long page; unsigned long page;
int writeaccess = 0; int writeaccess;
long signr;
int code;
if (notify_page_fault(DIE_PAGE_FAULT, regs, if (notify_page_fault(DIE_PAGE_FAULT, regs,
ecr, SIGSEGV) == NOTIFY_STOP) ecr, SIGSEGV) == NOTIFY_STOP)
...@@ -99,6 +85,9 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs) ...@@ -99,6 +85,9 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs)
tsk = current; tsk = current;
mm = tsk->mm; mm = tsk->mm;
signr = SIGSEGV;
code = SEGV_MAPERR;
/* /*
* If we're in an interrupt or have no user context, we must * If we're in an interrupt or have no user context, we must
* not take the fault... * not take the fault...
...@@ -125,7 +114,9 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs) ...@@ -125,7 +114,9 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs)
* can handle it... * can handle it...
*/ */
good_area: good_area:
//pr_debug("good area: vm_flags = 0x%lx\n", vma->vm_flags); code = SEGV_ACCERR;
writeaccess = 0;
switch (ecr) { switch (ecr) {
case ECR_PROTECTION_X: case ECR_PROTECTION_X:
case ECR_TLB_MISS_X: case ECR_TLB_MISS_X:
...@@ -176,46 +167,24 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs) ...@@ -176,46 +167,24 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs)
* map. Fix it, but check if it's kernel or user first... * map. Fix it, but check if it's kernel or user first...
*/ */
bad_area: bad_area:
pr_debug("Bad area [%s:%u]: addr %08lx, ecr %lu\n",
tsk->comm, tsk->pid, address, ecr);
up_read(&mm->mmap_sem); up_read(&mm->mmap_sem);
if (user_mode(regs)) { if (user_mode(regs)) {
/* Hmm...we have to pass address and ecr somehow... */ if (exception_trace)
/* tsk->thread.address = address; printk("%s%s[%d]: segfault at %08lx pc %08lx "
tsk->thread.error_code = ecr; */ "sp %08lx ecr %lu\n",
#ifdef DEBUG is_init(tsk) ? KERN_EMERG : KERN_INFO,
show_regs(regs); tsk->comm, tsk->pid, address, regs->pc,
dump_code(regs->pc); regs->sp, ecr);
_exception(SIGSEGV, regs, code, address);
page = sysreg_read(PTBR);
printk("ptbr = %08lx", page);
if (page) {
page = ((unsigned long *)page)[address >> 22];
printk(" pgd = %08lx", page);
if (page & _PAGE_PRESENT) {
page &= PAGE_MASK;
address &= 0x003ff000;
page = ((unsigned long *)__va(page))[address >> PAGE_SHIFT];
printk(" pte = %08lx\n", page);
}
}
#endif
pr_debug("Sending SIGSEGV to PID %d...\n",
tsk->pid);
force_sig(SIGSEGV, tsk);
return; return;
} }
no_context: no_context:
pr_debug("No context\n");
/* Are we prepared to handle this kernel fault? */ /* Are we prepared to handle this kernel fault? */
fixup = search_exception_tables(regs->pc); fixup = search_exception_tables(regs->pc);
if (fixup) { if (fixup) {
regs->pc = fixup->fixup; regs->pc = fixup->fixup;
pr_debug("Found fixup at %08lx\n", fixup->fixup);
return; return;
} }
...@@ -230,7 +199,6 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs) ...@@ -230,7 +199,6 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs)
printk(KERN_ALERT printk(KERN_ALERT
"Unable to handle kernel paging request"); "Unable to handle kernel paging request");
printk(" at virtual address %08lx\n", address); printk(" at virtual address %08lx\n", address);
printk(KERN_ALERT "pc = %08lx\n", regs->pc);
page = sysreg_read(PTBR); page = sysreg_read(PTBR);
printk(KERN_ALERT "ptbr = %08lx", page); printk(KERN_ALERT "ptbr = %08lx", page);
...@@ -241,20 +209,20 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs) ...@@ -241,20 +209,20 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs)
page &= PAGE_MASK; page &= PAGE_MASK;
address &= 0x003ff000; address &= 0x003ff000;
page = ((unsigned long *)__va(page))[address >> PAGE_SHIFT]; page = ((unsigned long *)__va(page))[address >> PAGE_SHIFT];
printk(" pte = %08lx\n", page); printk(" pte = %08lx", page);
} }
} }
die("\nOops", regs, ecr); printk("\n");
do_exit(SIGKILL); die("Kernel access of bad area", regs, signr);
return;
/* /*
* We ran out of memory, or some other thing happened to us * We ran out of memory, or some other thing happened to us
* that made us unable to handle the page fault gracefully. * that made us unable to handle the page fault gracefully.
*/ */
out_of_memory: out_of_memory:
printk("Out of memory\n");
up_read(&mm->mmap_sem); up_read(&mm->mmap_sem);
if (current->pid == 1) { if (is_init(current)) {
yield(); yield();
down_read(&mm->mmap_sem); down_read(&mm->mmap_sem);
goto survive; goto survive;
...@@ -267,21 +235,20 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs) ...@@ -267,21 +235,20 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs)
do_sigbus: do_sigbus:
up_read(&mm->mmap_sem); up_read(&mm->mmap_sem);
/*
* Send a sigbus, regardless of whether we were in kernel or
* user mode.
*/
/* address, error_code, trap_no, ... */
#ifdef DEBUG
show_regs(regs);
dump_code(regs->pc);
#endif
pr_debug("Sending SIGBUS to PID %d...\n", tsk->pid);
force_sig(SIGBUS, tsk);
/* Kernel mode? Handle exceptions or die */ /* Kernel mode? Handle exceptions or die */
signr = SIGBUS;
code = BUS_ADRERR;
if (!user_mode(regs)) if (!user_mode(regs))
goto no_context; goto no_context;
if (exception_trace)
printk("%s%s[%d]: bus error at %08lx pc %08lx "
"sp %08lx ecr %lu\n",
is_init(tsk) ? KERN_EMERG : KERN_INFO,
tsk->comm, tsk->pid, address, regs->pc,
regs->sp, ecr);
_exception(SIGBUS, regs, BUS_ADRERR, address);
} }
asmlinkage void do_bus_error(unsigned long addr, int write_access, asmlinkage void do_bus_error(unsigned long addr, int write_access,
...@@ -292,8 +259,7 @@ asmlinkage void do_bus_error(unsigned long addr, int write_access, ...@@ -292,8 +259,7 @@ asmlinkage void do_bus_error(unsigned long addr, int write_access,
addr, write_access ? "write" : "read"); addr, write_access ? "write" : "read");
printk(KERN_INFO "DTLB dump:\n"); printk(KERN_INFO "DTLB dump:\n");
dump_dtlb(); dump_dtlb();
die("Bus Error", regs, write_access); die("Bus Error", regs, SIGKILL);
do_exit(SIGKILL);
} }
/* /*
......
...@@ -18,27 +18,53 @@ ...@@ -18,27 +18,53 @@
#ifdef CONFIG_DEBUG_BUGVERBOSE #ifdef CONFIG_DEBUG_BUGVERBOSE
#define BUG() \ #define _BUG_OR_WARN(flags) \
do { \ asm volatile( \
asm volatile(".hword %0\n\t" \ "1: .hword %0\n" \
".hword %1\n\t" \ " .section __bug_table,\"a\",@progbits\n" \
".long %2" \ "2: .long 1b\n" \
" .long %1\n" \
" .short %2\n" \
" .short %3\n" \
" .org 2b + %4\n" \
" .previous" \
: \ : \
: "n"(AVR32_BUG_OPCODE), \ : "i"(AVR32_BUG_OPCODE), "i"(__FILE__), \
"i"(__LINE__), "X"(__FILE__)); \ "i"(__LINE__), "i"(flags), \
} while (0) "i"(sizeof(struct bug_entry)))
#else #else
#define _BUG_OR_WARN(flags) \
asm volatile( \
"1: .hword %0\n" \
" .section __bug_table,\"a\",@progbits\n" \
"2: .long 1b\n" \
" .short %1\n" \
" .org 2b + %2\n" \
" .previous" \
: \
: "i"(AVR32_BUG_OPCODE), "i"(flags), \
"i"(sizeof(struct bug_entry)))
#endif /* CONFIG_DEBUG_BUGVERBOSE */
#define BUG() \ #define BUG() \
do { \ do { \
asm volatile(".hword %0\n\t" \ _BUG_OR_WARN(0); \
: : "n"(AVR32_BUG_OPCODE)); \ for (;;); \
} while (0) } while (0)
#endif /* CONFIG_DEBUG_BUGVERBOSE */ #define WARN_ON(condition) \
({ \
typeof(condition) __ret_warn_on = (condition); \
if (unlikely(__ret_warn_on)) \
_BUG_OR_WARN(BUGFLAG_WARNING); \
unlikely(__ret_warn_on); \
})
#define HAVE_ARCH_BUG #define HAVE_ARCH_BUG
#define HAVE_ARCH_WARN_ON
#endif /* CONFIG_BUG */ #endif /* CONFIG_BUG */
......
...@@ -134,10 +134,10 @@ extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); ...@@ -134,10 +134,10 @@ extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
#define thread_saved_pc(tsk) ((tsk)->thread.cpu_context.pc) #define thread_saved_pc(tsk) ((tsk)->thread.cpu_context.pc)
struct pt_regs; struct pt_regs;
void show_trace(struct task_struct *task, unsigned long *stack,
struct pt_regs *regs);
extern unsigned long get_wchan(struct task_struct *p); extern unsigned long get_wchan(struct task_struct *p);
extern void show_regs_log_lvl(struct pt_regs *regs, const char *log_lvl);
extern void show_stack_log_lvl(struct task_struct *tsk, unsigned long sp,
struct pt_regs *regs, const char *log_lvl);
#define KSTK_EIP(tsk) ((tsk)->thread.cpu_context.pc) #define KSTK_EIP(tsk) ((tsk)->thread.cpu_context.pc)
#define KSTK_ESP(tsk) ((tsk)->thread.cpu_context.ksp) #define KSTK_ESP(tsk) ((tsk)->thread.cpu_context.ksp)
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#define __ASM_AVR32_SYSTEM_H #define __ASM_AVR32_SYSTEM_H
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/linkage.h>
#include <linux/types.h> #include <linux/types.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
...@@ -140,15 +141,9 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, ...@@ -140,15 +141,9 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
sizeof(*(ptr)))) sizeof(*(ptr))))
struct pt_regs; struct pt_regs;
extern void __die(const char *, struct pt_regs *, unsigned long, void NORET_TYPE die(const char *str, struct pt_regs *regs, long err);
const char *, const char *, unsigned long); void _exception(long signr, struct pt_regs *regs, int code,
extern void __die_if_kernel(const char *, struct pt_regs *, unsigned long, unsigned long addr);
const char *, const char *, unsigned long);
#define die(msg, regs, err) \
__die(msg, regs, err, __FILE__ ":", __FUNCTION__, __LINE__)
#define die_if_kernel(msg, regs, err) \
__die_if_kernel(msg, regs, err, __FILE__ ":", __FUNCTION__, __LINE__)
#define arch_align_stack(x) (x) #define arch_align_stack(x) (x)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment