patch-2.4.13 linux/arch/s390/kernel/signal.c
Next file: linux/arch/s390/kernel/smp.c
Previous file: linux/arch/s390/kernel/setup.c
Back to the patch index
Back to the overall index
- Lines: 311
- Date:
Thu Oct 11 09:04:57 2001
- Orig file:
v2.4.12/linux/arch/s390/kernel/signal.c
- Orig date:
Sun Aug 12 13:27:58 2001
diff -u --recursive --new-file v2.4.12/linux/arch/s390/kernel/signal.c linux/arch/s390/kernel/signal.c
@@ -12,6 +12,7 @@
* 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
*/
+#include <linux/config.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
@@ -23,31 +24,25 @@
#include <linux/ptrace.h>
#include <linux/unistd.h>
#include <linux/stddef.h>
+#include <linux/personality.h>
#include <asm/ucontext.h>
#include <asm/uaccess.h>
-#define DEBUG_SIG 0
-
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-/* pretcode & sig are used to store the return addr on Intel
- & the signal no as the first parameter we do this differently
- using gpr14 & gpr2. */
-
-#define SIGFRAME_COMMON \
-__u8 callee_used_stack[__SIGNAL_FRAMESIZE]; \
-struct sigcontext sc; \
-_sigregs sregs; \
-__u8 retcode[S390_SYSCALL_SIZE];
typedef struct
{
- SIGFRAME_COMMON
+ __u8 callee_used_stack[__SIGNAL_FRAMESIZE];
+ struct sigcontext sc;
+ _sigregs sregs;
+ __u8 retcode[S390_SYSCALL_SIZE];
} sigframe;
typedef struct
{
- SIGFRAME_COMMON
+ __u8 callee_used_stack[__SIGNAL_FRAMESIZE];
+ __u8 retcode[S390_SYSCALL_SIZE];
struct siginfo info;
struct ucontext uc;
} rt_sigframe;
@@ -205,7 +200,7 @@
err=__copy_from_user(regs,&sregs->regs,sizeof(_s390_regs_common));
if(!err)
{
- regs->orig_gpr2 = -1; /* disable syscall checks */
+ regs->trap = -1; /* disable syscall checks */
regs->psw.mask=(saved_psw.mask&~PSW_MASK_DEBUGCHANGE)|
(regs->psw.mask&PSW_MASK_DEBUGCHANGE);
regs->psw.addr=(saved_psw.addr&~PSW_ADDR_DEBUGCHANGE)|
@@ -217,53 +212,51 @@
return(err);
}
-static int
-restore_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
- _sigregs *sregs,sigset_t *set)
-{
- unsigned int err;
-
- err=restore_sigregs(regs,sregs);
- if(!err)
- err=__copy_from_user(&set->sig,&sc->oldmask,_SIGMASK_COPY_SIZE);
- return(err);
-}
-
-int sigreturn_common(struct pt_regs *regs,int framesize)
+asmlinkage long sys_sigreturn(struct pt_regs *regs)
{
sigframe *frame = (sigframe *)regs->gprs[15];
sigset_t set;
if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
- return -1;
- if (restore_sigcontext(&frame->sc,regs,&frame->sregs,&set))
- return -1;
+ goto badframe;
+ if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE))
+ goto badframe;
+
sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(¤t->sigmask_lock);
current->blocked = set;
recalc_sigpending(current);
spin_unlock_irq(¤t->sigmask_lock);
- return 0;
-}
-
-asmlinkage int sys_sigreturn(struct pt_regs *regs)
-{
- if (sigreturn_common(regs,sizeof(sigframe)))
+ if (restore_sigregs(regs, &frame->sregs))
goto badframe;
+
return regs->gprs[2];
badframe:
force_sig(SIGSEGV, current);
return 0;
-}
+}
-asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
+asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
{
rt_sigframe *frame = (rt_sigframe *)regs->gprs[15];
+ sigset_t set;
+
+ if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+ if (__copy_from_user(&set.sig, &frame->uc.uc_sigmask, sizeof(set)))
+ goto badframe;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(¤t->sigmask_lock);
+ current->blocked = set;
+ recalc_sigpending(current);
+ spin_unlock_irq(¤t->sigmask_lock);
- if (sigreturn_common(regs,sizeof(rt_sigframe)))
+ if (restore_sigregs(regs, &frame->uc.uc_mcontext))
goto badframe;
+
/* It is more difficult to avoid calling this function than to
call it and ignore errors. */
do_sigaltstack(&frame->uc.uc_stack, NULL, regs->gprs[15]);
@@ -272,7 +265,7 @@
badframe:
force_sig(SIGSEGV, current);
return 0;
-}
+}
/*
* Set up a signal frame.
@@ -306,58 +299,48 @@
return (void *)((sp - frame_size) & -8ul);
}
-static void *setup_frame_common(int sig, struct k_sigaction *ka,
- sigset_t *set, struct pt_regs * regs,
- int frame_size,u16 retcode)
+static inline int map_signal(int sig)
{
- sigframe *frame;
- int err;
+ if (current->exec_domain
+ && current->exec_domain->signal_invmap
+ && sig < 32)
+ return current->exec_domain->signal_invmap[sig];
+ else
+ return sig;
+}
- frame = get_sigframe(ka, regs,frame_size);
- if (!access_ok(VERIFY_WRITE, frame,frame_size))
- return 0;
- err = save_sigregs(regs,&frame->sregs);
- if(!err)
- err=__put_user(&frame->sregs,&frame->sc.sregs);
- if(!err)
+static void setup_frame(int sig, struct k_sigaction *ka,
+ sigset_t *set, struct pt_regs * regs)
+{
+ sigframe *frame = get_sigframe(ka, regs, sizeof(sigframe));
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(sigframe)))
+ goto give_sigsegv;
+
+ if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE))
+ goto give_sigsegv;
+
+ if (save_sigregs(regs, &frame->sregs))
+ goto give_sigsegv;
+ if (__put_user(&frame->sregs, &frame->sc.sregs))
+ goto give_sigsegv;
- err=__copy_to_user(&frame->sc.oldmask,&set->sig,_SIGMASK_COPY_SIZE);
- if(!err)
- {
- regs->gprs[2]=(current->exec_domain
- && current->exec_domain->signal_invmap
- && sig < 32
- ? current->exec_domain->signal_invmap[sig]
- : sig);
- /* Set up registers for signal handler */
- regs->gprs[15] = (addr_t)frame;
- regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
- regs->psw.mask = _USER_PSW_MASK;
- }
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
if (ka->sa.sa_flags & SA_RESTORER) {
regs->gprs[14] = FIX_PSW(ka->sa.sa_restorer);
} else {
regs->gprs[14] = FIX_PSW(frame->retcode);
- err |= __put_user(retcode, (u16 *)(frame->retcode));
+ if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
+ (u16 *)(frame->retcode)))
+ goto give_sigsegv;
}
- return(err ? 0:frame);
-}
-static void setup_frame(int sig, struct k_sigaction *ka,
- sigset_t *set, struct pt_regs * regs)
-{
- sigframe *frame;
+ /* Set up registers for signal handler */
+ regs->gprs[15] = (addr_t)frame;
+ regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
+ regs->psw.mask = _USER_PSW_MASK;
- if((frame=setup_frame_common(sig,ka,set,regs,sizeof(sigframe),
- (S390_SYSCALL_OPCODE|__NR_sigreturn)))==0)
- goto give_sigsegv;
-#if DEBUG_SIG
- printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
- current->comm, current->pid, frame, regs->eip, frame->pretcode);
-#endif
- /* Martin wants this for pthreads */
+ regs->gprs[2] = map_signal(sig);
regs->gprs[3] = (addr_t)&frame->sc;
/* We forgot to include these in the sigcontext.
@@ -375,34 +358,44 @@
static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs * regs)
{
- rt_sigframe *frame;
- addr_t orig_sp=regs->gprs[15];
- int err;
+ int err = 0;
+ rt_sigframe *frame = get_sigframe(ka, regs, sizeof(rt_sigframe));
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(rt_sigframe)))
+ goto give_sigsegv;
- if((frame=setup_frame_common(sig,ka,set,regs,sizeof(rt_sigframe),
- (S390_SYSCALL_OPCODE|__NR_rt_sigreturn)))==0)
+ if (copy_siginfo_to_user(&frame->info, info))
goto give_sigsegv;
-
- err = copy_siginfo_to_user(&frame->info, info);
/* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags);
err |= __put_user(0, &frame->uc.uc_link);
err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
- err |= __put_user(sas_ss_flags(orig_sp),
+ err |= __put_user(sas_ss_flags(regs->gprs[15]),
&frame->uc.uc_stack.ss_flags);
err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
- err |= __put_user(&frame->sc,&frame->uc.sc);
- regs->gprs[3] = (addr_t)&frame->info;
- regs->gprs[4] = (addr_t)&frame->uc;
-
+ err |= save_sigregs(regs, &frame->uc.uc_mcontext);
+ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
if (err)
goto give_sigsegv;
-#if DEBUG_SIG
- printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
- current->comm, current->pid, frame, regs->eip, frame->pretcode);
-#endif
+ /* Set up to return from userspace. If provided, use a stub
+ already in userspace. */
+ if (ka->sa.sa_flags & SA_RESTORER) {
+ regs->gprs[14] = FIX_PSW(ka->sa.sa_restorer);
+ } else {
+ regs->gprs[14] = FIX_PSW(frame->retcode);
+ err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
+ (u16 *)(frame->retcode));
+ }
+
+ /* Set up registers for signal handler */
+ regs->gprs[15] = (addr_t)frame;
+ regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
+ regs->psw.mask = _USER_PSW_MASK;
+
+ regs->gprs[2] = map_signal(sig);
+ regs->gprs[3] = (addr_t)&frame->info;
+ regs->gprs[4] = (addr_t)&frame->uc;
return;
give_sigsegv:
@@ -551,13 +544,16 @@
continue;
/* FALLTHRU */
- case SIGSTOP:
+ case SIGSTOP: {
+ struct signal_struct *sig;
set_current_state(TASK_STOPPED);
current->exit_code = signr;
- if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
+ sig = current->p_pptr->sig;
+ if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
notify_parent(current, SIGCHLD);
schedule();
continue;
+ }
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV:
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)