>From 1450a09c513a3051e3cf44d948983fe48ef368e0 Mon Sep 17 00:00:00 2001 From: Maxim Kuvyrkov Date: Mon, 1 Mar 2010 02:48:31 -0800 Subject: [PATCH 3/4] Fix signal handling for ColdFire Handle FPU registers. Pack structures that contain 16-bit fields. This avoid problems due to differences between host and target structure alignment requirements. Use ColdFire version of rt_sigreturn trampoline. Signed-off-by: Maxim Kuvyrkov --- linux-user/signal.c | 60 ++++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 50 insertions(+), 10 deletions(-) diff --git a/linux-user/signal.c b/linux-user/signal.c index 8f9da80..dc6f957 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -4058,9 +4058,17 @@ struct target_sigcontext { abi_ulong sc_d1; abi_ulong sc_a0; abi_ulong sc_a1; - unsigned short sc_sr; + uint16_t sc_sr; + /* M68K Linux ABI allows int32_t to be aligned at 2 bytes, + as most host architectures align int32's at 4 bytes, + we need to pack target_sigcontext so that sc_pc will be at + the correct offset. */ abi_ulong sc_pc; -}; + uint16_t sc_formatvec; + float64 sc_fpregs[2]; /* room for two fp registers */ + uint32_t sc_fpcntl[3]; + unsigned char sc_fpstate[216]; +} __attribute__((__packed__)); struct target_sigframe { @@ -4078,8 +4086,8 @@ typedef int target_greg_t; typedef target_greg_t target_gregset_t[TARGET_NGREG]; typedef struct target_fpregset { - int f_fpcntl[3]; - int f_fpregs[8*3]; + uint32_t f_fpcntl[3]; + float64 f_fpregs[8]; } target_fpregset_t; struct target_mcontext { @@ -4106,7 +4114,7 @@ struct target_rt_sigframe abi_ulong pinfo; abi_ulong puc; char retcode[8]; - struct target_siginfo info; + target_siginfo_t info; struct target_ucontext uc; }; @@ -4123,6 +4131,12 @@ setup_sigcontext(struct target_sigcontext *sc, CPUState *env, abi_ulong mask) 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); + err |= __put_user(env->fregs[0], &sc->sc_fpregs[0]); + err |= __put_user(env->fregs[1], &sc->sc_fpregs[1]); + err |= __put_user(env->fpcr, &sc->sc_fpcntl[0]); + err |= __put_user(env->fpsr, &sc->sc_fpcntl[1]); + err |= __put_user(0, &sc->sc_fpcntl[2]); + err |= __put_user(0, (uint32_t *) &sc->sc_fpstate[0]); return err; } @@ -4140,6 +4154,10 @@ restore_sigcontext(CPUState *env, struct target_sigcontext *sc, int *pd0) err |= __get_user(env->pc, &sc->sc_pc); err |= __get_user(temp, &sc->sc_sr); env->sr = (env->sr & 0xff00) | (temp & 0xff); + err |= __get_user(env->fregs[0], &sc->sc_fpregs[0]); + err |= __get_user(env->fregs[1], &sc->sc_fpregs[1]); + err |= __get_user(env->fpcr, &sc->sc_fpcntl[0]); + err |= __get_user(env->fpsr, &sc->sc_fpcntl[1]); *pd0 = tswapl(sc->sc_d0); @@ -4222,6 +4240,7 @@ static inline int target_rt_setup_ucontext(struct target_ucontext *uc, CPUState *env) { target_greg_t *gregs = uc->uc_mcontext.gregs; + target_fpregset_t *fpregs = &uc->uc_mcontext.fpregs; int err; err = __put_user(TARGET_MCONTEXT_VERSION, &uc->uc_mcontext.version); @@ -4243,6 +4262,17 @@ static inline int target_rt_setup_ucontext(struct target_ucontext *uc, err |= __put_user(env->aregs[7], &gregs[15]); err |= __put_user(env->pc, &gregs[16]); err |= __put_user(env->sr, &gregs[17]); + err |= __put_user(env->fpcr, &fpregs->f_fpcntl[0]); + err |= __put_user(env->fpsr, &fpregs->f_fpcntl[1]); + err |= __put_user(0, &fpregs->f_fpcntl[2]); + err |= __put_user(env->fregs[0], &fpregs->f_fpregs[0]); + err |= __put_user(env->fregs[1], &fpregs->f_fpregs[1]); + err |= __put_user(env->fregs[2], &fpregs->f_fpregs[2]); + err |= __put_user(env->fregs[3], &fpregs->f_fpregs[3]); + err |= __put_user(env->fregs[4], &fpregs->f_fpregs[4]); + err |= __put_user(env->fregs[5], &fpregs->f_fpregs[5]); + err |= __put_user(env->fregs[6], &fpregs->f_fpregs[6]); + err |= __put_user(env->fregs[7], &fpregs->f_fpregs[7]); return err; } @@ -4254,6 +4284,7 @@ static inline int target_rt_restore_ucontext(CPUState *env, int temp; int err; target_greg_t *gregs = uc->uc_mcontext.gregs; + target_fpregset_t *fpregs = &uc->uc_mcontext.fpregs; err = __get_user(temp, &uc->uc_mcontext.version); if (temp != TARGET_MCONTEXT_VERSION) @@ -4279,6 +4310,16 @@ static inline int target_rt_restore_ucontext(CPUState *env, err |= __get_user(env->pc, &gregs[16]); err |= __get_user(temp, &gregs[17]); env->sr = (env->sr & 0xff00) | (temp & 0xff); + err |= __get_user(env->fpcr, &fpregs->f_fpcntl[0]); + err |= __get_user(env->fpsr, &fpregs->f_fpcntl[1]); + err |= __get_user(env->fregs[0], &fpregs->f_fpregs[0]); + err |= __get_user(env->fregs[1], &fpregs->f_fpregs[1]); + err |= __get_user(env->fregs[2], &fpregs->f_fpregs[2]); + err |= __get_user(env->fregs[3], &fpregs->f_fpregs[3]); + err |= __get_user(env->fregs[4], &fpregs->f_fpregs[4]); + err |= __get_user(env->fregs[5], &fpregs->f_fpregs[5]); + err |= __get_user(env->fregs[6], &fpregs->f_fpregs[6]); + err |= __get_user(env->fregs[7], &fpregs->f_fpregs[7]); *pd0 = env->dregs[0]; return err; @@ -4338,11 +4379,10 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, 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)); + /* movel #__NR_rt_sigreturn,d0; trap #0 */ + err |= __put_user(0x203c0000, (long *)(frame->retcode + 0)); + err |= __put_user(0x00004e40 + (TARGET_NR_rt_sigreturn << 16), + (long *)(frame->retcode + 4)); if (err) goto give_sigsegv; -- 1.6.2.4