target/ppc: Add support for SMT CTRL register

A relatively simple case to begin with, CTRL is a SMT shared register
where reads and writes need to synchronise against state changes by
other threads in the core.

Atomic serialisation operations are used to achieve this.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
This commit is contained in:
Nicholas Piggin 2023-06-22 19:33:52 +10:00 committed by Cédric Le Goater
parent b769d4c8f4
commit c5d98a7b3d
3 changed files with 44 additions and 1 deletions

View File

@ -704,6 +704,8 @@ DEF_HELPER_3(store_dcr, void, env, tl, tl)
DEF_HELPER_2(load_dump_spr, void, env, i32)
DEF_HELPER_2(store_dump_spr, void, env, i32)
DEF_HELPER_3(spr_write_CTRL, void, env, i32, tl)
DEF_HELPER_4(fscr_facility_check, void, env, i32, i32, i32)
DEF_HELPER_4(msr_facility_check, void, env, i32, i32, i32)
DEF_HELPER_FLAGS_1(load_tbl, TCG_CALL_NO_RWG, tl, env)

View File

@ -43,6 +43,31 @@ void helper_store_dump_spr(CPUPPCState *env, uint32_t sprn)
env->spr[sprn]);
}
void helper_spr_write_CTRL(CPUPPCState *env, uint32_t sprn,
target_ulong val)
{
CPUState *cs = env_cpu(env);
CPUState *ccs;
uint32_t run = val & 1;
uint32_t ts, ts_mask;
assert(sprn == SPR_CTRL);
env->spr[sprn] &= ~1U;
env->spr[sprn] |= run;
ts_mask = ~(1U << (8 + env->spr[SPR_TIR]));
ts = run << (8 + env->spr[SPR_TIR]);
THREAD_SIBLING_FOREACH(cs, ccs) {
CPUPPCState *cenv = &POWERPC_CPU(ccs)->env;
cenv->spr[sprn] &= ts_mask;
cenv->spr[sprn] |= ts;
}
}
#ifdef TARGET_PPC64
static void raise_hv_fu_exception(CPUPPCState *env, uint32_t bit,
const char *caller, uint32_t cause,

View File

@ -438,7 +438,7 @@ void spr_write_generic32(DisasContext *ctx, int sprn, int gprn)
#endif
}
void spr_write_CTRL(DisasContext *ctx, int sprn, int gprn)
static void spr_write_CTRL_ST(DisasContext *ctx, int sprn, int gprn)
{
/* This does not implement >1 thread */
TCGv t0 = tcg_temp_new();
@ -447,6 +447,22 @@ void spr_write_CTRL(DisasContext *ctx, int sprn, int gprn)
tcg_gen_shli_tl(t1, t0, 8); /* Duplicate the bit in TS */
tcg_gen_or_tl(t1, t1, t0);
gen_store_spr(sprn, t1);
}
void spr_write_CTRL(DisasContext *ctx, int sprn, int gprn)
{
if (!(ctx->flags & POWERPC_FLAG_SMT)) {
spr_write_CTRL_ST(ctx, sprn, gprn);
goto out;
}
if (!gen_serialize(ctx)) {
return;
}
gen_helper_spr_write_CTRL(cpu_env, tcg_constant_i32(sprn),
cpu_gpr[gprn]);
out:
spr_store_dump_spr(sprn);
/*