| .. | .. |
|---|
| 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 | } |
|---|