[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [RFC v2 08/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 74ab357..a59295a 100644 --- a/xen/arch/arm/gic-vgic.c +++ b/xen/arch/arm/gic-vgic.c @@ -101,10 +101,6 @@ void gic_raise_inflight_irq(struct vcpu *v, struct pending_irq *n) 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 ) @@ -382,6 +378,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. */ @@ -389,28 +386,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 371576f..ab301d9 100644 --- a/xen/arch/arm/vgic.c +++ b/xen/arch/arm/vgic.c @@ -383,6 +383,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); @@ -434,6 +435,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, p); spin_unlock_irqrestore(&v_target->arch.vgic.lock, flags); @@ -601,6 +619,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, n); @@ -610,9 +634,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, n); + gic_raise_guest_irq(v, n); 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 0b1f519..a27a1a9 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |