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

Re: [Xen-devel] [XenARM] XEN tools for ARM with Virtualization Extensions - Patch #2



On 15 July 2013 19:39, Stefano Stabellini
<stefano.stabellini@xxxxxxxxxxxxx> wrote:
> On Fri, 12 Jul 2013, Eric Trudeau wrote:
>> Patch #2 begins here:
>> --------------------------------------------
>>
>> From 924441c3eddb1765cb4fb0e94f6b62177195837d Mon Sep 17 00:00:00 2001
>> From: Eric Trudeau <etrudeau@xxxxxxxxxxxx>
>> Date: Fri, 12 Jul 2013 14:54:24 -0400
>> Subject: [PATCH] xen/arm: Add support for 1:1 IRQ mapping into guest domains
>>  on ARM
>>
>> ARM guests will now have the ability to access 1:1 mapped IRQs.
>>
>> The irqs list in the domain configuration file is used.  A SPI irq
>> number must include the offset of 32.  For example, if the device
>> tree irq number is 76 for a SPI, then the irqs field in the dom.cfg
>> file would be:
>>    irqs = [ 108 ]
>>
>> Only level-triggered IRQs are supported at this time.
>>
>> When an IRQ is released on destruction of the guest, any in-progress
>> handlers are given at least a 100 msec to complete.
>
> Overall it's pretty good patch, but I don't like the busy loop. I admit
> that it's an improvement over what we have today but release_irq wasn't
> actually called by anybody until now.
>
>
>> Signed-off-by: Eric Trudeau <etrudeau@xxxxxxxxxxxx>
>> ---
>>  xen/arch/arm/domain.c  | 15 ++++++++++++++
>>  xen/arch/arm/gic.c     | 29 ++++++++++++++++++--------
>>  xen/arch/arm/physdev.c | 56 
>> ++++++++++++++++++++++++++++++++++++++++++++++++--
>>  xen/arch/arm/vgic.c    |  5 +----
>>  4 files changed, 91 insertions(+), 14 deletions(-)
>>
>> diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
>> index 4c434a1..f15ff06 100644
>> --- a/xen/arch/arm/domain.c
>> +++ b/xen/arch/arm/domain.c
>> @@ -31,6 +31,8 @@
>>  #include <asm/gic.h>
>>  #include "vtimer.h"
>>  #include "vpl011.h"
>> +#include <xen/iocap.h>
>> +#include <xen/irq.h>
>>
>>  DEFINE_PER_CPU(struct vcpu *, curr_vcpu);
>>
>> @@ -513,8 +515,21 @@ fail:
>>      return rc;
>>  }
>>
>> +static int release_domain_irqs(struct domain *d)
>> +{
>> +    int i;
>> +    for (i = 0; i <= d->nr_pirqs; i++) {
>> +        if (irq_access_permitted(d, i)) {
>> +            release_irq(i);
>> +        }
>> +    }
>> +    return 0;
>> +}
>> +
>> +
>>  void arch_domain_destroy(struct domain *d)
>>  {
>> +    release_domain_irqs(d);
>>      p2m_teardown(d);
>>      domain_vgic_free(d);
>>      domain_uart0_free(d);
>> diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
>> index ccce565..ed15ec3 100644
>> --- a/xen/arch/arm/gic.c
>> +++ b/xen/arch/arm/gic.c
>> @@ -30,6 +30,7 @@
>>  #include <xen/device_tree.h>
>>  #include <asm/p2m.h>
>>  #include <asm/domain.h>
>> +#include <xen/delay.h>
>>
>>  #include <asm/gic.h>
>>
>> @@ -510,11 +511,12 @@ void gic_route_spis(void)
>>      }
>>  }
>>
>> -void __init release_irq(unsigned int irq)
>> +void release_irq(unsigned int irq)
>>  {
>>      struct irq_desc *desc;
>>      unsigned long flags;
>> -   struct irqaction *action;
>> +    struct irqaction *action;
>> +    int    inprogresschecks;
>>
>>      desc = irq_to_desc(irq);
>>
>> @@ -530,8 +532,15 @@ void __init release_irq(unsigned int irq)
>>
>>      spin_unlock_irqrestore(&desc->lock,flags);
>>
>> -    /* Wait to make sure it's not being used on another CPU */
>> -    do { smp_mb(); } while ( desc->status & IRQ_INPROGRESS );
>> +    /* Wait a little while to make sure it's not being used on another CPU
>> +     * But not indefinitely, because a guest may have crashed */
>> +    for (inprogresschecks = 0; (inprogresschecks < 100); 
>> inprogresschecks++) {
>> +        smp_mb();
>> +        if ( desc->status & IRQ_INPROGRESS )
>> +            mdelay(1);
>> +        else
>> +            break;
>> +    }
>
> Can we use a timer based watchdog instead to avoid the busy loop?
> Looping for 100ms means wasting a considerable amount of time.
>
>
>>      if (action && action->free_on_release)
>>          xfree(action);
>> @@ -708,6 +717,12 @@ int gic_route_irq_to_guest(struct domain *d, const 
>> struct dt_irq *irq,
>>      spin_lock_irqsave(&desc->lock, flags);
>>      spin_lock(&gic.lock);
>>
>> +    if ( desc->action != NULL )
>> +    {
>> +        retval = -EBUSY;
>> +        goto out;
>> +    }
>>
>>      desc->handler = &gic_guest_irq_type;
>>      desc->status |= IRQ_GUEST;
>>
>> @@ -716,12 +731,10 @@ int gic_route_irq_to_guest(struct domain *d, const 
>> struct dt_irq *irq,
>>      gic_set_irq_properties(irq->irq, level, 1u << smp_processor_id(), 0xa0);
>>
>>      retval = __setup_irq(desc, irq->irq, action);
>> -    if (retval) {
>> -        xfree(action);
>> -        goto out;
>> -    }
>>
>>  out:
>> +    if (retval)
>> +        xfree(action);
>>      spin_unlock(&gic.lock);
>>      spin_unlock_irqrestore(&desc->lock, flags);
>>      return retval;
>> diff --git a/xen/arch/arm/physdev.c b/xen/arch/arm/physdev.c
>> index 61b4a18..8d76d11 100644
>> --- a/xen/arch/arm/physdev.c
>> +++ b/xen/arch/arm/physdev.c
>> @@ -9,12 +9,64 @@
>>  #include <xen/lib.h>
>>  #include <xen/errno.h>
>>  #include <asm/hypercall.h>
>> +#include <public/physdev.h>
>> +#include <xen/guest_access.h>
>> +#include <xen/irq.h>
>> +#include <xen/sched.h>
>> +#include <asm/gic.h>
>> +#include <xsm/xsm.h>
>>
>>
>>  int do_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
>>  {
>> -    printk("%s %d cmd=%d: not implemented yet\n", __func__, __LINE__, cmd);
>> -    return -ENOSYS;
>> +    int ret;
>> +
>> +    switch ( cmd )
>> +    {
>> +    case PHYSDEVOP_map_pirq: {
>> +        physdev_map_pirq_t map;
>> +        struct dt_irq irq;
>> +        struct domain *d;
>> +
>> +        ret = -EFAULT;
>> +        if ( copy_from_guest(&map, arg, 1) != 0 )
>> +            break;
>> +
>> +        d = rcu_lock_domain_by_any_id(map.domid);
>> +        if ( d == NULL ) {
>> +            ret = -ESRCH;
>> +            break;
>> +        }
>> +
>> +        ret = xsm_map_domain_pirq(XSM_TARGET, d);
>> +
>> +        if (!ret && (map.pirq >= gic_number_lines()))
>> +            ret = -EINVAL;
>> +
>> +        if (!ret) {
>> +            irq.irq = map.pirq;
>> +            irq.type = DT_IRQ_TYPE_LEVEL_MASK;
>
> You should add a comment here to explain why you are hardcoding level,
> even if it's just a temporary limitation.
>
>
>> +            ret = gic_route_irq_to_guest(d, &irq, "GuestIRQ");
>> +            if (!ret)
>
> Code style (even though I admit that we are not following it to the
> letter ourselves). See CODING_STYLE.
>
>
>> +                dprintk(XENLOG_G_INFO, "dom%d: gic_route_irq_to_guest 
>> mapped in IRQ %d\n",
>> +                        d->domain_id, irq.irq);
>> +        }
>> +
>> +        rcu_unlock_domain(d);
>> +
>> +        if (!ret && __copy_to_guest(arg, &map, 1) )
>
> Shouldn't you be copying back the irq number written by
> gic_route_irq_to_guest in map.irq?

That's fine because pirq is used to return the IRQ number into the guest.
Here, as we have 1:1 mapping, the value is same. But in the future, a physical
IRQ will be mapped to a different number into the guest

--
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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