| .. | .. | 
|---|
| 25 | 25 |  #include <linux/uaccess.h> | 
|---|
| 26 | 26 |   | 
|---|
| 27 | 27 |  #include <asm/page.h> | 
|---|
| 28 |  | -#include <asm/pgtable.h>  | 
|---|
| 29 | 28 |  #include <asm/openprom.h> | 
|---|
| 30 | 29 |  #include <asm/oplib.h> | 
|---|
| 31 | 30 |  #include <asm/setup.h> | 
|---|
| .. | .. | 
|---|
| 131 | 130 |  		show_signal_msg(regs, sig, code, | 
|---|
| 132 | 131 |  				addr, current); | 
|---|
| 133 | 132 |   | 
|---|
| 134 |  | -	force_sig_fault(sig, code, (void __user *) addr, 0, current);  | 
|---|
 | 133 | +	force_sig_fault(sig, code, (void __user *) addr, 0);  | 
|---|
| 135 | 134 |  } | 
|---|
| 136 | 135 |   | 
|---|
| 137 | 136 |  static unsigned long compute_si_addr(struct pt_regs *regs, int text_fault) | 
|---|
| .. | .. | 
|---|
| 168 | 167 |  	int from_user = !(regs->psr & PSR_PS); | 
|---|
| 169 | 168 |  	int code; | 
|---|
| 170 | 169 |  	vm_fault_t fault; | 
|---|
| 171 |  | -	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;  | 
|---|
 | 170 | +	unsigned int flags = FAULT_FLAG_DEFAULT;  | 
|---|
| 172 | 171 |   | 
|---|
| 173 | 172 |  	if (text_fault) | 
|---|
| 174 | 173 |  		address = regs->pc; | 
|---|
| .. | .. | 
|---|
| 196 | 195 |  	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); | 
|---|
| 197 | 196 |   | 
|---|
| 198 | 197 |  retry: | 
|---|
| 199 |  | -	down_read(&mm->mmap_sem);  | 
|---|
 | 198 | +	mmap_read_lock(mm);  | 
|---|
| 200 | 199 |   | 
|---|
| 201 | 200 |  	if (!from_user && address >= PAGE_OFFSET) | 
|---|
| 202 | 201 |  		goto bad_area; | 
|---|
| .. | .. | 
|---|
| 235 | 234 |  	 * make sure we exit gracefully rather than endlessly redo | 
|---|
| 236 | 235 |  	 * the fault. | 
|---|
| 237 | 236 |  	 */ | 
|---|
| 238 |  | -	fault = handle_mm_fault(vma, address, flags);  | 
|---|
 | 237 | +	fault = handle_mm_fault(vma, address, flags, regs);  | 
|---|
| 239 | 238 |   | 
|---|
| 240 |  | -	if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))  | 
|---|
 | 239 | +	if (fault_signal_pending(fault, regs))  | 
|---|
| 241 | 240 |  		return; | 
|---|
| 242 | 241 |   | 
|---|
| 243 | 242 |  	if (unlikely(fault & VM_FAULT_ERROR)) { | 
|---|
| .. | .. | 
|---|
| 251 | 250 |  	} | 
|---|
| 252 | 251 |   | 
|---|
| 253 | 252 |  	if (flags & FAULT_FLAG_ALLOW_RETRY) { | 
|---|
| 254 |  | -		if (fault & VM_FAULT_MAJOR) {  | 
|---|
| 255 |  | -			current->maj_flt++;  | 
|---|
| 256 |  | -			perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ,  | 
|---|
| 257 |  | -				      1, regs, address);  | 
|---|
| 258 |  | -		} else {  | 
|---|
| 259 |  | -			current->min_flt++;  | 
|---|
| 260 |  | -			perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN,  | 
|---|
| 261 |  | -				      1, regs, address);  | 
|---|
| 262 |  | -		}  | 
|---|
| 263 | 253 |  		if (fault & VM_FAULT_RETRY) { | 
|---|
| 264 |  | -			flags &= ~FAULT_FLAG_ALLOW_RETRY;  | 
|---|
| 265 | 254 |  			flags |= FAULT_FLAG_TRIED; | 
|---|
| 266 | 255 |   | 
|---|
| 267 |  | -			/* No need to up_read(&mm->mmap_sem) as we would  | 
|---|
 | 256 | +			/* No need to mmap_read_unlock(mm) as we would  | 
|---|
| 268 | 257 |  			 * have already released it in __lock_page_or_retry | 
|---|
| 269 | 258 |  			 * in mm/filemap.c. | 
|---|
| 270 | 259 |  			 */ | 
|---|
| .. | .. | 
|---|
| 273 | 262 |  		} | 
|---|
| 274 | 263 |  	} | 
|---|
| 275 | 264 |   | 
|---|
| 276 |  | -	up_read(&mm->mmap_sem);  | 
|---|
 | 265 | +	mmap_read_unlock(mm);  | 
|---|
| 277 | 266 |  	return; | 
|---|
| 278 | 267 |   | 
|---|
| 279 | 268 |  	/* | 
|---|
| .. | .. | 
|---|
| 281 | 270 |  	 * Fix it, but check if it's kernel or user first.. | 
|---|
| 282 | 271 |  	 */ | 
|---|
| 283 | 272 |  bad_area: | 
|---|
| 284 |  | -	up_read(&mm->mmap_sem);  | 
|---|
 | 273 | +	mmap_read_unlock(mm);  | 
|---|
| 285 | 274 |   | 
|---|
| 286 | 275 |  bad_area_nosemaphore: | 
|---|
| 287 | 276 |  	/* User mode accesses just cause a SIGSEGV */ | 
|---|
| .. | .. | 
|---|
| 299 | 288 |  		if (fixup > 10) { | 
|---|
| 300 | 289 |  			extern const unsigned int __memset_start[]; | 
|---|
| 301 | 290 |  			extern const unsigned int __memset_end[]; | 
|---|
| 302 |  | -			extern const unsigned int __csum_partial_copy_start[];  | 
|---|
| 303 |  | -			extern const unsigned int __csum_partial_copy_end[];  | 
|---|
| 304 | 291 |   | 
|---|
| 305 | 292 |  #ifdef DEBUG_EXCEPTIONS | 
|---|
| 306 | 293 |  			printk("Exception: PC<%08lx> faddr<%08lx>\n", | 
|---|
| .. | .. | 
|---|
| 309 | 296 |  				regs->pc, fixup, g2); | 
|---|
| 310 | 297 |  #endif | 
|---|
| 311 | 298 |  			if ((regs->pc >= (unsigned long)__memset_start && | 
|---|
| 312 |  | -			     regs->pc < (unsigned long)__memset_end) ||  | 
|---|
| 313 |  | -			    (regs->pc >= (unsigned long)__csum_partial_copy_start &&  | 
|---|
| 314 |  | -			     regs->pc < (unsigned long)__csum_partial_copy_end)) {  | 
|---|
 | 299 | +			     regs->pc < (unsigned long)__memset_end)) {  | 
|---|
| 315 | 300 |  				regs->u_regs[UREG_I4] = address; | 
|---|
| 316 | 301 |  				regs->u_regs[UREG_I5] = regs->pc; | 
|---|
| 317 | 302 |  			} | 
|---|
| .. | .. | 
|---|
| 330 | 315 |   * us unable to handle the page fault gracefully. | 
|---|
| 331 | 316 |   */ | 
|---|
| 332 | 317 |  out_of_memory: | 
|---|
| 333 |  | -	up_read(&mm->mmap_sem);  | 
|---|
 | 318 | +	mmap_read_unlock(mm);  | 
|---|
| 334 | 319 |  	if (from_user) { | 
|---|
| 335 | 320 |  		pagefault_out_of_memory(); | 
|---|
| 336 | 321 |  		return; | 
|---|
| .. | .. | 
|---|
| 338 | 323 |  	goto no_context; | 
|---|
| 339 | 324 |   | 
|---|
| 340 | 325 |  do_sigbus: | 
|---|
| 341 |  | -	up_read(&mm->mmap_sem);  | 
|---|
 | 326 | +	mmap_read_unlock(mm);  | 
|---|
| 342 | 327 |  	do_fault_siginfo(BUS_ADRERR, SIGBUS, regs, text_fault); | 
|---|
| 343 | 328 |  	if (!from_user) | 
|---|
| 344 | 329 |  		goto no_context; | 
|---|
| .. | .. | 
|---|
| 351 | 336 |  		 */ | 
|---|
| 352 | 337 |  		int offset = pgd_index(address); | 
|---|
| 353 | 338 |  		pgd_t *pgd, *pgd_k; | 
|---|
 | 339 | +		p4d_t *p4d, *p4d_k;  | 
|---|
 | 340 | +		pud_t *pud, *pud_k;  | 
|---|
| 354 | 341 |  		pmd_t *pmd, *pmd_k; | 
|---|
| 355 | 342 |   | 
|---|
| 356 | 343 |  		pgd = tsk->active_mm->pgd + offset; | 
|---|
| .. | .. | 
|---|
| 363 | 350 |  			return; | 
|---|
| 364 | 351 |  		} | 
|---|
| 365 | 352 |   | 
|---|
| 366 |  | -		pmd = pmd_offset(pgd, address);  | 
|---|
| 367 |  | -		pmd_k = pmd_offset(pgd_k, address);  | 
|---|
 | 353 | +		p4d = p4d_offset(pgd, address);  | 
|---|
 | 354 | +		pud = pud_offset(p4d, address);  | 
|---|
 | 355 | +		pmd = pmd_offset(pud, address);  | 
|---|
 | 356 | +  | 
|---|
 | 357 | +		p4d_k = p4d_offset(pgd_k, address);  | 
|---|
 | 358 | +		pud_k = pud_offset(p4d_k, address);  | 
|---|
 | 359 | +		pmd_k = pmd_offset(pud_k, address);  | 
|---|
| 368 | 360 |   | 
|---|
| 369 | 361 |  		if (pmd_present(*pmd) || !pmd_present(*pmd_k)) | 
|---|
| 370 | 362 |  			goto bad_area_nosemaphore; | 
|---|
| .. | .. | 
|---|
| 385 | 377 |   | 
|---|
| 386 | 378 |  	code = SEGV_MAPERR; | 
|---|
| 387 | 379 |   | 
|---|
| 388 |  | -	down_read(&mm->mmap_sem);  | 
|---|
 | 380 | +	mmap_read_lock(mm);  | 
|---|
| 389 | 381 |  	vma = find_vma(mm, address); | 
|---|
| 390 | 382 |  	if (!vma) | 
|---|
| 391 | 383 |  		goto bad_area; | 
|---|
| .. | .. | 
|---|
| 405 | 397 |  		if (!(vma->vm_flags & (VM_READ | VM_EXEC))) | 
|---|
| 406 | 398 |  			goto bad_area; | 
|---|
| 407 | 399 |  	} | 
|---|
| 408 |  | -	switch (handle_mm_fault(vma, address, flags)) {  | 
|---|
 | 400 | +	switch (handle_mm_fault(vma, address, flags, NULL)) {  | 
|---|
| 409 | 401 |  	case VM_FAULT_SIGBUS: | 
|---|
| 410 | 402 |  	case VM_FAULT_OOM: | 
|---|
| 411 | 403 |  		goto do_sigbus; | 
|---|
| 412 | 404 |  	} | 
|---|
| 413 |  | -	up_read(&mm->mmap_sem);  | 
|---|
 | 405 | +	mmap_read_unlock(mm);  | 
|---|
| 414 | 406 |  	return; | 
|---|
| 415 | 407 |  bad_area: | 
|---|
| 416 |  | -	up_read(&mm->mmap_sem);  | 
|---|
 | 408 | +	mmap_read_unlock(mm);  | 
|---|
| 417 | 409 |  	__do_fault_siginfo(code, SIGSEGV, tsk->thread.kregs, address); | 
|---|
| 418 | 410 |  	return; | 
|---|
| 419 | 411 |   | 
|---|
| 420 | 412 |  do_sigbus: | 
|---|
| 421 |  | -	up_read(&mm->mmap_sem);  | 
|---|
 | 413 | +	mmap_read_unlock(mm);  | 
|---|
| 422 | 414 |  	__do_fault_siginfo(BUS_ADRERR, SIGBUS, tsk->thread.kregs, address); | 
|---|
| 423 | 415 |  } | 
|---|
| 424 | 416 |   | 
|---|
| 425 | 417 |  static void check_stack_aligned(unsigned long sp) | 
|---|
| 426 | 418 |  { | 
|---|
| 427 | 419 |  	if (sp & 0x7UL) | 
|---|
| 428 |  | -		force_sig(SIGILL, current);  | 
|---|
 | 420 | +		force_sig(SIGILL);  | 
|---|
| 429 | 421 |  } | 
|---|
| 430 | 422 |   | 
|---|
| 431 | 423 |  void window_overflow_fault(void) | 
|---|