1 /* 2 * linux/arch/m68k/mm/fault.c 3 * 4 * Copyright (C) 1995 Hamish Macdonald 5 */ 6
7 #include <linux/mman.h>
8 #include <linux/mm.h>
9 #include <linux/kernel.h>
10 #include <linux/ptrace.h>
11
12 #include <asm/system.h>
13 #include <asm/pgtable.h>
14
15 externvoiddie_if_kernel(char *, structpt_regs *, long);
16
17 /* 18 * This routine handles page faults. It determines the problem, and 19 * then passes it off to one of the appropriate routines. 20 * 21 * error_code: 22 * bit 0 == 0 means no page found, 1 means protection fault 23 * bit 1 == 0 means read, 1 means write 24 * 25 * If this routine detects a bad access, it returns 1, otherwise it 26 * returns 0. 27 */ 28 asmlinkageintdo_page_fault(structpt_regs *regs, unsignedlongaddress,
/* */ 29 unsignedlongerror_code)
30 { 31 structvm_area_struct * vma;
32
33 #ifdefDEBUG 34 printk ("regs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld, %p\n",
35 regs->sr, regs->pc, address, error_code,
36 current->tss.pagedir_v);
37 #endif 38
39 vma = find_vma(current, address);
40 if (!vma)
41 gotobad_area;
42 if (vma->vm_start <= address)
43 gotogood_area;
44 if (!(vma->vm_flags & VM_GROWSDOWN))
45 gotobad_area;
46 if (user_mode(regs)) { 47 /* Accessing the stack below usp is always a bug. The 48 "+ 256" is there due to some instructions doing 49 pre-decrement on the stack and that doesn't show up 50 until later. */ 51 if (address + 256 < rdusp())
52 gotobad_area;
53 } 54 if (expand_stack(vma, address))
55 gotobad_area;
56
57 /* 58 * Ok, we have a good vm_area for this memory access, so 59 * we can handle it.. 60 */ 61 good_area:
62 /* 63 * was it a write? 64 */ 65 if (error_code & 2) { 66 if (!(vma->vm_flags & VM_WRITE))
67 gotobad_area;
68 }else{ 69 /* read with protection fault? */ 70 if (error_code & 1)
71 gotobad_area;
72 if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
73 gotobad_area;
74 } 75 if (error_code & 1) { 76 do_wp_page(current, vma, address, error_code & 2);
77 return 0;
78 } 79 do_no_page(current, vma, address, error_code & 2);
80
81 /* There seems to be a missing invalidate somewhere in do_no_page. 82 * Until I found it, this one cures the problem and makes 83 * 1.2 run on the 68040 (Martin Apel). 84 */ 85 flush_tlb_all();
86
87 return 0;
88
89 /* 90 * Something tried to access memory that isn't in our memory map.. 91 * Fix it, but check if it's kernel or user first.. 92 */ 93 bad_area:
94 if (user_mode(regs)) { 95 /* User memory access */ 96 send_sig (SIGSEGV, current, 1);
97 return 1;
98 } 99
100 /* 101 * Oops. The kernel tried to access some bad page. We'll have to 102 * terminate things with extreme prejudice. 103 */ 104 if ((unsignedlong) address < PAGE_SIZE) { 105 printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
106 }else 107 printk(KERN_ALERT "Unable to handle kernel access");
108 printk(" at virtual address %08lx\n",address);
109 die_if_kernel("Oops", regs, error_code);
110 do_exit(SIGKILL);
111
112 return 1;
113 }