patch-2.4.0-test12 linux/arch/arm/kernel/traps.c
Next file: linux/arch/arm/kernel/via82c505.c
Previous file: linux/arch/arm/kernel/oldlatches.c
Back to the patch index
Back to the overall index
- Lines: 267
- Date:
Sun Dec 3 17:48:19 2000
- Orig file:
v2.4.0-test11/linux/arch/arm/kernel/traps.c
- Orig date:
Sun Oct 8 10:50:05 2000
diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/kernel/traps.c linux/arch/arm/kernel/traps.c
@@ -31,6 +31,7 @@
#include "ptrace.h"
extern void c_backtrace (unsigned long fp, int pmode);
+extern void show_pte(struct mm_struct *mm, unsigned long addr);
const char *processor_modes[]=
{ "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" ,
@@ -41,12 +42,6 @@
static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
-static inline void console_verbose(void)
-{
- extern int console_loglevel;
- console_loglevel = 15;
-}
-
/*
* Stack pointers should always be within the kernels view of
* physical memory. If it is not there, then we can't dump
@@ -72,10 +67,14 @@
printk("%08lx: ", p);
for (i = 0; i < 8; i++, p += 4) {
+ unsigned int val;
+
if (p < bottom || p >= top)
printk(" ");
- else
- printk("%08lx ", *(unsigned long *)p);
+ else {
+ __get_user(val, (unsigned long *)p);
+ printk("%08x ", val);
+ }
if (i == 3)
printk(" ");
}
@@ -91,45 +90,57 @@
#define VMALLOC_OFFSET (8*1024*1024)
#define MODULE_RANGE (8*1024*1024)
-static void dump_instr(unsigned long pc, int user)
+static void dump_instr(struct pt_regs *regs)
{
- int pmin = -2, pmax = 3, ok = 0;
- extern char start_kernel, _etext;
+ unsigned long addr = instruction_pointer(regs);
+ const int thumb = thumb_mode(regs);
+ const int width = thumb ? 4 : 8;
+ int i;
- if (!user) {
- unsigned long module_start, module_end;
- unsigned long kernel_start, kernel_end;
-
- module_start = VMALLOC_START;
- module_end = module_start + MODULE_RANGE;
-
- kernel_start = (unsigned long)&start_kernel;
- kernel_end = (unsigned long)&_etext;
-
- if (pc >= kernel_start && pc < kernel_end) {
- if (pc + pmin < kernel_start)
- pmin = kernel_start - pc;
- if (pc + pmax > kernel_end)
- pmax = kernel_end - pc;
- ok = 1;
- } else if (pc >= module_start && pc < module_end) {
- if (pc + pmin < module_start)
- pmin = module_start - pc;
- if (pc + pmax > module_end)
- pmax = module_end - pc;
- ok = 1;
+ printk("Code: ");
+ for (i = -2; i < 3; i++) {
+ unsigned int val, bad;
+
+ if (thumb)
+ bad = __get_user(val, &((u16 *)addr)[i]);
+ else
+ bad = __get_user(val, &((u32 *)addr)[i]);
+
+ if (!bad)
+ printk(i == 0 ? "(%0*x) " : "%0*x", width, val);
+ else {
+ printk("bad PC value.");
+ break;
}
- } else
- ok = verify_area(VERIFY_READ, (void *)(pc + pmin), pmax - pmin) == 0;
+ }
+ printk("\n");
+}
- printk ("Code: ");
- if (ok) {
- int i;
- for (i = pmin; i < pmax; i++)
- printk(i == 0 ? "(%08lx) " : "%08lx ", ((unsigned long *)pc)[i]);
- printk ("\n");
- } else
- printk ("pc not in code space\n");
+static void dump_stack(struct task_struct *tsk, unsigned long sp)
+{
+ printk("Stack:\n");
+ dump_mem(sp - 16, 8192+(unsigned long)tsk);
+}
+
+static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
+{
+ unsigned int fp;
+ int ok = 1;
+
+ printk("Backtrace: ");
+ fp = regs->ARM_fp;
+ if (!fp) {
+ printk("no frame pointer");
+ ok = 0;
+ } else if (verify_stack(fp)) {
+ printk("invalid frame pointer %08lx", fp);
+ ok = 0;
+ } else if (fp < 4096+(unsigned long)tsk)
+ printk("frame pointer underflow");
+ printk("\n");
+
+ if (ok)
+ c_backtrace(fp, processor_mode(regs));
}
spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
@@ -141,9 +152,9 @@
{
struct task_struct *tsk = current;
+ console_verbose();
spin_lock_irq(&die_lock);
- console_verbose();
printk("Internal error: %s: %x\n", str, err);
printk("CPU: %d\n", smp_processor_id());
show_regs(regs);
@@ -151,39 +162,22 @@
current->comm, current->pid, 4096+(unsigned long)tsk);
if (!user_mode(regs)) {
- unsigned long sp = (unsigned long)(regs + 1);
- unsigned long fp;
- int dump_info = 1;
-
- printk("Stack: ");
- if (verify_stack(sp)) {
- printk("invalid kernel stack pointer %08lx", sp);
- dump_info = 0;
- } else if (sp < 4096+(unsigned long)tsk)
- printk("kernel stack pointer underflow");
- printk("\n");
-
- if (dump_info)
- dump_mem(sp - 16, 8192+(unsigned long)tsk);
-
- dump_info = 1;
-
- printk("Backtrace: ");
- fp = regs->ARM_fp;
- if (!fp) {
- printk("no frame pointer");
- dump_info = 0;
- } else if (verify_stack(fp)) {
- printk("invalid frame pointer %08lx", fp);
- dump_info = 0;
- } else if (fp < 4096+(unsigned long)tsk)
- printk("frame pointer underflow");
- printk("\n");
+ mm_segment_t fs;
- if (dump_info)
- c_backtrace(fp, processor_mode(regs));
+ /*
+ * We need to switch to kernel mode so that we can
+ * use __get_user to safely read from kernel space.
+ * Note that we now dump the code first, just in case
+ * the backtrace kills us.
+ */
+ fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ dump_instr(regs);
+ dump_stack(tsk, (unsigned long)(regs + 1));
+ dump_backtrace(regs, tsk);
- dump_instr(instruction_pointer(regs), 0);
+ set_fs(fs);
}
spin_unlock_irq(&die_lock);
@@ -206,6 +200,7 @@
#ifdef CONFIG_DEBUG_USER
printk(KERN_INFO "%s (%d): undefined instruction: pc=%08lx\n",
current->comm, current->pid, addr);
+ dump_instr(regs);
#endif
current->thread.error_code = 0;
@@ -228,6 +223,7 @@
#ifdef CONFIG_DEBUG_USER
printk(KERN_INFO "%s (%d): address exception: pc=%08lx\n",
current->comm, current->pid, instruction_pointer(regs));
+ dump_instr(regs);
#endif
current->thread.error_code = 0;
@@ -275,7 +271,7 @@
die("Oops", regs, 0);
cli();
- while(1);
+ panic("bad mode");
}
/*
@@ -332,6 +328,7 @@
* something catastrophic has happened
*/
printk("[%d] %s: arm syscall %d\n", current->pid, current->comm, no);
+ dump_instr(regs);
if (user_mode(regs)) {
show_regs(regs);
c_backtrace(regs->ARM_fp, processor_mode(regs));
@@ -359,8 +356,9 @@
}
#ifdef CONFIG_DEBUG_USER
- printk(KERN_ERR "[%d] %s: obsolete system call %08x.\n", current->pid,
- current->comm, n);
+ printk(KERN_ERR "[%d] %s: obsolete system call %08x.\n",
+ current->pid, current->comm, n);
+ dump_instr(regs);
#endif
force_sig(SIGILL, current);
die_if_kernel("Oops", regs, n);
@@ -384,21 +382,10 @@
siginfo_t info;
#ifdef CONFIG_DEBUG_USER
- dump_instr(addr, 1);
- {
- pgd_t *pgd;
-
- pgd = pgd_offset(current->mm, addr);
- printk ("*pgd = %08lx", pgd_val (*pgd));
- if (!pgd_none (*pgd)) {
- pmd_t *pmd;
- pmd = pmd_offset (pgd, addr);
- printk (", *pmd = %08lx", pmd_val (*pmd));
- if (!pmd_none (*pmd))
- printk (", *pte = %08lx", pte_val(*pte_offset (pmd, addr)));
- }
- printk ("\n");
- }
+ printk(KERN_ERR "[%d] %s: bad data abort: code %d instr 0x%08lx\n",
+ current->pid, current->comm, code, instr);
+ dump_instr(regs);
+ show_pte(current->mm, addr);
#endif
info.si_signo = SIGILL;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)