1/* 2 * arch/v850/kernel/bug.c -- Bug reporting functions 3 * 4 * Copyright (C) 2001,02,03 NEC Electronics Corporation 5 * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org> 6 * 7 * This file is subject to the terms and conditions of the GNU General 8 * Public License. See the file COPYING in the main directory of this 9 * archive for more details. 10 * 11 * Written by Miles Bader <miles@gnu.org> 12 */ 13 14#include <linux/kernel.h> 15#include <linux/reboot.h> 16#include <linux/sched.h> 17#include <linux/module.h> 18 19#include <asm/errno.h> 20#include <asm/ptrace.h> 21#include <asm/processor.h> 22#include <asm/current.h> 23 24/* We should use __builtin_return_address, but it doesn't work in gcc-2.90 25 (which is currently our standard compiler on the v850). */ 26#define ret_addr() ({ register u32 lp asm ("lp"); lp; }) 27#define stack_addr() ({ register u32 sp asm ("sp"); sp; }) 28 29void __bug () 30{ 31 printk (KERN_CRIT "kernel BUG at PC 0x%x (SP ~0x%x)!\n", 32 ret_addr() - 4, /* - 4 for `jarl' */ 33 stack_addr()); 34 machine_halt (); 35} 36 37int bad_trap (int trap_num, struct pt_regs *regs) 38{ 39 printk (KERN_CRIT 40 "unimplemented trap %d called at 0x%08lx, pid %d!\n", 41 trap_num, regs->pc, current->pid); 42 return -ENOSYS; 43} 44 45#ifdef CONFIG_RESET_GUARD 46void unexpected_reset (unsigned long ret_addr, unsigned long kmode, 47 struct task_struct *task, unsigned long sp) 48{ 49 printk (KERN_CRIT 50 "unexpected reset in %s mode, pid %d" 51 " (ret_addr = 0x%lx, sp = 0x%lx)\n", 52 kmode ? "kernel" : "user", 53 task ? task->pid : -1, 54 ret_addr, sp); 55 56 machine_halt (); 57} 58#endif /* CONFIG_RESET_GUARD */ 59 60 61 62struct spec_reg_name { 63 const char *name; 64 int gpr; 65}; 66 67struct spec_reg_name spec_reg_names[] = { 68 { "sp", GPR_SP }, 69 { "gp", GPR_GP }, 70 { "tp", GPR_TP }, 71 { "ep", GPR_EP }, 72 { "lp", GPR_LP }, 73 { 0, 0 } 74}; 75 76void show_regs (struct pt_regs *regs) 77{ 78 int gpr_base, gpr_offs; 79 80 printk (" pc 0x%08lx psw 0x%08lx kernel_mode %d\n", 81 regs->pc, regs->psw, regs->kernel_mode); 82 printk (" ctpc 0x%08lx ctpsw 0x%08lx ctbp 0x%08lx\n", 83 regs->ctpc, regs->ctpsw, regs->ctbp); 84 85 for (gpr_base = 0; gpr_base < NUM_GPRS; gpr_base += 4) { 86 for (gpr_offs = 0; gpr_offs < 4; gpr_offs++) { 87 int gpr = gpr_base + gpr_offs; 88 long val = regs->gpr[gpr]; 89 struct spec_reg_name *srn; 90 91 for (srn = spec_reg_names; srn->name; srn++) 92 if (srn->gpr == gpr) 93 break; 94 95 if (srn->name) 96 printk ("%7s 0x%08lx", srn->name, val); 97 else 98 printk (" r%02d 0x%08lx", gpr, val); 99 } 100 101 printk ("\n"); 102 } 103} 104 105/* 106 * TASK is a pointer to the task whose backtrace we want to see (or NULL 107 * for current task), SP is the stack pointer of the first frame that 108 * should be shown in the back trace (or NULL if the entire call-chain of 109 * the task should be shown). 110 */ 111void show_stack (struct task_struct *task, unsigned long *sp) 112{ 113 unsigned long addr, end; 114 115 if (sp) 116 addr = (unsigned long)sp; 117 else if (task) 118 addr = task_sp (task); 119 else 120 addr = stack_addr (); 121 122 addr = addr & ~3; 123 end = (addr + THREAD_SIZE - 1) & THREAD_MASK; 124 125 while (addr < end) { 126 printk ("%8lX: ", addr); 127 while (addr < end) { 128 printk (" %8lX", *(unsigned long *)addr); 129 addr += sizeof (unsigned long); 130 if (! (addr & 0xF)) 131 break; 132 } 133 printk ("\n"); 134 } 135} 136 137void dump_stack () 138{ 139 show_stack (0, 0); 140} 141 142EXPORT_SYMBOL(dump_stack); 143