From mboxrd@z Thu Jan 1 00:00:00 1970 Message-ID: <494BBB5A.90805@domain.hid> Date: Fri, 19 Dec 2008 16:18:50 +0100 From: Jan Kiszka MIME-Version: 1.0 References: <494B6A26.1040001@domain.hid> In-Reply-To: <494B6A26.1040001@domain.hid> Content-Type: text/plain; charset=ISO-8859-15 Content-Transfer-Encoding: 7bit Subject: Re: [Adeos-main] [RFC][PATCH] x86-64: Enable root domain IRQ migration List-Id: General discussion about Adeos List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: adeos-main 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)