4 * Copyright (C) 2000-2010 Axis Communications AB
8 #include <linux/interrupt.h>
9 #include <linux/module.h>
10 #include <linux/wait.h>
11 #include <asm/uaccess.h>
12 #include <arch/system.h>
14 extern int find_fixup_code(struct pt_regs
*);
15 extern void die_if_kernel(const char *, struct pt_regs
*, long);
16 extern void show_registers(struct pt_regs
*regs
);
18 /* debug of low-level TLB reload */
27 /* debug of higher-level faults */
30 /* current active page directory */
32 DEFINE_PER_CPU(pgd_t
*, current_pgd
);
33 unsigned long cris_signal_return_page
;
36 * This routine handles page faults. It determines the address,
37 * and the problem, and then passes it off to one of the appropriate
40 * Notice that the address we're given is aligned to the page the fault
41 * occurred in, since we only get the PFN in R_MMU_CAUSE not the complete
45 * bit 0 == 0 means no page found, 1 means protection fault
46 * bit 1 == 0 means read, 1 means write
48 * If this routine detects a bad access, it returns 1, otherwise it
53 do_page_fault(unsigned long address
, struct pt_regs
*regs
,
54 int protection
, int writeaccess
)
56 struct task_struct
*tsk
;
58 struct vm_area_struct
* vma
;
61 unsigned int flags
= FAULT_FLAG_ALLOW_RETRY
| FAULT_FLAG_KILLABLE
|
62 ((writeaccess
& 1) ? FAULT_FLAG_WRITE
: 0);
65 "Page fault for %lX on %X at %lX, prot %d write %d\n",
66 address
, smp_processor_id(), instruction_pointer(regs
),
67 protection
, writeaccess
));
72 * We fault-in kernel-space virtual memory on-demand. The
73 * 'reference' page table is init_mm.pgd.
75 * NOTE! We MUST NOT take any locks for this case. We may
76 * be in an interrupt or a critical region, and should
77 * only copy the information from the master page table,
80 * NOTE2: This is done so that, when updating the vmalloc
81 * mappings we don't have to walk all processes pgdirs and
82 * add the high mappings all at once. Instead we do it as they
83 * are used. However vmalloc'ed page entries have the PAGE_GLOBAL
84 * bit set so sometimes the TLB can use a lingering entry.
86 * This verifies that the fault happens in kernel space
87 * and that the fault was not a protection error (error_code & 1).
90 if (address
>= VMALLOC_START
&&
95 /* When stack execution is not allowed we store the signal
96 * trampolines in the reserved cris_signal_return_page.
97 * Handle this in the exact same way as vmalloc (we know
98 * that the mapping is there and is valid so no need to
99 * call handle_mm_fault).
101 if (cris_signal_return_page
&&
102 address
== cris_signal_return_page
&&
103 !protection
&& user_mode(regs
))
106 /* we can and should enable interrupts at this point */
110 info
.si_code
= SEGV_MAPERR
;
113 * If we're in an interrupt or "atomic" operation or have no
114 * user context, we must not take the fault.
117 if (in_atomic() || !mm
)
121 down_read(&mm
->mmap_sem
);
122 vma
= find_vma(mm
, address
);
125 if (vma
->vm_start
<= address
)
127 if (!(vma
->vm_flags
& VM_GROWSDOWN
))
129 if (user_mode(regs
)) {
131 * accessing the stack below usp is always a bug.
132 * we get page-aligned addresses so we can only check
133 * if we're within a page from usp, but that might be
134 * enough to catch brutal errors at least.
136 if (address
+ PAGE_SIZE
< rdusp())
139 if (expand_stack(vma
, address
))
143 * Ok, we have a good vm_area for this memory access, so
148 info
.si_code
= SEGV_ACCERR
;
150 /* first do some preliminary protection checks */
152 if (writeaccess
== 2){
153 if (!(vma
->vm_flags
& VM_EXEC
))
155 } else if (writeaccess
== 1) {
156 if (!(vma
->vm_flags
& VM_WRITE
))
159 if (!(vma
->vm_flags
& (VM_READ
| VM_EXEC
)))
164 * If for any reason at all we couldn't handle the fault,
165 * make sure we exit gracefully rather than endlessly redo
169 fault
= handle_mm_fault(mm
, vma
, address
, flags
);
171 if ((fault
& VM_FAULT_RETRY
) && fatal_signal_pending(current
))
174 if (unlikely(fault
& VM_FAULT_ERROR
)) {
175 if (fault
& VM_FAULT_OOM
)
177 else if (fault
& VM_FAULT_SIGBUS
)
182 if (flags
& FAULT_FLAG_ALLOW_RETRY
) {
183 if (fault
& VM_FAULT_MAJOR
)
187 if (fault
& VM_FAULT_RETRY
) {
188 flags
&= ~FAULT_FLAG_ALLOW_RETRY
;
189 flags
|= FAULT_FLAG_TRIED
;
192 * No need to up_read(&mm->mmap_sem) as we would
193 * have already released it in __lock_page_or_retry
201 up_read(&mm
->mmap_sem
);
205 * Something tried to access memory that isn't in our memory map..
206 * Fix it, but check if it's kernel or user first..
210 up_read(&mm
->mmap_sem
);
212 bad_area_nosemaphore
:
213 DPG(show_registers(regs
));
215 /* User mode accesses just cause a SIGSEGV */
217 if (user_mode(regs
)) {
218 printk(KERN_NOTICE
"%s (pid %d) segfaults for page "
219 "address %08lx at pc %08lx\n",
221 address
, instruction_pointer(regs
));
223 /* With DPG on, we've already dumped registers above. */
225 show_registers(regs
);
227 #ifdef CONFIG_NO_SEGFAULT_TERMINATION
228 DECLARE_WAIT_QUEUE_HEAD(wq
);
229 wait_event_interruptible(wq
, 0 == 1);
231 info
.si_signo
= SIGSEGV
;
233 /* info.si_code has been set above */
234 info
.si_addr
= (void *)address
;
235 force_sig_info(SIGSEGV
, &info
, tsk
);
242 /* Are we prepared to handle this kernel fault?
244 * (The kernel has valid exception-points in the source
245 * when it accesses user-memory. When it fails in one
246 * of those points, we find it in a table and do a jump
247 * to some fixup code that loads an appropriate error
251 if (find_fixup_code(regs
))
255 * Oops. The kernel tried to access some bad page. We'll have to
256 * terminate things with extreme prejudice.
259 if (!oops_in_progress
) {
260 oops_in_progress
= 1;
261 if ((unsigned long) (address
) < PAGE_SIZE
)
262 printk(KERN_ALERT
"Unable to handle kernel NULL "
263 "pointer dereference");
265 printk(KERN_ALERT
"Unable to handle kernel access"
266 " at virtual address %08lx\n", address
);
268 die_if_kernel("Oops", regs
, (writeaccess
<< 1) | protection
);
269 oops_in_progress
= 0;
275 * We ran out of memory, or some other thing happened to us that made
276 * us unable to handle the page fault gracefully.
280 up_read(&mm
->mmap_sem
);
281 if (!user_mode(regs
))
283 pagefault_out_of_memory();
287 up_read(&mm
->mmap_sem
);
290 * Send a sigbus, regardless of whether we were in kernel
293 info
.si_signo
= SIGBUS
;
295 info
.si_code
= BUS_ADRERR
;
296 info
.si_addr
= (void *)address
;
297 force_sig_info(SIGBUS
, &info
, tsk
);
299 /* Kernel mode? Handle exceptions or die */
300 if (!user_mode(regs
))
307 * Synchronize this task's top level page-table
308 * with the 'reference' page table.
310 * Use current_pgd instead of tsk->active_mm->pgd
311 * since the latter might be unavailable if this
312 * code is executed in a misfortunately run irq
313 * (like inside schedule() between switch_mm and
317 int offset
= pgd_index(address
);
323 pgd
= (pgd_t
*)per_cpu(current_pgd
, smp_processor_id()) + offset
;
324 pgd_k
= init_mm
.pgd
+ offset
;
326 /* Since we're two-level, we don't need to do both
327 * set_pgd and set_pmd (they do the same thing). If
328 * we go three-level at some point, do the right thing
329 * with pgd_present and set_pgd here.
331 * Also, since the vmalloc area is global, we don't
332 * need to copy individual PTE's, it is enough to
333 * copy the pgd pointer into the pte page of the
334 * root task. If that is there, we'll find our pte if
338 pud
= pud_offset(pgd
, address
);
339 pud_k
= pud_offset(pgd_k
, address
);
340 if (!pud_present(*pud_k
))
343 pmd
= pmd_offset(pud
, address
);
344 pmd_k
= pmd_offset(pud_k
, address
);
346 if (!pmd_present(*pmd_k
))
347 goto bad_area_nosemaphore
;
349 set_pmd(pmd
, *pmd_k
);
351 /* Make sure the actual PTE exists as well to
352 * catch kernel vmalloc-area accesses to non-mapped
353 * addresses. If we don't do this, this will just
354 * silently loop forever.
357 pte_k
= pte_offset_kernel(pmd_k
, address
);
358 if (!pte_present(*pte_k
))
365 /* Find fixup code. */
367 find_fixup_code(struct pt_regs
*regs
)
369 const struct exception_table_entry
*fixup
;
370 /* in case of delay slot fault (v32) */
371 unsigned long ip
= (instruction_pointer(regs
) & ~0x1);
373 fixup
= search_exception_tables(ip
);
375 /* Adjust the instruction pointer in the stackframe. */
376 instruction_pointer(regs
) = fixup
->fixup
;