[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 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? > + ret = -EFAULT; > + break; > + } > + > + default: > + printk("%s %d cmd=%d: not implemented yet\n", __func__, __LINE__, > cmd); > + ret = -ENOSYS; > + break; > + } > + > + return ret; > } > > /* > diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c > index 2e4b11f..9c95f67 100644 > --- a/xen/arch/arm/vgic.c > +++ b/xen/arch/arm/vgic.c > @@ -82,10 +82,7 @@ int domain_vgic_init(struct domain *d) > /* Currently nr_lines in vgic and gic doesn't have the same meanings > * Here nr_lines = number of SPIs > */ > - if ( d->domain_id == 0 ) > - d->arch.vgic.nr_lines = gic_number_lines() - 32; > - else > - d->arch.vgic.nr_lines = 0; /* We don't need SPIs for the guest */ > + d->arch.vgic.nr_lines = gic_number_lines() - 32; > > d->arch.vgic.shared_irqs = > xzalloc_array(struct vgic_irq_rank, DOMAIN_NR_RANKS(d)); _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |