Blame SOURCES/kvm-ppc-Deassert-the-external-interrupt-pin-in-KVM-on-re.patch

ddf19c
From 22fc9bd7e7ae0b72c6f6e483eb66cf996f519766 Mon Sep 17 00:00:00 2001
ddf19c
From: David Gibson <dgibson@redhat.com>
ddf19c
Date: Tue, 21 Jan 2020 05:16:11 +0000
ddf19c
Subject: [PATCH 01/15] ppc: Deassert the external interrupt pin in KVM on
ddf19c
 reset
ddf19c
MIME-Version: 1.0
ddf19c
Content-Type: text/plain; charset=UTF-8
ddf19c
Content-Transfer-Encoding: 8bit
ddf19c
ddf19c
RH-Author: David Gibson <dgibson@redhat.com>
ddf19c
Message-id: <20200121051613.388295-2-dgibson@redhat.com>
ddf19c
Patchwork-id: 93429
ddf19c
O-Subject: [RHEL-AV-8.2 qemu-kvm PATCH 1/3] ppc: Deassert the external interrupt pin in KVM on reset
ddf19c
Bugzilla: 1776638
ddf19c
RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
ddf19c
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
ddf19c
RH-Acked-by: Thomas Huth <thuth@redhat.com>
ddf19c
ddf19c
From: Greg Kurz <groug@kaod.org>
ddf19c
ddf19c
When a CPU is reset, QEMU makes sure no interrupt is pending by clearing
ddf19c
CPUPPCstate::pending_interrupts in ppc_cpu_reset(). In the case of a
ddf19c
complete machine emulation, eg. a sPAPR machine, an external interrupt
ddf19c
request could still be pending in KVM though, eg. an IPI. It will be
ddf19c
eventually presented to the guest, which is supposed to acknowledge it at
ddf19c
the interrupt controller. If the interrupt controller is emulated in QEMU,
ddf19c
either XICS or XIVE, ppc_set_irq() won't deassert the external interrupt
ddf19c
pin in KVM since it isn't pending anymore for QEMU. When the vCPU re-enters
ddf19c
the guest, the interrupt request is still pending and the vCPU will try
ddf19c
again to acknowledge it. This causes an infinite loop and eventually hangs
ddf19c
the guest.
ddf19c
ddf19c
The code has been broken since the beginning. The issue wasn't hit before
ddf19c
because accel=kvm,kernel-irqchip=off is an awkward setup that never got
ddf19c
used until recently with the LC92x IBM systems (aka, Boston).
ddf19c
ddf19c
Add a ppc_irq_reset() function to do the necessary cleanup, ie. deassert
ddf19c
the IRQ pins of the CPU in QEMU and most importantly the external interrupt
ddf19c
pin for this vCPU in KVM.
ddf19c
ddf19c
Reported-by: Satheesh Rajendran <sathnaga@linux.vnet.ibm.com>
ddf19c
Signed-off-by: Greg Kurz <groug@kaod.org>
ddf19c
Message-Id: <157548861740.3650476.16879693165328764758.stgit@bahia.lan>
ddf19c
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
ddf19c
(cherry picked from commit 401774387aeb37f2ada9bb18f7c7e307b21a3e93)
ddf19c
ddf19c
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1776638
ddf19c
ddf19c
Signed-off-by: David Gibson <dgibson@redhat.com>
ddf19c
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
ddf19c
---
ddf19c
 hw/ppc/ppc.c                    | 8 ++++++++
ddf19c
 include/hw/ppc/ppc.h            | 2 ++
ddf19c
 target/ppc/translate_init.inc.c | 1 +
ddf19c
 3 files changed, 11 insertions(+)
ddf19c
ddf19c
diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
ddf19c
index 52a18eb..d554b64 100644
ddf19c
--- a/hw/ppc/ppc.c
ddf19c
+++ b/hw/ppc/ppc.c
ddf19c
@@ -1510,3 +1510,11 @@ PowerPCCPU *ppc_get_vcpu_by_pir(int pir)
ddf19c
 
ddf19c
     return NULL;
ddf19c
 }
ddf19c
+
ddf19c
+void ppc_irq_reset(PowerPCCPU *cpu)
ddf19c
+{
ddf19c
+    CPUPPCState *env = &cpu->env;
ddf19c
+
ddf19c
+    env->irq_input_state = 0;
ddf19c
+    kvmppc_set_interrupt(cpu, PPC_INTERRUPT_EXT, 0);
ddf19c
+}
ddf19c
diff --git a/include/hw/ppc/ppc.h b/include/hw/ppc/ppc.h
ddf19c
index 4bdcb8b..5dd7531 100644
ddf19c
--- a/include/hw/ppc/ppc.h
ddf19c
+++ b/include/hw/ppc/ppc.h
ddf19c
@@ -76,6 +76,7 @@ static inline void ppc970_irq_init(PowerPCCPU *cpu) {}
ddf19c
 static inline void ppcPOWER7_irq_init(PowerPCCPU *cpu) {}
ddf19c
 static inline void ppcPOWER9_irq_init(PowerPCCPU *cpu) {}
ddf19c
 static inline void ppce500_irq_init(PowerPCCPU *cpu) {}
ddf19c
+static inline void ppc_irq_reset(PowerPCCPU *cpu) {}
ddf19c
 #else
ddf19c
 void ppc40x_irq_init(PowerPCCPU *cpu);
ddf19c
 void ppce500_irq_init(PowerPCCPU *cpu);
ddf19c
@@ -83,6 +84,7 @@ void ppc6xx_irq_init(PowerPCCPU *cpu);
ddf19c
 void ppc970_irq_init(PowerPCCPU *cpu);
ddf19c
 void ppcPOWER7_irq_init(PowerPCCPU *cpu);
ddf19c
 void ppcPOWER9_irq_init(PowerPCCPU *cpu);
ddf19c
+void ppc_irq_reset(PowerPCCPU *cpu);
ddf19c
 #endif
ddf19c
 
ddf19c
 /* PPC machines for OpenBIOS */
ddf19c
diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
ddf19c
index ba726de..64a8380 100644
ddf19c
--- a/target/ppc/translate_init.inc.c
ddf19c
+++ b/target/ppc/translate_init.inc.c
ddf19c
@@ -10461,6 +10461,7 @@ static void ppc_cpu_reset(CPUState *s)
ddf19c
     env->pending_interrupts = 0;
ddf19c
     s->exception_index = POWERPC_EXCP_NONE;
ddf19c
     env->error_code = 0;
ddf19c
+    ppc_irq_reset(cpu);
ddf19c
 
ddf19c
     /* tininess for underflow is detected before rounding */
ddf19c
     set_float_detect_tininess(float_tininess_before_rounding,
ddf19c
-- 
ddf19c
1.8.3.1
ddf19c