linux-user/sparc: Handle tstate in sparc64_get/set_context()

Correctly implement save/restore of the tstate field in
sparc64_get_context() and sparc64_set_context():
 * Don't use the CWP value from the guest in set_context
 * Construct and save a tstate value rather than leaving
   it as zero in get_context

To do this we factor out the "calculate TSTATE value from CPU state"
code from sparc_cpu_do_interrupt() into its own sparc64_tstate()
function; that in turn requires us to move some of the function
prototypes out from inside a CPU_NO_IO_DEFS ifdef guard.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20201106152738.26026-5-peter.maydell@linaro.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
This commit is contained in:
Peter Maydell 2020-11-06 15:27:38 +00:00 committed by Laurent Vivier
parent 0ad20314f1
commit 7a5805a08f
3 changed files with 24 additions and 12 deletions

View File

@ -438,9 +438,9 @@ void sparc64_set_context(CPUSPARCState *env)
env->npc = npc; env->npc = npc;
__get_user(env->y, &((*grp)[SPARC_MC_Y])); __get_user(env->y, &((*grp)[SPARC_MC_Y]));
__get_user(tstate, &((*grp)[SPARC_MC_TSTATE])); __get_user(tstate, &((*grp)[SPARC_MC_TSTATE]));
/* Honour TSTATE_ASI, TSTATE_ICC and TSTATE_XCC only */
env->asi = (tstate >> 24) & 0xff; env->asi = (tstate >> 24) & 0xff;
cpu_put_ccr(env, tstate >> 32); cpu_put_ccr(env, (tstate >> 32) & 0xff);
cpu_put_cwp64(env, tstate & 0x1f);
__get_user(env->gregs[1], (&(*grp)[SPARC_MC_G1])); __get_user(env->gregs[1], (&(*grp)[SPARC_MC_G1]));
__get_user(env->gregs[2], (&(*grp)[SPARC_MC_G2])); __get_user(env->gregs[2], (&(*grp)[SPARC_MC_G2]));
__get_user(env->gregs[3], (&(*grp)[SPARC_MC_G3])); __get_user(env->gregs[3], (&(*grp)[SPARC_MC_G3]));
@ -557,8 +557,7 @@ void sparc64_get_context(CPUSPARCState *env)
} }
} }
/* XXX: tstate must be saved properly */ __put_user(sparc64_tstate(env), &((*grp)[SPARC_MC_TSTATE]));
// __put_user(env->tstate, &((*grp)[SPARC_MC_TSTATE]));
__put_user(env->pc, &((*grp)[SPARC_MC_PC])); __put_user(env->pc, &((*grp)[SPARC_MC_PC]));
__put_user(env->npc, &((*grp)[SPARC_MC_NPC])); __put_user(env->npc, &((*grp)[SPARC_MC_NPC]));
__put_user(env->y, &((*grp)[SPARC_MC_Y])); __put_user(env->y, &((*grp)[SPARC_MC_Y]));

View File

@ -608,10 +608,6 @@ target_ulong cpu_get_psr(CPUSPARCState *env1);
void cpu_put_psr(CPUSPARCState *env1, target_ulong val); void cpu_put_psr(CPUSPARCState *env1, target_ulong val);
void cpu_put_psr_raw(CPUSPARCState *env1, target_ulong val); void cpu_put_psr_raw(CPUSPARCState *env1, target_ulong val);
#ifdef TARGET_SPARC64 #ifdef TARGET_SPARC64
target_ulong cpu_get_ccr(CPUSPARCState *env1);
void cpu_put_ccr(CPUSPARCState *env1, target_ulong val);
target_ulong cpu_get_cwp64(CPUSPARCState *env1);
void cpu_put_cwp64(CPUSPARCState *env1, int cwp);
void cpu_change_pstate(CPUSPARCState *env1, uint32_t new_pstate); void cpu_change_pstate(CPUSPARCState *env1, uint32_t new_pstate);
void cpu_gl_switch_gregs(CPUSPARCState *env, uint32_t new_gl); void cpu_gl_switch_gregs(CPUSPARCState *env, uint32_t new_gl);
#endif #endif
@ -829,4 +825,24 @@ static inline bool tb_am_enabled(int tb_flags)
#endif #endif
} }
#ifdef TARGET_SPARC64
/* win_helper.c */
target_ulong cpu_get_ccr(CPUSPARCState *env1);
void cpu_put_ccr(CPUSPARCState *env1, target_ulong val);
target_ulong cpu_get_cwp64(CPUSPARCState *env1);
void cpu_put_cwp64(CPUSPARCState *env1, int cwp);
static inline uint64_t sparc64_tstate(CPUSPARCState *env)
{
uint64_t tstate = (cpu_get_ccr(env) << 32) |
((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
cpu_get_cwp64(env);
if (env->def.features & CPU_FEATURE_GL) {
tstate |= (env->gl & 7ULL) << 40;
}
return tstate;
}
#endif
#endif #endif

View File

@ -131,9 +131,7 @@ void sparc_cpu_do_interrupt(CPUState *cs)
} }
tsptr = cpu_tsptr(env); tsptr = cpu_tsptr(env);
tsptr->tstate = (cpu_get_ccr(env) << 32) | tsptr->tstate = sparc64_tstate(env);
((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
cpu_get_cwp64(env);
tsptr->tpc = env->pc; tsptr->tpc = env->pc;
tsptr->tnpc = env->npc; tsptr->tnpc = env->npc;
tsptr->tt = intno; tsptr->tt = intno;
@ -148,7 +146,6 @@ void sparc_cpu_do_interrupt(CPUState *cs)
} }
if (env->def.features & CPU_FEATURE_GL) { if (env->def.features & CPU_FEATURE_GL) {
tsptr->tstate |= (env->gl & 7ULL) << 40;
cpu_gl_switch_gregs(env, env->gl + 1); cpu_gl_switch_gregs(env, env->gl + 1);
env->gl++; env->gl++;
} }