linux-user: Support for restarting system calls for M68K targets

Update the M68K main loop and sigreturn code:
 * on TARGET_ERESTARTSYS, wind guest PC backwards to repeat syscall insn
 * set all guest CPU state within signal.c code on sigreturn
 * handle TARGET_QEMU_ESIGRETURN in the main loop as the indication
   that the main loop should not touch any guest CPU state

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Message-id: 1441497448-32489-32-git-send-email-T.E.Baldwin99@members.leeds.ac.uk
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
[PMM: tweak commit message; drop TARGET_USE_ERESTARTSYS define]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
This commit is contained in:
Timothy E Baldwin 2016-05-12 18:47:39 +01:00 committed by Riku Voipio
parent 7fe7231a49
commit 7ccb84a916
3 changed files with 24 additions and 21 deletions

View File

@ -26,4 +26,5 @@ static inline abi_ulong get_sp_from_cpustate(CPUM68KState *state)
return state->aregs[7];
}
#endif /* TARGET_SIGNAL_H */

View File

@ -3086,18 +3086,24 @@ void cpu_loop(CPUM68KState *env)
break;
case EXCP_TRAP0:
{
abi_long ret;
ts->sim_syscalls = 0;
n = env->dregs[0];
env->pc += 2;
env->dregs[0] = do_syscall(env,
n,
env->dregs[1],
env->dregs[2],
env->dregs[3],
env->dregs[4],
env->dregs[5],
env->aregs[0],
0, 0);
ret = do_syscall(env,
n,
env->dregs[1],
env->dregs[2],
env->dregs[3],
env->dregs[4],
env->dregs[5],
env->aregs[0],
0, 0);
if (ret == -TARGET_ERESTARTSYS) {
env->pc -= 2;
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
env->dregs[0] = ret;
}
}
break;
case EXCP_INTERRUPT:

View File

@ -5009,19 +5009,18 @@ static void setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
}
static void
restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc, int *pd0)
restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc)
{
int temp;
__get_user(env->aregs[7], &sc->sc_usp);
__get_user(env->dregs[0], &sc->sc_d0);
__get_user(env->dregs[1], &sc->sc_d1);
__get_user(env->aregs[0], &sc->sc_a0);
__get_user(env->aregs[1], &sc->sc_a1);
__get_user(env->pc, &sc->sc_pc);
__get_user(temp, &sc->sc_sr);
env->sr = (env->sr & 0xff00) | (temp & 0xff);
*pd0 = tswapl(sc->sc_d0);
}
/*
@ -5120,8 +5119,7 @@ static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
}
static inline int target_rt_restore_ucontext(CPUM68KState *env,
struct target_ucontext *uc,
int *pd0)
struct target_ucontext *uc)
{
int temp;
target_greg_t *gregs = uc->tuc_mcontext.gregs;
@ -5151,7 +5149,6 @@ static inline int target_rt_restore_ucontext(CPUM68KState *env,
__get_user(temp, &gregs[17]);
env->sr = (env->sr & 0xff00) | (temp & 0xff);
*pd0 = env->dregs[0];
return 0;
badframe:
@ -5238,7 +5235,7 @@ long do_sigreturn(CPUM68KState *env)
abi_ulong frame_addr = env->aregs[7] - 4;
target_sigset_t target_set;
sigset_t set;
int d0, i;
int i;
trace_user_do_sigreturn(env, frame_addr);
if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
@ -5257,10 +5254,10 @@ long do_sigreturn(CPUM68KState *env)
/* restore registers */
restore_sigcontext(env, &frame->sc, &d0);
restore_sigcontext(env, &frame->sc);
unlock_user_struct(frame, frame_addr, 0);
return d0;
return -TARGET_QEMU_ESIGRETURN;
badframe:
force_sig(TARGET_SIGSEGV);
@ -5273,7 +5270,6 @@ long do_rt_sigreturn(CPUM68KState *env)
abi_ulong frame_addr = env->aregs[7] - 4;
target_sigset_t target_set;
sigset_t set;
int d0;
trace_user_do_rt_sigreturn(env, frame_addr);
if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
@ -5284,7 +5280,7 @@ long do_rt_sigreturn(CPUM68KState *env)
/* restore registers */
if (target_rt_restore_ucontext(env, &frame->uc, &d0))
if (target_rt_restore_ucontext(env, &frame->uc))
goto badframe;
if (do_sigaltstack(frame_addr +
@ -5293,7 +5289,7 @@ long do_rt_sigreturn(CPUM68KState *env)
goto badframe;
unlock_user_struct(frame, frame_addr, 0);
return d0;
return -TARGET_QEMU_ESIGRETURN;
badframe:
unlock_user_struct(frame, frame_addr, 0);