Revision a4c075f1 linux-user/signal.c

b/linux-user/signal.c
3614 3614
    return -TARGET_ENOSYS;
3615 3615
}
3616 3616

  
3617
#elif defined(TARGET_S390X)
3618

  
3619
#define __NUM_GPRS 16
3620
#define __NUM_FPRS 16
3621
#define __NUM_ACRS 16
3622

  
3623
#define S390_SYSCALL_SIZE   2
3624
#define __SIGNAL_FRAMESIZE      160 /* FIXME: 31-bit mode -> 96 */
3625

  
3626
#define _SIGCONTEXT_NSIG        64
3627
#define _SIGCONTEXT_NSIG_BPW    64 /* FIXME: 31-bit mode -> 32 */
3628
#define _SIGCONTEXT_NSIG_WORDS  (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
3629
#define _SIGMASK_COPY_SIZE    (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS)
3630
#define PSW_ADDR_AMODE            0x0000000000000000UL /* 0x80000000UL for 31-bit */
3631
#define S390_SYSCALL_OPCODE ((uint16_t)0x0a00)
3632

  
3633
typedef struct {
3634
    target_psw_t psw;
3635
    target_ulong gprs[__NUM_GPRS];
3636
    unsigned int acrs[__NUM_ACRS];
3637
} target_s390_regs_common;
3638

  
3639
typedef struct {
3640
    unsigned int fpc;
3641
    double   fprs[__NUM_FPRS];
3642
} target_s390_fp_regs;
3643

  
3644
typedef struct {
3645
    target_s390_regs_common regs;
3646
    target_s390_fp_regs     fpregs;
3647
} target_sigregs;
3648

  
3649
struct target_sigcontext {
3650
    target_ulong   oldmask[_SIGCONTEXT_NSIG_WORDS];
3651
    target_sigregs *sregs;
3652
};
3653

  
3654
typedef struct {
3655
    uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
3656
    struct target_sigcontext sc;
3657
    target_sigregs sregs;
3658
    int signo;
3659
    uint8_t retcode[S390_SYSCALL_SIZE];
3660
} sigframe;
3661

  
3662
struct target_ucontext {
3663
    target_ulong uc_flags;
3664
    struct target_ucontext *uc_link;
3665
    target_stack_t uc_stack;
3666
    target_sigregs uc_mcontext;
3667
    target_sigset_t uc_sigmask;   /* mask last for extensibility */
3668
};
3669

  
3670
typedef struct {
3671
    uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
3672
    uint8_t retcode[S390_SYSCALL_SIZE];
3673
    struct target_siginfo info;
3674
    struct target_ucontext uc;
3675
} rt_sigframe;
3676

  
3677
static inline abi_ulong
3678
get_sigframe(struct target_sigaction *ka, CPUState *env, size_t frame_size)
3679
{
3680
    abi_ulong sp;
3681

  
3682
    /* Default to using normal stack */
3683
    sp = env->regs[15];
3684

  
3685
    /* This is the X/Open sanctioned signal stack switching.  */
3686
    if (ka->sa_flags & TARGET_SA_ONSTACK) {
3687
        if (!sas_ss_flags(sp)) {
3688
            sp = target_sigaltstack_used.ss_sp +
3689
                 target_sigaltstack_used.ss_size;
3690
        }
3691
    }
3692

  
3693
    /* This is the legacy signal stack switching. */
3694
    else if (/* FIXME !user_mode(regs) */ 0 &&
3695
             !(ka->sa_flags & TARGET_SA_RESTORER) &&
3696
             ka->sa_restorer) {
3697
        sp = (abi_ulong) ka->sa_restorer;
3698
    }
3699

  
3700
    return (sp - frame_size) & -8ul;
3701
}
3702

  
3703
static void save_sigregs(CPUState *env, target_sigregs *sregs)
3704
{
3705
    int i;
3706
    //save_access_regs(current->thread.acrs); FIXME
3707

  
3708
    /* Copy a 'clean' PSW mask to the user to avoid leaking
3709
       information about whether PER is currently on.  */
3710
    __put_user(env->psw.mask, &sregs->regs.psw.mask);
3711
    __put_user(env->psw.addr, &sregs->regs.psw.addr);
3712
    for (i = 0; i < 16; i++) {
3713
        __put_user(env->regs[i], &sregs->regs.gprs[i]);
3714
    }
3715
    for (i = 0; i < 16; i++) {
3716
        __put_user(env->aregs[i], &sregs->regs.acrs[i]);
3717
    }
3718
    /*
3719
     * We have to store the fp registers to current->thread.fp_regs
3720
     * to merge them with the emulated registers.
3721
     */
3722
    //save_fp_regs(&current->thread.fp_regs); FIXME
3723
    for (i = 0; i < 16; i++) {
3724
        __put_user(env->fregs[i].ll, &sregs->fpregs.fprs[i]);
3725
    }
3726
}
3727

  
3728
static void setup_frame(int sig, struct target_sigaction *ka,
3729
			target_sigset_t *set, CPUState *env)
