Jan Kiszka wrote:
> Currently, I-pipe breaks the setting of IRQ affinities through Linux,
> the root domain. This is because migrating IRQs while they are active is
> a tricky business on x86, requiring special measures within the IRQ ack
> path. And as this path is now used by non-root domains, the migration
> code had to be deactivated.
> 
> The following patch is a proof of concept for x86-64 how to overcome
> this unfortunate limitation (if you want to isolate RT from non-RT
> CPUs). The approach works without adding code to critical paths. First
> tests inside KVM indicate that things work as expected, but more testing
> on real iron is scheduled, e.g. to check MSI IRQs which I don't have in
> my KVM environment.
> 

Here is version 2, now also including 32-bit support (untested).

Meanwhile I've run this patch on an real dual core box with MSI, and all
works smoothly.

Jan
---
 arch/x86/kernel/io_apic_32.c |   24 ++++++++++++++++++++++++
 arch/x86/kernel/io_apic_64.c |   42 +++++++++++++++++++++++++++++++++++++-----
 include/asm-x86/ipipe.h      |   11 +++++++++++
 include/asm-x86/ipipe_64.h   |    5 +++--
 include/linux/irq.h          |    3 +++
 5 files changed, 78 insertions(+), 7 deletions(-)

Index: b/arch/x86/kernel/io_apic_64.c
===================================================================
--- a/arch/x86/kernel/io_apic_64.c
+++ b/arch/x86/kernel/io_apic_64.c
@@ -174,7 +174,6 @@ static inline void io_apic_modify(unsign
        writel(value, &io_apic->data);
 }
 
