aboutsummaryrefslogtreecommitdiff
path: root/target/ppc/power8-pmu.c
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2022-01-04 07:55:34 +0100
committerCédric Le Goater <clg@kaod.org>2022-01-04 07:55:34 +0100
commit6e8b990354d244ad5af40c747fdf3c008962b4e3 (patch)
tree0e65c2d0e34eadbadf6ec696446caab29ba850be /target/ppc/power8-pmu.c
parent93130c8475692b1e52e3d3c3beedc3a79b4562d5 (diff)
target/ppc: Cache per-pmc insn and cycle count settings
This is the combination of frozen bit and counter type, on a per counter basis. So far this is only used by HFLAGS_INSN_CNT, but will be used more later. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> [danielhb: fixed PMC4 cyc_cnt shift, insn run latch code, MMCR0_FC handling, "PMC[1-6]" comment] Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> Message-Id: <20220103224746.167831-2-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater <clg@kaod.org>
Diffstat (limited to 'target/ppc/power8-pmu.c')
-rw-r--r--target/ppc/power8-pmu.c56
1 files changed, 45 insertions, 11 deletions
diff --git a/target/ppc/power8-pmu.c b/target/ppc/power8-pmu.c
index 08d1902cd5..1f4f611994 100644
--- a/target/ppc/power8-pmu.c
+++ b/target/ppc/power8-pmu.c
@@ -11,8 +11,6 @@
*/
#include "qemu/osdep.h"
-
-#include "power8-pmu.h"
#include "cpu.h"
#include "helper_regs.h"
#include "exec/exec-all.h"
@@ -20,6 +18,7 @@
#include "qemu/error-report.h"
#include "qemu/main-loop.h"
#include "hw/ppc/ppc.h"
+#include "power8-pmu.h"
#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
@@ -121,18 +120,52 @@ static PMUEventType pmc_get_event(CPUPPCState *env, int sprn)
return evt_type;
}
-bool pmu_insn_cnt_enabled(CPUPPCState *env)
+void pmu_update_summaries(CPUPPCState *env)
{
- int sprn;
+ target_ulong mmcr0 = env->spr[SPR_POWER_MMCR0];
+ target_ulong mmcr1 = env->spr[SPR_POWER_MMCR1];
+ int ins_cnt = 0;
+ int cyc_cnt = 0;
- for (sprn = SPR_POWER_PMC1; sprn <= SPR_POWER_PMC5; sprn++) {
- if (pmc_get_event(env, sprn) == PMU_EVENT_INSTRUCTIONS ||
- pmc_get_event(env, sprn) == PMU_EVENT_INSN_RUN_LATCH) {
- return true;
+ if (mmcr0 & MMCR0_FC) {
+ goto hflags_calc;
+ }
+
+ if (!(mmcr0 & MMCR0_FC14) && mmcr1 != 0) {
+ target_ulong sel;
+
+ sel = extract64(mmcr1, MMCR1_PMC1EVT_EXTR, MMCR1_EVT_SIZE);
+ switch (sel) {
+ case 0x02:
+ case 0xfe:
+ ins_cnt |= 1 << 1;
+ break;
+ case 0x1e:
+ case 0xf0:
+ cyc_cnt |= 1 << 1;
+ break;
}
+
+ sel = extract64(mmcr1, MMCR1_PMC2EVT_EXTR, MMCR1_EVT_SIZE);
+ ins_cnt |= (sel == 0x02) << 2;
+ cyc_cnt |= (sel == 0x1e) << 2;
+
+ sel = extract64(mmcr1, MMCR1_PMC3EVT_EXTR, MMCR1_EVT_SIZE);
+ ins_cnt |= (sel == 0x02) << 3;
+ cyc_cnt |= (sel == 0x1e) << 3;
+
+ sel = extract64(mmcr1, MMCR1_PMC4EVT_EXTR, MMCR1_EVT_SIZE);
+ ins_cnt |= ((sel == 0xfa) || (sel == 0x2)) << 4;
+ cyc_cnt |= (sel == 0x1e) << 4;
}
- return false;
+ ins_cnt |= !(mmcr0 & MMCR0_FC56) << 5;
+ cyc_cnt |= !(mmcr0 & MMCR0_FC56) << 6;
+
+ hflags_calc:
+ env->pmc_ins_cnt = ins_cnt;
+ env->pmc_cyc_cnt = cyc_cnt;
+ env->hflags = deposit32(env->hflags, HFLAGS_INSN_CNT, 1, ins_cnt != 0);
}
static bool pmu_increment_insns(CPUPPCState *env, uint32_t num_insns)
@@ -264,8 +297,9 @@ void helper_store_mmcr0(CPUPPCState *env, target_ulong value)
env->spr[SPR_POWER_MMCR0] = value;
- /* MMCR0 writes can change HFLAGS_PMCCCLEAR and HFLAGS_INSN_CNT */
+ /* MMCR0 writes can change HFLAGS_PMCC[01] and HFLAGS_INSN_CNT */
hreg_compute_hflags(env);
+ pmu_update_summaries(env);
/* Update cycle overflow timers with the current MMCR0 state */
pmu_update_overflow_timers(env);
@@ -278,7 +312,7 @@ void helper_store_mmcr1(CPUPPCState *env, uint64_t value)
env->spr[SPR_POWER_MMCR1] = value;
/* MMCR1 writes can change HFLAGS_INSN_CNT */
- hreg_compute_hflags(env);
+ pmu_update_summaries(env);
}
target_ulong helper_read_pmc(CPUPPCState *env, uint32_t sprn)