.. | .. |
---|
24 | 24 | #include <asm/tlbflush.h> |
---|
25 | 25 | #include <asm/traps.h> |
---|
26 | 26 | |
---|
27 | | -static inline int notify_page_fault(struct pt_regs *regs, int trap) |
---|
28 | | -{ |
---|
29 | | - int ret = 0; |
---|
30 | | - |
---|
31 | | - if (kprobes_built_in() && !user_mode(regs)) { |
---|
32 | | - preempt_disable(); |
---|
33 | | - if (kprobe_running() && kprobe_fault_handler(regs, trap)) |
---|
34 | | - ret = 1; |
---|
35 | | - preempt_enable(); |
---|
36 | | - } |
---|
37 | | - |
---|
38 | | - return ret; |
---|
39 | | -} |
---|
40 | | - |
---|
41 | 27 | static void |
---|
42 | | -force_sig_info_fault(int si_signo, int si_code, unsigned long address, |
---|
43 | | - struct task_struct *tsk) |
---|
| 28 | +force_sig_info_fault(int si_signo, int si_code, unsigned long address) |
---|
44 | 29 | { |
---|
45 | | - force_sig_fault(si_signo, si_code, (void __user *)address, tsk); |
---|
| 30 | + force_sig_fault(si_signo, si_code, (void __user *)address); |
---|
46 | 31 | } |
---|
47 | 32 | |
---|
48 | 33 | /* |
---|
.. | .. |
---|
62 | 47 | pgd = swapper_pg_dir; |
---|
63 | 48 | } |
---|
64 | 49 | |
---|
65 | | - printk(KERN_ALERT "pgd = %p\n", pgd); |
---|
| 50 | + pr_alert("pgd = %p\n", pgd); |
---|
66 | 51 | pgd += pgd_index(addr); |
---|
67 | | - printk(KERN_ALERT "[%08lx] *pgd=%0*Lx", addr, |
---|
68 | | - (u32)(sizeof(*pgd) * 2), (u64)pgd_val(*pgd)); |
---|
| 52 | + pr_alert("[%08lx] *pgd=%0*llx", addr, (u32)(sizeof(*pgd) * 2), |
---|
| 53 | + (u64)pgd_val(*pgd)); |
---|
69 | 54 | |
---|
70 | 55 | do { |
---|
| 56 | + p4d_t *p4d; |
---|
71 | 57 | pud_t *pud; |
---|
72 | 58 | pmd_t *pmd; |
---|
73 | 59 | pte_t *pte; |
---|
.. | .. |
---|
76 | 62 | break; |
---|
77 | 63 | |
---|
78 | 64 | if (pgd_bad(*pgd)) { |
---|
79 | | - printk("(bad)"); |
---|
| 65 | + pr_cont("(bad)"); |
---|
80 | 66 | break; |
---|
81 | 67 | } |
---|
82 | 68 | |
---|
83 | | - pud = pud_offset(pgd, addr); |
---|
| 69 | + p4d = p4d_offset(pgd, addr); |
---|
| 70 | + if (PTRS_PER_P4D != 1) |
---|
| 71 | + pr_cont(", *p4d=%0*Lx", (u32)(sizeof(*p4d) * 2), |
---|
| 72 | + (u64)p4d_val(*p4d)); |
---|
| 73 | + |
---|
| 74 | + if (p4d_none(*p4d)) |
---|
| 75 | + break; |
---|
| 76 | + |
---|
| 77 | + if (p4d_bad(*p4d)) { |
---|
| 78 | + pr_cont("(bad)"); |
---|
| 79 | + break; |
---|
| 80 | + } |
---|
| 81 | + |
---|
| 82 | + pud = pud_offset(p4d, addr); |
---|
84 | 83 | if (PTRS_PER_PUD != 1) |
---|
85 | | - printk(", *pud=%0*Lx", (u32)(sizeof(*pud) * 2), |
---|
86 | | - (u64)pud_val(*pud)); |
---|
| 84 | + pr_cont(", *pud=%0*llx", (u32)(sizeof(*pud) * 2), |
---|
| 85 | + (u64)pud_val(*pud)); |
---|
87 | 86 | |
---|
88 | 87 | if (pud_none(*pud)) |
---|
89 | 88 | break; |
---|
90 | 89 | |
---|
91 | 90 | if (pud_bad(*pud)) { |
---|
92 | | - printk("(bad)"); |
---|
| 91 | + pr_cont("(bad)"); |
---|
93 | 92 | break; |
---|
94 | 93 | } |
---|
95 | 94 | |
---|
96 | 95 | pmd = pmd_offset(pud, addr); |
---|
97 | 96 | if (PTRS_PER_PMD != 1) |
---|
98 | | - printk(", *pmd=%0*Lx", (u32)(sizeof(*pmd) * 2), |
---|
99 | | - (u64)pmd_val(*pmd)); |
---|
| 97 | + pr_cont(", *pmd=%0*llx", (u32)(sizeof(*pmd) * 2), |
---|
| 98 | + (u64)pmd_val(*pmd)); |
---|
100 | 99 | |
---|
101 | 100 | if (pmd_none(*pmd)) |
---|
102 | 101 | break; |
---|
103 | 102 | |
---|
104 | 103 | if (pmd_bad(*pmd)) { |
---|
105 | | - printk("(bad)"); |
---|
| 104 | + pr_cont("(bad)"); |
---|
106 | 105 | break; |
---|
107 | 106 | } |
---|
108 | 107 | |
---|
.. | .. |
---|
111 | 110 | break; |
---|
112 | 111 | |
---|
113 | 112 | pte = pte_offset_kernel(pmd, addr); |
---|
114 | | - printk(", *pte=%0*Lx", (u32)(sizeof(*pte) * 2), |
---|
115 | | - (u64)pte_val(*pte)); |
---|
| 113 | + pr_cont(", *pte=%0*llx", (u32)(sizeof(*pte) * 2), |
---|
| 114 | + (u64)pte_val(*pte)); |
---|
116 | 115 | } while (0); |
---|
117 | 116 | |
---|
118 | | - printk("\n"); |
---|
| 117 | + pr_cont("\n"); |
---|
119 | 118 | } |
---|
120 | 119 | |
---|
121 | 120 | static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address) |
---|
122 | 121 | { |
---|
123 | 122 | unsigned index = pgd_index(address); |
---|
124 | 123 | pgd_t *pgd_k; |
---|
| 124 | + p4d_t *p4d, *p4d_k; |
---|
125 | 125 | pud_t *pud, *pud_k; |
---|
126 | 126 | pmd_t *pmd, *pmd_k; |
---|
127 | 127 | |
---|
.. | .. |
---|
131 | 131 | if (!pgd_present(*pgd_k)) |
---|
132 | 132 | return NULL; |
---|
133 | 133 | |
---|
134 | | - pud = pud_offset(pgd, address); |
---|
135 | | - pud_k = pud_offset(pgd_k, address); |
---|
| 134 | + p4d = p4d_offset(pgd, address); |
---|
| 135 | + p4d_k = p4d_offset(pgd_k, address); |
---|
| 136 | + if (!p4d_present(*p4d_k)) |
---|
| 137 | + return NULL; |
---|
| 138 | + |
---|
| 139 | + pud = pud_offset(p4d, address); |
---|
| 140 | + pud_k = pud_offset(p4d_k, address); |
---|
136 | 141 | if (!pud_present(*pud_k)) |
---|
137 | 142 | return NULL; |
---|
138 | 143 | |
---|
.. | .. |
---|
203 | 208 | if (!oops_may_print()) |
---|
204 | 209 | return; |
---|
205 | 210 | |
---|
206 | | - printk(KERN_ALERT "BUG: unable to handle kernel "); |
---|
207 | | - if (address < PAGE_SIZE) |
---|
208 | | - printk(KERN_CONT "NULL pointer dereference"); |
---|
209 | | - else |
---|
210 | | - printk(KERN_CONT "paging request"); |
---|
211 | | - |
---|
212 | | - printk(KERN_CONT " at %08lx\n", address); |
---|
213 | | - printk(KERN_ALERT "PC:"); |
---|
| 211 | + pr_alert("BUG: unable to handle kernel %s at %08lx\n", |
---|
| 212 | + address < PAGE_SIZE ? "NULL pointer dereference" |
---|
| 213 | + : "paging request", |
---|
| 214 | + address); |
---|
| 215 | + pr_alert("PC:"); |
---|
214 | 216 | printk_address(regs->pc, 1); |
---|
215 | 217 | |
---|
216 | 218 | show_pte(NULL, address); |
---|
.. | .. |
---|
244 | 246 | __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code, |
---|
245 | 247 | unsigned long address, int si_code) |
---|
246 | 248 | { |
---|
247 | | - struct task_struct *tsk = current; |
---|
248 | | - |
---|
249 | 249 | /* User mode accesses just cause a SIGSEGV */ |
---|
250 | 250 | if (user_mode(regs)) { |
---|
251 | 251 | /* |
---|
.. | .. |
---|
253 | 253 | */ |
---|
254 | 254 | local_irq_enable(); |
---|
255 | 255 | |
---|
256 | | - force_sig_info_fault(SIGSEGV, si_code, address, tsk); |
---|
| 256 | + force_sig_info_fault(SIGSEGV, si_code, address); |
---|
257 | 257 | |
---|
258 | 258 | return; |
---|
259 | 259 | } |
---|
.. | .. |
---|
278 | 278 | * Something tried to access memory that isn't in our memory map.. |
---|
279 | 279 | * Fix it, but check if it's kernel or user first.. |
---|
280 | 280 | */ |
---|
281 | | - up_read(&mm->mmap_sem); |
---|
| 281 | + mmap_read_unlock(mm); |
---|
282 | 282 | |
---|
283 | 283 | __bad_area_nosemaphore(regs, error_code, address, si_code); |
---|
284 | 284 | } |
---|
.. | .. |
---|
302 | 302 | struct task_struct *tsk = current; |
---|
303 | 303 | struct mm_struct *mm = tsk->mm; |
---|
304 | 304 | |
---|
305 | | - up_read(&mm->mmap_sem); |
---|
| 305 | + mmap_read_unlock(mm); |
---|
306 | 306 | |
---|
307 | 307 | /* Kernel mode? Handle exceptions or die: */ |
---|
308 | 308 | if (!user_mode(regs)) |
---|
309 | 309 | no_context(regs, error_code, address); |
---|
310 | 310 | |
---|
311 | | - force_sig_info_fault(SIGBUS, BUS_ADRERR, address, tsk); |
---|
| 311 | + force_sig_info_fault(SIGBUS, BUS_ADRERR, address); |
---|
312 | 312 | } |
---|
313 | 313 | |
---|
314 | 314 | static noinline int |
---|
.. | .. |
---|
319 | 319 | * Pagefault was interrupted by SIGKILL. We have no reason to |
---|
320 | 320 | * continue pagefault. |
---|
321 | 321 | */ |
---|
322 | | - if (fatal_signal_pending(current)) { |
---|
323 | | - if (!(fault & VM_FAULT_RETRY)) |
---|
324 | | - up_read(¤t->mm->mmap_sem); |
---|
| 322 | + if (fault_signal_pending(fault, regs)) { |
---|
325 | 323 | if (!user_mode(regs)) |
---|
326 | 324 | no_context(regs, error_code, address); |
---|
327 | 325 | return 1; |
---|
328 | 326 | } |
---|
| 327 | + |
---|
| 328 | + /* Release mmap_lock first if necessary */ |
---|
| 329 | + if (!(fault & VM_FAULT_RETRY)) |
---|
| 330 | + mmap_read_unlock(current->mm); |
---|
329 | 331 | |
---|
330 | 332 | if (!(fault & VM_FAULT_ERROR)) |
---|
331 | 333 | return 0; |
---|
.. | .. |
---|
333 | 335 | if (fault & VM_FAULT_OOM) { |
---|
334 | 336 | /* Kernel mode? Handle exceptions or die: */ |
---|
335 | 337 | if (!user_mode(regs)) { |
---|
336 | | - up_read(¤t->mm->mmap_sem); |
---|
337 | 338 | no_context(regs, error_code, address); |
---|
338 | 339 | return 1; |
---|
339 | 340 | } |
---|
340 | | - up_read(¤t->mm->mmap_sem); |
---|
341 | 341 | |
---|
342 | 342 | /* |
---|
343 | 343 | * We ran out of memory, call the OOM killer, and return the |
---|
.. | .. |
---|
372 | 372 | return 1; |
---|
373 | 373 | |
---|
374 | 374 | /* read, not present: */ |
---|
375 | | - if (unlikely(!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))) |
---|
| 375 | + if (unlikely(!vma_is_accessible(vma))) |
---|
376 | 376 | return 1; |
---|
377 | 377 | |
---|
378 | 378 | return 0; |
---|
.. | .. |
---|
397 | 397 | struct mm_struct *mm; |
---|
398 | 398 | struct vm_area_struct * vma; |
---|
399 | 399 | vm_fault_t fault; |
---|
400 | | - unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; |
---|
| 400 | + unsigned int flags = FAULT_FLAG_DEFAULT; |
---|
401 | 401 | |
---|
402 | 402 | tsk = current; |
---|
403 | 403 | mm = tsk->mm; |
---|
.. | .. |
---|
415 | 415 | if (unlikely(fault_in_kernel_space(address))) { |
---|
416 | 416 | if (vmalloc_fault(address) >= 0) |
---|
417 | 417 | return; |
---|
418 | | - if (notify_page_fault(regs, vec)) |
---|
| 418 | + if (kprobe_page_fault(regs, vec)) |
---|
419 | 419 | return; |
---|
420 | 420 | |
---|
421 | 421 | bad_area_nosemaphore(regs, error_code, address); |
---|
422 | 422 | return; |
---|
423 | 423 | } |
---|
424 | 424 | |
---|
425 | | - if (unlikely(notify_page_fault(regs, vec))) |
---|
| 425 | + if (unlikely(kprobe_page_fault(regs, vec))) |
---|
426 | 426 | return; |
---|
427 | 427 | |
---|
428 | 428 | /* Only enable interrupts if they were on before the fault */ |
---|
.. | .. |
---|
441 | 441 | } |
---|
442 | 442 | |
---|
443 | 443 | retry: |
---|
444 | | - down_read(&mm->mmap_sem); |
---|
| 444 | + mmap_read_lock(mm); |
---|
445 | 445 | |
---|
446 | 446 | vma = find_vma(mm, address); |
---|
447 | 447 | if (unlikely(!vma)) { |
---|
.. | .. |
---|
481 | 481 | * make sure we exit gracefully rather than endlessly redo |
---|
482 | 482 | * the fault. |
---|
483 | 483 | */ |
---|
484 | | - fault = handle_mm_fault(vma, address, flags); |
---|
| 484 | + fault = handle_mm_fault(vma, address, flags, regs); |
---|
485 | 485 | |
---|
486 | 486 | if (unlikely(fault & (VM_FAULT_RETRY | VM_FAULT_ERROR))) |
---|
487 | 487 | if (mm_fault_error(regs, error_code, address, fault)) |
---|
488 | 488 | return; |
---|
489 | 489 | |
---|
490 | 490 | if (flags & FAULT_FLAG_ALLOW_RETRY) { |
---|
491 | | - if (fault & VM_FAULT_MAJOR) { |
---|
492 | | - tsk->maj_flt++; |
---|
493 | | - perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, |
---|
494 | | - regs, address); |
---|
495 | | - } else { |
---|
496 | | - tsk->min_flt++; |
---|
497 | | - perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, |
---|
498 | | - regs, address); |
---|
499 | | - } |
---|
500 | 491 | if (fault & VM_FAULT_RETRY) { |
---|
501 | | - flags &= ~FAULT_FLAG_ALLOW_RETRY; |
---|
502 | 492 | flags |= FAULT_FLAG_TRIED; |
---|
503 | 493 | |
---|
504 | 494 | /* |
---|
505 | | - * No need to up_read(&mm->mmap_sem) as we would |
---|
| 495 | + * No need to mmap_read_unlock(mm) as we would |
---|
506 | 496 | * have already released it in __lock_page_or_retry |
---|
507 | 497 | * in mm/filemap.c. |
---|
508 | 498 | */ |
---|
.. | .. |
---|
510 | 500 | } |
---|
511 | 501 | } |
---|
512 | 502 | |
---|
513 | | - up_read(&mm->mmap_sem); |
---|
| 503 | + mmap_read_unlock(mm); |
---|
514 | 504 | } |
---|