All of lore.kernel.org
 help / color / mirror / Atom feed
From: Richard Henderson <rth@twiddle.net>
To: qemu-devel@nongnu.org
Cc: aurelien@aurel32.net
Subject: Re: [Qemu-devel] [PATCH] alpha-linux-user: Implement signals.
Date: Tue, 09 Feb 2010 10:46:32 -0800	[thread overview]
Message-ID: <4B71AD88.5090607@twiddle.net> (raw)
In-Reply-To: <666f99639d39331da942b9c52cd23b6b661bdcf1.1262647064.git.rth@twiddle.net>

Ping?

r~

On 01/04/2010 03:17 PM, Richard Henderson wrote:
> Move userland PALcode handling into linux-user main loop so that
> we can send signals from there.  This also makes alpha_palcode.c
> system-level only, so don't build it for userland.  Add defines
> for GENTRAP PALcall mapping to signals.
>
> Signed-off-by: Richard Henderson<rth@twiddle.net>
> ---
>   Makefile.target                  |    3 +-
>   hw/alpha_palcode.c               |   81 +-----------
>   linux-user/alpha/target_signal.h |   27 ++++
>   linux-user/main.c                |  137 ++++++++++++++++----
>   linux-user/signal.c              |  267 ++++++++++++++++++++++++++++++++++++++
>   linux-user/syscall.c             |   61 ++++++++-
>   linux-user/syscall_defs.h        |   23 +++-
>   target-alpha/cpu.h               |    4 +-
>   target-alpha/translate.c         |    3 +-
>   9 files changed, 489 insertions(+), 117 deletions(-)
>
> diff --git a/Makefile.target b/Makefile.target
> index 7c1f30c..0ecfe76 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -47,7 +47,6 @@ libobj-$(CONFIG_NOSOFTFLOAT) += fpu/softfloat-native.o
>   libobj-y += op_helper.o helper.o
>   libobj-$(CONFIG_NEED_MMU) += mmu.o
>   libobj-$(TARGET_ARM) += neon_helper.o iwmmxt_helper.o
> -libobj-$(TARGET_ALPHA) += alpha_palcode.o
>
>   # NOTE: the disassembler code is only needed for debugging
>   libobj-y += disas.o
> @@ -295,6 +294,8 @@ obj-m68k-y += m68k-semi.o dummy_m68k.o
>
>   obj-s390x-y = s390-virtio-bus.o s390-virtio.o
>
> +obj-alpha-y = alpha_palcode.o
> +
>   main.o vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
>
>   vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS)
> diff --git a/hw/alpha_palcode.c b/hw/alpha_palcode.c
> index 843bd14..c1220ad 100644
> --- a/hw/alpha_palcode.c
> +++ b/hw/alpha_palcode.c
> @@ -21,11 +21,9 @@
>   #include<stdlib.h>
>   #include<stdio.h>
>
> -#include "qemu.h"
>   #include "cpu.h"
>   #include "exec-all.h"
>
> -#if !defined (CONFIG_USER_ONLY)
>   /* Shared handlers */
>   static void pal_reset (CPUState *env);
>   /* Console handlers */
> @@ -997,12 +995,9 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
>       uint64_t physical, page_size, end;
>       int prot, zbits, ret;
>
> -#if defined(CONFIG_USER_ONLY)
> -        ret = 2;
> -#else
> -        ret = virtual_to_physical(env,&physical,&zbits,&prot,
> -                                  address, mmu_idx, rw);
> -#endif
> +    ret = virtual_to_physical(env,&physical,&zbits,&prot,
> +                              address, mmu_idx, rw);
> +
>       switch (ret) {
>       case 0:
>           /* No fault */
> @@ -1050,73 +1045,3 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
>       return ret;
>   }
>   #endif
> -
> -#else /* !defined (CONFIG_USER_ONLY) */
> -void pal_init (CPUState *env)
> -{
> -}
> -
> -void call_pal (CPUState *env, int palcode)
> -{
> -    target_long ret;
> -
> -    switch (palcode) {
> -    case 0x80:
> -        /* BPT */
> -        qemu_log("BPT\n");
> -        /* FIXME: Sends SIGTRAP, si_code=TRAP_BRKPT.  */
> -        exit(1);
> -    case 0x81:
> -        /* BUGCHK */
> -        qemu_log("BUGCHK\n");
> -        /* FIXME: Sends SIGTRAP, si_code=SI_FAULT.  */
> -        exit(1);
> -    case 0x83:
> -        /* CALLSYS */
> -        qemu_log("CALLSYS n " TARGET_FMT_ld "\n", env->ir[0]);
> -        ret = do_syscall(env, env->ir[IR_V0], env->ir[IR_A0], env->ir[IR_A1],
> -                         env->ir[IR_A2], env->ir[IR_A3], env->ir[IR_A4],
> -                         env->ir[IR_A5]);
> -        if (ret>= 0) {
> -            env->ir[IR_A3] = 0;
> -            env->ir[IR_V0] = ret;
> -        } else {
> -            env->ir[IR_A3] = 1;
> -            env->ir[IR_V0] = -ret;
> -        }
> -        break;
> -    case 0x86:
> -        /* IMB */
> -        qemu_log("IMB\n");
> -        /* ??? We can probably elide the code using page_unprotect that is
> -           checking for self-modifying code.  Instead we could simply call
> -           tb_flush here.  Until we work out the changes required to turn
> -           off the extra write protection, this can be a no-op.  */
> -        break;
> -    case 0x9E:
> -        /* RDUNIQUE */
> -        qemu_log("RDUNIQUE: " TARGET_FMT_lx "\n", env->unique);
> -        /* Handled in the translator for usermode.  */
> -        abort();
> -    case 0x9F:
> -        /* WRUNIQUE */
> -        qemu_log("WRUNIQUE: " TARGET_FMT_lx "\n", env->ir[IR_A0]);
> -        /* Handled in the translator for usermode.  */
> -        abort();
> -    case 0xAA:
> -        /* GENTRAP */
> -        qemu_log("GENTRAP: " TARGET_FMT_lx "\n", env->ir[IR_A0]);
> -        /* FIXME: This is supposed to send a signal:
> -           SIGFPE:
> -             GEN_INTOVF, GEN_INTDIV, GEN_FLTOVF, GEN_FLTDIV,
> -             GEN_FLTUND, GEN_FLTINV, GEN_FLTINE, GEN_ROPRAND
> -           SIGTRAP:
> -             others
> -           with various settings of si_code.  */
> -        exit(1);
> -    default:
> -        qemu_log("%s: unhandled palcode %02x\n", __func__, palcode);
> -        exit(1);
> -    }
> -}
> -#endif
> diff --git a/linux-user/alpha/target_signal.h b/linux-user/alpha/target_signal.h
> index 2382ffd..cb86402 100644
> --- a/linux-user/alpha/target_signal.h
> +++ b/linux-user/alpha/target_signal.h
> @@ -26,4 +26,31 @@ static inline abi_ulong get_sp_from_cpustate(CPUAlphaState *state)
>       return state->ir[IR_SP];
>   }
>
> +/* From<asm/gentrap.h>.  */
> +#define TARGET_GEN_INTOVF      -1      /* integer overflow */
> +#define TARGET_GEN_INTDIV      -2      /* integer division by zero */
> +#define TARGET_GEN_FLTOVF      -3      /* fp overflow */
> +#define TARGET_GEN_FLTDIV      -4      /* fp division by zero */
> +#define TARGET_GEN_FLTUND      -5      /* fp underflow */
> +#define TARGET_GEN_FLTINV      -6      /* invalid fp operand */
> +#define TARGET_GEN_FLTINE      -7      /* inexact fp operand */
> +#define TARGET_GEN_DECOVF      -8      /* decimal overflow (for COBOL??) */
> +#define TARGET_GEN_DECDIV      -9      /* decimal division by zero */
> +#define TARGET_GEN_DECINV      -10     /* invalid decimal operand */
> +#define TARGET_GEN_ROPRAND     -11     /* reserved operand */
> +#define TARGET_GEN_ASSERTERR   -12     /* assertion error */
> +#define TARGET_GEN_NULPTRERR   -13     /* null pointer error */
> +#define TARGET_GEN_STKOVF      -14     /* stack overflow */
> +#define TARGET_GEN_STRLENERR   -15     /* string length error */
> +#define TARGET_GEN_SUBSTRERR   -16     /* substring error */
> +#define TARGET_GEN_RANGERR     -17     /* range error */
> +#define TARGET_GEN_SUBRNG      -18
> +#define TARGET_GEN_SUBRNG1     -19
> +#define TARGET_GEN_SUBRNG2     -20
> +#define TARGET_GEN_SUBRNG3     -21
> +#define TARGET_GEN_SUBRNG4     -22
> +#define TARGET_GEN_SUBRNG5     -23
> +#define TARGET_GEN_SUBRNG6     -24
> +#define TARGET_GEN_SUBRNG7     -25
> +
>   #endif /* TARGET_SIGNAL_H */
> diff --git a/linux-user/main.c b/linux-user/main.c
> index 91e5009..bddfb45 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -2351,6 +2351,7 @@ void cpu_loop (CPUState *env)
>   {
>       int trapnr;
>       target_siginfo_t info;
> +    abi_long sysret;
>
>       while (1) {
>           trapnr = cpu_alpha_exec (env);
> @@ -2365,16 +2366,22 @@ void cpu_loop (CPUState *env)
>               exit(1);
>               break;
>           case EXCP_ARITH:
> -            fprintf(stderr, "Arithmetic trap.\n");
> -            exit(1);
> +            info.si_signo = TARGET_SIGFPE;
> +            info.si_errno = 0;
> +            info.si_code = TARGET_FPE_FLTINV;
> +            info._sifields._sigfault._addr = env->pc;
> +            queue_signal(env, info.si_signo,&info);
>               break;
>           case EXCP_HW_INTERRUPT:
>               fprintf(stderr, "External interrupt. Exit\n");
>               exit(1);
>               break;
>           case EXCP_DFAULT:
> -            fprintf(stderr, "MMU data fault\n");
> -            exit(1);
> +            info.si_signo = TARGET_SIGSEGV;
> +            info.si_errno = 0;
> +            info.si_code = 0;  /* ??? SEGV_MAPERR vs SEGV_ACCERR.  */
> +            info._sifields._sigfault._addr = env->pc;
> +            queue_signal(env, info.si_signo,&info);
>               break;
>           case EXCP_DTB_MISS_PAL:
>               fprintf(stderr, "MMU data TLB miss in PALcode\n");
> @@ -2393,36 +2400,116 @@ void cpu_loop (CPUState *env)
>               exit(1);
>               break;
>           case EXCP_UNALIGN:
> -            fprintf(stderr, "Unaligned access\n");
> -            exit(1);
> +            info.si_signo = TARGET_SIGBUS;
> +            info.si_errno = 0;
> +            info.si_code = TARGET_BUS_ADRALN;
> +            info._sifields._sigfault._addr = env->pc;
> +            queue_signal(env, info.si_signo,&info);
>               break;
>           case EXCP_OPCDEC:
> -            fprintf(stderr, "Invalid instruction\n");
> -            exit(1);
> +        do_sigill:
> +            info.si_signo = TARGET_SIGILL;
> +            info.si_errno = 0;
> +            info.si_code = TARGET_ILL_ILLOPC;
> +            info._sifields._sigfault._addr = env->pc;
> +            queue_signal(env, info.si_signo,&info);
>               break;
>           case EXCP_FEN:
> -            fprintf(stderr, "Floating-point not allowed\n");
> -            exit(1);
> +            /* No-op.  Linux simply re-enables the FPU.  */
>               break;
>           case EXCP_CALL_PAL ... (EXCP_CALL_PALP - 1):
> -            call_pal(env, (trapnr>>  6) | 0x80);
> +            switch ((trapnr>>  6) | 0x80) {
> +            case 0x80:
> +                /* BPT */
> +                info.si_signo = TARGET_SIGTRAP;
> +                info.si_errno = 0;
> +                info.si_code = TARGET_TRAP_BRKPT;
> +                info._sifields._sigfault._addr = env->pc;
> +                queue_signal(env, info.si_signo,&info);
> +                break;
> +            case 0x81:
> +                /* BUGCHK */
> +                info.si_signo = TARGET_SIGTRAP;
> +                info.si_errno = 0;
> +                info.si_code = 0;
> +                info._sifields._sigfault._addr = env->pc;
> +                queue_signal(env, info.si_signo,&info);
> +                break;
> +            case 0x83:
> +                /* CALLSYS */
> +                trapnr = env->ir[IR_V0];
> +                sysret = do_syscall(env, trapnr,
> +                                    env->ir[IR_A0], env->ir[IR_A1],
> +                                    env->ir[IR_A2], env->ir[IR_A3],
> +                                    env->ir[IR_A4], env->ir[IR_A5]);
> +		if (trapnr != TARGET_NR_sigreturn
> +&&  trapnr != TARGET_NR_rt_sigreturn) {
> +                    env->ir[IR_V0] = (sysret<  0 ? -sysret : sysret);
> +                    env->ir[IR_A3] = (sysret<  0);
> +                }
> +                break;
> +            case 0x86:
> +                /* IMB */
> +                /* ??? We can probably elide the code using page_unprotect
> +                   that is checking for self-modifying code.  Instead we
> +                   could simply call tb_flush here.  Until we work out the
> +                   changes required to turn off the extra write protection,
> +                   this can be a no-op.  */
> +                break;
> +            case 0x9E:
> +                /* RDUNIQUE */
> +                /* Handled in the translator for usermode.  */
> +                abort();
> +            case 0x9F:
> +                /* WRUNIQUE */
> +                /* Handled in the translator for usermode.  */
> +                abort();
> +            case 0xAA:
> +                /* GENTRAP */
> +                info.si_signo = TARGET_SIGFPE;
> +                switch (env->ir[IR_A0]) {
> +                case TARGET_GEN_INTOVF:
> +                    info.si_code = TARGET_FPE_INTOVF;
> +                    break;
> +                case TARGET_GEN_INTDIV:
> +                    info.si_code = TARGET_FPE_INTDIV;
> +                    break;
> +                case TARGET_GEN_FLTOVF:
> +                    info.si_code = TARGET_FPE_FLTOVF;
> +                    break;
> +                case TARGET_GEN_FLTUND:
> +                    info.si_code = TARGET_FPE_FLTUND;
> +                    break;
> +                case TARGET_GEN_FLTINV:
> +                    info.si_code = TARGET_FPE_FLTINV;
> +                    break;
> +                case TARGET_GEN_FLTINE:
> +                    info.si_code = TARGET_FPE_FLTRES;
> +                    break;
> +                case TARGET_GEN_ROPRAND:
> +                    info.si_code = 0;
> +                    break;
> +                default:
> +                    info.si_signo = TARGET_SIGTRAP;
> +                    info.si_code = 0;
> +                    break;
> +                }
> +                info.si_errno = 0;
> +                info._sifields._sigfault._addr = env->pc;
> +                queue_signal(env, info.si_signo,&info);
> +                break;
> +            default:
> +                goto do_sigill;
> +            }
>               break;
>           case EXCP_CALL_PALP ... (EXCP_CALL_PALE - 1):
> -            fprintf(stderr, "Privileged call to PALcode\n");
> -            exit(1);
> -            break;
> +            goto do_sigill;
>           case EXCP_DEBUG:
> -            {
> -                int sig;
> -
> -                sig = gdb_handlesig (env, TARGET_SIGTRAP);
> -                if (sig)
> -                  {
> -                    info.si_signo = sig;
> -                    info.si_errno = 0;
> -                    info.si_code = TARGET_TRAP_BRKPT;
> -                    queue_signal(env, info.si_signo,&info);
> -                  }
> +            info.si_signo = gdb_handlesig (env, TARGET_SIGTRAP);
> +            if (info.si_signo) {
> +                info.si_errno = 0;
> +                info.si_code = TARGET_TRAP_BRKPT;
> +                queue_signal(env, info.si_signo,&info);
>               }
>               break;
>           default:
> diff --git a/linux-user/signal.c b/linux-user/signal.c
> index b0faf2e..e9abb1a 100644
> --- a/linux-user/signal.c
> +++ b/linux-user/signal.c
> @@ -4410,6 +4410,273 @@ badframe:
>       return 0;
>   }
>
> +#elif defined(TARGET_ALPHA)
> +
> +struct target_sigcontext {
> +    abi_long sc_onstack;
> +    abi_long sc_mask;
> +    abi_long sc_pc;
> +    abi_long sc_ps;
> +    abi_long sc_regs[32];
> +    abi_long sc_ownedfp;
> +    abi_long sc_fpregs[32];
> +    abi_ulong sc_fpcr;
> +    abi_ulong sc_fp_control;
> +    abi_ulong sc_reserved1;
> +    abi_ulong sc_reserved2;
> +    abi_ulong sc_ssize;
> +    abi_ulong sc_sbase;
> +    abi_ulong sc_traparg_a0;
> +    abi_ulong sc_traparg_a1;
> +    abi_ulong sc_traparg_a2;
> +    abi_ulong sc_fp_trap_pc;
> +    abi_ulong sc_fp_trigger_sum;
> +    abi_ulong sc_fp_trigger_inst;
> +};
> +
> +struct target_ucontext {
> +    abi_ulong uc_flags;
> +    abi_ulong uc_link;
> +    abi_ulong uc_osf_sigmask;
> +    target_stack_t uc_stack;
> +    struct target_sigcontext uc_mcontext;
> +    target_sigset_t uc_sigmask;
> +};
> +
> +struct target_sigframe {
> +    struct target_sigcontext sc;
> +    unsigned int retcode[3];
> +};
> +
> +struct target_rt_sigframe {
> +    target_siginfo_t info;
> +    struct target_ucontext uc;
> +    unsigned int retcode[3];
> +};
> +
> +#define INSN_MOV_R30_R16        0x47fe0410
> +#define INSN_LDI_R0             0x201f0000
> +#define INSN_CALLSYS            0x00000083
> +
> +static int setup_sigcontext(struct target_sigcontext *sc, CPUState *env,
> +                            abi_ulong frame_addr, target_sigset_t *set)
> +{
> +    int i, err = 0;
> +
> +    err |= __put_user(on_sig_stack(frame_addr),&sc->sc_onstack);
> +    err |= __put_user(set->sig[0],&sc->sc_mask);
> +    err |= __put_user(env->pc,&sc->sc_pc);
> +    err |= __put_user(8,&sc->sc_ps);
> +
> +    for (i = 0; i<  31; ++i) {
> +        err |= __put_user(env->ir[i],&sc->sc_regs[i]);
> +    }
> +    err |= __put_user(0,&sc->sc_regs[31]);
> +
> +    for (i = 0; i<  31; ++i) {
> +        err |= __put_user(env->fir[i],&sc->sc_fpregs[i]);
> +    }
> +    err |= __put_user(0,&sc->sc_fpregs[31]);
> +    err |= __put_user(cpu_alpha_load_fpcr(env),&sc->sc_fpcr);
> +
> +    err |= __put_user(0,&sc->sc_traparg_a0); /* FIXME */
> +    err |= __put_user(0,&sc->sc_traparg_a1); /* FIXME */
> +    err |= __put_user(0,&sc->sc_traparg_a2); /* FIXME */
> +
> +    return err;
> +}
> +
> +static int restore_sigcontext(CPUState *env, struct target_sigcontext *sc)
> +{
> +    uint64_t fpcr;
> +    int i, err = 0;
> +
> +    err |= __get_user(env->pc,&sc->sc_pc);
> +
> +    for (i = 0; i<  31; ++i) {
> +        err |= __get_user(env->ir[i],&sc->sc_regs[i]);
> +    }
> +    for (i = 0; i<  31; ++i) {
> +        err |= __get_user(env->fir[i],&sc->sc_fpregs[i]);
> +    }
> +
> +    err |= __get_user(fpcr,&sc->sc_fpcr);
> +    cpu_alpha_store_fpcr(env, fpcr);
> +
> +    return err;
> +}
> +
> +static inline abi_ulong get_sigframe(struct target_sigaction *sa,
> +                                     CPUState *env, unsigned long framesize)
> +{
> +    abi_ulong sp = env->ir[IR_SP];
> +
> +    /* This is the X/Open sanctioned signal stack switching.  */
> +    if ((sa->sa_flags&  TARGET_SA_ONSTACK) != 0&&  !sas_ss_flags(sp)) {
> +        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
> +    }
> +    return (sp - framesize)&  -32;
> +}
> +
> +static void setup_frame(int sig, struct target_sigaction *ka,
> +                        target_sigset_t *set, CPUState *env)
> +{
> +    abi_ulong frame_addr, r26;
> +    struct target_sigframe *frame;
> +    int err = 0;
> +
> +    frame_addr = get_sigframe(ka, env, sizeof(*frame));
> +    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
> +        goto give_sigsegv;
> +    }
> +
> +    err |= setup_sigcontext(&frame->sc, env, frame_addr, set);
> +
> +    if (ka->sa_restorer) {
> +        r26 = ka->sa_restorer;
> +    } else {
> +        err |= __put_user(INSN_MOV_R30_R16,&frame->retcode[0]);
> +        err |= __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn,
> +&frame->retcode[1]);
> +        err |= __put_user(INSN_CALLSYS,&frame->retcode[2]);
> +        /* imb() */
> +        r26 = frame_addr;
> +    }
> +
> +    unlock_user_struct(frame, frame_addr, 1);
> +
> +    if (err) {
> +    give_sigsegv:
> +        if (sig == TARGET_SIGSEGV) {
> +            ka->_sa_handler = TARGET_SIG_DFL;
> +        }
> +        force_sig(TARGET_SIGSEGV);
> +    }
> +
> +    env->ir[IR_RA] = r26;
> +    env->ir[IR_PV] = env->pc = ka->_sa_handler;
> +    env->ir[IR_A0] = sig;
> +    env->ir[IR_A1] = 0;
> +    env->ir[IR_A2] = frame_addr + offsetof(struct target_sigframe, sc);
> +    env->ir[IR_SP] = frame_addr;
> +}
> +
> +static void setup_rt_frame(int sig, struct target_sigaction *ka,
> +                           target_siginfo_t *info,
> +			   target_sigset_t *set, CPUState *env)
> +{
> +    abi_ulong frame_addr, r26;
> +    struct target_rt_sigframe *frame;
> +    int i, err = 0;
> +
> +    frame_addr = get_sigframe(ka, env, sizeof(*frame));
> +    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
> +        goto give_sigsegv;
> +    }
> +
> +    err |= copy_siginfo_to_user(&frame->info, info);
> +
> +    err |= __put_user(0,&frame->uc.uc_flags);
> +    err |= __put_user(0,&frame->uc.uc_link);
> +    err |= __put_user(set->sig[0],&frame->uc.uc_osf_sigmask);
> +    err |= __put_user(target_sigaltstack_used.ss_sp,
> +&frame->uc.uc_stack.ss_sp);
> +    err |= __put_user(sas_ss_flags(env->ir[IR_SP]),
> +&frame->uc.uc_stack.ss_flags);
> +    err |= __put_user(target_sigaltstack_used.ss_size,
> +&frame->uc.uc_stack.ss_size);
> +    err |= setup_sigcontext(&frame->uc.uc_mcontext, env, frame_addr, set);
> +    for (i = 0; i<  TARGET_NSIG_WORDS; ++i) {
> +        err |= __put_user(set->sig[i],&frame->uc.uc_sigmask.sig[i]);
> +    }
> +
> +    if (ka->sa_restorer) {
> +        r26 = ka->sa_restorer;
> +    } else {
> +        err |= __put_user(INSN_MOV_R30_R16,&frame->retcode[0]);
> +        err |= __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn,
> +&frame->retcode[1]);
> +        err |= __put_user(INSN_CALLSYS,&frame->retcode[2]);
> +        /* imb(); */
> +        r26 = frame_addr;
> +    }
> +
> +    if (err) {
> +    give_sigsegv:
> +       if (sig == TARGET_SIGSEGV) {
> +            ka->_sa_handler = TARGET_SIG_DFL;
> +        }
> +        force_sig(TARGET_SIGSEGV);
> +    }
> +
> +    env->ir[IR_RA] = r26;
> +    env->ir[IR_PV] = env->pc = ka->_sa_handler;
> +    env->ir[IR_A0] = sig;
> +    env->ir[IR_A1] = frame_addr + offsetof(struct target_rt_sigframe, info);
> +    env->ir[IR_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
> +    env->ir[IR_SP] = frame_addr;
> +}
> +
> +long do_sigreturn(CPUState *env)
> +{
> +    struct target_sigcontext *sc;
> +    abi_ulong sc_addr = env->ir[IR_A0];
> +    target_sigset_t target_set;
> +    sigset_t set;
> +
> +    if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) {
> +        goto badframe;
> +    }
> +
> +    target_sigemptyset(&target_set);
> +    if (__get_user(target_set.sig[0],&sc->sc_mask)) {
> +        goto badframe;
> +    }
> +
> +    target_to_host_sigset_internal(&set,&target_set);
> +    sigprocmask(SIG_SETMASK,&set, NULL);
> +
> +    if (restore_sigcontext(env, sc)) {
> +        goto badframe;
> +    }
> +    unlock_user_struct(sc, sc_addr, 0);
> +    return env->ir[IR_V0];
> +
> + badframe:
> +    unlock_user_struct(sc, sc_addr, 0);
> +    force_sig(TARGET_SIGSEGV);
> +}
> +
> +long do_rt_sigreturn(CPUState *env)
> +{
> +    abi_ulong frame_addr = env->ir[IR_A0];
> +    struct target_rt_sigframe *frame;
> +    sigset_t set;
> +
> +    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
> +        goto badframe;
> +    }
> +    target_to_host_sigset(&set,&frame->uc.uc_sigmask);
> +    sigprocmask(SIG_SETMASK,&set, NULL);
> +
> +    if (restore_sigcontext(env,&frame->uc.uc_mcontext)) {
> +        goto badframe;
> +    }
> +    if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
> +                                             uc.uc_stack),
> +                       0, env->ir[IR_SP]) == -EFAULT) {
> +        goto badframe;
> +    }
> +
> +    unlock_user_struct(frame, frame_addr, 0);
> +    return env->ir[IR_V0];
> +
> +
> + badframe:
> +    unlock_user_struct(frame, frame_addr, 0);
> +    force_sig(TARGET_SIGSEGV);
> +}
> +
>   #else
>
>   static void setup_frame(int sig, struct target_sigaction *ka,
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 1acf1f5..65c15be 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -4774,20 +4774,18 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
>   #ifdef TARGET_NR_sigaction
>       case TARGET_NR_sigaction:
>           {
> -#if !defined(TARGET_MIPS)
> +#if defined(TARGET_ALPHA)
> +            struct target_sigaction act, oact, *pact = 0;
>               struct target_old_sigaction *old_act;
> -            struct target_sigaction act, oact, *pact;
>               if (arg2) {
>                   if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
>                       goto efault;
>                   act._sa_handler = old_act->_sa_handler;
>                   target_siginitset(&act.sa_mask, old_act->sa_mask);
>                   act.sa_flags = old_act->sa_flags;
> -                act.sa_restorer = old_act->sa_restorer;
> +                act.sa_restorer = 0;
>                   unlock_user_struct(old_act, arg2, 0);
>                   pact =&act;
> -            } else {
> -                pact = NULL;
>               }
>               ret = get_errno(do_sigaction(arg1, pact,&oact));
>               if (!is_error(ret)&&  arg3) {
> @@ -4796,10 +4794,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
>                   old_act->_sa_handler = oact._sa_handler;
>                   old_act->sa_mask = oact.sa_mask.sig[0];
>                   old_act->sa_flags = oact.sa_flags;
> -                old_act->sa_restorer = oact.sa_restorer;
>                   unlock_user_struct(old_act, arg3, 1);
>               }
> -#else
> +#elif defined(TARGET_MIPS)
>   	    struct target_sigaction act, oact, *pact, *old_act;
>
>   	    if (arg2) {
> @@ -4827,12 +4824,61 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
>   		old_act->sa_mask.sig[3] = 0;
>   		unlock_user_struct(old_act, arg3, 1);
>   	    }
> +#else
> +            struct target_old_sigaction *old_act;
> +            struct target_sigaction act, oact, *pact;
> +            if (arg2) {
> +                if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
> +                    goto efault;
> +                act._sa_handler = old_act->_sa_handler;
> +                target_siginitset(&act.sa_mask, old_act->sa_mask);
> +                act.sa_flags = old_act->sa_flags;
> +                act.sa_restorer = old_act->sa_restorer;
> +                unlock_user_struct(old_act, arg2, 0);
> +                pact =&act;
> +            } else {
> +                pact = NULL;
> +            }
> +            ret = get_errno(do_sigaction(arg1, pact,&oact));
> +            if (!is_error(ret)&&  arg3) {
> +                if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
> +                    goto efault;
> +                old_act->_sa_handler = oact._sa_handler;
> +                old_act->sa_mask = oact.sa_mask.sig[0];
> +                old_act->sa_flags = oact.sa_flags;
> +                old_act->sa_restorer = oact.sa_restorer;
> +                unlock_user_struct(old_act, arg3, 1);
> +            }
>   #endif
>           }
>           break;
>   #endif
>       case TARGET_NR_rt_sigaction:
>           {
> +#if defined(TARGET_ALPHA)
> +            struct target_sigaction act, oact, *pact = 0;
> +            struct target_rt_sigaction *rt_act;
> +            /* ??? arg4 == sizeof(sigset_t).  */
> +            if (arg2) {
> +                if (!lock_user_struct(VERIFY_READ, rt_act, arg2, 1))
> +                    goto efault;
> +                act._sa_handler = rt_act->_sa_handler;
> +                act.sa_mask = rt_act->sa_mask;
> +                act.sa_flags = rt_act->sa_flags;
> +                act.sa_restorer = arg5;
> +                unlock_user_struct(rt_act, arg2, 0);
> +                pact =&act;
> +            }
> +            ret = get_errno(do_sigaction(arg1, pact,&oact));
> +            if (!is_error(ret)&&  arg3) {
> +                if (!lock_user_struct(VERIFY_WRITE, rt_act, arg3, 0))
> +                    goto efault;
> +                rt_act->_sa_handler = oact._sa_handler;
> +                rt_act->sa_mask = oact.sa_mask;
> +                rt_act->sa_flags = oact.sa_flags;
> +                unlock_user_struct(rt_act, arg3, 1);
> +            }
> +#else
>               struct target_sigaction *act;
>               struct target_sigaction *oact;
>
> @@ -4854,6 +4900,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
>                   unlock_user_struct(act, arg2, 0);
>               if (oact)
>                   unlock_user_struct(oact, arg3, 1);
> +#endif
>           }
>           break;
>   #ifdef TARGET_NR_sgetmask /* not on alpha */
> diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
> index 2d45753..63c2bc3 100644
> --- a/linux-user/syscall_defs.h
> +++ b/linux-user/syscall_defs.h
> @@ -472,8 +472,28 @@ int do_sigaction(int sig, const struct target_sigaction *act,
>
>   #endif
>
> -#if defined(TARGET_MIPS)
> +#if defined(TARGET_ALPHA)
> +struct target_old_sigaction {
> +    abi_ulong _sa_handler;
> +    abi_ulong sa_mask;
> +    abi_ulong sa_flags;
> +};
> +
> +struct target_rt_sigaction {
> +    abi_ulong _sa_handler;
> +    abi_ulong sa_flags;
> +    target_sigset_t sa_mask;
> +};
>
> +/* This is the struct used inside the kernel.  The ka_restorer
> +   field comes from the 5th argument to sys_rt_sigaction.  */
> +struct target_sigaction {
> +    abi_ulong _sa_handler;
> +    abi_ulong sa_flags;
> +    target_sigset_t sa_mask;
> +    abi_ulong sa_restorer;
> +};
> +#elif defined(TARGET_MIPS)
>   struct target_sigaction {
>   	uint32_t	sa_flags;
>   #if defined(TARGET_ABI_MIPSN32)
> @@ -483,7 +503,6 @@ struct target_sigaction {
>   #endif
>   	target_sigset_t	sa_mask;
>   };
> -
>   #else
>   struct target_old_sigaction {
>           abi_ulong _sa_handler;
> diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
> index eda1b4a..617f55c 100644
> --- a/target-alpha/cpu.h
> +++ b/target-alpha/cpu.h
> @@ -511,11 +511,9 @@ uint64_t cpu_alpha_load_fpcr (CPUState *env);
>   void cpu_alpha_store_fpcr (CPUState *env, uint64_t val);
>   int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp);
>   int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp);
> -void pal_init (CPUState *env);
>   #if !defined (CONFIG_USER_ONLY)
> +void pal_init (CPUState *env);
>   void call_pal (CPUState *env);
> -#else
> -void call_pal (CPUState *env, int palcode);
>   #endif
>
>   static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
> diff --git a/target-alpha/translate.c b/target-alpha/translate.c
> index a11e5ed..719b423 100644
> --- a/target-alpha/translate.c
> +++ b/target-alpha/translate.c
> @@ -3094,8 +3094,9 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model)
>       env->ps |= 1<<  3;
>       cpu_alpha_store_fpcr(env, (FPCR_INVD | FPCR_DZED | FPCR_OVFD
>                                  | FPCR_UNFD | FPCR_INED | FPCR_DNOD));
> -#endif
> +#else
>       pal_init(env);
> +#endif
>
>       /* Initialize IPR */
>   #if defined (CONFIG_USER_ONLY)

  reply	other threads:[~2010-02-09 18:46 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-01-04 23:17 [Qemu-devel] [PATCH] alpha-linux-user: Implement signals Richard Henderson
2010-02-09 18:46 ` Richard Henderson [this message]
2010-02-10 12:04   ` Riku Voipio
2010-02-10 17:35     ` Richard Henderson
2010-02-10 18:24       ` Richard Henderson
2010-02-28 17:59       ` Aurelien Jarno

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4B71AD88.5090607@twiddle.net \
    --to=rth@twiddle.net \
    --cc=aurelien@aurel32.net \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.