Message ID | 20180411184556.17200-13-laurent@vivier.eu |
---|---|
State | New |
Headers | show |
Series | move arch specific parts to arch directories | expand |
On 04/11/2018 03:45 PM, Laurent Vivier wrote: > No code change, only move code from signal.c to > tilegx/signal.c, except adding includes and > exporting setup_rt_frame(). > > Signed-off-by: Laurent Vivier <laurent@vivier.eu> > Reviewed-by: Alex Bennée <alex.bennee@linaro.org> > Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> > --- > linux-user/signal.c | 165 ------------------------------------- > linux-user/tilegx/signal.c | 168 ++++++++++++++++++++++++++++++++++++++ > linux-user/tilegx/target_signal.h | 4 +- > 3 files changed, 171 insertions(+), 166 deletions(-) > > diff --git a/linux-user/signal.c b/linux-user/signal.c > index 7c2a963e7c..5a3e5bff5e 100644 > --- a/linux-user/signal.c > +++ b/linux-user/signal.c > @@ -3032,171 +3032,6 @@ sigsegv: > return -TARGET_QEMU_ESIGRETURN; > } > > -#elif defined(TARGET_TILEGX) > - > -struct target_sigcontext { > - union { > - /* General-purpose registers. */ > - abi_ulong gregs[56]; > - struct { > - abi_ulong __gregs[53]; > - abi_ulong tp; /* Aliases gregs[TREG_TP]. */ > - abi_ulong sp; /* Aliases gregs[TREG_SP]. */ > - abi_ulong lr; /* Aliases gregs[TREG_LR]. */ > - }; > - }; > - abi_ulong pc; /* Program counter. */ > - abi_ulong ics; /* In Interrupt Critical Section? */ > - abi_ulong faultnum; /* Fault number. */ > - abi_ulong pad[5]; > -}; > - > -struct target_ucontext { > - abi_ulong tuc_flags; > - abi_ulong tuc_link; > - target_stack_t tuc_stack; > - struct target_sigcontext tuc_mcontext; > - target_sigset_t tuc_sigmask; /* mask last for extensibility */ > -}; > - > -struct target_rt_sigframe { > - unsigned char save_area[16]; /* caller save area */ > - struct target_siginfo info; > - struct target_ucontext uc; > - abi_ulong retcode[2]; > -}; > - > -#define INSN_MOVELI_R10_139 0x00045fe551483000ULL /* { moveli r10, 139 } */ > -#define INSN_SWINT1 0x286b180051485000ULL /* { swint1 } */ > - > - > -static void setup_sigcontext(struct target_sigcontext *sc, > - CPUArchState *env, int signo) > -{ > - int i; > - > - for (i = 0; i < TILEGX_R_COUNT; ++i) { > - __put_user(env->regs[i], &sc->gregs[i]); > - } > - > - __put_user(env->pc, &sc->pc); > - __put_user(0, &sc->ics); > - __put_user(signo, &sc->faultnum); > -} > - > -static void restore_sigcontext(CPUTLGState *env, struct target_sigcontext *sc) > -{ > - int i; > - > - for (i = 0; i < TILEGX_R_COUNT; ++i) { > - __get_user(env->regs[i], &sc->gregs[i]); > - } > - > - __get_user(env->pc, &sc->pc); > -} > - > -static abi_ulong get_sigframe(struct target_sigaction *ka, CPUArchState *env, > - size_t frame_size) > -{ > - unsigned long sp = env->regs[TILEGX_R_SP]; > - > - if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size))) { > - return -1UL; > - } > - > - if ((ka->sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) { > - sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; > - } > - > - sp -= frame_size; > - sp &= -16UL; > - return sp; > -} > - > -static void setup_rt_frame(int sig, struct target_sigaction *ka, > - target_siginfo_t *info, > - target_sigset_t *set, CPUArchState *env) > -{ > - abi_ulong frame_addr; > - struct target_rt_sigframe *frame; > - unsigned long restorer; > - > - frame_addr = get_sigframe(ka, env, sizeof(*frame)); > - trace_user_setup_rt_frame(env, frame_addr); > - if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { > - goto give_sigsegv; > - } > - > - /* Always write at least the signal number for the stack backtracer. */ > - if (ka->sa_flags & TARGET_SA_SIGINFO) { > - /* At sigreturn time, restore the callee-save registers too. */ > - tswap_siginfo(&frame->info, info); > - /* regs->flags |= PT_FLAGS_RESTORE_REGS; FIXME: we can skip it? */ > - } else { > - __put_user(info->si_signo, &frame->info.si_signo); > - } > - > - /* Create the ucontext. */ > - __put_user(0, &frame->uc.tuc_flags); > - __put_user(0, &frame->uc.tuc_link); > - __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp); > - __put_user(sas_ss_flags(env->regs[TILEGX_R_SP]), > - &frame->uc.tuc_stack.ss_flags); > - __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size); > - setup_sigcontext(&frame->uc.tuc_mcontext, env, info->si_signo); > - > - if (ka->sa_flags & TARGET_SA_RESTORER) { > - restorer = (unsigned long) ka->sa_restorer; > - } else { > - __put_user(INSN_MOVELI_R10_139, &frame->retcode[0]); > - __put_user(INSN_SWINT1, &frame->retcode[1]); > - restorer = frame_addr + offsetof(struct target_rt_sigframe, retcode); > - } > - env->pc = (unsigned long) ka->_sa_handler; > - env->regs[TILEGX_R_SP] = (unsigned long) frame; > - env->regs[TILEGX_R_LR] = restorer; > - env->regs[0] = (unsigned long) sig; > - env->regs[1] = (unsigned long) &frame->info; > - env->regs[2] = (unsigned long) &frame->uc; > - /* regs->flags |= PT_FLAGS_CALLER_SAVES; FIXME: we can skip it? */ > - > - unlock_user_struct(frame, frame_addr, 1); > - return; > - > -give_sigsegv: > - force_sigsegv(sig); > -} > - > -long do_rt_sigreturn(CPUTLGState *env) > -{ > - abi_ulong frame_addr = env->regs[TILEGX_R_SP]; > - struct target_rt_sigframe *frame; > - sigset_t set; > - > - trace_user_do_rt_sigreturn(env, frame_addr); > - if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { > - goto badframe; > - } > - target_to_host_sigset(&set, &frame->uc.tuc_sigmask); > - set_sigmask(&set); > - > - restore_sigcontext(env, &frame->uc.tuc_mcontext); > - if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe, > - uc.tuc_stack), > - 0, env->regs[TILEGX_R_SP]) == -EFAULT) { > - goto badframe; > - } > - > - unlock_user_struct(frame, frame_addr, 0); > - return -TARGET_QEMU_ESIGRETURN; > - > - > - badframe: > - unlock_user_struct(frame, frame_addr, 0); > - force_sig(TARGET_SIGSEGV); > - return -TARGET_QEMU_ESIGRETURN; > -} > - > #elif defined(TARGET_RISCV) > > /* Signal handler invocation must be transparent for the code being > diff --git a/linux-user/tilegx/signal.c b/linux-user/tilegx/signal.c > index 02ca338b6c..8f54f54f95 100644 > --- a/linux-user/tilegx/signal.c > +++ b/linux-user/tilegx/signal.c > @@ -16,3 +16,171 @@ > * You should have received a copy of the GNU General Public License > * along with this program; if not, see <http://www.gnu.org/licenses/>. > */ > +#include "qemu/osdep.h" > +#include "qemu.h" > +#include "target_signal.h" > +#include "signal-common.h" > +#include "linux-user/trace.h" > + > +struct target_sigcontext { > + union { > + /* General-purpose registers. */ > + abi_ulong gregs[56]; > + struct { > + abi_ulong __gregs[53]; > + abi_ulong tp; /* Aliases gregs[TREG_TP]. */ > + abi_ulong sp; /* Aliases gregs[TREG_SP]. */ > + abi_ulong lr; /* Aliases gregs[TREG_LR]. */ > + }; > + }; > + abi_ulong pc; /* Program counter. */ > + abi_ulong ics; /* In Interrupt Critical Section? */ > + abi_ulong faultnum; /* Fault number. */ > + abi_ulong pad[5]; > +}; > + > +struct target_ucontext { > + abi_ulong tuc_flags; > + abi_ulong tuc_link; > + target_stack_t tuc_stack; > + struct target_sigcontext tuc_mcontext; > + target_sigset_t tuc_sigmask; /* mask last for extensibility */ > +}; > + > +struct target_rt_sigframe { > + unsigned char save_area[16]; /* caller save area */ > + struct target_siginfo info; > + struct target_ucontext uc; > + abi_ulong retcode[2]; > +}; > + > +#define INSN_MOVELI_R10_139 0x00045fe551483000ULL /* { moveli r10, 139 } */ > +#define INSN_SWINT1 0x286b180051485000ULL /* { swint1 } */ > + > + > +static void setup_sigcontext(struct target_sigcontext *sc, > + CPUArchState *env, int signo) > +{ > + int i; > + > + for (i = 0; i < TILEGX_R_COUNT; ++i) { > + __put_user(env->regs[i], &sc->gregs[i]); > + } > + > + __put_user(env->pc, &sc->pc); > + __put_user(0, &sc->ics); > + __put_user(signo, &sc->faultnum); > +} > + > +static void restore_sigcontext(CPUTLGState *env, struct target_sigcontext *sc) > +{ > + int i; > + > + for (i = 0; i < TILEGX_R_COUNT; ++i) { > + __get_user(env->regs[i], &sc->gregs[i]); > + } > + > + __get_user(env->pc, &sc->pc); > +} > + > +static abi_ulong get_sigframe(struct target_sigaction *ka, CPUArchState *env, > + size_t frame_size) > +{ > + unsigned long sp = env->regs[TILEGX_R_SP]; > + > + if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size))) { > + return -1UL; > + } > + > + if ((ka->sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) { > + sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; > + } > + > + sp -= frame_size; > + sp &= -16UL; > + return sp; > +} > + > +void setup_rt_frame(int sig, struct target_sigaction *ka, > + target_siginfo_t *info, > + target_sigset_t *set, CPUArchState *env) > +{ > + abi_ulong frame_addr; > + struct target_rt_sigframe *frame; > + unsigned long restorer; > + > + frame_addr = get_sigframe(ka, env, sizeof(*frame)); > + trace_user_setup_rt_frame(env, frame_addr); > + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { > + goto give_sigsegv; > + } > + > + /* Always write at least the signal number for the stack backtracer. */ > + if (ka->sa_flags & TARGET_SA_SIGINFO) { > + /* At sigreturn time, restore the callee-save registers too. */ > + tswap_siginfo(&frame->info, info); > + /* regs->flags |= PT_FLAGS_RESTORE_REGS; FIXME: we can skip it? */ > + } else { > + __put_user(info->si_signo, &frame->info.si_signo); > + } > + > + /* Create the ucontext. */ > + __put_user(0, &frame->uc.tuc_flags); > + __put_user(0, &frame->uc.tuc_link); > + __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp); > + __put_user(sas_ss_flags(env->regs[TILEGX_R_SP]), > + &frame->uc.tuc_stack.ss_flags); > + __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size); > + setup_sigcontext(&frame->uc.tuc_mcontext, env, info->si_signo); > + > + if (ka->sa_flags & TARGET_SA_RESTORER) { > + restorer = (unsigned long) ka->sa_restorer; > + } else { > + __put_user(INSN_MOVELI_R10_139, &frame->retcode[0]); > + __put_user(INSN_SWINT1, &frame->retcode[1]); > + restorer = frame_addr + offsetof(struct target_rt_sigframe, retcode); > + } > + env->pc = (unsigned long) ka->_sa_handler; > + env->regs[TILEGX_R_SP] = (unsigned long) frame; > + env->regs[TILEGX_R_LR] = restorer; > + env->regs[0] = (unsigned long) sig; > + env->regs[1] = (unsigned long) &frame->info; > + env->regs[2] = (unsigned long) &frame->uc; > + /* regs->flags |= PT_FLAGS_CALLER_SAVES; FIXME: we can skip it? */ > + > + unlock_user_struct(frame, frame_addr, 1); > + return; > + > +give_sigsegv: > + force_sigsegv(sig); > +} > + > +long do_rt_sigreturn(CPUTLGState *env) > +{ > + abi_ulong frame_addr = env->regs[TILEGX_R_SP]; > + struct target_rt_sigframe *frame; > + sigset_t set; > + > + trace_user_do_rt_sigreturn(env, frame_addr); > + if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { > + goto badframe; > + } > + target_to_host_sigset(&set, &frame->uc.tuc_sigmask); > + set_sigmask(&set); > + > + restore_sigcontext(env, &frame->uc.tuc_mcontext); > + if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe, > + uc.tuc_stack), > + 0, env->regs[TILEGX_R_SP]) == -EFAULT) { > + goto badframe; > + } > + > + unlock_user_struct(frame, frame_addr, 0); > + return -TARGET_QEMU_ESIGRETURN; > + > + > + badframe: > + unlock_user_struct(frame, frame_addr, 0); > + force_sig(TARGET_SIGSEGV); > + return -TARGET_QEMU_ESIGRETURN; > +} > diff --git a/linux-user/tilegx/target_signal.h b/linux-user/tilegx/target_signal.h > index f64551a8cf..132d7781fe 100644 > --- a/linux-user/tilegx/target_signal.h > +++ b/linux-user/tilegx/target_signal.h > @@ -25,5 +25,7 @@ static inline abi_ulong get_sp_from_cpustate(CPUTLGState *state) > return state->regs[TILEGX_R_SP]; > } > > - > +void setup_rt_frame(int sig, struct target_sigaction *ka, > + target_siginfo_t *info, > + target_sigset_t *set, CPUArchState *env); > #endif /* TILEGX_TARGET_SIGNAL_H */ >
diff --git a/linux-user/signal.c b/linux-user/signal.c index 7c2a963e7c..5a3e5bff5e 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -3032,171 +3032,6 @@ sigsegv: return -TARGET_QEMU_ESIGRETURN; } -#elif defined(TARGET_TILEGX) - -struct target_sigcontext { - union { - /* General-purpose registers. */ - abi_ulong gregs[56]; - struct { - abi_ulong __gregs[53]; - abi_ulong tp; /* Aliases gregs[TREG_TP]. */ - abi_ulong sp; /* Aliases gregs[TREG_SP]. */ - abi_ulong lr; /* Aliases gregs[TREG_LR]. */ - }; - }; - abi_ulong pc; /* Program counter. */ - abi_ulong ics; /* In Interrupt Critical Section? */ - abi_ulong faultnum; /* Fault number. */ - abi_ulong pad[5]; -}; - -struct target_ucontext { - abi_ulong tuc_flags; - abi_ulong tuc_link; - target_stack_t tuc_stack; - struct target_sigcontext tuc_mcontext; - target_sigset_t tuc_sigmask; /* mask last for extensibility */ -}; - -struct target_rt_sigframe { - unsigned char save_area[16]; /* caller save area */ - struct target_siginfo info; - struct target_ucontext uc; - abi_ulong retcode[2]; -}; - -#define INSN_MOVELI_R10_139 0x00045fe551483000ULL /* { moveli r10, 139 } */ -#define INSN_SWINT1 0x286b180051485000ULL /* { swint1 } */ - - -static void setup_sigcontext(struct target_sigcontext *sc, - CPUArchState *env, int signo) -{ - int i; - - for (i = 0; i < TILEGX_R_COUNT; ++i) { - __put_user(env->regs[i], &sc->gregs[i]); - } - - __put_user(env->pc, &sc->pc); - __put_user(0, &sc->ics); - __put_user(signo, &sc->faultnum); -} - -static void restore_sigcontext(CPUTLGState *env, struct target_sigcontext *sc) -{ - int i; - - for (i = 0; i < TILEGX_R_COUNT; ++i) { - __get_user(env->regs[i], &sc->gregs[i]); - } - - __get_user(env->pc, &sc->pc); -} - -static abi_ulong get_sigframe(struct target_sigaction *ka, CPUArchState *env, - size_t frame_size) -{ - unsigned long sp = env->regs[TILEGX_R_SP]; - - if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size))) { - return -1UL; - } - - if ((ka->sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) { - sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; - } - - sp -= frame_size; - sp &= -16UL; - return sp; -} - -static void setup_rt_frame(int sig, struct target_sigaction *ka, - target_siginfo_t *info, - target_sigset_t *set, CPUArchState *env) -{ - abi_ulong frame_addr; - struct target_rt_sigframe *frame; - unsigned long restorer; - - frame_addr = get_sigframe(ka, env, sizeof(*frame)); - trace_user_setup_rt_frame(env, frame_addr); - if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { - goto give_sigsegv; - } - - /* Always write at least the signal number for the stack backtracer. */ - if (ka->sa_flags & TARGET_SA_SIGINFO) { - /* At sigreturn time, restore the callee-save registers too. */ - tswap_siginfo(&frame->info, info); - /* regs->flags |= PT_FLAGS_RESTORE_REGS; FIXME: we can skip it? */ - } else { - __put_user(info->si_signo, &frame->info.si_signo); - } - - /* Create the ucontext. */ - __put_user(0, &frame->uc.tuc_flags); - __put_user(0, &frame->uc.tuc_link); - __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp); - __put_user(sas_ss_flags(env->regs[TILEGX_R_SP]), - &frame->uc.tuc_stack.ss_flags); - __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size); - setup_sigcontext(&frame->uc.tuc_mcontext, env, info->si_signo); - - if (ka->sa_flags & TARGET_SA_RESTORER) { - restorer = (unsigned long) ka->sa_restorer; - } else { - __put_user(INSN_MOVELI_R10_139, &frame->retcode[0]); - __put_user(INSN_SWINT1, &frame->retcode[1]); - restorer = frame_addr + offsetof(struct target_rt_sigframe, retcode); - } - env->pc = (unsigned long) ka->_sa_handler; - env->regs[TILEGX_R_SP] = (unsigned long) frame; - env->regs[TILEGX_R_LR] = restorer; - env->regs[0] = (unsigned long) sig; - env->regs[1] = (unsigned long) &frame->info; - env->regs[2] = (unsigned long) &frame->uc; - /* regs->flags |= PT_FLAGS_CALLER_SAVES; FIXME: we can skip it? */ - - unlock_user_struct(frame, frame_addr, 1); - return; - -give_sigsegv: - force_sigsegv(sig); -} - -long do_rt_sigreturn(CPUTLGState *env) -{ - abi_ulong frame_addr = env->regs[TILEGX_R_SP]; - struct target_rt_sigframe *frame; - sigset_t set; - - trace_user_do_rt_sigreturn(env, frame_addr); - if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { - goto badframe; - } - target_to_host_sigset(&set, &frame->uc.tuc_sigmask); - set_sigmask(&set); - - restore_sigcontext(env, &frame->uc.tuc_mcontext); - if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe, - uc.tuc_stack), - 0, env->regs[TILEGX_R_SP]) == -EFAULT) { - goto badframe; - } - - unlock_user_struct(frame, frame_addr, 0); - return -TARGET_QEMU_ESIGRETURN; - - - badframe: - unlock_user_struct(frame, frame_addr, 0); - force_sig(TARGET_SIGSEGV); - return -TARGET_QEMU_ESIGRETURN; -} - #elif defined(TARGET_RISCV) /* Signal handler invocation must be transparent for the code being diff --git a/linux-user/tilegx/signal.c b/linux-user/tilegx/signal.c index 02ca338b6c..8f54f54f95 100644 --- a/linux-user/tilegx/signal.c +++ b/linux-user/tilegx/signal.c @@ -16,3 +16,171 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see <http://www.gnu.org/licenses/>. */ +#include "qemu/osdep.h" +#include "qemu.h" +#include "target_signal.h" +#include "signal-common.h" +#include "linux-user/trace.h" + +struct target_sigcontext { + union { + /* General-purpose registers. */ + abi_ulong gregs[56]; + struct { + abi_ulong __gregs[53]; + abi_ulong tp; /* Aliases gregs[TREG_TP]. */ + abi_ulong sp; /* Aliases gregs[TREG_SP]. */ + abi_ulong lr; /* Aliases gregs[TREG_LR]. */ + }; + }; + abi_ulong pc; /* Program counter. */ + abi_ulong ics; /* In Interrupt Critical Section? */ + abi_ulong faultnum; /* Fault number. */ + abi_ulong pad[5]; +}; + +struct target_ucontext { + abi_ulong tuc_flags; + abi_ulong tuc_link; + target_stack_t tuc_stack; + struct target_sigcontext tuc_mcontext; + target_sigset_t tuc_sigmask; /* mask last for extensibility */ +}; + +struct target_rt_sigframe { + unsigned char save_area[16]; /* caller save area */ + struct target_siginfo info; + struct target_ucontext uc; + abi_ulong retcode[2]; +}; + +#define INSN_MOVELI_R10_139 0x00045fe551483000ULL /* { moveli r10, 139 } */ +#define INSN_SWINT1 0x286b180051485000ULL /* { swint1 } */ + + +static void setup_sigcontext(struct target_sigcontext *sc, + CPUArchState *env, int signo) +{ + int i; + + for (i = 0; i < TILEGX_R_COUNT; ++i) { + __put_user(env->regs[i], &sc->gregs[i]); + } + + __put_user(env->pc, &sc->pc); + __put_user(0, &sc->ics); + __put_user(signo, &sc->faultnum); +} + +static void restore_sigcontext(CPUTLGState *env, struct target_sigcontext *sc) +{ + int i; + + for (i = 0; i < TILEGX_R_COUNT; ++i) { + __get_user(env->regs[i], &sc->gregs[i]); + } + + __get_user(env->pc, &sc->pc); +} + +static abi_ulong get_sigframe(struct target_sigaction *ka, CPUArchState *env, + size_t frame_size) +{ + unsigned long sp = env->regs[TILEGX_R_SP]; + + if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size))) { + return -1UL; + } + + if ((ka->sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) { + sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; + } + + sp -= frame_size; + sp &= -16UL; + return sp; +} + +void setup_rt_frame(int sig, struct target_sigaction *ka, + target_siginfo_t *info, + target_sigset_t *set, CPUArchState *env) +{ + abi_ulong frame_addr; + struct target_rt_sigframe *frame; + unsigned long restorer; + + frame_addr = get_sigframe(ka, env, sizeof(*frame)); + trace_user_setup_rt_frame(env, frame_addr); + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { + goto give_sigsegv; + } + + /* Always write at least the signal number for the stack backtracer. */ + if (ka->sa_flags & TARGET_SA_SIGINFO) { + /* At sigreturn time, restore the callee-save registers too. */ + tswap_siginfo(&frame->info, info); + /* regs->flags |= PT_FLAGS_RESTORE_REGS; FIXME: we can skip it? */ + } else { + __put_user(info->si_signo, &frame->info.si_signo); + } + + /* Create the ucontext. */ + __put_user(0, &frame->uc.tuc_flags); + __put_user(0, &frame->uc.tuc_link); + __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp); + __put_user(sas_ss_flags(env->regs[TILEGX_R_SP]), + &frame->uc.tuc_stack.ss_flags); + __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size); + setup_sigcontext(&frame->uc.tuc_mcontext, env, info->si_signo); + + if (ka->sa_flags & TARGET_SA_RESTORER) { + restorer = (unsigned long) ka->sa_restorer; + } else { + __put_user(INSN_MOVELI_R10_139, &frame->retcode[0]); + __put_user(INSN_SWINT1, &frame->retcode[1]); + restorer = frame_addr + offsetof(struct target_rt_sigframe, retcode); + } + env->pc = (unsigned long) ka->_sa_handler; + env->regs[TILEGX_R_SP] = (unsigned long) frame; + env->regs[TILEGX_R_LR] = restorer; + env->regs[0] = (unsigned long) sig; + env->regs[1] = (unsigned long) &frame->info; + env->regs[2] = (unsigned long) &frame->uc; + /* regs->flags |= PT_FLAGS_CALLER_SAVES; FIXME: we can skip it? */ + + unlock_user_struct(frame, frame_addr, 1); + return; + +give_sigsegv: + force_sigsegv(sig); +} + +long do_rt_sigreturn(CPUTLGState *env) +{ + abi_ulong frame_addr = env->regs[TILEGX_R_SP]; + struct target_rt_sigframe *frame; + sigset_t set; + + trace_user_do_rt_sigreturn(env, frame_addr); + if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { + goto badframe; + } + target_to_host_sigset(&set, &frame->uc.tuc_sigmask); + set_sigmask(&set); + + restore_sigcontext(env, &frame->uc.tuc_mcontext); + if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe, + uc.tuc_stack), + 0, env->regs[TILEGX_R_SP]) == -EFAULT) { + goto badframe; + } + + unlock_user_struct(frame, frame_addr, 0); + return -TARGET_QEMU_ESIGRETURN; + + + badframe: + unlock_user_struct(frame, frame_addr, 0); + force_sig(TARGET_SIGSEGV); + return -TARGET_QEMU_ESIGRETURN; +} diff --git a/linux-user/tilegx/target_signal.h b/linux-user/tilegx/target_signal.h index f64551a8cf..132d7781fe 100644 --- a/linux-user/tilegx/target_signal.h +++ b/linux-user/tilegx/target_signal.h @@ -25,5 +25,7 @@ static inline abi_ulong get_sp_from_cpustate(CPUTLGState *state) return state->regs[TILEGX_R_SP]; } - +void setup_rt_frame(int sig, struct target_sigaction *ka, + target_siginfo_t *info, + target_sigset_t *set, CPUArchState *env); #endif /* TILEGX_TARGET_SIGNAL_H */