diff mbox series

[for,2.13,v2,03/20] linux-user: move arm signal.c parts to arm directory

Message ID 20180323225739.17329-4-laurent@vivier.eu
State New
Headers show
Series linux-user: move arch specific parts to arch directories | expand

Commit Message

Laurent Vivier March 23, 2018, 10:57 p.m. UTC
No code change, only move code from signal.c to
arm/signal.c, except adding includes and
exporting setup_frame() and setup_rt_frame().

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 linux-user/arm/signal.c        | 754 +++++++++++++++++++++++++++++++++++++++++
 linux-user/arm/target_signal.h |   6 +-
 linux-user/signal.c            | 751 ----------------------------------------
 3 files changed, 759 insertions(+), 752 deletions(-)

Comments

Alex Bennée March 28, 2018, 2:34 p.m. UTC | #1
Laurent Vivier <laurent@vivier.eu> writes:

> No code change, only move code from signal.c to
> arm/signal.c, except adding includes and
> exporting setup_frame() and setup_rt_frame().
>
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  linux-user/arm/signal.c        | 754 +++++++++++++++++++++++++++++++++++++++++
>  linux-user/arm/target_signal.h |   6 +-
>  linux-user/signal.c            | 751 ----------------------------------------
>  3 files changed, 759 insertions(+), 752 deletions(-)
>
> diff --git a/linux-user/arm/signal.c b/linux-user/arm/signal.c
> index 02ca338b6c..975f80fdd2 100644
> --- a/linux-user/arm/signal.c
> +++ b/linux-user/arm/signal.c
> @@ -16,3 +16,757 @@
>   *  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 {
> +    abi_ulong trap_no;
> +    abi_ulong error_code;
> +    abi_ulong oldmask;
> +    abi_ulong arm_r0;
> +    abi_ulong arm_r1;
> +    abi_ulong arm_r2;
> +    abi_ulong arm_r3;
> +    abi_ulong arm_r4;
> +    abi_ulong arm_r5;
> +    abi_ulong arm_r6;
> +    abi_ulong arm_r7;
> +    abi_ulong arm_r8;
> +    abi_ulong arm_r9;
> +    abi_ulong arm_r10;
> +    abi_ulong arm_fp;
> +    abi_ulong arm_ip;
> +    abi_ulong arm_sp;
> +    abi_ulong arm_lr;
> +    abi_ulong arm_pc;
> +    abi_ulong arm_cpsr;
> +    abi_ulong fault_address;
> +};
> +
> +struct target_ucontext_v1 {
> +    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_ucontext_v2 {
> +    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 */
> +    char __unused[128 - sizeof(target_sigset_t)];
> +    abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
> +};
> +
> +struct target_user_vfp {
> +    uint64_t fpregs[32];
> +    abi_ulong fpscr;
> +};
> +
> +struct target_user_vfp_exc {
> +    abi_ulong fpexc;
> +    abi_ulong fpinst;
> +    abi_ulong fpinst2;
> +};
> +
> +struct target_vfp_sigframe {
> +    abi_ulong magic;
> +    abi_ulong size;
> +    struct target_user_vfp ufp;
> +    struct target_user_vfp_exc ufp_exc;
> +} __attribute__((__aligned__(8)));
> +
> +struct target_iwmmxt_sigframe {
> +    abi_ulong magic;
> +    abi_ulong size;
> +    uint64_t regs[16];
> +    /* Note that not all the coprocessor control registers are stored here */
> +    uint32_t wcssf;
> +    uint32_t wcasf;
> +    uint32_t wcgr0;
> +    uint32_t wcgr1;
> +    uint32_t wcgr2;
> +    uint32_t wcgr3;
> +} __attribute__((__aligned__(8)));
> +
> +#define TARGET_VFP_MAGIC 0x56465001
> +#define TARGET_IWMMXT_MAGIC 0x12ef842a
> +
> +struct sigframe_v1
> +{
> +    struct target_sigcontext sc;
> +    abi_ulong extramask[TARGET_NSIG_WORDS-1];
> +    abi_ulong retcode;
> +};
> +
> +struct sigframe_v2
> +{
> +    struct target_ucontext_v2 uc;
> +    abi_ulong retcode;
> +};
> +
> +struct rt_sigframe_v1
> +{
> +    abi_ulong pinfo;
> +    abi_ulong puc;
> +    struct target_siginfo info;
> +    struct target_ucontext_v1 uc;
> +    abi_ulong retcode;
> +};
> +
> +struct rt_sigframe_v2
> +{
> +    struct target_siginfo info;
> +    struct target_ucontext_v2 uc;
> +    abi_ulong retcode;
> +};
> +
> +#define TARGET_CONFIG_CPU_32 1
> +
> +/*
> + * For ARM syscalls, we encode the syscall number into the instruction.
> + */
> +#define SWI_SYS_SIGRETURN	(0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
> +#define SWI_SYS_RT_SIGRETURN	(0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
> +
> +/*
> + * For Thumb syscalls, we pass the syscall number via r7.  We therefore
> + * need two 16-bit instructions.
> + */
> +#define SWI_THUMB_SIGRETURN	(0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
> +#define SWI_THUMB_RT_SIGRETURN	(0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
> +
> +static const abi_ulong retcodes[4] = {
> +	SWI_SYS_SIGRETURN,	SWI_THUMB_SIGRETURN,
> +	SWI_SYS_RT_SIGRETURN,	SWI_THUMB_RT_SIGRETURN
> +};
> +
> +
> +static inline int valid_user_regs(CPUARMState *regs)
> +{
> +    return 1;
> +}
> +
> +static void
> +setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
> +                 CPUARMState *env, abi_ulong mask)
> +{
> +    __put_user(env->regs[0], &sc->arm_r0);
> +    __put_user(env->regs[1], &sc->arm_r1);
> +    __put_user(env->regs[2], &sc->arm_r2);
> +    __put_user(env->regs[3], &sc->arm_r3);
> +    __put_user(env->regs[4], &sc->arm_r4);
> +    __put_user(env->regs[5], &sc->arm_r5);
> +    __put_user(env->regs[6], &sc->arm_r6);
> +    __put_user(env->regs[7], &sc->arm_r7);
> +    __put_user(env->regs[8], &sc->arm_r8);
> +    __put_user(env->regs[9], &sc->arm_r9);
> +    __put_user(env->regs[10], &sc->arm_r10);
> +    __put_user(env->regs[11], &sc->arm_fp);
> +    __put_user(env->regs[12], &sc->arm_ip);
> +    __put_user(env->regs[13], &sc->arm_sp);
> +    __put_user(env->regs[14], &sc->arm_lr);
> +    __put_user(env->regs[15], &sc->arm_pc);
> +#ifdef TARGET_CONFIG_CPU_32
> +    __put_user(cpsr_read(env), &sc->arm_cpsr);
> +#endif
> +
> +    __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
> +    __put_user(/* current->thread.error_code */ 0, &sc->error_code);
> +    __put_user(/* current->thread.address */ 0, &sc->fault_address);
> +    __put_user(mask, &sc->oldmask);
> +}
> +
> +static inline abi_ulong
> +get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
> +{
> +    unsigned long sp = regs->regs[13];
> +
> +    /*
> +     * This is the X/Open sanctioned signal stack switching.
> +     */
> +    if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
> +        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
> +    }
> +    /*
> +     * ATPCS B01 mandates 8-byte alignment
> +     */
> +    return (sp - framesize) & ~7;
> +}
> +
> +static void
> +setup_return(CPUARMState *env, struct target_sigaction *ka,
> +             abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
> +{
> +    abi_ulong handler = ka->_sa_handler;
> +    abi_ulong retcode;
> +    int thumb = handler & 1;
> +    uint32_t cpsr = cpsr_read(env);
> +
> +    cpsr &= ~CPSR_IT;
> +    if (thumb) {
> +        cpsr |= CPSR_T;
> +    } else {
> +        cpsr &= ~CPSR_T;
> +    }
> +
> +    if (ka->sa_flags & TARGET_SA_RESTORER) {
> +        retcode = ka->sa_restorer;
> +    } else {
> +        unsigned int idx = thumb;
> +
> +        if (ka->sa_flags & TARGET_SA_SIGINFO) {
> +            idx += 2;
> +        }
> +
> +        __put_user(retcodes[idx], rc);
> +
> +        retcode = rc_addr + thumb;
> +    }
> +
> +    env->regs[0] = usig;
> +    env->regs[13] = frame_addr;
> +    env->regs[14] = retcode;
> +    env->regs[15] = handler & (thumb ? ~1 : ~3);
> +    cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
> +}
> +
> +static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
> +{
> +    int i;
> +    struct target_vfp_sigframe *vfpframe;
> +    vfpframe = (struct target_vfp_sigframe *)regspace;
> +    __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
> +    __put_user(sizeof(*vfpframe), &vfpframe->size);
> +    for (i = 0; i < 32; i++) {
> +        __put_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
> +    }
> +    __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
> +    __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
> +    __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
> +    __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
> +    return (abi_ulong*)(vfpframe+1);
> +}
> +
> +static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
> +                                           CPUARMState *env)
> +{
> +    int i;
> +    struct target_iwmmxt_sigframe *iwmmxtframe;
> +    iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
> +    __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
> +    __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
> +    for (i = 0; i < 16; i++) {
> +        __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
> +    }
> +    __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
> +    __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
> +    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
> +    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
> +    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
> +    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
> +    return (abi_ulong*)(iwmmxtframe+1);
> +}
> +
> +static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
> +                              target_sigset_t *set, CPUARMState *env)
> +{
> +    struct target_sigaltstack stack;
> +    int i;
> +    abi_ulong *regspace;
> +
> +    /* Clear all the bits of the ucontext we don't use.  */
> +    memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
> +
> +    memset(&stack, 0, sizeof(stack));
> +    __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
> +    __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
> +    __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
> +    memcpy(&uc->tuc_stack, &stack, sizeof(stack));
> +
> +    setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
> +    /* Save coprocessor signal frame.  */
> +    regspace = uc->tuc_regspace;
> +    if (arm_feature(env, ARM_FEATURE_VFP)) {
> +        regspace = setup_sigframe_v2_vfp(regspace, env);
> +    }
> +    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
> +        regspace = setup_sigframe_v2_iwmmxt(regspace, env);
> +    }
> +
> +    /* Write terminating magic word */
> +    __put_user(0, regspace);
> +
> +    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
> +        __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
> +    }
> +}
> +
> +/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
> +static void setup_frame_v1(int usig, struct target_sigaction *ka,
> +                           target_sigset_t *set, CPUARMState *regs)
> +{
> +    struct sigframe_v1 *frame;
> +    abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
> +    int i;
> +
> +    trace_user_setup_frame(regs, frame_addr);
> +    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
> +        goto sigsegv;
> +    }
> +
> +    setup_sigcontext(&frame->sc, regs, set->sig[0]);
> +
> +    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
> +        __put_user(set->sig[i], &frame->extramask[i - 1]);
> +    }
> +
> +    setup_return(regs, ka, &frame->retcode, frame_addr, usig,
> +                 frame_addr + offsetof(struct sigframe_v1, retcode));
> +
> +    unlock_user_struct(frame, frame_addr, 1);
> +    return;
> +sigsegv:
> +    force_sigsegv(usig);
> +}
> +
> +static void setup_frame_v2(int usig, struct target_sigaction *ka,
> +                           target_sigset_t *set, CPUARMState *regs)
> +{
> +    struct sigframe_v2 *frame;
> +    abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
> +
> +    trace_user_setup_frame(regs, frame_addr);
> +    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
> +        goto sigsegv;
> +    }
> +
> +    setup_sigframe_v2(&frame->uc, set, regs);
> +
> +    setup_return(regs, ka, &frame->retcode, frame_addr, usig,
> +                 frame_addr + offsetof(struct sigframe_v2, retcode));
> +
> +    unlock_user_struct(frame, frame_addr, 1);
> +    return;
> +sigsegv:
> +    force_sigsegv(usig);
> +}
> +
> +void setup_frame(int usig, struct target_sigaction *ka,
> +                 target_sigset_t *set, CPUARMState *regs)
> +{
> +    if (get_osversion() >= 0x020612) {
> +        setup_frame_v2(usig, ka, set, regs);
> +    } else {
> +        setup_frame_v1(usig, ka, set, regs);
> +    }
> +}
> +
> +/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
> +static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
> +                              target_siginfo_t *info,
> +                              target_sigset_t *set, CPUARMState *env)
> +{
> +    struct rt_sigframe_v1 *frame;
> +    abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
> +    struct target_sigaltstack stack;
> +    int i;
> +    abi_ulong info_addr, uc_addr;
> +
> +    trace_user_setup_rt_frame(env, frame_addr);
> +    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
> +        goto sigsegv;
> +    }
> +
> +    info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
> +    __put_user(info_addr, &frame->pinfo);
> +    uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
> +    __put_user(uc_addr, &frame->puc);
> +    tswap_siginfo(&frame->info, info);
> +
> +    /* Clear all the bits of the ucontext we don't use.  */
> +    memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
> +
> +    memset(&stack, 0, sizeof(stack));
> +    __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
> +    __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
> +    __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
> +    memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
> +
> +    setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
> +    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
> +        __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
> +    }
> +
> +    setup_return(env, ka, &frame->retcode, frame_addr, usig,
> +                 frame_addr + offsetof(struct rt_sigframe_v1, retcode));
> +
> +    env->regs[1] = info_addr;
> +    env->regs[2] = uc_addr;
> +
> +    unlock_user_struct(frame, frame_addr, 1);
> +    return;
> +sigsegv:
> +    force_sigsegv(usig);
> +}
> +
> +static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
> +                              target_siginfo_t *info,
> +                              target_sigset_t *set, CPUARMState *env)
> +{
> +    struct rt_sigframe_v2 *frame;
> +    abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
> +    abi_ulong info_addr, uc_addr;
> +
> +    trace_user_setup_rt_frame(env, frame_addr);
> +    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
> +        goto sigsegv;
> +    }
> +
> +    info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
> +    uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
> +    tswap_siginfo(&frame->info, info);
> +
> +    setup_sigframe_v2(&frame->uc, set, env);
> +
> +    setup_return(env, ka, &frame->retcode, frame_addr, usig,
> +                 frame_addr + offsetof(struct rt_sigframe_v2, retcode));
> +
> +    env->regs[1] = info_addr;
> +    env->regs[2] = uc_addr;
> +
> +    unlock_user_struct(frame, frame_addr, 1);
> +    return;
> +sigsegv:
> +    force_sigsegv(usig);
> +}
> +
> +void setup_rt_frame(int usig, struct target_sigaction *ka,
> +                    target_siginfo_t *info,
> +                    target_sigset_t *set, CPUARMState *env)
> +{
> +    if (get_osversion() >= 0x020612) {
> +        setup_rt_frame_v2(usig, ka, info, set, env);
> +    } else {
> +        setup_rt_frame_v1(usig, ka, info, set, env);
> +    }
> +}
> +
> +static int
> +restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
> +{
> +    int err = 0;
> +    uint32_t cpsr;
> +
> +    __get_user(env->regs[0], &sc->arm_r0);
> +    __get_user(env->regs[1], &sc->arm_r1);
> +    __get_user(env->regs[2], &sc->arm_r2);
> +    __get_user(env->regs[3], &sc->arm_r3);
> +    __get_user(env->regs[4], &sc->arm_r4);
> +    __get_user(env->regs[5], &sc->arm_r5);
> +    __get_user(env->regs[6], &sc->arm_r6);
> +    __get_user(env->regs[7], &sc->arm_r7);
> +    __get_user(env->regs[8], &sc->arm_r8);
> +    __get_user(env->regs[9], &sc->arm_r9);
> +    __get_user(env->regs[10], &sc->arm_r10);
> +    __get_user(env->regs[11], &sc->arm_fp);
> +    __get_user(env->regs[12], &sc->arm_ip);
> +    __get_user(env->regs[13], &sc->arm_sp);
> +    __get_user(env->regs[14], &sc->arm_lr);
> +    __get_user(env->regs[15], &sc->arm_pc);
> +#ifdef TARGET_CONFIG_CPU_32
> +    __get_user(cpsr, &sc->arm_cpsr);
> +    cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
> +#endif
> +
> +    err |= !valid_user_regs(env);
> +
> +    return err;
> +}
> +
> +static long do_sigreturn_v1(CPUARMState *env)
> +{
> +    abi_ulong frame_addr;
> +    struct sigframe_v1 *frame = NULL;
> +    target_sigset_t set;
> +    sigset_t host_set;
> +    int i;
> +
> +    /*
> +     * Since we stacked the signal on a 64-bit boundary,
> +     * then 'sp' should be word aligned here.  If it's
> +     * not, then the user is trying to mess with us.
> +     */
> +    frame_addr = env->regs[13];
> +    trace_user_do_sigreturn(env, frame_addr);
> +    if (frame_addr & 7) {
> +        goto badframe;
> +    }
> +
> +    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
> +        goto badframe;
> +    }
> +
> +    __get_user(set.sig[0], &frame->sc.oldmask);
> +    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
> +        __get_user(set.sig[i], &frame->extramask[i - 1]);
> +    }
> +
> +    target_to_host_sigset_internal(&host_set, &set);
> +    set_sigmask(&host_set);
> +
> +    if (restore_sigcontext(env, &frame->sc)) {
> +        goto badframe;
> +    }
> +
> +#if 0
> +    /* Send SIGTRAP if we're single-stepping */
> +    if (ptrace_cancel_bpt(current))
> +        send_sig(SIGTRAP, current, 1);
> +#endif
> +    unlock_user_struct(frame, frame_addr, 0);
> +    return -TARGET_QEMU_ESIGRETURN;
> +
> +badframe:
> +    force_sig(TARGET_SIGSEGV);
> +    return -TARGET_QEMU_ESIGRETURN;
> +}
> +
> +static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
> +{
> +    int i;
> +    abi_ulong magic, sz;
> +    uint32_t fpscr, fpexc;
> +    struct target_vfp_sigframe *vfpframe;
> +    vfpframe = (struct target_vfp_sigframe *)regspace;
> +
> +    __get_user(magic, &vfpframe->magic);
> +    __get_user(sz, &vfpframe->size);
> +    if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
> +        return 0;
> +    }
> +    for (i = 0; i < 32; i++) {
> +        __get_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
> +    }
> +    __get_user(fpscr, &vfpframe->ufp.fpscr);
> +    vfp_set_fpscr(env, fpscr);
> +    __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
> +    /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
> +     * and the exception flag is cleared
> +     */
> +    fpexc |= (1 << 30);
> +    fpexc &= ~((1 << 31) | (1 << 28));
> +    env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
> +    __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
> +    __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
> +    return (abi_ulong*)(vfpframe + 1);
> +}
> +
> +static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
> +                                             abi_ulong *regspace)
> +{
> +    int i;
> +    abi_ulong magic, sz;
> +    struct target_iwmmxt_sigframe *iwmmxtframe;
> +    iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
> +
> +    __get_user(magic, &iwmmxtframe->magic);
> +    __get_user(sz, &iwmmxtframe->size);
> +    if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
> +        return 0;
> +    }
> +    for (i = 0; i < 16; i++) {
> +        __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
> +    }
> +    __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
> +    __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
> +    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
> +    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
> +    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
> +    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
> +    return (abi_ulong*)(iwmmxtframe + 1);
> +}
> +
> +static int do_sigframe_return_v2(CPUARMState *env,
> +                                 target_ulong context_addr,
> +                                 struct target_ucontext_v2 *uc)
> +{
> +    sigset_t host_set;
> +    abi_ulong *regspace;
> +
> +    target_to_host_sigset(&host_set, &uc->tuc_sigmask);
> +    set_sigmask(&host_set);
> +
> +    if (restore_sigcontext(env, &uc->tuc_mcontext))
> +        return 1;
> +
> +    /* Restore coprocessor signal frame */
> +    regspace = uc->tuc_regspace;
> +    if (arm_feature(env, ARM_FEATURE_VFP)) {
> +        regspace = restore_sigframe_v2_vfp(env, regspace);
> +        if (!regspace) {
> +            return 1;
> +        }
> +    }
> +    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
> +        regspace = restore_sigframe_v2_iwmmxt(env, regspace);
> +        if (!regspace) {
> +            return 1;
> +        }
> +    }
> +
> +    if (do_sigaltstack(context_addr
> +                       + offsetof(struct target_ucontext_v2, tuc_stack),
> +                       0, get_sp_from_cpustate(env)) == -EFAULT) {
> +        return 1;
> +    }
> +
> +#if 0
> +    /* Send SIGTRAP if we're single-stepping */
> +    if (ptrace_cancel_bpt(current))
> +        send_sig(SIGTRAP, current, 1);
> +#endif
> +
> +    return 0;
> +}
> +
> +static long do_sigreturn_v2(CPUARMState *env)
> +{
> +    abi_ulong frame_addr;
> +    struct sigframe_v2 *frame = NULL;
> +
> +    /*
> +     * Since we stacked the signal on a 64-bit boundary,
> +     * then 'sp' should be word aligned here.  If it's
> +     * not, then the user is trying to mess with us.
> +     */
> +    frame_addr = env->regs[13];
> +    trace_user_do_sigreturn(env, frame_addr);
> +    if (frame_addr & 7) {
> +        goto badframe;
> +    }
> +
> +    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
> +        goto badframe;
> +    }
> +
> +    if (do_sigframe_return_v2(env,
> +                              frame_addr
> +                              + offsetof(struct sigframe_v2, uc),
> +                              &frame->uc)) {
> +        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;
> +}
> +
> +long do_sigreturn(CPUARMState *env)
> +{
> +    if (get_osversion() >= 0x020612) {
> +        return do_sigreturn_v2(env);
> +    } else {
> +        return do_sigreturn_v1(env);
> +    }
> +}
> +
> +static long do_rt_sigreturn_v1(CPUARMState *env)
> +{
> +    abi_ulong frame_addr;
> +    struct rt_sigframe_v1 *frame = NULL;
> +    sigset_t host_set;
> +
> +    /*
> +     * Since we stacked the signal on a 64-bit boundary,
> +     * then 'sp' should be word aligned here.  If it's
> +     * not, then the user is trying to mess with us.
> +     */
> +    frame_addr = env->regs[13];
> +    trace_user_do_rt_sigreturn(env, frame_addr);
> +    if (frame_addr & 7) {
> +        goto badframe;
> +    }
> +
> +    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
> +        goto badframe;
> +    }
> +
> +    target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
> +    set_sigmask(&host_set);
> +
> +    if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
> +        goto badframe;
> +    }
> +
> +    if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
> +        goto badframe;
> +
> +#if 0
> +    /* Send SIGTRAP if we're single-stepping */
> +    if (ptrace_cancel_bpt(current))
> +        send_sig(SIGTRAP, current, 1);
> +#endif
> +    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;
> +}
> +
> +static long do_rt_sigreturn_v2(CPUARMState *env)
> +{
> +    abi_ulong frame_addr;
> +    struct rt_sigframe_v2 *frame = NULL;
> +
> +    /*
> +     * Since we stacked the signal on a 64-bit boundary,
> +     * then 'sp' should be word aligned here.  If it's
> +     * not, then the user is trying to mess with us.
> +     */
> +    frame_addr = env->regs[13];
> +    trace_user_do_rt_sigreturn(env, frame_addr);
> +    if (frame_addr & 7) {
> +        goto badframe;
> +    }
> +
> +    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
> +        goto badframe;
> +    }
> +
> +    if (do_sigframe_return_v2(env,
> +                              frame_addr
> +                              + offsetof(struct rt_sigframe_v2, uc),
> +                              &frame->uc)) {
> +        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;
> +}
> +
> +long do_rt_sigreturn(CPUARMState *env)
> +{
> +    if (get_osversion() >= 0x020612) {
> +        return do_rt_sigreturn_v2(env);
> +    } else {
> +        return do_rt_sigreturn_v1(env);
> +    }
> +}
> diff --git a/linux-user/arm/target_signal.h b/linux-user/arm/target_signal.h
> index cbbeb09f4d..4b542c324f 100644
> --- a/linux-user/arm/target_signal.h
> +++ b/linux-user/arm/target_signal.h
> @@ -26,5 +26,9 @@ static inline abi_ulong get_sp_from_cpustate(CPUARMState *state)
>     return state->regs[13];
>  }
>
> -
> +void setup_frame(int usig, struct target_sigaction *ka,
> +                 target_sigset_t *set, CPUARMState *regs);
> +void setup_rt_frame(int usig, struct target_sigaction *ka,
> +                    target_siginfo_t *info,
> +                    target_sigset_t *set, CPUARMState *env);
>  #endif /* ARM_TARGET_SIGNAL_H */
> diff --git a/linux-user/signal.c b/linux-user/signal.c
> index 2b05d7951b..38ebba9cf6 100644
> --- a/linux-user/signal.c
> +++ b/linux-user/signal.c
> @@ -1383,757 +1383,6 @@ badframe:
>      return -TARGET_QEMU_ESIGRETURN;
>  }
>
> -#elif defined(TARGET_ARM) && !defined(TARGET_AARCH64)
> -
> -struct target_sigcontext {
> -    abi_ulong trap_no;
> -    abi_ulong error_code;
> -    abi_ulong oldmask;
> -    abi_ulong arm_r0;
> -    abi_ulong arm_r1;
> -    abi_ulong arm_r2;
> -    abi_ulong arm_r3;
> -    abi_ulong arm_r4;
> -    abi_ulong arm_r5;
> -    abi_ulong arm_r6;
> -    abi_ulong arm_r7;
> -    abi_ulong arm_r8;
> -    abi_ulong arm_r9;
> -    abi_ulong arm_r10;
> -    abi_ulong arm_fp;
> -    abi_ulong arm_ip;
> -    abi_ulong arm_sp;
> -    abi_ulong arm_lr;
> -    abi_ulong arm_pc;
> -    abi_ulong arm_cpsr;
> -    abi_ulong fault_address;
> -};
> -
> -struct target_ucontext_v1 {
> -    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_ucontext_v2 {
> -    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 */
> -    char __unused[128 - sizeof(target_sigset_t)];
> -    abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
> -};
> -
> -struct target_user_vfp {
> -    uint64_t fpregs[32];
> -    abi_ulong fpscr;
> -};
> -
> -struct target_user_vfp_exc {
> -    abi_ulong fpexc;
> -    abi_ulong fpinst;
> -    abi_ulong fpinst2;
> -};
> -
> -struct target_vfp_sigframe {
> -    abi_ulong magic;
> -    abi_ulong size;
> -    struct target_user_vfp ufp;
> -    struct target_user_vfp_exc ufp_exc;
> -} __attribute__((__aligned__(8)));
> -
> -struct target_iwmmxt_sigframe {
> -    abi_ulong magic;
> -    abi_ulong size;
> -    uint64_t regs[16];
> -    /* Note that not all the coprocessor control registers are stored here */
> -    uint32_t wcssf;
> -    uint32_t wcasf;
> -    uint32_t wcgr0;
> -    uint32_t wcgr1;
> -    uint32_t wcgr2;
> -    uint32_t wcgr3;
> -} __attribute__((__aligned__(8)));
> -
> -#define TARGET_VFP_MAGIC 0x56465001
> -#define TARGET_IWMMXT_MAGIC 0x12ef842a
> -
> -struct sigframe_v1
> -{
> -    struct target_sigcontext sc;
> -    abi_ulong extramask[TARGET_NSIG_WORDS-1];
> -    abi_ulong retcode;
> -};
> -
> -struct sigframe_v2
> -{
> -    struct target_ucontext_v2 uc;
> -    abi_ulong retcode;
> -};
> -
> -struct rt_sigframe_v1
> -{
> -    abi_ulong pinfo;
> -    abi_ulong puc;
> -    struct target_siginfo info;
> -    struct target_ucontext_v1 uc;
> -    abi_ulong retcode;
> -};
> -
> -struct rt_sigframe_v2
> -{
> -    struct target_siginfo info;
> -    struct target_ucontext_v2 uc;
> -    abi_ulong retcode;
> -};
> -
> -#define TARGET_CONFIG_CPU_32 1
> -
> -/*
> - * For ARM syscalls, we encode the syscall number into the instruction.
> - */
> -#define SWI_SYS_SIGRETURN	(0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
> -#define SWI_SYS_RT_SIGRETURN	(0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
> -
> -/*
> - * For Thumb syscalls, we pass the syscall number via r7.  We therefore
> - * need two 16-bit instructions.
> - */
> -#define SWI_THUMB_SIGRETURN	(0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
> -#define SWI_THUMB_RT_SIGRETURN	(0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
> -
> -static const abi_ulong retcodes[4] = {
> -	SWI_SYS_SIGRETURN,	SWI_THUMB_SIGRETURN,
> -	SWI_SYS_RT_SIGRETURN,	SWI_THUMB_RT_SIGRETURN
> -};
> -
> -
> -static inline int valid_user_regs(CPUARMState *regs)
> -{
> -    return 1;
> -}
> -
> -static void
> -setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
> -                 CPUARMState *env, abi_ulong mask)
> -{
> -    __put_user(env->regs[0], &sc->arm_r0);
> -    __put_user(env->regs[1], &sc->arm_r1);
> -    __put_user(env->regs[2], &sc->arm_r2);
> -    __put_user(env->regs[3], &sc->arm_r3);
> -    __put_user(env->regs[4], &sc->arm_r4);
> -    __put_user(env->regs[5], &sc->arm_r5);
> -    __put_user(env->regs[6], &sc->arm_r6);
> -    __put_user(env->regs[7], &sc->arm_r7);
> -    __put_user(env->regs[8], &sc->arm_r8);
> -    __put_user(env->regs[9], &sc->arm_r9);
> -    __put_user(env->regs[10], &sc->arm_r10);
> -    __put_user(env->regs[11], &sc->arm_fp);
> -    __put_user(env->regs[12], &sc->arm_ip);
> -    __put_user(env->regs[13], &sc->arm_sp);
> -    __put_user(env->regs[14], &sc->arm_lr);
> -    __put_user(env->regs[15], &sc->arm_pc);
> -#ifdef TARGET_CONFIG_CPU_32
> -    __put_user(cpsr_read(env), &sc->arm_cpsr);
> -#endif
> -
> -    __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
> -    __put_user(/* current->thread.error_code */ 0, &sc->error_code);
> -    __put_user(/* current->thread.address */ 0, &sc->fault_address);
> -    __put_user(mask, &sc->oldmask);
> -}
> -
> -static inline abi_ulong
> -get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
> -{
> -    unsigned long sp = regs->regs[13];
> -
> -    /*
> -     * This is the X/Open sanctioned signal stack switching.
> -     */
> -    if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
> -        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
> -    }
> -    /*
> -     * ATPCS B01 mandates 8-byte alignment
> -     */
> -    return (sp - framesize) & ~7;
> -}
> -
> -static void
> -setup_return(CPUARMState *env, struct target_sigaction *ka,
> -             abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
> -{
> -    abi_ulong handler = ka->_sa_handler;
> -    abi_ulong retcode;
> -    int thumb = handler & 1;
> -    uint32_t cpsr = cpsr_read(env);
> -
> -    cpsr &= ~CPSR_IT;
> -    if (thumb) {
> -        cpsr |= CPSR_T;
> -    } else {
> -        cpsr &= ~CPSR_T;
> -    }
> -
> -    if (ka->sa_flags & TARGET_SA_RESTORER) {
> -        retcode = ka->sa_restorer;
> -    } else {
> -        unsigned int idx = thumb;
> -
> -        if (ka->sa_flags & TARGET_SA_SIGINFO) {
> -            idx += 2;
> -        }
> -
> -        __put_user(retcodes[idx], rc);
> -
> -        retcode = rc_addr + thumb;
> -    }
> -
> -    env->regs[0] = usig;
> -    env->regs[13] = frame_addr;
> -    env->regs[14] = retcode;
> -    env->regs[15] = handler & (thumb ? ~1 : ~3);
> -    cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
> -}
> -
> -static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
> -{
> -    int i;
> -    struct target_vfp_sigframe *vfpframe;
> -    vfpframe = (struct target_vfp_sigframe *)regspace;
> -    __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
> -    __put_user(sizeof(*vfpframe), &vfpframe->size);
> -    for (i = 0; i < 32; i++) {
> -        __put_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
> -    }
> -    __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
> -    __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
> -    __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
> -    __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
> -    return (abi_ulong*)(vfpframe+1);
> -}
> -
> -static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
> -                                           CPUARMState *env)
> -{
> -    int i;
> -    struct target_iwmmxt_sigframe *iwmmxtframe;
> -    iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
> -    __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
> -    __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
> -    for (i = 0; i < 16; i++) {
> -        __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
> -    }
> -    __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
> -    __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
> -    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
> -    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
> -    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
> -    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
> -    return (abi_ulong*)(iwmmxtframe+1);
> -}
> -
> -static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
> -                              target_sigset_t *set, CPUARMState *env)
> -{
> -    struct target_sigaltstack stack;
> -    int i;
> -    abi_ulong *regspace;
> -
> -    /* Clear all the bits of the ucontext we don't use.  */
> -    memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
> -
> -    memset(&stack, 0, sizeof(stack));
> -    __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
> -    __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
> -    __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
> -    memcpy(&uc->tuc_stack, &stack, sizeof(stack));
> -
> -    setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
> -    /* Save coprocessor signal frame.  */
> -    regspace = uc->tuc_regspace;
> -    if (arm_feature(env, ARM_FEATURE_VFP)) {
> -        regspace = setup_sigframe_v2_vfp(regspace, env);
> -    }
> -    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
> -        regspace = setup_sigframe_v2_iwmmxt(regspace, env);
> -    }
> -
> -    /* Write terminating magic word */
> -    __put_user(0, regspace);
> -
> -    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
> -        __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
> -    }
> -}
> -
> -/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
> -static void setup_frame_v1(int usig, struct target_sigaction *ka,
> -                           target_sigset_t *set, CPUARMState *regs)
> -{
> -    struct sigframe_v1 *frame;
> -    abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
> -    int i;
> -
> -    trace_user_setup_frame(regs, frame_addr);
> -    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
> -        goto sigsegv;
> -    }
> -
> -    setup_sigcontext(&frame->sc, regs, set->sig[0]);
> -
> -    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
> -        __put_user(set->sig[i], &frame->extramask[i - 1]);
> -    }
> -
> -    setup_return(regs, ka, &frame->retcode, frame_addr, usig,
> -                 frame_addr + offsetof(struct sigframe_v1, retcode));
> -
> -    unlock_user_struct(frame, frame_addr, 1);
> -    return;
> -sigsegv:
> -    force_sigsegv(usig);
> -}
> -
> -static void setup_frame_v2(int usig, struct target_sigaction *ka,
> -                           target_sigset_t *set, CPUARMState *regs)
> -{
> -    struct sigframe_v2 *frame;
> -    abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
> -
> -    trace_user_setup_frame(regs, frame_addr);
> -    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
> -        goto sigsegv;
> -    }
> -
> -    setup_sigframe_v2(&frame->uc, set, regs);
> -
> -    setup_return(regs, ka, &frame->retcode, frame_addr, usig,
> -                 frame_addr + offsetof(struct sigframe_v2, retcode));
> -
> -    unlock_user_struct(frame, frame_addr, 1);
> -    return;
> -sigsegv:
> -    force_sigsegv(usig);
> -}
> -
> -static void setup_frame(int usig, struct target_sigaction *ka,
> -                        target_sigset_t *set, CPUARMState *regs)
> -{
> -    if (get_osversion() >= 0x020612) {
> -        setup_frame_v2(usig, ka, set, regs);
> -    } else {
> -        setup_frame_v1(usig, ka, set, regs);
> -    }
> -}
> -
> -/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
> -static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
> -                              target_siginfo_t *info,
> -                              target_sigset_t *set, CPUARMState *env)
> -{
> -    struct rt_sigframe_v1 *frame;
> -    abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
> -    struct target_sigaltstack stack;
> -    int i;
> -    abi_ulong info_addr, uc_addr;
> -
> -    trace_user_setup_rt_frame(env, frame_addr);
> -    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
> -        goto sigsegv;
> -    }
> -
> -    info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
> -    __put_user(info_addr, &frame->pinfo);
> -    uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
> -    __put_user(uc_addr, &frame->puc);
> -    tswap_siginfo(&frame->info, info);
> -
> -    /* Clear all the bits of the ucontext we don't use.  */
> -    memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
> -
> -    memset(&stack, 0, sizeof(stack));
> -    __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
> -    __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
> -    __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
> -    memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
> -
> -    setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
> -    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
> -        __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
> -    }
> -
> -    setup_return(env, ka, &frame->retcode, frame_addr, usig,
> -                 frame_addr + offsetof(struct rt_sigframe_v1, retcode));
> -
> -    env->regs[1] = info_addr;
> -    env->regs[2] = uc_addr;
> -
> -    unlock_user_struct(frame, frame_addr, 1);
> -    return;
> -sigsegv:
> -    force_sigsegv(usig);
> -}
> -
> -static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
> -                              target_siginfo_t *info,
> -                              target_sigset_t *set, CPUARMState *env)
> -{
> -    struct rt_sigframe_v2 *frame;
> -    abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
> -    abi_ulong info_addr, uc_addr;
> -
> -    trace_user_setup_rt_frame(env, frame_addr);
> -    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
> -        goto sigsegv;
> -    }
> -
> -    info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
> -    uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
> -    tswap_siginfo(&frame->info, info);
> -
> -    setup_sigframe_v2(&frame->uc, set, env);
> -
> -    setup_return(env, ka, &frame->retcode, frame_addr, usig,
> -                 frame_addr + offsetof(struct rt_sigframe_v2, retcode));
> -
> -    env->regs[1] = info_addr;
> -    env->regs[2] = uc_addr;
> -
> -    unlock_user_struct(frame, frame_addr, 1);
> -    return;
> -sigsegv:
> -    force_sigsegv(usig);
> -}
> -
> -static void setup_rt_frame(int usig, struct target_sigaction *ka,
> -                           target_siginfo_t *info,
> -                           target_sigset_t *set, CPUARMState *env)
> -{
> -    if (get_osversion() >= 0x020612) {
> -        setup_rt_frame_v2(usig, ka, info, set, env);
> -    } else {
> -        setup_rt_frame_v1(usig, ka, info, set, env);
> -    }
> -}
> -
> -static int
> -restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
> -{
> -    int err = 0;
> -    uint32_t cpsr;
> -
> -    __get_user(env->regs[0], &sc->arm_r0);
> -    __get_user(env->regs[1], &sc->arm_r1);
> -    __get_user(env->regs[2], &sc->arm_r2);
> -    __get_user(env->regs[3], &sc->arm_r3);
> -    __get_user(env->regs[4], &sc->arm_r4);
> -    __get_user(env->regs[5], &sc->arm_r5);
> -    __get_user(env->regs[6], &sc->arm_r6);
> -    __get_user(env->regs[7], &sc->arm_r7);
> -    __get_user(env->regs[8], &sc->arm_r8);
> -    __get_user(env->regs[9], &sc->arm_r9);
> -    __get_user(env->regs[10], &sc->arm_r10);
> -    __get_user(env->regs[11], &sc->arm_fp);
> -    __get_user(env->regs[12], &sc->arm_ip);
> -    __get_user(env->regs[13], &sc->arm_sp);
> -    __get_user(env->regs[14], &sc->arm_lr);
> -    __get_user(env->regs[15], &sc->arm_pc);
> -#ifdef TARGET_CONFIG_CPU_32
> -    __get_user(cpsr, &sc->arm_cpsr);
> -    cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
> -#endif
> -
> -    err |= !valid_user_regs(env);
> -
> -    return err;
> -}
> -
> -static long do_sigreturn_v1(CPUARMState *env)
> -{
> -    abi_ulong frame_addr;
> -    struct sigframe_v1 *frame = NULL;
> -    target_sigset_t set;
> -    sigset_t host_set;
> -    int i;
> -
> -    /*
> -     * Since we stacked the signal on a 64-bit boundary,
> -     * then 'sp' should be word aligned here.  If it's
> -     * not, then the user is trying to mess with us.
> -     */
> -    frame_addr = env->regs[13];
> -    trace_user_do_sigreturn(env, frame_addr);
> -    if (frame_addr & 7) {
> -        goto badframe;
> -    }
> -
> -    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
> -        goto badframe;
> -    }
> -
> -    __get_user(set.sig[0], &frame->sc.oldmask);
> -    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
> -        __get_user(set.sig[i], &frame->extramask[i - 1]);
> -    }
> -
> -    target_to_host_sigset_internal(&host_set, &set);
> -    set_sigmask(&host_set);
> -
> -    if (restore_sigcontext(env, &frame->sc)) {
> -        goto badframe;
> -    }
> -
> -#if 0
> -    /* Send SIGTRAP if we're single-stepping */
> -    if (ptrace_cancel_bpt(current))
> -        send_sig(SIGTRAP, current, 1);
> -#endif
> -    unlock_user_struct(frame, frame_addr, 0);
> -    return -TARGET_QEMU_ESIGRETURN;
> -
> -badframe:
> -    force_sig(TARGET_SIGSEGV);
> -    return -TARGET_QEMU_ESIGRETURN;
> -}
> -
> -static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
> -{
> -    int i;
> -    abi_ulong magic, sz;
> -    uint32_t fpscr, fpexc;
> -    struct target_vfp_sigframe *vfpframe;
> -    vfpframe = (struct target_vfp_sigframe *)regspace;
> -
> -    __get_user(magic, &vfpframe->magic);
> -    __get_user(sz, &vfpframe->size);
> -    if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
> -        return 0;
> -    }
> -    for (i = 0; i < 32; i++) {
> -        __get_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
> -    }
> -    __get_user(fpscr, &vfpframe->ufp.fpscr);
> -    vfp_set_fpscr(env, fpscr);
> -    __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
> -    /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
> -     * and the exception flag is cleared
> -     */
> -    fpexc |= (1 << 30);
> -    fpexc &= ~((1 << 31) | (1 << 28));
> -    env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
> -    __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
> -    __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
> -    return (abi_ulong*)(vfpframe + 1);
> -}
> -
> -static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
> -                                             abi_ulong *regspace)
> -{
> -    int i;
> -    abi_ulong magic, sz;
> -    struct target_iwmmxt_sigframe *iwmmxtframe;
> -    iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
> -
> -    __get_user(magic, &iwmmxtframe->magic);
> -    __get_user(sz, &iwmmxtframe->size);
> -    if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
> -        return 0;
> -    }
> -    for (i = 0; i < 16; i++) {
> -        __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
> -    }
> -    __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
> -    __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
> -    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
> -    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
> -    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
> -    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
> -    return (abi_ulong*)(iwmmxtframe + 1);
> -}
> -
> -static int do_sigframe_return_v2(CPUARMState *env,
> -                                 target_ulong context_addr,
> -                                 struct target_ucontext_v2 *uc)
> -{
> -    sigset_t host_set;
> -    abi_ulong *regspace;
> -
> -    target_to_host_sigset(&host_set, &uc->tuc_sigmask);
> -    set_sigmask(&host_set);
> -
> -    if (restore_sigcontext(env, &uc->tuc_mcontext))
> -        return 1;
> -
> -    /* Restore coprocessor signal frame */
> -    regspace = uc->tuc_regspace;
> -    if (arm_feature(env, ARM_FEATURE_VFP)) {
> -        regspace = restore_sigframe_v2_vfp(env, regspace);
> -        if (!regspace) {
> -            return 1;
> -        }
> -    }
> -    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
> -        regspace = restore_sigframe_v2_iwmmxt(env, regspace);
> -        if (!regspace) {
> -            return 1;
> -        }
> -    }
> -
> -    if (do_sigaltstack(context_addr
> -                       + offsetof(struct target_ucontext_v2, tuc_stack),
> -                       0, get_sp_from_cpustate(env)) == -EFAULT) {
> -        return 1;
> -    }
> -
> -#if 0
> -    /* Send SIGTRAP if we're single-stepping */
> -    if (ptrace_cancel_bpt(current))
> -        send_sig(SIGTRAP, current, 1);
> -#endif
> -
> -    return 0;
> -}
> -
> -static long do_sigreturn_v2(CPUARMState *env)
> -{
> -    abi_ulong frame_addr;
> -    struct sigframe_v2 *frame = NULL;
> -
> -    /*
> -     * Since we stacked the signal on a 64-bit boundary,
> -     * then 'sp' should be word aligned here.  If it's
> -     * not, then the user is trying to mess with us.
> -     */
> -    frame_addr = env->regs[13];
> -    trace_user_do_sigreturn(env, frame_addr);
> -    if (frame_addr & 7) {
> -        goto badframe;
> -    }
> -
> -    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
> -        goto badframe;
> -    }
> -
> -    if (do_sigframe_return_v2(env,
> -                              frame_addr
> -                              + offsetof(struct sigframe_v2, uc),
> -                              &frame->uc)) {
> -        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;
> -}
> -
> -long do_sigreturn(CPUARMState *env)
> -{
> -    if (get_osversion() >= 0x020612) {
> -        return do_sigreturn_v2(env);
> -    } else {
> -        return do_sigreturn_v1(env);
> -    }
> -}
> -
> -static long do_rt_sigreturn_v1(CPUARMState *env)
> -{
> -    abi_ulong frame_addr;
> -    struct rt_sigframe_v1 *frame = NULL;
> -    sigset_t host_set;
> -
> -    /*
> -     * Since we stacked the signal on a 64-bit boundary,
> -     * then 'sp' should be word aligned here.  If it's
> -     * not, then the user is trying to mess with us.
> -     */
> -    frame_addr = env->regs[13];
> -    trace_user_do_rt_sigreturn(env, frame_addr);
> -    if (frame_addr & 7) {
> -        goto badframe;
> -    }
> -
> -    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
> -        goto badframe;
> -    }
> -
> -    target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
> -    set_sigmask(&host_set);
> -
> -    if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
> -        goto badframe;
> -    }
> -
> -    if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
> -        goto badframe;
> -
> -#if 0
> -    /* Send SIGTRAP if we're single-stepping */
> -    if (ptrace_cancel_bpt(current))
> -        send_sig(SIGTRAP, current, 1);
> -#endif
> -    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;
> -}
> -
> -static long do_rt_sigreturn_v2(CPUARMState *env)
> -{
> -    abi_ulong frame_addr;
> -    struct rt_sigframe_v2 *frame = NULL;
> -
> -    /*
> -     * Since we stacked the signal on a 64-bit boundary,
> -     * then 'sp' should be word aligned here.  If it's
> -     * not, then the user is trying to mess with us.
> -     */
> -    frame_addr = env->regs[13];
> -    trace_user_do_rt_sigreturn(env, frame_addr);
> -    if (frame_addr & 7) {
> -        goto badframe;
> -    }
> -
> -    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
> -        goto badframe;
> -    }
> -
> -    if (do_sigframe_return_v2(env,
> -                              frame_addr
> -                              + offsetof(struct rt_sigframe_v2, uc),
> -                              &frame->uc)) {
> -        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;
> -}
> -
> -long do_rt_sigreturn(CPUARMState *env)
> -{
> -    if (get_osversion() >= 0x020612) {
> -        return do_rt_sigreturn_v2(env);
> -    } else {
> -        return do_rt_sigreturn_v1(env);
> -    }
> -}
> -
>  #elif defined(TARGET_SPARC)
>
>  #define __SUNOS_MAXWIN   31


