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

Re: [Xen-devel] [PATCH 4/4] xen: events: allocate GSIs and dynamic IRQs from separate IRQ ranges.



On Tue, Jan 11, 2011 at 05:20:16PM +0000, Ian Campbell wrote:
> There are three cases which we need to care about, PV guest, PV domain
> 0 and HVM guest.
> 
> The PV guest case is simple since it has no access to ACPI or real
> APICs and therefore has no GSIs therefore we simply dynamically
> allocate all IRQs. The potentially interesting case here is PIRQ type
> event channels associated with passed through PCI devices. However
> even in this case the guest has no direct interaction with the
> physical GSI since that happens in the PCI backend.
> 
> The PV domain 0 and HVM guest cases are actually the same. In domain 0
> case the kernel sees the host ACPI and GSIs (although it only sees the
> APIC indirectly via the hypervisor) and in the HVM guest case it sees
> the virtualised ACPI and emulated APICs. In these cases we start
> allocating dynamic IRQs at nr_irqs_gsi so that they cannot clash with
> any GSI.
> 
> Currently xen_allocate_irq_dynamic starts at nr_irqs and works
> backwards looking for a free IRQ in order to (try and) avoid clashing
> with GSIs used in domain 0 and in HVM guests. This change avoids that
> although we retain the behaviour of allowing dynamic IRQs to encroach
> on the GSI range if no suitable IRQs are available since a future IRQ
> clash is deemed preferable to failure right now.
> 
> Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
> Cc: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx>
> Cc: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
> Cc: Jeremy Fitzhardinge <jeremy@xxxxxxxx>
> ---
>  drivers/xen/events.c |   84 +++++++++++++++----------------------------------
>  1 files changed, 26 insertions(+), 58 deletions(-)
> 
> diff --git a/drivers/xen/events.c b/drivers/xen/events.c
> index 74fb216..a7b60f6 100644
> --- a/drivers/xen/events.c
> +++ b/drivers/xen/events.c
> @@ -373,81 +373,49 @@ static void unmask_evtchn(int port)
>       put_cpu();
>  }
>  
> -static int get_nr_hw_irqs(void)
> +static int xen_allocate_irq_dynamic(void)
>  {
> -     int ret = 1;
> +     int first = 0;
> +     int irq;
>  
>  #ifdef CONFIG_X86_IO_APIC
> -     ret = get_nr_irqs_gsi();
> +     /*
> +      * For an HVM guest or domain 0 which see "real" (emulated or
> +      * actual repectively) GSIs we allocate dynamic IRQs
> +      * e.g. those corresponding to event channels or MSIs
> +      * etc. from the range above those "real" GSIs to avoid
> +      * collisions.
> +      */
> +     if (xen_initial_domain() || xen_hvm_domain())
> +             first = get_nr_irqs_gsi();
>  #endif
>  
> -     return ret;
> -}
> -
> -static int xen_allocate_irq_dynamic(void)
> -{
> -     struct irq_data *data;
> -     int irq, res;
> -     int bottom = get_nr_hw_irqs();
> -     int top = nr_irqs-1;
> -
> -     if (bottom == nr_irqs)
> -             goto no_irqs;
> -
>  retry:
> -     /* This loop starts from the top of IRQ space and goes down.
> -      * We need this b/c if we have a PCI device in a Xen PV guest
> -      * we do not have an IO-APIC (though the backend might have them)
> -      * mapped in. To not have a collision of physical IRQs with the Xen
> -      * event channels start at the top of the IRQ space for virtual IRQs.
> -      */
> -     for (irq = top; irq > bottom; irq--) {
> -             data = irq_get_irq_data(irq);
> -             /* only 15->0 have init'd desc; handle irq > 16 */
> -             if (!data)
> -                     break;
> -             if (data->chip == &no_irq_chip)
> -                     break;
> -             if (data->chip != &xen_dynamic_chip)
> -                     continue;
> -             if (irq_info[irq].type == IRQT_UNBOUND)
> -                     return irq;
> -     }
> +     irq = irq_alloc_desc_from(first, -1);
>  
> -     if (irq == bottom)
> -             goto no_irqs;
> -
> -     res = irq_alloc_desc_at(irq, -1);
> -     if (res == -EEXIST) {
> -             top--;
> -             if (bottom > top)
> -                     printk(KERN_ERR "Eating in GSI/MSI space (%d)!" \
> -                             " Your PCI device might not work!\n", top);
> -             if (top > NR_IRQS_LEGACY)
> -                     goto retry;
> +     if (irq == -ENOMEM && first > NR_IRQS_LEGACY) {
> +             printk(KERN_ERR "Out of dynamic IRQ space and eating into GSI 
> space. You should increase nr_irqs\n");
> +             first = max(NR_IRQS_LEGACY, first - NR_IRQS_LEGACY);
> +             goto retry;

You don't check for irq == -EEXIST. So if specific IRQ (first) is already
occupied you panic. Would it be better to check for that too in this got
and retry with that value?

>       }
>  
> -     if (WARN_ON(res != irq))
> -             return -1;
> +     if (irq < 0)
> +             panic("No available IRQ to bind to: increase nr_irqs!\n");
>  
>       return irq;
> -
> -no_irqs:
> -     panic("No available IRQ to bind to: increase nr_irqs!\n");
> -}
> -
> -static bool identity_mapped_irq(unsigned irq)
> -{
> -     /* identity map all the hardware irqs */
> -     return irq < get_nr_hw_irqs();
>  }
>  
>  static int xen_allocate_irq_gsi(unsigned gsi)
>  {
>       int irq;
>  
> -     if (!identity_mapped_irq(gsi) &&
> -         (xen_initial_domain() || !xen_pv_domain()))
> +     /*
> +      * A PV guest has no concept of a GSI (since it has no ACPI
> +      * nor access to/knowledge of the physical APICs). Therefore
> +      * all IRQs are dynamically allocated from the entire IRQ
> +      * space.
> +      */
> +     if (xen_pv_domain() && !xen_initial_domain())
>               return xen_allocate_irq_dynamic();

OK. So with a IDE disk at IRQ 14 it can end up with irq = 5 (say the first five
IRQs are used by xen-spinlock, xen-timer, xen-debug, xen-console, and something 
else).
The gsi that gets stuck via the mk_pirq_info[5] ends up being 14, and pirq = 14.
When you do EVTCHNOP_bind_pirq you end up passing in pirq=14 and bind that to 
the
Linux irq five, right?


>  
>       /* Legacy IRQ descriptors are already allocated by the arch. */
> -- 
> 1.5.6.5
> 
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@xxxxxxxxxxxxxxxxxxx
> http://lists.xensource.com/xen-devel

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

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