mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-07 01:33:56 -06:00
target/ppc: introduce ppc_maybe_interrupt
This new method will check if any pending interrupt was unmasked and then call cpu_interrupt/cpu_reset_interrupt accordingly. Code that raises/lowers or masks/unmasks interrupts should call this method to keep CPU_INTERRUPT_HARD coherent with env->pending_interrupts. Signed-off-by: Matheus Ferst <matheus.ferst@eldorado.org.br> Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com> Message-Id: <20221021142156.4134411-2-matheus.ferst@eldorado.org.br> Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
This commit is contained in:
parent
6a8e8188c3
commit
2fdedcbc69
10 changed files with 67 additions and 8 deletions
|
@ -390,6 +390,7 @@ static void powerpc_set_excp_state(PowerPCCPU *cpu, target_ulong vector,
|
|||
env->nip = vector;
|
||||
env->msr = msr;
|
||||
hreg_compute_hflags(env);
|
||||
ppc_maybe_interrupt(env);
|
||||
|
||||
powerpc_reset_excp_state(cpu);
|
||||
|
||||
|
@ -2044,6 +2045,40 @@ static int ppc_next_unmasked_interrupt(CPUPPCState *env)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets CPU_INTERRUPT_HARD if there is at least one unmasked interrupt to be
|
||||
* delivered and clears CPU_INTERRUPT_HARD otherwise.
|
||||
*
|
||||
* This method is called by ppc_set_interrupt when an interrupt is raised or
|
||||
* lowered, and should also be called whenever an interrupt masking condition
|
||||
* is changed, e.g.:
|
||||
* - When relevant bits of MSR are altered, like EE, HV, PR, etc.;
|
||||
* - When relevant bits of LPCR are altered, like PECE, HDICE, HVICE, etc.;
|
||||
* - When PSSCR[EC] or env->resume_as_sreset are changed;
|
||||
* - When cs->halted is changed and the CPU has a different interrupt masking
|
||||
* logic in power-saving mode (e.g., POWER7/8/9/10);
|
||||
*/
|
||||
void ppc_maybe_interrupt(CPUPPCState *env)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
bool locked = false;
|
||||
|
||||
if (!qemu_mutex_iothread_locked()) {
|
||||
locked = true;
|
||||
qemu_mutex_lock_iothread();
|
||||
}
|
||||
|
||||
if (ppc_next_unmasked_interrupt(env)) {
|
||||
cpu_interrupt(cs, CPU_INTERRUPT_HARD);
|
||||
} else {
|
||||
cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
|
||||
}
|
||||
|
||||
if (locked) {
|
||||
qemu_mutex_unlock_iothread();
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(TARGET_PPC64)
|
||||
static void p7_deliver_interrupt(CPUPPCState *env, int interrupt)
|
||||
{
|
||||
|
@ -2479,6 +2514,11 @@ void helper_store_msr(CPUPPCState *env, target_ulong val)
|
|||
}
|
||||
}
|
||||
|
||||
void helper_ppc_maybe_interrupt(CPUPPCState *env)
|
||||
{
|
||||
ppc_maybe_interrupt(env);
|
||||
}
|
||||
|
||||
#if defined(TARGET_PPC64)
|
||||
void helper_scv(CPUPPCState *env, uint32_t lev)
|
||||
{
|
||||
|
@ -2499,6 +2539,8 @@ void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn)
|
|||
/* Condition for waking up at 0x100 */
|
||||
env->resume_as_sreset = (insn != PPC_PM_STOP) ||
|
||||
(env->spr[SPR_PSSCR] & PSSCR_EC);
|
||||
|
||||
ppc_maybe_interrupt(env);
|
||||
}
|
||||
#endif /* defined(TARGET_PPC64) */
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue