Ok. I didn't make 2.4.0 in 2000. Tough. I tried, but we had some
[davej-history.git] / arch / mips / mm / fault.c
blob1d93088486ae645576a98839bdfd9b21526e0592
1 /*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
6 * Copyright (C) 1995 - 2000 by Ralf Baechle
7 */
8 #include <linux/signal.h>
9 #include <linux/sched.h>
10 #include <linux/interrupt.h>
11 #include <linux/kernel.h>
12 #include <linux/errno.h>
13 #include <linux/string.h>
14 #include <linux/types.h>
15 #include <linux/ptrace.h>
16 #include <linux/mman.h>
17 #include <linux/mm.h>
18 #include <linux/smp.h>
19 #include <linux/smp_lock.h>
20 #include <linux/version.h>
22 #include <asm/hardirq.h>
23 #include <asm/pgalloc.h>
24 #include <asm/mmu_context.h>
25 #include <asm/softirq.h>
26 #include <asm/system.h>
27 #include <asm/uaccess.h>
29 #define development_version (LINUX_VERSION_CODE & 0x100)
31 unsigned long asid_cache = ASID_FIRST_VERSION;
34 * Macro for exception fixup code to access integer registers.
36 #define dpf_reg(r) (regs->regs[r])
39 * This routine handles page faults. It determines the address,
40 * and the problem, and then passes it off to one of the appropriate
41 * routines.
43 asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
44 unsigned long address)
46 struct vm_area_struct * vma;
47 struct task_struct *tsk = current;
48 struct mm_struct *mm = tsk->mm;
49 unsigned long fixup;
50 siginfo_t info;
52 info.si_code = SEGV_MAPERR;
54 * If we're in an interrupt or have no user
55 * context, we must not take the fault..
57 if (in_interrupt() || !mm)
58 goto no_context;
59 #if 0
60 printk("[%s:%d:%08lx:%ld:%08lx]\n", current->comm, current->pid,
61 address, write, regs->cp0_epc);
62 #endif
63 down(&mm->mmap_sem);
64 vma = find_vma(mm, address);
65 if (!vma)
66 goto bad_area;
67 if (vma->vm_start <= address)
68 goto good_area;
69 if (!(vma->vm_flags & VM_GROWSDOWN))
70 goto bad_area;
71 if (expand_stack(vma, address))
72 goto bad_area;
74 * Ok, we have a good vm_area for this memory access, so
75 * we can handle it..
77 good_area:
78 info.si_code = SEGV_ACCERR;
80 if (write) {
81 if (!(vma->vm_flags & VM_WRITE))
82 goto bad_area;
83 } else {
84 if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
85 goto bad_area;
89 * If for any reason at all we couldn't handle the fault,
90 * make sure we exit gracefully rather than endlessly redo
91 * the fault.
93 switch (handle_mm_fault(mm, vma, address, write)) {
94 case 1:
95 tsk->min_flt++;
96 break;
97 case 2:
98 tsk->maj_flt++;
99 break;
100 case 0:
101 goto do_sigbus;
102 default:
103 goto out_of_memory;
106 up(&mm->mmap_sem);
107 return;
110 * Something tried to access memory that isn't in our memory map..
111 * Fix it, but check if it's kernel or user first..
113 bad_area:
114 up(&mm->mmap_sem);
116 if (user_mode(regs)) {
117 tsk->thread.cp0_badvaddr = address;
118 tsk->thread.error_code = write;
119 #if 0
120 printk("do_page_fault() #2: sending SIGSEGV to %s for illegal %s\n"
121 "%08lx (epc == %08lx, ra == %08lx)\n",
122 tsk->comm,
123 write ? "write access to" : "read access from",
124 address,
125 (unsigned long) regs->cp0_epc,
126 (unsigned long) regs->regs[31]);
127 #endif
128 info.si_signo = SIGSEGV;
129 info.si_errno = 0;
130 /* info.si_code has been set above */
131 info.si_addr = (void *) address;
132 force_sig_info(SIGSEGV, &info, tsk);
133 return;
136 no_context:
137 /* Are we prepared to handle this kernel fault? */
138 fixup = search_exception_table(regs->cp0_epc);
139 if (fixup) {
140 long new_epc;
142 tsk->thread.cp0_baduaddr = address;
143 new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc);
144 if (development_version)
145 printk(KERN_DEBUG "%s: Exception at [<%lx>] (%lx)\n",
146 tsk->comm, regs->cp0_epc, new_epc);
147 regs->cp0_epc = new_epc;
148 return;
152 * Oops. The kernel tried to access some bad page. We'll have to
153 * terminate things with extreme prejudice.
155 printk(KERN_ALERT "Unable to handle kernel paging request at virtual "
156 "address %08lx, epc == %08lx, ra == %08lx\n",
157 address, regs->cp0_epc, regs->regs[31]);
158 die("Oops", regs);
159 do_exit(SIGKILL);
162 * We ran out of memory, or some other thing happened to us that made
163 * us unable to handle the page fault gracefully.
165 out_of_memory:
166 up(&mm->mmap_sem);
167 printk("VM: killing process %s\n", tsk->comm);
168 if (user_mode(regs))
169 do_exit(SIGKILL);
170 goto no_context;
172 do_sigbus:
173 up(&mm->mmap_sem);
176 * Send a sigbus, regardless of whether we were in kernel
177 * or user mode.
179 tsk->thread.cp0_badvaddr = address;
180 info.si_code = SIGBUS;
181 info.si_errno = 0;
182 info.si_code = BUS_ADRERR;
183 info.si_addr = (void *) address;
184 force_sig_info(SIGBUS, &info, tsk);
186 /* Kernel mode? Handle exceptions or die */
187 if (!user_mode(regs))
188 goto no_context;