2009-05-26 16:30:13 +02:00
/*
* arch / microblaze / mm / fault . c
*
* Copyright ( C ) 2007 Xilinx , Inc . All rights reserved .
*
* Derived from " arch/ppc/mm/fault.c "
* Copyright ( C ) 1995 - 1996 Gary Thomas ( gdt @ linuxppc . org )
*
* Derived from " arch/i386/mm/fault.c "
* Copyright ( C ) 1991 , 1992 , 1993 , 1994 Linus Torvalds
*
* Modified by Cort Dougan and Paul Mackerras .
*
* This file is subject to the terms and conditions of the GNU General
* Public License . See the file COPYING in the main directory of this
* archive for more details .
*
*/
# include <linux/module.h>
# include <linux/signal.h>
# include <linux/sched.h>
# include <linux/kernel.h>
# include <linux/errno.h>
# include <linux/string.h>
# include <linux/types.h>
# include <linux/ptrace.h>
# include <linux/mman.h>
# include <linux/mm.h>
# include <linux/interrupt.h>
# include <asm/page.h>
# include <asm/pgtable.h>
# include <asm/mmu.h>
# include <asm/mmu_context.h>
# include <asm/system.h>
# include <linux/uaccess.h>
# include <asm/exceptions.h>
# if defined(CONFIG_KGDB)
int debugger_kernel_faults = 1 ;
# endif
static unsigned long pte_misses ; /* updated by do_page_fault() */
static unsigned long pte_errors ; /* updated by do_page_fault() */
/*
* Check whether the instruction at regs - > pc is a store using
* an update addressing form which will update r1 .
*/
static int store_updates_sp ( struct pt_regs * regs )
{
unsigned int inst ;
if ( get_user ( inst , ( unsigned int * ) regs - > pc ) )
return 0 ;
/* check for 1 in the rD field */
if ( ( ( inst > > 21 ) & 0x1f ) ! = 1 )
return 0 ;
/* check for store opcodes */
if ( ( inst & 0xd0000000 ) = = 0xd0000000 )
return 1 ;
return 0 ;
}
/*
* bad_page_fault is called when we have a bad access from the kernel .
* It is called from do_page_fault above and from some of the procedures
* in traps . c .
*/
2009-07-21 12:48:01 +02:00
void bad_page_fault ( struct pt_regs * regs , unsigned long address , int sig )
2009-05-26 16:30:13 +02:00
{
const struct exception_table_entry * fixup ;
/* MS: no context */
/* Are we prepared to handle this fault? */
fixup = search_exception_tables ( regs - > pc ) ;
if ( fixup ) {
regs - > pc = fixup - > fixup ;
return ;
}
/* kernel has accessed a bad area */
# if defined(CONFIG_KGDB)
if ( debugger_kernel_faults )
debugger ( regs ) ;
# endif
die ( " kernel access of bad area " , regs , sig ) ;
}
/*
* The error_code parameter is ESR for a data fault ,
* 0 for an instruction fault .
*/
void do_page_fault ( struct pt_regs * regs , unsigned long address ,
unsigned long error_code )
{
struct vm_area_struct * vma ;
struct mm_struct * mm = current - > mm ;
siginfo_t info ;
int code = SEGV_MAPERR ;
int is_write = error_code & ESR_S ;
int fault ;
regs - > ear = address ;
regs - > esr = error_code ;
/* On a kernel SLB miss we can only check for a valid exception entry */
2010-03-23 15:37:02 +01:00
if ( unlikely ( kernel_mode ( regs ) & & ( address > = TASK_SIZE ) ) ) {
2009-05-26 16:30:13 +02:00
printk ( KERN_WARNING " kernel task_size exceed " ) ;
_exception ( SIGSEGV , regs , code , address ) ;
}
/* for instr TLB miss and instr storage exception ESR_S is undefined */
if ( ( error_code & 0x13 ) = = 0x13 | | ( error_code & 0x11 ) = = 0x11 )
is_write = 0 ;
# if defined(CONFIG_KGDB)
if ( debugger_fault_handler & & regs - > trap = = 0x300 ) {
debugger_fault_handler ( regs ) ;
return ;
}
# endif /* CONFIG_KGDB */
2010-03-23 15:37:02 +01:00
if ( unlikely ( in_atomic ( ) | | ! mm ) ) {
2009-07-16 16:00:49 +02:00
if ( kernel_mode ( regs ) )
goto bad_area_nosemaphore ;
2009-05-26 16:30:13 +02:00
/* in_atomic() in user mode is really bad,
as is current - > mm = = NULL . */
printk ( KERN_EMERG " Page fault in user mode with "
" in_atomic(), mm = %p \n " , mm ) ;
printk ( KERN_EMERG " r15 = %lx MSR = %lx \n " ,
regs - > r15 , regs - > msr ) ;
die ( " Weird page fault " , regs , SIGSEGV ) ;
}
/* When running in the kernel we expect faults to occur only to
* addresses in user space . All other faults represent errors in the
* kernel and should generate an OOPS . Unfortunately , in the case of an
* erroneous fault occurring in a code path which already holds mmap_sem
* we will deadlock attempting to validate the fault against the
* address space . Luckily the kernel only validly references user
* space from well defined areas of code , which are listed in the
* exceptions table .
*
* As the vast majority of faults will be valid we will only perform
* the source reference check when there is a possibility of a deadlock .
* Attempt to lock the address space , if we cannot we then validate the
* source . If this is invalid we can skip the address space check ,
* thus avoiding the deadlock .
*/
2010-03-23 15:37:02 +01:00
if ( unlikely ( ! down_read_trylock ( & mm - > mmap_sem ) ) ) {
2009-05-26 16:30:13 +02:00
if ( kernel_mode ( regs ) & & ! search_exception_tables ( regs - > pc ) )
goto bad_area_nosemaphore ;
down_read ( & mm - > mmap_sem ) ;
}
vma = find_vma ( mm , address ) ;
2010-03-23 15:37:02 +01:00
if ( unlikely ( ! vma ) )
2009-05-26 16:30:13 +02:00
goto bad_area ;
if ( vma - > vm_start < = address )
goto good_area ;
2010-03-23 15:37:02 +01:00
if ( unlikely ( ! ( vma - > vm_flags & VM_GROWSDOWN ) ) )
2009-05-26 16:30:13 +02:00
goto bad_area ;
2010-03-23 15:37:02 +01:00
if ( unlikely ( ! is_write ) )
2009-05-26 16:30:13 +02:00
goto bad_area ;
/*
* N . B . The ABI allows programs to access up to
* a few hundred bytes below the stack pointer ( TBD ) .
* The kernel signal delivery code writes up to about 1.5 kB
* below the stack pointer ( r1 ) before decrementing it .
* The exec code can write slightly over 640 kB to the stack
* before setting the user r1 . Thus we allow the stack to
* expand to 1 MB without further checks .
*/
2010-03-23 15:37:02 +01:00
if ( unlikely ( address + 0x100000 < vma - > vm_end ) ) {
2009-05-26 16:30:13 +02:00
/* get user regs even if this fault is in kernel mode */
struct pt_regs * uregs = current - > thread . regs ;
if ( uregs = = NULL )
goto bad_area ;
/*
* A user - mode access to an address a long way below
* the stack pointer is only valid if the instruction
* is one which would update the stack pointer to the
* address accessed if the instruction completed ,
* i . e . either stwu rs , n ( r1 ) or stwux rs , r1 , rb
* ( or the byte , halfword , float or double forms ) .
*
* If we don ' t check this then any write to the area
* between the last mapped region and the stack will
* expand the stack rather than segfaulting .
*/
if ( address + 2048 < uregs - > r1
& & ( kernel_mode ( regs ) | | ! store_updates_sp ( regs ) ) )
goto bad_area ;
}
if ( expand_stack ( vma , address ) )
goto bad_area ;
good_area :
code = SEGV_ACCERR ;
/* a write */
2010-03-23 15:37:02 +01:00
if ( unlikely ( is_write ) ) {
if ( unlikely ( ! ( vma - > vm_flags & VM_WRITE ) ) )
2009-05-26 16:30:13 +02:00
goto bad_area ;
/* a read */
} else {
/* protection fault */
2010-03-23 15:37:02 +01:00
if ( unlikely ( error_code & 0x08000000 ) )
2009-05-26 16:30:13 +02:00
goto bad_area ;
2010-03-23 15:37:02 +01:00
if ( unlikely ( ! ( vma - > vm_flags & ( VM_READ | VM_EXEC ) ) ) )
2009-05-26 16:30:13 +02:00
goto bad_area ;
}
/*
* If for any reason at all we couldn ' t handle the fault ,
* make sure we exit gracefully rather than endlessly redo
* the fault .
*/
survive :
2009-04-10 09:01:23 -07:00
fault = handle_mm_fault ( mm , vma , address , is_write ? FAULT_FLAG_WRITE : 0 ) ;
2009-05-26 16:30:13 +02:00
if ( unlikely ( fault & VM_FAULT_ERROR ) ) {
if ( fault & VM_FAULT_OOM )
goto out_of_memory ;
else if ( fault & VM_FAULT_SIGBUS )
goto do_sigbus ;
BUG ( ) ;
}
2010-03-23 15:37:02 +01:00
if ( unlikely ( fault & VM_FAULT_MAJOR ) )
2009-05-26 16:30:13 +02:00
current - > maj_flt + + ;
else
current - > min_flt + + ;
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 ( )
* - - Cort
*/
pte_misses + + ;
return ;
bad_area :
up_read ( & mm - > mmap_sem ) ;
bad_area_nosemaphore :
pte_errors + + ;
/* User mode accesses cause a SIGSEGV */
if ( user_mode ( regs ) ) {
_exception ( SIGSEGV , regs , code , address ) ;
/* info.si_signo = SIGSEGV;
info . si_errno = 0 ;
info . si_code = code ;
info . si_addr = ( void * ) address ;
force_sig_info ( SIGSEGV , & info , current ) ; */
return ;
}
bad_page_fault ( regs , address , SIGSEGV ) ;
return ;
/*
* 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 ) ;
2010-04-23 02:06:21 +10:00
if ( ! user_mode ( regs ) )
bad_page_fault ( regs , address , SIGKILL ) ;
else
pagefault_out_of_memory ( ) ;
2009-05-26 16:30:13 +02:00
return ;
do_sigbus :
up_read ( & mm - > mmap_sem ) ;
if ( user_mode ( regs ) ) {
info . si_signo = SIGBUS ;
info . si_errno = 0 ;
info . si_code = BUS_ADRERR ;
info . si_addr = ( void __user * ) address ;
force_sig_info ( SIGBUS , & info , current ) ;
return ;
}
bad_page_fault ( regs , address , SIGBUS ) ;
}