[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 |