[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v2 10/21] xen/arm: Implement hypercall PHYSDEVOP_{, un}map_pirq
On Thu, 31 Jul 2014, Julien Grall wrote: > The physdev sub-hypercalls PHYSDEVOP_{,map}_pirq allow the toolstack to > assign/deassign a physical IRQ to the guest (via the config options "irqs" > for xl). > For now, we allow only SPIs to be mapped to the guest. > The type MAP_PIRQ_TYPE_GSI is used for this purpose. > > The virtual IRQ number is allocated by Xen. The toolstack as to specify > the number of SPIs handled by the vGIC via an hypercall. > > Signed-off-by: Julien Grall <julien.grall@xxxxxxxxxx> Acked-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx> > --- > I'm wondering if we should introduce an alias of MAP_PIRQ_TYPE_GSI > for ARM. It's will be less confuse for the user. Just improve the error message below, maybe: "wrong map_pirq type 0x%x, only MAP_PIRQ_TYPE_GSI is supported" > Changes in v2: > - Add PHYSDEVOP_unmap_pirq > - Rework commit message > - Add functions to allocate/release a VIRQ > - is_routable_irq has been renamed into is_assignable_irq > --- > xen/arch/arm/physdev.c | 120 > +++++++++++++++++++++++++++++++++++++++++- > xen/arch/arm/vgic.c | 51 ++++++++++++++++++ > xen/include/asm-arm/domain.h | 1 + > xen/include/asm-arm/vgic.h | 5 ++ > 4 files changed, 175 insertions(+), 2 deletions(-) > > diff --git a/xen/arch/arm/physdev.c b/xen/arch/arm/physdev.c > index 61b4a18..9333aa0 100644 > --- a/xen/arch/arm/physdev.c > +++ b/xen/arch/arm/physdev.c > @@ -8,13 +8,129 @@ > #include <xen/types.h> > #include <xen/lib.h> > #include <xen/errno.h> > +#include <xen/iocap.h> > +#include <xen/guest_access.h> > +#include <xsm/xsm.h> > +#include <asm/current.h> > #include <asm/hypercall.h> > +#include <public/physdev.h> > > +static int physdev_map_pirq(domid_t domid, int type, int index, int *pirq_p) > +{ > + struct domain *d; > + int ret; > + int irq = index; > + int virq = 0; > + > + d = rcu_lock_domain_by_any_id(domid); > + if ( d == NULL ) > + return -ESRCH; > + > + ret = xsm_map_domain_pirq(XSM_TARGET, d); > + if ( ret ) > + goto free_domain; > + > + /* For now we only suport GSI */ > + if ( type != MAP_PIRQ_TYPE_GSI ) > + { > + ret = -EINVAL; > + dprintk(XENLOG_G_ERR, "dom%u: wrong map_pirq type 0x%x\n", > + d->domain_id, type); > + goto free_domain; > + } > + > + if ( !is_assignable_irq(irq) ) > + { > + ret = -EINVAL; > + dprintk(XENLOG_G_ERR, "IRQ%u is not routable to a guest\n", irq); > + goto free_domain; > + } > + > + ret = -EPERM; > + if ( !irq_access_permitted(current->domain, irq) ) > + goto free_domain; > + > + virq = vgic_allocate_virq(d, irq); > + ret = -EMFILE; > + if ( virq == -1 ) > + goto free_domain; > + > + ret = route_irq_to_guest(d, virq, irq, "routed IRQ"); > + > + if ( !ret ) > + *pirq_p = virq; > + else > + vgic_free_virq(d, virq); > + > +free_domain: > + rcu_unlock_domain(d); > + > + return ret; > +} > + > +int physdev_unmap_pirq(domid_t domid, int pirq) > +{ > + struct domain *d; > + int ret; > + > + d = rcu_lock_domain_by_any_id(domid); > + if ( d == NULL ) > + return -ESRCH; > + > + ret = xsm_unmap_domain_pirq(XSM_TARGET, d); > + if ( ret ) > + goto free_domain; > + > + ret = release_guest_irq(d, pirq); > + if ( ret ) > + goto free_domain; > + > + vgic_free_virq(d, pirq); > + > +free_domain: > + rcu_unlock_domain(d); > + > + return ret; > +} > > 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; > + > + ret = -EFAULT; > + if ( copy_from_guest(&map, arg, 1) != 0 ) > + break; > + > + ret = physdev_map_pirq(map.domid, map.type, map.index, > &map.pirq); > + > + if ( __copy_to_guest(arg, &map, 1) ) > + ret = -EFAULT; > + } > + break; > + > + case PHYSDEVOP_unmap_pirq: > + { > + physdev_unmap_pirq_t unmap; > + > + ret = -EFAULT; > + if ( copy_from_guest(&unmap, arg, 1) != 0 ) > + break; > + > + ret = physdev_unmap_pirq(unmap.domid, unmap.pirq); > + } > + > + default: > + ret = -ENOSYS; > + break; > + } > + > + return ret; > } > > /* > diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c > index 2a5fc18..644742e 100644 > --- a/xen/arch/arm/vgic.c > +++ b/xen/arch/arm/vgic.c > @@ -81,6 +81,8 @@ int domain_vgic_init(struct domain *d, unsigned int nr_spis) > return -ENODEV; > } > > + spin_lock_init(&d->arch.vgic.lock); > + > d->arch.vgic.shared_irqs = > xzalloc_array(struct vgic_irq_rank, DOMAIN_NR_RANKS(d)); > if ( d->arch.vgic.shared_irqs == NULL ) > @@ -108,6 +110,11 @@ int domain_vgic_init(struct domain *d, unsigned int > nr_spis) > > d->arch.vgic.handler->domain_init(d); > > + d->arch.vgic.allocated_spis = > + xzalloc_array(unsigned long, BITS_TO_LONGS(d->arch.vgic.nr_spis)); > + if ( !d->arch.vgic.allocated_spis ) > + return -ENOMEM; > + > return 0; > } > > @@ -444,6 +451,50 @@ void arch_evtchn_inject(struct vcpu *v) > vgic_vcpu_inject_irq(v, v->domain->arch.evtchn_irq); > } > > +int vgic_allocate_virq(struct domain *d, unsigned int irq) > +{ > + unsigned int spi; > + int virq = -1; > + > + /* Hardware domain has IRQ mapped 1:1 */ > + if ( is_hardware_domain(d) ) > + return irq; > + > + spin_lock(&d->arch.vgic.lock); > + > + spi = find_first_zero_bit(d->arch.vgic.allocated_spis, > + d->arch.vgic.nr_spis); > + > + if ( spi >= d->arch.vgic.nr_spis ) > + goto unlock; > + > + set_bit(spi, d->arch.vgic.allocated_spis); > + > + virq = 32 + spi; > + > +unlock: > + spin_unlock(&d->arch.vgic.lock); > + > + return virq; > +} > + > +void vgic_free_virq(struct domain *d, unsigned int virq) > +{ > + unsigned int spi; > + > + if ( is_hardware_domain(d) ) > + return; > + > + if ( virq < 32 && virq >= vgic_num_irqs(d) ) > + return; > + > + spi = virq - 32; > + > + spin_lock(&d->arch.vgic.lock); > + clear_bit(spi, d->arch.vgic.allocated_spis); > + spin_unlock(&d->arch.vgic.lock); > +} > + > /* > * Local variables: > * mode: C > diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h > index 44727b2..a4039c1 100644 > --- a/xen/include/asm-arm/domain.h > +++ b/xen/include/asm-arm/domain.h > @@ -94,6 +94,7 @@ struct arch_domain > spinlock_t lock; > int ctlr; > int nr_spis; /* Number of SPIs */ > + unsigned long *allocated_spis; /* bitmap of SPIs allocated */ > struct vgic_irq_rank *shared_irqs; > /* > * SPIs are domain global, SGIs and PPIs are per-VCPU and stored in > diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h > index 84ae441..c5d8b2e 100644 > --- a/xen/include/asm-arm/vgic.h > +++ b/xen/include/asm-arm/vgic.h > @@ -180,6 +180,11 @@ extern int vgic_to_sgi(struct vcpu *v, register_t sgir, > enum gic_sgi_mode irqmode, int virq, > unsigned long vcpu_mask); > extern void vgic_migrate_irq(struct vcpu *old, struct vcpu *new, unsigned > int irq); > + > +/* Allocate a VIRQ number of a guest SPI */ > +extern int vgic_allocate_virq(struct domain *d, unsigned int irq); > +extern void vgic_free_virq(struct domain *d, unsigned int irq); > + > #endif /* __ASM_ARM_VGIC_H__ */ > > /* _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |