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>
This commit is contained in:
parent
93130c8475
commit
6e8b990354
@ -1144,6 +1144,9 @@ struct CPUPPCState {
|
|||||||
/* Other registers */
|
/* Other registers */
|
||||||
target_ulong spr[1024]; /* special purpose registers */
|
target_ulong spr[1024]; /* special purpose registers */
|
||||||
ppc_spr_t spr_cb[1024];
|
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 */
|
/* Vector status and control register, minus VSCR_SAT */
|
||||||
uint32_t vscr;
|
uint32_t vscr;
|
||||||
/* VSX registers (including FP and AVR) */
|
/* VSX registers (including FP and AVR) */
|
||||||
|
@ -8313,6 +8313,7 @@ static void ppc_cpu_reset(DeviceState *dev)
|
|||||||
#endif /* CONFIG_TCG */
|
#endif /* CONFIG_TCG */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
pmu_update_summaries(env);
|
||||||
hreg_compute_hflags(env);
|
hreg_compute_hflags(env);
|
||||||
env->reserve_addr = (target_ulong)-1ULL;
|
env->reserve_addr = (target_ulong)-1ULL;
|
||||||
/* Be sure no exception or interrupt is pending */
|
/* 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 defined(TARGET_PPC64)
|
||||||
if (pmu_insn_cnt_enabled(env)) {
|
if (env->pmc_ins_cnt) {
|
||||||
hflags |= 1 << HFLAGS_INSN_CNT;
|
hflags |= 1 << HFLAGS_INSN_CNT;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qemu/main-loop.h"
|
#include "qemu/main-loop.h"
|
||||||
#include "kvm_ppc.h"
|
#include "kvm_ppc.h"
|
||||||
|
#include "power8-pmu.h"
|
||||||
|
|
||||||
static void post_load_update_msr(CPUPPCState *env)
|
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);
|
env->msr ^= env->msr_mask & ~((1ULL << MSR_TGPR) | MSR_HVB);
|
||||||
ppc_store_msr(env, msr);
|
ppc_store_msr(env, msr);
|
||||||
|
pmu_update_summaries(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
|
static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
|
||||||
|
@ -11,8 +11,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
|
|
||||||
#include "power8-pmu.h"
|
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "helper_regs.h"
|
#include "helper_regs.h"
|
||||||
#include "exec/exec-all.h"
|
#include "exec/exec-all.h"
|
||||||
@ -20,6 +18,7 @@
|
|||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "qemu/main-loop.h"
|
#include "qemu/main-loop.h"
|
||||||
#include "hw/ppc/ppc.h"
|
#include "hw/ppc/ppc.h"
|
||||||
|
#include "power8-pmu.h"
|
||||||
|
|
||||||
#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
|
#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
|
||||||
|
|
||||||
@ -121,18 +120,52 @@ static PMUEventType pmc_get_event(CPUPPCState *env, int sprn)
|
|||||||
return evt_type;
|
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 (mmcr0 & MMCR0_FC) {
|
||||||
if (pmc_get_event(env, sprn) == PMU_EVENT_INSTRUCTIONS ||
|
goto hflags_calc;
|
||||||
pmc_get_event(env, sprn) == PMU_EVENT_INSN_RUN_LATCH) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
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;
|
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);
|
hreg_compute_hflags(env);
|
||||||
|
pmu_update_summaries(env);
|
||||||
|
|
||||||
/* Update cycle overflow timers with the current MMCR0 state */
|
/* Update cycle overflow timers with the current MMCR0 state */
|
||||||
pmu_update_overflow_timers(env);
|
pmu_update_overflow_timers(env);
|
||||||
@ -278,7 +312,7 @@ void helper_store_mmcr1(CPUPPCState *env, uint64_t value)
|
|||||||
env->spr[SPR_POWER_MMCR1] = value;
|
env->spr[SPR_POWER_MMCR1] = value;
|
||||||
|
|
||||||
/* MMCR1 writes can change HFLAGS_INSN_CNT */
|
/* 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)
|
target_ulong helper_read_pmc(CPUPPCState *env, uint32_t sprn)
|
||||||
|
@ -13,14 +13,12 @@
|
|||||||
#ifndef POWER8_PMU
|
#ifndef POWER8_PMU
|
||||||
#define 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);
|
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
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user