mirror of https://github.com/proxmox/mirror_qemu
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>master
parent
93130c8475
commit
6e8b990354
|
@ -1144,6 +1144,9 @@ struct CPUPPCState {
|
|||
/* Other registers */
|
||||
target_ulong spr[1024]; /* special purpose registers */
|
||||
ppc_spr_t spr_cb[1024];
|
||||
/* Composite status for PMC[1-6] enabled and counting insns or cycles. */
|
||||
uint8_t pmc_ins_cnt;
|
||||
uint8_t pmc_cyc_cnt;
|
||||
/* Vector status and control register, minus VSCR_SAT */
|
||||
uint32_t vscr;
|
||||
/* VSX registers (including FP and AVR) */
|
||||
|
|
|
@ -8313,6 +8313,7 @@ static void ppc_cpu_reset(DeviceState *dev)
|
|||
#endif /* CONFIG_TCG */
|
||||
#endif
|
||||
|
||||
pmu_update_summaries(env);
|
||||
hreg_compute_hflags(env);
|
||||
env->reserve_addr = (target_ulong)-1ULL;
|
||||
/* Be sure no exception or interrupt is pending */
|
||||
|
|
|
@ -123,7 +123,7 @@ static uint32_t hreg_compute_hflags_value(CPUPPCState *env)
|
|||
}
|
||||
|
||||
#if defined(TARGET_PPC64)
|
||||
if (pmu_insn_cnt_enabled(env)) {
|
||||
if (env->pmc_ins_cnt) {
|
||||
hflags |= 1 << HFLAGS_INSN_CNT;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "qapi/error.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "kvm_ppc.h"
|
||||
#include "power8-pmu.h"
|
||||
|
||||
static void post_load_update_msr(CPUPPCState *env)
|
||||
{
|
||||
|
@ -19,6 +20,7 @@ static void post_load_update_msr(CPUPPCState *env)
|
|||
*/
|
||||
env->msr ^= env->msr_mask & ~((1ULL << MSR_TGPR) | MSR_HVB);
|
||||
ppc_store_msr(env, msr);
|
||||
pmu_update_summaries(env);
|
||||
}
|
||||
|
||||
static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
return false;
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
|
@ -13,14 +13,12 @@
|
|||
#ifndef POWER8_PMU
|
||||
#define POWER8_PMU
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/main-loop.h"
|
||||
|
||||
void cpu_ppc_pmu_init(CPUPPCState *env);
|
||||
bool pmu_insn_cnt_enabled(CPUPPCState *env);
|
||||
|
||||
#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
|
||||
void pmu_update_summaries(CPUPPCState *env);
|
||||
#else
|
||||
static inline void pmu_update_summaries(CPUPPCState *env) { }
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue