summaryrefslogtreecommitdiff
path: root/arch/arm/mm/alignment.c
diff options
context:
space:
mode:
authorRussell King <rmk@flint.arm.linux.org.uk>2002-06-05 14:57:54 +0100
committerRussell King <rmk@flint.arm.linux.org.uk>2002-06-05 14:57:54 +0100
commit75fb1f976e7b45a585ecdb214a6027e271a44dbf (patch)
tree3ce1cc765fcda2f76660917c60842b0b74ae4d99 /arch/arm/mm/alignment.c
parentea1e2d6259e83d6fae83473f7b90a683ec770322 (diff)
[ARM] Generic hook for page faults
Provide a method where various other parts of the kernel (eg, alignment fault handler, PCI subsystems, etc) can hook into the page fault processing to handle alignment and PCI faults respectively.
Diffstat (limited to 'arch/arm/mm/alignment.c')
-rw-r--r--arch/arm/mm/alignment.c69
1 files changed, 37 insertions, 32 deletions
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index 0e76c39dc3f5..0b678b1d7fdd 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -30,9 +30,7 @@
#include <asm/pgtable.h>
#include <asm/unaligned.h>
-extern void
-do_bad_area(struct task_struct *tsk, struct mm_struct *mm, unsigned long addr,
- int error_code, struct pt_regs *regs);
+#include "fault.h"
/*
* 32-bit misaligned trap handler (c) 1998 San Mehat (CCC) -July 1998
@@ -130,31 +128,6 @@ static int proc_alignment_write(struct file *file, const char *buffer,
return count;
}
-/*
- * This needs to be done after sysctl_init, otherwise sys/ will be
- * overwritten. Actually, this shouldn't be in sys/ at all since
- * it isn't a sysctl, and it doesn't contain sysctl information.
- * We now locate it in /proc/cpu/alignment instead.
- */
-static int __init alignment_init(void)
-{
- struct proc_dir_entry *res;
-
- res = proc_mkdir("cpu", NULL);
- if (!res)
- return -ENOMEM;
-
- res = create_proc_entry("alignment", S_IWUSR | S_IRUGO, res);
- if (!res)
- return -ENOMEM;
-
- res->read_proc = proc_alignment_read;
- res->write_proc = proc_alignment_write;
-
- return 0;
-}
-
-__initcall(alignment_init);
#endif /* CONFIG_PROC_FS */
union offset_union {
@@ -486,7 +459,8 @@ bad:
return TYPE_ERROR;
}
-int do_alignment(unsigned long addr, int error_code, struct pt_regs *regs)
+static int
+do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
{
union offset_union offset;
unsigned long instr, instrptr;
@@ -577,7 +551,7 @@ int do_alignment(unsigned long addr, int error_code, struct pt_regs *regs)
/*
* We got a fault - fix it up, or die.
*/
- do_bad_area(current, current->mm, addr, error_code, regs);
+ do_bad_area(current, current->mm, addr, fsr, regs);
return 0;
bad:
@@ -594,8 +568,8 @@ int do_alignment(unsigned long addr, int error_code, struct pt_regs *regs)
if (ai_usermode & 1)
printk("Alignment trap: %s (%d) PC=0x%08lx Instr=0x%08lx "
- "Address=0x%08lx Code 0x%02x\n", current->comm,
- current->pid, instrptr, instr, addr, error_code);
+ "Address=0x%08lx FSR 0x%03x\n", current->comm,
+ current->pid, instrptr, instr, addr, fsr);
if (ai_usermode & 2)
goto fixup;
@@ -607,3 +581,34 @@ int do_alignment(unsigned long addr, int error_code, struct pt_regs *regs)
return 0;
}
+
+/*
+ * This needs to be done after sysctl_init, otherwise sys/ will be
+ * overwritten. Actually, this shouldn't be in sys/ at all since
+ * it isn't a sysctl, and it doesn't contain sysctl information.
+ * We now locate it in /proc/cpu/alignment instead.
+ */
+static int __init alignment_init(void)
+{
+#ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *res;
+
+ res = proc_mkdir("cpu", NULL);
+ if (!res)
+ return -ENOMEM;
+
+ res = create_proc_entry("alignment", S_IWUSR | S_IRUGO, res);
+ if (!res)
+ return -ENOMEM;
+
+ res->read_proc = proc_alignment_read;
+ res->write_proc = proc_alignment_write;
+#endif
+
+ hook_fault_code(1, do_alignment, SIGILL, "alignment exception");
+ hook_fault_code(3, do_alignment, SIGILL, "alignment exception");
+
+ return 0;
+}
+
+__initcall(alignment_init);