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.
+ + /* MMCR0 writes can change HFLAGS_PMCCCLEAR and HFLAGS_MMCR0FC */ + if (((curr_value & MMCR0_PMCC) != (value & MMCR0_PMCC)) || + (curr_FC != new_FC)) { + hreg_compute_hflags(env); + } + + /* + * In an frozen count (FC) bit change: + * + * - if PMCs were running (curr_FC = false) and we're freezing + * them (new_FC = true), save the PMCs values in the registers. + * + * - if PMCs were frozen (curr_FC = true) and we're activating + * them (new_FC = false), set the new base_time for future cycle + * calculations. + */ + if (curr_FC != new_FC) { + if (!curr_FC) { > + pmu_update_cycles(env); + } else { + start_cycle_count_session(env); + } + } +}
-- Matheus K. Ferst Instituto de Pesquisas ELDORADO <http://www.eldorado.org.br/> Analista de Software Aviso Legal - Disclaimer <https://www.eldorado.org.br/disclaimer.html>