The CPU hotplugging code might re-trigger a vector. In that case the
vector is in the VECTOR_RETRIGGERED state. With this patch applied ipipe
does no longer call BUG() for such vectors.

This is a backport from the 4.19 and 5.4 ipipe branches handling the
VECTOR_SHUTDOWN state. The VECTOR_SHUTDOWN case itself does not exist in
4.4, but the VECTOR_RETRIGGERED case does.

__ipipe_handle_irq() is now synchronized with do_IRQ().

Signed-off-by: Florian Bezdeka <florian.bezd...@siemens.com>
---
 arch/x86/kernel/ipipe.c | 44 +++++++++++++++++++++++++++++++----------
 1 file changed, 34 insertions(+), 10 deletions(-)

diff --git a/arch/x86/kernel/ipipe.c b/arch/x86/kernel/ipipe.c
index 739b5c37ec7b..6020739256f9 100644
--- a/arch/x86/kernel/ipipe.c
+++ b/arch/x86/kernel/ipipe.c
@@ -33,6 +33,7 @@
 #include <linux/mm.h>
 #include <linux/kgdb.h>
 #include <linux/ipipe_tickdev.h>
+#include <linux/ratelimit.h>
 #include <asm/asm-offsets.h>
 #include <asm/unistd.h>
 #include <asm/processor.h>
@@ -428,22 +429,44 @@ skip_kgdb:
        return 0;
 }
 
+static inline int __ipipe_irq_from_vector(int vector, int *irq)
+{
+       struct irq_desc *desc;
+
+       if (vector >= FIRST_SYSTEM_VECTOR) {
+               *irq = ipipe_apic_vector_irq(vector);
+               return 0;
+       }
+
+       desc = __this_cpu_read(vector_irq[vector]);
+       if (likely(!IS_ERR_OR_NULL(desc))) {
+               *irq = irq_desc_get_irq(desc);
+               return 0;
+       }
+
+#ifdef CONFIG_X86_LOCAL_APIC
+       __ack_APIC_irq();
+#endif
+
+       if (desc == VECTOR_UNUSED) {
+               pr_emerg_ratelimited("%s: %d.%d Unexpected IRQ trap\n",
+                                    __func__, smp_processor_id(), vector);
+       } else {
+               __this_cpu_write(vector_irq[vector], VECTOR_UNUSED);
+       }
+
+       return -1;
+}
+
 int __ipipe_handle_irq(struct pt_regs *regs)
 {
        struct ipipe_percpu_data *p = __ipipe_raw_cpu_ptr(&ipipe_percpu);
        int irq, vector = regs->orig_ax, flags = 0;
        struct pt_regs *tick_regs;
-       struct irq_desc *desc;
 
        if (likely(vector < 0)) {
-               vector = ~vector;
-               if (vector >= FIRST_SYSTEM_VECTOR)
-                       irq = ipipe_apic_vector_irq(vector);
-               else {
-                       desc = __this_cpu_read(vector_irq[vector]);
-                       BUG_ON(IS_ERR_OR_NULL(desc));
-                       irq = irq_desc_get_irq(desc);
-               }
+               if (__ipipe_irq_from_vector(~vector, &irq) < 0)
+                       goto out;
        } else { /* Software-generated. */
                irq = vector;
                flags = IPIPE_IRQF_NOACK;
@@ -477,7 +500,8 @@ int __ipipe_handle_irq(struct pt_regs *regs)
                __ipipe_call_mayday(regs);
 
        ipipe_trace_irqend(irq, regs);
-       
+
+out:
        if (!__ipipe_root_p ||
            test_bit(IPIPE_STALL_FLAG, &__ipipe_root_status))
                return 0;
-- 
2.30.2


Reply via email to