2006-01-08 12:01:31 +03:00
/*
2007-10-16 12:27:00 +04:00
* Copyright ( C ) 2002 - 2007 Jeff Dike ( jdike @ { addtoit , linux . intel } . com )
2005-04-17 02:20:36 +04:00
* Licensed under the GPL
*/
2007-10-16 12:27:00 +04:00
#if 0
2005-04-17 02:20:36 +04:00
# include "kern_util.h"
[PATCH] uml: S390 preparation, abstract host page fault data
This patch removes the arch-specific fault/trap-infos from thread and
skas-regs.
It adds a new struct faultinfo, that is arch-specific defined in
sysdep/faultinfo.h.
The structure is inserted in thread.arch and thread.regs.skas and
thread.regs.tt
Now, segv and other trap-handlers can copy the contents from regs.X.faultinfo
to thread.arch.faultinfo with one simple assignment.
Also, the number of macros necessary is reduced to
FAULT_ADDRESS(struct faultinfo)
extracts the faulting address from faultinfo
FAULT_WRITE(struct faultinfo)
extracts the "is_write" flag
SEGV_IS_FIXABLE(struct faultinfo)
is true for the fixable segvs, i.e. (TRAP == 14)
on i386
UPT_FAULTINFO(regs)
result is (struct faultinfo *) to the faultinfo
in regs->skas.faultinfo
GET_FAULTINFO_FROM_SC(struct faultinfo, struct sigcontext *)
copies the relevant parts of the sigcontext to
struct faultinfo.
On SIGSEGV, call user_signal() instead of handle_segv(), if the architecture
provides the information needed in PTRACE_FAULTINFO, or if PTRACE_FAULTINFO is
missing, because segv-stub will provide the info.
The benefit of the change is, that in case of a non-fixable SIGSEGV, we can
give user processes a SIGSEGV, instead of possibly looping on pagefault
handling.
Since handle_segv() sikked arch_fixup() implicitly by passing ip==0 to segv(),
I changed segv() to call arch_fixup() only, if !is_user.
Signed-off-by: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-05-06 03:15:31 +04:00
# include "skas.h"
# include "ptrace_user.h"
# include "sysdep/ptrace_user.h"
2007-10-16 12:27:00 +04:00
# endif
# include <errno.h>
# include <signal.h>
# include "sysdep/ptrace.h"
# include "kern_constants.h"
# include "as-layout.h"
2006-01-08 12:01:29 +03:00
# include "os.h"
2007-10-16 12:27:00 +04:00
# include "sigcontext.h"
# include "task.h"
2005-04-17 02:20:36 +04:00
2007-10-16 12:26:58 +04:00
static struct uml_pt_regs ksig_regs [ UM_NR_CPUS ] ;
2007-05-07 01:51:25 +04:00
2005-04-17 02:20:36 +04:00
void sig_handler_common_skas ( int sig , void * sc_ptr )
{
struct sigcontext * sc = sc_ptr ;
2007-10-16 12:26:58 +04:00
struct uml_pt_regs * r ;
void ( * handler ) ( int , struct uml_pt_regs * ) ;
2007-05-07 01:51:24 +04:00
int save_user , save_errno = errno ;
2005-04-17 02:20:36 +04:00
2007-10-16 12:27:00 +04:00
/*
* This is done because to allow SIGSEGV to be delivered inside a SEGV
2005-04-17 02:20:36 +04:00
* handler . This can happen in copy_user , and if SEGV is disabled ,
* the process will die .
* XXX Figure out why this is better than SA_NODEFER
*/
2007-10-16 12:27:00 +04:00
if ( sig = = SIGSEGV ) {
2005-04-17 02:20:36 +04:00
change_sig ( SIGSEGV , 1 ) ;
2007-10-16 12:27:00 +04:00
/*
* For segfaults , we want the data from the
2007-05-07 01:51:25 +04:00
* sigcontext . In this case , we don ' t want to mangle
* the process registers , so use a static set of
* registers . For other signals , the process
* registers are OK .
*/
r = & ksig_regs [ cpu ( ) ] ;
copy_sc ( r , sc_ptr ) ;
}
else r = TASK_REGS ( get_current ( ) ) ;
2005-04-17 02:20:36 +04:00
2007-10-16 12:26:58 +04:00
save_user = r - > is_user ;
r - > is_user = 0 ;
2007-10-16 12:27:00 +04:00
if ( ( sig = = SIGFPE ) | | ( sig = = SIGSEGV ) | | ( sig = = SIGBUS ) | |
( sig = = SIGILL ) | | ( sig = = SIGTRAP ) )
2007-10-16 12:26:58 +04:00
GET_FAULTINFO_FROM_SC ( r - > faultinfo , sc ) ;
2005-04-17 02:20:36 +04:00
change_sig ( SIGUSR1 , 1 ) ;
2006-01-08 12:01:31 +03:00
handler = sig_info [ sig ] ;
/* unblock SIGALRM, SIGVTALRM, SIGIO if sig isn't IRQ signal */
if ( sig ! = SIGIO & & sig ! = SIGWINCH & &
sig ! = SIGVTALRM & & sig ! = SIGALRM )
unblock_signals ( ) ;
2007-05-07 01:51:24 +04:00
handler ( sig , r ) ;
2005-04-17 02:20:36 +04:00
errno = save_errno ;
2007-10-16 12:26:58 +04:00
r - > is_user = save_user ;
2005-04-17 02:20:36 +04:00
}