qemu/linux-user/arm/signal.c
<<
>>
Prefs
   1/*
   2 *  Emulation of Linux signals
   3 *
   4 *  Copyright (c) 2003 Fabrice Bellard
   5 *
   6 *  This program is free software; you can redistribute it and/or modify
   7 *  it under the terms of the GNU General Public License as published by
   8 *  the Free Software Foundation; either version 2 of the License, or
   9 *  (at your option) any later version.
  10 *
  11 *  This program is distributed in the hope that it will be useful,
  12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 *  GNU General Public License for more details.
  15 *
  16 *  You should have received a copy of the GNU General Public License
  17 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  18 */
  19#include "qemu/osdep.h"
  20#include "qemu.h"
  21#include "signal-common.h"
  22#include "linux-user/trace.h"
  23
  24struct target_sigcontext {
  25    abi_ulong trap_no;
  26    abi_ulong error_code;
  27    abi_ulong oldmask;
  28    abi_ulong arm_r0;
  29    abi_ulong arm_r1;
  30    abi_ulong arm_r2;
  31    abi_ulong arm_r3;
  32    abi_ulong arm_r4;
  33    abi_ulong arm_r5;
  34    abi_ulong arm_r6;
  35    abi_ulong arm_r7;
  36    abi_ulong arm_r8;
  37    abi_ulong arm_r9;
  38    abi_ulong arm_r10;
  39    abi_ulong arm_fp;
  40    abi_ulong arm_ip;
  41    abi_ulong arm_sp;
  42    abi_ulong arm_lr;
  43    abi_ulong arm_pc;
  44    abi_ulong arm_cpsr;
  45    abi_ulong fault_address;
  46};
  47
  48struct target_ucontext_v1 {
  49    abi_ulong tuc_flags;
  50    abi_ulong tuc_link;
  51    target_stack_t tuc_stack;
  52    struct target_sigcontext tuc_mcontext;
  53    target_sigset_t  tuc_sigmask;       /* mask last for extensibility */
  54};
  55
  56struct target_ucontext_v2 {
  57    abi_ulong tuc_flags;
  58    abi_ulong tuc_link;
  59    target_stack_t tuc_stack;
  60    struct target_sigcontext tuc_mcontext;
  61    target_sigset_t  tuc_sigmask;       /* mask last for extensibility */
  62    char __unused[128 - sizeof(target_sigset_t)];
  63    abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
  64};
  65
  66struct target_user_vfp {
  67    uint64_t fpregs[32];
  68    abi_ulong fpscr;
  69};
  70
  71struct target_user_vfp_exc {
  72    abi_ulong fpexc;
  73    abi_ulong fpinst;
  74    abi_ulong fpinst2;
  75};
  76
  77struct target_vfp_sigframe {
  78    abi_ulong magic;
  79    abi_ulong size;
  80    struct target_user_vfp ufp;
  81    struct target_user_vfp_exc ufp_exc;
  82} __attribute__((__aligned__(8)));
  83
  84struct target_iwmmxt_sigframe {
  85    abi_ulong magic;
  86    abi_ulong size;
  87    uint64_t regs[16];
  88    /* Note that not all the coprocessor control registers are stored here */
  89    uint32_t wcssf;
  90    uint32_t wcasf;
  91    uint32_t wcgr0;
  92    uint32_t wcgr1;
  93    uint32_t wcgr2;
  94    uint32_t wcgr3;
  95} __attribute__((__aligned__(8)));
  96
  97#define TARGET_VFP_MAGIC 0x56465001
  98#define TARGET_IWMMXT_MAGIC 0x12ef842a
  99
 100struct sigframe_v1
 101{
 102    struct target_sigcontext sc;
 103    abi_ulong extramask[TARGET_NSIG_WORDS-1];
 104    abi_ulong retcode[4];
 105};
 106
 107struct sigframe_v2
 108{
 109    struct target_ucontext_v2 uc;
 110    abi_ulong retcode[4];
 111};
 112
 113struct rt_sigframe_v1
 114{
 115    abi_ulong pinfo;
 116    abi_ulong puc;
 117    struct target_siginfo info;
 118    struct target_ucontext_v1 uc;
 119    abi_ulong retcode[4];
 120};
 121
 122struct rt_sigframe_v2
 123{
 124    struct target_siginfo info;
 125    struct target_ucontext_v2 uc;
 126    abi_ulong retcode[4];
 127};
 128
 129#define TARGET_CONFIG_CPU_32 1
 130
 131/*
 132 * For ARM syscalls, we encode the syscall number into the instruction.
 133 */
 134#define SWI_SYS_SIGRETURN       (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
 135#define SWI_SYS_RT_SIGRETURN    (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
 136
 137/*
 138 * For Thumb syscalls, we pass the syscall number via r7.  We therefore
 139 * need two 16-bit instructions.
 140 */
 141#define SWI_THUMB_SIGRETURN     (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
 142#define SWI_THUMB_RT_SIGRETURN  (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
 143
 144static const abi_ulong retcodes[4] = {
 145        SWI_SYS_SIGRETURN,      SWI_THUMB_SIGRETURN,
 146        SWI_SYS_RT_SIGRETURN,   SWI_THUMB_RT_SIGRETURN
 147};
 148
 149/*
 150 * Stub needed to make sure the FD register (r9) contains the right
 151 * value.
 152 */
 153static const unsigned long sigreturn_fdpic_codes[3] = {
 154    0xe59fc004, /* ldr r12, [pc, #4] to read function descriptor */
 155    0xe59c9004, /* ldr r9, [r12, #4] to setup GOT */
 156    0xe59cf000  /* ldr pc, [r12] to jump into restorer */
 157};
 158
 159static const unsigned long sigreturn_fdpic_thumb_codes[3] = {
 160    0xc008f8df, /* ldr r12, [pc, #8] to read function descriptor */
 161    0x9004f8dc, /* ldr r9, [r12, #4] to setup GOT */
 162    0xf000f8dc  /* ldr pc, [r12] to jump into restorer */
 163};
 164
 165static inline int valid_user_regs(CPUARMState *regs)
 166{
 167    return 1;
 168}
 169
 170static void
 171setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
 172                 CPUARMState *env, abi_ulong mask)
 173{
 174    __put_user(env->regs[0], &sc->arm_r0);
 175    __put_user(env->regs[1], &sc->arm_r1);
 176    __put_user(env->regs[2], &sc->arm_r2);
 177    __put_user(env->regs[3], &sc->arm_r3);
 178    __put_user(env->regs[4], &sc->arm_r4);
 179    __put_user(env->regs[5], &sc->arm_r5);
 180    __put_user(env->regs[6], &sc->arm_r6);
 181    __put_user(env->regs[7], &sc->arm_r7);
 182    __put_user(env->regs[8], &sc->arm_r8);
 183    __put_user(env->regs[9], &sc->arm_r9);
 184    __put_user(env->regs[10], &sc->arm_r10);
 185    __put_user(env->regs[11], &sc->arm_fp);
 186    __put_user(env->regs[12], &sc->arm_ip);
 187    __put_user(env->regs[13], &sc->arm_sp);
 188    __put_user(env->regs[14], &sc->arm_lr);
 189    __put_user(env->regs[15], &sc->arm_pc);
 190#ifdef TARGET_CONFIG_CPU_32
 191    __put_user(cpsr_read(env), &sc->arm_cpsr);
 192#endif
 193
 194    __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
 195    __put_user(/* current->thread.error_code */ 0, &sc->error_code);
 196    __put_user(/* current->thread.address */ 0, &sc->fault_address);
 197    __put_user(mask, &sc->oldmask);
 198}
 199
 200static inline abi_ulong
 201get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
 202{
 203    unsigned long sp;
 204
 205    sp = target_sigsp(get_sp_from_cpustate(regs), ka);
 206    /*
 207     * ATPCS B01 mandates 8-byte alignment
 208     */
 209    return (sp - framesize) & ~7;
 210}
 211
 212static int
 213setup_return(CPUARMState *env, struct target_sigaction *ka,
 214             abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
 215{
 216    abi_ulong handler = 0;
 217    abi_ulong handler_fdpic_GOT = 0;
 218    abi_ulong retcode;
 219
 220    int thumb;
 221    int is_fdpic = info_is_fdpic(((TaskState *)thread_cpu->opaque)->info);
 222
 223    if (is_fdpic) {
 224        /* In FDPIC mode, ka->_sa_handler points to a function
 225         * descriptor (FD). The first word contains the address of the
 226         * handler. The second word contains the value of the PIC
 227         * register (r9).  */
 228        abi_ulong funcdesc_ptr = ka->_sa_handler;
 229        if (get_user_ual(handler, funcdesc_ptr)
 230            || get_user_ual(handler_fdpic_GOT, funcdesc_ptr + 4)) {
 231            return 1;
 232        }
 233    } else {
 234        handler = ka->_sa_handler;
 235    }
 236
 237    thumb = handler & 1;
 238
 239    uint32_t cpsr = cpsr_read(env);
 240
 241    cpsr &= ~CPSR_IT;
 242    if (thumb) {
 243        cpsr |= CPSR_T;
 244    } else {
 245        cpsr &= ~CPSR_T;
 246    }
 247
 248    if (ka->sa_flags & TARGET_SA_RESTORER) {
 249        if (is_fdpic) {
 250            /* For FDPIC we ensure that the restorer is called with a
 251             * correct r9 value.  For that we need to write code on
 252             * the stack that sets r9 and jumps back to restorer
 253             * value.
 254             */
 255            if (thumb) {
 256                __put_user(sigreturn_fdpic_thumb_codes[0], rc);
 257                __put_user(sigreturn_fdpic_thumb_codes[1], rc + 1);
 258                __put_user(sigreturn_fdpic_thumb_codes[2], rc + 2);
 259                __put_user((abi_ulong)ka->sa_restorer, rc + 3);
 260            } else {
 261                __put_user(sigreturn_fdpic_codes[0], rc);
 262                __put_user(sigreturn_fdpic_codes[1], rc + 1);
 263                __put_user(sigreturn_fdpic_codes[2], rc + 2);
 264                __put_user((abi_ulong)ka->sa_restorer, rc + 3);
 265            }
 266
 267            retcode = rc_addr + thumb;
 268        } else {
 269            retcode = ka->sa_restorer;
 270        }
 271    } else {
 272        unsigned int idx = thumb;
 273
 274        if (ka->sa_flags & TARGET_SA_SIGINFO) {
 275            idx += 2;
 276        }
 277
 278        __put_user(retcodes[idx], rc);
 279
 280        retcode = rc_addr + thumb;
 281    }
 282
 283    env->regs[0] = usig;
 284    if (is_fdpic) {
 285        env->regs[9] = handler_fdpic_GOT;
 286    }
 287    env->regs[13] = frame_addr;
 288    env->regs[14] = retcode;
 289    env->regs[15] = handler & (thumb ? ~1 : ~3);
 290    cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
 291
 292    return 0;
 293}
 294
 295static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
 296{
 297    int i;
 298    struct target_vfp_sigframe *vfpframe;
 299    vfpframe = (struct target_vfp_sigframe *)regspace;
 300    __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
 301    __put_user(sizeof(*vfpframe), &vfpframe->size);
 302    for (i = 0; i < 32; i++) {
 303        __put_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
 304    }
 305    __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
 306    __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
 307    __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
 308    __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
 309    return (abi_ulong*)(vfpframe+1);
 310}
 311
 312static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
 313                                           CPUARMState *env)
 314{
 315    int i;
 316    struct target_iwmmxt_sigframe *iwmmxtframe;
 317    iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
 318    __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
 319    __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
 320    for (i = 0; i < 16; i++) {
 321        __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
 322    }
 323    __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
 324    __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
 325    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
 326    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
 327    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
 328    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
 329    return (abi_ulong*)(iwmmxtframe+1);
 330}
 331
 332static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
 333                              target_sigset_t *set, CPUARMState *env)
 334{
 335    struct target_sigaltstack stack;
 336    int i;
 337    abi_ulong *regspace;
 338
 339    /* Clear all the bits of the ucontext we don't use.  */
 340    memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
 341
 342    memset(&stack, 0, sizeof(stack));
 343    target_save_altstack(&stack, env);
 344    memcpy(&uc->tuc_stack, &stack, sizeof(stack));
 345
 346    setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
 347    /* Save coprocessor signal frame.  */
 348    regspace = uc->tuc_regspace;
 349    if (arm_feature(env, ARM_FEATURE_VFP)) {
 350        regspace = setup_sigframe_v2_vfp(regspace, env);
 351    }
 352    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
 353        regspace = setup_sigframe_v2_iwmmxt(regspace, env);
 354    }
 355
 356    /* Write terminating magic word */
 357    __put_user(0, regspace);
 358
 359    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
 360        __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
 361    }
 362}
 363
 364/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
 365static void setup_frame_v1(int usig, struct target_sigaction *ka,
 366                           target_sigset_t *set, CPUARMState *regs)
 367{
 368    struct sigframe_v1 *frame;
 369    abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
 370    int i;
 371
 372    trace_user_setup_frame(regs, frame_addr);
 373    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
 374        goto sigsegv;
 375    }
 376
 377    setup_sigcontext(&frame->sc, regs, set->sig[0]);
 378
 379    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
 380        __put_user(set->sig[i], &frame->extramask[i - 1]);
 381    }
 382
 383    if (setup_return(regs, ka, frame->retcode, frame_addr, usig,
 384                     frame_addr + offsetof(struct sigframe_v1, retcode))) {
 385        goto sigsegv;
 386    }
 387
 388    unlock_user_struct(frame, frame_addr, 1);
 389    return;
 390sigsegv:
 391    unlock_user_struct(frame, frame_addr, 1);
 392    force_sigsegv(usig);
 393}
 394
 395static void setup_frame_v2(int usig, struct target_sigaction *ka,
 396                           target_sigset_t *set, CPUARMState *regs)
 397{
 398    struct sigframe_v2 *frame;
 399    abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
 400
 401    trace_user_setup_frame(regs, frame_addr);
 402    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
 403        goto sigsegv;
 404    }
 405
 406    setup_sigframe_v2(&frame->uc, set, regs);
 407
 408    if (setup_return(regs, ka, frame->retcode, frame_addr, usig,
 409                     frame_addr + offsetof(struct sigframe_v2, retcode))) {
 410        goto sigsegv;
 411    }
 412
 413    unlock_user_struct(frame, frame_addr, 1);
 414    return;
 415sigsegv:
 416    unlock_user_struct(frame, frame_addr, 1);
 417    force_sigsegv(usig);
 418}
 419
 420void setup_frame(int usig, struct target_sigaction *ka,
 421                 target_sigset_t *set, CPUARMState *regs)
 422{
 423    if (get_osversion() >= 0x020612) {
 424        setup_frame_v2(usig, ka, set, regs);
 425    } else {
 426        setup_frame_v1(usig, ka, set, regs);
 427    }
 428}
 429
 430/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
 431static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
 432                              target_siginfo_t *info,
 433                              target_sigset_t *set, CPUARMState *env)
 434{
 435    struct rt_sigframe_v1 *frame;
 436    abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
 437    struct target_sigaltstack stack;
 438    int i;
 439    abi_ulong info_addr, uc_addr;
 440
 441    trace_user_setup_rt_frame(env, frame_addr);
 442    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
 443        goto sigsegv;
 444    }
 445
 446    info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
 447    __put_user(info_addr, &frame->pinfo);
 448    uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
 449    __put_user(uc_addr, &frame->puc);
 450    tswap_siginfo(&frame->info, info);
 451
 452    /* Clear all the bits of the ucontext we don't use.  */
 453    memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
 454
 455    memset(&stack, 0, sizeof(stack));
 456    target_save_altstack(&stack, env);
 457    memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
 458
 459    setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
 460    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
 461        __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
 462    }
 463
 464    if (setup_return(env, ka, frame->retcode, frame_addr, usig,
 465                     frame_addr + offsetof(struct rt_sigframe_v1, retcode))) {
 466        goto sigsegv;
 467    }
 468
 469    env->regs[1] = info_addr;
 470    env->regs[2] = uc_addr;
 471
 472    unlock_user_struct(frame, frame_addr, 1);
 473    return;
 474sigsegv:
 475    unlock_user_struct(frame, frame_addr, 1);
 476    force_sigsegv(usig);
 477}
 478
 479static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
 480                              target_siginfo_t *info,
 481                              target_sigset_t *set, CPUARMState *env)
 482{
 483    struct rt_sigframe_v2 *frame;
 484    abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
 485    abi_ulong info_addr, uc_addr;
 486
 487    trace_user_setup_rt_frame(env, frame_addr);
 488    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
 489        goto sigsegv;
 490    }
 491
 492    info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
 493    uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
 494    tswap_siginfo(&frame->info, info);
 495
 496    setup_sigframe_v2(&frame->uc, set, env);
 497
 498    if (setup_return(env, ka, frame->retcode, frame_addr, usig,
 499                     frame_addr + offsetof(struct rt_sigframe_v2, retcode))) {
 500        goto sigsegv;
 501    }
 502
 503    env->regs[1] = info_addr;
 504    env->regs[2] = uc_addr;
 505
 506    unlock_user_struct(frame, frame_addr, 1);
 507    return;
 508sigsegv:
 509    unlock_user_struct(frame, frame_addr, 1);
 510    force_sigsegv(usig);
 511}
 512
 513void setup_rt_frame(int usig, struct target_sigaction *ka,
 514                    target_siginfo_t *info,
 515                    target_sigset_t *set, CPUARMState *env)
 516{
 517    if (get_osversion() >= 0x020612) {
 518        setup_rt_frame_v2(usig, ka, info, set, env);
 519    } else {
 520        setup_rt_frame_v1(usig, ka, info, set, env);
 521    }
 522}
 523
 524static int
 525restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
 526{
 527    int err = 0;
 528    uint32_t cpsr;
 529
 530    __get_user(env->regs[0], &sc->arm_r0);
 531    __get_user(env->regs[1], &sc->arm_r1);
 532    __get_user(env->regs[2], &sc->arm_r2);
 533    __get_user(env->regs[3], &sc->arm_r3);
 534    __get_user(env->regs[4], &sc->arm_r4);
 535    __get_user(env->regs[5], &sc->arm_r5);
 536    __get_user(env->regs[6], &sc->arm_r6);
 537    __get_user(env->regs[7], &sc->arm_r7);
 538    __get_user(env->regs[8], &sc->arm_r8);
 539    __get_user(env->regs[9], &sc->arm_r9);
 540    __get_user(env->regs[10], &sc->arm_r10);
 541    __get_user(env->regs[11], &sc->arm_fp);
 542    __get_user(env->regs[12], &sc->arm_ip);
 543    __get_user(env->regs[13], &sc->arm_sp);
 544    __get_user(env->regs[14], &sc->arm_lr);
 545    __get_user(env->regs[15], &sc->arm_pc);
 546#ifdef TARGET_CONFIG_CPU_32
 547    __get_user(cpsr, &sc->arm_cpsr);
 548    cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
 549#endif
 550
 551    err |= !valid_user_regs(env);
 552
 553    return err;
 554}
 555
 556static long do_sigreturn_v1(CPUARMState *env)
 557{
 558    abi_ulong frame_addr;
 559    struct sigframe_v1 *frame = NULL;
 560    target_sigset_t set;
 561    sigset_t host_set;
 562    int i;
 563
 564    /*
 565     * Since we stacked the signal on a 64-bit boundary,
 566     * then 'sp' should be word aligned here.  If it's
 567     * not, then the user is trying to mess with us.
 568     */
 569    frame_addr = env->regs[13];
 570    trace_user_do_sigreturn(env, frame_addr);
 571    if (frame_addr & 7) {
 572        goto badframe;
 573    }
 574
 575    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
 576        goto badframe;
 577    }
 578
 579    __get_user(set.sig[0], &frame->sc.oldmask);
 580    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
 581        __get_user(set.sig[i], &frame->extramask[i - 1]);
 582    }
 583
 584    target_to_host_sigset_internal(&host_set, &set);
 585    set_sigmask(&host_set);
 586
 587    if (restore_sigcontext(env, &frame->sc)) {
 588        goto badframe;
 589    }
 590
 591#if 0
 592    /* Send SIGTRAP if we're single-stepping */
 593    if (ptrace_cancel_bpt(current))
 594        send_sig(SIGTRAP, current, 1);
 595#endif
 596    unlock_user_struct(frame, frame_addr, 0);
 597    return -TARGET_QEMU_ESIGRETURN;
 598
 599badframe:
 600    force_sig(TARGET_SIGSEGV);
 601    return -TARGET_QEMU_ESIGRETURN;
 602}
 603
 604static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
 605{
 606    int i;
 607    abi_ulong magic, sz;
 608    uint32_t fpscr, fpexc;
 609    struct target_vfp_sigframe *vfpframe;
 610    vfpframe = (struct target_vfp_sigframe *)regspace;
 611
 612    __get_user(magic, &vfpframe->magic);
 613    __get_user(sz, &vfpframe->size);
 614    if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
 615        return 0;
 616    }
 617    for (i = 0; i < 32; i++) {
 618        __get_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
 619    }
 620    __get_user(fpscr, &vfpframe->ufp.fpscr);
 621    vfp_set_fpscr(env, fpscr);
 622    __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
 623    /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
 624     * and the exception flag is cleared
 625     */
 626    fpexc |= (1 << 30);
 627    fpexc &= ~((1 << 31) | (1 << 28));
 628    env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
 629    __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
 630    __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
 631    return (abi_ulong*)(vfpframe + 1);
 632}
 633
 634static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
 635                                             abi_ulong *regspace)
 636{
 637    int i;
 638    abi_ulong magic, sz;
 639    struct target_iwmmxt_sigframe *iwmmxtframe;
 640    iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
 641
 642    __get_user(magic, &iwmmxtframe->magic);
 643    __get_user(sz, &iwmmxtframe->size);
 644    if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
 645        return 0;
 646    }
 647    for (i = 0; i < 16; i++) {
 648        __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
 649    }
 650    __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
 651    __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
 652    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
 653    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
 654    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
 655    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
 656    return (abi_ulong*)(iwmmxtframe + 1);
 657}
 658
 659static int do_sigframe_return_v2(CPUARMState *env,
 660                                 target_ulong context_addr,
 661                                 struct target_ucontext_v2 *uc)
 662{
 663    sigset_t host_set;
 664    abi_ulong *regspace;
 665
 666    target_to_host_sigset(&host_set, &uc->tuc_sigmask);
 667    set_sigmask(&host_set);
 668
 669    if (restore_sigcontext(env, &uc->tuc_mcontext))
 670        return 1;
 671
 672    /* Restore coprocessor signal frame */
 673    regspace = uc->tuc_regspace;
 674    if (arm_feature(env, ARM_FEATURE_VFP)) {
 675        regspace = restore_sigframe_v2_vfp(env, regspace);
 676        if (!regspace) {
 677            return 1;
 678        }
 679    }
 680    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
 681        regspace = restore_sigframe_v2_iwmmxt(env, regspace);
 682        if (!regspace) {
 683            return 1;
 684        }
 685    }
 686
 687    if (do_sigaltstack(context_addr
 688                       + offsetof(struct target_ucontext_v2, tuc_stack),
 689                       0, get_sp_from_cpustate(env)) == -EFAULT) {
 690        return 1;
 691    }
 692
 693#if 0
 694    /* Send SIGTRAP if we're single-stepping */
 695    if (ptrace_cancel_bpt(current))
 696        send_sig(SIGTRAP, current, 1);
 697#endif
 698
 699    return 0;
 700}
 701
 702static long do_sigreturn_v2(CPUARMState *env)
 703{
 704    abi_ulong frame_addr;
 705    struct sigframe_v2 *frame = NULL;
 706
 707    /*
 708     * Since we stacked the signal on a 64-bit boundary,
 709     * then 'sp' should be word aligned here.  If it's
 710     * not, then the user is trying to mess with us.
 711     */
 712    frame_addr = env->regs[13];
 713    trace_user_do_sigreturn(env, frame_addr);
 714    if (frame_addr & 7) {
 715        goto badframe;
 716    }
 717
 718    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
 719        goto badframe;
 720    }
 721
 722    if (do_sigframe_return_v2(env,
 723                              frame_addr
 724                              + offsetof(struct sigframe_v2, uc),
 725                              &frame->uc)) {
 726        goto badframe;
 727    }
 728
 729    unlock_user_struct(frame, frame_addr, 0);
 730    return -TARGET_QEMU_ESIGRETURN;
 731
 732badframe:
 733    unlock_user_struct(frame, frame_addr, 0);
 734    force_sig(TARGET_SIGSEGV);
 735    return -TARGET_QEMU_ESIGRETURN;
 736}
 737
 738long do_sigreturn(CPUARMState *env)
 739{
 740    if (get_osversion() >= 0x020612) {
 741        return do_sigreturn_v2(env);
 742    } else {
 743        return do_sigreturn_v1(env);
 744    }
 745}
 746
 747static long do_rt_sigreturn_v1(CPUARMState *env)
 748{
 749    abi_ulong frame_addr;
 750    struct rt_sigframe_v1 *frame = NULL;
 751    sigset_t host_set;
 752
 753    /*
 754     * Since we stacked the signal on a 64-bit boundary,
 755     * then 'sp' should be word aligned here.  If it's
 756     * not, then the user is trying to mess with us.
 757     */
 758    frame_addr = env->regs[13];
 759    trace_user_do_rt_sigreturn(env, frame_addr);
 760    if (frame_addr & 7) {
 761        goto badframe;
 762    }
 763
 764    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
 765        goto badframe;
 766    }
 767
 768    target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
 769    set_sigmask(&host_set);
 770
 771    if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
 772        goto badframe;
 773    }
 774
 775    if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
 776        goto badframe;
 777
 778#if 0
 779    /* Send SIGTRAP if we're single-stepping */
 780    if (ptrace_cancel_bpt(current))
 781        send_sig(SIGTRAP, current, 1);
 782#endif
 783    unlock_user_struct(frame, frame_addr, 0);
 784    return -TARGET_QEMU_ESIGRETURN;
 785
 786badframe:
 787    unlock_user_struct(frame, frame_addr, 0);
 788    force_sig(TARGET_SIGSEGV);
 789    return -TARGET_QEMU_ESIGRETURN;
 790}
 791
 792static long do_rt_sigreturn_v2(CPUARMState *env)
 793{
 794    abi_ulong frame_addr;
 795    struct rt_sigframe_v2 *frame = NULL;
 796
 797    /*
 798     * Since we stacked the signal on a 64-bit boundary,
 799     * then 'sp' should be word aligned here.  If it's
 800     * not, then the user is trying to mess with us.
 801     */
 802    frame_addr = env->regs[13];
 803    trace_user_do_rt_sigreturn(env, frame_addr);
 804    if (frame_addr & 7) {
 805        goto badframe;
 806    }
 807
 808    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
 809        goto badframe;
 810    }
 811
 812    if (do_sigframe_return_v2(env,
 813                              frame_addr
 814                              + offsetof(struct rt_sigframe_v2, uc),
 815                              &frame->uc)) {
 816        goto badframe;
 817    }
 818
 819    unlock_user_struct(frame, frame_addr, 0);
 820    return -TARGET_QEMU_ESIGRETURN;
 821
 822badframe:
 823    unlock_user_struct(frame, frame_addr, 0);
 824    force_sig(TARGET_SIGSEGV);
 825    return -TARGET_QEMU_ESIGRETURN;
 826}
 827
 828long do_rt_sigreturn(CPUARMState *env)
 829{
 830    if (get_osversion() >= 0x020612) {
 831        return do_rt_sigreturn_v2(env);
 832    } else {
 833        return do_rt_sigreturn_v1(env);
 834    }
 835}
 836