-#ifndef CONFIG_IPIPE
 static bool io_apic_level_ack_pending(unsigned int irq)
 {
        struct irq_pin_list *entry;
@@ -203,7 +202,6 @@ static bool io_apic_level_ack_pending(un
 
        return false;
 }
-#endif /* !CONFIG_IPIPE */
 
 /*
  * Synchronize the IO-APIC and the CPU by doing
@@ -1436,7 +1434,6 @@ unlock:
        irq_exit();
 }
 
-#ifndef CONFIG_IPIPE
 static void irq_complete_move(unsigned int irq)
 {
        struct irq_cfg *cfg = irq_cfg + irq;
@@ -1456,11 +1453,34 @@ static void irq_complete_move(unsigned i
                cfg->move_in_progress = 0;
        }
 }
-#endif
-#elif !defined(CONFIG_IPIPE)
+#else
 static inline void irq_complete_move(unsigned int irq) {}
 #endif
 
+#ifdef CONFIG_IPIPE
+static void move_apic_irq(unsigned int irq)
+{
+       struct irq_desc *desc = &irq_desc[irq];
+
+       if (desc->handle_irq == &handle_edge_irq) {
+               spin_lock(&desc->lock);
+               irq_complete_move(irq);
+               move_native_irq(irq);
+               spin_unlock(&desc->lock);
+       } else if (desc->handle_irq == &handle_fasteoi_irq) {
+               spin_lock(&desc->lock);
+               irq_complete_move(irq);
+               if (unlikely(desc->status & IRQ_MOVE_PENDING)) {
+                       if (!io_apic_level_ack_pending(irq))
+                               move_masked_irq(irq);
+                       unmask_IO_APIC_irq(irq);
+               }
+               spin_unlock(&desc->lock);
+       } else
+               WARN_ON_ONCE(1);
+}
+#endif /* CONFIG_IPIPE */
+
 static void ack_apic_edge(unsigned int irq)
 {
 #ifndef CONFIG_IPIPE
@@ -1544,6 +1564,9 @@ static struct irq_chip ioapic_chip __rea
        .eoi            = ack_apic_level,
 #ifdef CONFIG_SMP
        .set_affinity   = set_ioapic_affinity_irq,
+#ifdef CONFIG_IPIPE
+       .move           = move_apic_irq,
+#endif
 #endif
        .retrigger      = ioapic_retrigger_irq,
 };
@@ -2087,6 +2110,9 @@ static struct irq_chip msi_chip = {
        .ack            = ack_apic_edge,
 #ifdef CONFIG_SMP
        .set_affinity   = set_msi_irq_affinity,
+#ifdef CONFIG_IPIPE
+       .move           = move_apic_irq,
+#endif
 #endif
        .retrigger      = ioapic_retrigger_irq,
 };
@@ -2156,6 +2182,9 @@ struct irq_chip dmar_msi_type = {
        .ack = ack_apic_edge,
 #ifdef CONFIG_SMP
        .set_affinity = dmar_msi_set_affinity,
+#ifdef CONFIG_IPIPE
+       .move = move_apic_irq,
+#endif
 #endif
        .retrigger = ioapic_retrigger_irq,
 };
@@ -2225,6 +2254,9 @@ static struct irq_chip ht_irq_chip = {
        .ack            = ack_apic_edge,
 #ifdef CONFIG_SMP
        .set_affinity   = set_ht_irq_affinity,
+#ifdef CONFIG_IPIPE
+       .move           = move_apic_irq,
+#endif
 #endif
        .retrigger      = ioapic_retrigger_irq,
 };
Index: b/include/asm-x86/ipipe_64.h
===================================================================
--- a/include/asm-x86/ipipe_64.h
+++ b/include/asm-x86/ipipe_64.h
@@ -144,10 +144,11 @@ static inline void __ipipe_call_root_vir
        do {                                                            \
                local_irq_enable_nohead(ipd);                           \
                if (ipd == ipipe_root_domain) {                         \
-                       if (likely(!ipipe_virtual_irq_p(irq)))          \
+                       if (likely(!ipipe_virtual_irq_p(irq))) {        \
+                               __ipipe_move_root_irq(irq);             \
                                __ipipe_call_root_xirq_handler(         \
                                        irq, (ipd)->irqs[irq].handler); \
-                       else                                            \
+                       } else                                          \
                                __ipipe_call_root_virq_handler(         \
                                        irq, (ipd)->irqs[irq].handler,  \
                                        (ipd)->irqs[irq].cookie);       \
Index: b/include/linux/irq.h
===================================================================
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -111,6 +111,9 @@ struct irq_chip {
 
        void            (*end)(unsigned int irq);
        void            (*set_affinity)(unsigned int irq, cpumask_t dest);
+#ifdef CONFIG_IPIPE
+       void            (*move)(unsigned int irq);
+#endif /* CONFIG_IPIPE */
        int             (*retrigger)(unsigned int irq);
        int             (*set_type)(unsigned int irq, unsigned int flow_type);
        int             (*set_wake)(unsigned int irq, unsigned int on);
Index: b/arch/x86/kernel/io_apic_32.c
===================================================================
--- a/arch/x86/kernel/io_apic_32.c
+++ b/arch/x86/kernel/io_apic_32.c
@@ -1929,6 +1929,21 @@ static unsigned int startup_ioapic_irq(u
        return was_pending;
 }
 
+#if defined(CONFIG_IPIPE) && defined(CONFIG_SMP)
+static void move_apic_irq(unsigned int irq)
+{
+       struct irq_desc *desc = &irq_desc[irq];
+
+       if (desc->handle_irq == &handle_edge_irq ||
+           desc->handle_irq == &handle_fasteoi_irq) {
+               spin_lock(&desc->lock);
+               move_native_irq(irq);
+               spin_unlock(&desc->lock);
+       } else
+               WARN_ON_ONCE(1);
+}
+#endif /* CONFIG_IPIPE && CONFIG_SMP */
+
 static void ack_ioapic_irq(unsigned int irq)
 {
 #ifndef CONFIG_IPIPE
@@ -2018,6 +2033,9 @@ static struct irq_chip ioapic_chip __rea
        .eoi            = ack_ioapic_quirk_irq,
 #ifdef CONFIG_SMP
        .set_affinity   = set_ioapic_affinity_irq,
+#ifdef CONFIG_IPIPE
+       .move           = move_apic_irq,
+#endif
 #endif
        .retrigger      = ioapic_retrigger_irq,
 };
@@ -2600,6 +2618,9 @@ static struct irq_chip msi_chip = {
        .ack            = ack_ioapic_irq,
 #ifdef CONFIG_SMP
        .set_affinity   = set_msi_irq_affinity,
+#ifdef CONFIG_IPIPE
+       .move           = move_apic_irq,
+#endif
 #endif
        .retrigger      = ioapic_retrigger_irq,
 };
@@ -2680,6 +2701,9 @@ static struct irq_chip ht_irq_chip = {
        .ack            = ack_ioapic_irq,
 #ifdef CONFIG_SMP
        .set_affinity   = set_ht_irq_affinity,
+#ifdef CONFIG_IPIPE
+       .move           = move_apic_irq,
+#endif
 #endif
        .retrigger      = ioapic_retrigger_irq,
 };
Index: b/include/asm-x86/ipipe.h
===================================================================
--- a/include/asm-x86/ipipe.h
+++ b/include/asm-x86/ipipe.h
@@ -118,6 +118,17 @@ int __ipipe_check_tickdev(const char *de
 
 #define __ipipe_root_tick_p(regs)      ((regs)->flags & X86_EFLAGS_IF)
 
+#ifdef CONFIG_SMP
+#define __ipipe_move_root_irq(irq)                                     \
+       do {                                                            \
+               struct irq_chip *chip = irq_desc[irq].chip;             \
+               if (irq < NR_IRQS && chip->move)                        \
+                       chip->move(irq);                                \
+       } while (0)
+#else /* !CONFIG_SMP */
+#define __ipipe_move_root_irq(irq)     do { } while (0)
+#endif /* !CONFIG_SMP */
+
 #else /* !CONFIG_IPIPE */
 
 #define ipipe_update_tick_evtdev(evtdev)       do { } while (0)

_______________________________________________
Adeos-main mailing list
[email protected]
https://mail.gna.org/listinfo/adeos-main

Reply via email to