* [Qemu-devel] [PATCH 0/3][RESEND] m68k, linux-user: signal management @ 2009-08-03 14:12 Laurent Vivier 2009-08-03 14:12 ` [Qemu-devel] [PATCH 1/3][RESEND] m68k,linux-user: add setup_frame Laurent Vivier 0 siblings, 1 reply; 4+ messages in thread From: Laurent Vivier @ 2009-08-03 14:12 UTC (permalink / raw) To: qemu-devel; +Cc: Paul Brook This series of patches implements signal management for linux-user m68k. [PATCH 1/3] m68k,linux-user: add setup_frame [PATCH 2/3] m68k,linux-user: add setup_rt_frame [PATCH 3/3] m68k,linux-user: enable sigaltstack() Laurent ^ permalink raw reply [flat|nested] 4+ messages in thread
* [Qemu-devel] [PATCH 1/3][RESEND] m68k,linux-user: add setup_frame 2009-08-03 14:12 [Qemu-devel] [PATCH 0/3][RESEND] m68k, linux-user: signal management Laurent Vivier @ 2009-08-03 14:12 ` Laurent Vivier 2009-08-03 14:12 ` [Qemu-devel] [PATCH 2/3][RESEND] m68k, linux-user: add setup_rt_frame Laurent Vivier 0 siblings, 1 reply; 4+ messages in thread From: Laurent Vivier @ 2009-08-03 14:12 UTC (permalink / raw) To: qemu-devel; +Cc: Paul Brook, Laurent Vivier This patch adds signals management for linux-user. It implements setup_frame() which allows to call the user signal handler. setup_rt_frame() is always unimplemented. Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/signal.c | 183 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 183 insertions(+), 0 deletions(-) diff --git a/linux-user/signal.c b/linux-user/signal.c index b2c0623..0756380 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -4028,6 +4028,189 @@ sigsegv: return 0; } +#elif defined(TARGET_M68K) + +struct target_sigcontext { + abi_ulong sc_mask; + abi_ulong sc_usp; + abi_ulong sc_d0; + abi_ulong sc_d1; + abi_ulong sc_a0; + abi_ulong sc_a1; + unsigned short sc_sr; + abi_ulong sc_pc; +}; + +struct target_sigframe +{ + abi_ulong pretcode; + int sig; + int code; + abi_ulong psc; + char retcode[8]; + abi_ulong extramask[TARGET_NSIG_WORDS-1]; + struct target_sigcontext sc; +}; + +static int +setup_sigcontext(struct target_sigcontext *sc, CPUState *env, abi_ulong mask) +{ + int err = 0; + + err |= __put_user(mask, &sc->sc_mask); + err |= __put_user(env->aregs[7], &sc->sc_usp); + err |= __put_user(env->dregs[0], &sc->sc_d0); + err |= __put_user(env->dregs[1], &sc->sc_d1); + err |= __put_user(env->aregs[0], &sc->sc_a0); + err |= __put_user(env->aregs[1], &sc->sc_a1); + err |= __put_user(env->sr, &sc->sc_sr); + err |= __put_user(env->pc, &sc->sc_pc); + + return err; +} + +static int +restore_sigcontext(CPUState *env, struct target_sigcontext *sc, int *pd0) +{ + int err = 0; + int temp; + + err |= __get_user(env->aregs[7], &sc->sc_usp); + err |= __get_user(env->dregs[1], &sc->sc_d1); + err |= __get_user(env->aregs[0], &sc->sc_a0); + err |= __get_user(env->aregs[1], &sc->sc_a1); + err |= __get_user(env->pc, &sc->sc_pc); + err |= __get_user(temp, &sc->sc_sr); + env->sr = (env->sr & 0xff00) | (temp & 0xff); + + *pd0 = tswapl(sc->sc_d0); + + return err; +} + +/* + * Determine which stack to use.. + */ +static inline abi_ulong +get_sigframe(struct target_sigaction *ka, CPUState *regs, size_t frame_size) +{ + unsigned long sp; + + sp = regs->aregs[7]; + + /* This is the X/Open sanctioned signal stack switching. */ + if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) { + sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; + } + + return ((sp - frame_size) & -8UL); +} + +static void setup_frame(int sig, struct target_sigaction *ka, + target_sigset_t *set, CPUState *env) +{ + struct target_sigframe *frame; + abi_ulong frame_addr; + abi_ulong retcode_addr; + abi_ulong sc_addr; + int err = 0; + int i; + + frame_addr = get_sigframe(ka, env, sizeof *frame); + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) + goto give_sigsegv; + + err |= __put_user(sig, &frame->sig); + + sc_addr = frame_addr + offsetof(struct target_sigframe, sc); + err |= __put_user(sc_addr, &frame->psc); + + err |= setup_sigcontext(&frame->sc, env, set->sig[0]); + if (err) + goto give_sigsegv; + + for(i = 1; i < TARGET_NSIG_WORDS; i++) { + if (__put_user(set->sig[i], &frame->extramask[i - 1])) + goto give_sigsegv; + } + + /* Set up to return from userspace. */ + + retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode); + err |= __put_user(retcode_addr, &frame->pretcode); + + /* moveq #,d0; trap #0 */ + + err |= __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16), + (long *)(frame->retcode)); + + if (err) + goto give_sigsegv; + + /* Set up to return from userspace */ + + env->aregs[7] = frame_addr; + env->pc = ka->_sa_handler; + + unlock_user_struct(frame, frame_addr, 1); + return; + +give_sigsegv: + unlock_user_struct(frame, frame_addr, 1); + force_sig(SIGSEGV); +} + +static void setup_rt_frame(int sig, struct target_sigaction *ka, + target_siginfo_t *info, + target_sigset_t *set, CPUState *env) +{ + fprintf(stderr, "setup_rt_frame: not implemented\n"); +} + +long do_sigreturn(CPUState *env) +{ + struct target_sigframe *frame; + abi_ulong frame_addr = env->aregs[7] - 4; + target_sigset_t target_set; + sigset_t set; + int d0, i; + + if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) + goto badframe; + + /* set blocked signals */ + + if (__get_user(target_set.sig[0], &frame->sc.sc_mask)) + goto badframe; + + for(i = 1; i < TARGET_NSIG_WORDS; i++) { + if (__get_user(target_set.sig[i], &frame->extramask[i - 1])) + goto badframe; + } + + target_to_host_sigset_internal(&set, &target_set); + sigprocmask(SIG_SETMASK, &set, NULL); + + /* restore registers */ + + if (restore_sigcontext(env, &frame->sc, &d0)) + goto badframe; + + unlock_user_struct(frame, frame_addr, 0); + return d0; + +badframe: + unlock_user_struct(frame, frame_addr, 0); + force_sig(TARGET_SIGSEGV); + return 0; +} + +long do_rt_sigreturn(CPUState *env) +{ + fprintf(stderr, "do_rt_sigreturn: not implemented\n"); + return -TARGET_ENOSYS; +} + #else static void setup_frame(int sig, struct target_sigaction *ka, -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [Qemu-devel] [PATCH 2/3][RESEND] m68k, linux-user: add setup_rt_frame 2009-08-03 14:12 ` [Qemu-devel] [PATCH 1/3][RESEND] m68k,linux-user: add setup_frame Laurent Vivier @ 2009-08-03 14:12 ` Laurent Vivier 2009-08-03 14:12 ` [Qemu-devel] [PATCH 3/3][RESEND] m68k, linux-user: enable sigaltstack() Laurent Vivier 0 siblings, 1 reply; 4+ messages in thread From: Laurent Vivier @ 2009-08-03 14:12 UTC (permalink / raw) To: qemu-devel; +Cc: Paul Brook, Laurent Vivier This patch implements setup_rt_frame(). Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/signal.c | 205 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 202 insertions(+), 3 deletions(-) diff --git a/linux-user/signal.c b/linux-user/signal.c index 0756380..2df17aa 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -4051,6 +4051,43 @@ struct target_sigframe abi_ulong extramask[TARGET_NSIG_WORDS-1]; struct target_sigcontext sc; }; + +typedef int target_greg_t; +#define TARGET_NGREG 18 +typedef target_greg_t target_gregset_t[TARGET_NGREG]; + +typedef struct target_fpregset { + int f_fpcntl[3]; + int f_fpregs[8*3]; +} target_fpregset_t; + +struct target_mcontext { + int version; + target_gregset_t gregs; + target_fpregset_t fpregs; +}; + +#define TARGET_MCONTEXT_VERSION 2 + +struct target_ucontext { + abi_ulong uc_flags; + abi_ulong uc_link; + target_stack_t uc_stack; + struct target_mcontext uc_mcontext; + abi_long uc_filler[80]; + target_sigset_t uc_sigmask; +}; + +struct target_rt_sigframe +{ + abi_ulong pretcode; + int sig; + abi_ulong pinfo; + abi_ulong puc; + char retcode[8]; + struct target_siginfo info; + struct target_ucontext uc; +}; static int setup_sigcontext(struct target_sigcontext *sc, CPUState *env, abi_ulong mask) @@ -4160,11 +4197,146 @@ give_sigsegv: force_sig(SIGSEGV); } +static inline int target_rt_setup_ucontext(struct target_ucontext *uc, + CPUState *env) +{ + target_greg_t *gregs = uc->uc_mcontext.gregs; + int err; + + err = __put_user(TARGET_MCONTEXT_VERSION, &uc->uc_mcontext.version); + err |= __put_user(env->dregs[0], &gregs[0]); + err |= __put_user(env->dregs[1], &gregs[1]); + err |= __put_user(env->dregs[2], &gregs[2]); + err |= __put_user(env->dregs[3], &gregs[3]); + err |= __put_user(env->dregs[4], &gregs[4]); + err |= __put_user(env->dregs[5], &gregs[5]); + err |= __put_user(env->dregs[6], &gregs[6]); + err |= __put_user(env->dregs[7], &gregs[7]); + err |= __put_user(env->aregs[0], &gregs[8]); + err |= __put_user(env->aregs[1], &gregs[9]); + err |= __put_user(env->aregs[2], &gregs[10]); + err |= __put_user(env->aregs[3], &gregs[11]); + err |= __put_user(env->aregs[4], &gregs[12]); + err |= __put_user(env->aregs[5], &gregs[13]); + err |= __put_user(env->aregs[6], &gregs[14]); + err |= __put_user(env->aregs[7], &gregs[15]); + err |= __put_user(env->pc, &gregs[16]); + err |= __put_user(env->sr, &gregs[17]); + + return err; +} + +static inline int target_rt_restore_ucontext(CPUState *env, + struct target_ucontext *uc, + int *pd0) +{ + int temp; + int err; + target_greg_t *gregs = uc->uc_mcontext.gregs; + + err = __get_user(temp, &uc->uc_mcontext.version); + if (temp != TARGET_MCONTEXT_VERSION) + goto badframe; + + /* restore passed registers */ + err |= __get_user(env->dregs[0], &gregs[0]); + err |= __get_user(env->dregs[1], &gregs[1]); + err |= __get_user(env->dregs[2], &gregs[2]); + err |= __get_user(env->dregs[3], &gregs[3]); + err |= __get_user(env->dregs[4], &gregs[4]); + err |= __get_user(env->dregs[5], &gregs[5]); + err |= __get_user(env->dregs[6], &gregs[6]); + err |= __get_user(env->dregs[7], &gregs[7]); + err |= __get_user(env->aregs[0], &gregs[8]); + err |= __get_user(env->aregs[1], &gregs[9]); + err |= __get_user(env->aregs[2], &gregs[10]); + err |= __get_user(env->aregs[3], &gregs[11]); + err |= __get_user(env->aregs[4], &gregs[12]); + err |= __get_user(env->aregs[5], &gregs[13]); + err |= __get_user(env->aregs[6], &gregs[14]); + err |= __get_user(env->aregs[7], &gregs[15]); + err |= __get_user(env->pc, &gregs[16]); + err |= __get_user(temp, &gregs[17]); + env->sr = (env->sr & 0xff00) | (temp & 0xff); + + *pd0 = env->dregs[0]; + return err; + +badframe: + return 1; +} + static void setup_rt_frame(int sig, struct target_sigaction *ka, target_siginfo_t *info, target_sigset_t *set, CPUState *env) { - fprintf(stderr, "setup_rt_frame: not implemented\n"); + struct target_rt_sigframe *frame; + abi_ulong frame_addr; + abi_ulong retcode_addr; + abi_ulong info_addr; + abi_ulong uc_addr; + int err = 0; + int i; + + frame_addr = get_sigframe(ka, env, sizeof *frame); + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) + goto give_sigsegv; + + err |= __put_user(sig, &frame->sig); + + info_addr = frame_addr + offsetof(struct target_rt_sigframe, info); + err |= __put_user(info_addr, &frame->pinfo); + + uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc); + err |= __put_user(uc_addr, &frame->puc); + + err |= copy_siginfo_to_user(&frame->info, info); + + /* Create the ucontext */ + + err |= __put_user(0, &frame->uc.uc_flags); + err |= __put_user(0, &frame->uc.uc_link); + err |= __put_user(target_sigaltstack_used.ss_sp, + &frame->uc.uc_stack.ss_sp); + err |= __put_user(sas_ss_flags(env->aregs[7]), + &frame->uc.uc_stack.ss_flags); + err |= __put_user(target_sigaltstack_used.ss_size, + &frame->uc.uc_stack.ss_size); + err |= target_rt_setup_ucontext(&frame->uc, env); + + if (err) + goto give_sigsegv; + + for(i = 0; i < TARGET_NSIG_WORDS; i++) { + if (__put_user(set->sig[i], &frame->uc.uc_sigmask.sig[i])) + goto give_sigsegv; + } + + /* Set up to return from userspace. */ + + retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode); + err |= __put_user(retcode_addr, &frame->pretcode); + + /* moveq #,d0; notb d0; trap #0 */ + + err |= __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16), + (long *)(frame->retcode + 0)); + err |= __put_user(0x4e40, (short *)(frame->retcode + 4)); + + if (err) + goto give_sigsegv; + + /* Set up to return from userspace */ + + env->aregs[7] = frame_addr; + env->pc = ka->_sa_handler; + + unlock_user_struct(frame, frame_addr, 1); + return; + +give_sigsegv: + unlock_user_struct(frame, frame_addr, 1); + force_sig(SIGSEGV); } long do_sigreturn(CPUState *env) @@ -4207,8 +4379,35 @@ badframe: long do_rt_sigreturn(CPUState *env) { - fprintf(stderr, "do_rt_sigreturn: not implemented\n"); - return -TARGET_ENOSYS; + struct target_rt_sigframe *frame; + abi_ulong frame_addr = env->aregs[7] - 4; + target_sigset_t target_set; + sigset_t set; + int d0; + + if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) + goto badframe; + + target_to_host_sigset_internal(&set, &target_set); + sigprocmask(SIG_SETMASK, &set, NULL); + + /* restore registers */ + + if (target_rt_restore_ucontext(env, &frame->uc, &d0)) + goto badframe; + + if (do_sigaltstack(frame_addr + + offsetof(struct target_rt_sigframe, uc.uc_stack), + 0, get_sp_from_cpustate(env)) == -EFAULT) + goto badframe; + + unlock_user_struct(frame, frame_addr, 0); + return d0; + +badframe: + unlock_user_struct(frame, frame_addr, 0); + force_sig(TARGET_SIGSEGV); + return 0; } #else -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [Qemu-devel] [PATCH 3/3][RESEND] m68k, linux-user: enable sigaltstack() 2009-08-03 14:12 ` [Qemu-devel] [PATCH 2/3][RESEND] m68k, linux-user: add setup_rt_frame Laurent Vivier @ 2009-08-03 14:12 ` Laurent Vivier 0 siblings, 0 replies; 4+ messages in thread From: Laurent Vivier @ 2009-08-03 14:12 UTC (permalink / raw) To: qemu-devel; +Cc: Paul Brook, Laurent Vivier As setup_frame() and setup_rt_frame() are now implemented we can now enable sigaltstack(). Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/syscall.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index b5f669e..36caa43 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -6100,7 +6100,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, goto unimplemented; case TARGET_NR_sigaltstack: #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \ - defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA) + defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA) || \ + defined(TARGET_M68K) ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState *)cpu_env)); break; #else -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2009-08-03 14:12 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2009-08-03 14:12 [Qemu-devel] [PATCH 0/3][RESEND] m68k, linux-user: signal management Laurent Vivier 2009-08-03 14:12 ` [Qemu-devel] [PATCH 1/3][RESEND] m68k,linux-user: add setup_frame Laurent Vivier 2009-08-03 14:12 ` [Qemu-devel] [PATCH 2/3][RESEND] m68k, linux-user: add setup_rt_frame Laurent Vivier 2009-08-03 14:12 ` [Qemu-devel] [PATCH 3/3][RESEND] m68k, linux-user: enable sigaltstack() Laurent Vivier
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).