| .. | .. | 
|---|
| 27 | 27 |  #include <linux/uaccess.h> | 
|---|
| 28 | 28 |   | 
|---|
| 29 | 29 |  #include <asm/page.h> | 
|---|
| 30 |  | -#include <asm/pgtable.h>  | 
|---|
| 31 | 30 |  #include <asm/openprom.h> | 
|---|
| 32 | 31 |  #include <asm/oplib.h> | 
|---|
| 33 | 32 |  #include <asm/asi.h> | 
|---|
| .. | .. | 
|---|
| 37 | 36 |  #include <asm/setup.h> | 
|---|
| 38 | 37 |   | 
|---|
| 39 | 38 |  int show_unhandled_signals = 1; | 
|---|
| 40 |  | -  | 
|---|
| 41 |  | -static inline __kprobes int notify_page_fault(struct pt_regs *regs)  | 
|---|
| 42 |  | -{  | 
|---|
| 43 |  | -	int ret = 0;  | 
|---|
| 44 |  | -  | 
|---|
| 45 |  | -	/* kprobe_running() needs smp_processor_id() */  | 
|---|
| 46 |  | -	if (kprobes_built_in() && !user_mode(regs)) {  | 
|---|
| 47 |  | -		preempt_disable();  | 
|---|
| 48 |  | -		if (kprobe_running() && kprobe_fault_handler(regs, 0))  | 
|---|
| 49 |  | -			ret = 1;  | 
|---|
| 50 |  | -		preempt_enable();  | 
|---|
| 51 |  | -	}  | 
|---|
| 52 |  | -	return ret;  | 
|---|
| 53 |  | -}  | 
|---|
| 54 | 39 |   | 
|---|
| 55 | 40 |  static void __kprobes unhandled_fault(unsigned long address, | 
|---|
| 56 | 41 |  				      struct task_struct *tsk, | 
|---|
| .. | .. | 
|---|
| 85 | 70 |  } | 
|---|
| 86 | 71 |   | 
|---|
| 87 | 72 |  /* | 
|---|
| 88 |  | - * We now make sure that mmap_sem is held in all paths that call   | 
|---|
 | 73 | + * We now make sure that mmap_lock is held in all paths that call  | 
|---|
| 89 | 74 |   * this. Additionally, to prevent kswapd from ripping ptes from | 
|---|
| 90 | 75 |   * under us, raise interrupts around the time that we look at the | 
|---|
| 91 | 76 |   * pte, kswapd will have to wait to get his smp ipi response from | 
|---|
| .. | .. | 
|---|
| 94 | 79 |  static unsigned int get_user_insn(unsigned long tpc) | 
|---|
| 95 | 80 |  { | 
|---|
| 96 | 81 |  	pgd_t *pgdp = pgd_offset(current->mm, tpc); | 
|---|
 | 82 | +	p4d_t *p4dp;  | 
|---|
| 97 | 83 |  	pud_t *pudp; | 
|---|
| 98 | 84 |  	pmd_t *pmdp; | 
|---|
| 99 | 85 |  	pte_t *ptep, pte; | 
|---|
| .. | .. | 
|---|
| 102 | 88 |   | 
|---|
| 103 | 89 |  	if (pgd_none(*pgdp) || unlikely(pgd_bad(*pgdp))) | 
|---|
| 104 | 90 |  		goto out; | 
|---|
| 105 |  | -	pudp = pud_offset(pgdp, tpc);  | 
|---|
 | 91 | +	p4dp = p4d_offset(pgdp, tpc);  | 
|---|
 | 92 | +	if (p4d_none(*p4dp) || unlikely(p4d_bad(*p4dp)))  | 
|---|
 | 93 | +		goto out;  | 
|---|
 | 94 | +	pudp = pud_offset(p4dp, tpc);  | 
|---|
| 106 | 95 |  	if (pud_none(*pudp) || unlikely(pud_bad(*pudp))) | 
|---|
| 107 | 96 |  		goto out; | 
|---|
| 108 | 97 |   | 
|---|
| .. | .. | 
|---|
| 187 | 176 |  	if (unlikely(show_unhandled_signals)) | 
|---|
| 188 | 177 |  		show_signal_msg(regs, sig, code, addr, current); | 
|---|
| 189 | 178 |   | 
|---|
| 190 |  | -	force_sig_fault(sig, code, (void __user *) addr, 0, current);  | 
|---|
 | 179 | +	force_sig_fault(sig, code, (void __user *) addr, 0);  | 
|---|
| 191 | 180 |  } | 
|---|
| 192 | 181 |   | 
|---|
| 193 | 182 |  static unsigned int get_fault_insn(struct pt_regs *regs, unsigned int insn) | 
|---|
| .. | .. | 
|---|
| 281 | 270 |  	int si_code, fault_code; | 
|---|
| 282 | 271 |  	vm_fault_t fault; | 
|---|
| 283 | 272 |  	unsigned long address, mm_rss; | 
|---|
| 284 |  | -	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;  | 
|---|
 | 273 | +	unsigned int flags = FAULT_FLAG_DEFAULT;  | 
|---|
| 285 | 274 |   | 
|---|
| 286 | 275 |  	fault_code = get_thread_fault_code(); | 
|---|
| 287 | 276 |   | 
|---|
| 288 |  | -	if (notify_page_fault(regs))  | 
|---|
 | 277 | +	if (kprobe_page_fault(regs, 0))  | 
|---|
| 289 | 278 |  		goto exit_exception; | 
|---|
| 290 | 279 |   | 
|---|
| 291 | 280 |  	si_code = SEGV_MAPERR; | 
|---|
| .. | .. | 
|---|
| 329 | 318 |   | 
|---|
| 330 | 319 |  	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); | 
|---|
| 331 | 320 |   | 
|---|
| 332 |  | -	if (!down_read_trylock(&mm->mmap_sem)) {  | 
|---|
 | 321 | +	if (!mmap_read_trylock(mm)) {  | 
|---|
| 333 | 322 |  		if ((regs->tstate & TSTATE_PRIV) && | 
|---|
| 334 | 323 |  		    !search_exception_tables(regs->tpc)) { | 
|---|
| 335 | 324 |  			insn = get_fault_insn(regs, insn); | 
|---|
| .. | .. | 
|---|
| 337 | 326 |  		} | 
|---|
| 338 | 327 |   | 
|---|
| 339 | 328 |  retry: | 
|---|
| 340 |  | -		down_read(&mm->mmap_sem);  | 
|---|
 | 329 | +		mmap_read_lock(mm);  | 
|---|
| 341 | 330 |  	} | 
|---|
| 342 | 331 |   | 
|---|
| 343 | 332 |  	if (fault_code & FAULT_CODE_BAD_RA) | 
|---|
| .. | .. | 
|---|
| 433 | 422 |  			goto bad_area; | 
|---|
| 434 | 423 |  	} | 
|---|
| 435 | 424 |   | 
|---|
| 436 |  | -	fault = handle_mm_fault(vma, address, flags);  | 
|---|
 | 425 | +	fault = handle_mm_fault(vma, address, flags, regs);  | 
|---|
| 437 | 426 |   | 
|---|
| 438 |  | -	if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))  | 
|---|
 | 427 | +	if (fault_signal_pending(fault, regs))  | 
|---|
| 439 | 428 |  		goto exit_exception; | 
|---|
| 440 | 429 |   | 
|---|
| 441 | 430 |  	if (unlikely(fault & VM_FAULT_ERROR)) { | 
|---|
| .. | .. | 
|---|
| 449 | 438 |  	} | 
|---|
| 450 | 439 |   | 
|---|
| 451 | 440 |  	if (flags & FAULT_FLAG_ALLOW_RETRY) { | 
|---|
| 452 |  | -		if (fault & VM_FAULT_MAJOR) {  | 
|---|
| 453 |  | -			current->maj_flt++;  | 
|---|
| 454 |  | -			perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ,  | 
|---|
| 455 |  | -				      1, regs, address);  | 
|---|
| 456 |  | -		} else {  | 
|---|
| 457 |  | -			current->min_flt++;  | 
|---|
| 458 |  | -			perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN,  | 
|---|
| 459 |  | -				      1, regs, address);  | 
|---|
| 460 |  | -		}  | 
|---|
| 461 | 441 |  		if (fault & VM_FAULT_RETRY) { | 
|---|
| 462 |  | -			flags &= ~FAULT_FLAG_ALLOW_RETRY;  | 
|---|
| 463 | 442 |  			flags |= FAULT_FLAG_TRIED; | 
|---|
| 464 | 443 |   | 
|---|
| 465 |  | -			/* No need to up_read(&mm->mmap_sem) as we would  | 
|---|
 | 444 | +			/* No need to mmap_read_unlock(mm) as we would  | 
|---|
| 466 | 445 |  			 * have already released it in __lock_page_or_retry | 
|---|
| 467 | 446 |  			 * in mm/filemap.c. | 
|---|
| 468 | 447 |  			 */ | 
|---|
| .. | .. | 
|---|
| 470 | 449 |  			goto retry; | 
|---|
| 471 | 450 |  		} | 
|---|
| 472 | 451 |  	} | 
|---|
| 473 |  | -	up_read(&mm->mmap_sem);  | 
|---|
 | 452 | +	mmap_read_unlock(mm);  | 
