differences between host and target structure alignment requirements.
Use ColdFire version of rt_sigreturn trampoline.
Signed-off-by: Maxim Kuvyrkov <maxim@codesourcery.com>
---
linux-user/signal.c | 60 ++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 50 insertions(+), 10 deletions(-)
@@ -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;
From 1450a09c513a3051e3cf44d948983fe48ef368e0 Mon Sep 17 00:00:00 2001 From: Maxim Kuvyrkov <maxim@codesourcery.com> 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