On 01/11/2021 20:56, Daniel Henrique Barboza wrote:
diff --git a/target/ppc/power8-pmu.c b/target/ppc/power8-pmu.c
index 3c2f73896f..a0a42b666c 100644
--- a/target/ppc/power8-pmu.c
+++ b/target/ppc/power8-pmu.c
<snip>
+static bool pmc_is_active(CPUPPCState *env, int sprn)
+{
+ if (sprn < SPR_POWER_PMC5) {
+ return !(env->spr[SPR_POWER_MMCR0] & MMCR0_FC14);
+ }
+
+ return !(env->spr[SPR_POWER_MMCR0] & MMCR0_FC56);
+}
+
+static void pmu_update_cycles(CPUPPCState *env)
+{
+ uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ uint64_t time_delta = now - env->pmu_base_time;
+ int sprn;
+
+ for (sprn = SPR_POWER_PMC1; sprn <= SPR_POWER_PMC6; sprn++) {
+ if (!pmc_is_active(env, sprn) ||
+ getPMUEventType(env, sprn) != PMU_EVENT_CYCLES) {
+ continue;
+ }
+
+ /*
+ * The pseries and powernv clock runs at 1Ghz, meaning
+ * that 1 nanosec equals 1 cycle.
+ */
+ env->spr[sprn] += time_delta;
+ }
+
+ /*
+ * Update base_time for future calculations if we updated
+ * the PMCs while the PMU was running.
+ */
+ if (!(env->spr[SPR_POWER_MMCR0] & MMCR0_FC)) {
+ env->pmu_base_time = now;
+ }
+}
+
+/*
+ * A cycle count session consists of the basic operations we
+ * need to do to support PM_CYC events: redefine a new base_time
+ * to be used to calculate PMC values and start overflow timers.
+ */
+static void start_cycle_count_session(CPUPPCState *env)
+{
+ /* Just define pmu_base_time for now */
+ env->pmu_base_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+}
+
+void helper_store_mmcr0(CPUPPCState *env, target_ulong value)
+{
+ target_ulong curr_value = env->spr[SPR_POWER_MMCR0];
+ bool curr_FC = curr_value & MMCR0_FC;
+ bool new_FC = value & MMCR0_FC;
+
+ env->spr[SPR_POWER_MMCR0] = value;
I'm not sure if this is the right place to update MMCR0. If we set both FC and
FC14 in one write, the code will call pmu_update_cycles, but PMCs 1-4 will not
be updated because pmc_is_active will use the new value to check if the PMCs
are frozen.