[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v3 14/39] ARM: new VGIC: Add GICv2 world switch backend
This is a "patch to the patch" mentioned above, to make it clear what changed: We now take the desc lock in vgic_v2_fold_lr_state() when we are dealing with a hardware IRQ. This is a bit complicated, because we have to obey the existing locking order, so do our infamous "drop-take-retake" dance. Also I print a message about using the new VGIC and fix that last remaining "u32" usage. Please note that I had to initialise "desc" to NULL because my compiler (GCC 5.3) is not smart enough to see that we only use it with irq->hw set and it's safe. Please let me know if it's me not being smart enough here instead ;-) Signed-off-by: Andre Przywara <andre.przywara@xxxxxxxxxx> --- Hi, will send a proper, merged v3a version of the patch separately. Cheers, Andre xen/arch/arm/vgic/vgic-v2.c | 43 ++++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/xen/arch/arm/vgic/vgic-v2.c b/xen/arch/arm/vgic/vgic-v2.c index 5516a8534f..3424a4a66f 100644 --- a/xen/arch/arm/vgic/vgic-v2.c +++ b/xen/arch/arm/vgic/vgic-v2.c @@ -43,6 +43,8 @@ void vgic_v2_setup_hw(paddr_t dbase, paddr_t cbase, paddr_t csize, gic_v2_hw_data.csize = csize; gic_v2_hw_data.vbase = vbase; gic_v2_hw_data.aliased_offset = aliased_offset; + + printk("Using the new VGIC implementation.\n"); } /* @@ -69,6 +71,8 @@ void vgic_v2_fold_lr_state(struct vcpu *vcpu) struct gic_lr lr_val; uint32_t intid; struct vgic_irq *irq; + struct irq_desc *desc = NULL; + bool have_desc_lock = false; gic_hw_ops->read_lr(lr, &lr_val); @@ -88,18 +92,30 @@ void vgic_v2_fold_lr_state(struct vcpu *vcpu) intid = lr_val.virq; irq = vgic_get_irq(vcpu->domain, vcpu, intid); - spin_lock_irqsave(&irq->irq_lock, flags); + local_irq_save(flags); + spin_lock(&irq->irq_lock); + + /* The locking order forces us to drop and re-take the locks here. */ + if ( irq->hw ) + { + spin_unlock(&irq->irq_lock); + + desc = irq_to_desc(irq->hwintid); + spin_lock(&desc->lock); + spin_lock(&irq->irq_lock); + + /* This h/w IRQ should still be assigned to the virtual IRQ. */ + ASSERT(irq->hw && desc->irq == irq->hwintid); + + have_desc_lock = true; + } /* * If a hardware mapped IRQ has been handled for good, we need to * clear the _IRQ_INPROGRESS bit to allow handling of new IRQs. */ if ( irq->hw && !lr_val.active && !lr_val.pending ) - { - struct irq_desc *irqd = irq_to_desc(irq->hwintid); - - clear_bit(_IRQ_INPROGRESS, &irqd->status); - } + clear_bit(_IRQ_INPROGRESS, &desc->status); /* Always preserve the active bit */ irq->active = lr_val.active; @@ -132,18 +148,19 @@ void vgic_v2_fold_lr_state(struct vcpu *vcpu) */ if ( vgic_irq_is_mapped_level(irq) && lr_val.pending ) { - struct irq_desc *irqd; - ASSERT(irq->hwintid >= VGIC_NR_PRIVATE_IRQS); - irqd = irq_to_desc(irq->hwintid); - irq->line_level = gic_read_pending_state(irqd); + irq->line_level = gic_read_pending_state(desc); if ( !irq->line_level ) - gic_set_active_state(irqd, false); + gic_set_active_state(desc, false); } - spin_unlock_irqrestore(&irq->irq_lock, flags); + spin_unlock(&irq->irq_lock); + if ( have_desc_lock ) + spin_unlock(&desc->lock); + local_irq_restore(flags); + vgic_put_irq(vcpu->domain, irq); } @@ -184,7 +201,7 @@ void vgic_v2_populate_lr(struct vcpu *vcpu, struct vgic_irq *irq, int lr) if ( vgic_irq_is_sgi(irq->intid) ) { - u32 src = ffs(irq->source); + uint32_t src = ffs(irq->source); BUG_ON(!src); lr_val.virt.source = (src - 1); -- 2.14.1 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |