2005-06-24 09:01:16 +04:00
/*
2007-06-01 04:49:32 +04:00
* arch / xtensa / kernel / signal . c
2005-06-24 09:01:16 +04:00
*
2007-06-01 04:49:32 +04:00
* Default platform functions .
2005-06-24 09:01:16 +04:00
*
2007-06-01 04:49:32 +04:00
* 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 .
2005-06-24 09:01:16 +04:00
*
2007-06-01 04:49:32 +04:00
* Copyright ( C ) 2005 , 2006 Tensilica Inc .
* Copyright ( C ) 1991 , 1992 Linus Torvalds
* 1997 - 11 - 28 Modified for POSIX .1 b signals by Richard Henderson
2005-06-24 09:01:16 +04:00
*
2007-06-01 04:49:32 +04:00
* Chris Zankel < chris @ zankel . net >
* Joe Taylor < joe @ tensilica . com >
2005-06-24 09:01:16 +04:00
*/
# include <linux/signal.h>
# include <linux/errno.h>
# include <linux/ptrace.h>
# include <linux/personality.h>
2012-04-24 10:30:16 +04:00
# include <linux/tracehook.h>
2017-02-08 20:51:37 +03:00
# include <linux/sched/task_stack.h>
2007-06-01 04:49:32 +04:00
2005-06-24 09:01:16 +04:00
# include <asm/ucontext.h>
2016-12-24 22:46:01 +03:00
# include <linux/uaccess.h>
2005-06-24 09:01:16 +04:00
# include <asm/cacheflush.h>
2007-06-01 04:49:32 +04:00
# include <asm/coprocessor.h>
# include <asm/unistd.h>
2005-06-24 09:01:16 +04:00
# define DEBUG_SIG 0
extern struct task_struct * coproc_owners [ ] ;
2007-06-01 04:49:32 +04:00
struct rt_sigframe
{
struct siginfo info ;
struct ucontext uc ;
2008-02-13 00:17:07 +03:00
struct {
xtregs_opt_t opt ;
xtregs_user_t user ;
# if XTENSA_HAVE_COPROCESSORS
xtregs_coprocessor_t cp ;
# endif
} xtregs ;
2007-06-01 04:49:32 +04:00
unsigned char retcode [ 6 ] ;
unsigned int window [ 4 ] ;
} ;
/*
* Flush register windows stored in pt_regs to stack .
* Returns 1 for errors .
2005-06-24 09:01:16 +04:00
*/
2007-06-01 04:49:32 +04:00
int
flush_window_regs_user ( struct pt_regs * regs )
2005-06-24 09:01:16 +04:00
{
2007-06-01 04:49:32 +04:00
const unsigned long ws = regs - > windowstart ;
const unsigned long wb = regs - > windowbase ;
unsigned long sp = 0 ;
unsigned long wm ;
int err = 1 ;
int base ;
2005-06-24 09:01:16 +04:00
2007-06-01 04:49:32 +04:00
/* Return if no other frames. */
2005-06-24 09:01:16 +04:00
2007-06-01 04:49:32 +04:00
if ( regs - > wmask = = 1 )
return 0 ;
2005-06-24 09:01:16 +04:00
2007-06-01 04:49:32 +04:00
/* Rotate windowmask and skip empty frames. */
2005-06-24 09:01:16 +04:00
2007-06-01 04:49:32 +04:00
wm = ( ws > > wb ) | ( ws < < ( XCHAL_NUM_AREGS / 4 - wb ) ) ;
base = ( XCHAL_NUM_AREGS / 4 ) - ( regs - > wmask > > 4 ) ;
/* For call8 or call12 frames, we need the previous stack pointer. */
2005-06-24 09:01:16 +04:00
2007-06-01 04:49:32 +04:00
if ( ( regs - > wmask & 2 ) = = 0 )
if ( __get_user ( sp , ( int * ) ( regs - > areg [ base * 4 + 1 ] - 12 ) ) )
goto errout ;
2005-06-24 09:01:16 +04:00
2007-06-01 04:49:32 +04:00
/* Spill frames to stack. */
2005-06-24 09:01:16 +04:00
2007-06-01 04:49:32 +04:00
while ( base < XCHAL_NUM_AREGS / 4 ) {
2005-06-24 09:01:16 +04:00
2007-06-01 04:49:32 +04:00
int m = ( wm > > base ) ;
int inc = 0 ;
2005-06-24 09:01:16 +04:00
2007-06-01 04:49:32 +04:00
/* Save registers a4..a7 (call8) or a4...a11 (call12) */
2005-06-24 09:01:16 +04:00
2007-06-01 04:49:32 +04:00
if ( m & 2 ) { /* call4 */
inc = 1 ;
2005-06-24 09:01:16 +04:00
2007-06-01 04:49:32 +04:00
} else if ( m & 4 ) { /* call8 */
2015-01-27 01:15:10 +03:00
if ( copy_to_user ( & SPILL_SLOT_CALL8 ( sp , 4 ) ,
& regs - > areg [ ( base + 1 ) * 4 ] , 16 ) )
2007-06-01 04:49:32 +04:00
goto errout ;
inc = 2 ;
2005-06-24 09:01:16 +04:00
2007-06-01 04:49:32 +04:00
} else if ( m & 8 ) { /* call12 */
2015-01-27 01:15:10 +03:00
if ( copy_to_user ( & SPILL_SLOT_CALL12 ( sp , 4 ) ,
& regs - > areg [ ( base + 1 ) * 4 ] , 32 ) )
2007-06-01 04:49:32 +04:00
goto errout ;
inc = 3 ;
}
2005-06-24 09:01:16 +04:00
2007-06-01 04:49:32 +04:00
/* Save current frame a0..a3 under next SP */
2005-06-24 09:01:16 +04:00
2007-06-01 04:49:32 +04:00
sp = regs - > areg [ ( ( base + inc ) * 4 + 1 ) % XCHAL_NUM_AREGS ] ;
2015-01-27 01:15:10 +03:00
if ( copy_to_user ( & SPILL_SLOT ( sp , 0 ) , & regs - > areg [ base * 4 ] , 16 ) )
2007-06-01 04:49:32 +04:00
goto errout ;
/* Get current stack pointer for next loop iteration. */
sp = regs - > areg [ base * 4 + 1 ] ;
base + = inc ;
}
2008-02-12 23:22:15 +03:00
regs - > wmask = 1 ;
regs - > windowstart = 1 < < wb ;
2007-06-01 04:49:32 +04:00
return 0 ;
2005-06-24 09:01:16 +04:00
2007-06-01 04:49:32 +04:00
errout :
return err ;
}
2005-06-24 09:01:16 +04:00
/*
2007-06-01 04:49:32 +04:00
* Note : We don ' t copy double exception ' regs ' , we have to finish double exc .
* first before we return to signal handler ! This dbl . exc . handler might cause
* another double exception , but I think we are fine as the situation is the
* same as if we had returned to the signal handerl and got an interrupt
* immediately . . .
2005-06-24 09:01:16 +04:00
*/
2007-06-01 04:49:32 +04:00
static int
2008-02-13 00:17:07 +03:00
setup_sigcontext ( struct rt_sigframe __user * frame , struct pt_regs * regs )
2005-06-24 09:01:16 +04:00
{
2008-02-13 00:17:07 +03:00
struct sigcontext __user * sc = & frame - > uc . uc_mcontext ;
struct thread_info * ti = current_thread_info ( ) ;
2007-06-01 04:49:32 +04:00
int err = 0 ;
2005-06-24 09:01:16 +04:00
2007-06-01 04:49:32 +04:00
# define COPY(x) err |= __put_user(regs->x, &sc->sc_##x)
COPY ( pc ) ;
COPY ( ps ) ;
COPY ( lbeg ) ;
COPY ( lend ) ;
COPY ( lcount ) ;
COPY ( sar ) ;
# undef COPY
2005-06-24 09:01:16 +04:00
2007-06-01 04:49:32 +04:00
err | = flush_window_regs_user ( regs ) ;
err | = __copy_to_user ( sc - > sc_a , regs - > areg , 16 * 4 ) ;
2008-02-13 00:17:07 +03:00
err | = __put_user ( 0 , & sc - > sc_xtregs ) ;
2005-06-24 09:01:16 +04:00
2008-02-13 00:17:07 +03:00
if ( err )
return err ;
2005-06-24 09:01:16 +04:00
2008-02-13 00:17:07 +03:00
# if XTENSA_HAVE_COPROCESSORS
coprocessor_flush_all ( ti ) ;
coprocessor_release_all ( ti ) ;
err | = __copy_to_user ( & frame - > xtregs . cp , & ti - > xtregs_cp ,
sizeof ( frame - > xtregs . cp ) ) ;
2005-06-24 09:01:16 +04:00
# endif
2008-02-13 00:17:07 +03:00
err | = __copy_to_user ( & frame - > xtregs . opt , & regs - > xtregs_opt ,
sizeof ( xtregs_opt_t ) ) ;
err | = __copy_to_user ( & frame - > xtregs . user , & ti - > xtregs_user ,
sizeof ( xtregs_user_t ) ) ;
err | = __put_user ( err ? NULL : & frame - > xtregs , & sc - > sc_xtregs ) ;
2005-06-24 09:01:16 +04:00
2007-06-01 04:49:32 +04:00
return err ;
}
2005-06-24 09:01:16 +04:00
static int
2008-02-13 00:17:07 +03:00
restore_sigcontext ( struct pt_regs * regs , struct rt_sigframe __user * frame )
2005-06-24 09:01:16 +04:00
{
2008-02-13 00:17:07 +03:00
struct sigcontext __user * sc = & frame - > uc . uc_mcontext ;
struct thread_info * ti = current_thread_info ( ) ;
2005-06-24 09:01:16 +04:00
unsigned int err = 0 ;
unsigned long ps ;
# define COPY(x) err |= __get_user(regs->x, &sc->sc_##x)
COPY ( pc ) ;
COPY ( lbeg ) ;
COPY ( lend ) ;
COPY ( lcount ) ;
COPY ( sar ) ;
# undef COPY
2007-06-01 04:49:32 +04:00
/* All registers were flushed to stack. Start with a prestine frame. */
regs - > wmask = 1 ;
regs - > windowbase = 0 ;
regs - > windowstart = 1 ;
2008-02-13 00:17:07 +03:00
regs - > syscall = - 1 ; /* disable syscall checks */
2005-06-24 09:01:16 +04:00
/* For PS, restore only PS.CALLINC.
* Assume that all other bits are either the same as for the signal
* handler , or the user mode value doesn ' t matter ( e . g . PS . OWB ) .
*/
err | = __get_user ( ps , & sc - > sc_ps ) ;
2007-06-01 04:49:32 +04:00
regs - > ps = ( regs - > ps & ~ PS_CALLINC_MASK ) | ( ps & PS_CALLINC_MASK ) ;
2005-06-24 09:01:16 +04:00
/* Additional corruption checks */
if ( ( regs - > lcount > 0 )
2007-06-01 04:49:32 +04:00
& & ( ( regs - > lbeg > TASK_SIZE ) | | ( regs - > lend > TASK_SIZE ) ) )
2005-06-24 09:01:16 +04:00
err = 1 ;
2007-06-01 04:49:32 +04:00
err | = __copy_from_user ( regs - > areg , sc - > sc_a , 16 * 4 ) ;
2005-06-24 09:01:16 +04:00
2008-02-13 00:17:07 +03:00
if ( err )
return err ;
2012-11-29 04:53:51 +04:00
/* The signal handler may have used coprocessors in which
2007-06-01 04:49:32 +04:00
* case they are still enabled . We disable them to force a
* reloading of the original task ' s CP state by the lazy
* context - switching mechanisms of CP exception handling .
* Also , we essentially discard any coprocessor state that the
* signal handler created . */
2005-06-24 09:01:16 +04:00
2008-02-13 00:17:07 +03:00
# if XTENSA_HAVE_COPROCESSORS
coprocessor_release_all ( ti ) ;
err | = __copy_from_user ( & ti - > xtregs_cp , & frame - > xtregs . cp ,
sizeof ( frame - > xtregs . cp ) ) ;
2005-06-24 09:01:16 +04:00
# endif
2008-02-13 00:17:07 +03:00
err | = __copy_from_user ( & ti - > xtregs_user , & frame - > xtregs . user ,
sizeof ( xtregs_user_t ) ) ;
err | = __copy_from_user ( & regs - > xtregs_opt , & frame - > xtregs . opt ,
sizeof ( xtregs_opt_t ) ) ;
2005-06-24 09:01:16 +04:00
return err ;
}
2007-06-01 04:49:32 +04:00
/*
* Do a signal return ; undo the signal stack .
*/
2005-06-24 09:01:16 +04:00
2007-06-01 04:49:32 +04:00
asmlinkage long xtensa_rt_sigreturn ( long a0 , long a1 , long a2 , long a3 ,
long a4 , long a5 , struct pt_regs * regs )
2005-06-24 09:01:16 +04:00
{
2007-06-01 04:49:32 +04:00
struct rt_sigframe __user * frame ;
2005-06-24 09:01:16 +04:00
sigset_t set ;
int ret ;
2007-06-01 04:49:32 +04:00
2012-04-22 11:35:28 +04:00
/* Always make any pending restarted system calls return -EINTR */
2015-02-13 02:01:14 +03:00
current - > restart_block . fn = do_no_restart_syscall ;
2012-04-22 11:35:28 +04:00
2005-06-24 09:01:16 +04:00
if ( regs - > depc > 64 )
2007-06-01 04:49:32 +04:00
panic ( " rt_sigreturn in double exception! \n " ) ;
frame = ( struct rt_sigframe __user * ) regs - > areg [ 1 ] ;
2005-06-24 09:01:16 +04:00
2006-06-23 13:05:04 +04:00
if ( ! access_ok ( VERIFY_READ , frame , sizeof ( * frame ) ) )
2005-06-24 09:01:16 +04:00
goto badframe ;
if ( __copy_from_user ( & set , & frame - > uc . uc_sigmask , sizeof ( set ) ) )
goto badframe ;
2012-03-22 03:33:45 +04:00
set_current_blocked ( & set ) ;
2005-06-24 09:01:16 +04:00
2008-02-13 00:17:07 +03:00
if ( restore_sigcontext ( regs , frame ) )
2005-06-24 09:01:16 +04:00
goto badframe ;
2007-06-01 04:49:32 +04:00
2005-06-24 09:01:16 +04:00
ret = regs - > areg [ 2 ] ;
2012-12-23 12:54:43 +04:00
if ( restore_altstack ( & frame - > uc . uc_stack ) )
2005-06-24 09:01:16 +04:00
goto badframe ;
return ret ;
badframe :
force_sig ( SIGSEGV , current ) ;
return 0 ;
}
2007-06-01 04:49:32 +04:00
2005-06-24 09:01:16 +04:00
/*
2007-06-01 04:49:32 +04:00
* Set up a signal frame .
2005-06-24 09:01:16 +04:00
*/
static int
2007-06-01 04:49:32 +04:00
gen_return_code ( unsigned char * codemem )
2005-06-24 09:01:16 +04:00
{
int err = 0 ;
2007-06-01 04:49:32 +04:00
/*
* The 12 - bit immediate is really split up within the 24 - bit MOVI
* instruction . As long as the above system call numbers fit within
* 8 - bits , the following code works fine . See the Xtensa ISA for
* details .
2005-06-24 09:01:16 +04:00
*/
2007-06-01 04:49:32 +04:00
# if __NR_rt_sigreturn > 255
# error Generating the MOVI instruction below breaks!
2005-06-24 09:01:16 +04:00
# endif
# ifdef __XTENSA_EB__ /* Big Endian version */
2007-06-01 04:49:32 +04:00
/* Generate instruction: MOVI a2, __NR_rt_sigreturn */
err | = __put_user ( 0x22 , & codemem [ 0 ] ) ;
err | = __put_user ( 0x0a , & codemem [ 1 ] ) ;
err | = __put_user ( __NR_rt_sigreturn , & codemem [ 2 ] ) ;
/* Generate instruction: SYSCALL */
err | = __put_user ( 0x00 , & codemem [ 3 ] ) ;
err | = __put_user ( 0x05 , & codemem [ 4 ] ) ;
err | = __put_user ( 0x00 , & codemem [ 5 ] ) ;
2005-06-24 09:01:16 +04:00
# elif defined __XTENSA_EL__ /* Little Endian version */
2007-06-01 04:49:32 +04:00
/* Generate instruction: MOVI a2, __NR_rt_sigreturn */
err | = __put_user ( 0x22 , & codemem [ 0 ] ) ;
err | = __put_user ( 0xa0 , & codemem [ 1 ] ) ;
err | = __put_user ( __NR_rt_sigreturn , & codemem [ 2 ] ) ;
/* Generate instruction: SYSCALL */
err | = __put_user ( 0x00 , & codemem [ 3 ] ) ;
err | = __put_user ( 0x50 , & codemem [ 4 ] ) ;
err | = __put_user ( 0x00 , & codemem [ 5 ] ) ;
2005-06-24 09:01:16 +04:00
# else
2007-06-01 04:49:32 +04:00
# error Must use compiler for Xtensa processors.
2005-06-24 09:01:16 +04:00
# endif
/* Flush generated code out of the data cache */
2006-12-10 13:18:48 +03:00
if ( err = = 0 ) {
__invalidate_icache_range ( ( unsigned long ) codemem , 6UL ) ;
__flush_invalidate_dcache_range ( ( unsigned long ) codemem , 6UL ) ;
}
2005-06-24 09:01:16 +04:00
return err ;
}
2013-10-07 17:09:23 +04:00
static int setup_frame ( struct ksignal * ksig , sigset_t * set ,
struct pt_regs * regs )
2005-06-24 09:01:16 +04:00
{
2007-06-01 04:49:32 +04:00
struct rt_sigframe * frame ;
2013-10-07 17:09:23 +04:00
int err = 0 , sig = ksig - > sig ;
2013-02-24 07:35:57 +04:00
unsigned long sp , ra , tp ;
2005-06-24 09:01:16 +04:00
2007-06-01 04:49:32 +04:00
sp = regs - > areg [ 1 ] ;
2005-06-24 09:01:16 +04:00
2013-10-07 17:09:23 +04:00
if ( ( ksig - > ka . sa . sa_flags & SA_ONSTACK ) ! = 0 & & sas_ss_flags ( sp ) = = 0 ) {
2007-06-01 04:49:32 +04:00
sp = current - > sas_ss_sp + current - > sas_ss_size ;
2005-06-24 09:01:16 +04:00
}
2007-06-01 04:49:32 +04:00
frame = ( void * ) ( ( sp - sizeof ( * frame ) ) & - 16ul ) ;
2005-06-24 09:01:16 +04:00
if ( regs - > depc > 64 )
panic ( " Double exception sys_sigreturn \n " ) ;
2007-06-01 04:49:32 +04:00
if ( ! access_ok ( VERIFY_WRITE , frame , sizeof ( * frame ) ) ) {
2013-10-07 17:09:23 +04:00
return - EFAULT ;
2007-06-01 04:49:32 +04:00
}
2005-06-24 09:01:16 +04:00
2013-10-07 17:09:23 +04:00
if ( ksig - > ka . sa . sa_flags & SA_SIGINFO ) {
err | = copy_siginfo_to_user ( & frame - > info , & ksig - > info ) ;
2007-06-01 04:49:32 +04:00
}
/* Create the user context. */
2005-06-24 09:01:16 +04:00
err | = __put_user ( 0 , & frame - > uc . uc_flags ) ;
err | = __put_user ( 0 , & frame - > uc . uc_link ) ;
2012-12-23 12:54:43 +04:00
err | = __save_altstack ( & frame - > uc . uc_stack , regs - > areg [ 1 ] ) ;
2008-02-13 00:17:07 +03:00
err | = setup_sigcontext ( frame , regs ) ;
2005-06-24 09:01:16 +04:00
err | = __copy_to_user ( & frame - > uc . uc_sigmask , set , sizeof ( * set ) ) ;
2013-10-07 17:09:23 +04:00
if ( ksig - > ka . sa . sa_flags & SA_RESTORER ) {
ra = ( unsigned long ) ksig - > ka . sa . sa_restorer ;
2008-01-11 22:44:17 +03:00
} else {
2005-06-24 09:01:16 +04:00
2008-01-11 22:44:17 +03:00
/* Create sys_rt_sigreturn syscall in stack frame */
2007-06-01 04:49:32 +04:00
2008-01-11 22:44:17 +03:00
err | = gen_return_code ( frame - > retcode ) ;
if ( err ) {
2013-10-07 17:09:23 +04:00
return - EFAULT ;
2008-01-11 22:44:17 +03:00
}
ra = ( unsigned long ) frame - > retcode ;
2007-06-01 04:49:32 +04:00
}
2005-06-24 09:01:16 +04:00
2007-06-01 04:49:32 +04:00
/*
* Create signal handler execution context .
2005-06-24 09:01:16 +04:00
* Return context not modified until this point .
*/
2007-06-01 04:49:32 +04:00
2013-02-24 07:35:57 +04:00
/* Set up registers for signal handler; preserve the threadptr */
tp = regs - > threadptr ;
2013-10-07 17:09:23 +04:00
start_thread ( regs , ( unsigned long ) ksig - > ka . sa . sa_handler ,
2007-06-01 04:49:32 +04:00
( unsigned long ) frame ) ;
/* Set up a stack frame for a call4
* Note : PS . CALLINC is set to one by start_thread
*/
regs - > areg [ 4 ] = ( ( ( unsigned long ) ra ) & 0x3fffffff ) | 0x40000000 ;
2014-07-13 19:45:11 +04:00
regs - > areg [ 6 ] = ( unsigned long ) sig ;
2007-06-01 04:49:32 +04:00
regs - > areg [ 7 ] = ( unsigned long ) & frame - > info ;
regs - > areg [ 8 ] = ( unsigned long ) & frame - > uc ;
2013-02-24 07:35:57 +04:00
regs - > threadptr = tp ;
2005-06-24 09:01:16 +04:00
# if DEBUG_SIG
printk ( " SIG rt deliver (%s:%d): signal=%d sp=%p pc=%08x \n " ,
2014-07-13 19:45:11 +04:00
current - > comm , current - > pid , sig , frame , regs - > pc ) ;
2005-06-24 09:01:16 +04:00
# endif
2012-03-22 03:33:45 +04:00
return 0 ;
2005-06-24 09:01:16 +04:00
}
/*
* Note that ' init ' is a special process : it doesn ' t get signals it doesn ' t
* want to handle . Thus you cannot kill init even with a SIGKILL even by
* mistake .
*
* Note that we go through the signals twice : once to check the signals that
* the kernel can handle , and then we build all the user - level signal handling
* stack - frames in one go after that .
*/
2012-04-24 10:30:16 +04:00
static void do_signal ( struct pt_regs * regs )
2005-06-24 09:01:16 +04:00
{
2013-10-07 17:09:23 +04:00
struct ksignal ksig ;
2005-06-24 09:01:16 +04:00
2007-06-01 04:49:32 +04:00
task_pt_regs ( current ) - > icountlevel = 0 ;
2013-10-07 17:09:23 +04:00
if ( get_signal ( & ksig ) ) {
2012-04-19 00:17:13 +04:00
int ret ;
2007-06-01 04:49:32 +04:00
/* Are we from a system call? */
if ( ( signed ) regs - > syscall > = 0 ) {
2005-06-24 09:01:16 +04:00
2007-06-01 04:49:32 +04:00
/* If so, check system call restarting.. */
switch ( regs - > areg [ 2 ] ) {
case - ERESTARTNOHAND :
case - ERESTART_RESTARTBLOCK :
2005-06-24 09:01:16 +04:00
regs - > areg [ 2 ] = - EINTR ;
break ;
2007-06-01 04:49:32 +04:00
case - ERESTARTSYS :
2013-10-07 17:09:23 +04:00
if ( ! ( ksig . ka . sa . sa_flags & SA_RESTART ) ) {
2007-06-01 04:49:32 +04:00
regs - > areg [ 2 ] = - EINTR ;
break ;
}
/* fallthrough */
case - ERESTARTNOINTR :
regs - > areg [ 2 ] = regs - > syscall ;
regs - > pc - = 3 ;
break ;
default :
/* nothing to do */
if ( regs - > areg [ 2 ] ! = 0 )
break ;
}
2005-06-24 09:01:16 +04:00
}
2007-06-01 04:49:32 +04:00
/* Whee! Actually deliver the signal. */
/* Set up the stack frame */
2013-10-07 17:09:23 +04:00
ret = setup_frame ( & ksig , sigmask_to_save ( ) , regs ) ;
signal_setup_done ( ret , & ksig , 0 ) ;
2007-06-01 04:49:32 +04:00
if ( current - > ptrace & PT_SINGLESTEP )
task_pt_regs ( current ) - > icountlevel = 1 ;
2005-06-24 09:01:16 +04:00
2012-04-22 08:59:07 +04:00
return ;
2007-06-01 04:49:32 +04:00
}
2005-06-24 09:01:16 +04:00
2007-06-01 04:49:32 +04:00
/* Did we come from a system call? */
if ( ( signed ) regs - > syscall > = 0 ) {
/* Restart the system call - no handlers present */
switch ( regs - > areg [ 2 ] ) {
case - ERESTARTNOHAND :
case - ERESTARTSYS :
case - ERESTARTNOINTR :
regs - > areg [ 2 ] = regs - > syscall ;
regs - > pc - = 3 ;
break ;
case - ERESTART_RESTARTBLOCK :
regs - > areg [ 2 ] = __NR_restart_syscall ;
regs - > pc - = 3 ;
break ;
}
}
2012-04-22 08:59:07 +04:00
/* If there's no signal to deliver, we just restore the saved mask. */
2012-05-22 07:33:55 +04:00
restore_saved_sigmask ( ) ;
2012-04-22 08:59:07 +04:00
2007-06-01 04:49:32 +04:00
if ( current - > ptrace & PT_SINGLESTEP )
task_pt_regs ( current ) - > icountlevel = 1 ;
2012-04-22 08:59:07 +04:00
return ;
2005-06-24 09:01:16 +04:00
}
2007-06-01 04:49:32 +04:00
2012-04-24 10:30:16 +04:00
void do_notify_resume ( struct pt_regs * regs )
{
if ( test_thread_flag ( TIF_SIGPENDING ) )
do_signal ( regs ) ;
2012-05-23 22:44:37 +04:00
if ( test_and_clear_thread_flag ( TIF_NOTIFY_RESUME ) )
2012-04-24 10:30:16 +04:00
tracehook_notify_resume ( regs ) ;
}