diff options
-rw-r--r-- | linux-user/arm/target_signal.h | 1 | ||||
-rw-r--r-- | linux-user/main.c | 48 | ||||
-rw-r--r-- | linux-user/signal.c | 10 |
3 files changed, 36 insertions, 23 deletions
diff --git a/linux-user/arm/target_signal.h b/linux-user/arm/target_signal.h index 2b3281312b..fb31f4c5ec 100644 --- a/linux-user/arm/target_signal.h +++ b/linux-user/arm/target_signal.h @@ -26,4 +26,5 @@ static inline abi_ulong get_sp_from_cpustate(CPUARMState *state) return state->regs[13]; } + #endif /* TARGET_SIGNAL_H */ diff --git a/linux-user/main.c b/linux-user/main.c index da5a0333b6..7916efc0e2 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -727,6 +727,7 @@ void cpu_loop(CPUARMState *env) unsigned int n, insn; target_siginfo_t info; uint32_t addr; + abi_ulong ret; for(;;) { cpu_exec_start(cs); @@ -865,15 +866,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); + 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; @@ -1056,6 +1062,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 (;;) { @@ -1065,15 +1072,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 11ddd05173..14e58b05b2 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -1390,7 +1390,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); @@ -1902,7 +1902,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 */); @@ -2028,7 +2028,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); @@ -2082,7 +2082,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); @@ -2115,7 +2115,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); |