patch-2.3.40 linux/arch/arm/mm/fault-armv.c
Next file: linux/arch/arm/mm/fault-common.c
Previous file: linux/arch/arm/lib/uaccess.S
Back to the patch index
Back to the overall index
- Lines: 227
- Date:
Thu Jan 13 13:30:31 2000
- Orig file:
v2.3.39/linux/arch/arm/mm/fault-armv.c
- Orig date:
Mon Nov 1 13:56:26 1999
diff -u --recursive --new-file v2.3.39/linux/arch/arm/mm/fault-armv.c linux/arch/arm/mm/fault-armv.c
@@ -29,6 +29,8 @@
#define DO_COW(m) (!((m) & FAULT_CODE_READ))
#define READ_FAULT(m) ((m) & FAULT_CODE_READ)
+extern void die_if_kernel(const char *str, struct pt_regs *regs, int err);
+
#include "fault-common.c"
#ifdef DEBUG
@@ -118,17 +120,18 @@
* This needs to be done after sysctl_init, otherwise sys/
* will be overwritten.
*/
-void __init alignment_init(void)
+static int __init alignment_init(void)
{
create_proc_read_entry("sys/debug/alignment", 0, NULL,
- proc_alignment_read);
+ proc_alignment_read, NULL);
+ return 0;
}
__initcall(alignment_init);
#endif /* CONFIG_SYSCTL */
static int
-do_alignment_exception(struct pt_regs *regs)
+do_alignment(unsigned long addr, int error_code, struct pt_regs *regs)
{
unsigned int instr, rd, rn, correction, nr_regs, regbits;
unsigned long eaddr;
@@ -308,116 +311,99 @@
return 0;
}
+#else
+
+#define do_alignment NULL
+
#endif
-#define BUG_PROC_MSG \
- "Buggy processor (%08X), trying to continue.\n" \
- "Please read http://www.arm.linux.org.uk/state.html for more information"
+#ifdef CONFIG_DEBUG_USER
-asmlinkage void
-do_DataAbort(unsigned long addr, int fsr, int error_code, struct pt_regs *regs)
+static int
+do_sect_fault(unsigned long addr, int error_code, struct pt_regs *regs)
{
if (user_mode(regs)) {
- if (addr == regs->ARM_pc) {
- static int first = 1;
- if (first) {
- /*
- * I want statistical information on this problem!
- */
- printk(KERN_ERR BUG_PROC_MSG, fsr);
- first = 0;
+ printk("%s: permission fault on section, "
+ "address=0x%08lx, code %d\n",
+ current->comm, addr, error_code);
+#ifdef DEBUG
+ {
+ unsigned int i, j;
+ unsigned long *sp;
+
+ sp = (unsigned long *) (regs->ARM_sp - 128);
+ for (j = 0; j < 20 && sp_valid(sp); j++) {
+ printk("%p: ", sp);
+ for (i = 0; i < 8 && sp_valid(sp); i += 1, sp++)
+ printk("%08lx ", *sp);
+ printk("\n");
}
- return;
+ show_regs(regs);
+ c_backtrace(regs->ARM_fp, regs->ARM_cpsr);
}
+#endif
}
+ return 1; /* not fixed up */
+}
+#else
-#define DIE(signr,nam)\
- force_sig(signr, current);\
- die(nam, regs, fsr);\
- do_exit(signr);\
- break
-
- switch (fsr & 15) {
- /*
- * 0 - vector exception
- */
- case 0:
- force_sig(SIGSEGV, current);
- if (!user_mode(regs)) {
- die("vector exception", regs, fsr);
- do_exit(SIGSEGV);
- }
- break;
+#define do_sect_fault NULL
- /*
- * 15 - permission fault on page
- * 5 - page-table entry descriptor fault
- * 7 - first-level descriptor fault
- */
- case 15: case 5: case 7:
- do_page_fault(addr, error_code, regs);
- break;
-
- /*
- * 13 - permission fault on section
- */
- case 13:
- force_sig(SIGSEGV, current);
- if (!user_mode(regs)) {
- die("section permission fault", regs, fsr);
- do_exit(SIGSEGV);
- } else {
-#ifdef CONFIG_DEBUG_USER
- printk("%s: permission fault on section, "
- "address=0x%08lx, code %d\n",
- current->comm, addr, error_code);
-#ifdef DEBUG
- {
- unsigned int i, j;
- unsigned long *sp;
-
- sp = (unsigned long *) (regs->ARM_sp - 128);
- for (j = 0; j < 20 && sp_valid(sp); j++) {
- printk("%p: ", sp);
- for (i = 0; i < 8 && sp_valid(sp); i += 1, sp++)
- printk("%08lx ", *sp);
- printk("\n");
- }
- show_regs(regs);
- c_backtrace(regs->ARM_fp, regs->ARM_cpsr);
- }
-#endif
#endif
+
+static struct fsr_info {
+ int (*fn)(unsigned long addr, int error_code, struct pt_regs *regs);
+ int sig;
+ char *name;
+} fsr_info[] = {
+ { NULL, SIGSEGV, "vector exception" },
+ { do_alignment, SIGBUS, "alignment exception" },
+ { NULL, SIGKILL, "terminal exception" },
+ { do_alignment, SIGBUS, "alignment exception" },
+ { NULL, SIGBUS, "external abort on linefetch" },
+ { do_page_fault, SIGSEGV, "page fault" },
+ { NULL, SIGBUS, "external abort on linefetch" },
+ { do_page_fault, SIGSEGV, "page fault" },
+ { NULL, SIGBUS, "external abort on non-linefetch" },
+ { NULL, SIGSEGV, "domain fault" },
+ { NULL, SIGBUS, "external abort on non-linefetch" },
+ { NULL, SIGSEGV, "domain fault" },
+ { NULL, SIGBUS, "external abort on translation" },
+ { do_sect_fault, SIGSEGV, "section permission fault" },
+ { NULL, SIGBUS, "external abort on translation" },
+ { do_page_fault, SIGSEGV, "page permission fault" }
+};
+
+/*
+ * Currently dropped down to debug level
+ */
+#define BUG_PROC_MSG \
+ KERN_DEBUG "Weird data abort (%08X).\n" \
+ KERN_DEBUG "Please see http://www.arm.linux.org.uk/state.html for more information"
+
+asmlinkage void
+do_DataAbort(unsigned long addr, int fsr, int error_code, struct pt_regs *regs)
+{
+ struct fsr_info *inf;
+
+ if (user_mode(regs) && addr == regs->ARM_pc) {
+ static int first = 1;
+ if (first) {
+ /*
+ * I want statistical information on this problem,
+ * but we don't want to hastle the users too much.
+ */
+ printk(BUG_PROC_MSG, fsr);
+ first = 0;
}
- break;
+ return;
+ }
- case 1:
- case 3:
-#ifdef CONFIG_ALIGNMENT_TRAP
- if (!do_alignment_exception(regs))
- break;
-#endif
- /*
- * this should never happen
- */
- DIE(SIGBUS, "Alignment exception");
- break;
+ inf = fsr_info + (fsr & 15);
- case 2:
- DIE(SIGKILL, "Terminal exception");
- case 12:
- case 14:
- DIE(SIGBUS, "External abort on translation");
- case 9:
- case 11:
- DIE(SIGSEGV, "Domain fault");
-
- case 4:
- case 6:
- DIE(SIGBUS, "External abort on linefetch");
- case 8:
- case 10:
- DIE(SIGBUS, "External abort on non-linefetch");
+ if (!inf->fn || inf->fn(addr, error_code, regs)) {
+ force_sig(inf->sig, current);
+ die_if_kernel(inf->name, regs, fsr);
}
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)