aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2017-01-16 12:58:53 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-01-26 02:24:39 -0500
commit09187cdf50c17a5f537b78a3154c4b1014d9a36e (patch)
tree751dfae449e85e244c20a679bd15b9c7279d31c2
parent26c4d513b6af730941bb4ff4c237789a4d190c27 (diff)
powerpc/icp-opal: Fix missing KVM case and harden replay
commit 9728a7c8ab2f7a1c8d5c95278d2e4f4ac1285385 upstream. The icp-opal call is missing the code from icp-native to recover interrupts snatched by KVM. Without that, when running KVM, we can get into a situation where an interrupt is lost and the CPU stuck with an elevated CPPR. Also harden replay by always checking the return from opal_int_eoi(). Fixes: d74361881f0d ("powerpc/xics: Add ICP OPAL backend") Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--arch/powerpc/sysdev/xics/icp-opal.c31
1 files changed, 24 insertions, 7 deletions
diff --git a/arch/powerpc/sysdev/xics/icp-opal.c b/arch/powerpc/sysdev/xics/icp-opal.c
index d38e86fd5720..60c57657c772 100644
--- a/arch/powerpc/sysdev/xics/icp-opal.c
+++ b/arch/powerpc/sysdev/xics/icp-opal.c
@@ -20,6 +20,7 @@
20#include <asm/xics.h> 20#include <asm/xics.h>
21#include <asm/io.h> 21#include <asm/io.h>
22#include <asm/opal.h> 22#include <asm/opal.h>
23#include <asm/kvm_ppc.h>
23 24
24static void icp_opal_teardown_cpu(void) 25static void icp_opal_teardown_cpu(void)
25{ 26{
@@ -39,7 +40,26 @@ static void icp_opal_flush_ipi(void)
39 * Should we be flagging idle loop instead? 40 * Should we be flagging idle loop instead?
40 * Or creating some task to be scheduled? 41 * Or creating some task to be scheduled?
41 */ 42 */
42 opal_int_eoi((0x00 << 24) | XICS_IPI); 43 if (opal_int_eoi((0x00 << 24) | XICS_IPI) > 0)
44 force_external_irq_replay();
45}
46
47static unsigned int icp_opal_get_xirr(void)
48{
49 unsigned int kvm_xirr;
50 __be32 hw_xirr;
51 int64_t rc;
52
53 /* Handle an interrupt latched by KVM first */
54 kvm_xirr = kvmppc_get_xics_latch();
55 if (kvm_xirr)
56 return kvm_xirr;
57
58 /* Then ask OPAL */
59 rc = opal_int_get_xirr(&hw_xirr, false);
60 if (rc < 0)
61 return 0;
62 return be32_to_cpu(hw_xirr);
43} 63}
44 64
45static unsigned int icp_opal_get_irq(void) 65static unsigned int icp_opal_get_irq(void)
@@ -47,12 +67,8 @@ static unsigned int icp_opal_get_irq(void)
47 unsigned int xirr; 67 unsigned int xirr;
48 unsigned int vec; 68 unsigned int vec;
49 unsigned int irq; 69 unsigned int irq;
50 int64_t rc;
51 70
52 rc = opal_int_get_xirr(&xirr, false); 71 xirr = icp_opal_get_xirr();
53 if (rc < 0)
54 return 0;
55 xirr = be32_to_cpu(xirr);
56 vec = xirr & 0x00ffffff; 72 vec = xirr & 0x00ffffff;
57 if (vec == XICS_IRQ_SPURIOUS) 73 if (vec == XICS_IRQ_SPURIOUS)
58 return 0; 74 return 0;
@@ -67,7 +83,8 @@ static unsigned int icp_opal_get_irq(void)
67 xics_mask_unknown_vec(vec); 83 xics_mask_unknown_vec(vec);
68 84
69 /* We might learn about it later, so EOI it */ 85 /* We might learn about it later, so EOI it */
70 opal_int_eoi(xirr); 86 if (opal_int_eoi(xirr) > 0)
87 force_external_irq_replay();
71 88
72 return 0; 89 return 0;
73} 90}