@ -92,6 +92,8 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
int code = SEGV_MAPERR ;
int is_write = error_code & ESR_S ;
int fault ;
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
( is_write ? FAULT_FLAG_WRITE : 0 ) ;
regs - > ear = address ;
regs - > esr = error_code ;
@ -138,6 +140,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
if ( kernel_mode ( regs ) & & ! search_exception_tables ( regs - > pc ) )
goto bad_area_nosemaphore ;
retry :
down_read ( & mm - > mmap_sem ) ;
}
@ -210,7 +213,11 @@ good_area:
* make sure we exit gracefully rather than endlessly redo
* the fault .
*/
fault = handle_mm_fault ( mm , vma , address , is_write ? FAULT_FLAG_WRITE : 0 ) ;
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 ;
@ -218,11 +225,27 @@ good_area:
goto do_sigbus ;
BUG ( ) ;
}
if ( unlikely ( fault & VM_FAULT_MAJOR ) )
current - > maj_flt + + ;
else
current - > min_flt + + ;
if ( flags & FAULT_FLAG_ALLOW_RETRY ) {
if ( unlikely ( 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 ) ;
/*
* keep track of tlb + htab misses that are good addrs but
* just need pte ' s created via handle_mm_fault ( )