We failed to set the secondary return value in %o1 we failed to advance the PC past the syscall, we failed to adjust regwptr into the new structure, we stored the stack pointer into the wrong register.
Signed-off-by: Richard Henderson <richard.hender...@linaro.org> --- linux-user/sparc/target_cpu.h | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/linux-user/sparc/target_cpu.h b/linux-user/sparc/target_cpu.h index 567351d564..bbcb3a92ed 100644 --- a/linux-user/sparc/target_cpu.h +++ b/linux-user/sparc/target_cpu.h @@ -23,18 +23,34 @@ static inline void cpu_clone_regs(CPUSPARCState *env, CPUSPARCState *old_env, target_ulong newsp) { - if (newsp) { - env->regwptr[22] = newsp; - } - /* syscall return for clone child: 0, and clear CF since - * this counts as a success return value. + /* + * After cpu_copy, env->regwptr is pointing into old_env. + * Update the new cpu to use its own register window. */ - env->regwptr[0] = 0; + env->regwptr = env->regbase + (env->cwp * 16); + + /* Set a new stack, if requested. */ + if (newsp) { + env->regwptr[WREG_SP] = newsp; + } + + /* + * Syscall return for clone child: %o0 = 0 and clear CF since + * this counts as a success return value. %o1 = 1 to indicate + * this is the child. Advance the PC past the syscall. + */ + env->regwptr[WREG_O0] = 0; #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) env->xcc &= ~PSR_CARRY; #else env->psr &= ~PSR_CARRY; #endif + env->regwptr[WREG_O1] = 1; + env->pc = env->npc; + env->npc = env->npc + 4; + + /* Set the second return value for the parent: %o1 = 0. */ + old_env->regwptr[WREG_O1] = 0; } static inline void cpu_set_tls(CPUSPARCState *env, target_ulong newtls) -- 2.17.1