1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include <linux/module.h>
21#include <linux/signal.h>
22#include <linux/sched.h>
23#include <linux/kernel.h>
24#include <linux/errno.h>
25#include <linux/string.h>
26#include <linux/types.h>
27#include <linux/ptrace.h>
28#include <linux/mman.h>
29#include <linux/mm.h>
30#include <linux/interrupt.h>
31
32#include <asm/page.h>
33#include <asm/pgtable.h>
34#include <asm/mmu.h>
35#include <asm/mmu_context.h>
36#include <asm/system.h>
37#include <linux/uaccess.h>
38#include <asm/exceptions.h>
39
40#if defined(CONFIG_KGDB)
41int debugger_kernel_faults = 1;
42#endif
43
44static unsigned long pte_misses;
45static unsigned long pte_errors;
46
47
48
49
50
51static int store_updates_sp(struct pt_regs *regs)
52{
53 unsigned int inst;
54
55 if (get_user(inst, (unsigned int *)regs->pc))
56 return 0;
57
58 if (((inst >> 21) & 0x1f) != 1)
59 return 0;
60
61 if ((inst & 0xd0000000) == 0xd0000000)
62 return 1;
63 return 0;
64}
65
66
67
68
69
70
71
72void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
73{
74 const struct exception_table_entry *fixup;
75
76
77 fixup = search_exception_tables(regs->pc);
78 if (fixup) {
79 regs->pc = fixup->fixup;
80 return;
81 }
82
83
84#if defined(CONFIG_KGDB)
85 if (debugger_kernel_faults)
86 debugger(regs);
87#endif
88 die("kernel access of bad area", regs, sig);
89}
90
91
92
93
94
95void do_page_fault(struct pt_regs *regs, unsigned long address,
96 unsigned long error_code)
97{
98 struct vm_area_struct *vma;
99 struct mm_struct *mm = current->mm;
100 siginfo_t info;
101 int code = SEGV_MAPERR;
102 int is_write = error_code & ESR_S;
103 int fault;
104
105 regs->ear = address;
106 regs->esr = error_code;
107
108
109 if (kernel_mode(regs) && (address >= TASK_SIZE)) {
110 printk(KERN_WARNING "kernel task_size exceed");
111 _exception(SIGSEGV, regs, code, address);
112 }
113
114
115 if ((error_code & 0x13) == 0x13 || (error_code & 0x11) == 0x11)
116 is_write = 0;
117
118#if defined(CONFIG_KGDB)
119 if (debugger_fault_handler && regs->trap == 0x300) {
120 debugger_fault_handler(regs);
121 return;
122 }
123#endif
124
125 if (in_atomic() || !mm) {
126 if (kernel_mode(regs))
127 goto bad_area_nosemaphore;
128
129
130
131 printk(KERN_EMERG "Page fault in user mode with "
132 "in_atomic(), mm = %p\n", mm);
133 printk(KERN_EMERG "r15 = %lx MSR = %lx\n",
134 regs->r15, regs->msr);
135 die("Weird page fault", regs, SIGSEGV);
136 }
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153 if (!down_read_trylock(&mm->mmap_sem)) {
154 if (kernel_mode(regs) && !search_exception_tables(regs->pc))
155 goto bad_area_nosemaphore;
156
157 down_read(&mm->mmap_sem);
158 }
159
160 vma = find_vma(mm, address);
161 if (!vma)
162 goto bad_area;
163
164 if (vma->vm_start <= address)
165 goto good_area;
166
167 if (!(vma->vm_flags & VM_GROWSDOWN))
168 goto bad_area;
169
170 if (!is_write)
171 goto bad_area;
172
173
174
175
176
177
178
179
180
181
182 if (address + 0x100000 < vma->vm_end) {
183
184
185 struct pt_regs *uregs = current->thread.regs;
186 if (uregs == NULL)
187 goto bad_area;
188
189
190
191
192
193
194
195
196
197
198
199
200
201 if (address + 2048 < uregs->r1
202 && (kernel_mode(regs) || !store_updates_sp(regs)))
203 goto bad_area;
204 }
205 if (expand_stack(vma, address))
206 goto bad_area;
207
208good_area:
209 code = SEGV_ACCERR;
210
211
212 if (is_write) {
213 if (!(vma->vm_flags & VM_WRITE))
214 goto bad_area;
215
216 } else {
217
218 if (error_code & 0x08000000)
219 goto bad_area;
220 if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
221 goto bad_area;
222 }
223
224
225
226
227
228
229survive:
230 fault = handle_mm_fault(mm, vma, address, is_write ? FAULT_FLAG_WRITE : 0);
231 if (unlikely(fault & VM_FAULT_ERROR)) {
232 if (fault & VM_FAULT_OOM)
233 goto out_of_memory;
234 else if (fault & VM_FAULT_SIGBUS)
235 goto do_sigbus;
236 BUG();
237 }
238 if (fault & VM_FAULT_MAJOR)
239 current->maj_flt++;
240 else
241 current->min_flt++;
242 up_read(&mm->mmap_sem);
243
244
245
246
247
248 pte_misses++;
249 return;
250
251bad_area:
252 up_read(&mm->mmap_sem);
253
254bad_area_nosemaphore:
255 pte_errors++;
256
257
258 if (user_mode(regs)) {
259 _exception(SIGSEGV, regs, code, address);
260
261
262
263
264
265 return;
266 }
267
268 bad_page_fault(regs, address, SIGSEGV);
269 return;
270
271
272
273
274
275out_of_memory:
276 if (current->pid == 1) {
277 yield();
278 down_read(&mm->mmap_sem);
279 goto survive;
280 }
281 up_read(&mm->mmap_sem);
282 printk(KERN_WARNING "VM: killing process %s\n", current->comm);
283 if (user_mode(regs))
284 do_exit(SIGKILL);
285 bad_page_fault(regs, address, SIGKILL);
286 return;
287
288do_sigbus:
289 up_read(&mm->mmap_sem);
290 if (user_mode(regs)) {
291 info.si_signo = SIGBUS;
292 info.si_errno = 0;
293 info.si_code = BUS_ADRERR;
294 info.si_addr = (void __user *)address;
295 force_sig_info(SIGBUS, &info, current);
296 return;
297 }
298 bad_page_fault(regs, address, SIGBUS);
299}
300