From: Volodymyr Babchuk <Volodymyr_Babchuk@epam.com>
To: Mykyta Poturai <Mykyta_Poturai@epam.com>
Cc: "xen-devel@lists.xenproject.org" <xen-devel@lists.xenproject.org>,
Stefano Stabellini <sstabellini@kernel.org>,
Julien Grall <julien@xen.org>,
Bertrand Marquis <bertrand.marquis@arm.com>,
Michal Orzel <michal.orzel@amd.com>
Subject: Re: [PATCH v9 2/6] arm/irq: Migrate IRQs during CPU up/down operations
Date: Tue, 22 Sep 2026 01:01:52 +0000 [thread overview]
Message-ID: <87jyoe85fk.fsf@epam.com> (raw)
In-Reply-To: <55f4839f427df6675a621bb61bfbdac4fb089382.1787042017.git.mykyta_poturai@epam.com> (Mykyta Poturai's message of "Tue, 18 Aug 2026 08:48:29 +0000")
Sorry, forgot to comment one more thing...
Mykyta Poturai <Mykyta_Poturai@epam.com> writes:
> Move IRQs from dying CPU to the online ones when a CPU is getting
> offlined. When onlining, rebalance all IRQs in a round-robin fashion.
> Guest-bound IRQs are already handled by scheduler in the process of
> moving vCPUs to active pCPUs, so we only need to handle IRQs used by Xen
> itself.
>
> Signed-off-by: Mykyta Poturai <mykyta_poturai@epam.com>
> ---
> v8->v9:
> * replace CONFIG_CPU_HOTPLUG with CONFIG_CPU_ONLINE_OFFLINE
>
> v7->v8:
> * check only existings ESPIs
>
> v6->v7:
> * replace ifdef with IS_ENABLED
>
> v5->v6:
> * don't do any balancing on boot
> * only do balancing when cpu hotplug is enabled
>
> v4->v5:
> * handle CPU onlining as well
> * more comments
> * fix crash when ESPI is disabled
> * don't assume CPU 0 is a boot CPU
> * use insigned int for irq number
> * remove assumption that all irqs a bound to CPU 0 by default from the
> commit message
>
> v3->v4:
> * patch introduced
> ---
> xen/arch/arm/include/asm/irq.h | 6 ++++
> xen/arch/arm/irq.c | 60 ++++++++++++++++++++++++++++++++++
> xen/arch/arm/smpboot.c | 7 ++++
> 3 files changed, 73 insertions(+)
>
> diff --git a/xen/arch/arm/include/asm/irq.h b/xen/arch/arm/include/asm/irq.h
> index 09788dbfeb..d043360135 100644
> --- a/xen/arch/arm/include/asm/irq.h
> +++ b/xen/arch/arm/include/asm/irq.h
> @@ -126,6 +126,12 @@ bool irq_type_set_by_domain(const struct domain *d);
> void irq_end_none(struct irq_desc *irq);
> #define irq_end_none irq_end_none
>
> +#ifdef CONFIG_CPU_ONLINE_OFFLINE
> +void rebalance_irqs(unsigned int from, bool up);
> +#else
> +static inline void rebalance_irqs(unsigned int from, bool up) {}
> +#endif
> +
> #endif /* _ASM_HW_IRQ_H */
> /*
> * Local variables:
> diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c
> index 7204bc2b68..6445183f5c 100644
> --- a/xen/arch/arm/irq.c
> +++ b/xen/arch/arm/irq.c
> @@ -158,6 +158,61 @@ static int init_local_irq_data(unsigned int cpu)
> return 0;
> }
>
> +#ifdef CONFIG_CPU_ONLINE_OFFLINE
> +static int cpu_next;
This variable is used only in balance_irq(). Maybe make it static for
that function? No need in keeping it global.
> +
> +static void balance_irq(int irq, unsigned int from, bool up)
> +{
> + struct irq_desc *desc = irq_to_desc(irq);
> + unsigned long flags;
> +
> + ASSERT(!cpumask_empty(&cpu_online_map));
> +
> + spin_lock_irqsave(&desc->lock, flags);
> + if ( likely(!desc->action) )
> + goto out;
> +
> + if ( likely(test_bit(_IRQ_GUEST, &desc->status) ||
> + test_bit(_IRQ_MOVE_PENDING, &desc->status)) )
> + goto out;
> +
> + /*
> + * Setting affinity to a mask of multiple CPUs causes the GIC drivers to
> + * select one CPU from that mask. If the dying CPU was included in the IRQ's
> + * affinity mask, we cannot determine exactly which CPU the interrupt is
> + * currently routed to, as GIC drivers lack a concrete get_affinity API. So
> + * to be safe we must reroute it to a new, definitely online, CPU. In the
> + * case of CPU going down, we move only the interrupt that could reside on
> + * it. Otherwise, we rearrange all interrupts in a round-robin fashion.
> + */
> + if ( !up && !cpumask_test_cpu(from, desc->affinity) )
> + goto out;
> +
> + cpu_next = cpumask_cycle(cpu_next, &cpu_online_map);
> + irq_set_affinity(desc, cpumask_of(cpu_next));
> +
> +out:
> + spin_unlock_irqrestore(&desc->lock, flags);
> +}
> +
> +void rebalance_irqs(unsigned int from, bool up)
> +{
> + int irq;
> +
> + if ( cpumask_empty(&cpu_online_map) )
> + return;
> +
> + for ( irq = NR_LOCAL_IRQS; irq < NR_IRQS; irq++ )
> + balance_irq(irq, from, up);
> +
> +#ifdef CONFIG_GICV3_ESPI
> + for ( irq = ESPI_BASE_INTID; irq < ESPI_BASE_INTID + gic_number_espis();
> + irq++ )
> + balance_irq(irq, from, up);
> +#endif
> +}
> +#endif /* CONFIG_CPU_ONLINE_OFFLINE */
> +
> static int cpu_callback(struct notifier_block *nfb, unsigned long action,
> void *hcpu)
> {
> @@ -172,6 +227,11 @@ static int cpu_callback(struct notifier_block *nfb, unsigned long action,
> printk(XENLOG_ERR "Unable to allocate local IRQ for CPU%u\n",
> cpu);
> break;
> + case CPU_ONLINE:
> + if ( IS_ENABLED(CONFIG_CPU_ONLINE_OFFLINE) &&
> + system_state >= SYS_STATE_active )
> + rebalance_irqs(cpu, true);
> + break;
> }
>
> return notifier_from_errno(rc);
> diff --git a/xen/arch/arm/smpboot.c b/xen/arch/arm/smpboot.c
> index 1806c47a08..239d4a7a25 100644
> --- a/xen/arch/arm/smpboot.c
> +++ b/xen/arch/arm/smpboot.c
> @@ -433,6 +433,13 @@ void __cpu_disable(void)
>
> smp_mb();
>
> + /*
> + * Now that the interrupts are cleared and the CPU marked as offline,
> + * move interrupts out of it
> + */
> + if ( IS_ENABLED(CONFIG_CPU_ONLINE_OFFLINE) )
> + rebalance_irqs(cpu, false);
> +
> /* Return to caller; eventually the IPI mechanism will unwind and the
> * scheduler will drop to the idle loop, which will call stop_cpu(). */
> }
--
WBR, Volodymyr
next prev parent reply other threads:[~2026-09-22 1:02 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-18 8:48 [PATCH v9 0/6] Implement CPU hotplug on Arm Mykyta Poturai
2026-08-18 8:48 ` [PATCH v9 2/6] arm/irq: Migrate IRQs during CPU up/down operations Mykyta Poturai
2026-09-22 0:59 ` Volodymyr Babchuk
2026-09-22 1:01 ` Volodymyr Babchuk [this message]
2026-08-18 8:48 ` [PATCH v9 1/6] arm/irq: Keep track of irq affinities Mykyta Poturai
2026-08-18 8:48 ` [PATCH v9 3/6] Kconfig: Make cpu hotplug configurable Mykyta Poturai
2026-08-18 8:48 ` [PATCH v9 4/6] arm/sysctl: Implement cpu hotplug ops Mykyta Poturai
2026-08-18 9:07 ` Jan Beulich
2026-08-18 8:48 ` [PATCH v9 6/6] docs: Document CPU hotplug Mykyta Poturai
2026-09-22 1:13 ` Volodymyr Babchuk
2026-10-08 8:48 ` Mykyta Poturai
2026-08-18 8:48 ` [PATCH v9 5/6] tools: Allow building xen-hptool without CONFIG_MIGRATE Mykyta Poturai
2026-09-09 9:00 ` Anthony PERARD
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87jyoe85fk.fsf@epam.com \
--to=volodymyr_babchuk@epam.com \
--cc=Mykyta_Poturai@epam.com \
--cc=bertrand.marquis@arm.com \
--cc=julien@xen.org \
--cc=michal.orzel@amd.com \
--cc=sstabellini@kernel.org \
--cc=xen-devel@lists.xenproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.