HID is a per-core shared register, skiboot sets this (e.g., setting
HILE) on one thread and that must affect all threads of the core.
Tested-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
target/ppc/cpu_init.c | 2 +-
target/ppc/helper.h | 1 +
target/ppc/misc_helper.c | 21 +++++++++++++++++++++
target/ppc/spr_common.h | 1 +
target/ppc/translate.c | 16 ++++++++++++++++
5 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 905a59aea9..720aad9e05 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -5638,7 +5638,7 @@ static void register_power_common_book4_sprs(CPUPPCState *env)
spr_register_hv(env, SPR_HID0, "HID0",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
+ &spr_read_generic, &spr_core_write_generic,
0x00000000);
spr_register_hv(env, SPR_TSCR, "TSCR",
SPR_NOACCESS, SPR_NOACCESS,
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 828f7844c8..abec6fe341 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -704,6 +704,7 @@ 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_core_write_generic, void, env, i32, tl)
DEF_HELPER_3(spr_write_CTRL, void, env, i32, tl)
DEF_HELPER_4(fscr_facility_check, void, env, i32, i32, i32)
diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c
index 1f1af21f33..0da335472e 100644
--- a/target/ppc/misc_helper.c
+++ b/target/ppc/misc_helper.c
@@ -43,6 +43,27 @@ void helper_store_dump_spr(CPUPPCState *env, uint32_t sprn)
env->spr[sprn]);
}
+void helper_spr_core_write_generic(CPUPPCState *env, uint32_t sprn,
+ target_ulong val)
+{
+ CPUState *cs = env_cpu(env);
+ CPUState *ccs;
+ uint32_t nr_threads = cs->nr_threads;
+ uint32_t core_id = env->spr[SPR_PIR] & ~(nr_threads - 1);
+
+ assert(core_id == env->spr[SPR_PIR] - env->spr[SPR_TIR]);
+
+ if (nr_threads == 1) {
+ env->spr[sprn] = val;
+ return;
+ }
+
+ THREAD_SIBLING_FOREACH(cs, ccs) {
+ CPUPPCState *cenv = &POWERPC_CPU(ccs)->env;
+ cenv->spr[sprn] = val;
+ }
+}
+
void helper_spr_write_CTRL(CPUPPCState *env, uint32_t sprn,
target_ulong val)
{
diff --git a/target/ppc/spr_common.h b/target/ppc/spr_common.h
index fbf52123b5..5995070eaf 100644
--- a/target/ppc/spr_common.h
+++ b/target/ppc/spr_common.h
@@ -82,6 +82,7 @@ void spr_noaccess(DisasContext *ctx, int gprn, int sprn);
void spr_read_generic(DisasContext *ctx, int gprn, int sprn);
void spr_write_generic(DisasContext *ctx, int sprn, int gprn);
void spr_write_generic32(DisasContext *ctx, int sprn, int gprn);
+void spr_core_write_generic(DisasContext *ctx, int sprn, int gprn);
void spr_write_MMCR0(DisasContext *ctx, int sprn, int gprn);
void spr_write_MMCR1(DisasContext *ctx, int sprn, int gprn);
void spr_write_PMC(DisasContext *ctx, int sprn, int gprn);
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 10598cde40..07c491df62 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -448,6 +448,22 @@ void spr_write_generic32(DisasContext *ctx, int sprn, int gprn)
#endif
}
+void spr_core_write_generic(DisasContext *ctx, int sprn, int gprn)
+{
+ if (!(ctx->flags & POWERPC_FLAG_SMT)) {
+ spr_write_generic(ctx, sprn, gprn);
+ return;
+ }
+
+ if (!gen_serialize(ctx)) {
+ return;
+ }
+
+ gen_helper_spr_core_write_generic(cpu_env, tcg_constant_i32(sprn),
+ cpu_gpr[gprn]);
+ spr_store_dump_spr(sprn);
+}
+
static void spr_write_CTRL_ST(DisasContext *ctx, int sprn, int gprn)
{
/* This does not implement >1 thread */
--
2.40.1
On 7/3/23 12:16, Nicholas Piggin wrote:
> HID is a per-core shared register, skiboot sets this (e.g., setting
> HILE) on one thread and that must affect all threads of the core.
>
> Tested-by: Cédric Le Goater <clg@kaod.org>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Thanks,
C.
> ---
> target/ppc/cpu_init.c | 2 +-
> target/ppc/helper.h | 1 +
> target/ppc/misc_helper.c | 21 +++++++++++++++++++++
> target/ppc/spr_common.h | 1 +
> target/ppc/translate.c | 16 ++++++++++++++++
> 5 files changed, 40 insertions(+), 1 deletion(-)
>
> diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
> index 905a59aea9..720aad9e05 100644
> --- a/target/ppc/cpu_init.c
> +++ b/target/ppc/cpu_init.c
> @@ -5638,7 +5638,7 @@ static void register_power_common_book4_sprs(CPUPPCState *env)
> spr_register_hv(env, SPR_HID0, "HID0",
> SPR_NOACCESS, SPR_NOACCESS,
> SPR_NOACCESS, SPR_NOACCESS,
> - &spr_read_generic, &spr_write_generic,
> + &spr_read_generic, &spr_core_write_generic,
> 0x00000000);
> spr_register_hv(env, SPR_TSCR, "TSCR",
> SPR_NOACCESS, SPR_NOACCESS,
> diff --git a/target/ppc/helper.h b/target/ppc/helper.h
> index 828f7844c8..abec6fe341 100644
> --- a/target/ppc/helper.h
> +++ b/target/ppc/helper.h
> @@ -704,6 +704,7 @@ 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_core_write_generic, void, env, i32, tl)
> DEF_HELPER_3(spr_write_CTRL, void, env, i32, tl)
>
> DEF_HELPER_4(fscr_facility_check, void, env, i32, i32, i32)
> diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c
> index 1f1af21f33..0da335472e 100644
> --- a/target/ppc/misc_helper.c
> +++ b/target/ppc/misc_helper.c
> @@ -43,6 +43,27 @@ void helper_store_dump_spr(CPUPPCState *env, uint32_t sprn)
> env->spr[sprn]);
> }
>
> +void helper_spr_core_write_generic(CPUPPCState *env, uint32_t sprn,
> + target_ulong val)
> +{
> + CPUState *cs = env_cpu(env);
> + CPUState *ccs;
> + uint32_t nr_threads = cs->nr_threads;
> + uint32_t core_id = env->spr[SPR_PIR] & ~(nr_threads - 1);
> +
> + assert(core_id == env->spr[SPR_PIR] - env->spr[SPR_TIR]);
> +
> + if (nr_threads == 1) {
> + env->spr[sprn] = val;
> + return;
> + }
> +
> + THREAD_SIBLING_FOREACH(cs, ccs) {
> + CPUPPCState *cenv = &POWERPC_CPU(ccs)->env;
> + cenv->spr[sprn] = val;
> + }
> +}
> +
> void helper_spr_write_CTRL(CPUPPCState *env, uint32_t sprn,
> target_ulong val)
> {
> diff --git a/target/ppc/spr_common.h b/target/ppc/spr_common.h
> index fbf52123b5..5995070eaf 100644
> --- a/target/ppc/spr_common.h
> +++ b/target/ppc/spr_common.h
> @@ -82,6 +82,7 @@ void spr_noaccess(DisasContext *ctx, int gprn, int sprn);
> void spr_read_generic(DisasContext *ctx, int gprn, int sprn);
> void spr_write_generic(DisasContext *ctx, int sprn, int gprn);
> void spr_write_generic32(DisasContext *ctx, int sprn, int gprn);
> +void spr_core_write_generic(DisasContext *ctx, int sprn, int gprn);
> void spr_write_MMCR0(DisasContext *ctx, int sprn, int gprn);
> void spr_write_MMCR1(DisasContext *ctx, int sprn, int gprn);
> void spr_write_PMC(DisasContext *ctx, int sprn, int gprn);
> diff --git a/target/ppc/translate.c b/target/ppc/translate.c
> index 10598cde40..07c491df62 100644
> --- a/target/ppc/translate.c
> +++ b/target/ppc/translate.c
> @@ -448,6 +448,22 @@ void spr_write_generic32(DisasContext *ctx, int sprn, int gprn)
> #endif
> }
>
> +void spr_core_write_generic(DisasContext *ctx, int sprn, int gprn)
> +{
> + if (!(ctx->flags & POWERPC_FLAG_SMT)) {
> + spr_write_generic(ctx, sprn, gprn);
> + return;
> + }
> +
> + if (!gen_serialize(ctx)) {
> + return;
> + }
> +
> + gen_helper_spr_core_write_generic(cpu_env, tcg_constant_i32(sprn),
> + cpu_gpr[gprn]);
> + spr_store_dump_spr(sprn);
> +}
> +
> static void spr_write_CTRL_ST(DisasContext *ctx, int sprn, int gprn)
> {
> /* This does not implement >1 thread */
© 2016 - 2026 Red Hat, Inc.