Commit 6dc56113 authored by Jeff Dike's avatar Jeff Dike Committed by Linus Torvalds

[PATCH] uml: make signal frame construction more resemble x86

From: Bodo Stroesser <bstroesser@fujitsu-siemens.com>

This makes the UML signal frame construction interface somewhat more similar
to x86 than before.  Also, some small code cleanup, and checking for errors
before changing the signal mask in the SA_NODEFER case.
Signed-off-by: default avatarJeff Dike <jdike@addtoit.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent b0baa0f5
...@@ -10,13 +10,11 @@ ...@@ -10,13 +10,11 @@
#include "sysdep/frame_kern.h" #include "sysdep/frame_kern.h"
extern int setup_signal_stack_sc(unsigned long stack_top, int sig, extern int setup_signal_stack_sc(unsigned long stack_top, int sig,
unsigned long handler, struct k_sigaction *ka,
void (*restorer)(void),
struct pt_regs *regs, struct pt_regs *regs,
sigset_t *mask); sigset_t *mask);
extern int setup_signal_stack_si(unsigned long stack_top, int sig, extern int setup_signal_stack_si(unsigned long stack_top, int sig,
unsigned long handler, struct k_sigaction *ka,
void (*restorer)(void),
struct pt_regs *regs, siginfo_t *info, struct pt_regs *regs, siginfo_t *info,
sigset_t *mask); sigset_t *mask);
......
...@@ -56,11 +56,11 @@ static int copy_ucontext_to_user(struct ucontext *uc, void *fp, sigset_t *set, ...@@ -56,11 +56,11 @@ static int copy_ucontext_to_user(struct ucontext *uc, void *fp, sigset_t *set,
} }
int setup_signal_stack_si(unsigned long stack_top, int sig, int setup_signal_stack_si(unsigned long stack_top, int sig,
unsigned long handler, void (*restorer)(void), struct k_sigaction *ka, struct pt_regs *regs,
struct pt_regs *regs, siginfo_t *info, siginfo_t *info, sigset_t *mask)
sigset_t *mask)
{ {
unsigned long start; unsigned long start;
void *restorer;
void *sip, *ucp, *fp; void *sip, *ucp, *fp;
start = stack_top - signal_frame_si.common.len; start = stack_top - signal_frame_si.common.len;
...@@ -68,6 +68,10 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, ...@@ -68,6 +68,10 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
ucp = (void *) (start + signal_frame_si.uc_index); ucp = (void *) (start + signal_frame_si.uc_index);
fp = (void *) (((unsigned long) ucp) + sizeof(struct ucontext)); fp = (void *) (((unsigned long) ucp) + sizeof(struct ucontext));
restorer = NULL;
if(ka->sa.sa_flags & SA_RESTORER)
restorer = ka->sa.sa_restorer;
if(restorer == NULL) if(restorer == NULL)
panic("setup_signal_stack_si - no restorer"); panic("setup_signal_stack_si - no restorer");
...@@ -85,21 +89,26 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, ...@@ -85,21 +89,26 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
signal_frame_si.common.sr_relative)) signal_frame_si.common.sr_relative))
return(1); return(1);
PT_REGS_IP(regs) = handler; PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
PT_REGS_SP(regs) = start + signal_frame_si.common.sp_index; PT_REGS_SP(regs) = start + signal_frame_si.common.sp_index;
return(0); return(0);
} }
int setup_signal_stack_sc(unsigned long stack_top, int sig, int setup_signal_stack_sc(unsigned long stack_top, int sig,
unsigned long handler, void (*restorer)(void), struct k_sigaction *ka, struct pt_regs *regs,
struct pt_regs *regs, sigset_t *mask) sigset_t *mask)
{ {
struct frame_common *frame = &signal_frame_sc_sr.common; struct frame_common *frame = &signal_frame_sc_sr.common;
void *restorer;
void *user_sc; void *user_sc;
int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long); int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
unsigned long sigs, sr; unsigned long sigs, sr;
unsigned long start = stack_top - frame->len - sig_size; unsigned long start = stack_top - frame->len - sig_size;
restorer = NULL;
if(ka->sa.sa_flags & SA_RESTORER)
restorer = ka->sa.sa_restorer;
user_sc = (void *) (start + signal_frame_sc_sr.sc_index); user_sc = (void *) (start + signal_frame_sc_sr.sc_index);
if(restorer == NULL){ if(restorer == NULL){
frame = &signal_frame_sc.common; frame = &signal_frame_sc.common;
...@@ -121,7 +130,7 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig, ...@@ -121,7 +130,7 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
copy_restorer(restorer, start, frame->sr_index, frame->sr_relative)) copy_restorer(restorer, start, frame->sr_index, frame->sr_relative))
return(1); return(1);
PT_REGS_IP(regs) = handler; PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
PT_REGS_SP(regs) = start + frame->sp_index; PT_REGS_SP(regs) = start + frame->sp_index;
return(0); return(0);
......
...@@ -42,7 +42,6 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr, ...@@ -42,7 +42,6 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr,
struct k_sigaction *ka, siginfo_t *info, struct k_sigaction *ka, siginfo_t *info,
sigset_t *oldset) sigset_t *oldset)
{ {
void (*restorer)(void);
unsigned long sp; unsigned long sp;
int err; int err;
...@@ -75,20 +74,12 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr, ...@@ -75,20 +74,12 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr,
if((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0)) if((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
sp = current->sas_ss_sp + current->sas_ss_size; sp = current->sas_ss_sp + current->sas_ss_size;
if (ka->sa.sa_flags & SA_RESTORER)
restorer = ka->sa.sa_restorer;
else restorer = NULL;
if(ka->sa.sa_flags & SA_SIGINFO) if(ka->sa.sa_flags & SA_SIGINFO)
err = setup_signal_stack_si(sp, signr, err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset);
(unsigned long) ka->sa.sa_handler,
restorer, regs, info, oldset);
else else
err = setup_signal_stack_sc(sp, signr, err = setup_signal_stack_sc(sp, signr, ka, regs, oldset);
(unsigned long) ka->sa.sa_handler,
restorer, regs, oldset);
if (!(ka->sa.sa_flags & SA_NODEFER)) { if (!err && !(ka->sa.sa_flags & SA_NODEFER)) {
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked, &current->blocked, sigorsets(&current->blocked, &current->blocked,
&ka->sa.sa_mask); &ka->sa.sa_mask);
...@@ -107,9 +98,6 @@ static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset) ...@@ -107,9 +98,6 @@ static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset)
siginfo_t info; siginfo_t info;
int sig; int sig;
if (!oldset)
oldset = &current->blocked;
sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL); sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL);
if(sig > 0){ if(sig > 0){
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
...@@ -147,7 +135,7 @@ static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset) ...@@ -147,7 +135,7 @@ static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset)
int do_signal(void) int do_signal(void)
{ {
return(kern_do_signal(&current->thread.regs, NULL)); return(kern_do_signal(&current->thread.regs, &current->blocked));
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment