On Fri, Aug 08, 2014 at 11:56:54AM +0800, Jincheng Miao wrote: > 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.
Thanks applied to linux-user tree for next pull request. Riku > Signed-off-by: Jincheng Miao <jm...@redhat.com> > --- > linux-user/main.c | 1 - > target-i386/seg_helper.c | 4 ++-- > 2 files changed, 2 insertions(+), 3 deletions(-) > > diff --git a/linux-user/main.c b/linux-user/main.c > index b453a39..472a16d 100644 > --- a/linux-user/main.c > +++ b/linux-user/main.c > @@ -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: > diff --git a/target-i386/seg_helper.c b/target-i386/seg_helper.c > index 2d970d0..13eefba 100644 > --- a/target-i386/seg_helper.c > +++ b/target-i386/seg_helper.c > @@ -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; > } > } > -- > 1.7.1 >