--
Alex Bennée
Alex Bennée March 28, 2018, 2:35 p.m. UTC | #2
Laurent Vivier <laurent@vivier.eu> writes:

> No code change, only move code from signal.c to
> arm/signal.c, except adding includes and
> exporting setup_frame() and setup_rt_frame().
>
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>

Apparently there are some tabs in the old code, could you de-tabify on
the next iteration please?

> ---
>  linux-user/arm/signal.c        | 754 +++++++++++++++++++++++++++++++++++++++++
>  linux-user/arm/target_signal.h |   6 +-
>  linux-user/signal.c            | 751 ----------------------------------------
>  3 files changed, 759 insertions(+), 752 deletions(-)
>
> diff --git a/linux-user/arm/signal.c b/linux-user/arm/signal.c
> index 02ca338b6c..975f80fdd2 100644
> --- a/linux-user/arm/signal.c
> +++ b/linux-user/arm/signal.c
> @@ -16,3 +16,757 @@
>   *  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 {
> +    abi_ulong trap_no;
> +    abi_ulong error_code;
> +    abi_ulong oldmask;
> +    abi_ulong arm_r0;
> +    abi_ulong arm_r1;
> +    abi_ulong arm_r2;
> +    abi_ulong arm_r3;
> +    abi_ulong arm_r4;
> +    abi_ulong arm_r5;
> +    abi_ulong arm_r6;
> +    abi_ulong arm_r7;
> +    abi_ulong arm_r8;
> +    abi_ulong arm_r9;
> +    abi_ulong arm_r10;
> +    abi_ulong arm_fp;
> +    abi_ulong arm_ip;
> +    abi_ulong arm_sp;
> +    abi_ulong arm_lr;
> +    abi_ulong arm_pc;
> +    abi_ulong arm_cpsr;
> +    abi_ulong fault_address;
> +};
> +
> +struct target_ucontext_v1 {
> +    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_ucontext_v2 {
> +    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 */
> +    char __unused[128 - sizeof(target_sigset_t)];
> +    abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
> +};
> +
> +struct target_user_vfp {
> +    uint64_t fpregs[32];
> +    abi_ulong fpscr;
> +};
> +
> +struct target_user_vfp_exc {
> +    abi_ulong fpexc;
> +    abi_ulong fpinst;
> +    abi_ulong fpinst2;
> +};
> +
> +struct target_vfp_sigframe {
> +    abi_ulong magic;
> +    abi_ulong size;
> +    struct target_user_vfp ufp;
> +    struct target_user_vfp_exc ufp_exc;
> +} __attribute__((__aligned__(8)));
> +
> +struct target_iwmmxt_sigframe {
> +    abi_ulong magic;
> +    abi_ulong size;
> +    uint64_t regs[16];
> +    /* Note that not all the coprocessor control registers are stored here */
> +    uint32_t wcssf;
> +    uint32_t wcasf;
> +    uint32_t wcgr0;
> +    uint32_t wcgr1;
> +    uint32_t wcgr2;
> +    uint32_t wcgr3;
> +} __attribute__((__aligned__(8)));
> +
> +#define TARGET_VFP_MAGIC 0x56465001
> +#define TARGET_IWMMXT_MAGIC 0x12ef842a
> +
> +struct sigframe_v1
> +{
> +    struct target_sigcontext sc;
> +    abi_ulong extramask[TARGET_NSIG_WORDS-1];
> +    abi_ulong retcode;
> +};
> +
> +struct sigframe_v2
> +{
> +    struct target_ucontext_v2 uc;
> +    abi_ulong retcode;
> +};
> +
> +struct rt_sigframe_v1
> +{
> +    abi_ulong pinfo;
> +    abi_ulong puc;
> +    struct target_siginfo info;
> +    struct target_ucontext_v1 uc;
> +    abi_ulong retcode;
> +};
> +
> +struct rt_sigframe_v2
> +{
> +    struct target_siginfo info;
> +    struct target_ucontext_v2 uc;
> +    abi_ulong retcode;
> +};
> +
> +#define TARGET_CONFIG_CPU_32 1
> +
> +/*
> + * For ARM syscalls, we encode the syscall number into the instruction.
> + */
> +#define SWI_SYS_SIGRETURN	(0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
> +#define SWI_SYS_RT_SIGRETURN	(0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
> +
> +/*
> + * For Thumb syscalls, we pass the syscall number via r7.  We therefore
> + * need two 16-bit instructions.
> + */
> +#define SWI_THUMB_SIGRETURN	(0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
> +#define SWI_THUMB_RT_SIGRETURN	(0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
> +
> +static const abi_ulong retcodes[4] = {
> +	SWI_SYS_SIGRETURN,	SWI_THUMB_SIGRETURN,
> +	SWI_SYS_RT_SIGRETURN,	SWI_THUMB_RT_SIGRETURN
> +};
> +
> +
> +static inline int valid_user_regs(CPUARMState *regs)
> +{
> +    return 1;
> +}
> +
> +static void
> +setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
> +                 CPUARMState *env, abi_ulong mask)
> +{
> +    __put_user(env->regs[0], &sc->arm_r0);
> +    __put_user(env->regs[1], &sc->arm_r1);
> +    __put_user(env->regs[2], &sc->arm_r2);
> +    __put_user(env->regs[3], &sc->arm_r3);
> +    __put_user(env->regs[4], &sc->arm_r4);
> +    __put_user(env->regs[5], &sc->arm_r5);
> +    __put_user(env->regs[6], &sc->arm_r6);
> +    __put_user(env->regs[7], &sc->arm_r7);
> +    __put_user(env->regs[8], &sc->arm_r8);
> +    __put_user(env->regs[9], &sc->arm_r9);
> +    __put_user(env->regs[10], &sc->arm_r10);
> +    __put_user(env->regs[11], &sc->arm_fp);
> +    __put_user(env->regs[12], &sc->arm_ip);
> +    __put_user(env->regs[13], &sc->arm_sp);
> +    __put_user(env->regs[14], &sc->arm_lr);
> +    __put_user(env->regs[15], &sc->arm_pc);
> +#ifdef TARGET_CONFIG_CPU_32
> +    __put_user(cpsr_read(env), &sc->arm_cpsr);
> +#endif
> +
> +    __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
> +    __put_user(/* current->thread.error_code */ 0, &sc->error_code);
> +    __put_user(/* current->thread.address */ 0, &sc->fault_address);
> +    __put_user(mask, &sc->oldmask);
> +}
> +
> +static inline abi_ulong
> +get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
> +{
> +    unsigned long sp = regs->regs[13];
> +
> +    /*
> +     * This is the X/Open sanctioned signal stack switching.
> +     */
> +    if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
> +        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
> +    }
> +    /*
> +     * ATPCS B01 mandates 8-byte alignment
> +     */
> +    return (sp - framesize) & ~7;
> +}
> +
> +static void
> +setup_return(CPUARMState *env, struct target_sigaction *ka,
> +             abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
> +{
> +    abi_ulong handler = ka->_sa_handler;
> +    abi_ulong retcode;
> +    int thumb = handler & 1;
> +    uint32_t cpsr = cpsr_read(env);
> +
> +    cpsr &= ~CPSR_IT;
> +    if (thumb) {
> +        cpsr |= CPSR_T;
> +    } else {
> +        cpsr &= ~CPSR_T;
> +    }
> +
> +    if (ka->sa_flags & TARGET_SA_RESTORER) {
> +        retcode = ka->sa_restorer;
> +    } else {
> +        unsigned int idx = thumb;
> +
> +        if (ka->sa_flags & TARGET_SA_SIGINFO) {
> +            idx += 2;
> +        }
> +
> +        __put_user(retcodes[idx], rc);
> +
> +        retcode = rc_addr + thumb;
> +    }
> +
> +    env->regs[0] = usig;
> +    env->regs[13] = frame_addr;
> +    env->regs[14] = retcode;
> +    env->regs[15] = handler & (thumb ? ~1 : ~3);
> +    cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
> +}
> +
> +static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
> +{
> +    int i;
> +    struct target_vfp_sigframe *vfpframe;
> +    vfpframe = (struct target_vfp_sigframe *)regspace;
> +    __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
> +    __put_user(sizeof(*vfpframe), &vfpframe->size);
> +    for (i = 0; i < 32; i++) {
> +        __put_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
> +    }
> +    __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
> +    __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
> +    __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
> +    __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
> +    return (abi_ulong*)(vfpframe+1);
> +}
> +
> +static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
> +                                           CPUARMState *env)
> +{
> +    int i;
> +    struct target_iwmmxt_sigframe *iwmmxtframe;
> +    iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
> +    __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
> +    __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
> +    for (i = 0; i < 16; i++) {
> +        __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
> +    }
> +    __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
> +    __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
> +    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
> +    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
> +    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
> +    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
> +    return (abi_ulong*)(iwmmxtframe+1);
> +}
> +
> +static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
> +                              target_sigset_t *set, CPUARMState *env)
> +{
> +    struct target_sigaltstack stack;
> +    int i;
> +    abi_ulong *regspace;
> +
> +    /* Clear all the bits of the ucontext we don't use.  */
> +    memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
> +
> +    memset(&stack, 0, sizeof(stack));
> +    __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
> +    __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
> +    __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
> +    memcpy(&uc->tuc_stack, &stack, sizeof(stack));
> +
> +    setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
> +    /* Save coprocessor signal frame.  */
> +    regspace = uc->tuc_regspace;
> +    if (arm_feature(env, ARM_FEATURE_VFP)) {
> +        regspace = setup_sigframe_v2_vfp(regspace, env);
> +    }
> +    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
> +        regspace = setup_sigframe_v2_iwmmxt(regspace, env);
> +    }
> +
> +    /* Write terminating magic word */
> +    __put_user(0, regspace);
> +
> +    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
> +        __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
> +    }
> +}
> +
> +/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
> +static void setup_frame_v1(int usig, struct target_sigaction *ka,
> +                           target_sigset_t *set, CPUARMState *regs)
> +{
> +    struct sigframe_v1 *frame;
> +    abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
> +    int i;
> +
> +    trace_user_setup_frame(regs, frame_addr);
> +    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
> +        goto sigsegv;
> +    }
> +
> +    setup_sigcontext(&frame->sc, regs, set->sig[0]);
> +
> +    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
> +        __put_user(set->sig[i], &frame->extramask[i - 1]);
> +    }
> +
> +    setup_return(regs, ka, &frame->retcode, frame_addr, usig,
> +                 frame_addr + offsetof(struct sigframe_v1, retcode));
> +
> +    unlock_user_struct(frame, frame_addr, 1);
> +    return;
> +sigsegv:
> +    force_sigsegv(usig);
> +}
> +
> +static void setup_frame_v2(int usig, struct target_sigaction *ka,
> +                           target_sigset_t *set, CPUARMState *regs)
> +{
> +    struct sigframe_v2 *frame;
> +    abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
> +
> +    trace_user_setup_frame(regs, frame_addr);
> +    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
> +        goto sigsegv;
> +    }
> +
> +    setup_sigframe_v2(&frame->uc, set, regs);
> +
> +    setup_return(regs, ka, &frame->retcode, frame_addr, usig,
> +                 frame_addr + offsetof(struct sigframe_v2, retcode));
> +
> +    unlock_user_struct(frame, frame_addr, 1);
> +    return;
> +sigsegv:
> +    force_sigsegv(usig);
> +}
> +
> +void setup_frame(int usig, struct target_sigaction *ka,
> +                 target_sigset_t *set, CPUARMState *regs)
> +{
> +    if (get_osversion() >= 0x020612) {
> +        setup_frame_v2(usig, ka, set, regs);
> +    } else {
> +        setup_frame_v1(usig, ka, set, regs);
> +    }
> +}
> +
> +/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
> +static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
> +                              target_siginfo_t *info,
> +                              target_sigset_t *set, CPUARMState *env)
> +{
> +    struct rt_sigframe_v1 *frame;
> +    abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
> +    struct target_sigaltstack stack;
> +    int i;
> +    abi_ulong info_addr, uc_addr;
> +
> +    trace_user_setup_rt_frame(env, frame_addr);
> +    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
> +        goto sigsegv;
> +    }
> +
> +    info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
> +    __put_user(info_addr, &frame->pinfo);
> +    uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
> +    __put_user(uc_addr, &frame->puc);
> +    tswap_siginfo(&frame->info, info);
> +
> +    /* Clear all the bits of the ucontext we don't use.  */
> +    memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
> +
> +    memset(&stack, 0, sizeof(stack));
> +    __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
> +    __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
> +    __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
> +    memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
> +
> +    setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
> +    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
> +        __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
> +    }
> +
> +    setup_return(env, ka, &frame->retcode, frame_addr, usig,
> +                 frame_addr + offsetof(struct rt_sigframe_v1, retcode));
> +
> +    env->regs[1] = info_addr;
> +    env->regs[2] = uc_addr;
> +
> +    unlock_user_struct(frame, frame_addr, 1);
> +    return;
> +sigsegv:
> +    force_sigsegv(usig);
> +}
> +
> +static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
> +                              target_siginfo_t *info,
> +                              target_sigset_t *set, CPUARMState *env)
> +{
> +    struct rt_sigframe_v2 *frame;
> +    abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
> +    abi_ulong info_addr, uc_addr;
> +
> +    trace_user_setup_rt_frame(env, frame_addr);
> +    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
> +        goto sigsegv;
> +    }
> +
> +    info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
> +    uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
> +    tswap_siginfo(&frame->info, info);
> +
> +    setup_sigframe_v2(&frame->uc, set, env);
> +
> +    setup_return(env, ka, &frame->retcode, frame_addr, usig,
> +                 frame_addr + offsetof(struct rt_sigframe_v2, retcode));
> +
> +    env->regs[1] = info_addr;
> +    env->regs[2] = uc_addr;
> +
> +    unlock_user_struct(frame, frame_addr, 1);
> +    return;
> +sigsegv:
> +    force_sigsegv(usig);
> +}
> +
> +void setup_rt_frame(int usig, struct target_sigaction *ka,
> +                    target_siginfo_t *info,
> +                    target_sigset_t *set, CPUARMState *env)
> +{
> +    if (get_osversion() >= 0x020612) {
> +        setup_rt_frame_v2(usig, ka, info, set, env);
> +    } else {
> +        setup_rt_frame_v1(usig, ka, info, set, env);
> +    }
> +}
> +
> +static int
> +restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
> +{
> +    int err = 0;
> +    uint32_t cpsr;
> +
> +    __get_user(env->regs[0], &sc->arm_r0);
> +    __get_user(env->regs[1], &sc->arm_r1);
> +    __get_user(env->regs[2], &sc->arm_r2);
> +    __get_user(env->regs[3], &sc->arm_r3);
> +    __get_user(env->regs[4], &sc->arm_r4);
> +    __get_user(env->regs[5], &sc->arm_r5);
> +    __get_user(env->regs[6], &sc->arm_r6);
> +    __get_user(env->regs[7], &sc->arm_r7);
> +    __get_user(env->regs[8], &sc->arm_r8);
> +    __get_user(env->regs[9], &sc->arm_r9);
> +    __get_user(env->regs[10], &sc->arm_r10);
> +    __get_user(env->regs[11], &sc->arm_fp);
> +    __get_user(env->regs[12], &sc->arm_ip);
> +    __get_user(env->regs[13], &sc->arm_sp);
> +    __get_user(env->regs[14], &sc->arm_lr);
> +    __get_user(env->regs[15], &sc->arm_pc);
> +#ifdef TARGET_CONFIG_CPU_32
> +    __get_user(cpsr, &sc->arm_cpsr);
> +    cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
> +#endif
> +
> +    err |= !valid_user_regs(env);
> +
> +    return err;
> +}
> +
> +static long do_sigreturn_v1(CPUARMState *env)
> +{
> +    abi_ulong frame_addr;
> +    struct sigframe_v1 *frame = NULL;
> +    target_sigset_t set;
> +    sigset_t host_set;
> +    int i;
> +
> +    /*
> +     * Since we stacked the signal on a 64-bit boundary,
> +     * then 'sp' should be word aligned here.  If it's
> +     * not, then the user is trying to mess with us.
> +     */
> +    frame_addr = env->regs[13];
> +    trace_user_do_sigreturn(env, frame_addr);
> +    if (frame_addr & 7) {
> +        goto badframe;
> +    }
> +
> +    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
> +        goto badframe;
> +    }
> +
> +    __get_user(set.sig[0], &frame->sc.oldmask);
> +    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
> +        __get_user(set.sig[i], &frame->extramask[i - 1]);
> +    }
> +
> +    target_to_host_sigset_internal(&host_set, &set);
> +    set_sigmask(&host_set);
> +
> +    if (restore_sigcontext(env, &frame->sc)) {
> +        goto badframe;
> +    }
> +
> +#if 0
> +    /* Send SIGTRAP if we're single-stepping */
> +    if (ptrace_cancel_bpt(current))
> +        send_sig(SIGTRAP, current, 1);
> +#endif
> +    unlock_user_struct(frame, frame_addr, 0);
> +    return -TARGET_QEMU_ESIGRETURN;
> +
> +badframe:
> +    force_sig(TARGET_SIGSEGV);
> +    return -TARGET_QEMU_ESIGRETURN;
> +}
> +
> +static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
> +{
> +    int i;
> +    abi_ulong magic, sz;
> +    uint32_t fpscr, fpexc;
> +    struct target_vfp_sigframe *vfpframe;
> +    vfpframe = (struct target_vfp_sigframe *)regspace;
> +
> +    __get_user(magic, &vfpframe->magic);
> +    __get_user(sz, &vfpframe->size);
> +    if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
> +        return 0;
> +    }
> +    for (i = 0; i < 32; i++) {
> +        __get_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
> +    }
> +    __get_user(fpscr, &vfpframe->ufp.fpscr);
> +    vfp_set_fpscr(env, fpscr);
> +    __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
> +    /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
> +     * and the exception flag is cleared
> +     */
> +    fpexc |= (1 << 30);
> +    fpexc &= ~((1 << 31) | (1 << 28));
> +    env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
> +    __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
> +    __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
> +    return (abi_ulong*)(vfpframe + 1);
> +}
> +
> +static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
> +                                             abi_ulong *regspace)
> +{
> +    int i;
> +    abi_ulong magic, sz;
> +    struct target_iwmmxt_sigframe *iwmmxtframe;
> +    iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
> +
> +    __get_user(magic, &iwmmxtframe->magic);
> +    __get_user(sz, &iwmmxtframe->size);
> +    if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
> +        return 0;
> +    }
> +    for (i = 0; i < 16; i++) {
> +        __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
> +    }
> +    __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
> +    __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
> +    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
> +    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
> +    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
> +    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
> +    return (abi_ulong*)(iwmmxtframe + 1);
> +}
> +
> +static int do_sigframe_return_v2(CPUARMState *env,
> +                                 target_ulong context_addr,
> +                                 struct target_ucontext_v2 *uc)
> +{
> +    sigset_t host_set;
> +    abi_ulong *regspace;
> +
> +    target_to_host_sigset(&host_set, &uc->tuc_sigmask);
> +    set_sigmask(&host_set);
> +
> +    if (restore_sigcontext(env, &uc->tuc_mcontext))
> +        return 1;
> +
> +    /* Restore coprocessor signal frame */
> +    regspace = uc->tuc_regspace;
> +    if (arm_feature(env, ARM_FEATURE_VFP)) {
> +        regspace = restore_sigframe_v2_vfp(env, regspace);
> +        if (!regspace) {
> +            return 1;
> +        }
> +    }
> +    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
> +        regspace = restore_sigframe_v2_iwmmxt(env, regspace);
> +        if (!regspace) {
> +            return 1;
> +        }
> +    }
> +
> +    if (do_sigaltstack(context_addr
> +                       + offsetof(struct target_ucontext_v2, tuc_stack),
> +                       0, get_sp_from_cpustate(env)) == -EFAULT) {
> +        return 1;
> +    }
> +
> +#if 0
> +    /* Send SIGTRAP if we're single-stepping */
> +    if (ptrace_cancel_bpt(current))
> +        send_sig(SIGTRAP, current, 1);
> +#endif
> +
> +    return 0;
> +}
> +
> +static long do_sigreturn_v2(CPUARMState *env)
> +{
> +    abi_ulong frame_addr;
> +    struct sigframe_v2 *frame = NULL;
> +
> +    /*
> +     * Since we stacked the signal on a 64-bit boundary,
> +     * then 'sp' should be word aligned here.  If it's
> +     * not, then the user is trying to mess with us.
> +     */
> +    frame_addr = env->regs[13];
> +    trace_user_do_sigreturn(env, frame_addr);
> +    if (frame_addr & 7) {
> +        goto badframe;
> +    }
> +
> +    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
> +        goto badframe;
> +    }
> +
> +    if (do_sigframe_return_v2(env,
> +                              frame_addr
> +                              + offsetof(struct sigframe_v2, uc),
> +                              &frame->uc)) {
> +        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;
> +}
> +
> +long do_sigreturn(CPUARMState *env)
> +{
> +    if (get_osversion() >= 0x020612) {
> +        return do_sigreturn_v2(env);
> +    } else {
> +        return do_sigreturn_v1(env);
> +    }
> +}
> +
> +static long do_rt_sigreturn_v1(CPUARMState *env)
> +{
> +    abi_ulong frame_addr;
> +    struct rt_sigframe_v1 *frame = NULL;
> +    sigset_t host_set;
> +
> +    /*
> +     * Since we stacked the signal on a 64-bit boundary,
> +     * then 'sp' should be word aligned here.  If it's
> +     * not, then the user is trying to mess with us.
> +     */
> +    frame_addr = env->regs[13];
> +    trace_user_do_rt_sigreturn(env, frame_addr);
> +    if (frame_addr & 7) {
> +        goto badframe;
> +    }
> +
> +    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
> +        goto badframe;
> +    }
> +
> +    target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
> +    set_sigmask(&host_set);
> +
> +    if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
> +        goto badframe;
> +    }
> +
> +    if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
> +        goto badframe;
> +
> +#if 0
> +    /* Send SIGTRAP if we're single-stepping */
> +    if (ptrace_cancel_bpt(current))
> +        send_sig(SIGTRAP, current, 1);
> +#endif
> +    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;
> +}
> +
> +static long do_rt_sigreturn_v2(CPUARMState *env)
> +{
> +    abi_ulong frame_addr;
> +    struct rt_sigframe_v2 *frame = NULL;
> +
> +    /*
> +     * Since we stacked the signal on a 64-bit boundary,
> +     * then 'sp' should be word aligned here.  If it's
> +     * not, then the user is trying to mess with us.
> +     */
> +    frame_addr = env->regs[13];
> +    trace_user_do_rt_sigreturn(env, frame_addr);
> +    if (frame_addr & 7) {
> +        goto badframe;
> +    }
> +
> +    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
> +        goto badframe;
> +    }
> +
> +    if (do_sigframe_return_v2(env,
> +                              frame_addr
> +                              + offsetof(struct rt_sigframe_v2, uc),
> +                              &frame->uc)) {
> +        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;
> +}
> +
> +long do_rt_sigreturn(CPUARMState *env)
> +{
> +    if (get_osversion() >= 0x020612) {
> +        return do_rt_sigreturn_v2(env);
> +    } else {
> +        return do_rt_sigreturn_v1(env);
> +    }
> +}
> diff --git a/linux-user/arm/target_signal.h b/linux-user/arm/target_signal.h
> index cbbeb09f4d..4b542c324f 100644
> --- a/linux-user/arm/target_signal.h
> +++ b/linux-user/arm/target_signal.h
> @@ -26,5 +26,9 @@ static inline abi_ulong get_sp_from_cpustate(CPUARMState *state)
>     return state->regs[13];
>  }
>
> -
> +void setup_frame(int usig, struct target_sigaction *ka,
> +                 target_sigset_t *set, CPUARMState *regs);
> +void setup_rt_frame(int usig, struct target_sigaction *ka,
> +                    target_siginfo_t *info,
> +                    target_sigset_t *set, CPUARMState *env);
>  #endif /* ARM_TARGET_SIGNAL_H */
> diff --git a/linux-user/signal.c b/linux-user/signal.c
> index 2b05d7951b..38ebba9cf6 100644
> --- a/linux-user/signal.c
> +++ b/linux-user/signal.c
> @@ -1383,757 +1383,6 @@ badframe:
>      return -TARGET_QEMU_ESIGRETURN;
>  }
>
> -#elif defined(TARGET_ARM) && !defined(TARGET_AARCH64)
> -
> -struct target_sigcontext {
> -    abi_ulong trap_no;
> -    abi_ulong error_code;
> -    abi_ulong oldmask;
> -    abi_ulong arm_r0;
> -    abi_ulong arm_r1;
> -    abi_ulong arm_r2;
> -    abi_ulong arm_r3;
> -    abi_ulong arm_r4;
> -    abi_ulong arm_r5;
> -    abi_ulong arm_r6;
> -    abi_ulong arm_r7;
> -    abi_ulong arm_r8;
> -    abi_ulong arm_r9;
> -    abi_ulong arm_r10;
> -    abi_ulong arm_fp;
> -    abi_ulong arm_ip;
> -    abi_ulong arm_sp;
> -    abi_ulong arm_lr;
> -    abi_ulong arm_pc;
> -    abi_ulong arm_cpsr;
> -    abi_ulong fault_address;
> -};
> -
> -struct target_ucontext_v1 {
> -    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_ucontext_v2 {
> -    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 */
> -    char __unused[128 - sizeof(target_sigset_t)];
> -    abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
> -};
> -
> -struct target_user_vfp {
> -    uint64_t fpregs[32];
> -    abi_ulong fpscr;
> -};
> -
> -struct target_user_vfp_exc {
> -    abi_ulong fpexc;
> -    abi_ulong fpinst;
> -    abi_ulong fpinst2;
> -};
> -
> -struct target_vfp_sigframe {
> -    abi_ulong magic;
> -    abi_ulong size;
> -    struct target_user_vfp ufp;
> -    struct target_user_vfp_exc ufp_exc;
> -} __attribute__((__aligned__(8)));
> -
> -struct target_iwmmxt_sigframe {
> -    abi_ulong magic;
> -    abi_ulong size;
> -    uint64_t regs[16];
> -    /* Note that not all the coprocessor control registers are stored here */
> -    uint32_t wcssf;
> -    uint32_t wcasf;
> -    uint32_t wcgr0;
> -    uint32_t wcgr1;
> -    uint32_t wcgr2;
> -    uint32_t wcgr3;
> -} __attribute__((__aligned__(8)));
> -
> -#define TARGET_VFP_MAGIC 0x56465001
> -#define TARGET_IWMMXT_MAGIC 0x12ef842a
> -
> -struct sigframe_v1
> -{
> -    struct target_sigcontext sc;
> -    abi_ulong extramask[TARGET_NSIG_WORDS-1];
> -    abi_ulong retcode;
> -};
> -
> -struct sigframe_v2
> -{
> -    struct target_ucontext_v2 uc;
> -    abi_ulong retcode;
> -};
> -
> -struct rt_sigframe_v1
> -{
> -    abi_ulong pinfo;
> -    abi_ulong puc;
> -    struct target_siginfo info;
> -    struct target_ucontext_v1 uc;
> -    abi_ulong retcode;
> -};
> -
> -struct rt_sigframe_v2
> -{
> -    struct target_siginfo info;
> -    struct target_ucontext_v2 uc;
> -    abi_ulong retcode;
> -};
> -
> -#define TARGET_CONFIG_CPU_32 1
> -
> -/*
> - * For ARM syscalls, we encode the syscall number into the instruction.
> - */
> -#define SWI_SYS_SIGRETURN	(0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
> -#define SWI_SYS_RT_SIGRETURN	(0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
> -
> -/*
> - * For Thumb syscalls, we pass the syscall number via r7.  We therefore
> - * need two 16-bit instructions.
> - */
> -#define SWI_THUMB_SIGRETURN	(0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
> -#define SWI_THUMB_RT_SIGRETURN	(0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
> -
> -static const abi_ulong retcodes[4] = {
> -	SWI_SYS_SIGRETURN,	SWI_THUMB_SIGRETURN,
> -	SWI_SYS_RT_SIGRETURN,	SWI_THUMB_RT_SIGRETURN
> -};
> -
> -
> -static inline int valid_user_regs(CPUARMState *regs)
> -{
> -    return 1;
> -}
> -
> -static void
> -setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
> -                 CPUARMState *env, abi_ulong mask)
> -{
> -    __put_user(env->regs[0], &sc->arm_r0);
> -    __put_user(env->regs[1], &sc->arm_r1);
> -    __put_user(env->regs[2], &sc->arm_r2);
> -    __put_user(env->regs[3], &sc->arm_r3);
> -    __put_user(env->regs[4], &sc->arm_r4);
> -    __put_user(env->regs[5], &sc->arm_r5);
> -    __put_user(env->regs[6], &sc->arm_r6);
> -    __put_user(env->regs[7], &sc->arm_r7);
> -    __put_user(env->regs[8], &sc->arm_r8);
> -    __put_user(env->regs[9], &sc->arm_r9);
> -    __put_user(env->regs[10], &sc->arm_r10);
> -    __put_user(env->regs[11], &sc->arm_fp);
> -    __put_user(env->regs[12], &sc->arm_ip);
> -    __put_user(env->regs[13], &sc->arm_sp);
> -    __put_user(env->regs[14], &sc->arm_lr);
> -    __put_user(env->regs[15], &sc->arm_pc);
> -#ifdef TARGET_CONFIG_CPU_32
> -    __put_user(cpsr_read(env), &sc->arm_cpsr);
> -#endif
> -
> -    __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
> -    __put_user(/* current->thread.error_code */ 0, &sc->error_code);
> -    __put_user(/* current->thread.address */ 0, &sc->fault_address);
> -    __put_user(mask, &sc->oldmask);
> -}
> -
> -static inline abi_ulong
> -get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
> -{
> -    unsigned long sp = regs->regs[13];
> -
> -    /*
> -     * This is the X/Open sanctioned signal stack switching.
> -     */
> -    if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
> -        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
> -    }
> -    /*
> -     * ATPCS B01 mandates 8-byte alignment
> -     */
> -    return (sp - framesize) & ~7;
> -}
> -
> -static void
> -setup_return(CPUARMState *env, struct target_sigaction *ka,
> -             abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
> -{
> -    abi_ulong handler = ka->_sa_handler;
> -    abi_ulong retcode;
> -    int thumb = handler & 1;
> -    uint32_t cpsr = cpsr_read(env);
> -
> -    cpsr &= ~CPSR_IT;
> -    if (thumb) {
> -        cpsr |= CPSR_T;
> -    } else {
> -        cpsr &= ~CPSR_T;
> -    }
> -
> -    if (ka->sa_flags & TARGET_SA_RESTORER) {
> -        retcode = ka->sa_restorer;
> -    } else {
> -        unsigned int idx = thumb;
> -
> -        if (ka->sa_flags & TARGET_SA_SIGINFO) {
> -            idx += 2;
> -        }
> -
> -        __put_user(retcodes[idx], rc);
> -
> -        retcode = rc_addr + thumb;
> -    }
> -
> -    env->regs[0] = usig;
> -    env->regs[13] = frame_addr;
> -    env->regs[14] = retcode;
> -    env->regs[15] = handler & (thumb ? ~1 : ~3);
> -    cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
> -}
> -
> -static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
> -{
> -    int i;
> -    struct target_vfp_sigframe *vfpframe;
> -    vfpframe = (struct target_vfp_sigframe *)regspace;
> -    __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
> -    __put_user(sizeof(*vfpframe), &vfpframe->size);
> -    for (i = 0; i < 32; i++) {
> -        __put_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
> -    }
> -    __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
> -    __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
> -    __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
> -    __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
> -    return (abi_ulong*)(vfpframe+1);
> -}
> -
> -static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
> -                                           CPUARMState *env)
> -{
> -    int i;
> -    struct target_iwmmxt_sigframe *iwmmxtframe;
> -    iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
> -    __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
> -    __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
> -    for (i = 0; i < 16; i++) {
> -        __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
> -    }
> -    __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
> -    __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
> -    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
> -    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
> -    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
> -    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
> -    return (abi_ulong*)(iwmmxtframe+1);
> -}
> -
> -static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
> -                              target_sigset_t *set, CPUARMState *env)
> -{
> -    struct target_sigaltstack stack;
> -    int i;
> -    abi_ulong *regspace;
> -
> -    /* Clear all the bits of the ucontext we don't use.  */
> -    memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
> -
> -    memset(&stack, 0, sizeof(stack));
> -    __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
> -    __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
> -    __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
> -    memcpy(&uc->tuc_stack, &stack, sizeof(stack));
> -
> -    setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
> -    /* Save coprocessor signal frame.  */
> -    regspace = uc->tuc_regspace;
> -    if (arm_feature(env, ARM_FEATURE_VFP)) {
> -        regspace = setup_sigframe_v2_vfp(regspace, env);
> -    }
> -    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
> -        regspace = setup_sigframe_v2_iwmmxt(regspace, env);
> -    }
> -
> -    /* Write terminating magic word */
> -    __put_user(0, regspace);
> -
> -    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
> -        __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
> -    }
> -}
> -
> -/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
> -static void setup_frame_v1(int usig, struct target_sigaction *ka,
> -                           target_sigset_t *set, CPUARMState *regs)
> -{
> -    struct sigframe_v1 *frame;
> -    abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
> -    int i;
> -
> -    trace_user_setup_frame(regs, frame_addr);
> -    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
> -        goto sigsegv;
> -    }
> -
> -    setup_sigcontext(&frame->sc, regs, set->sig[0]);
> -
> -    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
> -        __put_user(set->sig[i], &frame->extramask[i - 1]);
> -    }
> -
> -    setup_return(regs, ka, &frame->retcode, frame_addr, usig,
> -                 frame_addr + offsetof(struct sigframe_v1, retcode));
> -
> -    unlock_user_struct(frame, frame_addr, 1);
> -    return;
> -sigsegv:
> -    force_sigsegv(usig);
> -}
> -
> -static void setup_frame_v2(int usig, struct target_sigaction *ka,
> -                           target_sigset_t *set, CPUARMState *regs)
> -{
> -    struct sigframe_v2 *frame;
> -    abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
> -
> -    trace_user_setup_frame(regs, frame_addr);
> -    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
> -        goto sigsegv;
> -    }
> -
> -    setup_sigframe_v2(&frame->uc, set, regs);
> -
> -    setup_return(regs, ka, &frame->retcode, frame_addr, usig,
> -                 frame_addr + offsetof(struct sigframe_v2, retcode));
> -
> -    unlock_user_struct(frame, frame_addr, 1);
> -    return;
> -sigsegv:
> -    force_sigsegv(usig);
> -}
> -
> -static void setup_frame(int usig, struct target_sigaction *ka,
> -                        target_sigset_t *set, CPUARMState *regs)
> -{
> -    if (get_osversion() >= 0x020612) {
> -        setup_frame_v2(usig, ka, set, regs);
> -    } else {
> -        setup_frame_v1(usig, ka, set, regs);
> -    }
> -}
> -
> -/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
> -static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
> -                              target_siginfo_t *info,
> -                              target_sigset_t *set, CPUARMState *env)
> -{
> -    struct rt_sigframe_v1 *frame;
> -    abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
> -    struct target_sigaltstack stack;
> -    int i;
> -    abi_ulong info_addr, uc_addr;
> -
> -    trace_user_setup_rt_frame(env, frame_addr);
> -    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
> -        goto sigsegv;
> -    }
> -
> -    info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
> -    __put_user(info_addr, &frame->pinfo);
> -    uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
> -    __put_user(uc_addr, &frame->puc);
> -    tswap_siginfo(&frame->info, info);
> -
> -    /* Clear all the bits of the ucontext we don't use.  */
> -    memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
> -
> -    memset(&stack, 0, sizeof(stack));
> -    __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
> -    __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
> -    __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
> -    memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
> -
> -    setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
> -    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
> -        __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
> -    }
> -
> -    setup_return(env, ka, &frame->retcode, frame_addr, usig,
> -                 frame_addr + offsetof(struct rt_sigframe_v1, retcode));
> -
> -    env->regs[1] = info_addr;
> -    env->regs[2] = uc_addr;
> -
> -    unlock_user_struct(frame, frame_addr, 1);
> -    return;
> -sigsegv:
> -    force_sigsegv(usig);
> -}
> -
> -static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
> -                              target_siginfo_t *info,
> -                              target_sigset_t *set, CPUARMState *env)
> -{
> -    struct rt_sigframe_v2 *frame;
> -    abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
> -    abi_ulong info_addr, uc_addr;
> -
> -    trace_user_setup_rt_frame(env, frame_addr);
> -    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
> -        goto sigsegv;
> -    }
> -
> -    info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
> -    uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
> -    tswap_siginfo(&frame->info, info);
> -
> -    setup_sigframe_v2(&frame->uc, set, env);
> -
> -    setup_return(env, ka, &frame->retcode, frame_addr, usig,
> -                 frame_addr + offsetof(struct rt_sigframe_v2, retcode));
> -
> -    env->regs[1] = info_addr;
> -    env->regs[2] = uc_addr;
> -
> -    unlock_user_struct(frame, frame_addr, 1);
> -    return;
> -sigsegv:
> -    force_sigsegv(usig);
> -}
> -
> -static void setup_rt_frame(int usig, struct target_sigaction *ka,
> -                           target_siginfo_t *info,
> -                           target_sigset_t *set, CPUARMState *env)
> -{
> -    if (get_osversion() >= 0x020612) {
> -        setup_rt_frame_v2(usig, ka, info, set, env);
> -    } else {
> -        setup_rt_frame_v1(usig, ka, info, set, env);
> -    }
> -}
> -
> -static int
> -restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
> -{
> -    int err = 0;
> -    uint32_t cpsr;
> -
> -    __get_user(env->regs[0], &sc->arm_r0);
> -    __get_user(env->regs[1], &sc->arm_r1);
> -    __get_user(env->regs[2], &sc->arm_r2);
> -    __get_user(env->regs[3], &sc->arm_r3);
> -    __get_user(env->regs[4], &sc->arm_r4);
> -    __get_user(env->regs[5], &sc->arm_r5);
> -    __get_user(env->regs[6], &sc->arm_r6);
> -    __get_user(env->regs[7], &sc->arm_r7);
> -    __get_user(env->regs[8], &sc->arm_r8);
> -    __get_user(env->regs[9], &sc->arm_r9);
> -    __get_user(env->regs[10], &sc->arm_r10);
> -    __get_user(env->regs[11], &sc->arm_fp);
> -    __get_user(env->regs[12], &sc->arm_ip);
> -    __get_user(env->regs[13], &sc->arm_sp);
> -    __get_user(env->regs[14], &sc->arm_lr);
> -    __get_user(env->regs[15], &sc->arm_pc);
> -#ifdef TARGET_CONFIG_CPU_32
> -    __get_user(cpsr, &sc->arm_cpsr);
> -    cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
> -#endif
> -
> -    err |= !valid_user_regs(env);
> -
> -    return err;
> -}
> -
> -static long do_sigreturn_v1(CPUARMState *env)
> -{
> -    abi_ulong frame_addr;
> -    struct sigframe_v1 *frame = NULL;
> -    target_sigset_t set;
> -    sigset_t host_set;
> -    int i;
> -
> -    /*
> -     * Since we stacked the signal on a 64-bit boundary,
> -     * then 'sp' should be word aligned here.  If it's
> -     * not, then the user is trying to mess with us.
> -     */
> -    frame_addr = env->regs[13];
> -    trace_user_do_sigreturn(env, frame_addr);
> -    if (frame_addr & 7) {
> -        goto badframe;
> -    }
> -
> -    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
> -        goto badframe;
> -    }
> -
> -    __get_user(set.sig[0], &frame->sc.oldmask);
> -    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
> -        __get_user(set.sig[i], &frame->extramask[i - 1]);
> -    }
> -
> -    target_to_host_sigset_internal(&host_set, &set);
> -    set_sigmask(&host_set);
> -
> -    if (restore_sigcontext(env, &frame->sc)) {
> -        goto badframe;
> -    }
> -
> -#if 0
> -    /* Send SIGTRAP if we're single-stepping */
> -    if (ptrace_cancel_bpt(current))
> -        send_sig(SIGTRAP, current, 1);
> -#endif
> -    unlock_user_struct(frame, frame_addr, 0);
> -    return -TARGET_QEMU_ESIGRETURN;
> -
> -badframe:
> -    force_sig(TARGET_SIGSEGV);
> -    return -TARGET_QEMU_ESIGRETURN;
> -}
> -
> -static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
> -{
> -    int i;
> -    abi_ulong magic, sz;
> -    uint32_t fpscr, fpexc;
> -    struct target_vfp_sigframe *vfpframe;
> -    vfpframe = (struct target_vfp_sigframe *)regspace;
> -
> -    __get_user(magic, &vfpframe->magic);
> -    __get_user(sz, &vfpframe->size);
> -    if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
> -        return 0;
> -    }
> -    for (i = 0; i < 32; i++) {
> -        __get_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
> -    }
> -    __get_user(fpscr, &vfpframe->ufp.fpscr);
> -    vfp_set_fpscr(env, fpscr);
> -    __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
> -    /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
> -     * and the exception flag is cleared
> -     */
> -    fpexc |= (1 << 30);
> -    fpexc &= ~((1 << 31) | (1 << 28));
> -    env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
> -    __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
> -    __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
> -    return (abi_ulong*)(vfpframe + 1);
> -}
> -
> -static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
> -                                             abi_ulong *regspace)
> -{
> -    int i;
> -    abi_ulong magic, sz;
> -    struct target_iwmmxt_sigframe *iwmmxtframe;
> -    iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
> -
> -    __get_user(magic, &iwmmxtframe->magic);
> -    __get_user(sz, &iwmmxtframe->size);
> -    if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
> -        return 0;
> -    }
> -    for (i = 0; i < 16; i++) {
> -        __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
> -    }
> -    __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
> -    __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
> -    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
> -    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
> -    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
> -    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
> -    return (abi_ulong*)(iwmmxtframe + 1);
> -}
> -
> -static int do_sigframe_return_v2(CPUARMState *env,
> -                                 target_ulong context_addr,
> -                                 struct target_ucontext_v2 *uc)
> -{
> -    sigset_t host_set;
> -    abi_ulong *regspace;
> -
> -    target_to_host_sigset(&host_set, &uc->tuc_sigmask);
> -    set_sigmask(&host_set);
> -
> -    if (restore_sigcontext(env, &uc->tuc_mcontext))
> -        return 1;
> -
> -    /* Restore coprocessor signal frame */
> -    regspace = uc->tuc_regspace;
> -    if (arm_feature(env, ARM_FEATURE_VFP)) {
> -        regspace = restore_sigframe_v2_vfp(env, regspace);
> -        if (!regspace) {
> -            return 1;
> -        }
> -    }
> -    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
> -        regspace = restore_sigframe_v2_iwmmxt(env, regspace);
> -        if (!regspace) {
> -            return 1;
> -        }
> -    }
> -
> -    if (do_sigaltstack(context_addr
> -                       + offsetof(struct target_ucontext_v2, tuc_stack),
> -                       0, get_sp_from_cpustate(env)) == -EFAULT) {
> -        return 1;
> -    }
> -
> -#if 0
> -    /* Send SIGTRAP if we're single-stepping */
> -    if (ptrace_cancel_bpt(current))
> -        send_sig(SIGTRAP, current, 1);
> -#endif
> -
> -    return 0;
> -}
> -
> -static long do_sigreturn_v2(CPUARMState *env)
> -{
> -    abi_ulong frame_addr;
> -    struct sigframe_v2 *frame = NULL;
> -
> -    /*
> -     * Since we stacked the signal on a 64-bit boundary,
> -     * then 'sp' should be word aligned here.  If it's
> -     * not, then the user is trying to mess with us.
> -     */
> -    frame_addr = env->regs[13];
> -    trace_user_do_sigreturn(env, frame_addr);
> -    if (frame_addr & 7) {
> -        goto badframe;
> -    }
> -
> -    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
> -        goto badframe;
> -    }
> -
> -    if (do_sigframe_return_v2(env,
> -                              frame_addr
> -                              + offsetof(struct sigframe_v2, uc),
> -                              &frame->uc)) {
> -        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;
> -}
> -
> -long do_sigreturn(CPUARMState *env)
> -{
> -    if (get_osversion() >= 0x020612) {
> -        return do_sigreturn_v2(env);
> -    } else {
> -        return do_sigreturn_v1(env);
> -    }
> -}
> -
> -static long do_rt_sigreturn_v1(CPUARMState *env)
> -{
> -    abi_ulong frame_addr;
> -    struct rt_sigframe_v1 *frame = NULL;
> -    sigset_t host_set;
> -
> -    /*
> -     * Since we stacked the signal on a 64-bit boundary,
> -     * then 'sp' should be word aligned here.  If it's
> -     * not, then the user is trying to mess with us.
> -     */
> -    frame_addr = env->regs[13];
> -    trace_user_do_rt_sigreturn(env, frame_addr);
> -    if (frame_addr & 7) {
> -        goto badframe;
> -    }
> -
> -    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
> -        goto badframe;
> -    }
> -
> -    target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
> -    set_sigmask(&host_set);
> -
> -    if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
> -        goto badframe;
> -    }
> -
> -    if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
> -        goto badframe;
> -
> -#if 0
> -    /* Send SIGTRAP if we're single-stepping */
> -    if (ptrace_cancel_bpt(current))
> -        send_sig(SIGTRAP, current, 1);
> -#endif
> -    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;
> -}
> -
> -static long do_rt_sigreturn_v2(CPUARMState *env)
> -{
> -    abi_ulong frame_addr;
> -    struct rt_sigframe_v2 *frame = NULL;
> -
> -    /*
> -     * Since we stacked the signal on a 64-bit boundary,
> -     * then 'sp' should be word aligned here.  If it's
> -     * not, then the user is trying to mess with us.
> -     */
> -    frame_addr = env->regs[13];
> -    trace_user_do_rt_sigreturn(env, frame_addr);
> -    if (frame_addr & 7) {
> -        goto badframe;
> -    }
> -
> -    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
> -        goto badframe;
> -    }
> -
> -    if (do_sigframe_return_v2(env,
> -                              frame_addr
> -                              + offsetof(struct rt_sigframe_v2, uc),
> -                              &frame->uc)) {
> -        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;
> -}
> -
> -long do_rt_sigreturn(CPUARMState *env)
> -{
> -    if (get_osversion() >= 0x020612) {
> -        return do_rt_sigreturn_v2(env);
> -    } else {
> -        return do_rt_sigreturn_v1(env);
> -    }
> -}
> -
>  #elif defined(TARGET_SPARC)
>
>  #define __SUNOS_MAXWIN   31


--
Alex Bennée
Laurent Vivier March 28, 2018, 2:40 p.m. UTC | #3
Le 28/03/2018 à 16:35, Alex Bennée a écrit :
> 
> Laurent Vivier <laurent@vivier.eu> writes:
> 
>> No code change, only move code from signal.c to
>> arm/signal.c, except adding includes and
>> exporting setup_frame() and setup_rt_frame().
>>
>> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> 
> Apparently there are some tabs in the old code, could you de-tabify on
> the next iteration please?

I don't want to change the code, just to move it.

If you look at the patchew report, you can see there are too many
changes to do...

Thanks,
Laurent
diff mbox series

Patch

diff --git a/linux-user/arm/signal.c b/linux-user/arm/signal.c
index 02ca338b6c..975f80fdd2 100644
--- a/linux-user/arm/signal.c
+++ b/linux-user/arm/signal.c
@@ -16,3 +16,757 @@ 
  *  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 {
+    abi_ulong trap_no;
+    abi_ulong error_code;
+    abi_ulong oldmask;
+    abi_ulong arm_r0;
+    abi_ulong arm_r1;
+    abi_ulong arm_r2;
+    abi_ulong arm_r3;
+    abi_ulong arm_r4;
+    abi_ulong arm_r5;
+    abi_ulong arm_r6;
+    abi_ulong arm_r7;
+    abi_ulong arm_r8;
+    abi_ulong arm_r9;
+    abi_ulong arm_r10;
+    abi_ulong arm_fp;
+    abi_ulong arm_ip;
+    abi_ulong arm_sp;
+    abi_ulong arm_lr;
+    abi_ulong arm_pc;
+    abi_ulong arm_cpsr;
+    abi_ulong fault_address;
+};
+
+struct target_ucontext_v1 {
+    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_ucontext_v2 {
+    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 */
+    char __unused[128 - sizeof(target_sigset_t)];
+    abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
+};
+
+struct target_user_vfp {
+    uint64_t fpregs[32];
+    abi_ulong fpscr;
+};
+
+struct target_user_vfp_exc {
+    abi_ulong fpexc;
+    abi_ulong fpinst;
+    abi_ulong fpinst2;
+};
+
+struct target_vfp_sigframe {
+    abi_ulong magic;
+    abi_ulong size;
+    struct target_user_vfp ufp;
+    struct target_user_vfp_exc ufp_exc;
+} __attribute__((__aligned__(8)));
+
+struct target_iwmmxt_sigframe {
+    abi_ulong magic;
+    abi_ulong size;
+    uint64_t regs[16];
+    /* Note that not all the coprocessor control registers are stored here */
+    uint32_t wcssf;
+    uint32_t wcasf;
+    uint32_t wcgr0;
+    uint32_t wcgr1;
+    uint32_t wcgr2;
+    uint32_t wcgr3;
+} __attribute__((__aligned__(8)));
+
+#define TARGET_VFP_MAGIC 0x56465001
+#define TARGET_IWMMXT_MAGIC 0x12ef842a
+
+struct sigframe_v1
+{
+    struct target_sigcontext sc;
+    abi_ulong extramask[TARGET_NSIG_WORDS-1];
+    abi_ulong retcode;
+};
+
+struct sigframe_v2
+{
+    struct target_ucontext_v2 uc;
+    abi_ulong retcode;
+};
+
+struct rt_sigframe_v1
+{
+    abi_ulong pinfo;
+    abi_ulong puc;
+    struct target_siginfo info;
+    struct target_ucontext_v1 uc;
+    abi_ulong retcode;
+};
+
+struct rt_sigframe_v2
+{
+    struct target_siginfo info;
+    struct target_ucontext_v2 uc;
+    abi_ulong retcode;
+};
+
+#define TARGET_CONFIG_CPU_32 1
+
+/*
+ * For ARM syscalls, we encode the syscall number into the instruction.
+ */
+#define SWI_SYS_SIGRETURN	(0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
+#define SWI_SYS_RT_SIGRETURN	(0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
+
+/*
+ * For Thumb syscalls, we pass the syscall number via r7.  We therefore
+ * need two 16-bit instructions.
+ */
+#define SWI_THUMB_SIGRETURN	(0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
+#define SWI_THUMB_RT_SIGRETURN	(0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
+
+static const abi_ulong retcodes[4] = {
+	SWI_SYS_SIGRETURN,	SWI_THUMB_SIGRETURN,
+	SWI_SYS_RT_SIGRETURN,	SWI_THUMB_RT_SIGRETURN
+};
+
+
+static inline int valid_user_regs(CPUARMState *regs)
+{
+    return 1;
+}
+
+static void
+setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
+                 CPUARMState *env, abi_ulong mask)
+{
+    __put_user(env->regs[0], &sc->arm_r0);
+    __put_user(env->regs[1], &sc->arm_r1);
+    __put_user(env->regs[2], &sc->arm_r2);
+    __put_user(env->regs[3], &sc->arm_r3);
+    __put_user(env->regs[4], &sc->arm_r4);
+    __put_user(env->regs[5], &sc->arm_r5);
+    __put_user(env->regs[6], &sc->arm_r6);
+    __put_user(env->regs[7], &sc->arm_r7);
+    __put_user(env->regs[8], &sc->arm_r8);
+    __put_user(env->regs[9], &sc->arm_r9);
+    __put_user(env->regs[10], &sc->arm_r10);
+    __put_user(env->regs[11], &sc->arm_fp);
+    __put_user(env->regs[12], &sc->arm_ip);
+    __put_user(env->regs[13], &sc->arm_sp);
+    __put_user(env->regs[14], &sc->arm_lr);
+    __put_user(env->regs[15], &sc->arm_pc);
+#ifdef TARGET_CONFIG_CPU_32
+    __put_user(cpsr_read(env), &sc->arm_cpsr);
+#endif
+
+    __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
+    __put_user(/* current->thread.error_code */ 0, &sc->error_code);
+    __put_user(/* current->thread.address */ 0, &sc->fault_address);
+    __put_user(mask, &sc->oldmask);
+}
+
+static inline abi_ulong
+get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
+{
+    unsigned long sp = regs->regs[13];
+
+    /*
+     * This is the X/Open sanctioned signal stack switching.
+     */
+    if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
+        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
+    }
+    /*
+     * ATPCS B01 mandates 8-byte alignment
+     */
+    return (sp - framesize) & ~7;
+}
+
+static void
+setup_return(CPUARMState *env, struct target_sigaction *ka,
+             abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
+{
+    abi_ulong handler = ka->_sa_handler;
+    abi_ulong retcode;
+    int thumb = handler & 1;
+    uint32_t cpsr = cpsr_read(env);
+
+    cpsr &= ~CPSR_IT;
+    if (thumb) {
+        cpsr |= CPSR_T;
+    } else {
+        cpsr &= ~CPSR_T;
+    }
+
+    if (ka->sa_flags & TARGET_SA_RESTORER) {
+        retcode = ka->sa_restorer;
+    } else {
+        unsigned int idx = thumb;
+
+        if (ka->sa_flags & TARGET_SA_SIGINFO) {
+            idx += 2;
+        }
+
+        __put_user(retcodes[idx], rc);
+
+        retcode = rc_addr + thumb;
+    }
+
+    env->regs[0] = usig;
+    env->regs[13] = frame_addr;
+    env->regs[14] = retcode;
+    env->regs[15] = handler & (thumb ? ~1 : ~3);
+    cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
+}
+
+static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
+{
+    int i;
+    struct target_vfp_sigframe *vfpframe;
+    vfpframe = (struct target_vfp_sigframe *)regspace;
+    __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
+    __put_user(sizeof(*vfpframe), &vfpframe->size);
+    for (i = 0; i < 32; i++) {
+        __put_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
+    }
+    __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
+    __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
+    __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
+    __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
+    return (abi_ulong*)(vfpframe+1);
+}
+
+static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
+                                           CPUARMState *env)
+{
+    int i;
+    struct target_iwmmxt_sigframe *iwmmxtframe;
+    iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
+    __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
+    __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
+    for (i = 0; i < 16; i++) {
+        __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
+    }
+    __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
+    __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
+    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
+    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
+    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
+    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
+    return (abi_ulong*)(iwmmxtframe+1);
+}
+
+static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
+                              target_sigset_t *set, CPUARMState *env)
+{
+    struct target_sigaltstack stack;
+    int i;
+    abi_ulong *regspace;
+
+    /* Clear all the bits of the ucontext we don't use.  */
+    memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
+
+    memset(&stack, 0, sizeof(stack));
+    __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
+    __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
+    __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
+    memcpy(&uc->tuc_stack, &stack, sizeof(stack));
+
+    setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
+    /* Save coprocessor signal frame.  */
+    regspace = uc->tuc_regspace;
+    if (arm_feature(env, ARM_FEATURE_VFP)) {
+        regspace = setup_sigframe_v2_vfp(regspace, env);
+    }
+    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
+        regspace = setup_sigframe_v2_iwmmxt(regspace, env);
+    }
+
+    /* Write terminating magic word */
+    __put_user(0, regspace);
+
+    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
+        __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
+    }
+}
+
+/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
+static void setup_frame_v1(int usig, struct target_sigaction *ka,
+                           target_sigset_t *set, CPUARMState *regs)
+{
+    struct sigframe_v1 *frame;
+    abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
+    int i;
+
+    trace_user_setup_frame(regs, frame_addr);
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+        goto sigsegv;
+    }
+
+    setup_sigcontext(&frame->sc, regs, set->sig[0]);
+
+    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
+        __put_user(set->sig[i], &frame->extramask[i - 1]);
+    }
+
+    setup_return(regs, ka, &frame->retcode, frame_addr, usig,
+                 frame_addr + offsetof(struct sigframe_v1, retcode));
+
+    unlock_user_struct(frame, frame_addr, 1);
+    return;
+sigsegv:
+    force_sigsegv(usig);
+}
+
+static void setup_frame_v2(int usig, struct target_sigaction *ka,
+                           target_sigset_t *set, CPUARMState *regs)
+{
+    struct sigframe_v2 *frame;
+    abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
+
+    trace_user_setup_frame(regs, frame_addr);
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+        goto sigsegv;
+    }
+
+    setup_sigframe_v2(&frame->uc, set, regs);
+
+    setup_return(regs, ka, &frame->retcode, frame_addr, usig,
+                 frame_addr + offsetof(struct sigframe_v2, retcode));
+
+    unlock_user_struct(frame, frame_addr, 1);
+    return;
+sigsegv:
+    force_sigsegv(usig);
+}
+
+void setup_frame(int usig, struct target_sigaction *ka,
+                 target_sigset_t *set, CPUARMState *regs)
+{
+    if (get_osversion() >= 0x020612) {
+        setup_frame_v2(usig, ka, set, regs);
+    } else {
+        setup_frame_v1(usig, ka, set, regs);
+    }
+}
+
+/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
+static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
+                              target_siginfo_t *info,
+                              target_sigset_t *set, CPUARMState *env)
+{
+    struct rt_sigframe_v1 *frame;
+    abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
+    struct target_sigaltstack stack;
+    int i;
+    abi_ulong info_addr, uc_addr;
+
+    trace_user_setup_rt_frame(env, frame_addr);
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+        goto sigsegv;
+    }
+
+    info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
+    __put_user(info_addr, &frame->pinfo);
+    uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
+    __put_user(uc_addr, &frame->puc);
+    tswap_siginfo(&frame->info, info);
+
+    /* Clear all the bits of the ucontext we don't use.  */
+    memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
+
+    memset(&stack, 0, sizeof(stack));
+    __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
+    __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
+    __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
+    memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
+
+    setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
+    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
+        __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
+    }
+
+    setup_return(env, ka, &frame->retcode, frame_addr, usig,
+                 frame_addr + offsetof(struct rt_sigframe_v1, retcode));
+
+    env->regs[1] = info_addr;
+    env->regs[2] = uc_addr;
+
+    unlock_user_struct(frame, frame_addr, 1);
+    return;
+sigsegv:
+    force_sigsegv(usig);
+}
+
+static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
+                              target_siginfo_t *info,
+                              target_sigset_t *set, CPUARMState *env)
+{
+    struct rt_sigframe_v2 *frame;
+    abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
+    abi_ulong info_addr, uc_addr;
+
+    trace_user_setup_rt_frame(env, frame_addr);
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+        goto sigsegv;
+    }
+
+    info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
+    uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
+    tswap_siginfo(&frame->info, info);
+
+    setup_sigframe_v2(&frame->uc, set, env);
+
+    setup_return(env, ka, &frame->retcode, frame_addr, usig,
+                 frame_addr + offsetof(struct rt_sigframe_v2, retcode));
+
+    env->regs[1] = info_addr;
+    env->regs[2] = uc_addr;
+
+    unlock_user_struct(frame, frame_addr, 1);
+    return;
+sigsegv:
+    force_sigsegv(usig);
+}
+
+void setup_rt_frame(int usig, struct target_sigaction *ka,
+                    target_siginfo_t *info,
+                    target_sigset_t *set, CPUARMState *env)
+{
+    if (get_osversion() >= 0x020612) {
+        setup_rt_frame_v2(usig, ka, info, set, env);
+    } else {
+        setup_rt_frame_v1(usig, ka, info, set, env);
+    }
+}
+
+static int
+restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
+{
+    int err = 0;
+    uint32_t cpsr;
+
+    __get_user(env->regs[0], &sc->arm_r0);
+    __get_user(env->regs[1], &sc->arm_r1);
+    __get_user(env->regs[2], &sc->arm_r2);
+    __get_user(env->regs[3], &sc->arm_r3);
+    __get_user(env->regs[4], &sc->arm_r4);
+    __get_user(env->regs[5], &sc->arm_r5);
+    __get_user(env->regs[6], &sc->arm_r6);
+    __get_user(env->regs[7], &sc->arm_r7);
+    __get_user(env->regs[8], &sc->arm_r8);
+    __get_user(env->regs[9], &sc->arm_r9);
+    __get_user(env->regs[10], &sc->arm_r10);
+    __get_user(env->regs[11], &sc->arm_fp);
+    __get_user(env->regs[12], &sc->arm_ip);
+    __get_user(env->regs[13], &sc->arm_sp);
+    __get_user(env->regs[14], &sc->arm_lr);
+    __get_user(env->regs[15], &sc->arm_pc);
+#ifdef TARGET_CONFIG_CPU_32
+    __get_user(cpsr, &sc->arm_cpsr);
+    cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
+#endif
+
+    err |= !valid_user_regs(env);
+
+    return err;
+}
+
+static long do_sigreturn_v1(CPUARMState *env)
+{
+    abi_ulong frame_addr;
+    struct sigframe_v1 *frame = NULL;
+    target_sigset_t set;
+    sigset_t host_set;
+    int i;
+
+    /*
+     * Since we stacked the signal on a 64-bit boundary,
+     * then 'sp' should be word aligned here.  If it's
+     * not, then the user is trying to mess with us.
+     */
+    frame_addr = env->regs[13];
+    trace_user_do_sigreturn(env, frame_addr);
+    if (frame_addr & 7) {
+        goto badframe;
+    }
+
+    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
+        goto badframe;
+    }
+
+    __get_user(set.sig[0], &frame->sc.oldmask);
+    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
+        __get_user(set.sig[i], &frame->extramask[i - 1]);
+    }
+
+    target_to_host_sigset_internal(&host_set, &set);
+    set_sigmask(&host_set);
+
+    if (restore_sigcontext(env, &frame->sc)) {
+        goto badframe;
+    }
+
+#if 0
+    /* Send SIGTRAP if we're single-stepping */
+    if (ptrace_cancel_bpt(current))
+        send_sig(SIGTRAP, current, 1);
+#endif
+    unlock_user_struct(frame, frame_addr, 0);
+    return -TARGET_QEMU_ESIGRETURN;
+
+badframe:
+    force_sig(TARGET_SIGSEGV);
+    return -TARGET_QEMU_ESIGRETURN;
+}
+
+static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
+{
+    int i;
+    abi_ulong magic, sz;
+    uint32_t fpscr, fpexc;
+    struct target_vfp_sigframe *vfpframe;
+    vfpframe = (struct target_vfp_sigframe *)regspace;
+
+    __get_user(magic, &vfpframe->magic);
+    __get_user(sz, &vfpframe->size);
+    if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
+        return 0;
+    }
+    for (i = 0; i < 32; i++) {
+        __get_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
+    }
+    __get_user(fpscr, &vfpframe->ufp.fpscr);
+    vfp_set_fpscr(env, fpscr);
+    __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
+    /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
+     * and the exception flag is cleared
+     */
+    fpexc |= (1 << 30);
+    fpexc &= ~((1 << 31) | (1 << 28));
+    env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
+    __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
+    __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
+    return (abi_ulong*)(vfpframe + 1);
+}
+
+static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
+                                             abi_ulong *regspace)
+{
+    int i;
+    abi_ulong magic, sz;
+    struct target_iwmmxt_sigframe *iwmmxtframe;
+    iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
+
+    __get_user(magic, &iwmmxtframe->magic);
+    __get_user(sz, &iwmmxtframe->size);
+    if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
+        return 0;
+    }
+    for (i = 0; i < 16; i++) {
+        __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
+    }
+    __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
+    __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
+    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
+    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
+    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
+    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
+    return (abi_ulong*)(iwmmxtframe + 1);
+}
+
+static int do_sigframe_return_v2(CPUARMState *env,
+                                 target_ulong context_addr,
+                                 struct target_ucontext_v2 *uc)
+{
+    sigset_t host_set;
+    abi_ulong *regspace;
+
+    target_to_host_sigset(&host_set, &uc->tuc_sigmask);
+    set_sigmask(&host_set);
+
+    if (restore_sigcontext(env, &uc->tuc_mcontext))
+        return 1;
+
+    /* Restore coprocessor signal frame */
+    regspace = uc->tuc_regspace;
+    if (arm_feature(env, ARM_FEATURE_VFP)) {
+        regspace = restore_sigframe_v2_vfp(env, regspace);
+        if (!regspace) {
+            return 1;
+        }
+    }
+    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
+        regspace = restore_sigframe_v2_iwmmxt(env, regspace);
+        if (!regspace) {
+            return 1;
+        }
+    }
+
+    if (do_sigaltstack(context_addr
+                       + offsetof(struct target_ucontext_v2, tuc_stack),
+                       0, get_sp_from_cpustate(env)) == -EFAULT) {
+        return 1;
+    }
+
+#if 0
+    /* Send SIGTRAP if we're single-stepping */
+    if (ptrace_cancel_bpt(current))
+        send_sig(SIGTRAP, current, 1);
+#endif
+
+    return 0;
+}
+
+static long do_sigreturn_v2(CPUARMState *env)
+{
+    abi_ulong frame_addr;
+    struct sigframe_v2 *frame = NULL;
+
+    /*
+     * Since we stacked the signal on a 64-bit boundary,
+     * then 'sp' should be word aligned here.  If it's
+     * not, then the user is trying to mess with us.
+     */
+    frame_addr = env->regs[13];
+    trace_user_do_sigreturn(env, frame_addr);
+    if (frame_addr & 7) {
+        goto badframe;
+    }
+
+    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
+        goto badframe;
+    }
+
+    if (do_sigframe_return_v2(env,
+                              frame_addr
+                              + offsetof(struct sigframe_v2, uc),
+                              &frame->uc)) {
+        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;
+}
+
+long do_sigreturn(CPUARMState *env)
+{
+    if (get_osversion() >= 0x020612) {
+        return do_sigreturn_v2(env);
+    } else {
+        return do_sigreturn_v1(env);
+    }
+}
+
+static long do_rt_sigreturn_v1(CPUARMState *env)
+{
+    abi_ulong frame_addr;
+    struct rt_sigframe_v1 *frame = NULL;
+    sigset_t host_set;
+
+    /*
+     * Since we stacked the signal on a 64-bit boundary,
+     * then 'sp' should be word aligned here.  If it's
+     * not, then the user is trying to mess with us.
+     */
+    frame_addr = env->regs[13];
+    trace_user_do_rt_sigreturn(env, frame_addr);
+    if (frame_addr & 7) {
+        goto badframe;
+    }
+
+    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
+        goto badframe;
+    }
+
+    target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
+    set_sigmask(&host_set);
+
+    if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
+        goto badframe;
+    }
+
+    if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
+        goto badframe;
+
+#if 0
+    /* Send SIGTRAP if we're single-stepping */
+    if (ptrace_cancel_bpt(current))
+        send_sig(SIGTRAP, current, 1);
+#endif
+    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;
+}
+
+static long do_rt_sigreturn_v2(CPUARMState *env)
+{
+    abi_ulong frame_addr;
+    struct rt_sigframe_v2 *frame = NULL;
+
+    /*
+     * Since we stacked the signal on a 64-bit boundary,
+     * then 'sp' should be word aligned here.  If it's
+     * not, then the user is trying to mess with us.
+     */
+    frame_addr = env->regs[13];
+    trace_user_do_rt_sigreturn(env, frame_addr);
+    if (frame_addr & 7) {
+        goto badframe;
+    }
+
+    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
+        goto badframe;
+    }
+
+    if (do_sigframe_return_v2(env,
+                              frame_addr
+                              + offsetof(struct rt_sigframe_v2, uc),
+                              &frame->uc)) {
+        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;
+}
+
+long do_rt_sigreturn(CPUARMState *env)
+{
+    if (get_osversion() >= 0x020612) {
+        return do_rt_sigreturn_v2(env);
+    } else {
+        return do_rt_sigreturn_v1(env);
+    }
+}
diff --git a/linux-user/arm/target_signal.h b/linux-user/arm/target_signal.h
index cbbeb09f4d..4b542c324f 100644
--- a/linux-user/arm/target_signal.h
+++ b/linux-user/arm/target_signal.h
@@ -26,5 +26,9 @@  static inline abi_ulong get_sp_from_cpustate(CPUARMState *state)
    return state->regs[13];
 }
 
-
+void setup_frame(int usig, struct target_sigaction *ka,
+                 target_sigset_t *set, CPUARMState *regs);
+void setup_rt_frame(int usig, struct target_sigaction *ka,
+                    target_siginfo_t *info,
+                    target_sigset_t *set, CPUARMState *env);
 #endif /* ARM_TARGET_SIGNAL_H */
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 2b05d7951b..38ebba9cf6 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1383,757 +1383,6 @@  badframe:
     return -TARGET_QEMU_ESIGRETURN;
 }
 
-#elif defined(TARGET_ARM) && !defined(TARGET_AARCH64)
-
-struct target_sigcontext {
-    abi_ulong trap_no;
-    abi_ulong error_code;
-    abi_ulong oldmask;
-    abi_ulong arm_r0;
-    abi_ulong arm_r1;
-    abi_ulong arm_r2;
-    abi_ulong arm_r3;
-    abi_ulong arm_r4;
-    abi_ulong arm_r5;
-    abi_ulong arm_r6;
-    abi_ulong arm_r7;
-    abi_ulong arm_r8;
-    abi_ulong arm_r9;
-    abi_ulong arm_r10;
-    abi_ulong arm_fp;
-    abi_ulong arm_ip;
-    abi_ulong arm_sp;
-    abi_ulong arm_lr;
-    abi_ulong arm_pc;
-    abi_ulong arm_cpsr;
-    abi_ulong fault_address;
-};
-
-struct target_ucontext_v1 {
-    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_ucontext_v2 {
-    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 */
-    char __unused[128 - sizeof(target_sigset_t)];
-    abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
-};
-
-struct target_user_vfp {
-    uint64_t fpregs[32];
-    abi_ulong fpscr;
-};
-
-struct target_user_vfp_exc {
-    abi_ulong fpexc;
-    abi_ulong fpinst;
-    abi_ulong fpinst2;
-};
-
-struct target_vfp_sigframe {
-    abi_ulong magic;
-    abi_ulong size;
-    struct target_user_vfp ufp;
-    struct target_user_vfp_exc ufp_exc;
-} __attribute__((__aligned__(8)));
-
-struct target_iwmmxt_sigframe {
-    abi_ulong magic;
-    abi_ulong size;
-    uint64_t regs[16];
-    /* Note that not all the coprocessor control registers are stored here */
-    uint32_t wcssf;
-    uint32_t wcasf;
-    uint32_t wcgr0;
-    uint32_t wcgr1;
-    uint32_t wcgr2;
-    uint32_t wcgr3;
-} __attribute__((__aligned__(8)));
-
-#define TARGET_VFP_MAGIC 0x56465001
-#define TARGET_IWMMXT_MAGIC 0x12ef842a
-
-struct sigframe_v1
-{
-    struct target_sigcontext sc;
-    abi_ulong extramask[TARGET_NSIG_WORDS-1];
-    abi_ulong retcode;
-};
-
-struct sigframe_v2
-{
-    struct target_ucontext_v2 uc;
-    abi_ulong retcode;
-};
-
-struct rt_sigframe_v1
-{
-    abi_ulong pinfo;
-    abi_ulong puc;
-    struct target_siginfo info;
-    struct target_ucontext_v1 uc;
-    abi_ulong retcode;
-};
-
-struct rt_sigframe_v2
-{
-    struct target_siginfo info;
-    struct target_ucontext_v2 uc;
-    abi_ulong retcode;
-};
-
-#define TARGET_CONFIG_CPU_32 1
-
-/*
- * For ARM syscalls, we encode the syscall number into the instruction.
- */
-#define SWI_SYS_SIGRETURN	(0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
-#define SWI_SYS_RT_SIGRETURN	(0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
-
-/*
- * For Thumb syscalls, we pass the syscall number via r7.  We therefore
- * need two 16-bit instructions.
- */
-#define SWI_THUMB_SIGRETURN	(0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
-#define SWI_THUMB_RT_SIGRETURN	(0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
-
-static const abi_ulong retcodes[4] = {
-	SWI_SYS_SIGRETURN,	SWI_THUMB_SIGRETURN,
-	SWI_SYS_RT_SIGRETURN,	SWI_THUMB_RT_SIGRETURN
-};
-
-
-static inline int valid_user_regs(CPUARMState *regs)
-{
-    return 1;
-}
-
-static void
-setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
-                 CPUARMState *env, abi_ulong mask)
-{
-    __put_user(env->regs[0], &sc->arm_r0);
-    __put_user(env->regs[1], &sc->arm_r1);
-    __put_user(env->regs[2], &sc->arm_r2);
-    __put_user(env->regs[3], &sc->arm_r3);
-    __put_user(env->regs[4], &sc->arm_r4);
-    __put_user(env->regs[5], &sc->arm_r5);
-    __put_user(env->regs[6], &sc->arm_r6);
-    __put_user(env->regs[7], &sc->arm_r7);
-    __put_user(env->regs[8], &sc->arm_r8);
-    __put_user(env->regs[9], &sc->arm_r9);
-    __put_user(env->regs[10], &sc->arm_r10);
-    __put_user(env->regs[11], &sc->arm_fp);
-    __put_user(env->regs[12], &sc->arm_ip);
-    __put_user(env->regs[13], &sc->arm_sp);
-    __put_user(env->regs[14], &sc->arm_lr);
-    __put_user(env->regs[15], &sc->arm_pc);
-#ifdef TARGET_CONFIG_CPU_32
-    __put_user(cpsr_read(env), &sc->arm_cpsr);
-#endif
-
-    __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
-    __put_user(/* current->thread.error_code */ 0, &sc->error_code);
-    __put_user(/* current->thread.address */ 0, &sc->fault_address);
-    __put_user(mask, &sc->oldmask);
-}
-
-static inline abi_ulong
-get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
-{
-    unsigned long sp = regs->regs[13];
-
-    /*
-     * This is the X/Open sanctioned signal stack switching.
-     */
-    if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
-        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
-    }
-    /*
-     * ATPCS B01 mandates 8-byte alignment
-     */
-    return (sp - framesize) & ~7;
-}
-
-static void
-setup_return(CPUARMState *env, struct target_sigaction *ka,
-             abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
-{
-    abi_ulong handler = ka->_sa_handler;
-    abi_ulong retcode;
-    int thumb = handler & 1;
-    uint32_t cpsr = cpsr_read(env);
-
-    cpsr &= ~CPSR_IT;
-    if (thumb) {
-        cpsr |= CPSR_T;
-    } else {
-        cpsr &= ~CPSR_T;
-    }
-
-    if (ka->sa_flags & TARGET_SA_RESTORER) {
-        retcode = ka->sa_restorer;
-    } else {
-        unsigned int idx = thumb;
-
-        if (ka->sa_flags & TARGET_SA_SIGINFO) {
-            idx += 2;
-        }
-
-        __put_user(retcodes[idx], rc);
-
-        retcode = rc_addr + thumb;
-    }
-
-    env->regs[0] = usig;
-    env->regs[13] = frame_addr;
-    env->regs[14] = retcode;
-    env->regs[15] = handler & (thumb ? ~1 : ~3);
-    cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
-}
-
-static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
-{
-    int i;
-    struct target_vfp_sigframe *vfpframe;
-    vfpframe = (struct target_vfp_sigframe *)regspace;
-    __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
-    __put_user(sizeof(*vfpframe), &vfpframe->size);
-    for (i = 0; i < 32; i++) {
-        __put_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
-    }
-    __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
-    __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
-    __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
-    __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
-    return (abi_ulong*)(vfpframe+1);
-}
-
-static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
-                                           CPUARMState *env)
-{
-    int i;
-    struct target_iwmmxt_sigframe *iwmmxtframe;
-    iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
-    __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
-    __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
-    for (i = 0; i < 16; i++) {
-        __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
-    }
-    __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
-    __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
-    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
-    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
-    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
-    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
-    return (abi_ulong*)(iwmmxtframe+1);
-}
-
-static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
-                              target_sigset_t *set, CPUARMState *env)
-{
-    struct target_sigaltstack stack;
-    int i;
-    abi_ulong *regspace;
-
-    /* Clear all the bits of the ucontext we don't use.  */
-    memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
-
-    memset(&stack, 0, sizeof(stack));
-    __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
-    __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
-    __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
-    memcpy(&uc->tuc_stack, &stack, sizeof(stack));
-
-    setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
-    /* Save coprocessor signal frame.  */
-    regspace = uc->tuc_regspace;
-    if (arm_feature(env, ARM_FEATURE_VFP)) {
-        regspace = setup_sigframe_v2_vfp(regspace, env);
-    }
-    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
-        regspace = setup_sigframe_v2_iwmmxt(regspace, env);
-    }
-
-    /* Write terminating magic word */
-    __put_user(0, regspace);
-
-    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
-        __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
-    }
-}
-
-/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
-static void setup_frame_v1(int usig, struct target_sigaction *ka,
-                           target_sigset_t *set, CPUARMState *regs)
-{
-    struct sigframe_v1 *frame;
-    abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
-    int i;
-
-    trace_user_setup_frame(regs, frame_addr);
-    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
-        goto sigsegv;
-    }
-
-    setup_sigcontext(&frame->sc, regs, set->sig[0]);
-
-    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
-        __put_user(set->sig[i], &frame->extramask[i - 1]);
-    }
-
-    setup_return(regs, ka, &frame->retcode, frame_addr, usig,
-                 frame_addr + offsetof(struct sigframe_v1, retcode));
-
-    unlock_user_struct(frame, frame_addr, 1);
-    return;
-sigsegv:
-    force_sigsegv(usig);
-}
-
-static void setup_frame_v2(int usig, struct target_sigaction *ka,
-                           target_sigset_t *set, CPUARMState *regs)
-{
-    struct sigframe_v2 *frame;
-    abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
-
-    trace_user_setup_frame(regs, frame_addr);
-    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
-        goto sigsegv;
-    }
-
-    setup_sigframe_v2(&frame->uc, set, regs);
-
-    setup_return(regs, ka, &frame->retcode, frame_addr, usig,
-                 frame_addr + offsetof(struct sigframe_v2, retcode));
-
-    unlock_user_struct(frame, frame_addr, 1);
-    return;
-sigsegv:
-    force_sigsegv(usig);
-}
-
-static void setup_frame(int usig, struct target_sigaction *ka,
-                        target_sigset_t *set, CPUARMState *regs)
-{
-    if (get_osversion() >= 0x020612) {
-        setup_frame_v2(usig, ka, set, regs);
-    } else {
-        setup_frame_v1(usig, ka, set, regs);
-    }
-}
-
-/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
-static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
-                              target_siginfo_t *info,
-                              target_sigset_t *set, CPUARMState *env)
-{
-    struct rt_sigframe_v1 *frame;
-    abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
-    struct target_sigaltstack stack;
-    int i;
-    abi_ulong info_addr, uc_addr;
-
-    trace_user_setup_rt_frame(env, frame_addr);
-    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
-        goto sigsegv;
-    }
-
-    info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
-    __put_user(info_addr, &frame->pinfo);
-    uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
-    __put_user(uc_addr, &frame->puc);
-    tswap_siginfo(&frame->info, info);
-
-    /* Clear all the bits of the ucontext we don't use.  */
-    memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
-
-    memset(&stack, 0, sizeof(stack));
-    __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
-    __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
-    __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
-    memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
-
-    setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
-    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
-        __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
-    }
-
-    setup_return(env, ka, &frame->retcode, frame_addr, usig,
-                 frame_addr + offsetof(struct rt_sigframe_v1, retcode));
-
-    env->regs[1] = info_addr;
-    env->regs[2] = uc_addr;
-
-    unlock_user_struct(frame, frame_addr, 1);
-    return;
-sigsegv:
-    force_sigsegv(usig);
-}
-
-static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
-                              target_siginfo_t *info,
-                              target_sigset_t *set, CPUARMState *env)
-{
-    struct rt_sigframe_v2 *frame;
-    abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
-    abi_ulong info_addr, uc_addr;
-
-    trace_user_setup_rt_frame(env, frame_addr);
-    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
-        goto sigsegv;
-    }
-
-    info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
-    uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
-    tswap_siginfo(&frame->info, info);
-
-    setup_sigframe_v2(&frame->uc, set, env);
-
-    setup_return(env, ka, &frame->retcode, frame_addr, usig,
-                 frame_addr + offsetof(struct rt_sigframe_v2, retcode));
-
-    env->regs[1] = info_addr;
-    env->regs[2] = uc_addr;
-
-    unlock_user_struct(frame, frame_addr, 1);
-    return;
-sigsegv:
-    force_sigsegv(usig);
-}
-
-static void setup_rt_frame(int usig, struct target_sigaction *ka,
-                           target_siginfo_t *info,
-                           target_sigset_t *set, CPUARMState *env)
-{
-    if (get_osversion() >= 0x020612) {
-        setup_rt_frame_v2(usig, ka, info, set, env);
-    } else {
-        setup_rt_frame_v1(usig, ka, info, set, env);
-    }
-}
-
-static int
-restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
-{
-    int err = 0;
-    uint32_t cpsr;
-
-    __get_user(env->regs[0], &sc->arm_r0);
-    __get_user(env->regs[1], &sc->arm_r1);
-    __get_user(env->regs[2], &sc->arm_r2);
-    __get_user(env->regs[3], &sc->arm_r3);
-    __get_user(env->regs[4], &sc->arm_r4);
-    __get_user(env->regs[5], &sc->arm_r5);
-    __get_user(env->regs[6], &sc->arm_r6);
-    __get_user(env->regs[7], &sc->arm_r7);
-    __get_user(env->regs[8], &sc->arm_r8);
-    __get_user(env->regs[9], &sc->arm_r9);
-    __get_user(env->regs[10], &sc->arm_r10);
-    __get_user(env->regs[11], &sc->arm_fp);
-    __get_user(env->regs[12], &sc->arm_ip);
-    __get_user(env->regs[13], &sc->arm_sp);
-    __get_user(env->regs[14], &sc->arm_lr);
-    __get_user(env->regs[15], &sc->arm_pc);
-#ifdef TARGET_CONFIG_CPU_32
-    __get_user(cpsr, &sc->arm_cpsr);
-    cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
-#endif
-
-    err |= !valid_user_regs(env);
-
-    return err;
-}
-
-static long do_sigreturn_v1(CPUARMState *env)
-{
-    abi_ulong frame_addr;
-    struct sigframe_v1 *frame = NULL;
-    target_sigset_t set;
-    sigset_t host_set;
-    int i;
-
-    /*
-     * Since we stacked the signal on a 64-bit boundary,
-     * then 'sp' should be word aligned here.  If it's
-     * not, then the user is trying to mess with us.
-     */
-    frame_addr = env->regs[13];
-    trace_user_do_sigreturn(env, frame_addr);
-    if (frame_addr & 7) {
-        goto badframe;
-    }
-
-    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
-        goto badframe;
-    }
-
-    __get_user(set.sig[0], &frame->sc.oldmask);
-    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
-        __get_user(set.sig[i], &frame->extramask[i - 1]);
-    }
-
-    target_to_host_sigset_internal(&host_set, &set);
-    set_sigmask(&host_set);
-
-    if (restore_sigcontext(env, &frame->sc)) {
-        goto badframe;
-    }
-
-#if 0
-    /* Send SIGTRAP if we're single-stepping */
-    if (ptrace_cancel_bpt(current))
-        send_sig(SIGTRAP, current, 1);
-#endif
-    unlock_user_struct(frame, frame_addr, 0);
-    return -TARGET_QEMU_ESIGRETURN;
-
-badframe:
-    force_sig(TARGET_SIGSEGV);
-    return -TARGET_QEMU_ESIGRETURN;
-}
-
-static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
-{
-    int i;
-    abi_ulong magic, sz;
-    uint32_t fpscr, fpexc;
-    struct target_vfp_sigframe *vfpframe;
-    vfpframe = (struct target_vfp_sigframe *)regspace;
-
-    __get_user(magic, &vfpframe->magic);
-    __get_user(sz, &vfpframe->size);
-    if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
-        return 0;
-    }
-    for (i = 0; i < 32; i++) {
-        __get_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
-    }
-    __get_user(fpscr, &vfpframe->ufp.fpscr);
-    vfp_set_fpscr(env, fpscr);
-    __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
-    /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
-     * and the exception flag is cleared
-     */
-    fpexc |= (1 << 30);
-    fpexc &= ~((1 << 31) | (1 << 28));
-    env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
-    __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
-    __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
-    return (abi_ulong*)(vfpframe + 1);
-}
-
-static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
-                                             abi_ulong *regspace)
-{
-    int i;
-    abi_ulong magic, sz;
-    struct target_iwmmxt_sigframe *iwmmxtframe;
-    iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
-
-    __get_user(magic, &iwmmxtframe->magic);
-    __get_user(sz, &iwmmxtframe->size);
-    if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
-        return 0;
-    }
-    for (i = 0; i < 16; i++) {
-        __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
-    }
-    __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
-    __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
-    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
-    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
-    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
-    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
-    return (abi_ulong*)(iwmmxtframe + 1);
-}
-
-static int do_sigframe_return_v2(CPUARMState *env,
-                                 target_ulong context_addr,
-                                 struct target_ucontext_v2 *uc)
-{
-    sigset_t host_set;
-    abi_ulong *regspace;
-
-    target_to_host_sigset(&host_set, &uc->tuc_sigmask);
-    set_sigmask(&host_set);
-
-    if (restore_sigcontext(env, &uc->tuc_mcontext))
-        return 1;
-
-    /* Restore coprocessor signal frame */
-    regspace = uc->tuc_regspace;
-    if (arm_feature(env, ARM_FEATURE_VFP)) {
-        regspace = restore_sigframe_v2_vfp(env, regspace);
-        if (!regspace) {
-            return 1;
-        }
-    }
-    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
-        regspace = restore_sigframe_v2_iwmmxt(env, regspace);
-        if (!regspace) {
-            return 1;
-        }
-    }
-
-    if (do_sigaltstack(context_addr
-                       + offsetof(struct target_ucontext_v2, tuc_stack),
-                       0, get_sp_from_cpustate(env)) == -EFAULT) {
-        return 1;
-    }
-
-#if 0
-    /* Send SIGTRAP if we're single-stepping */
-    if (ptrace_cancel_bpt(current))
-        send_sig(SIGTRAP, current, 1);
-#endif
-
-    return 0;
-}
-
-static long do_sigreturn_v2(CPUARMState *env)
-{
-    abi_ulong frame_addr;
-    struct sigframe_v2 *frame = NULL;
-
-    /*
-     * Since we stacked the signal on a 64-bit boundary,
-     * then 'sp' should be word aligned here.  If it's
-     * not, then the user is trying to mess with us.
-     */
-    frame_addr = env->regs[13];
-    trace_user_do_sigreturn(env, frame_addr);
-    if (frame_addr & 7) {
-        goto badframe;
-    }
-
-    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
-        goto badframe;
-    }
-
-    if (do_sigframe_return_v2(env,
-                              frame_addr
-                              + offsetof(struct sigframe_v2, uc),
-                              &frame->uc)) {
-        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;
-}
-
-long do_sigreturn(CPUARMState *env)
-{
-    if (get_osversion() >= 0x020612) {
-        return do_sigreturn_v2(env);
-    } else {
-        return do_sigreturn_v1(env);
-    }
-}
-
-static long do_rt_sigreturn_v1(CPUARMState *env)
-{
-    abi_ulong frame_addr;
-    struct rt_sigframe_v1 *frame = NULL;
-    sigset_t host_set;
-
-    /*
-     * Since we stacked the signal on a 64-bit boundary,
-     * then 'sp' should be word aligned here.  If it's
-     * not, then the user is trying to mess with us.
-     */
-    frame_addr = env->regs[13];
-    trace_user_do_rt_sigreturn(env, frame_addr);
-    if (frame_addr & 7) {
-        goto badframe;
-    }
-
-    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
-        goto badframe;
-    }
-
-    target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
-    set_sigmask(&host_set);
-
-    if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
-        goto badframe;
-    }
-
-    if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
-        goto badframe;
-
-#if 0
-    /* Send SIGTRAP if we're single-stepping */
-    if (ptrace_cancel_bpt(current))
-        send_sig(SIGTRAP, current, 1);
-#endif
-    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;
-}
-
-static long do_rt_sigreturn_v2(CPUARMState *env)
-{
-    abi_ulong frame_addr;
-    struct rt_sigframe_v2 *frame = NULL;
-
-    /*
-     * Since we stacked the signal on a 64-bit boundary,
-     * then 'sp' should be word aligned here.  If it's
-     * not, then the user is trying to mess with us.
-     */
-    frame_addr = env->regs[13];
-    trace_user_do_rt_sigreturn(env, frame_addr);
-    if (frame_addr & 7) {
-        goto badframe;
-    }
-
-    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
-        goto badframe;
-    }
-
-    if (do_sigframe_return_v2(env,
-                              frame_addr
-                              + offsetof(struct rt_sigframe_v2, uc),
-                              &frame->uc)) {
-        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;
-}
-
-long do_rt_sigreturn(CPUARMState *env)
-{
-    if (get_osversion() >= 0x020612) {
-        return do_rt_sigreturn_v2(env);
-    } else {
-        return do_rt_sigreturn_v1(env);
-    }
-}
-
 #elif defined(TARGET_SPARC)
 
 #define __SUNOS_MAXWIN   31