Index: sys/amd64/amd64/vm_machdep.c =================================================================== --- sys/amd64/amd64/vm_machdep.c +++ sys/amd64/amd64/vm_machdep.c @@ -245,9 +245,12 @@ td2->td_frame = (struct trapframe *)td2->td_md.md_stack_base - 1; bcopy(td1->td_frame, td2->td_frame, sizeof(struct trapframe)); - td2->td_frame->tf_rax = 0; /* Child returns zero */ - td2->td_frame->tf_rflags &= ~PSL_C; /* success */ - td2->td_frame->tf_rdx = 1; + if (__predict_true(p2->p_sysent->sv_cpu_fork == NULL)) { + td2->td_frame->tf_rax = 0; /* Child returns zero */ + td2->td_frame->tf_rflags &= ~PSL_C; /* success */ + td2->td_frame->tf_rdx = 1; /* System V emulation */ + } else + p2->p_sysent->sv_cpu_fork(td2); /* * If the parent process has the trap bit set (i.e. a debugger Index: sys/amd64/linux/linux_sysvec.c =================================================================== --- sys/amd64/linux/linux_sysvec.c +++ sys/amd64/linux/linux_sysvec.c @@ -112,6 +112,7 @@ static int linux_copyout_strings(struct image_params *imgp, uintptr_t *stack_base); +static void linux_cpu_fork(struct thread *td); static int linux_fixup_elf(uintptr_t *stack_base, struct image_params *iparams); static bool linux_trans_osrel(const Elf_Note *note, int32_t *osrel); @@ -269,6 +270,14 @@ set_pcb_flags(td->td_pcb, PCB_FULL_IRET); } +static void +linux_cpu_fork(struct thread *td) +{ + struct trapframe *frame = td->td_frame; + + frame->tf_rax = 0; +} + static int linux_copyout_auxargs(struct image_params *imgp, uintptr_t base) { @@ -790,6 +799,7 @@ .sv_onexit = linux_on_exit, .sv_ontdexit = linux_thread_dtor, .sv_setid_allowed = &linux_setid_allowed_query, + .sv_cpu_fork = linux_cpu_fork, }; static int Index: sys/amd64/linux32/linux32_sysvec.c =================================================================== --- sys/amd64/linux32/linux32_sysvec.c +++ sys/amd64/linux32/linux32_sysvec.c @@ -117,6 +117,7 @@ struct image_params *iparams); static int linux_copyout_strings(struct image_params *imgp, uintptr_t *stack_base); +static void linux32_cpu_fork(struct thread *td); static void linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask); static void linux_exec_setregs(struct thread *td, struct image_params *imgp, uintptr_t stack); @@ -703,6 +704,14 @@ } } +static void +linux32_cpu_fork(struct thread *td) +{ + struct trapframe *frame = td->td_frame; + + frame->tf_rax = 0; +} + /* * Clear registers on exec * XXX copied from ia32_signal.c. @@ -956,6 +965,7 @@ .sv_onexit = linux_on_exit, .sv_ontdexit = linux_thread_dtor, .sv_setid_allowed = &linux_setid_allowed_query, + .sv_cpu_fork = linux32_cpu_fork, }; static int Index: sys/i386/i386/vm_machdep.c =================================================================== --- sys/i386/i386/vm_machdep.c +++ sys/i386/i386/vm_machdep.c @@ -258,9 +258,12 @@ VM86_STACK_SPACE) - 1; bcopy(td1->td_frame, td2->td_frame, sizeof(struct trapframe)); - td2->td_frame->tf_eax = 0; /* Child returns zero */ - td2->td_frame->tf_eflags &= ~PSL_C; /* success */ - td2->td_frame->tf_edx = 1; + if (__predict_true(p2->p_sysent->sv_cpu_fork == NULL)) + td2->td_frame->tf_eax = 0; /* Child returns zero */ + td2->td_frame->tf_eflags &= ~PSL_C; /* success */ + td2->td_frame->tf_edx = 1; /* System V emulation */ + } else + p2->p_sysent->sv_cpu_fork(td2); /* * If the parent process has the trap bit set (i.e. a debugger Index: sys/i386/linux/linux_sysvec.c =================================================================== --- sys/i386/linux/linux_sysvec.c +++ sys/i386/linux/linux_sysvec.c @@ -96,6 +96,7 @@ SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler); +static void linux_cpu_fork(struct thread *td); static int linux_fixup(uintptr_t *stack_base, struct image_params *iparams); static int linux_fixup_elf(uintptr_t *stack_base, @@ -803,6 +804,14 @@ } } +static void +linux_cpu_fork(struct thread *td) +{ + struct trapframe *frame = td->td_frame; + + frame->tf_eax = 0; +} + /* * exec_setregs may initialize some registers differently than Linux * does, thus potentially confusing Linux binaries. If necessary, we @@ -856,6 +865,7 @@ .sv_onexit = linux_on_exit, .sv_ontdexit = linux_thread_dtor, .sv_setid_allowed = &linux_setid_allowed_query, + .sv_cpu_fork = linux_cpu_fork, }; INIT_SYSENTVEC(aout_sysvec, &linux_sysvec); @@ -898,6 +908,7 @@ .sv_onexit = linux_on_exit, .sv_ontdexit = linux_thread_dtor, .sv_setid_allowed = &linux_setid_allowed_query, + .sv_cpu_fork = linux_cpu_fork, }; static int Index: sys/sys/sysent.h =================================================================== --- sys/sys/sysent.h +++ sys/sys/sysent.h @@ -156,6 +156,7 @@ void (*sv_ontdexit)(struct thread *td); int (*sv_setid_allowed)(struct thread *td, struct image_params *imgp); + void (*sv_cpu_fork)(struct thread *); }; #define SV_ILP32 0x000100 /* 32-bit executable. */