target/ppc: Fix doorbell delivery to threads in powersave

Doorbell exceptions are not not cleared when they cause a wake from
powersave state, only when they take the corresponding interrupt.
The sreset-on-wake logic must avoid clearing the interrupt in this
case.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
This commit is contained in:
Nicholas Piggin 2024-08-06 23:13:15 +10:00
parent c5747965af
commit 06229545f5

View File

@ -2237,7 +2237,9 @@ static void p8_deliver_interrupt(CPUPPCState *env, int interrupt)
powerpc_excp(cpu, POWERPC_EXCP_DECR);
break;
case PPC_INTERRUPT_DOORBELL:
env->pending_interrupts &= ~PPC_INTERRUPT_DOORBELL;
if (!env->resume_as_sreset) {
env->pending_interrupts &= ~PPC_INTERRUPT_DOORBELL;
}
if (is_book3s_arch2x(env)) {
powerpc_excp(cpu, POWERPC_EXCP_SDOOR);
} else {
@ -2245,7 +2247,9 @@ static void p8_deliver_interrupt(CPUPPCState *env, int interrupt)
}
break;
case PPC_INTERRUPT_HDOORBELL:
env->pending_interrupts &= ~PPC_INTERRUPT_HDOORBELL;
if (!env->resume_as_sreset) {
env->pending_interrupts &= ~PPC_INTERRUPT_HDOORBELL;
}
powerpc_excp(cpu, POWERPC_EXCP_SDOOR_HV);
break;
case PPC_INTERRUPT_PERFM:
@ -2301,6 +2305,7 @@ static void p9_deliver_interrupt(CPUPPCState *env, int interrupt)
case PPC_INTERRUPT_HDECR: /* Hypervisor decrementer exception */
/* HDEC clears on delivery */
/* XXX: should not see an HDEC if resume_as_sreset. assert? */
env->pending_interrupts &= ~PPC_INTERRUPT_HDECR;
powerpc_excp(cpu, POWERPC_EXCP_HDECR);
break;
@ -2320,11 +2325,15 @@ static void p9_deliver_interrupt(CPUPPCState *env, int interrupt)
powerpc_excp(cpu, POWERPC_EXCP_DECR);
break;
case PPC_INTERRUPT_DOORBELL:
env->pending_interrupts &= ~PPC_INTERRUPT_DOORBELL;
if (!env->resume_as_sreset) {
env->pending_interrupts &= ~PPC_INTERRUPT_DOORBELL;
}
powerpc_excp(cpu, POWERPC_EXCP_SDOOR);
break;
case PPC_INTERRUPT_HDOORBELL:
env->pending_interrupts &= ~PPC_INTERRUPT_HDOORBELL;
if (!env->resume_as_sreset) {
env->pending_interrupts &= ~PPC_INTERRUPT_HDOORBELL;
}
powerpc_excp(cpu, POWERPC_EXCP_SDOOR_HV);
break;
case PPC_INTERRUPT_PERFM: