|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v5 p1 11/14] xen/arm: gic: Add sanity checks gic_route_irq_to_guest
From: Julien Grall <julien.grall@xxxxxxxxxx>
With the addition of interrupt assignment to guest, we need to make sure
the guest can't blow up the interrupt management in Xen.
Before associating the IRQ to a vIRQ we need to make sure:
- the vIRQ is not already associated to another IRQ
- the guest didn't enable the vIRQ
Signed-off-by: Julien Grall <julien.grall@xxxxxxxxxx>
Acked-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
Acked-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
---
Changes in v5:
- Add Ian's ack
Changes in v4:
- Move functional change (GIC_IRQ_PRI -> priority) in a separate
patch.
- Split the 2 conditions of the ASSERT in 2 different ASSERTs
- Typoes
- Add Stefano's ack
Changes in v3:
- Patch added
---
xen/arch/arm/gic.c | 35 +++++++++++++++++++++++++++--------
xen/arch/arm/irq.c | 12 ++++++++++--
xen/include/asm-arm/gic.h | 7 +++----
3 files changed, 40 insertions(+), 14 deletions(-)
diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index fe8f69b..2709415 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -126,22 +126,41 @@ void gic_route_irq_to_xen(struct irq_desc *desc, const
cpumask_t *cpu_mask,
/* Program the GIC to route an interrupt to a guest
* - desc.lock must be held
*/
-void gic_route_irq_to_guest(struct domain *d, unsigned int virq,
- struct irq_desc *desc,
- const cpumask_t *cpu_mask, unsigned int priority)
+int gic_route_irq_to_guest(struct domain *d, unsigned int virq,
+ struct irq_desc *desc, unsigned int priority)
{
- struct pending_irq *p;
+ unsigned long flags;
+ /* Use vcpu0 to retrieve the pending_irq struct. Given that we only
+ * route SPIs to guests, it doesn't make any difference. */
+ struct vcpu *v_target = vgic_get_target_vcpu(d->vcpu[0], virq);
+ struct vgic_irq_rank *rank = vgic_rank_irq(v_target, virq);
+ struct pending_irq *p = irq_to_pending(v_target, virq);
+ int res = -EBUSY;
+
ASSERT(spin_is_locked(&desc->lock));
+ /* Caller has already checked that the IRQ is an SPI */
+ ASSERT(virq >= 32);
+ ASSERT(virq < vgic_num_irqs(d));
+
+ vgic_lock_rank(v_target, rank, flags);
+
+ if ( p->desc ||
+ /* The VIRQ should not be already enabled by the guest */
+ test_bit(GIC_IRQ_GUEST_ENABLED, &p->status) )
+ goto out;
desc->handler = gic_hw_ops->gic_guest_irq_type;
set_bit(_IRQ_GUEST, &desc->status);
- gic_set_irq_properties(desc, cpumask_of(smp_processor_id()), GIC_PRI_IRQ);
+ gic_set_irq_properties(desc, cpumask_of(v_target->processor), GIC_PRI_IRQ);
- /* Use vcpu0 to retrieve the pending_irq struct. Given that we only
- * route SPIs to guests, it doesn't make any difference. */
- p = irq_to_pending(d->vcpu[0], virq);
p->desc = desc;
+ res = 0;
+
+out:
+ vgic_unlock_rank(v_target, rank, flags);
+
+ return res;
}
int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c
index 4c3e381..b2ddf6b 100644
--- a/xen/arch/arm/irq.c
+++ b/xen/arch/arm/irq.c
@@ -492,14 +492,22 @@ int route_irq_to_guest(struct domain *d, unsigned int
virq,
if ( retval )
goto out;
- gic_route_irq_to_guest(d, virq, desc, cpumask_of(smp_processor_id()),
- GIC_PRI_IRQ);
+ retval = gic_route_irq_to_guest(d, virq, desc, GIC_PRI_IRQ);
+
spin_unlock_irqrestore(&desc->lock, flags);
+
+ if ( retval )
+ {
+ release_irq(desc->irq, info);
+ goto free_info;
+ }
+
return 0;
out:
spin_unlock_irqrestore(&desc->lock, flags);
xfree(action);
+free_info:
xfree(info);
return retval;
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index bb2a922..ef4bf9a 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -216,10 +216,9 @@ extern enum gic_version gic_hw_version(void);
/* Program the GIC to route an interrupt */
extern void gic_route_irq_to_xen(struct irq_desc *desc, const cpumask_t
*cpu_mask,
unsigned int priority);
-extern void gic_route_irq_to_guest(struct domain *, unsigned int virq,
- struct irq_desc *desc,
- const cpumask_t *cpu_mask,
- unsigned int priority);
+extern int gic_route_irq_to_guest(struct domain *, unsigned int virq,
+ struct irq_desc *desc,
+ unsigned int priority);
extern void gic_inject(void);
extern void gic_clear_pending_irqs(struct vcpu *v);
--
2.1.4
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |