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