]> Git Repo - qemu.git/commitdiff
linux-user: Fix syscall instruction usermode emulation on X86_64
authorJincheng Miao <[email protected]>
Fri, 8 Aug 2014 03:56:54 +0000 (11:56 +0800)
committerRiku Voipio <[email protected]>
Fri, 22 Aug 2014 12:06:33 +0000 (15:06 +0300)
Currently syscall instruction is buggy on user mode X86_64,
the EIP is updated after do_syscall(), that is too late for
clone(). Because clone() will create a thread at the env->EIP
(the address of syscall insn), and then child thread enters
do_syscall() again, that is not expected. Sometimes it is tragic.

User mode syscall insn emulation is not used MSR, so the
action should be same to INT 0x80. INT 0x80 will update EIP in
do_interrupt(), ditto for syscall() for consistency.

Signed-off-by: Jincheng Miao <[email protected]>
Reviewed-by: Richard Henderson <[email protected]>
Signed-off-by: Riku Voipio <[email protected]>
linux-user/main.c
target-i386/seg_helper.c

index b453a39853e1701101d4384ce1a418038432657e..472a16d2db9a9ca42ee2c729f01bfc6a8ab2d653 100644 (file)
@@ -309,7 +309,6 @@ void cpu_loop(CPUX86State *env)
                                           env->regs[8],
                                           env->regs[9],
                                           0, 0);
-            env->eip = env->exception_next_eip;
             break;
 #endif
         case EXCP0B_NOSEG:
index 2d970d0cb9c3f8a6f9eb33a4e813cc5c4974a5cb..13eefbac3b6ca7a46772813264207076e3bf5f77 100644 (file)
@@ -1127,8 +1127,8 @@ static void do_interrupt_user(CPUX86State *env, int intno, int is_int,
 
     /* Since we emulate only user space, we cannot do more than
        exiting the emulation with the suitable exception and error
-       code */
-    if (is_int) {
+       code. So update EIP for INT 0x80 and EXCP_SYSCALL. */
+    if (is_int || intno == EXCP_SYSCALL) {
         env->eip = next_eip;
     }
 }
This page took 0.028355 seconds and 4 git commands to generate.