From patchwork Sat Sep 5 23:56:58 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Timothy Baldwin X-Patchwork-Id: 514863 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id DC9D4140549 for ; Sun, 6 Sep 2015 10:01:10 +1000 (AEST) Received: from localhost ([::1]:43548 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZYNOO-0007ih-M0 for incoming@patchwork.ozlabs.org; Sat, 05 Sep 2015 20:01:08 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55323) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZYNLe-0002x8-1S for qemu-devel@nongnu.org; Sat, 05 Sep 2015 19:58:22 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZYNLc-0005sx-RG for qemu-devel@nongnu.org; Sat, 05 Sep 2015 19:58:17 -0400 Received: from avasout06.plus.net ([212.159.14.18]:39179) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZYNLc-0005sS-IK for qemu-devel@nongnu.org; Sat, 05 Sep 2015 19:58:16 -0400 Received: from bfg ([87.114.133.92]) by avasout06 with smtp id DbyE1r0021zmLPr01byFe0; Sun, 06 Sep 2015 00:58:15 +0100 X-CM-Score: 0.00 X-CNFS-Analysis: v=2.1 cv=E4sw3vpl c=1 sm=1 tr=0 a=wMIFfKY+zwUDgD4aAwecrg==:117 a=wMIFfKY+zwUDgD4aAwecrg==:17 a=0Bzu9jTXAAAA:8 a=FJhpQO9QAAAA:8 a=h_6DSLV0AAAA:8 a=ff-B7xzCdYMA:10 a=j2zMk5SrqVSFv8xCN1oA:9 a=Sk_-zaTS7jx0j4Z_:21 a=AzWK3faStAMqoTj_:21 Received: from tim by bfg with local (Exim 4.84) (envelope-from ) id 1ZYNLa-0008Uv-1q; Sun, 06 Sep 2015 00:58:14 +0100 From: Timothy E Baldwin To: qemu-devel@nongnu.org Date: Sun, 6 Sep 2015 00:56:58 +0100 Message-Id: <1441497448-32489-5-git-send-email-T.E.Baldwin99@members.leeds.ac.uk> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1441497448-32489-1-git-send-email-T.E.Baldwin99@members.leeds.ac.uk> References: <1441497448-32489-1-git-send-email-T.E.Baldwin99@members.leeds.ac.uk> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x (no timestamps) [generic] X-Received-From: 212.159.14.18 Cc: riku.voipio@iki.fi, Timothy E Baldwin Subject: [Qemu-devel] [PATCH 04/34] linux-user: Support for restarting system calls for x86 targets X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Signed-off-by: Timothy Edward Baldwin Reviewed-by: Peter Maydell --- linux-user/i386/syscall.h | 2 ++ linux-user/main.c | 47 ++++++++++++++++++++++++++++----------------- linux-user/signal.c | 15 +++++++-------- linux-user/syscall.c | 2 -- linux-user/x86_64/syscall.h | 2 ++ 5 files changed, 40 insertions(+), 28 deletions(-) diff --git a/linux-user/i386/syscall.h b/linux-user/i386/syscall.h index 906aaac..f7d9fbe 100644 --- a/linux-user/i386/syscall.h +++ b/linux-user/i386/syscall.h @@ -150,3 +150,5 @@ struct target_vm86plus_struct { #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 2c9658e..99fe591 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -274,6 +274,7 @@ void cpu_loop(CPUX86State *env) CPUState *cs = CPU(x86_env_get_cpu(env)); int trapnr; abi_ulong pc; + abi_ulong ret; target_siginfo_t info; for(;;) { @@ -283,28 +284,38 @@ void cpu_loop(CPUX86State *env) switch(trapnr) { case 0x80: /* linux syscall from int $0x80 */ - env->regs[R_EAX] = do_syscall(env, - env->regs[R_EAX], - env->regs[R_EBX], - env->regs[R_ECX], - env->regs[R_EDX], - env->regs[R_ESI], - env->regs[R_EDI], - env->regs[R_EBP], - 0, 0); + ret = do_syscall(env, + env->regs[R_EAX], + env->regs[R_EBX], + env->regs[R_ECX], + env->regs[R_EDX], + env->regs[R_ESI], + env->regs[R_EDI], + env->regs[R_EBP], + 0, 0); + if (ret == -TARGET_ERESTARTSYS) { + env->eip -= 2; + } else if (ret != -TARGET_QEMU_ESIGRETURN) { + env->regs[R_EAX] = ret; + } break; #ifndef TARGET_ABI32 case EXCP_SYSCALL: /* linux syscall from syscall instruction */ - env->regs[R_EAX] = do_syscall(env, - env->regs[R_EAX], - env->regs[R_EDI], - env->regs[R_ESI], - env->regs[R_EDX], - env->regs[10], - env->regs[8], - env->regs[9], - 0, 0); + ret = do_syscall(env, + env->regs[R_EAX], + env->regs[R_EDI], + env->regs[R_ESI], + env->regs[R_EDX], + env->regs[10], + env->regs[8], + env->regs[9], + 0, 0); + if (ret == -TARGET_ERESTARTSYS) { + env->eip -= 2; + } else if (ret != -TARGET_QEMU_ESIGRETURN) { + env->regs[R_EAX] = ret; + } break; #endif case EXCP0B_NOSEG: diff --git a/linux-user/signal.c b/linux-user/signal.c index 7c846c0..0186147 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -1036,7 +1036,7 @@ give_sigsegv: } static int -restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax) +restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc) { unsigned int err = 0; abi_ulong fpstate_addr; @@ -1054,6 +1054,7 @@ restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax) env->regs[R_EBX] = tswapl(sc->ebx); env->regs[R_EDX] = tswapl(sc->edx); env->regs[R_ECX] = tswapl(sc->ecx); + env->regs[R_EAX] = tswapl(sc->eax); env->eip = tswapl(sc->eip); cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3); @@ -1071,7 +1072,6 @@ restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax) cpu_x86_frstor(env, fpstate_addr, 1); } - *peax = tswapl(sc->eax); return err; badframe: return 1; @@ -1083,7 +1083,7 @@ long do_sigreturn(CPUX86State *env) abi_ulong frame_addr = env->regs[R_ESP] - 8; target_sigset_t target_set; sigset_t set; - int eax, i; + int i; #if defined(DEBUG_SIGNAL) fprintf(stderr, "do_sigreturn\n"); @@ -1100,10 +1100,10 @@ long do_sigreturn(CPUX86State *env) do_sigprocmask(SIG_SETMASK, &set, NULL); /* restore registers */ - if (restore_sigcontext(env, &frame->sc, &eax)) + if (restore_sigcontext(env, &frame->sc)) goto badframe; unlock_user_struct(frame, frame_addr, 0); - return eax; + return -TARGET_QEMU_ESIGRETURN; badframe: unlock_user_struct(frame, frame_addr, 0); @@ -1116,7 +1116,6 @@ long do_rt_sigreturn(CPUX86State *env) abi_ulong frame_addr; struct rt_sigframe *frame; sigset_t set; - int eax; frame_addr = env->regs[R_ESP] - 4; if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { @@ -1125,7 +1124,7 @@ long do_rt_sigreturn(CPUX86State *env) target_to_host_sigset(&set, &frame->uc.tuc_sigmask); do_sigprocmask(SIG_SETMASK, &set, NULL); - if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax)) { + if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) { goto badframe; } @@ -1135,7 +1134,7 @@ long do_rt_sigreturn(CPUX86State *env) } unlock_user_struct(frame, frame_addr, 0); - return eax; + return -TARGET_QEMU_ESIGRETURN; badframe: unlock_user_struct(frame, frame_addr, 0); diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 4e40dc6..04c91fb 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -6601,12 +6601,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, break; #ifdef TARGET_NR_sigreturn case TARGET_NR_sigreturn: - /* NOTE: ret is eax, so not transcoding must be done */ ret = do_sigreturn(cpu_env); break; #endif case TARGET_NR_rt_sigreturn: - /* NOTE: ret is eax, so not transcoding must be done */ ret = do_rt_sigreturn(cpu_env); break; case TARGET_NR_sethostname: diff --git a/linux-user/x86_64/syscall.h b/linux-user/x86_64/syscall.h index 88b3c3f..d41a93a 100644 --- a/linux-user/x86_64/syscall.h +++ b/linux-user/x86_64/syscall.h @@ -100,3 +100,5 @@ struct target_msqid64_ds { #define TARGET_MINSIGSTKSZ 2048 #define TARGET_MLOCKALL_MCL_CURRENT 1 #define TARGET_MLOCKALL_MCL_FUTURE 2 + +#define TARGET_USE_ERESTARTSYS 1