diff options
| author | Olof Johansson <olof@lixom.net> | 2012-09-05 15:35:48 -0700 | 
|---|---|---|
| committer | Olof Johansson <olof@lixom.net> | 2012-09-05 15:35:48 -0700 | 
| commit | 1875962377574b4edb7b164001e3e341c25290d5 (patch) | |
| tree | 374a5299403ec21e2d9a66a6548ce876a388b589 /arch/alpha/mm/fault.c | |
| parent | 5cbee140a28c2746449ae31e85738043ae4da927 (diff) | |
| parent | c88a79a7789b2909ad1cf69ea2c9142030bbd6f4 (diff) | |
| download | olio-linux-3.10-1875962377574b4edb7b164001e3e341c25290d5.tar.xz olio-linux-3.10-1875962377574b4edb7b164001e3e341c25290d5.zip  | |
Merge branch 'soc-core' of git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas into next/dt
* 'soc-core' of git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas:
  ARM: mach-shmobile: Add compilation support for dtbs using 'make dtbs'
  + sync to 3.6-rc3
Diffstat (limited to 'arch/alpha/mm/fault.c')
| -rw-r--r-- | arch/alpha/mm/fault.c | 36 | 
1 files changed, 30 insertions, 6 deletions
diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c index 5eecab1a84e..0c4132dd350 100644 --- a/arch/alpha/mm/fault.c +++ b/arch/alpha/mm/fault.c @@ -89,6 +89,8 @@ do_page_fault(unsigned long address, unsigned long mmcsr,  	const struct exception_table_entry *fixup;  	int fault, si_code = SEGV_MAPERR;  	siginfo_t info; +	unsigned int flags = (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | +			      (cause > 0 ? FAULT_FLAG_WRITE : 0));  	/* As of EV6, a load into $31/$f31 is a prefetch, and never faults  	   (or is suppressed by the PALcode).  Support that for older CPUs @@ -114,6 +116,7 @@ do_page_fault(unsigned long address, unsigned long mmcsr,  		goto vmalloc_fault;  #endif +retry:  	down_read(&mm->mmap_sem);  	vma = find_vma(mm, address);  	if (!vma) @@ -144,8 +147,11 @@ do_page_fault(unsigned long address, unsigned long mmcsr,  	/* If for any reason at all we couldn't handle the fault,  	   make sure we exit gracefully rather than endlessly redo  	   the fault.  */ -	fault = handle_mm_fault(mm, vma, address, cause > 0 ? FAULT_FLAG_WRITE : 0); -	up_read(&mm->mmap_sem); +	fault = handle_mm_fault(mm, vma, address, flags); + +	if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) +		return; +  	if (unlikely(fault & VM_FAULT_ERROR)) {  		if (fault & VM_FAULT_OOM)  			goto out_of_memory; @@ -153,10 +159,26 @@ do_page_fault(unsigned long address, unsigned long mmcsr,  			goto do_sigbus;  		BUG();  	} -	if (fault & VM_FAULT_MAJOR) -		current->maj_flt++; -	else -		current->min_flt++; + +	if (flags & FAULT_FLAG_ALLOW_RETRY) { +		if (fault & VM_FAULT_MAJOR) +			current->maj_flt++; +		else +			current->min_flt++; +		if (fault & VM_FAULT_RETRY) { +			flags &= ~FAULT_FLAG_ALLOW_RETRY; + +			 /* No need to up_read(&mm->mmap_sem) as we would +			 * have already released it in __lock_page_or_retry +			 * in mm/filemap.c. +			 */ + +			goto retry; +		} +	} + +	up_read(&mm->mmap_sem); +  	return;  	/* Something tried to access memory that isn't in our memory map. @@ -186,12 +208,14 @@ do_page_fault(unsigned long address, unsigned long mmcsr,  	/* We ran out of memory, or some other thing happened to us that  	   made us unable to handle the page fault gracefully.  */   out_of_memory: +	up_read(&mm->mmap_sem);  	if (!user_mode(regs))  		goto no_context;  	pagefault_out_of_memory();  	return;   do_sigbus: +	up_read(&mm->mmap_sem);  	/* Send a sigbus, regardless of whether we were in kernel  	   or user mode.  */  	info.si_signo = SIGBUS;  |