diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 0c5f0a2ae9..3c39e9f82c 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -2744,64 +2744,8 @@ int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp) first_task_state = ts; /* we create a new CPU instance. */ new_env = cpu_copy(env); -#if defined(TARGET_I386) - if (!newsp) - newsp = env->regs[R_ESP]; - new_env->regs[R_ESP] = newsp; - new_env->regs[R_EAX] = 0; -#elif defined(TARGET_ARM) - if (!newsp) - newsp = env->regs[13]; - new_env->regs[13] = newsp; - new_env->regs[0] = 0; -#elif defined(TARGET_SPARC) - if (!newsp) - newsp = env->regwptr[22]; - new_env->regwptr[22] = newsp; - new_env->regwptr[0] = 0; - /* XXXXX */ - printf ("HELPME: %s:%d\n", __FILE__, __LINE__); -#elif defined(TARGET_M68K) - if (!newsp) - newsp = env->aregs[7]; - new_env->aregs[7] = newsp; - new_env->dregs[0] = 0; - /* ??? is this sufficient? */ -#elif defined(TARGET_MIPS) - if (!newsp) - newsp = env->gpr[env->current_tc][29]; - new_env->gpr[env->current_tc][29] = newsp; -#elif defined(TARGET_PPC) - if (!newsp) - newsp = env->gpr[1]; - new_env->gpr[1] = newsp; - { - int i; - for (i = 7; i < 32; i++) - new_env->gpr[i] = 0; - } -#elif defined(TARGET_SH4) - if (!newsp) - newsp = env->gregs[15]; - new_env->gregs[15] = newsp; - /* XXXXX */ -#elif defined(TARGET_ALPHA) - if (!newsp) - newsp = env->ir[30]; - new_env->ir[30] = newsp; - /* ? */ - { - int i; - for (i = 7; i < 30; i++) - new_env->ir[i] = 0; - } -#elif defined(TARGET_CRIS) - if (!newsp) - newsp = env->regs[14]; - new_env->regs[14] = newsp; -#else -#error unsupported target CPU -#endif + /* Init regs that differ from the parent. */ + cpu_clone_regs(new_env, newsp); new_env->opaque = ts; #ifdef __ia64__ ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env); @@ -2813,6 +2757,9 @@ int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp) if ((flags & ~CSIGNAL) != 0) return -EINVAL; ret = fork(); + if (ret == 0) { + cpu_clone_regs(env, newsp); + } } return ret; } diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h index c955997fce..0c1b580f97 100644 --- a/target-alpha/cpu.h +++ b/target-alpha/cpu.h @@ -311,6 +311,15 @@ static inline int cpu_mmu_index (CPUState *env) return (env->ps >> 3) & 3; } +#if defined(CONFIG_USER_ONLY) +static inline void cpu_clone_regs(CPUState *env, target_ulong newsp) +{ + if (!newsp) + env->ir[30] = newsp; + /* FIXME: Zero syscall return value. */ +} +#endif + #include "cpu-all.h" enum { diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 1042808665..1c51d2df40 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -408,6 +408,15 @@ static inline int cpu_mmu_index (CPUState *env) return (env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR ? 1 : 0; } +#if defined(CONFIG_USER_ONLY) +static inline void cpu_clone_regs(CPUState *env, target_ulong newsp) +{ + if (!newsp) + env->regs[13] = newsp; + env->regs[0] = 0; +} +#endif + #include "cpu-all.h" #endif diff --git a/target-cris/cpu.h b/target-cris/cpu.h index 14b09d8cb6..ea86bf9024 100644 --- a/target-cris/cpu.h +++ b/target-cris/cpu.h @@ -218,6 +218,15 @@ static inline int cpu_mmu_index (CPUState *env) return !!(env->pregs[PR_CCS] & U_FLAG); } +#if defined(CONFIG_USER_ONLY) +static inline void cpu_clone_regs(CPUState *env, target_ulong newsp) +{ + if (!newsp) + env->regs[14] = newsp; + env->regs[10] = 0; +} +#endif + /* Support function regs. */ #define SFR_RW_GC_CFG 0][0 #define SFR_RW_MM_CFG env->pregs[PR_SRS]][0 diff --git a/target-i386/cpu.h b/target-i386/cpu.h index eb0052786c..7d4551e765 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -734,6 +734,15 @@ typedef struct CCTable { extern CCTable cc_table[]; +#if defined(CONFIG_USER_ONLY) +static inline void cpu_clone_regs(CPUState *env, target_ulong newsp) +{ + if (!newsp) + env->regs[R_ESP] = newsp; + env->regs[R_EAX] = 0; +} +#endif + #include "cpu-all.h" #include "svm.h" diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h index d5c5a10556..76914525f6 100644 --- a/target-m68k/cpu.h +++ b/target-m68k/cpu.h @@ -226,6 +226,15 @@ static inline int cpu_mmu_index (CPUState *env) return (env->sr & SR_S) == 0 ? 1 : 0; } +#if defined(CONFIG_USER_ONLY) +static inline void cpu_clone_regs(CPUState *env, target_ulong newsp) +{ + if (!newsp) + env->aregs[7] = newsp; + env->dregs[0] = 0; +} +#endif + #include "cpu-all.h" #endif diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 9295b531d6..f9fcafbb1f 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -500,6 +500,16 @@ static inline int cpu_mmu_index (CPUState *env) return env->hflags & MIPS_HFLAG_KSU; } +#if defined(CONFIG_USER_ONLY) +static inline void cpu_clone_regs(CPUState *env, target_ulong newsp) +{ + if (!newsp) + env->gpr[env->current_tc][29] = newsp; + env->gpr[env->current_tc][7] = 0; + env->gpr[env->current_tc][2] = 0; +} +#endif + #include "cpu-all.h" /* Memory access type : diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index a884fd6333..06dc083909 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -822,6 +822,17 @@ static inline int cpu_mmu_index (CPUState *env) return env->mmu_idx; } +#if defined(CONFIG_USER_ONLY) +static inline void cpu_clone_regs(CPUState *env, target_ulong newsp) +{ + int i; + if (!newsp) + env->gpr[1] = newsp; + for (i = 7; i < 32; i++) + env->gpr[i] = 0; +} +#endif + #include "cpu-all.h" /*****************************************************************************/ diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h index c03cdb188c..9294b94e3f 100644 --- a/target-sh4/cpu.h +++ b/target-sh4/cpu.h @@ -143,6 +143,15 @@ static inline int cpu_mmu_index (CPUState *env) return (env->sr & SR_MD) == 0 ? 1 : 0; } +#if defined(CONFIG_USER_ONLY) +static inline void cpu_clone_regs(CPUState *env, target_ulong newsp) +{ + if (!newsp) + env->gregs[15] = newsp; + env->gregs[0] = 0; +} +#endif + #include "cpu-all.h" /* Memory access type */ diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index 539fd2d264..54807fb021 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -403,6 +403,18 @@ static inline int cpu_fpu_enabled(CPUState *env1) #endif } +#if defined(CONFIG_USER_ONLY) +static inline void cpu_clone_regs(CPUState *env, target_ulong newsp) +{ + if (!newsp) + env->regwptr[22] = newsp; + env->regwptr[0] = 0; + /* FIXME: Do we also need to clear CF? */ + /* XXXXX */ + printf ("HELPME: %s:%d\n", __FILE__, __LINE__); +} +#endif + #include "cpu-all.h" #endif