3730
{
3731
    sigframe *frame;
3732
    abi_ulong frame_addr;
3733

  
3734
    frame_addr = get_sigframe(ka, env, sizeof(*frame));
3735
    qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__,
3736
             (unsigned long long)frame_addr);
3737
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3738
            goto give_sigsegv;
3739
    }
3740

  
3741
    qemu_log("%s: 1\n", __FUNCTION__);
3742
    if (__put_user(set->sig[0], &frame->sc.oldmask[0])) {
3743
              goto give_sigsegv;
3744
    }
3745

  
3746
    save_sigregs(env, &frame->sregs);
3747

  
3748
    __put_user((abi_ulong)(unsigned long)&frame->sregs,
3749
               (abi_ulong *)&frame->sc.sregs);
3750

  
3751
    /* Set up to return from userspace.  If provided, use a stub
3752
       already in userspace.  */
3753
    if (ka->sa_flags & TARGET_SA_RESTORER) {
3754
            env->regs[14] = (unsigned long)
3755
                    ka->sa_restorer | PSW_ADDR_AMODE;
3756
    } else {
3757
            env->regs[14] = (unsigned long)
3758
                    frame->retcode | PSW_ADDR_AMODE;
3759
            if (__put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn,
3760
                           (uint16_t *)(frame->retcode)))
3761
                    goto give_sigsegv;
3762
    }
3763

  
3764
    /* Set up backchain. */
3765
    if (__put_user(env->regs[15], (abi_ulong *) frame)) {
3766
            goto give_sigsegv;
3767
    }
3768

  
3769
    /* Set up registers for signal handler */
3770
    env->regs[15] = (target_ulong)(unsigned long) frame;
3771
    env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
3772

  
3773
    env->regs[2] = sig; //map_signal(sig);
3774
    env->regs[3] = (target_ulong)(unsigned long) &frame->sc;
3775

  
3776
    /* We forgot to include these in the sigcontext.
3777
       To avoid breaking binary compatibility, they are passed as args. */
3778
    env->regs[4] = 0; // FIXME: no clue... current->thread.trap_no;
3779
    env->regs[5] = 0; // FIXME: no clue... current->thread.prot_addr;
3780

  
3781
    /* Place signal number on stack to allow backtrace from handler.  */
3782
    if (__put_user(env->regs[2], (int *) &frame->signo)) {
3783
            goto give_sigsegv;
3784
    }
3785
    unlock_user_struct(frame, frame_addr, 1);
3786
    return;
3787

  
3788
give_sigsegv:
3789
    qemu_log("%s: give_sigsegv\n", __FUNCTION__);
3790
    unlock_user_struct(frame, frame_addr, 1);
3791
    force_sig(TARGET_SIGSEGV);
3792
}
3793

  
3794
static void setup_rt_frame(int sig, struct target_sigaction *ka,
3795
                           target_siginfo_t *info,
3796
                           target_sigset_t *set, CPUState *env)
3797
{
3798
    int i;
3799
    rt_sigframe *frame;
3800
    abi_ulong frame_addr;
3801

  
3802
    frame_addr = get_sigframe(ka, env, sizeof *frame);
3803
    qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__,
3804
             (unsigned long long)frame_addr);
3805
    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
3806
        goto give_sigsegv;
3807
    }
3808

  
3809
    qemu_log("%s: 1\n", __FUNCTION__);
3810
    if (copy_siginfo_to_user(&frame->info, info)) {
3811
        goto give_sigsegv;
3812
    }
3813

  
3814
    /* Create the ucontext.  */
3815
    __put_user(0, &frame->uc.uc_flags);
3816
    __put_user((abi_ulong)0, (abi_ulong *)&frame->uc.uc_link);
3817
    __put_user(target_sigaltstack_used.ss_sp, &frame->uc.uc_stack.ss_sp);
3818
    __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
3819
                      &frame->uc.uc_stack.ss_flags);
3820
    __put_user(target_sigaltstack_used.ss_size, &frame->uc.uc_stack.ss_size);
3821
    save_sigregs(env, &frame->uc.uc_mcontext);
3822
    for (i = 0; i < TARGET_NSIG_WORDS; i++) {
3823
        __put_user((abi_ulong)set->sig[i],
3824
        (abi_ulong *)&frame->uc.uc_sigmask.sig[i]);
3825
    }
3826

  
3827
    /* Set up to return from userspace.  If provided, use a stub
3828
       already in userspace.  */