|---|
| 474 | 453 |   | 
|---|
| 475 | 454 |  	mm_rss = get_mm_rss(mm); | 
|---|
| 476 | 455 |  #if defined(CONFIG_TRANSPARENT_HUGEPAGE) | 
|---|
| .. | .. | 
|---|
| 501 | 480 |  	 */ | 
|---|
| 502 | 481 |  bad_area: | 
|---|
| 503 | 482 |  	insn = get_fault_insn(regs, insn); | 
|---|
| 504 |  | -	up_read(&mm->mmap_sem);  | 
|---|
 | 483 | +	mmap_read_unlock(mm);  | 
|---|
| 505 | 484 |   | 
|---|
| 506 | 485 |  handle_kernel_fault: | 
|---|
| 507 | 486 |  	do_kernel_fault(regs, si_code, fault_code, insn, address); | 
|---|
| .. | .. | 
|---|
| 513 | 492 |   */ | 
|---|
| 514 | 493 |  out_of_memory: | 
|---|
| 515 | 494 |  	insn = get_fault_insn(regs, insn); | 
|---|
| 516 |  | -	up_read(&mm->mmap_sem);  | 
|---|
 | 495 | +	mmap_read_unlock(mm);  | 
|---|
| 517 | 496 |  	if (!(regs->tstate & TSTATE_PRIV)) { | 
|---|
| 518 | 497 |  		pagefault_out_of_memory(); | 
|---|
| 519 | 498 |  		goto exit_exception; | 
|---|
| .. | .. | 
|---|
| 526 | 505 |   | 
|---|
| 527 | 506 |  do_sigbus: | 
|---|
| 528 | 507 |  	insn = get_fault_insn(regs, insn); | 
|---|
| 529 |  | -	up_read(&mm->mmap_sem);  | 
|---|
 | 508 | +	mmap_read_unlock(mm);  | 
|---|
| 530 | 509 |   | 
|---|
| 531 | 510 |  	/* | 
|---|
| 532 | 511 |  	 * Send a sigbus, regardless of whether we were in kernel | 
|---|