From: Daniel Henrique Barboza <danielhb413@gmail.com>
To: qemu-devel@nongnu.org
Cc: qemu-ppc@nongnu.org, danielhb413@gmail.com,
peter.maydell@linaro.org, richard.henderson@linaro.org,
Nicholas Piggin <npiggin@gmail.com>
Subject: [PULL 08/29] target/ppc: Fix PMU hflags calculation
Date: Sat, 10 Jun 2023 10:31:11 -0300 [thread overview]
Message-ID: <20230610133132.290703-9-danielhb413@gmail.com> (raw)
In-Reply-To: <20230610133132.290703-1-danielhb413@gmail.com>
From: Nicholas Piggin <npiggin@gmail.com>
Some of the PMU hflags bits can go out of synch, for example a store to
MMCR0 with PMCjCE=1 fails to update hflags correctly and results in
hflags mismatch:
qemu: fatal: TCG hflags mismatch (current:0x2408003d rebuilt:0x240a003d)
This can be reproduced by running perf on a recent machine.
Some of the fragility here is the duplication of PMU hflags calculations.
This change consolidates that in a single place to update pmu-related
hflags, to be called after a well defined state changes.
The post-load PMU update is pulled out of the MSR update because it does
not depend on the MSR value.
Fixes: 8b3d1c49a9f0 ("target/ppc: Add new PMC HFLAGS")
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
Message-Id: <20230530130447.372617-1-npiggin@gmail.com>
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
---
target/ppc/cpu_init.c | 2 +-
target/ppc/helper_regs.c | 73 ++++++++++++++++++++++++++++++----------
target/ppc/helper_regs.h | 1 +
target/ppc/machine.c | 8 ++---
target/ppc/power8-pmu.c | 38 ++++++++++++---------
target/ppc/power8-pmu.h | 4 +--
6 files changed, 85 insertions(+), 41 deletions(-)
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 05bf73296b..398f2d9966 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -7083,7 +7083,7 @@ static void ppc_cpu_reset_hold(Object *obj)
if (env->mmu_model != POWERPC_MMU_REAL) {
ppc_tlb_invalidate_all(env);
}
- pmu_update_summaries(env);
+ pmu_mmcr01_updated(env);
}
/* clean any pending stop state */
diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c
index fb351c303f..bc7e9d7eda 100644
--- a/target/ppc/helper_regs.c
+++ b/target/ppc/helper_regs.c
@@ -47,6 +47,48 @@ void hreg_swap_gpr_tgpr(CPUPPCState *env)
env->tgpr[3] = tmp;
}
+static uint32_t hreg_compute_pmu_hflags_value(CPUPPCState *env)
+{
+ uint32_t hflags = 0;
+
+#if defined(TARGET_PPC64)
+ if (env->spr[SPR_POWER_MMCR0] & MMCR0_PMCC0) {
+ hflags |= 1 << HFLAGS_PMCC0;
+ }
+ if (env->spr[SPR_POWER_MMCR0] & MMCR0_PMCC1) {
+ hflags |= 1 << HFLAGS_PMCC1;
+ }
+ if (env->spr[SPR_POWER_MMCR0] & MMCR0_PMCjCE) {
+ hflags |= 1 << HFLAGS_PMCJCE;
+ }
+
+#ifndef CONFIG_USER_ONLY
+ if (env->pmc_ins_cnt) {
+ hflags |= 1 << HFLAGS_INSN_CNT;
+ }
+ if (env->pmc_ins_cnt & 0x1e) {
+ hflags |= 1 << HFLAGS_PMC_OTHER;
+ }
+#endif
+#endif
+
+ return hflags;
+}
+
+/* Mask of all PMU hflags */
+static uint32_t hreg_compute_pmu_hflags_mask(CPUPPCState *env)
+{
+ uint32_t hflags_mask = 0;
+#if defined(TARGET_PPC64)
+ hflags_mask |= 1 << HFLAGS_PMCC0;
+ hflags_mask |= 1 << HFLAGS_PMCC1;
+ hflags_mask |= 1 << HFLAGS_PMCJCE;
+ hflags_mask |= 1 << HFLAGS_INSN_CNT;
+ hflags_mask |= 1 << HFLAGS_PMC_OTHER;
+#endif
+ return hflags_mask;
+}
+
static uint32_t hreg_compute_hflags_value(CPUPPCState *env)
{
target_ulong msr = env->msr;
@@ -104,30 +146,12 @@ static uint32_t hreg_compute_hflags_value(CPUPPCState *env)
if (env->spr[SPR_LPCR] & LPCR_HR) {
hflags |= 1 << HFLAGS_HR;
}
- if (env->spr[SPR_POWER_MMCR0] & MMCR0_PMCC0) {
- hflags |= 1 << HFLAGS_PMCC0;
- }
- if (env->spr[SPR_POWER_MMCR0] & MMCR0_PMCC1) {
- hflags |= 1 << HFLAGS_PMCC1;
- }
- if (env->spr[SPR_POWER_MMCR0] & MMCR0_PMCjCE) {
- hflags |= 1 << HFLAGS_PMCJCE;
- }
#ifndef CONFIG_USER_ONLY
if (!env->has_hv_mode || (msr & (1ull << MSR_HV))) {
hflags |= 1 << HFLAGS_HV;
}
-#if defined(TARGET_PPC64)
- if (env->pmc_ins_cnt) {
- hflags |= 1 << HFLAGS_INSN_CNT;
- }
- if (env->pmc_ins_cnt & 0x1e) {
- hflags |= 1 << HFLAGS_PMC_OTHER;
- }
-#endif
-
/*
* This is our encoding for server processors. The architecture
* specifies that there is no such thing as userspace with
@@ -172,6 +196,8 @@ static uint32_t hreg_compute_hflags_value(CPUPPCState *env)
hflags |= dmmu_idx << HFLAGS_DMMU_IDX;
#endif
+ hflags |= hreg_compute_pmu_hflags_value(env);
+
return hflags | (msr & msr_mask);
}
@@ -180,6 +206,17 @@ void hreg_compute_hflags(CPUPPCState *env)
env->hflags = hreg_compute_hflags_value(env);
}
+/*
+ * This can be used as a lighter-weight alternative to hreg_compute_hflags
+ * when PMU MMCR0 or pmc_ins_cnt changes. pmc_ins_cnt is changed by
+ * pmu_update_summaries.
+ */
+void hreg_update_pmu_hflags(CPUPPCState *env)
+{
+ env->hflags &= ~hreg_compute_pmu_hflags_mask(env);
+ env->hflags |= hreg_compute_pmu_hflags_value(env);
+}
+
#ifdef CONFIG_DEBUG_TCG
void cpu_get_tb_cpu_state(CPUPPCState *env, target_ulong *pc,
target_ulong *cs_base, uint32_t *flags)
diff --git a/target/ppc/helper_regs.h b/target/ppc/helper_regs.h
index 42f26870b9..8196c1346d 100644
--- a/target/ppc/helper_regs.h
+++ b/target/ppc/helper_regs.h
@@ -22,6 +22,7 @@
void hreg_swap_gpr_tgpr(CPUPPCState *env);
void hreg_compute_hflags(CPUPPCState *env);
+void hreg_update_pmu_hflags(CPUPPCState *env);
void cpu_interrupt_exittb(CPUState *cs);
int hreg_store_msr(CPUPPCState *env, target_ulong value, int alter_hv);
diff --git a/target/ppc/machine.c b/target/ppc/machine.c
index be6eb3d968..134b16c625 100644
--- a/target/ppc/machine.c
+++ b/target/ppc/machine.c
@@ -21,10 +21,6 @@ static void post_load_update_msr(CPUPPCState *env)
*/
env->msr ^= env->msr_mask & ~((1ULL << MSR_TGPR) | MSR_HVB);
ppc_store_msr(env, msr);
-
- if (tcg_enabled()) {
- pmu_update_summaries(env);
- }
}
static int get_avr(QEMUFile *f, void *pv, size_t size,
@@ -317,6 +313,10 @@ static int cpu_post_load(void *opaque, int version_id)
post_load_update_msr(env);
+ if (tcg_enabled()) {
+ pmu_mmcr01_updated(env);
+ }
+
return 0;
}
diff --git a/target/ppc/power8-pmu.c b/target/ppc/power8-pmu.c
index 64a64865d7..c4c331c6b5 100644
--- a/target/ppc/power8-pmu.c
+++ b/target/ppc/power8-pmu.c
@@ -31,7 +31,11 @@ static bool pmc_has_overflow_enabled(CPUPPCState *env, int sprn)
return env->spr[SPR_POWER_MMCR0] & MMCR0_PMCjCE;
}
-void pmu_update_summaries(CPUPPCState *env)
+/*
+ * Called after MMCR0 or MMCR1 changes to update pmc_ins_cnt and pmc_cyc_cnt.
+ * hflags must subsequently be updated.
+ */
+static void pmu_update_summaries(CPUPPCState *env)
{
target_ulong mmcr0 = env->spr[SPR_POWER_MMCR0];
target_ulong mmcr1 = env->spr[SPR_POWER_MMCR1];
@@ -39,7 +43,7 @@ void pmu_update_summaries(CPUPPCState *env)
int cyc_cnt = 0;
if (mmcr0 & MMCR0_FC) {
- goto hflags_calc;
+ goto out;
}
if (!(mmcr0 & MMCR0_FC14) && mmcr1 != 0) {
@@ -73,10 +77,19 @@ void pmu_update_summaries(CPUPPCState *env)
ins_cnt |= !(mmcr0 & MMCR0_FC56) << 5;
cyc_cnt |= !(mmcr0 & MMCR0_FC56) << 6;
- hflags_calc:
+ out:
env->pmc_ins_cnt = ins_cnt;
env->pmc_cyc_cnt = cyc_cnt;
- env->hflags = deposit32(env->hflags, HFLAGS_INSN_CNT, 1, ins_cnt != 0);
+}
+
+void pmu_mmcr01_updated(CPUPPCState *env)
+{
+ pmu_update_summaries(env);
+ hreg_update_pmu_hflags(env);
+ /*
+ * Should this update overflow timers (if mmcr0 is updated) so they
+ * get set in cpu_post_load?
+ */
}
static bool pmu_increment_insns(CPUPPCState *env, uint32_t num_insns)
@@ -234,18 +247,11 @@ static void pmu_delete_timers(CPUPPCState *env)
void helper_store_mmcr0(CPUPPCState *env, target_ulong value)
{
- bool hflags_pmcc0 = (value & MMCR0_PMCC0) != 0;
- bool hflags_pmcc1 = (value & MMCR0_PMCC1) != 0;
-
pmu_update_cycles(env);
env->spr[SPR_POWER_MMCR0] = value;
- /* MMCR0 writes can change HFLAGS_PMCC[01] and HFLAGS_INSN_CNT */
- env->hflags = deposit32(env->hflags, HFLAGS_PMCC0, 1, hflags_pmcc0);
- env->hflags = deposit32(env->hflags, HFLAGS_PMCC1, 1, hflags_pmcc1);
-
- pmu_update_summaries(env);
+ pmu_mmcr01_updated(env);
/* Update cycle overflow timers with the current MMCR0 state */
pmu_update_overflow_timers(env);
@@ -257,8 +263,7 @@ void helper_store_mmcr1(CPUPPCState *env, uint64_t value)
env->spr[SPR_POWER_MMCR1] = value;
- /* MMCR1 writes can change HFLAGS_INSN_CNT */
- pmu_update_summaries(env);
+ pmu_mmcr01_updated(env);
}
target_ulong helper_read_pmc(CPUPPCState *env, uint32_t sprn)
@@ -287,8 +292,8 @@ static void fire_PMC_interrupt(PowerPCCPU *cpu)
env->spr[SPR_POWER_MMCR0] &= ~MMCR0_FCECE;
env->spr[SPR_POWER_MMCR0] |= MMCR0_FC;
- /* Changing MMCR0_FC requires a new HFLAGS_INSN_CNT calc */
- pmu_update_summaries(env);
+ /* Changing MMCR0_FC requires summaries and hflags update */
+ pmu_mmcr01_updated(env);
/*
* Delete all pending timers if we need to freeze
@@ -299,6 +304,7 @@ static void fire_PMC_interrupt(PowerPCCPU *cpu)
}
if (env->spr[SPR_POWER_MMCR0] & MMCR0_PMAE) {
+ /* These MMCR0 bits do not require summaries or hflags update. */
env->spr[SPR_POWER_MMCR0] &= ~MMCR0_PMAE;
env->spr[SPR_POWER_MMCR0] |= MMCR0_PMAO;
}
diff --git a/target/ppc/power8-pmu.h b/target/ppc/power8-pmu.h
index c0093e2219..775e640053 100644
--- a/target/ppc/power8-pmu.h
+++ b/target/ppc/power8-pmu.h
@@ -18,10 +18,10 @@
#define PMC_COUNTER_NEGATIVE_VAL 0x80000000UL
void cpu_ppc_pmu_init(CPUPPCState *env);
-void pmu_update_summaries(CPUPPCState *env);
+void pmu_mmcr01_updated(CPUPPCState *env);
#else
static inline void cpu_ppc_pmu_init(CPUPPCState *env) { }
-static inline void pmu_update_summaries(CPUPPCState *env) { }
+static inline void pmu_mmcr01_updated(CPUPPCState *env) { }
#endif
#endif
--
2.40.1
next prev parent reply other threads:[~2023-06-10 13:34 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-10 13:31 [PULL 00/29] ppc queue Daniel Henrique Barboza
2023-06-10 13:31 ` [PULL 01/29] pnv/xive2: Add definition for TCTXT Config register Daniel Henrique Barboza
2023-06-10 13:31 ` [PULL 02/29] pnv/xive2: Add definition for the ESB cache configuration register Daniel Henrique Barboza
2023-06-10 13:31 ` [PULL 03/29] pnv/xive2: Allow writes to the Physical Thread Enable registers Daniel Henrique Barboza
2023-06-10 13:31 ` [PULL 04/29] pnv/xive2: Introduce macros to manipulate TIMA addresses Daniel Henrique Barboza
2023-06-10 13:31 ` [PULL 05/29] pnv/xive2: Handle TIMA access through all ports Daniel Henrique Barboza
2023-06-20 10:45 ` Peter Maydell
2023-06-20 11:20 ` Cédric Le Goater
2023-06-20 14:31 ` Frederic Barrat
2023-06-20 14:57 ` Cédric Le Goater
2023-06-21 7:18 ` Cédric Le Goater
2023-06-21 15:18 ` Frederic Barrat
2023-06-21 16:59 ` Cédric Le Goater
2023-06-10 13:31 ` [PULL 06/29] target/ppc: Fix nested-hv HEAI delivery Daniel Henrique Barboza
2023-06-10 13:31 ` [PULL 07/29] pnv/xive2: Quiet down some error messages Daniel Henrique Barboza
2023-06-10 13:31 ` Daniel Henrique Barboza [this message]
2023-06-10 13:31 ` [PULL 09/29] target/ppc: PMU do not clear MMCR0[FCECE] on performance monitor alert Daniel Henrique Barboza
2023-06-10 13:31 ` [PULL 10/29] target/ppc: Fix msgclrp interrupt type Daniel Henrique Barboza
2023-06-10 13:31 ` [PULL 11/29] target/ppc: Support directed privileged doorbell interrupt (SDOOR) Daniel Henrique Barboza
2023-06-10 13:31 ` [PULL 12/29] target/ppc: PMU implement PERFM interrupts Daniel Henrique Barboza
2023-06-10 13:31 ` [PULL 13/29] target/ppc: Remove single use function Daniel Henrique Barboza
2023-06-10 13:31 ` [PULL 14/29] target/ppc: Remove "ext" parameter of ppcemb_tlb_check() Daniel Henrique Barboza
2023-06-10 13:31 ` [PULL 15/29] target/ppc: Move ppcemb_tlb_search() to mmu_common.c Daniel Henrique Barboza
2023-06-10 13:31 ` [PULL 16/29] target/ppc: Remove some unneded line breaks Daniel Henrique Barboza
2023-06-10 13:31 ` [PULL 17/29] target/ppc: Simplify ppcemb_tlb_search() Daniel Henrique Barboza
2023-06-10 13:31 ` [PULL 18/29] target/ppc: Change ppcemb_tlb_check() to return bool Daniel Henrique Barboza
2023-06-10 13:31 ` [PULL 19/29] target/ppc: Eliminate goto in mmubooke_check_tlb() Daniel Henrique Barboza
2023-06-10 13:31 ` [PULL 20/29] target/ppc: Fix lqarx to set cpu_reserve Daniel Henrique Barboza
2023-06-10 13:31 ` [PULL 21/29] target/ppc: Ensure stcx size matches larx Daniel Henrique Barboza
2023-06-10 13:31 ` [PULL 22/29] target/ppc: Remove larx/stcx. memory barrier semantics Daniel Henrique Barboza
2023-06-10 13:31 ` [PULL 23/29] target/ppc: Rework store conditional to avoid branch Daniel Henrique Barboza
2023-06-10 13:31 ` [PULL 24/29] target/ppc: Fix decrementer time underflow and infinite timer loop Daniel Henrique Barboza
2023-06-10 13:31 ` [PULL 25/29] target/ppc: Decrementer fix BookE semantics Daniel Henrique Barboza
2023-06-10 13:31 ` [PULL 26/29] hw/ppc/openpic: Do not open-code ROUND_UP() macro Daniel Henrique Barboza
2023-06-10 13:31 ` [PULL 27/29] tests/avocado/tuxrun_baselines: Fix ppc64 tests for binaries without slirp Daniel Henrique Barboza
2023-06-10 13:31 ` [PULL 28/29] target/ppc: Implement gathering irq statistics Daniel Henrique Barboza
2023-06-10 13:31 ` [PULL 29/29] hw/ppc/Kconfig: MAC_NEWWORLD should always select USB_OHCI_PCI Daniel Henrique Barboza
2023-06-10 15:44 ` [PULL 00/29] ppc queue Richard Henderson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230610133132.290703-9-danielhb413@gmail.com \
--to=danielhb413@gmail.com \
--cc=npiggin@gmail.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=qemu-ppc@nongnu.org \
--cc=richard.henderson@linaro.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.