2005-04-17 02:20:36 +04:00
/*
* Copyright ( C ) 2003 Broadcom Corporation
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
2005-06-15 17:00:12 +04:00
# include <linux/cache.h>
# include <linux/sched.h>
2005-04-17 02:20:36 +04:00
# include <linux/mm.h>
# include <linux/smp.h>
# include <linux/kernel.h>
# include <linux/signal.h>
# include <linux/errno.h>
# include <linux/wait.h>
# include <linux/ptrace.h>
# include <linux/unistd.h>
# include <linux/compat.h>
# include <linux/bitops.h>
2007-02-15 14:40:37 +03:00
# include <asm/abi.h>
2005-04-17 02:20:36 +04:00
# include <asm/asm.h>
# include <asm/cacheflush.h>
2007-02-13 03:05:11 +03:00
# include <asm/compat-signal.h>
2005-04-17 02:20:36 +04:00
# include <asm/sim.h>
# include <asm/uaccess.h>
# include <asm/ucontext.h>
# include <asm/fpu.h>
# include <asm/cpu-features.h>
2005-06-15 17:00:12 +04:00
# include <asm/war.h>
2005-04-17 02:20:36 +04:00
# include "signal-common.h"
/*
* Including < asm / unistd . h > would give use the 64 - bit syscall numbers . . .
*/
# define __NR_N32_restart_syscall 6214
2007-02-13 04:28:09 +03:00
extern int setup_sigcontext ( struct pt_regs * , struct sigcontext __user * ) ;
extern int restore_sigcontext ( struct pt_regs * , struct sigcontext __user * ) ;
2005-04-17 02:20:36 +04:00
struct ucontextn32 {
2013-01-22 15:59:30 +04:00
u32 uc_flags ;
s32 uc_link ;
2012-12-23 12:13:40 +04:00
compat_stack_t uc_stack ;
2005-04-17 02:20:36 +04:00
struct sigcontext uc_mcontext ;
2013-01-22 15:59:30 +04:00
compat_sigset_t uc_sigmask ; /* mask last for extensibility */
2005-04-17 02:20:36 +04:00
} ;
2007-02-05 17:24:21 +03:00
struct rt_sigframe_n32 {
u32 rs_ass [ 4 ] ; /* argument save space for o32 */
2010-02-19 03:13:05 +03:00
u32 rs_pad [ 2 ] ; /* Was: signal trampoline */
2007-06-05 13:42:20 +04:00
struct compat_siginfo rs_info ;
2007-02-05 17:24:21 +03:00
struct ucontextn32 rs_uc ;
2005-04-17 02:20:36 +04:00
} ;
2007-02-05 17:24:27 +03:00
asmlinkage void sysn32_rt_sigreturn ( nabi_no_regargs struct pt_regs regs )
2005-04-17 02:20:36 +04:00
{
2006-01-31 19:41:09 +03:00
struct rt_sigframe_n32 __user * frame ;
2005-04-17 02:20:36 +04:00
sigset_t set ;
2007-03-09 19:03:48 +03:00
int sig ;
2005-04-17 02:20:36 +04:00
2006-01-31 19:41:09 +03:00
frame = ( struct rt_sigframe_n32 __user * ) regs . regs [ 29 ] ;
2005-04-17 02:20:36 +04:00
if ( ! access_ok ( VERIFY_READ , frame , sizeof ( * frame ) ) )
goto badframe ;
2007-02-13 03:05:11 +03:00
if ( __copy_conv_sigset_from_user ( & set , & frame - > rs_uc . uc_sigmask ) )
2005-04-17 02:20:36 +04:00
goto badframe ;
2012-02-14 15:40:52 +04:00
set_current_blocked ( & set ) ;
2005-04-17 02:20:36 +04:00
2007-03-09 19:03:48 +03:00
sig = restore_sigcontext ( & regs , & frame - > rs_uc . uc_mcontext ) ;
if ( sig < 0 )
2005-04-17 02:20:36 +04:00
goto badframe ;
2007-03-09 19:03:48 +03:00
else if ( sig )
force_sig ( sig , current ) ;
2005-04-17 02:20:36 +04:00
2012-12-23 12:13:40 +04:00
if ( compat_restore_altstack ( & frame - > rs_uc . uc_stack ) )
2005-04-17 02:20:36 +04:00
goto badframe ;
/*
* Don ' t let your children do this . . .
*/
__asm__ __volatile__ (
" move \t $29, %0 \n \t "
" j \t syscall_exit "
: /* no outputs */
: " r " ( & regs ) ) ;
/* Unreached */
badframe :
force_sig ( SIGSEGV , current ) ;
}
2013-10-07 00:25:42 +04:00
static int setup_rt_frame_n32 ( void * sig_return , struct ksignal * ksig ,
struct pt_regs * regs , sigset_t * set )
2005-04-17 02:20:36 +04:00
{
2006-01-31 19:41:09 +03:00
struct rt_sigframe_n32 __user * frame ;
2005-04-17 02:20:36 +04:00
int err = 0 ;
2014-03-05 18:35:41 +04:00
frame = get_sigframe ( ksig , regs , sizeof ( * frame ) ) ;
2005-04-17 02:20:36 +04:00
if ( ! access_ok ( VERIFY_WRITE , frame , sizeof ( * frame ) ) )
2013-10-07 00:25:42 +04:00
return - EFAULT ;
2005-04-17 02:20:36 +04:00
/* Create siginfo. */
2013-10-07 00:25:42 +04:00
err | = copy_siginfo_to_user32 ( & frame - > rs_info , & ksig - > info ) ;
2005-04-17 02:20:36 +04:00
2013-01-22 15:59:30 +04:00
/* Create the ucontext. */
2005-04-17 02:20:36 +04:00
err | = __put_user ( 0 , & frame - > rs_uc . uc_flags ) ;
err | = __put_user ( 0 , & frame - > rs_uc . uc_link ) ;
2012-12-23 12:13:40 +04:00
err | = __compat_save_altstack ( & frame - > rs_uc . uc_stack , regs - > regs [ 29 ] ) ;
2005-04-17 02:20:36 +04:00
err | = setup_sigcontext ( regs , & frame - > rs_uc . uc_mcontext ) ;
2007-02-13 03:05:11 +03:00
err | = __copy_conv_sigset_to_user ( & frame - > rs_uc . uc_sigmask , set ) ;
2005-04-17 02:20:36 +04:00
if ( err )
2013-10-07 00:25:42 +04:00
return - EFAULT ;
2005-04-17 02:20:36 +04:00
/*
* Arguments to signal handler :
*
* a0 = signal number
* a1 = 0 ( should be cause )
* a2 = pointer to ucontext
*
* $ 25 and c0_epc point to the signal handler , $ 29 points to
* the struct rt_sigframe .
*/
2013-10-07 00:25:42 +04:00
regs - > regs [ 4 ] = ksig - > sig ;
2005-04-17 02:20:36 +04:00
regs - > regs [ 5 ] = ( unsigned long ) & frame - > rs_info ;
regs - > regs [ 6 ] = ( unsigned long ) & frame - > rs_uc ;
regs - > regs [ 29 ] = ( unsigned long ) frame ;
2010-02-19 03:13:05 +03:00
regs - > regs [ 31 ] = ( unsigned long ) sig_return ;
2013-10-07 00:25:42 +04:00
regs - > cp0_epc = regs - > regs [ 25 ] = ( unsigned long ) ksig - > ka . sa . sa_handler ;
2005-04-17 02:20:36 +04:00
2007-02-05 17:24:24 +03:00
DEBUGP ( " SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx \n " ,
2005-04-17 02:20:36 +04:00
current - > comm , current - > pid ,
frame , regs - > cp0_epc , regs - > regs [ 31 ] ) ;
2007-02-05 17:24:24 +03:00
2006-02-08 15:58:41 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
2007-02-15 14:40:37 +03:00
struct mips_abi mips_abi_n32 = {
2013-01-22 15:59:30 +04:00
. setup_rt_frame = setup_rt_frame_n32 ,
2015-07-27 22:58:14 +03:00
. restart = __NR_N32_restart_syscall ,
. off_sc_fpregs = offsetof ( struct sigcontext , sc_fpregs ) ,
. off_sc_fpc_csr = offsetof ( struct sigcontext , sc_fpc_csr ) ,
. off_sc_used_math = offsetof ( struct sigcontext , sc_used_math ) ,
2015-10-21 11:54:38 +03:00
. vdso = & vdso_image_n32 ,
2007-02-15 14:40:37 +03:00
} ;