linux-user: Support for restarting system calls for SH4 targets
Update the SH4 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-12-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:
parent
c0bea68f9e
commit
ba41249678
@ -2826,7 +2826,11 @@ void cpu_loop(CPUSH4State *env)
|
||||
env->gregs[0],
|
||||
env->gregs[1],
|
||||
0, 0);
|
||||
env->gregs[0] = ret;
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
env->pc -= 2;
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
env->gregs[0] = ret;
|
||||
}
|
||||
break;
|
||||
case EXCP_INTERRUPT:
|
||||
/* just indicate that signals should be handled asap */
|
||||
|
@ -26,4 +26,5 @@ static inline abi_ulong get_sp_from_cpustate(CPUSH4State *state)
|
||||
return state->gregs[15];
|
||||
}
|
||||
|
||||
|
||||
#endif /* TARGET_SIGNAL_H */
|
||||
|
@ -3202,13 +3202,12 @@ static void setup_sigcontext(struct target_sigcontext *sc,
|
||||
__put_user(mask, &sc->oldmask);
|
||||
}
|
||||
|
||||
static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc,
|
||||
target_ulong *r0_p)
|
||||
static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc)
|
||||
{
|
||||
int i;
|
||||
|
||||
#define COPY(x) __get_user(regs->x, &sc->sc_##x)
|
||||
COPY(gregs[1]);
|
||||
COPY(gregs[0]); COPY(gregs[1]);
|
||||
COPY(gregs[2]); COPY(gregs[3]);
|
||||
COPY(gregs[4]); COPY(gregs[5]);
|
||||
COPY(gregs[6]); COPY(gregs[7]);
|
||||
@ -3228,7 +3227,6 @@ static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc,
|
||||
__get_user(regs->fpul, &sc->sc_fpul);
|
||||
|
||||
regs->tra = -1; /* disable syscall checks */
|
||||
__get_user(*r0_p, &sc->sc_gregs[0]);
|
||||
}
|
||||
|
||||
static void setup_frame(int sig, struct target_sigaction *ka,
|
||||
@ -3345,7 +3343,6 @@ long do_sigreturn(CPUSH4State *regs)
|
||||
abi_ulong frame_addr;
|
||||
sigset_t blocked;
|
||||
target_sigset_t target_set;
|
||||
target_ulong r0;
|
||||
int i;
|
||||
int err = 0;
|
||||
|
||||
@ -3366,10 +3363,10 @@ long do_sigreturn(CPUSH4State *regs)
|
||||
target_to_host_sigset_internal(&blocked, &target_set);
|
||||
do_sigprocmask(SIG_SETMASK, &blocked, NULL);
|
||||
|
||||
restore_sigcontext(regs, &frame->sc, &r0);
|
||||
restore_sigcontext(regs, &frame->sc);
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
return r0;
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
|
||||
badframe:
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
@ -3382,7 +3379,6 @@ long do_rt_sigreturn(CPUSH4State *regs)
|
||||
struct target_rt_sigframe *frame;
|
||||
abi_ulong frame_addr;
|
||||
sigset_t blocked;
|
||||
target_ulong r0;
|
||||
|
||||
frame_addr = regs->gregs[15];
|
||||
trace_user_do_rt_sigreturn(regs, frame_addr);
|
||||
@ -3393,7 +3389,7 @@ long do_rt_sigreturn(CPUSH4State *regs)
|
||||
target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask);
|
||||
do_sigprocmask(SIG_SETMASK, &blocked, NULL);
|
||||
|
||||
restore_sigcontext(regs, &frame->uc.tuc_mcontext, &r0);
|
||||
restore_sigcontext(regs, &frame->uc.tuc_mcontext);
|
||||
|
||||
if (do_sigaltstack(frame_addr +
|
||||
offsetof(struct target_rt_sigframe, uc.tuc_stack),
|
||||
@ -3402,7 +3398,7 @@ long do_rt_sigreturn(CPUSH4State *regs)
|
||||
}
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
return r0;
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
|
||||
badframe:
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
|
Loading…
Reference in New Issue
Block a user