From: Volodymyr Babchuk <Volodymyr_Babchuk@epam.com>
To: Mykola Kvach <Mykola_Kvach@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 v5 4/4] xen/arm: vgic: free eSPIs using the bitmap index
Date: Thu, 24 Sep 2026 22:55:53 +0000 [thread overview]
Message-ID: <877bka1cp3.fsf@epam.com> (raw)
In-Reply-To: <8c61cf31b69377737d1f688bded43d123ac55d00.1790160605.git.mykola_kvach@epam.com> (Mykola Kvach's message of "Thu, 24 Sep 2026 23:57:56 +0300")
Hi Mykola,
Mykola Kvach <mykola_kvach@epam.com> writes:
> The allocated_irqs bitmap in the existing vGIC implementation stores eSPI
> allocation bits immediately after the regular vIRQ bits.
> vgic_reserve_virq() converts an eSPI INTID to this compressed bitmap index,
> but vgic_free_virq() used the raw INTID.
>
> Freeing INTID 4096 therefore clears bit 4096 instead of the first eSPI bit.
> This writes beyond allocated_irqs and leaves the intended eSPI bit set.
> Valid eSPIs reach this path during DOMCTL bind failure cleanup and unbind,
> and during vPL011 teardown.
>
> Add virq_to_idx(), the inverse of idx_to_virq(), and use it when reserving
> and freeing vIRQs. Use vgic_is_valid_line() for the validity checks when
> reserving and freeing vIRQs in both vGIC implementations.
>
> Fixes: bdde400c6e1b ("xen/arm: vgic: add resource management for extended SPIs")
> Signed-off-by: Mykola Kvach <mykola_kvach@epam.com>
> Reviewed-by: Michal Orzel <michal.orzel@amd.com>
> ---
> Changes in v5:
> - Add the vgic_is_valid_line() guard to vgic_free_virq() in the new
> vGIC implementation and use the same helper in vgic_reserve_virq().
>
> Changes in v4:
> - Document the compressed bitmap layout with an ASCII diagram above the
> conversion helpers and refer to struct vgic_dist for the full layout.
>
> Changes in v3:
> - Adapt virq_to_idx() to the configuration-neutral is_espi() helper.
>
> Changes in v2:
> - Call is_espi() without a configuration guard.
> ---
> xen/arch/arm/vgic.c | 42 +++++++++++++++++++++++++++++-----------
> xen/arch/arm/vgic/vgic.c | 5 ++++-
> 2 files changed, 35 insertions(+), 12 deletions(-)
>
> diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
> index 0ba13e18da..acded6a40f 100644
> --- a/xen/arch/arm/vgic.c
> +++ b/xen/arch/arm/vgic.c
> @@ -25,6 +25,21 @@
> #include <asm/vgic.h>
>
>
> +/*
> + * The allocated_irqs bitmap is compressed: eSPI bits immediately follow
> + * regular IRQ bits, skipping the gap in the INTID space.
> + *
> + * +-----------+-----------+-------------------+-------------------+
> + * | SGIs | PPIs | SPIs | eSPIs |
> + * +-----------+-----------+-------------------+-------------------+
> + * 0 16 32 vgic_num_irqs(d)
> + *
> + * INTID ESPI_BASE_INTID maps to bitmap index vgic_num_irqs(d).
> + * The following idx_to_virq() and virq_to_idx() convert between INTIDs
> + * and bitmap indexes.
> + *
> + * See also the allocated_irqs comment in struct vgic_dist.
> + */
> static inline unsigned int idx_to_virq(struct domain *d, unsigned int idx)
> {
> if ( idx >= vgic_num_irqs(d) )
> @@ -33,6 +48,16 @@ static inline unsigned int idx_to_virq(struct domain *d, unsigned int idx)
> return idx;
> }
>
> +static inline unsigned int virq_to_idx(struct domain *d, unsigned int virq)
> +{
> + ASSERT(IS_ENABLED(CONFIG_GICV3_ESPI) || !is_espi(virq));
> +
> + if ( IS_ENABLED(CONFIG_GICV3_ESPI) && is_espi(virq) )
> + return espi_intid_to_idx(virq) + vgic_num_irqs(d);
> +
> + return virq;
> +}
> +
> bool vgic_is_valid_line(struct domain *d, unsigned int virq)
> {
> #ifdef CONFIG_GICV3_ESPI
> @@ -854,19 +879,11 @@ bool vgic_emulate(struct cpu_user_regs *regs, union hsr hsr)
>
> bool vgic_reserve_virq(struct domain *d, unsigned int virq)
> {
> - unsigned int idx = virq;
> -
> if ( !vgic_is_valid_line(d, virq) )
> return false;
>
> - if ( is_espi(virq) )
> - {
> - unsigned int num_regular_irqs = vgic_num_irqs(d);
> -
> - idx = espi_intid_to_idx(virq) + num_regular_irqs;
> - }
> -
> - return !test_and_set_bit(idx, d->arch.vgic.allocated_irqs);
> + return !test_and_set_bit(virq_to_idx(d, virq),
> + d->arch.vgic.allocated_irqs);
> }
>
> int vgic_allocate_virq(struct domain *d, bool spi)
> @@ -903,7 +920,10 @@ int vgic_allocate_virq(struct domain *d, bool spi)
>
> void vgic_free_virq(struct domain *d, unsigned int virq)
> {
> - clear_bit(virq, d->arch.vgic.allocated_irqs);
> + if ( !vgic_is_valid_line(d, virq) )
> + return;
I don't think that silently failing is a good idea. It needs an ASSERT()
at least.
> +
> + clear_bit(virq_to_idx(d, virq), d->arch.vgic.allocated_irqs);
> }
>
> unsigned int vgic_max_vcpus(unsigned int domctl_vgic_version)
> diff --git a/xen/arch/arm/vgic/vgic.c b/xen/arch/arm/vgic/vgic.c
> index ba029b8a3b..84212bbefe 100644
> --- a/xen/arch/arm/vgic/vgic.c
> +++ b/xen/arch/arm/vgic/vgic.c
> @@ -712,7 +712,7 @@ bool vgic_evtchn_irq_pending(struct vcpu *v)
>
> bool vgic_reserve_virq(struct domain *d, unsigned int virq)
> {
> - if ( virq >= vgic_num_irqs(d) )
> + if ( !vgic_is_valid_line(d, virq) )
> return false;
>
> return !test_and_set_bit(virq, d->arch.vgic.allocated_irqs);
> @@ -756,6 +756,9 @@ int vgic_allocate_virq(struct domain *d, bool spi)
>
> void vgic_free_virq(struct domain *d, unsigned int virq)
> {
> + if ( !vgic_is_valid_line(d, virq) )
> + return;
> +
> clear_bit(virq, d->arch.vgic.allocated_irqs);
> }
--
WBR, Volodymyr
next prev parent reply other threads:[~2026-09-24 22:56 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-24 20:57 [PATCH v5 0/4] xen/arm: Fix eSPI IRQ handling Mykola Kvach
2026-09-24 20:57 ` [PATCH v5 1/4] xen/arm: handle irq_set_type() failures Mykola Kvach
2026-09-25 11:09 ` Orzel, Michal
2026-09-24 20:57 ` [PATCH v5 2/4] xen/arm: make is_espi() a pure range predicate Mykola Kvach
2026-09-24 22:48 ` Volodymyr Babchuk
2026-09-25 11:10 ` Orzel, Michal
2026-09-24 20:57 ` [PATCH v5 3/4] xen/arm: validate IRQs before descriptor lookup Mykola Kvach
2026-09-24 20:57 ` [PATCH v5 4/4] xen/arm: vgic: free eSPIs using the bitmap index Mykola Kvach
2026-09-24 22:55 ` Volodymyr Babchuk [this message]
2026-09-25 11:16 ` Orzel, Michal
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=877bka1cp3.fsf@epam.com \
--to=volodymyr_babchuk@epam.com \
--cc=Mykola_Kvach@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.