diff options
Diffstat (limited to 'target-ppc/excp_helper.c')
-rw-r--r-- | target-ppc/excp_helper.c | 22 |
1 files changed, 12 insertions, 10 deletions
diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c index 26adda49b2..d6e1678a63 100644 --- a/target-ppc/excp_helper.c +++ b/target-ppc/excp_helper.c @@ -753,7 +753,6 @@ void ppc_cpu_do_interrupt(CPUState *cs) static void ppc_hw_interrupt(CPUPPCState *env) { PowerPCCPU *cpu = ppc_env_get_cpu(env); - int hdice; #if 0 CPUState *cs = CPU(cpu); @@ -781,15 +780,13 @@ static void ppc_hw_interrupt(CPUPPCState *env) return; } #endif - if (0) { - /* XXX: find a suitable condition to enable the hypervisor mode */ - hdice = env->spr[SPR_LPCR] & 1; - } else { - hdice = 0; - } - if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) { - /* Hypervisor decrementer exception */ - if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) { + /* Hypervisor decrementer exception */ + if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) { + /* LPCR will be clear when not supported so this will work */ + bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE); + if ((msr_ee != 0 || msr_hv == 0) && hdice) { + /* HDEC clears on delivery */ + env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR); powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR); return; } @@ -941,6 +938,11 @@ void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn) cs->halted = 1; env->in_pm_state = true; + /* The architecture specifies that HDEC interrupts are + * discarded in PM states + */ + env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR); + /* Technically, nap doesn't set EE, but if we don't set it * then ppc_hw_interrupt() won't deliver. We could add some * other tests there based on LPCR but it's simpler to just |