|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH for-4.22 2/2] xen/arm: vgic: free eSPIs using the bitmap index
Classic vGIC stores eSPIs in allocated_irqs after the regular virtual
interrupts. vgic_reserve_virq() therefore translates an eSPI INTID to a
compressed bitmap index before test_and_set_bit().
vgic_free_virq() still used the raw virtual INTID. Freeing INTID 4096
would clear bit 4096 instead of the first eSPI allocation bit, which is
outside allocated_irqs for a domain with eSPI support. That can leave
the eSPI reserved and may corrupt memory.
Add the inverse of idx_to_virq() and use it in both reserve and free, so
the allocation bitmap is indexed consistently. Also reject invalid
virtual INTIDs before clearing the bitmap.
Fixes: bdde400c6e1b ("xen/arm: vgic: add resource management for extended SPIs")
Signed-off-by: Mykola Kvach <mykola_kvach@xxxxxxxx>
---
xen/arch/arm/vgic.c | 27 ++++++++++++++++-----------
1 file changed, 16 insertions(+), 11 deletions(-)
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index e5aca17dcb..b85710c6a7 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -33,6 +33,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)
+{
+#ifdef CONFIG_GICV3_ESPI
+ if ( is_espi(virq) )
+ return espi_intid_to_idx(virq) + vgic_num_irqs(d);
+#endif
+
+ return virq;
+}
+
bool vgic_is_valid_line(struct domain *d, unsigned int virq)
{
#ifdef CONFIG_GICV3_ESPI
@@ -848,19 +858,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)
@@ -897,7 +899,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;
+
+ clear_bit(virq_to_idx(d, virq), d->arch.vgic.allocated_irqs);
}
unsigned int vgic_max_vcpus(unsigned int domctl_vgic_version)
--
2.43.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |