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

[Xen-devel] [RFC 07/16] gic-vgic:vgic: do not keep disabled IRQs in any of queues



From: Andrii Anisov <andrii_anisov@xxxxxxxx>

Do not put already disabled IRQs into any of queues, and remove
an IRQ from all queues on disable. Insert the IRQ into queues on
enable if needed. This also allows simplification of under-lock
decission of events needed delivery.

Signed-off-by: Andrii Anisov <andrii_anisov@xxxxxxxx>
---
 xen/arch/arm/gic-vgic.c    | 26 +++++++++-----------------
 xen/arch/arm/vgic.c        | 28 +++++++++++++++++++++++++---
 xen/include/asm-arm/vgic.h |  3 ++-
 3 files changed, 36 insertions(+), 21 deletions(-)

diff --git a/xen/arch/arm/gic-vgic.c b/xen/arch/arm/gic-vgic.c
index 4e18169..9bbd0c5 100644
--- a/xen/arch/arm/gic-vgic.c
+++ b/xen/arch/arm/gic-vgic.c
@@ -87,10 +87,6 @@ void gic_raise_inflight_irq(struct vcpu *v, unsigned int 
virtual_irq)
 
     ASSERT(spin_is_locked(&v->arch.vgic.lock));
 
-    /* Don't try to update the LR if the interrupt is disabled */
-    if ( !test_bit(GIC_IRQ_GUEST_ENABLED, &n->status) )
-        return;
-
     if ( list_empty(&n->lr_queue) )
     {
         if ( v == current )
@@ -366,6 +362,7 @@ int vgic_vcpu_pending_irq(struct vcpu *v)
     const unsigned long apr = gic_hw_ops->read_apr(0);
     int mask_priority;
     int active_priority;
+    int effective_priority;
     int rc = 0;
 
     /* We rely on reading the VMCR, which is only accessible locally. */
@@ -373,28 +370,23 @@ int vgic_vcpu_pending_irq(struct vcpu *v)
 
     mask_priority = gic_hw_ops->read_vmcr_priority();
     active_priority = find_first_bit(&apr, 32);
+    effective_priority = min(mask_priority, active_priority);
 
     spin_lock_irqsave(&v->arch.vgic.lock, flags);
 
     /* TODO: We order the guest irqs by priority, but we don't change
      * the priority of host irqs. */
 
-    /* find the first enabled non-active irq, the queue is already
-     * ordered by priority */
-    list_for_each_entry( p, &v->arch.vgic.inflight_irqs, inflight )
+    /* take the first non-active irq, the queue is already
+     * ordered by priority and has no disabled IRQs*/
+    if ( !list_empty(&v->arch.vgic.inflight_irqs) )
     {
-        if ( GIC_PRI_TO_GUEST(p->priority) >= mask_priority )
-            goto out;
-        if ( GIC_PRI_TO_GUEST(p->priority) >= active_priority )
-            goto out;
-        if ( test_bit(GIC_IRQ_GUEST_ENABLED, &p->status) )
-        {
-            rc = 1;
-            goto out;
-        }
+        p = container_of(v->arch.vgic.inflight_irqs.next, struct pending_irq,
+                          inflight);
+        if ( GIC_PRI_TO_GUEST(p->priority) < effective_priority )
+             rc = 1;
     }
 
-out:
     spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
     return rc;
 }
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 37857b1..e30a518 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -364,6 +364,7 @@ void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n)
         spin_lock_irqsave(&v_target->arch.vgic.lock, flags);
         p = irq_to_pending(v_target, irq);
         clear_bit(GIC_IRQ_GUEST_ENABLED, &p->status);
+        list_del_init(&p->inflight);
         gic_remove_from_lr_pending(v_target, p);
         desc = p->desc;
         spin_unlock_irqrestore(&v_target->arch.vgic.lock, flags);
@@ -415,6 +416,23 @@ void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n)
         spin_lock_irqsave(&v_target->arch.vgic.lock, flags);
         p = irq_to_pending(v_target, irq);
         set_bit(GIC_IRQ_GUEST_ENABLED, &p->status);
+        if ( test_bit(GIC_IRQ_GUEST_VISIBLE, &p->status) ||
+             test_bit(GIC_IRQ_GUEST_QUEUED, &p->status) )
+        {
+            struct pending_irq *iter;
+            p->priority = vgic_get_virq_priority(v, irq);
+            list_for_each_entry( iter, &v_target->arch.vgic.inflight_irqs,
+                                 inflight )
+            {
+                if ( iter->priority > p->priority )
+                {
+                    list_add_tail(&p->inflight, &iter->inflight);
+                    goto out;
+                }
+            }
+            list_add_tail(&p->inflight, &v_target->arch.vgic.inflight_irqs);
+        }
+out:
         if ( !list_empty(&p->inflight) && !test_bit(GIC_IRQ_GUEST_VISIBLE, 
&p->status) )
             gic_raise_guest_irq(v_target, irq, p->priority);
         spin_unlock_irqrestore(&v_target->arch.vgic.lock, flags);
@@ -582,6 +600,12 @@ void vgic_inject_irq(struct domain *d, struct vcpu *v, 
unsigned int virq,
 
     set_bit(GIC_IRQ_GUEST_QUEUED, &n->status);
 
+    if ( !test_bit(GIC_IRQ_GUEST_ENABLED, &n->status) )
+    {/*Do not insert a disabled IRQ into any queue*/
+        spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
+        return;
+    }
+
     if ( !list_empty(&n->inflight) )
     {
         gic_raise_inflight_irq(v, virq);
@@ -591,9 +615,7 @@ void vgic_inject_irq(struct domain *d, struct vcpu *v, 
unsigned int virq,
     priority = vgic_get_virq_priority(v, virq);
     n->priority = priority;
 
-    /* the irq is enabled */
-    if ( test_bit(GIC_IRQ_GUEST_ENABLED, &n->status) )
-        gic_raise_guest_irq(v, virq, priority);
+    gic_raise_guest_irq(v, virq, priority);
 
     list_for_each_entry ( iter, &v->arch.vgic.inflight_irqs, inflight )
     {
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index c5cb63f..7507162 100644
--- a/xen/include/asm-arm/vgic.h
+++ b/xen/include/asm-arm/vgic.h
@@ -58,7 +58,8 @@ struct pending_irq
      * irq is enabled at the vgicd level:
      *
      * GIC_IRQ_GUEST_ENABLED: the guest IRQ is enabled at the VGICD
-     * level (GICD_ICENABLER/GICD_ISENABLER).
+     * level (GICD_ICENABLER/GICD_ISENABLER). Disabled guest IRQ do not appear
+     * in an inflight queue
      *
      * GIC_IRQ_GUEST_MIGRATING: the irq is being migrated to a different
      * vcpu while it is still inflight and on an GICH_LR register on the
-- 
2.7.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

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