Signed-off-by: Timothy Edward Baldwin <t.e.baldwi...@members.leeds.ac.uk> --- linux-user/aarch64/syscall.h | 2 ++ linux-user/arm/syscall.h | 2 ++ linux-user/main.c | 47 +++++++++++++++++++++++++++----------------- linux-user/signal.c | 10 +++++----- 4 files changed, 38 insertions(+), 23 deletions(-)
diff --git a/linux-user/aarch64/syscall.h b/linux-user/aarch64/syscall.h index dc72a15..bc1f01b 100644 --- a/linux-user/aarch64/syscall.h +++ b/linux-user/aarch64/syscall.h @@ -11,3 +11,5 @@ struct target_pt_regs { #define TARGET_MINSIGSTKSZ 2048 #define TARGET_MLOCKALL_MCL_CURRENT 1 #define TARGET_MLOCKALL_MCL_FUTURE 2 + +#define TARGET_USE_ERESTARTSYS 1 diff --git a/linux-user/arm/syscall.h b/linux-user/arm/syscall.h index 3844a96..38c925a 100644 --- a/linux-user/arm/syscall.h +++ b/linux-user/arm/syscall.h @@ -48,3 +48,5 @@ struct target_pt_regs { #define TARGET_MINSIGSTKSZ 2048 #define TARGET_MLOCKALL_MCL_CURRENT 1 #define TARGET_MLOCKALL_MCL_FUTURE 2 + +#define TARGET_USE_ERESTARTSYS 1 diff --git a/linux-user/main.c b/linux-user/main.c index 99fe591..9653155 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -820,15 +820,20 @@ void cpu_loop(CPUARMState *env) break; } } else { - env->regs[0] = do_syscall(env, - n, - env->regs[0], - env->regs[1], - env->regs[2], - env->regs[3], - env->regs[4], - env->regs[5], - 0, 0); + abi_ulong ret = do_syscall(env, + n, + env->regs[0], + env->regs[1], + env->regs[2], + env->regs[3], + env->regs[4], + env->regs[5], + 0, 0); + if (ret == -TARGET_ERESTARTSYS) { + env->regs[15] -= env->thumb ? 2 : 4; + } else if (ret != -TARGET_QEMU_ESIGRETURN) { + env->regs[0] = ret; + } } } else { goto error; @@ -1010,6 +1015,7 @@ void cpu_loop(CPUARMState *env) { CPUState *cs = CPU(arm_env_get_cpu(env)); int trapnr, sig; + abi_long ret; target_siginfo_t info; for (;;) { @@ -1019,15 +1025,20 @@ void cpu_loop(CPUARMState *env) switch (trapnr) { case EXCP_SWI: - env->xregs[0] = do_syscall(env, - env->xregs[8], - env->xregs[0], - env->xregs[1], - env->xregs[2], - env->xregs[3], - env->xregs[4], - env->xregs[5], - 0, 0); + ret = do_syscall(env, + env->xregs[8], + env->xregs[0], + env->xregs[1], + env->xregs[2], + env->xregs[3], + env->xregs[4], + env->xregs[5], + 0, 0); + if (ret == -TARGET_ERESTARTSYS) { + env->pc -= 4; + } else if (ret != -TARGET_QEMU_ESIGRETURN) { + env->xregs[0] = ret; + } break; case EXCP_INTERRUPT: /* just indicate that signals should be handled asap */ diff --git a/linux-user/signal.c b/linux-user/signal.c index 0186147..c8f288b 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -1402,7 +1402,7 @@ long do_rt_sigreturn(CPUARMState *env) } unlock_user_struct(frame, frame_addr, 0); - return env->xregs[0]; + return -TARGET_QEMU_ESIGRETURN; badframe: unlock_user_struct(frame, frame_addr, 0); @@ -1908,7 +1908,7 @@ static long do_sigreturn_v1(CPUARMState *env) send_sig(SIGTRAP, current, 1); #endif unlock_user_struct(frame, frame_addr, 0); - return env->regs[0]; + return -TARGET_QEMU_ESIGRETURN; badframe: force_sig(TARGET_SIGSEGV /* , current */); @@ -2033,7 +2033,7 @@ static long do_sigreturn_v2(CPUARMState *env) } unlock_user_struct(frame, frame_addr, 0); - return env->regs[0]; + return -TARGET_QEMU_ESIGRETURN; badframe: unlock_user_struct(frame, frame_addr, 0); @@ -2086,7 +2086,7 @@ static long do_rt_sigreturn_v1(CPUARMState *env) send_sig(SIGTRAP, current, 1); #endif unlock_user_struct(frame, frame_addr, 0); - return env->regs[0]; + return -TARGET_QEMU_ESIGRETURN; badframe: unlock_user_struct(frame, frame_addr, 0); @@ -2118,7 +2118,7 @@ static long do_rt_sigreturn_v2(CPUARMState *env) } unlock_user_struct(frame, frame_addr, 0); - return env->regs[0]; + return -TARGET_QEMU_ESIGRETURN; badframe: unlock_user_struct(frame, frame_addr, 0); -- 2.1.4