patch-1.3.94 linux/arch/m68k/mm/fault.c
Next file: linux/arch/m68k/mm/init.c
Previous file: linux/arch/m68k/mm/Makefile
Back to the patch index
Back to the overall index
- Lines: 114
- Date:
Thu Apr 18 02:59:59 1996
- Orig file:
v1.3.93/linux/arch/m68k/mm/fault.c
- Orig date:
Thu Jan 1 02:00:00 1970
diff -u --recursive --new-file v1.3.93/linux/arch/m68k/mm/fault.c linux/arch/m68k/mm/fault.c
@@ -0,0 +1,113 @@
+/*
+ * linux/arch/m68k/mm/fault.c
+ *
+ * Copyright (C) 1995 Hamish Macdonald
+ */
+
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/ptrace.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+
+extern void die_if_kernel(char *, struct pt_regs *, long);
+
+/*
+ * This routine handles page faults. It determines the problem, and
+ * then passes it off to one of the appropriate routines.
+ *
+ * error_code:
+ * bit 0 == 0 means no page found, 1 means protection fault
+ * bit 1 == 0 means read, 1 means write
+ *
+ * If this routine detects a bad access, it returns 1, otherwise it
+ * returns 0.
+ */
+asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
+ unsigned long error_code)
+{
+ struct vm_area_struct * vma;
+
+#ifdef DEBUG
+ printk ("regs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld, %p\n",
+ regs->sr, regs->pc, address, error_code,
+ current->tss.pagedir_v);
+#endif
+
+ vma = find_vma(current, address);
+ if (!vma)
+ goto bad_area;
+ if (vma->vm_start <= address)
+ goto good_area;
+ if (!(vma->vm_flags & VM_GROWSDOWN))
+ goto bad_area;
+ if (user_mode(regs)) {
+ /* Accessing the stack below usp is always a bug. The
+ "+ 256" is there due to some instructions doing
+ pre-decrement on the stack and that doesn't show up
+ until later. */
+ if (address + 256 < rdusp())
+ goto bad_area;
+ }
+ if (expand_stack(vma, address))
+ goto bad_area;
+
+/*
+ * Ok, we have a good vm_area for this memory access, so
+ * we can handle it..
+ */
+good_area:
+ /*
+ * was it a write?
+ */
+ if (error_code & 2) {
+ if (!(vma->vm_flags & VM_WRITE))
+ goto bad_area;
+ } else {
+ /* read with protection fault? */
+ if (error_code & 1)
+ goto bad_area;
+ if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+ goto bad_area;
+ }
+ if (error_code & 1) {
+ do_wp_page(current, vma, address, error_code & 2);
+ return 0;
+ }
+ do_no_page(current, vma, address, error_code & 2);
+
+ /* There seems to be a missing invalidate somewhere in do_no_page.
+ * Until I found it, this one cures the problem and makes
+ * 1.2 run on the 68040 (Martin Apel).
+ */
+ flush_tlb_all();
+
+ return 0;
+
+/*
+ * Something tried to access memory that isn't in our memory map..
+ * Fix it, but check if it's kernel or user first..
+ */
+bad_area:
+ if (user_mode(regs)) {
+ /* User memory access */
+ send_sig (SIGSEGV, current, 1);
+ return 1;
+ }
+
+/*
+ * Oops. The kernel tried to access some bad page. We'll have to
+ * terminate things with extreme prejudice.
+ */
+ if ((unsigned long) address < PAGE_SIZE) {
+ printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
+ } else
+ printk(KERN_ALERT "Unable to handle kernel access");
+ printk(" at virtual address %08lx\n",address);
+ die_if_kernel("Oops", regs, error_code);
+ do_exit(SIGKILL);
+
+ return 1;
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this