Commit bcd4933a23f1dbdb5b5546b81f3305ebcb13c9c0

Authored by Nathan Froyd
Committed by malc
1 parent c29b735c

linux-user: ppc signal handling

Implement setup_{,rt_}frame and do_{,rt_}sigreturn for PPC 32-bit.  Use
the same TARGET_QEMU_ESIGRETURN hack as for MIPS to avoid clobbering
register state on a sigreturn.

Signed-off-by: Nathan Froyd <froydnj@codesourcery.com>
Signed-off-by: malc <av1474@comtv.ru>
linux-user/main.c
... ... @@ -1461,6 +1461,11 @@ void cpu_loop(CPUPPCState *env)
1461 1461 ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
1462 1462 env->gpr[5], env->gpr[6], env->gpr[7],
1463 1463 env->gpr[8]);
  1464 + if (ret == (uint32_t)(-TARGET_QEMU_ESIGRETURN)) {
  1465 + /* Returning from a successful sigreturn syscall.
  1466 + Avoid corrupting register state. */
  1467 + break;
  1468 + }
1464 1469 if (ret > (uint32_t)(-515)) {
1465 1470 env->crf[0] |= 0x1;
1466 1471 ret = -ret;
... ...
linux-user/ppc/syscall.h
... ... @@ -51,6 +51,9 @@ struct target_revectored_struct {
51 51 abi_ulong __map[8]; /* 256 bits */
52 52 };
53 53  
  54 +/* Nasty hack: define a fake errno value for use by sigreturn. */
  55 +#define TARGET_QEMU_ESIGRETURN 255
  56 +
54 57 /*
55 58 * flags masks
56 59 */
... ...
linux-user/signal.c
... ... @@ -3182,6 +3182,602 @@ long do_rt_sigreturn(CPUState *env)
3182 3182 return -TARGET_ENOSYS;
3183 3183 }
3184 3184  
  3185 +#elif defined(TARGET_PPC) && !defined(TARGET_PPC64)
  3186 +
  3187 +/* FIXME: Many of the structures are defined for both PPC and PPC64, but
  3188 + the signal handling is different enough that we haven't implemented
  3189 + support for PPC64 yet. Hence the restriction above.
  3190 +
  3191 + There are various #if'd blocks for code for TARGET_PPC64. These
  3192 + blocks should go away so that we can successfully run 32-bit and
  3193 + 64-bit binaries on a QEMU configured for PPC64. */
  3194 +
  3195 +/* Size of dummy stack frame allocated when calling signal handler.
  3196 + See arch/powerpc/include/asm/ptrace.h. */
  3197 +#if defined(TARGET_PPC64)
  3198 +#define SIGNAL_FRAMESIZE 128
  3199 +#else
  3200 +#define SIGNAL_FRAMESIZE 64
  3201 +#endif
  3202 +
  3203 +/* See arch/powerpc/include/asm/sigcontext.h. */
  3204 +struct target_sigcontext {
  3205 + target_ulong _unused[4];
  3206 + int32_t signal;
  3207 +#if defined(TARGET_PPC64)
  3208 + int32_t pad0;
  3209 +#endif
  3210 + target_ulong handler;
  3211 + target_ulong oldmask;
  3212 + target_ulong regs; /* struct pt_regs __user * */
  3213 + /* TODO: PPC64 includes extra bits here. */
  3214 +};
  3215 +
  3216 +/* Indices for target_mcontext.mc_gregs, below.
  3217 + See arch/powerpc/include/asm/ptrace.h for details. */
  3218 +enum {
  3219 + TARGET_PT_R0 = 0,
  3220 + TARGET_PT_R1 = 1,
  3221 + TARGET_PT_R2 = 2,
  3222 + TARGET_PT_R3 = 3,
  3223 + TARGET_PT_R4 = 4,
  3224 + TARGET_PT_R5 = 5,
  3225 + TARGET_PT_R6 = 6,
  3226 + TARGET_PT_R7 = 7,
  3227 + TARGET_PT_R8 = 8,
  3228 + TARGET_PT_R9 = 9,
  3229 + TARGET_PT_R10 = 10,
  3230 + TARGET_PT_R11 = 11,
  3231 + TARGET_PT_R12 = 12,
  3232 + TARGET_PT_R13 = 13,
  3233 + TARGET_PT_R14 = 14,
  3234 + TARGET_PT_R15 = 15,
  3235 + TARGET_PT_R16 = 16,
  3236 + TARGET_PT_R17 = 17,
  3237 + TARGET_PT_R18 = 18,
  3238 + TARGET_PT_R19 = 19,
  3239 + TARGET_PT_R20 = 20,
  3240 + TARGET_PT_R21 = 21,
  3241 + TARGET_PT_R22 = 22,
  3242 + TARGET_PT_R23 = 23,
  3243 + TARGET_PT_R24 = 24,
  3244 + TARGET_PT_R25 = 25,
  3245 + TARGET_PT_R26 = 26,
  3246 + TARGET_PT_R27 = 27,
  3247 + TARGET_PT_R28 = 28,
  3248 + TARGET_PT_R29 = 29,
  3249 + TARGET_PT_R30 = 30,
  3250 + TARGET_PT_R31 = 31,
  3251 + TARGET_PT_NIP = 32,
  3252 + TARGET_PT_MSR = 33,
  3253 + TARGET_PT_ORIG_R3 = 34,
  3254 + TARGET_PT_CTR = 35,
  3255 + TARGET_PT_LNK = 36,
  3256 + TARGET_PT_XER = 37,
  3257 + TARGET_PT_CCR = 38,
  3258 + /* Yes, there are two registers with #39. One is 64-bit only. */
  3259 + TARGET_PT_MQ = 39,
  3260 + TARGET_PT_SOFTE = 39,
  3261 + TARGET_PT_TRAP = 40,
  3262 + TARGET_PT_DAR = 41,
  3263 + TARGET_PT_DSISR = 42,
  3264 + TARGET_PT_RESULT = 43,
  3265 + TARGET_PT_REGS_COUNT = 44
  3266 +};
  3267 +
  3268 +/* See arch/powerpc/include/asm/ucontext.h. Only used for 32-bit PPC;
  3269 + on 64-bit PPC, sigcontext and mcontext are one and the same. */
  3270 +struct target_mcontext {
  3271 + target_ulong mc_gregs[48];
  3272 + /* Includes fpscr. */
  3273 + uint64_t mc_fregs[33];
  3274 + target_ulong mc_pad[2];
  3275 + /* We need to handle Altivec and SPE at the same time, which no
  3276 + kernel needs to do. Fortunately, the kernel defines this bit to
  3277 + be Altivec-register-large all the time, rather than trying to
  3278 + twiddle it based on the specific platform. */
  3279 + union {
  3280 + /* SPE vector registers. One extra for SPEFSCR. */
  3281 + uint32_t spe[33];
  3282 + /* Altivec vector registers. The packing of VSCR and VRSAVE
  3283 + varies depending on whether we're PPC64 or not: PPC64 splits
  3284 + them apart; PPC32 stuffs them together. */
  3285 +#if defined(TARGET_PPC64)
  3286 +#define NVRREG 34
  3287 +#else
  3288 +#define NVRREG 33
  3289 +#endif
  3290 + ppc_avr_t altivec[NVRREG];
  3291 +#undef NVRREG
  3292 + } mc_vregs __attribute__((__aligned__(16)));
  3293 +};
  3294 +
  3295 +struct target_ucontext {
  3296 + target_ulong uc_flags;
  3297 + target_ulong uc_link; /* struct ucontext __user * */
  3298 + struct target_sigaltstack uc_stack;
  3299 +#if !defined(TARGET_PPC64)
  3300 + int32_t uc_pad[7];
  3301 + target_ulong uc_regs; /* struct mcontext __user *
  3302 + points to uc_mcontext field */
  3303 +#endif
  3304 + target_sigset_t uc_sigmask;
  3305 +#if defined(TARGET_PPC64)
  3306 + target_sigset_t unused[15]; /* Allow for uc_sigmask growth */
  3307 + struct target_sigcontext uc_mcontext;
  3308 +#else
  3309 + int32_t uc_maskext[30];
  3310 + int32_t uc_pad2[3];
  3311 + struct target_mcontext uc_mcontext;
  3312 +#endif
  3313 +};
  3314 +
  3315 +/* See arch/powerpc/kernel/signal_32.c. */
  3316 +struct target_sigframe {
  3317 + struct target_sigcontext sctx;
  3318 + struct target_mcontext mctx;
  3319 + int32_t abigap[56];
  3320 +};
  3321 +
  3322 +struct target_rt_sigframe {
  3323 + struct target_siginfo info;
  3324 + struct target_ucontext uc;
  3325 + int32_t abigap[56];
  3326 +};
  3327 +
  3328 +/* We use the mc_pad field for the signal return trampoline. */
  3329 +#define tramp mc_pad
  3330 +
  3331 +/* See arch/powerpc/kernel/signal.c. */
  3332 +static target_ulong get_sigframe(struct target_sigaction *ka,
  3333 + CPUState *env,
  3334 + int frame_size)
  3335 +{
  3336 + target_ulong oldsp, newsp;
  3337 +
  3338 + oldsp = env->gpr[1];
  3339 +
  3340 + if ((ka->sa_flags & TARGET_SA_ONSTACK) &&
  3341 + (sas_ss_flags(oldsp))) {
  3342 + oldsp = (target_sigaltstack_used.ss_sp
  3343 + + target_sigaltstack_used.ss_size);
  3344 + }
  3345 +
  3346 + newsp = (oldsp - frame_size) & ~0xFUL;
  3347 +
  3348 + return newsp;
  3349 +}
  3350 +
  3351 +static int save_user_regs(CPUState *env, struct target_mcontext *frame,
  3352 + int sigret)
  3353 +{
  3354 + target_ulong msr = env->msr;
  3355 + int i;
  3356 + target_ulong ccr = 0;
  3357 +
  3358 + /* In general, the kernel attempts to be intelligent about what it
  3359 + needs to save for Altivec/FP/SPE registers. We don't care that
  3360 + much, so we just go ahead and save everything. */
  3361 +
  3362 + /* Save general registers. */
  3363 + for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
  3364 + if (__put_user(env->gpr[i], &frame->mc_gregs[i])) {
  3365 + return 1;
  3366 + }
  3367 + }
  3368 + if (__put_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP])
  3369 + || __put_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR])
  3370 + || __put_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK])
  3371 + || __put_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]))
  3372 + return 1;
  3373 +
  3374 + for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
  3375 + ccr |= env->crf[i] << (32 - ((i + 1) * 4));
  3376 + }
  3377 + if (__put_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]))
  3378 + return 1;
  3379 +
  3380 + /* Save Altivec registers if necessary. */
  3381 + if (env->insns_flags & PPC_ALTIVEC) {
  3382 + for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
  3383 + ppc_avr_t *avr = &env->avr[i];
  3384 + ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
  3385 +
  3386 + if (__put_user(avr->u64[0], &vreg->u64[0]) ||
  3387 + __put_user(avr->u64[1], &vreg->u64[1])) {
  3388 + return 1;
  3389 + }
  3390 + }
  3391 + /* Set MSR_VR in the saved MSR value to indicate that
  3392 + frame->mc_vregs contains valid data. */
  3393 + msr |= MSR_VR;
  3394 + if (__put_user((uint32_t)env->spr[SPR_VRSAVE],
  3395 + &frame->mc_vregs.altivec[32].u32[3]))
  3396 + return 1;
  3397 + }
  3398 +
  3399 + /* Save floating point registers. */
  3400 + if (env->insns_flags & PPC_FLOAT) {
  3401 + for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
  3402 + if (__put_user(env->fpr[i], &frame->mc_fregs[i])) {
  3403 + return 1;
  3404 + }
  3405 + }
  3406 + if (__put_user((uint64_t) env->fpscr, &frame->mc_fregs[32]))
  3407 + return 1;
  3408 + }
  3409 +
  3410 + /* Save SPE registers. The kernel only saves the high half. */
  3411 + if (env->insns_flags & PPC_SPE) {
  3412 +#if defined(TARGET_PPC64)
  3413 + for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
  3414 + if (__put_user(env->gpr[i] >> 32, &frame->mc_vregs.spe[i])) {
  3415 + return 1;
  3416 + }
  3417 + }
  3418 +#else
  3419 + for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
  3420 + if (__put_user(env->gprh[i], &frame->mc_vregs.spe[i])) {
  3421 + return 1;
  3422 + }
  3423 + }
  3424 +#endif
  3425 + /* Set MSR_SPE in the saved MSR value to indicate that
  3426 + frame->mc_vregs contains valid data. */
  3427 + msr |= MSR_SPE;
  3428 + if (__put_user(env->spe_fscr, &frame->mc_vregs.spe[32]))
  3429 + return 1;
  3430 + }
  3431 +
  3432 + /* Store MSR. */
  3433 + if (__put_user(msr, &frame->mc_gregs[TARGET_PT_MSR]))
  3434 + return 1;
  3435 +
  3436 + /* Set up the sigreturn trampoline: li r0,sigret; sc. */
  3437 + if (sigret) {
  3438 + if (__put_user(0x38000000UL | sigret, &frame->tramp[0]) ||
  3439 + __put_user(0x44000002UL, &frame->tramp[1])) {
  3440 + return 1;
  3441 + }
  3442 + }
  3443 +
  3444 + return 0;
  3445 +}
  3446 +
  3447 +static int restore_user_regs(CPUState *env,
  3448 + struct target_mcontext *frame, int sig)
  3449 +{
  3450 + target_ulong save_r2 = 0;
  3451 + target_ulong msr;
  3452 + target_ulong ccr;
  3453 +
  3454 + int i;
  3455 +
  3456 + if (!sig) {
  3457 + save_r2 = env->gpr[2];
  3458 + }
  3459 +
  3460 + /* Restore general registers. */
  3461 + for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
  3462 + if (__get_user(env->gpr[i], &frame->mc_gregs[i])) {
  3463 + return 1;
  3464 + }
  3465 + }
  3466 + if (__get_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP])
  3467 + || __get_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR])
  3468 + || __get_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK])
  3469 + || __get_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]))
  3470 + return 1;
  3471 + if (__get_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]))
  3472 + return 1;
  3473 +
  3474 + for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
  3475 + env->crf[i] = (ccr >> (32 - ((i + 1) * 4))) & 0xf;
  3476 + }
  3477 +
  3478 + if (!sig) {
  3479 + env->gpr[2] = save_r2;
  3480 + }
  3481 + /* Restore MSR. */
  3482 + if (__get_user(msr, &frame->mc_gregs[TARGET_PT_MSR]))
  3483 + return 1;
  3484 +
  3485 + /* If doing signal return, restore the previous little-endian mode. */
  3486 + if (sig)
  3487 + env->msr = (env->msr & ~MSR_LE) | (msr & MSR_LE);
  3488 +
  3489 + /* Restore Altivec registers if necessary. */
  3490 + if (env->insns_flags & PPC_ALTIVEC) {
  3491 + for (i = 0; i < ARRAY_SIZE(env->avr); i++) {
  3492 + ppc_avr_t *avr = &env->avr[i];
  3493 + ppc_avr_t *vreg = &frame->mc_vregs.altivec[i];
  3494 +
  3495 + if (__get_user(avr->u64[0], &vreg->u64[0]) ||
  3496 + __get_user(avr->u64[1], &vreg->u64[1])) {
  3497 + return 1;
  3498 + }
  3499 + }
  3500 + /* Set MSR_VEC in the saved MSR value to indicate that
  3501 + frame->mc_vregs contains valid data. */
  3502 + if (__get_user(env->spr[SPR_VRSAVE],
  3503 + (target_ulong *)(&frame->mc_vregs.altivec[32].u32[3])))
  3504 + return 1;
  3505 + }
  3506 +
  3507 + /* Restore floating point registers. */
  3508 + if (env->insns_flags & PPC_FLOAT) {
  3509 + uint64_t fpscr;
  3510 + for (i = 0; i < ARRAY_SIZE(env->fpr); i++) {
  3511 + if (__get_user(env->fpr[i], &frame->mc_fregs[i])) {
  3512 + return 1;
  3513 + }
  3514 + }
  3515 + if (__get_user(fpscr, &frame->mc_fregs[32]))
  3516 + return 1;
  3517 + env->fpscr = (uint32_t) fpscr;
  3518 + }
  3519 +
  3520 + /* Save SPE registers. The kernel only saves the high half. */
  3521 + if (env->insns_flags & PPC_SPE) {
  3522 +#if defined(TARGET_PPC64)
  3523 + for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
  3524 + uint32_t hi;
  3525 +
  3526 + if (__get_user(hi, &frame->mc_vregs.spe[i])) {
  3527 + return 1;
  3528 + }
  3529 + env->gpr[i] = ((uint64_t)hi << 32) | ((uint32_t) env->gpr[i]);
  3530 + }
  3531 +#else
  3532 + for (i = 0; i < ARRAY_SIZE(env->gprh); i++) {
  3533 + if (__get_user(env->gprh[i], &frame->mc_vregs.spe[i])) {
  3534 + return 1;
  3535 + }
  3536 + }
  3537 +#endif
  3538 + if (__get_user(env->spe_fscr, &frame->mc_vregs.spe[32]))
  3539 + return 1;
  3540 + }
  3541 +
  3542 + return 0;
  3543 +}
  3544 +
  3545 +static void setup_frame(int sig, struct target_sigaction *ka,
  3546 + target_sigset_t *set, CPUState *env)
  3547 +{
  3548 + struct target_sigframe *frame;
  3549 + struct target_sigcontext *sc;
  3550 + target_ulong frame_addr, newsp;
  3551 + int err = 0;
  3552 + int signal;
  3553 +
  3554 + frame_addr = get_sigframe(ka, env, sizeof(*frame));
  3555 + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
  3556 + goto sigsegv;
  3557 + sc = &frame->sctx;
  3558 +
  3559 + signal = current_exec_domain_sig(sig);
  3560 +
  3561 + err |= __put_user(h2g(ka->_sa_handler), &sc->handler);
  3562 + err |= __put_user(set->sig[0], &sc->oldmask);
  3563 +#if defined(TARGET_PPC64)
  3564 + err |= __put_user(set->sig[0] >> 32, &sc->_unused[3]);
  3565 +#else
  3566 + err |= __put_user(set->sig[1], &sc->_unused[3]);
  3567 +#endif
  3568 + err |= __put_user(h2g(&frame->mctx), &sc->regs);
  3569 + err |= __put_user(sig, &sc->signal);
  3570 +
  3571 + /* Save user regs. */
  3572 + err |= save_user_regs(env, &frame->mctx, TARGET_NR_sigreturn);
  3573 +
  3574 + /* The kernel checks for the presence of a VDSO here. We don't
  3575 + emulate a vdso, so use a sigreturn system call. */
  3576 + env->lr = (target_ulong) h2g(frame->mctx.tramp);
  3577 +
  3578 + /* Turn off all fp exceptions. */
  3579 + env->fpscr = 0;
  3580 +
  3581 + /* Create a stack frame for the caller of the handler. */
  3582 + newsp = frame_addr - SIGNAL_FRAMESIZE;
  3583 + err |= __put_user(env->gpr[1], (target_ulong *)(uintptr_t) newsp);
  3584 +
  3585 + if (err)
  3586 + goto sigsegv;
  3587 +
  3588 + /* Set up registers for signal handler. */
  3589 + env->gpr[1] = newsp;
  3590 + env->gpr[3] = signal;
  3591 + env->gpr[4] = (target_ulong) h2g(sc);
  3592 + env->nip = (target_ulong) ka->_sa_handler;
  3593 + /* Signal handlers are entered in big-endian mode. */
  3594 + env->msr &= ~MSR_LE;
  3595 +
  3596 + unlock_user_struct(frame, frame_addr, 1);
  3597 + return;
  3598 +
  3599 +sigsegv:
  3600 + unlock_user_struct(frame, frame_addr, 1);
  3601 + if (logfile)
  3602 + fprintf (logfile, "segfaulting from setup_frame\n");
  3603 + force_sig(SIGSEGV);
  3604 +}
  3605 +
  3606 +static void setup_rt_frame(int sig, struct target_sigaction *ka,
  3607 + target_siginfo_t *info,
  3608 + target_sigset_t *set, CPUState *env)
  3609 +{
  3610 + struct target_rt_sigframe *rt_sf;
  3611 + struct target_mcontext *frame;
  3612 + target_ulong rt_sf_addr, newsp = 0;
  3613 + int i, err = 0;
  3614 + int signal;
  3615 +
  3616 + rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf));
  3617 + if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1))
  3618 + goto sigsegv;
  3619 +
  3620 + signal = current_exec_domain_sig(sig);
  3621 +
  3622 + err |= copy_siginfo_to_user(&rt_sf->info, info);
  3623 +
  3624 + err |= __put_user(0, &rt_sf->uc.uc_flags);
  3625 + err |= __put_user(0, &rt_sf->uc.uc_link);
  3626 + err |= __put_user((target_ulong)target_sigaltstack_used.ss_sp,
  3627 + &rt_sf->uc.uc_stack.ss_sp);
  3628 + err |= __put_user(sas_ss_flags(env->gpr[1]),
  3629 + &rt_sf->uc.uc_stack.ss_flags);
  3630 + err |= __put_user(target_sigaltstack_used.ss_size,
  3631 + &rt_sf->uc.uc_stack.ss_size);
  3632 + err |= __put_user(h2g (&rt_sf->uc.uc_mcontext),
  3633 + &rt_sf->uc.uc_regs);
  3634 + for(i = 0; i < TARGET_NSIG_WORDS; i++) {
  3635 + err |= __put_user(set->sig[i], &rt_sf->uc.uc_sigmask.sig[i]);
  3636 + }
  3637 +
  3638 + frame = &rt_sf->uc.uc_mcontext;
  3639 + err |= save_user_regs(env, frame, TARGET_NR_rt_sigreturn);
  3640 +
  3641 + /* The kernel checks for the presence of a VDSO here. We don't
  3642 + emulate a vdso, so use a sigreturn system call. */
  3643 + env->lr = (target_ulong) h2g(frame->tramp);
  3644 +
  3645 + /* Turn off all fp exceptions. */
  3646 + env->fpscr = 0;
  3647 +
  3648 + /* Create a stack frame for the caller of the handler. */
  3649 + newsp = rt_sf_addr - (SIGNAL_FRAMESIZE + 16);
  3650 + err |= __put_user(env->gpr[1], (target_ulong *)(uintptr_t) newsp);
  3651 +
  3652 + if (err)
  3653 + goto sigsegv;
  3654 +
  3655 + /* Set up registers for signal handler. */
  3656 + env->gpr[1] = newsp;
  3657 + env->gpr[3] = (target_ulong) signal;
  3658 + env->gpr[4] = (target_ulong) h2g(&rt_sf->info);
  3659 + env->gpr[5] = (target_ulong) h2g(&rt_sf->uc);
  3660 + env->gpr[6] = (target_ulong) h2g(rt_sf);
  3661 + env->nip = (target_ulong) ka->_sa_handler;
  3662 + /* Signal handlers are entered in big-endian mode. */
  3663 + env->msr &= ~MSR_LE;
  3664 +
  3665 + unlock_user_struct(rt_sf, rt_sf_addr, 1);
  3666 + return;
  3667 +
  3668 +sigsegv:
  3669 + unlock_user_struct(rt_sf, rt_sf_addr, 1);
  3670 + if (logfile)
  3671 + fprintf (logfile, "segfaulting from setup_rt_frame\n");
  3672 + force_sig(SIGSEGV);
  3673 +
  3674 +}
  3675 +
  3676 +long do_sigreturn(CPUState *env)
  3677 +{
  3678 + struct target_sigcontext *sc = NULL;
  3679 + struct target_mcontext *sr = NULL;
  3680 + target_ulong sr_addr, sc_addr;
  3681 + sigset_t blocked;
  3682 + target_sigset_t set;
  3683 +
  3684 + sc_addr = env->gpr[1] + SIGNAL_FRAMESIZE;
  3685 + if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1))
  3686 + goto sigsegv;
  3687 +
  3688 +#if defined(TARGET_PPC64)
  3689 + set.sig[0] = sc->oldmask + ((long)(sc->_unused[3]) << 32);
  3690 +#else
  3691 + if(__get_user(set.sig[0], &sc->oldmask) ||
  3692 + __get_user(set.sig[1], &sc->_unused[3]))
  3693 + goto sigsegv;
  3694 +#endif
  3695 + target_to_host_sigset_internal(&blocked, &set);
  3696 + sigprocmask(SIG_SETMASK, &blocked, NULL);
  3697 +
  3698 + if (__get_user(sr_addr, &sc->regs))
  3699 + goto sigsegv;
  3700 + if (!lock_user_struct(VERIFY_READ, sr, sr_addr, 1))
  3701 + goto sigsegv;
  3702 + if (restore_user_regs(env, sr, 1))
  3703 + goto sigsegv;
  3704 +
  3705 + unlock_user_struct(sr, sr_addr, 1);
  3706 + unlock_user_struct(sc, sc_addr, 1);
  3707 + return -TARGET_QEMU_ESIGRETURN;
  3708 +
  3709 +sigsegv:
  3710 + unlock_user_struct(sr, sr_addr, 1);
  3711 + unlock_user_struct(sc, sc_addr, 1);
  3712 + if (logfile)
  3713 + fprintf (logfile, "segfaulting from do_sigreturn\n");
  3714 + force_sig(SIGSEGV);
  3715 + return 0;
  3716 +}
  3717 +
  3718 +/* See arch/powerpc/kernel/signal_32.c. */
  3719 +static int do_setcontext(struct target_ucontext *ucp, CPUState *env, int sig)
  3720 +{
  3721 + struct target_mcontext *mcp;
  3722 + target_ulong mcp_addr;
  3723 + sigset_t blocked;
  3724 + target_sigset_t set;
  3725 +
  3726 + if (copy_from_user(&set, h2g(ucp) + offsetof(struct target_ucontext, uc_sigmask),
  3727 + sizeof (set)))
  3728 + return 1;
  3729 +
  3730 +#if defined(TARGET_PPC64)
  3731 + fprintf (stderr, "do_setcontext: not implemented\n");
  3732 + return 0;
  3733 +#else
  3734 + if (__get_user(mcp_addr, &ucp->uc_regs))
  3735 + return 1;
  3736 +
  3737 + if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1))
  3738 + return 1;
  3739 +
  3740 + target_to_host_sigset_internal(&blocked, &set);
  3741 + sigprocmask(SIG_SETMASK, &blocked, NULL);
  3742 + if (restore_user_regs(env, mcp, sig))
  3743 + goto sigsegv;
  3744 +
  3745 + unlock_user_struct(mcp, mcp_addr, 1);
  3746 + return 0;
  3747 +
  3748 +sigsegv:
  3749 + unlock_user_struct(mcp, mcp_addr, 1);
  3750 + return 1;
  3751 +#endif
  3752 +}
  3753 +
  3754 +long do_rt_sigreturn(CPUState *env)
  3755 +{
  3756 + struct target_rt_sigframe *rt_sf = NULL;
  3757 + target_ulong rt_sf_addr;
  3758 +
  3759 + rt_sf_addr = env->gpr[1] + SIGNAL_FRAMESIZE + 16;
  3760 + if (!lock_user_struct(VERIFY_READ, rt_sf, rt_sf_addr, 1))
  3761 + goto sigsegv;
  3762 +
  3763 + if (do_setcontext(&rt_sf->uc, env, 1))
  3764 + goto sigsegv;
  3765 +
  3766 + do_sigaltstack(rt_sf_addr
  3767 + + offsetof(struct target_rt_sigframe, uc.uc_stack),
  3768 + 0, env->gpr[1]);
  3769 +
  3770 + unlock_user_struct(rt_sf, rt_sf_addr, 1);
  3771 + return -TARGET_QEMU_ESIGRETURN;
  3772 +
  3773 +sigsegv:
  3774 + unlock_user_struct(rt_sf, rt_sf_addr, 1);
  3775 + if (logfile)
  3776 + fprintf (logfile, "segfaulting from do_rt_sigreturn\n");
  3777 + force_sig(SIGSEGV);
  3778 + return 0;
  3779 +}
  3780 +
3185 3781 #else
3186 3782  
3187 3783 static void setup_frame(int sig, struct target_sigaction *ka,
... ...