2005-04-16 15:20:36 -07:00
/*
* Copyright ( C ) 2003 PathScale , Inc .
2007-10-16 01:27:18 -07:00
* Copyright ( C ) 2003 - 2007 Jeff Dike ( jdike @ { addtoit , linux . intel } . com )
2005-04-16 15:20:36 -07:00
* Licensed under the GPL
*/
2008-01-30 13:31:08 +01:00
# include <linux/personality.h>
# include <linux/ptrace.h>
2010-04-20 17:47:24 +02:00
# include <linux/kernel.h>
2008-01-30 13:31:08 +01:00
# include <asm/unistd.h>
# include <asm/uaccess.h>
# include <asm/ucontext.h>
2005-04-16 15:20:36 -07:00
# include "frame_kern.h"
# include "skas.h"
2007-10-16 01:26:58 -07:00
void copy_sc ( struct uml_pt_regs * regs , void * from )
2007-05-06 14:51:25 -07:00
{
struct sigcontext * sc = from ;
2007-10-16 01:27:00 -07:00
# define GETREG(regs, regno, sc, regname) \
2007-10-16 01:27:07 -07:00
( regs ) - > gp [ ( regno ) / sizeof ( unsigned long ) ] = ( sc ) - > regname
2007-10-16 01:27:00 -07:00
GETREG ( regs , R8 , sc , r8 ) ;
GETREG ( regs , R9 , sc , r9 ) ;
GETREG ( regs , R10 , sc , r10 ) ;
GETREG ( regs , R11 , sc , r11 ) ;
GETREG ( regs , R12 , sc , r12 ) ;
GETREG ( regs , R13 , sc , r13 ) ;
GETREG ( regs , R14 , sc , r14 ) ;
GETREG ( regs , R15 , sc , r15 ) ;
2008-01-30 13:31:08 +01:00
GETREG ( regs , RDI , sc , di ) ;
GETREG ( regs , RSI , sc , si ) ;
GETREG ( regs , RBP , sc , bp ) ;
GETREG ( regs , RBX , sc , bx ) ;
GETREG ( regs , RDX , sc , dx ) ;
GETREG ( regs , RAX , sc , ax ) ;
GETREG ( regs , RCX , sc , cx ) ;
GETREG ( regs , RSP , sc , sp ) ;
GETREG ( regs , RIP , sc , ip ) ;
GETREG ( regs , EFLAGS , sc , flags ) ;
2007-10-16 01:27:00 -07:00
GETREG ( regs , CS , sc , cs ) ;
2007-05-06 14:51:25 -07:00
# undef GETREG
}
2007-10-16 01:26:58 -07:00
static int copy_sc_from_user ( struct pt_regs * regs ,
2007-10-16 01:27:15 -07:00
struct sigcontext __user * from ,
struct _fpstate __user * fpp )
2005-04-16 15:20:36 -07:00
{
2007-10-16 01:27:15 -07:00
struct user_i387_struct fp ;
2007-10-16 01:27:00 -07:00
int err = 0 ;
# define GETREG(regs, regno, sc, regname) \
2007-10-16 01:27:07 -07:00
__get_user ( ( regs ) - > regs . gp [ ( regno ) / sizeof ( unsigned long ) ] , \
2007-10-16 01:27:00 -07:00
& ( sc ) - > regname )
err | = GETREG ( regs , R8 , from , r8 ) ;
err | = GETREG ( regs , R9 , from , r9 ) ;
err | = GETREG ( regs , R10 , from , r10 ) ;
err | = GETREG ( regs , R11 , from , r11 ) ;
err | = GETREG ( regs , R12 , from , r12 ) ;
err | = GETREG ( regs , R13 , from , r13 ) ;
err | = GETREG ( regs , R14 , from , r14 ) ;
err | = GETREG ( regs , R15 , from , r15 ) ;
2008-01-30 13:31:08 +01:00
err | = GETREG ( regs , RDI , from , di ) ;
err | = GETREG ( regs , RSI , from , si ) ;
err | = GETREG ( regs , RBP , from , bp ) ;
err | = GETREG ( regs , RBX , from , bx ) ;
err | = GETREG ( regs , RDX , from , dx ) ;
err | = GETREG ( regs , RAX , from , ax ) ;
err | = GETREG ( regs , RCX , from , cx ) ;
err | = GETREG ( regs , RSP , from , sp ) ;
err | = GETREG ( regs , RIP , from , ip ) ;
err | = GETREG ( regs , EFLAGS , from , flags ) ;
2007-10-16 01:27:00 -07:00
err | = GETREG ( regs , CS , from , cs ) ;
2007-10-16 01:27:15 -07:00
if ( err )
return 1 ;
2005-04-16 15:20:36 -07:00
# undef GETREG
2007-10-16 01:27:15 -07:00
err = copy_from_user ( & fp , fpp , sizeof ( struct user_i387_struct ) ) ;
if ( err )
return 1 ;
2008-02-04 22:30:54 -08:00
err = restore_fp_registers ( userspace_pid [ current_thread_info ( ) - > cpu ] ,
2007-10-16 01:27:15 -07:00
( unsigned long * ) & fp ) ;
if ( err < 0 ) {
printk ( KERN_ERR " copy_sc_from_user - "
" restore_fp_registers failed, errno = %d \n " ,
- err ) ;
return 1 ;
}
return 0 ;
2005-04-16 15:20:36 -07:00
}
2007-10-16 01:26:58 -07:00
static int copy_sc_to_user ( struct sigcontext __user * to ,
struct _fpstate __user * to_fp , struct pt_regs * regs ,
unsigned long mask , unsigned long sp )
2005-04-16 15:20:36 -07:00
{
2007-10-16 01:27:00 -07:00
struct faultinfo * fi = & current - > thread . arch . faultinfo ;
2007-10-16 01:27:15 -07:00
struct user_i387_struct fp ;
2005-04-16 15:20:36 -07:00
int err = 0 ;
err | = __put_user ( 0 , & to - > gs ) ;
err | = __put_user ( 0 , & to - > fs ) ;
2007-10-16 01:27:00 -07:00
# define PUTREG(regs, regno, sc, regname) \
2007-10-16 01:27:07 -07:00
__put_user ( ( regs ) - > regs . gp [ ( regno ) / sizeof ( unsigned long ) ] , \
2007-10-16 01:27:00 -07:00
& ( sc ) - > regname )
2005-04-16 15:20:36 -07:00
2008-01-30 13:31:08 +01:00
err | = PUTREG ( regs , RDI , to , di ) ;
err | = PUTREG ( regs , RSI , to , si ) ;
err | = PUTREG ( regs , RBP , to , bp ) ;
2007-10-16 01:27:18 -07:00
/*
2008-02-03 17:05:25 +02:00
* Must use original RSP , which is passed in , rather than what ' s in
2007-10-16 01:27:00 -07:00
* the pt_regs , because that ' s already been updated to point at the
* signal frame .
*/
2008-01-30 13:31:08 +01:00
err | = __put_user ( sp , & to - > sp ) ;
err | = PUTREG ( regs , RBX , to , bx ) ;
err | = PUTREG ( regs , RDX , to , dx ) ;
err | = PUTREG ( regs , RCX , to , cx ) ;
err | = PUTREG ( regs , RAX , to , ax ) ;
2005-04-16 15:20:36 -07:00
err | = PUTREG ( regs , R8 , to , r8 ) ;
err | = PUTREG ( regs , R9 , to , r9 ) ;
err | = PUTREG ( regs , R10 , to , r10 ) ;
err | = PUTREG ( regs , R11 , to , r11 ) ;
err | = PUTREG ( regs , R12 , to , r12 ) ;
err | = PUTREG ( regs , R13 , to , r13 ) ;
err | = PUTREG ( regs , R14 , to , r14 ) ;
err | = PUTREG ( regs , R15 , to , r15 ) ;
err | = PUTREG ( regs , CS , to , cs ) ; /* XXX x86_64 doesn't do this */
[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-05 16:15:31 -07:00
2007-10-16 01:27:00 -07:00
err | = __put_user ( fi - > cr2 , & to - > cr2 ) ;
err | = __put_user ( fi - > error_code , & to - > err ) ;
err | = __put_user ( fi - > trap_no , & to - > trapno ) ;
[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-05 16:15:31 -07:00
2008-01-30 13:31:08 +01:00
err | = PUTREG ( regs , RIP , to , ip ) ;
err | = PUTREG ( regs , EFLAGS , to , flags ) ;
2005-04-16 15:20:36 -07:00
# undef PUTREG
err | = __put_user ( mask , & to - > oldmask ) ;
2007-10-16 01:27:15 -07:00
if ( err )
return 1 ;
2008-02-04 22:30:54 -08:00
err = save_fp_registers ( userspace_pid [ current_thread_info ( ) - > cpu ] ,
2007-10-16 01:27:15 -07:00
( unsigned long * ) & fp ) ;
if ( err < 0 ) {
printk ( KERN_ERR " copy_sc_from_user - restore_fp_registers "
" failed, errno = %d \n " , - err ) ;
return 1 ;
}
if ( copy_to_user ( to_fp , & fp , sizeof ( struct user_i387_struct ) ) )
return 1 ;
2005-04-16 15:20:36 -07:00
2007-10-16 01:27:18 -07:00
return err ;
2005-04-16 15:20:36 -07:00
}
struct rt_sigframe
{
2007-10-16 01:27:00 -07:00
char __user * pretcode ;
struct ucontext uc ;
struct siginfo info ;
2007-10-16 01:27:15 -07:00
struct _fpstate fpstate ;
2005-04-16 15:20:36 -07:00
} ;
int setup_signal_stack_si ( unsigned long stack_top , int sig ,
struct k_sigaction * ka , struct pt_regs * regs ,
siginfo_t * info , sigset_t * set )
{
struct rt_sigframe __user * frame ;
2006-03-27 01:14:38 -08:00
unsigned long save_sp = PT_REGS_RSP ( regs ) ;
2005-04-16 15:20:36 -07:00
int err = 0 ;
struct task_struct * me = current ;
frame = ( struct rt_sigframe __user * )
2007-01-30 14:36:17 -08:00
round_down ( stack_top - sizeof ( struct rt_sigframe ) , 16 ) ;
/* Subtract 128 for a red zone and 8 for proper alignment */
2007-10-16 01:27:00 -07:00
frame = ( struct rt_sigframe __user * ) ( ( unsigned long ) frame - 128 - 8 ) ;
2005-04-16 15:20:36 -07:00
if ( ! access_ok ( VERIFY_WRITE , frame , sizeof ( * frame ) ) )
goto out ;
if ( ka - > sa . sa_flags & SA_SIGINFO ) {
err | = copy_siginfo_to_user ( & frame - > info , info ) ;
if ( err )
goto out ;
}
2007-10-16 01:27:18 -07:00
/*
* Update SP now because the page fault handler refuses to extend
2006-03-27 01:14:38 -08:00
* the stack if the faulting address is too far below the current
* SP , which frame now certainly is . If there ' s an error , the original
* value is restored on the way out .
* When writing the sigcontext to the stack , we have to write the
* original value , so that ' s passed to copy_sc_to_user , which does
* the right thing with it .
*/
PT_REGS_RSP ( regs ) = ( unsigned long ) frame ;
2005-04-16 15:20:36 -07:00
/* Create the ucontext. */
err | = __put_user ( 0 , & frame - > uc . uc_flags ) ;
err | = __put_user ( 0 , & frame - > uc . uc_link ) ;
err | = __put_user ( me - > sas_ss_sp , & frame - > uc . uc_stack . ss_sp ) ;
2006-03-27 01:14:38 -08:00
err | = __put_user ( sas_ss_flags ( save_sp ) ,
2005-04-16 15:20:36 -07:00
& frame - > uc . uc_stack . ss_flags ) ;
err | = __put_user ( me - > sas_ss_size , & frame - > uc . uc_stack . ss_size ) ;
2007-10-16 01:27:15 -07:00
err | = copy_sc_to_user ( & frame - > uc . uc_mcontext , & frame - > fpstate , regs ,
set - > sig [ 0 ] , save_sp ) ;
err | = __put_user ( & frame - > fpstate , & frame - > uc . uc_mcontext . fpstate ) ;
2005-04-16 15:20:36 -07:00
if ( sizeof ( * set ) = = 16 ) {
__put_user ( set - > sig [ 0 ] , & frame - > uc . uc_sigmask . sig [ 0 ] ) ;
__put_user ( set - > sig [ 1 ] , & frame - > uc . uc_sigmask . sig [ 1 ] ) ;
}
else
err | = __copy_to_user ( & frame - > uc . uc_sigmask , set ,
sizeof ( * set ) ) ;
2007-10-16 01:27:18 -07:00
/*
* Set up to return from userspace . If provided , use a stub
* already in userspace .
*/
2005-04-16 15:20:36 -07:00
/* x86-64 should always use SA_RESTORER. */
if ( ka - > sa . sa_flags & SA_RESTORER )
err | = __put_user ( ka - > sa . sa_restorer , & frame - > pretcode ) ;
else
/* could use a vstub here */
2006-03-27 01:14:38 -08:00
goto restore_sp ;
2005-04-16 15:20:36 -07:00
if ( err )
2006-03-27 01:14:38 -08:00
goto restore_sp ;
2005-04-16 15:20:36 -07:00
/* Set up registers for signal handler */
{
struct exec_domain * ed = current_thread_info ( ) - > exec_domain ;
if ( unlikely ( ed & & ed - > signal_invmap & & sig < 32 ) )
sig = ed - > signal_invmap [ sig ] ;
}
PT_REGS_RDI ( regs ) = sig ;
/* In case the signal handler was declared without prototypes */
PT_REGS_RAX ( regs ) = 0 ;
2007-10-16 01:27:18 -07:00
/*
* This also works for non SA_SIGINFO handlers because they expect the
* next argument after the signal number on the stack .
*/
2005-04-16 15:20:36 -07:00
PT_REGS_RSI ( regs ) = ( unsigned long ) & frame - > info ;
PT_REGS_RDX ( regs ) = ( unsigned long ) & frame - > uc ;
PT_REGS_RIP ( regs ) = ( unsigned long ) ka - > sa . sa_handler ;
out :
2006-03-27 01:14:38 -08:00
return err ;
restore_sp :
PT_REGS_RSP ( regs ) = save_sp ;
return err ;
2005-04-16 15:20:36 -07:00
}
long sys_rt_sigreturn ( struct pt_regs * regs )
{
unsigned long sp = PT_REGS_SP ( & current - > thread . regs ) ;
struct rt_sigframe __user * frame =
( struct rt_sigframe __user * ) ( sp - 8 ) ;
struct ucontext __user * uc = & frame - > uc ;
sigset_t set ;
2007-10-16 01:27:00 -07:00
if ( copy_from_user ( & set , & uc - > uc_sigmask , sizeof ( set ) ) )
2005-04-16 15:20:36 -07:00
goto segfault ;
sigdelsetmask ( & set , ~ _BLOCKABLE ) ;
spin_lock_irq ( & current - > sighand - > siglock ) ;
current - > blocked = set ;
recalc_sigpending ( ) ;
spin_unlock_irq ( & current - > sighand - > siglock ) ;
2007-10-16 01:27:15 -07:00
if ( copy_sc_from_user ( & current - > thread . regs , & uc - > uc_mcontext ,
& frame - > fpstate ) )
2005-04-16 15:20:36 -07:00
goto segfault ;
/* Avoid ERESTART handling */
PT_REGS_SYSCALL_NR ( & current - > thread . regs ) = - 1 ;
2007-10-16 01:27:18 -07:00
return PT_REGS_SYSCALL_RET ( & current - > thread . regs ) ;
2005-04-16 15:20:36 -07:00
segfault :
force_sig ( SIGSEGV , current ) ;
return 0 ;
}