* [PATCH] target/ppc: Add Power9/10 power management SPRs
@ 2025-03-03 10:15 Nicholas Piggin
0 siblings, 0 replies; only message in thread
From: Nicholas Piggin @ 2025-03-03 10:15 UTC (permalink / raw)
To: qemu-ppc; +Cc: Nicholas Piggin, qemu-devel, Frédéric Barrat
Linux power management code accesses these registers for pstate
management. Wire up a very simple implementation.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
After OCC fixes in QEMU pnv model and skiboot (since they have suffered
some bitrot), Linux will start performing PM SPR accesses. This is a
very simple implementation that makes it a bit happier.
Thanks,
Nick
---
target/ppc/cpu.h | 2 ++
target/ppc/helper.h | 2 ++
target/ppc/spr_common.h | 2 ++
target/ppc/cpu_init.c | 11 +++++++++
target/ppc/misc_helper.c | 53 ++++++++++++++++++++++++++++++++++++++++
target/ppc/translate.c | 16 ++++++++++++
6 files changed, 86 insertions(+)
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index ff527e49b73..4ce812613e2 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -2092,6 +2092,7 @@ void ppc_compat_add_property(Object *obj, const char *name,
#define SPR_VTB (0x351)
#define SPR_LDBAR (0x352)
#define SPR_MMCRC (0x353)
+#define SPR_PMSR (0x355)
#define SPR_PSSCR (0x357)
#define SPR_440_INV0 (0x370)
#define SPR_440_INV1 (0x371)
@@ -2099,6 +2100,7 @@ void ppc_compat_add_property(Object *obj, const char *name,
#define SPR_440_INV2 (0x372)
#define SPR_TRIG2 (0x372)
#define SPR_440_INV3 (0x373)
+#define SPR_PMCR (0x374)
#define SPR_440_ITV0 (0x374)
#define SPR_440_ITV1 (0x375)
#define SPR_440_ITV2 (0x376)
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index e8de4f95581..4d25fa216b8 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -736,6 +736,8 @@ DEF_HELPER_2(store_tfmr, void, env, tl)
DEF_HELPER_FLAGS_2(store_sprc, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_FLAGS_1(load_sprd, TCG_CALL_NO_RWG_SE, tl, env)
DEF_HELPER_FLAGS_2(store_sprd, TCG_CALL_NO_RWG, void, env, tl)
+DEF_HELPER_FLAGS_1(load_pmsr, TCG_CALL_NO_RWG_SE, tl, env)
+DEF_HELPER_FLAGS_2(store_pmcr, TCG_CALL_NO_RWG, void, env, tl)
#endif
DEF_HELPER_2(store_sdr1, void, env, tl)
DEF_HELPER_2(store_pidr, void, env, tl)
diff --git a/target/ppc/spr_common.h b/target/ppc/spr_common.h
index 8cac82b2dac..cfe725a5292 100644
--- a/target/ppc/spr_common.h
+++ b/target/ppc/spr_common.h
@@ -205,6 +205,8 @@ void spr_write_hmer(DisasContext *ctx, int sprn, int gprn);
void spr_read_tfmr(DisasContext *ctx, int gprn, int sprn);
void spr_write_tfmr(DisasContext *ctx, int sprn, int gprn);
void spr_write_lpcr(DisasContext *ctx, int sprn, int gprn);
+void spr_read_pmsr(DisasContext *ctx, int gprn, int sprn);
+void spr_write_pmcr(DisasContext *ctx, int sprn, int gprn);
void spr_read_dexcr_ureg(DisasContext *ctx, int gprn, int sprn);
void spr_read_ppr32(DisasContext *ctx, int sprn, int gprn);
void spr_write_ppr32(DisasContext *ctx, int sprn, int gprn);
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 7d4aad505d7..91c1ca4f9d9 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -6468,6 +6468,17 @@ static void register_power9_common_sprs(CPUPPCState *env)
spr_read_generic, spr_write_generic,
KVM_REG_PPC_PSSCR, 0);
+ spr_register_hv(env, SPR_PMSR, "PMSR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_pmsr, SPR_NOACCESS,
+ 0);
+ spr_register_hv(env, SPR_PMCR, "PMCR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_pmcr,
+ PPC_BIT(63)); /* Version 1 (POWER9/10) */
+
}
static void init_proc_POWER9(CPUPPCState *env)
diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c
index 397bae12fe3..80177143170 100644
--- a/target/ppc/misc_helper.c
+++ b/target/ppc/misc_helper.c
@@ -459,6 +459,59 @@ void helper_store_sprd(CPUPPCState *env, target_ulong val)
break;
}
}
+
+target_ulong helper_load_pmsr(CPUPPCState *env)
+{
+ target_ulong lowerps = extract64(env->spr[SPR_PMCR], PPC_BIT_NR(15), 8);
+ target_ulong val = 0;
+
+ val |= PPC_BIT(63); /* verion 0x1 (POWER9/10) */
+ /* Pmin = 0 */
+ /* XXX: POWER9 should be 3 */
+ val |= 4ULL << PPC_BIT_NR(31); /* Pmax */
+ val |= lowerps << PPC_BIT_NR(15); /* Local actual Pstate */
+ val |= lowerps << PPC_BIT_NR(7); /* Global actual Pstate */
+
+ return val;
+}
+
+static void ppc_set_pmcr(PowerPCCPU *cpu, target_ulong val)
+{
+ cpu->env.spr[SPR_PMCR] = val;
+}
+
+void helper_store_pmcr(CPUPPCState *env, target_ulong val)
+{
+ PowerPCCPU *cpu = env_archcpu(env);
+ CPUState *cs = env_cpu(env);
+ CPUState *ccs;
+
+ /* Leave version field unchanged (0x1) */
+ val &= ~PPC_BITMASK(60, 63);
+ val |= PPC_BIT(63);
+
+ val &= ~PPC_BITMASK(0, 7); /* UpperPS ignored */
+ if (val & PPC_BITMASK(16, 59)) {
+ qemu_log_mask(LOG_GUEST_ERROR, "Non-zero PMCR reserved bits "
+ TARGET_FMT_lx"\n", val);
+ val &= ~PPC_BITMASK(16, 59);
+ }
+
+ /* DPDES behaves as 1-thread in LPAR-per-thread mode */
+ if (ppc_cpu_lpar_single_threaded(cs)) {
+ ppc_set_pmcr(cpu, val);
+ return;
+ }
+
+ /* Does iothread need to be locked for walking CPU list? */
+ bql_lock();
+ THREAD_SIBLING_FOREACH(cs, ccs) {
+ PowerPCCPU *ccpu = POWERPC_CPU(ccs);
+ ppc_set_pmcr(ccpu, val);
+ }
+ bql_unlock();
+}
+
#endif /* defined(TARGET_PPC64) */
void helper_store_pidr(CPUPPCState *env, target_ulong val)
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index c5fe3de64e9..a73afe600de 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -1288,6 +1288,22 @@ void spr_write_lpcr(DisasContext *ctx, int sprn, int gprn)
translator_io_start(&ctx->base);
gen_helper_store_lpcr(tcg_env, cpu_gpr[gprn]);
}
+
+void spr_read_pmsr(DisasContext *ctx, int gprn, int sprn)
+{
+ translator_io_start(&ctx->base);
+ gen_helper_load_pmsr(cpu_gpr[gprn], tcg_env);
+}
+
+void spr_write_pmcr(DisasContext *ctx, int sprn, int gprn)
+{
+ if (!gen_serialize_core_lpar(ctx)) {
+ return;
+ }
+ translator_io_start(&ctx->base);
+ gen_helper_store_pmcr(tcg_env, cpu_gpr[gprn]);
+}
+
#endif /* !defined(CONFIG_USER_ONLY) */
void spr_read_tar(DisasContext *ctx, int gprn, int sprn)
--
2.47.1
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2025-03-03 10:16 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-03 10:15 [PATCH] target/ppc: Add Power9/10 power management SPRs Nicholas Piggin
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.