]>
Commit | Line | Data |
---|---|---|
61e85e36 JB |
1 | /* |
2 | * OpenRISC fault.c | |
3 | * | |
4 | * Linux architectural port borrowing liberally from similar works of | |
5 | * others. All original copyrights apply as per the original source | |
6 | * declaration. | |
7 | * | |
8 | * Modifications for the OpenRISC architecture: | |
9 | * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com> | |
10 | * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se> | |
11 | * | |
12 | * This program is free software; you can redistribute it and/or | |
13 | * modify it under the terms of the GNU General Public License | |
14 | * as published by the Free Software Foundation; either version | |
15 | * 2 of the License, or (at your option) any later version. | |
16 | */ | |
17 | ||
18 | #include <linux/mm.h> | |
19 | #include <linux/interrupt.h> | |
ce139ab8 | 20 | #include <linux/extable.h> |
3f07c014 | 21 | #include <linux/sched/signal.h> |
61e85e36 | 22 | |
7c0f6ba6 | 23 | #include <linux/uaccess.h> |
61e85e36 JB |
24 | #include <asm/siginfo.h> |
25 | #include <asm/signal.h> | |
26 | ||
27 | #define NUM_TLB_ENTRIES 64 | |
28 | #define TLB_OFFSET(add) (((add) >> PAGE_SHIFT) & (NUM_TLB_ENTRIES-1)) | |
29 | ||
30 | unsigned long pte_misses; /* updated by do_page_fault() */ | |
31 | unsigned long pte_errors; /* updated by do_page_fault() */ | |
32 | ||
33 | /* __PHX__ :: - check the vmalloc_fault in do_page_fault() | |
34 | * - also look into include/asm-or32/mmu_context.h | |
35 | */ | |
8e6d08e0 | 36 | volatile pgd_t *current_pgd[NR_CPUS]; |
61e85e36 JB |
37 | |
38 | extern void die(char *, struct pt_regs *, long); | |
39 | ||
40 | /* | |
41 | * This routine handles page faults. It determines the address, | |
42 | * and the problem, and then passes it off to one of the appropriate | |
43 | * routines. | |
44 | * | |
45 | * If this routine detects a bad access, it returns 1, otherwise it | |
46 | * returns 0. | |
47 | */ | |
48 | ||
49 | asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address, | |
50 | unsigned long vector, int write_acc) | |
51 | { | |
52 | struct task_struct *tsk; | |
53 | struct mm_struct *mm; | |
54 | struct vm_area_struct *vma; | |
55 | siginfo_t info; | |
56 | int fault; | |
4971f2bd | 57 | unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; |
61e85e36 JB |
58 | |
59 | tsk = current; | |
60 | ||
61 | /* | |
62 | * We fault-in kernel-space virtual memory on-demand. The | |
63 | * 'reference' page table is init_mm.pgd. | |
64 | * | |
65 | * NOTE! We MUST NOT take any locks for this case. We may | |
66 | * be in an interrupt or a critical region, and should | |
67 | * only copy the information from the master page table, | |
68 | * nothing more. | |
69 | * | |
70 | * NOTE2: This is done so that, when updating the vmalloc | |
71 | * mappings we don't have to walk all processes pgdirs and | |
72 | * add the high mappings all at once. Instead we do it as they | |
73 | * are used. However vmalloc'ed page entries have the PAGE_GLOBAL | |
74 | * bit set so sometimes the TLB can use a lingering entry. | |
75 | * | |
76 | * This verifies that the fault happens in kernel space | |
77 | * and that the fault was not a protection error. | |
78 | */ | |
79 | ||
80 | if (address >= VMALLOC_START && | |
81 | (vector != 0x300 && vector != 0x400) && | |
82 | !user_mode(regs)) | |
83 | goto vmalloc_fault; | |
84 | ||
85 | /* If exceptions were enabled, we can reenable them here */ | |
86 | if (user_mode(regs)) { | |
87 | /* Exception was in userspace: reenable interrupts */ | |
88 | local_irq_enable(); | |
759496ba | 89 | flags |= FAULT_FLAG_USER; |
61e85e36 JB |
90 | } else { |
91 | /* If exception was in a syscall, then IRQ's may have | |
92 | * been enabled or disabled. If they were enabled, | |
93 | * reenable them. | |
94 | */ | |
95 | if (regs->sr && (SPR_SR_IEE | SPR_SR_TEE)) | |
96 | local_irq_enable(); | |
97 | } | |
98 | ||
99 | mm = tsk->mm; | |
100 | info.si_code = SEGV_MAPERR; | |
101 | ||
102 | /* | |
103 | * If we're in an interrupt or have no user | |
104 | * context, we must not take the fault.. | |
105 | */ | |
106 | ||
107 | if (in_interrupt() || !mm) | |
108 | goto no_context; | |
109 | ||
4971f2bd | 110 | retry: |
61e85e36 JB |
111 | down_read(&mm->mmap_sem); |
112 | vma = find_vma(mm, address); | |
113 | ||
114 | if (!vma) | |
115 | goto bad_area; | |
116 | ||
117 | if (vma->vm_start <= address) | |
118 | goto good_area; | |
119 | ||
120 | if (!(vma->vm_flags & VM_GROWSDOWN)) | |
121 | goto bad_area; | |
122 | ||
123 | if (user_mode(regs)) { | |
124 | /* | |
125 | * accessing the stack below usp is always a bug. | |
126 | * we get page-aligned addresses so we can only check | |
127 | * if we're within a page from usp, but that might be | |
128 | * enough to catch brutal errors at least. | |
129 | */ | |
130 | if (address + PAGE_SIZE < regs->sp) | |
131 | goto bad_area; | |
132 | } | |
133 | if (expand_stack(vma, address)) | |
134 | goto bad_area; | |
135 | ||
136 | /* | |
137 | * Ok, we have a good vm_area for this memory access, so | |
138 | * we can handle it.. | |
139 | */ | |
140 | ||
141 | good_area: | |
142 | info.si_code = SEGV_ACCERR; | |
143 | ||
144 | /* first do some preliminary protection checks */ | |
145 | ||
146 | if (write_acc) { | |
147 | if (!(vma->vm_flags & VM_WRITE)) | |
148 | goto bad_area; | |
4971f2bd | 149 | flags |= FAULT_FLAG_WRITE; |
61e85e36 JB |
150 | } else { |
151 | /* not present */ | |
152 | if (!(vma->vm_flags & (VM_READ | VM_EXEC))) | |
153 | goto bad_area; | |
154 | } | |
155 | ||
156 | /* are we trying to execute nonexecutable area */ | |
157 | if ((vector == 0x400) && !(vma->vm_page_prot.pgprot & _PAGE_EXEC)) | |
158 | goto bad_area; | |
159 | ||
160 | /* | |
161 | * If for any reason at all we couldn't handle the fault, | |
162 | * make sure we exit gracefully rather than endlessly redo | |
163 | * the fault. | |
164 | */ | |
165 | ||
dcddffd4 | 166 | fault = handle_mm_fault(vma, address, flags); |
4971f2bd KC |
167 | |
168 | if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) | |
169 | return; | |
170 | ||
61e85e36 JB |
171 | if (unlikely(fault & VM_FAULT_ERROR)) { |
172 | if (fault & VM_FAULT_OOM) | |
173 | goto out_of_memory; | |
33692f27 LT |
174 | else if (fault & VM_FAULT_SIGSEGV) |
175 | goto bad_area; | |
61e85e36 JB |
176 | else if (fault & VM_FAULT_SIGBUS) |
177 | goto do_sigbus; | |
178 | BUG(); | |
179 | } | |
4971f2bd KC |
180 | |
181 | if (flags & FAULT_FLAG_ALLOW_RETRY) { | |
182 | /*RGD modeled on Cris */ | |
183 | if (fault & VM_FAULT_MAJOR) | |
184 | tsk->maj_flt++; | |
185 | else | |
186 | tsk->min_flt++; | |
187 | if (fault & VM_FAULT_RETRY) { | |
188 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | |
45cac65b | 189 | flags |= FAULT_FLAG_TRIED; |
4971f2bd KC |
190 | |
191 | /* No need to up_read(&mm->mmap_sem) as we would | |
192 | * have already released it in __lock_page_or_retry | |
193 | * in mm/filemap.c. | |
194 | */ | |
195 | ||
196 | goto retry; | |
197 | } | |
198 | } | |
61e85e36 JB |
199 | |
200 | up_read(&mm->mmap_sem); | |
201 | return; | |
202 | ||
203 | /* | |
204 | * Something tried to access memory that isn't in our memory map.. | |
205 | * Fix it, but check if it's kernel or user first.. | |
206 | */ | |
207 | ||
208 | bad_area: | |
209 | up_read(&mm->mmap_sem); | |
210 | ||
211 | bad_area_nosemaphore: | |
212 | ||
213 | /* User mode accesses just cause a SIGSEGV */ | |
214 | ||
215 | if (user_mode(regs)) { | |
216 | info.si_signo = SIGSEGV; | |
217 | info.si_errno = 0; | |
218 | /* info.si_code has been set above */ | |
219 | info.si_addr = (void *)address; | |
220 | force_sig_info(SIGSEGV, &info, tsk); | |
221 | return; | |
222 | } | |
223 | ||
224 | no_context: | |
225 | ||
226 | /* Are we prepared to handle this kernel fault? | |
227 | * | |
228 | * (The kernel has valid exception-points in the source | |
229 | * when it acesses user-memory. When it fails in one | |
230 | * of those points, we find it in a table and do a jump | |
231 | * to some fixup code that loads an appropriate error | |
232 | * code) | |
233 | */ | |
234 | ||
235 | { | |
236 | const struct exception_table_entry *entry; | |
237 | ||
238 | __asm__ __volatile__("l.nop 42"); | |
239 | ||
240 | if ((entry = search_exception_tables(regs->pc)) != NULL) { | |
241 | /* Adjust the instruction pointer in the stackframe */ | |
242 | regs->pc = entry->fixup; | |
243 | return; | |
244 | } | |
245 | } | |
246 | ||
247 | /* | |
248 | * Oops. The kernel tried to access some bad page. We'll have to | |
249 | * terminate things with extreme prejudice. | |
250 | */ | |
251 | ||
252 | if ((unsigned long)(address) < PAGE_SIZE) | |
253 | printk(KERN_ALERT | |
254 | "Unable to handle kernel NULL pointer dereference"); | |
255 | else | |
256 | printk(KERN_ALERT "Unable to handle kernel access"); | |
257 | printk(" at virtual address 0x%08lx\n", address); | |
258 | ||
259 | die("Oops", regs, write_acc); | |
260 | ||
261 | do_exit(SIGKILL); | |
262 | ||
263 | /* | |
264 | * We ran out of memory, or some other thing happened to us that made | |
265 | * us unable to handle the page fault gracefully. | |
266 | */ | |
267 | ||
268 | out_of_memory: | |
269 | __asm__ __volatile__("l.nop 42"); | |
270 | __asm__ __volatile__("l.nop 1"); | |
271 | ||
272 | up_read(&mm->mmap_sem); | |
609838cf JW |
273 | if (!user_mode(regs)) |
274 | goto no_context; | |
275 | pagefault_out_of_memory(); | |
276 | return; | |
61e85e36 JB |
277 | |
278 | do_sigbus: | |
279 | up_read(&mm->mmap_sem); | |
280 | ||
281 | /* | |
282 | * Send a sigbus, regardless of whether we were in kernel | |
283 | * or user mode. | |
284 | */ | |
285 | info.si_signo = SIGBUS; | |
286 | info.si_errno = 0; | |
287 | info.si_code = BUS_ADRERR; | |
288 | info.si_addr = (void *)address; | |
289 | force_sig_info(SIGBUS, &info, tsk); | |
290 | ||
291 | /* Kernel mode? Handle exceptions or die */ | |
292 | if (!user_mode(regs)) | |
293 | goto no_context; | |
294 | return; | |
295 | ||
296 | vmalloc_fault: | |
297 | { | |
298 | /* | |
299 | * Synchronize this task's top level page-table | |
300 | * with the 'reference' page table. | |
301 | * | |
302 | * Use current_pgd instead of tsk->active_mm->pgd | |
303 | * since the latter might be unavailable if this | |
304 | * code is executed in a misfortunately run irq | |
305 | * (like inside schedule() between switch_mm and | |
306 | * switch_to...). | |
307 | */ | |
308 | ||
309 | int offset = pgd_index(address); | |
310 | pgd_t *pgd, *pgd_k; | |
311 | pud_t *pud, *pud_k; | |
312 | pmd_t *pmd, *pmd_k; | |
313 | pte_t *pte_k; | |
314 | ||
315 | /* | |
316 | phx_warn("do_page_fault(): vmalloc_fault will not work, " | |
317 | "since current_pgd assign a proper value somewhere\n" | |
318 | "anyhow we don't need this at the moment\n"); | |
319 | ||
320 | phx_mmu("vmalloc_fault"); | |
321 | */ | |
8e6d08e0 | 322 | pgd = (pgd_t *)current_pgd[smp_processor_id()] + offset; |
61e85e36 JB |
323 | pgd_k = init_mm.pgd + offset; |
324 | ||
325 | /* Since we're two-level, we don't need to do both | |
326 | * set_pgd and set_pmd (they do the same thing). If | |
327 | * we go three-level at some point, do the right thing | |
328 | * with pgd_present and set_pgd here. | |
329 | * | |
330 | * Also, since the vmalloc area is global, we don't | |
331 | * need to copy individual PTE's, it is enough to | |
332 | * copy the pgd pointer into the pte page of the | |
333 | * root task. If that is there, we'll find our pte if | |
334 | * it exists. | |
335 | */ | |
336 | ||
337 | pud = pud_offset(pgd, address); | |
338 | pud_k = pud_offset(pgd_k, address); | |
339 | if (!pud_present(*pud_k)) | |
340 | goto no_context; | |
341 | ||
342 | pmd = pmd_offset(pud, address); | |
343 | pmd_k = pmd_offset(pud_k, address); | |
344 | ||
345 | if (!pmd_present(*pmd_k)) | |
346 | goto bad_area_nosemaphore; | |
347 | ||
348 | set_pmd(pmd, *pmd_k); | |
349 | ||
350 | /* Make sure the actual PTE exists as well to | |
351 | * catch kernel vmalloc-area accesses to non-mapped | |
352 | * addresses. If we don't do this, this will just | |
353 | * silently loop forever. | |
354 | */ | |
355 | ||
356 | pte_k = pte_offset_kernel(pmd_k, address); | |
357 | if (!pte_present(*pte_k)) | |
358 | goto no_context; | |
359 | ||
360 | return; | |
361 | } | |
362 | } |