3829
    if (ka->sa_flags & TARGET_SA_RESTORER) {
3830
        env->regs[14] = (unsigned long) ka->sa_restorer | PSW_ADDR_AMODE;
3831
    } else {
3832
        env->regs[14] = (unsigned long) frame->retcode | PSW_ADDR_AMODE;
3833
        if (__put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn,
3834
                       (uint16_t *)(frame->retcode))) {
3835
            goto give_sigsegv;
3836
        }
3837
    }
3838

  
3839
    /* Set up backchain. */
3840
    if (__put_user(env->regs[15], (abi_ulong *) frame)) {
3841
        goto give_sigsegv;
3842
    }
3843

  
3844
    /* Set up registers for signal handler */
3845
    env->regs[15] = (target_ulong)(unsigned long) frame;
3846
    env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE;
3847

  
3848
    env->regs[2] = sig; //map_signal(sig);
3849
    env->regs[3] = (target_ulong)(unsigned long) &frame->info;
3850
    env->regs[4] = (target_ulong)(unsigned long) &frame->uc;
3851
    return;
3852

  
3853
give_sigsegv:
3854
    qemu_log("%s: give_sigsegv\n", __FUNCTION__);
3855
    unlock_user_struct(frame, frame_addr, 1);
3856
    force_sig(TARGET_SIGSEGV);
3857
}
3858

  
3859
static int
3860
restore_sigregs(CPUState *env, target_sigregs *sc)
3861
{
3862
    int err = 0;
3863
    int i;
3864

  
3865
    for (i = 0; i < 16; i++) {
3866
        err |= __get_user(env->regs[i], &sc->regs.gprs[i]);
3867
    }
3868

  
3869
    err |= __get_user(env->psw.mask, &sc->regs.psw.mask);
3870
    qemu_log("%s: sc->regs.psw.addr 0x%llx env->psw.addr 0x%llx\n",
3871
             __FUNCTION__, (unsigned long long)sc->regs.psw.addr,
3872
             (unsigned long long)env->psw.addr);
3873
    err |= __get_user(env->psw.addr, &sc->regs.psw.addr);
3874
    /* FIXME: 31-bit -> | PSW_ADDR_AMODE */
3875

  
3876
    for (i = 0; i < 16; i++) {
3877
        err |= __get_user(env->aregs[i], &sc->regs.acrs[i]);
3878
    }
3879
    for (i = 0; i < 16; i++) {
3880
        err |= __get_user(env->fregs[i].ll, &sc->fpregs.fprs[i]);
3881
    }
3882

  
3883
    return err;
3884
}
3885

  
3886
long do_sigreturn(CPUState *env)
3887
{
3888
    sigframe *frame;
3889
    abi_ulong frame_addr = env->regs[15];
3890
    qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__,
3891
             (unsigned long long)frame_addr);
3892
    target_sigset_t target_set;
3893
    sigset_t set;
3894

  
3895
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3896
        goto badframe;
3897
    }
3898
    if (__get_user(target_set.sig[0], &frame->sc.oldmask[0])) {
3899
        goto badframe;
3900
    }
3901

  
3902
    target_to_host_sigset_internal(&set, &target_set);
3903
    sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */
3904

  
3905
    if (restore_sigregs(env, &frame->sregs)) {
3906
        goto badframe;
3907
    }
3908

  
3909
    unlock_user_struct(frame, frame_addr, 0);
3910
    return env->regs[2];
3911

  
3912
badframe:
3913
    unlock_user_struct(frame, frame_addr, 0);
3914
    force_sig(TARGET_SIGSEGV);
3915
    return 0;
3916
}
3917

  
3918
long do_rt_sigreturn(CPUState *env)
3919
{
3920
    rt_sigframe *frame;
3921
    abi_ulong frame_addr = env->regs[15];
3922
    qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__,
3923
             (unsigned long long)frame_addr);
3924
    sigset_t set;
3925

  
3926
    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
3927
        goto badframe;
3928
    }
3929
    target_to_host_sigset(&set, &frame->uc.uc_sigmask);
3930

  
3931
    sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */
3932

  
3933
    if (restore_sigregs(env, &frame->uc.uc_mcontext)) {
3934
        goto badframe;
3935
    }
3936

  
3937
    if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.uc_stack), 0,
3938
                       get_sp_from_cpustate(env)) == -EFAULT) {
3939
        goto badframe;
3940
    }
3941
    unlock_user_struct(frame, frame_addr, 0);
3942
    return env->regs[2];
3943

  
3944
badframe:
3945
    unlock_user_struct(frame, frame_addr, 0);
3946
    force_sig(TARGET_SIGSEGV);
3947
    return 0;
3948
}
3949

  
3617 3950
#elif defined(TARGET_PPC) && !defined(TARGET_PPC64)
3618 3951

  
3619 3952
/* FIXME: Many of the structures are defined for both PPC and PPC64, but

Also available in: Unified diff