mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-11 03:24:58 -06:00
target/ppc: trigger PERFM EBBs from power8-pmu.c
This patch adds the EBB exception support that are triggered by Performance Monitor alerts. This happens when a Performance Monitor alert occurs and MMCR0_EBE, BESCR_PME and BESCR_GE are set. fire_PMC_interrupt() will execute the raise_ebb_perfm_exception() helper which will check for MMCR0_EBE, BESCR_PME and BESCR_GE bits. If all bits are set, do_ebb() will attempt to trigger a PERFM EBB event. If the EBB facility is enabled in both FSCR and HFSCR we consider that the EBB is valid and set BESCR_PMEO. After that, if we're running in problem state, fire a POWERPC_EXCP_PERM_EBB immediately. Otherwise we'll queue a PPC_INTERRUPT_EBB. Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20220225101140.1054160-5-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater <clg@kaod.org>
This commit is contained in:
parent
cb76bbc43f
commit
d3412df20a
3 changed files with 54 additions and 2 deletions
|
@ -2502,6 +2502,11 @@ void QEMU_NORETURN raise_exception_err(CPUPPCState *env, uint32_t exception,
|
||||||
void QEMU_NORETURN raise_exception_err_ra(CPUPPCState *env, uint32_t exception,
|
void QEMU_NORETURN raise_exception_err_ra(CPUPPCState *env, uint32_t exception,
|
||||||
uint32_t error_code, uintptr_t raddr);
|
uint32_t error_code, uintptr_t raddr);
|
||||||
|
|
||||||
|
/* PERFM EBB helper*/
|
||||||
|
#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
|
||||||
|
void raise_ebb_perfm_exception(CPUPPCState *env);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(CONFIG_USER_ONLY)
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
static inline int booke206_tlbm_id(CPUPPCState *env, ppcmas_tlb_t *tlbm)
|
static inline int booke206_tlbm_id(CPUPPCState *env, ppcmas_tlb_t *tlbm)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2066,6 +2066,54 @@ void helper_rfebb(CPUPPCState *env, target_ulong s)
|
||||||
env->spr[SPR_BESCR] &= ~BESCR_GE;
|
env->spr[SPR_BESCR] &= ~BESCR_GE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Triggers or queues an 'ebb_excp' EBB exception. All checks
|
||||||
|
* but FSCR, HFSCR and msr_pr must be done beforehand.
|
||||||
|
*
|
||||||
|
* PowerISA v3.1 isn't clear about whether an EBB should be
|
||||||
|
* postponed or cancelled if the EBB facility is unavailable.
|
||||||
|
* Our assumption here is that the EBB is cancelled if both
|
||||||
|
* FSCR and HFSCR EBB facilities aren't available.
|
||||||
|
*/
|
||||||
|
static void do_ebb(CPUPPCState *env, int ebb_excp)
|
||||||
|
{
|
||||||
|
PowerPCCPU *cpu = env_archcpu(env);
|
||||||
|
CPUState *cs = CPU(cpu);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FSCR_EBB and FSCR_IC_EBB are the same bits used with
|
||||||
|
* HFSCR.
|
||||||
|
*/
|
||||||
|
helper_fscr_facility_check(env, FSCR_EBB, 0, FSCR_IC_EBB);
|
||||||
|
helper_hfscr_facility_check(env, FSCR_EBB, "EBB", FSCR_IC_EBB);
|
||||||
|
|
||||||
|
if (ebb_excp == POWERPC_EXCP_PERFM_EBB) {
|
||||||
|
env->spr[SPR_BESCR] |= BESCR_PMEO;
|
||||||
|
} else if (ebb_excp == POWERPC_EXCP_EXTERNAL_EBB) {
|
||||||
|
env->spr[SPR_BESCR] |= BESCR_EEO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msr_pr == 1) {
|
||||||
|
powerpc_excp(cpu, ebb_excp);
|
||||||
|
} else {
|
||||||
|
env->pending_interrupts |= 1 << PPC_INTERRUPT_EBB;
|
||||||
|
cpu_interrupt(cs, CPU_INTERRUPT_HARD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void raise_ebb_perfm_exception(CPUPPCState *env)
|
||||||
|
{
|
||||||
|
bool perfm_ebb_enabled = env->spr[SPR_POWER_MMCR0] & MMCR0_EBE &&
|
||||||
|
env->spr[SPR_BESCR] & BESCR_PME &&
|
||||||
|
env->spr[SPR_BESCR] & BESCR_GE;
|
||||||
|
|
||||||
|
if (!perfm_ebb_enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
do_ebb(env, POWERPC_EXCP_PERFM_EBB);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
|
@ -307,8 +307,7 @@ static void fire_PMC_interrupt(PowerPCCPU *cpu)
|
||||||
env->spr[SPR_POWER_MMCR0] |= MMCR0_PMAO;
|
env->spr[SPR_POWER_MMCR0] |= MMCR0_PMAO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PMC interrupt not implemented yet */
|
raise_ebb_perfm_exception(env);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This helper assumes that the PMC is running. */
|
/* This helper assumes that the PMC is running. */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue