diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2017-01-16 12:58:53 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-01-26 02:24:39 -0500 |
commit | 09187cdf50c17a5f537b78a3154c4b1014d9a36e (patch) | |
tree | 751dfae449e85e244c20a679bd15b9c7279d31c2 | |
parent | 26c4d513b6af730941bb4ff4c237789a4d190c27 (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.c | 31 |
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 | ||
24 | static void icp_opal_teardown_cpu(void) | 25 | static 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 | |||
47 | static 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 | ||
45 | static unsigned int icp_opal_get_irq(void) | 65 | static 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 | } |