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