|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 5/5] xen/arm: Only enable physical IRQs when the guest asks
On 06/25/2013 05:19 PM, Stefano Stabellini wrote:
> On Tue, 25 Jun 2013, Julien Grall wrote:
>> If the guest VCPU receives an interrupts when it's disabled, it will throw
> ^interrupt
>
>> away the IRQ with EOIed it.
>
> What does this mean? I cannot parse the sentence.
"it will throw away the IRQ without EOIing".
>
>> This is result to lost IRQ forever.
>> Directly EOIed the interrupt doesn't help because the IRQ could be fired
>> again and result to an infinited loop.
>>
>> It happens during dom0 boot on the versatile express TC2 with the ethernet
>> card.
>>
>> Let the interrupt disabled when Xen setups the route and enable it when Linux
>> asks to enable it.
>
> Is the problem that Xen keeps the interrupt enabled even when Linux
> disables it at the gic level? Is this what this patch is trying to
> address?
This patch only delays the physical IRQ activation until Linux will
enable it. This patch avoids to lose IRQ when a VCPU is disabled.
I tried to also disable the IRQ when Linux asks to disable it but the
versatile express platform hang.
>
>> Signed-off-by: Julien Grall <julien.grall@xxxxxxxxxx>
>> ---
>> xen/arch/arm/domain_build.c | 14 ++++++++++++++
>> xen/arch/arm/gic.c | 25 +++++++++++++++++++++++--
>> xen/arch/arm/vgic.c | 7 +++----
>> xen/include/asm-arm/gic.h | 4 ++++
>> xen/include/asm-arm/irq.h | 6 ++++++
>> 5 files changed, 50 insertions(+), 6 deletions(-)
>>
>> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
>> index f5befbd..0470a2d 100644
>> --- a/xen/arch/arm/domain_build.c
>> +++ b/xen/arch/arm/domain_build.c
>> @@ -408,6 +408,20 @@ static int map_device(struct domain *d, const struct
>> dt_device_node *dev)
>> }
>>
>> DPRINT("irq %u = %u type = 0x%x\n", i, irq.irq, irq.type);
>> +
>> + /*
>> + * Only map SGI interrupt in the guest as XEN won't handle
>> + * it correctly.
>> + * TODO: Fix it
>> + */
>> + if ( !irq_is_sgi(irq.irq) )
>> + {
>> + printk(XENLOG_WARNING "WARNING: Don't map irq %u for %s has "
>> + "XEN doesn't handle properly non-SGI interrupt\n",
>> + i, dt_node_full_name(dev));
>
> do you mean SPI?
>
>
>> + continue;
>> + }
>> +
>> /* Don't check return because the IRQ can be use by multiple device
>> */
>> gic_route_irq_to_guest(d, &irq, dt_node_name(dev));
>> }
>> diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
>> index b16ba8c..e7d082a 100644
>> --- a/xen/arch/arm/gic.c
>> +++ b/xen/arch/arm/gic.c
>> @@ -179,6 +179,17 @@ static hw_irq_controller gic_guest_irq_type = {
>> .set_affinity = gic_irq_set_affinity,
>> };
>>
>> +void gic_irq_enable(struct irq_desc *desc)
>> +{
>> + spin_lock_irq(&desc->lock);
>> + spin_lock(&gic.lock);
>> +
>> + desc->handler->enable(desc);
>> +
>> + spin_unlock(&gic.lock);
>> + spin_unlock_irq(&desc->lock);
>> +}
>
> This function looks a bit too similar to gic_irq_mask and friends,
> except that it takes two locks.
>
> To make that obvious it's probably better to call it gic_irq_enable_safe
> or gic_irq_enable_locked.
>
>
>> /* needs to be called with gic.lock held */
>> static void gic_set_irq_properties(unsigned int irq, bool_t level,
>> unsigned int cpu_mask, unsigned int priority)
>> @@ -543,8 +554,6 @@ static int __setup_irq(struct irq_desc *desc, unsigned
>> int irq,
>> desc->status &= ~IRQ_DISABLED;
>> dsb();
>>
>> - desc->handler->startup(desc);
>> -
>> return 0;
>> }
>>
>> @@ -560,6 +569,8 @@ int __init setup_dt_irq(const struct dt_irq *irq, struct
>> irqaction *new)
>>
>> rc = __setup_irq(desc, irq->irq, new);
>>
>> + desc->handler->startup(desc);
>> +
>> spin_unlock_irqrestore(&desc->lock, flags);
>>
>> return rc;
>
> This two changes make it so guest irqs are not enabled by default, good.
>
>
>> @@ -711,6 +722,7 @@ void gic_inject(void)
>> gic_inject_irq_start();
>> }
>>
>> +/* TODO: Handle properly non SGI-interrupt */
>> int gic_route_irq_to_guest(struct domain *d, const struct dt_irq *irq,
>> const char * devname)
>> {
>> @@ -719,11 +731,18 @@ int gic_route_irq_to_guest(struct domain *d, const
>> struct dt_irq *irq,
>> unsigned long flags;
>> int retval;
>> bool_t level;
>> + struct pending_irq *p;
>> + /* XXX: handler other VCPU than 0 */
>> + struct vcpu *v = d->vcpu[0];
>>
>> action = xmalloc(struct irqaction);
>> if (!action)
>> return -ENOMEM;
>>
>> + /* XXX: Here we assume a 1:1 interrupt mapping between the host and
>> dom0 */
>> + BUG_ON(irq->irq >= (d->arch.vgic.nr_lines + NR_LOCAL_IRQS));
>> + p = irq_to_pending(v, irq->irq);
>> +
>> action->dev_id = d;
>> action->name = devname;
>> action->free_on_release = 1;
>> @@ -744,6 +763,8 @@ int gic_route_irq_to_guest(struct domain *d, const
>> struct dt_irq *irq,
>> goto out;
>> }
>>
>> + p->desc = desc;
>> +
>> out:
>> spin_unlock(&gic.lock);
>> spin_unlock_irqrestore(&desc->lock, flags);
>> diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
>> index cea9233..4f3d816 100644
>> --- a/xen/arch/arm/vgic.c
>> +++ b/xen/arch/arm/vgic.c
>> @@ -372,6 +372,9 @@ static void vgic_enable_irqs(struct vcpu *v, uint32_t r,
>> int n)
>> if ( !list_empty(&p->inflight) && !gic_irq_injected(irq) )
>> gic_set_guest_irq(v, irq, GICH_LR_PENDING, p->priority);
>>
>> + if ( p->desc != NULL )
>> + gic_irq_enable(p->desc);
>> +
>> i++;
>> }
>> }
>
> Should we add a gic_irq_disable call when the guest disables irqs?
>
>
>> @@ -685,10 +688,6 @@ void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int
>> irq, int virtual)
>>
>> n->irq = irq;
>> n->priority = priority;
>> - if (!virtual)
>> - n->desc = irq_to_desc(irq);
>> - else
>> - n->desc = NULL;
>>
>> /* the irq is enabled */
>> if ( rank->ienable & (1 << (irq % 32)) )
>
> I don't quite understand why are you changing where the "desc"
> assignement is done.
> If it is a cleanup you shouldn't mix it with a patch like this that is
> supposed to fix a specific issue. Otherwise please explain why you need
> this change.
>
>
>> diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
>> index f9e9ef1..f7f3c1e 100644
>> --- a/xen/include/asm-arm/gic.h
>> +++ b/xen/include/asm-arm/gic.h
>> @@ -134,6 +134,7 @@
>>
>> #ifndef __ASSEMBLY__
>> #include <xen/device_tree.h>
>> +#include <xen/irq.h>
>>
>> extern int domain_vgic_init(struct domain *d);
>> extern void domain_vgic_free(struct domain *d);
>> @@ -154,6 +155,9 @@ extern void gic_inject(void);
>> extern void gic_clear_pending_irqs(struct vcpu *v);
>> extern int gic_events_need_delivery(void);
>>
>> +/* Helper to enable an IRQ and take all the needed locks */
>> +extern void gic_irq_enable(struct irq_desc *desc);
>> +
>> extern void __cpuinit init_maintenance_interrupt(void);
>> extern void gic_set_guest_irq(struct vcpu *v, unsigned int irq,
>> unsigned int state, unsigned int priority);
>> diff --git a/xen/include/asm-arm/irq.h b/xen/include/asm-arm/irq.h
>> index 80ff68d..346dc1d 100644
>> --- a/xen/include/asm-arm/irq.h
>> +++ b/xen/include/asm-arm/irq.h
>> @@ -46,6 +46,12 @@ int __init request_dt_irq(const struct dt_irq *irq,
>> void *dev_id);
>> int __init setup_dt_irq(const struct dt_irq *irq, struct irqaction *new);
>>
>> +#define FIRST_SGI_IRQ 32
>> +static inline bool_t irq_is_sgi(unsigned int irq)
>> +{
>> + return (irq >= FIRST_SGI_IRQ);
>> +}
>
> Aren't SGIs supposed to be between 0 and 15? Aren't you talking about
> SPIs here?
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |