ppc: Fix conditions for delivering external interrupts to a guest

External interrupts can bypass the MSR_EE test if they occur in guest
mode and LPES0 is clear. In that case they are directed to the hypervisor

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
Benjamin Herrenschmidt 2016-06-27 08:55:17 +02:00 committed by David Gibson
parent 4b3fc37788
commit d1dbe37c1e

View File

@ -794,6 +794,14 @@ static void ppc_hw_interrupt(CPUPPCState *env)
return; return;
} }
} }
/* Extermal interrupt can ignore MSR:EE under some circumstances */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
if (msr_ee != 0 || (env->has_hv_mode && msr_hv == 0 && !lpes0)) {
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL);
return;
}
}
if (msr_ce != 0) { if (msr_ce != 0) {
/* External critical interrupt */ /* External critical interrupt */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) { if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
@ -839,17 +847,6 @@ static void ppc_hw_interrupt(CPUPPCState *env)
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR); powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR);
return; return;
} }
/* External interrupt */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
/* Taking an external interrupt does not clear the external
* interrupt status
*/
#if 0
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
#endif
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL);
return;
}
if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) { if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL); env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI); powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI);