[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen master] xen/arm: gic: Add sanity checks gic_route_irq_to_guest



commit 3998a3ce50b0dce1275dc31a3113f99e692cd67a
Author:     Julien Grall <julien.grall@xxxxxxxxxx>
AuthorDate: Wed Apr 1 17:21:44 2015 +0100
Commit:     Ian Campbell <ian.campbell@xxxxxxxxxx>
CommitDate: Thu Apr 2 10:42:35 2015 +0100

    xen/arm: gic: Add sanity checks gic_route_irq_to_guest
    
    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>
---
 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);
--
generated by git-patchbot for /home/xen/git/xen.git#master

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.