1
2
3
4
5
6
7
8
9
10
11#include <linux/config.h>
12#include <linux/signal.h>
13#include <linux/sched.h>
14#include <linux/kernel.h>
15#include <linux/errno.h>
16#include <linux/string.h>
17#include <linux/types.h>
18#include <linux/ptrace.h>
19#include <linux/mman.h>
20#include <linux/mm.h>
21#include <linux/interrupt.h>
22#include <linux/proc_fs.h>
23#include <linux/init.h>
24
25#include <asm/system.h>
26#include <asm/pgtable.h>
27
28#include "fault.h"
29
30#ifdef CONFIG_CPU_26
31#define FAULT_CODE_WRITE 0x02
32#define FAULT_CODE_FORCECOW 0x01
33#define DO_COW(m) ((m) & (FAULT_CODE_WRITE|FAULT_CODE_FORCECOW))
34#define READ_FAULT(m) (!((m) & FAULT_CODE_WRITE))
35#else
36
37
38
39
40#define DO_COW(code) ((code) & (1 << 11))
41#define READ_FAULT(code) (!DO_COW(code))
42#endif
43
44
45
46
47
48void show_pte(struct mm_struct *mm, unsigned long addr)
49{
50 pgd_t *pgd;
51
52 if (!mm)
53 mm = &init_mm;
54
55 printk(KERN_ALERT "pgd = %p\n", mm->pgd);
56 pgd = pgd_offset(mm, addr);
57 printk(KERN_ALERT "*pgd=%08lx", pgd_val(*pgd));
58
59 do {
60 pmd_t *pmd;
61 pte_t *pte;
62
63 if (pgd_none(*pgd))
64 break;
65
66 if (pgd_bad(*pgd)) {
67 printk("(bad)");
68 break;
69 }
70
71 pmd = pmd_offset(pgd, addr);
72#if PTRS_PER_PMD != 1
73 printk(", *pmd=%08lx", pmd_val(*pmd));
74#endif
75
76 if (pmd_none(*pmd))
77 break;
78
79 if (pmd_bad(*pmd)) {
80 printk("(bad)");
81 break;
82 }
83
84#ifndef CONFIG_HIGHMEM
85
86 pte = pte_offset_map(pmd, addr);
87 printk(", *pte=%08lx", pte_val(*pte));
88#ifdef CONFIG_CPU_32
89 printk(", *ppte=%08lx", pte_val(pte[-PTRS_PER_PTE]));
90#endif
91 pte_unmap(pte);
92#endif
93 } while(0);
94
95 printk("\n");
96}
97
98
99
100
101static void
102__do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
103 struct pt_regs *regs)
104{
105 unsigned long fixup;
106
107
108
109
110 if ((fixup = search_exception_table(instruction_pointer(regs))) != 0) {
111#ifdef DEBUG
112 printk(KERN_DEBUG "%s: Exception at [<%lx>] addr=%lx (fixup: %lx)\n",
113 current->comm, regs->ARM_pc, addr, fixup);
114#endif
115 regs->ARM_pc = fixup;
116 return;
117 }
118
119
120
121
122 printk(KERN_ALERT
123 "Unable to handle kernel %s at virtual address %08lx\n",
124 (addr < PAGE_SIZE) ? "NULL pointer dereference" :
125 "paging request", addr);
126
127 show_pte(mm, addr);
128 die("Oops", regs, fsr);
129 do_exit(SIGKILL);
130}
131
132
133
134
135
136static void
137__do_user_fault(struct task_struct *tsk, unsigned long addr,
138 unsigned int fsr, int code, struct pt_regs *regs)
139{
140 struct siginfo si;
141
142#ifdef CONFIG_DEBUG_USER
143 printk(KERN_DEBUG "%s: unhandled page fault at 0x%08lx, code 0x%03x\n",
144 tsk->comm, addr, fsr);
145 show_pte(tsk->mm, addr);
146 show_regs(regs);
147#endif
148
149 tsk->thread.address = addr;
150 tsk->thread.error_code = fsr;
151 tsk->thread.trap_no = 14;
152 si.si_signo = SIGSEGV;
153 si.si_errno = 0;
154 si.si_code = code;
155 si.si_addr = (void *)addr;
156 force_sig_info(SIGSEGV, &si, tsk);
157}
158
159void
160do_bad_area(struct task_struct *tsk, struct mm_struct *mm, unsigned long addr,
161 unsigned int fsr, struct pt_regs *regs)
162{
163
164
165
166
167 if (user_mode(regs))
168 __do_user_fault(tsk, addr, fsr, SEGV_MAPERR, regs);
169 else
170 __do_kernel_fault(mm, addr, fsr, regs);
171}
172
173static int
174__do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
175 struct task_struct *tsk)
176{
177 struct vm_area_struct *vma;
178 int fault, mask;
179
180 vma = find_vma(mm, addr);
181 fault = -2;
182 if (!vma)
183 goto out;
184 if (vma->vm_start > addr)
185 goto check_stack;
186
187
188
189
190
191good_area:
192 if (READ_FAULT(fsr))
193 mask = VM_READ|VM_EXEC;
194 else
195 mask = VM_WRITE;
196
197 fault = -1;
198 if (!(vma->vm_flags & mask))
199 goto out;
200
201
202
203
204
205
206survive:
207 fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, DO_COW(fsr));
208
209
210
211
212 switch (fault) {
213 case 2:
214 tsk->maj_flt++;
215 return fault;
216 case 1:
217 tsk->min_flt++;
218 case 0:
219 return fault;
220 }
221
222 fault = -3;
223 if (tsk->pid != 1)
224 goto out;
225
226
227
228
229
230 yield();
231 goto survive;
232
233check_stack:
234 if (vma->vm_flags & VM_GROWSDOWN && !expand_stack(vma, addr))
235 goto good_area;
236out:
237 return fault;
238}
239
240int do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
241{
242 struct task_struct *tsk;
243 struct mm_struct *mm;
244 int fault;
245
246 tsk = current;
247 mm = tsk->mm;
248
249
250
251
252
253 if (in_interrupt() || !mm)
254 goto no_context;
255
256 down_read(&mm->mmap_sem);
257 fault = __do_page_fault(mm, addr, fsr, tsk);
258 up_read(&mm->mmap_sem);
259
260
261
262
263 if (fault > 0)
264 return 0;
265
266
267
268
269
270 if (fault == 0)
271 goto do_sigbus;
272
273
274
275
276
277 if (!user_mode(regs))
278 goto no_context;
279
280 if (fault == -3) {
281
282
283
284
285 printk("VM: killing process %s\n", tsk->comm);
286 do_exit(SIGKILL);
287 } else
288 __do_user_fault(tsk, addr, fsr, fault == -1 ?
289 SEGV_ACCERR : SEGV_MAPERR, regs);
290 return 0;
291
292
293
294
295
296
297do_sigbus:
298
299
300
301
302 tsk->thread.address = addr;
303 tsk->thread.error_code = fsr;
304 tsk->thread.trap_no = 14;
305 force_sig(SIGBUS, tsk);
306#ifdef CONFIG_DEBUG_USER
307 printk(KERN_DEBUG "%s: sigbus at 0x%08lx, pc=0x%08lx\n",
308 current->comm, addr, instruction_pointer(regs));
309#endif
310
311
312 if (user_mode(regs))
313 return 0;
314
315no_context:
316 __do_kernel_fault(mm, addr, fsr, regs);
317 return 0;
318}
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337int do_translation_fault(unsigned long addr, unsigned int fsr,
338 struct pt_regs *regs)
339{
340 struct task_struct *tsk;
341 unsigned int offset;
342 pgd_t *pgd, *pgd_k;
343 pmd_t *pmd, *pmd_k;
344
345 if (addr < TASK_SIZE)
346 return do_page_fault(addr, fsr, regs);
347
348 offset = __pgd_offset(addr);
349
350
351
352
353 pgd = cpu_get_pgd() + offset;
354 pgd_k = init_mm.pgd + offset;
355
356 if (pgd_none(*pgd_k))
357 goto bad_area;
358
359 if (!pgd_present(*pgd))
360 set_pgd(pgd, *pgd_k);
361
362 pmd_k = pmd_offset(pgd_k, addr);
363 pmd = pmd_offset(pgd, addr);
364
365 if (pmd_none(*pmd_k))
366 goto bad_area;
367
368 set_pmd(pmd, *pmd_k);
369 return 0;
370
371bad_area:
372 tsk = current;
373
374 do_bad_area(tsk, tsk->active_mm, addr, fsr, regs);
375 return 0;
376}
377