patch-2.1.101 linux/arch/arm/kernel/traps.c

Next file: linux/arch/arm/lib/Makefile
Previous file: linux/arch/arm/kernel/sys_arm.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/traps.c linux/arch/arm/kernel/traps.c
@@ -49,7 +49,7 @@
 
 static int verify_stack_pointer (unsigned long stackptr, int size)
 {
-#if defined(CONFIG_CPU_ARM2) || defined(CONFIG_CPU_ARM3)
+#ifdef CONFIG_CPU_26
 	if (stackptr < 0x02048000 || stackptr + size > 0x03000000)
         	return -EFAULT;
 #else
@@ -90,38 +90,52 @@
 #define VMALLOC_OFFSET (8*1024*1024)
 #define MODULE_RANGE (8*1024*1024)
 
-static void dump_instr (unsigned long pc)
+static void dump_instr(unsigned long pc, int user)
 {
 	unsigned long module_start, module_end;
 	int pmin = -2, pmax = 3, ok = 0;
 	extern char start_kernel, _etext;
 
-	module_start = VMALLOC_START;
-	module_end   = module_start + MODULE_RANGE;
+	if (!user) {
+		module_start = VMALLOC_START;
+		module_end   = module_start + MODULE_RANGE;
+
+		if ((pc >= (unsigned long) &start_kernel) &&
+		    (pc <= (unsigned long) &_etext)) {
+			if (pc + pmin < (unsigned long) &start_kernel)
+				pmin = ((unsigned long) &start_kernel) - pc;
+			if (pc + pmax > (unsigned long) &_etext)
+				pmax = ((unsigned long) &_etext) - 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;
+		}
+	} else
+		ok = verify_area(VERIFY_READ, (void *)(pc + pmin), pmax - pmin) == 0;
 
-	if ((pc >= (unsigned long) &start_kernel) &&
-	    (pc <= (unsigned long) &_etext)) {
-		if (pc + pmin < (unsigned long) &start_kernel)
-			pmin = ((unsigned long) &start_kernel) - pc;
-		if (pc + pmax > (unsigned long) &_etext)
-			pmax = ((unsigned long) &_etext) - 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: ");
 	if (ok) {
 		int i;
 		for (i = pmin; i < pmax; i++)
-			printk("%08lx ", ((unsigned long *)pc)[i]);
+			printk(i == 0 ? "(%08lx) " : "%08lx ", ((unsigned long *)pc)[i]);
 		printk ("\n");
 	} else
 		printk ("pc not in code space\n");
-}	
+}
+
+static void dump_state(char *str, struct pt_regs *regs, int err)
+{
+	console_verbose();
+	printk("Internal error: %s: %x\n", str, err);
+	printk("CPU: %d\n", smp_processor_id());
+	show_regs(regs);
+	printk("Process %s (pid: %d, stackpage=%08lx)\n",
+		current->comm, current->pid, 4096+(unsigned long)current);
+}
 
 /*
  * This function is protected against kernel-mode re-entrancy.  If it
@@ -149,12 +163,7 @@
 		break;
 	}
 
-	console_verbose();
-	printk("Internal error: %s: %x\n", str, err);
-	printk("CPU: %d", smp_processor_id());
-	show_regs(regs);
-	printk("Process %s (pid: %d, stackpage=%08lx)\n",
-		current->comm, current->pid, 4096+(unsigned long)current);
+	dump_state(str, regs, err);
 
 	cstack = (unsigned long)(regs + 1);
 	sstack = 4096+(unsigned long)current;
@@ -180,7 +189,7 @@
 		}
 	}
 
-	dump_instr(instruction_pointer(regs));
+	dump_instr(instruction_pointer(regs), 0);
 	died = 0;
 	if (ret != -1)
 		do_exit (ret);
@@ -268,13 +277,13 @@
 {
 	switch (no) {
 	case 0: /* branch through 0 */
-		printk ("[%d] %s: branch through zero\n", current->pid, current->comm);
-		force_sig (SIGILL, current);
-		if (user_mode(regs)) {
-			show_regs (regs);
-			c_backtrace (regs->ARM_fp, processor_mode(regs));
-		}
-		die_if_kernel ("Oops", regs, 0, SIGILL);
+		force_sig(SIGSEGV, current);
+//		if (user_mode(regs)) {
+//			dump_state("branch through zero", regs, 0);
+//			if (regs->ARM_fp)
+//				c_backtrace (regs->ARM_fp, processor_mode(regs));
+//		}
+		die_if_kernel ("branch through zero", regs, 0, SIGSEGV);
 		break;
 
 	case 1: /* SWI_BREAK_POINT */
@@ -297,8 +306,7 @@
 
 asmlinkage void deferred(int n, struct pt_regs *regs)
 {
-	printk ("[%d] %s: old system call %X\n", current->pid, current->comm, n);
-	show_regs (regs);
+	dump_state("old system call", regs, 0);
 	force_sig (SIGILL, current);
 }
 
@@ -312,3 +320,37 @@
 	printk ("Invalid pointer size in %s (PC=%p) size %d\n",
 		function, __builtin_return_address(0), size);
 }
+
+#ifdef CONFIG_CPU_26
+asmlinkage void baddataabort(int code, unsigned long instr, struct pt_regs *regs)
+{
+	unsigned long phys, addr = instruction_pointer(regs);
+
+#ifdef CONFIG_DEBUG_ERRORS
+	printk("pid=%d\n", current->pid);
+
+	show_regs(regs);
+	dump_instr(instruction_pointer(regs), 1);
+	{
+		pgd_t *pgd;
+
+		printk ("current->tss.memmap = %08lX\n", current->tss.memmap);
+		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)) {
+				unsigned long ptr = pte_page(*pte_offset(pmd, addr));
+				printk (", *pte = %08lx", pte_val (*pte_offset (pmd, addr)));
+				phys = ptr + (addr & 0x7fff);
+			}
+		}
+		printk ("\n");
+	}
+#endif
+	panic("unknown data abort code %d [pc=%08lx *pc=%08lx lr=%08lx sp=%08lx]",
+		code, regs->ARM_pc, instr, regs->ARM_lr, regs->ARM_sp);
+}
+#endif

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov