1
2
3
4
5
6
7#include <linux/mm.h>
8#include <linux/interrupt.h>
9#include <linux/module.h>
10#include <linux/wait.h>
11#include <asm/uaccess.h>
12
13extern int find_fixup_code(struct pt_regs *);
14extern void die_if_kernel(const char *, struct pt_regs *, long);
15extern void show_registers(struct pt_regs *regs);
16
17
18#undef DEBUG
19
20#ifdef DEBUG
21#define D(x) x
22#else
23#define D(x)
24#endif
25
26
27#define DPG(x)
28
29
30
31DEFINE_PER_CPU(pgd_t *, current_pgd);
32unsigned long cris_signal_return_page;
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51asmlinkage void
52do_page_fault(unsigned long address, struct pt_regs *regs,
53 int protection, int writeaccess)
54{
55 struct task_struct *tsk;
56 struct mm_struct *mm;
57 struct vm_area_struct * vma;
58 siginfo_t info;
59 int fault;
60
61 D(printk(KERN_DEBUG
62 "Page fault for %lX on %X at %lX, prot %d write %d\n",
63 address, smp_processor_id(), instruction_pointer(regs),
64 protection, writeaccess));
65
66 tsk = current;
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 if (address >= VMALLOC_START &&
88 !protection &&
89 !user_mode(regs))
90 goto vmalloc_fault;
91
92
93
94
95
96
97
98 if (cris_signal_return_page &&
99 address == cris_signal_return_page &&
100 !protection && user_mode(regs))
101 goto vmalloc_fault;
102
103
104 local_irq_enable();
105
106 mm = tsk->mm;
107 info.si_code = SEGV_MAPERR;
108
109
110
111
112
113
114 if (in_atomic() || !mm)
115 goto no_context;
116
117 down_read(&mm->mmap_sem);
118 vma = find_vma(mm, address);
119 if (!vma)
120 goto bad_area;
121 if (vma->vm_start <= address)
122 goto good_area;
123 if (!(vma->vm_flags & VM_GROWSDOWN))
124 goto bad_area;
125 if (user_mode(regs)) {
126
127
128
129
130
131
132 if (address + PAGE_SIZE < rdusp())
133 goto bad_area;
134 }
135 if (expand_stack(vma, address))
136 goto bad_area;
137
138
139
140
141
142
143 good_area:
144 info.si_code = SEGV_ACCERR;
145
146
147
148 if (writeaccess == 2){
149 if (!(vma->vm_flags & VM_EXEC))
150 goto bad_area;
151 } else if (writeaccess == 1) {
152 if (!(vma->vm_flags & VM_WRITE))
153 goto bad_area;
154 } else {
155 if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
156 goto bad_area;
157 }
158
159
160
161
162
163
164
165 fault = handle_mm_fault(mm, vma, address, (writeaccess & 1) ? FAULT_FLAG_WRITE : 0);
166 if (unlikely(fault & VM_FAULT_ERROR)) {
167 if (fault & VM_FAULT_OOM)
168 goto out_of_memory;
169 else if (fault & VM_FAULT_SIGBUS)
170 goto do_sigbus;
171 BUG();
172 }
173 if (fault & VM_FAULT_MAJOR)
174 tsk->maj_flt++;
175 else
176 tsk->min_flt++;
177
178 up_read(&mm->mmap_sem);
179 return;
180
181
182
183
184
185
186 bad_area:
187 up_read(&mm->mmap_sem);
188
189 bad_area_nosemaphore:
190 DPG(show_registers(regs));
191
192
193
194 if (user_mode(regs)) {
195 printk(KERN_NOTICE "%s (pid %d) segfaults for page "
196 "address %08lx at pc %08lx\n",
197 tsk->comm, tsk->pid,
198 address, instruction_pointer(regs));
199
200
201 DPG(if (0))
202 show_registers(regs);
203
204#ifdef CONFIG_NO_SEGFAULT_TERMINATION
205 DECLARE_WAIT_QUEUE_HEAD(wq);
206 wait_event_interruptible(wq, 0 == 1);
207#else
208 info.si_signo = SIGSEGV;
209 info.si_errno = 0;
210
211 info.si_addr = (void *)address;
212 force_sig_info(SIGSEGV, &info, tsk);
213#endif
214 return;
215 }
216
217 no_context:
218
219
220
221
222
223
224
225
226
227
228 if (find_fixup_code(regs))
229 return;
230
231
232
233
234
235
236 if (!oops_in_progress) {
237 oops_in_progress = 1;
238 if ((unsigned long) (address) < PAGE_SIZE)
239 printk(KERN_ALERT "Unable to handle kernel NULL "
240 "pointer dereference");
241 else
242 printk(KERN_ALERT "Unable to handle kernel access"
243 " at virtual address %08lx\n", address);
244
245 die_if_kernel("Oops", regs, (writeaccess << 1) | protection);
246 oops_in_progress = 0;
247 }
248
249 do_exit(SIGKILL);
250
251
252
253
254
255
256 out_of_memory:
257 up_read(&mm->mmap_sem);
258 if (!user_mode(regs))
259 goto no_context;
260 pagefault_out_of_memory();
261 return;
262
263 do_sigbus:
264 up_read(&mm->mmap_sem);
265
266
267
268
269
270 info.si_signo = SIGBUS;
271 info.si_errno = 0;
272 info.si_code = BUS_ADRERR;
273 info.si_addr = (void *)address;
274 force_sig_info(SIGBUS, &info, tsk);
275
276
277 if (!user_mode(regs))
278 goto no_context;
279 return;
280
281vmalloc_fault:
282 {
283
284
285
286
287
288
289
290
291
292
293
294 int offset = pgd_index(address);
295 pgd_t *pgd, *pgd_k;
296 pud_t *pud, *pud_k;
297 pmd_t *pmd, *pmd_k;
298 pte_t *pte_k;
299
300 pgd = (pgd_t *)per_cpu(current_pgd, smp_processor_id()) + offset;
301 pgd_k = init_mm.pgd + offset;
302
303
304
305
306
307
308
309
310
311
312
313
314
315 pud = pud_offset(pgd, address);
316 pud_k = pud_offset(pgd_k, address);
317 if (!pud_present(*pud_k))
318 goto no_context;
319
320 pmd = pmd_offset(pud, address);
321 pmd_k = pmd_offset(pud_k, address);
322
323 if (!pmd_present(*pmd_k))
324 goto bad_area_nosemaphore;
325
326 set_pmd(pmd, *pmd_k);
327
328
329
330
331
332
333
334 pte_k = pte_offset_kernel(pmd_k, address);
335 if (!pte_present(*pte_k))
336 goto no_context;
337
338 return;
339 }
340}
341
342
343int
344find_fixup_code(struct pt_regs *regs)
345{
346 const struct exception_table_entry *fixup;
347
348 unsigned long ip = (instruction_pointer(regs) & ~0x1);
349
350 fixup = search_exception_tables(ip);
351 if (fixup != 0) {
352
353 instruction_pointer(regs) = fixup->fixup;
354 arch_fixup(regs);
355 return 1;
356 }
357
358 return 0;
359}
360