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

Re: [Xen-devel] [PATCH v3 08/24] xen/arm: Allow virq != irq



On Tue, 13 Jan 2015, Julien Grall wrote:
> Actually Xen is assuming that the virtual IRQ will always be the same as IRQ.
> 
> Modify route_guest_irq to take the virtual IRQ in parameter and let Xen
> assign a different IRQ number. Also store the vIRQ in the desc action to
> easily retrieve easily the IRQ target when we need to inject the interrupt.
> 
> As DOM0 will get most the devices, the vIRQ is equal to the IRQ in that case.
> 
> At the same time modify the behavior of irq_get_domain. The function now
> assumes that the irq_desc belongs to an IRQ assigned to a guest.
> 
> Signed-off-by: Julien Grall <julien.grall@xxxxxxxxxx>
> 
> ---
>     Changes in v3
>         - Spelling/grammar nits
>         - Fix compilation on ARM64. Forgot to update route_irq_to_guest
>           call for xgene platform.
>         - Add a word about irq_get_domain behavior change
>         - More s/irq/virq/ because of the rebasing on the latest staging
> 
>     Changes in v2:
>         - Patch added
> ---
>  xen/arch/arm/domain_build.c          |  2 +-
>  xen/arch/arm/gic.c                   |  5 ++--
>  xen/arch/arm/irq.c                   | 47 
> ++++++++++++++++++++++++++----------
>  xen/arch/arm/platforms/xgene-storm.c |  2 +-
>  xen/arch/arm/vgic.c                  | 20 +++++++--------
>  xen/include/asm-arm/gic.h            |  3 ++-
>  xen/include/asm-arm/irq.h            |  4 +--
>  xen/include/asm-arm/vgic.h           |  4 +--
>  8 files changed, 55 insertions(+), 32 deletions(-)
> 
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index b48b5d0..06c1dec 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -1029,7 +1029,7 @@ static int handle_device(struct domain *d, struct 
> dt_device_node *dev)
>               * twice the IRQ. This can happen if the IRQ is shared
>               */
>              vgic_reserve_virq(d, irq);
> -            res = route_irq_to_guest(d, irq, dt_node_name(dev));
> +            res = route_irq_to_guest(d, irq, irq, dt_node_name(dev));
>              if ( res )
>              {
>                  printk(XENLOG_ERR "Unable to route IRQ %u to domain %u\n",
> diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
> index eb0c5d6..15de283 100644
> --- a/xen/arch/arm/gic.c
> +++ b/xen/arch/arm/gic.c
> @@ -126,7 +126,8 @@ void gic_route_irq_to_xen(struct irq_desc *desc, const 
> cpumask_t *cpu_mask,
>  /* Program the GIC to route an interrupt to a guest
>   *   - desc.lock must be held
>   */
> -void gic_route_irq_to_guest(struct domain *d, struct irq_desc *desc,
> +void gic_route_irq_to_guest(struct domain *d, unsigned int virq,
> +                            struct irq_desc *desc,
>                              const cpumask_t *cpu_mask, unsigned int priority)
>  {
>      struct pending_irq *p;
> @@ -139,7 +140,7 @@ void gic_route_irq_to_guest(struct domain *d, struct 
> irq_desc *desc,
>  
>      /* Use vcpu0 to retrieve the pending_irq struct. Given that we only
>       * route SPIs to guests, it doesn't make any difference. */
> -    p = irq_to_pending(d->vcpu[0], desc->irq);
> +    p = irq_to_pending(d->vcpu[0], virq);
>      p->desc = desc;
>  }
>  
> diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c
> index 25ecf1d..830832c 100644
> --- a/xen/arch/arm/irq.c
> +++ b/xen/arch/arm/irq.c
> @@ -31,6 +31,13 @@
>  static unsigned int local_irqs_type[NR_LOCAL_IRQS];
>  static DEFINE_SPINLOCK(local_irqs_type_lock);
>  
> +/* Describe an IRQ assigned to a guest */
> +struct irq_guest
> +{
> +    struct domain *d;
> +    unsigned int virq;
> +};

I would prefer if you didn't use dev_id for this and just added a virq
field to irqaction.



>  static void ack_none(struct irq_desc *irq)
>  {
>      printk("unexpected IRQ trap at irq %02x\n", irq->irq);
> @@ -122,18 +129,20 @@ void __cpuinit init_secondary_IRQ(void)
>      BUG_ON(init_local_irq_data() < 0);
>  }
>  
> -static inline struct domain *irq_get_domain(struct irq_desc *desc)
> +static inline struct irq_guest *irq_get_guest_info(struct irq_desc *desc)
>  {
>      ASSERT(spin_is_locked(&desc->lock));
> -
> -    if ( !test_bit(_IRQ_GUEST, &desc->status) )
> -        return dom_xen;
> -
> +    ASSERT(test_bit(_IRQ_GUEST, &desc->status));
>      ASSERT(desc->action != NULL);
>  
>      return desc->action->dev_id;
>  }
>  
> +static inline struct domain *irq_get_domain(struct irq_desc *desc)
> +{
> +    return irq_get_guest_info(desc)->d;
> +}
> +
>  void irq_set_affinity(struct irq_desc *desc, const cpumask_t *cpu_mask)
>  {
>      if ( desc != NULL )
> @@ -197,7 +206,7 @@ void do_IRQ(struct cpu_user_regs *regs, unsigned int irq, 
> int is_fiq)
>  
>      if ( test_bit(_IRQ_GUEST, &desc->status) )
>      {
> -        struct domain *d = irq_get_domain(desc);
> +        struct irq_guest *info = irq_get_guest_info(desc);
>  
>          desc->handler->end(desc);
>  
> @@ -206,7 +215,7 @@ void do_IRQ(struct cpu_user_regs *regs, unsigned int irq, 
> int is_fiq)
>  
>          /* the irq cannot be a PPI, we only support delivery of SPIs to
>           * guests */
> -        vgic_vcpu_inject_spi(d, irq);
> +        vgic_vcpu_inject_spi(info->d, info->virq);
>          goto out_no_end;
>      }
>  
> @@ -370,19 +379,30 @@ err:
>      return rc;
>  }
>  
> -int route_irq_to_guest(struct domain *d, unsigned int irq,
> -                       const char * devname)
> +int route_irq_to_guest(struct domain *d, unsigned int virq,
> +                       unsigned int irq, const char * devname)
>  {
>      struct irqaction *action;
> -    struct irq_desc *desc = irq_to_desc(irq);
> +    struct irq_guest *info;
> +    struct irq_desc *desc;
>      unsigned long flags;
>      int retval = 0;
>  
>      action = xmalloc(struct irqaction);
> -    if (!action)
> +    if ( !action )
> +        return -ENOMEM;
> +
> +    info = xmalloc(struct irq_guest);
> +    if ( !info )
> +    {
> +        xfree(action);
>          return -ENOMEM;
> +    }
> +
> +    info->d = d;
> +    info->virq = virq;
>  
> -    action->dev_id = d;
> +    action->dev_id = info;
>      action->name = devname;
>      action->free_on_release = 1;
>  
> @@ -413,7 +433,7 @@ int route_irq_to_guest(struct domain *d, unsigned int irq,
>      if ( retval )
>          goto out;
>  
> -    gic_route_irq_to_guest(d, desc, cpumask_of(smp_processor_id()),
> +    gic_route_irq_to_guest(d, virq, desc, cpumask_of(smp_processor_id()),
>                             GIC_PRI_IRQ);
>      spin_unlock_irqrestore(&desc->lock, flags);
>      return 0;
> @@ -421,6 +441,7 @@ int route_irq_to_guest(struct domain *d, unsigned int irq,
>  out:
>      spin_unlock_irqrestore(&desc->lock, flags);
>      xfree(action);
> +    xfree(info);
>  
>      return retval;
>  }
> diff --git a/xen/arch/arm/platforms/xgene-storm.c 
> b/xen/arch/arm/platforms/xgene-storm.c
> index b0808b8..e2f8b89 100644
> --- a/xen/arch/arm/platforms/xgene-storm.c
> +++ b/xen/arch/arm/platforms/xgene-storm.c
> @@ -75,7 +75,7 @@ static int map_one_spi(struct domain *d, const char *what,
>          printk("Failed to reserve the vIRQ %u on dom%d\n",
>                 irq, d->domain_id);
>  
> -    ret = route_irq_to_guest(d, irq, what);
> +    ret = route_irq_to_guest(d, irq, irq, what);
>      if ( ret )
>          printk("Failed to route %s to dom%d\n", what, d->domain_id);
>  
> diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
> index 38216f7..c915670 100644
> --- a/xen/arch/arm/vgic.c
> +++ b/xen/arch/arm/vgic.c
> @@ -380,16 +380,16 @@ void vgic_clear_pending_irqs(struct vcpu *v)
>      spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
>  }
>  
> -void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq)
> +void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int virq)
>  {
>      uint8_t priority;
> -    struct vgic_irq_rank *rank = vgic_rank_irq(v, irq);
> -    struct pending_irq *iter, *n = irq_to_pending(v, irq);
> +    struct vgic_irq_rank *rank = vgic_rank_irq(v, virq);
> +    struct pending_irq *iter, *n = irq_to_pending(v, virq);
>      unsigned long flags;
>      bool_t running;
>  
>      vgic_lock_rank(v, rank, flags);
> -    priority = v->domain->arch.vgic.handler->get_irq_priority(v, irq);
> +    priority = v->domain->arch.vgic.handler->get_irq_priority(v, virq);
>      vgic_unlock_rank(v, rank, flags);
>  
>      spin_lock_irqsave(&v->arch.vgic.lock, flags);
> @@ -405,7 +405,7 @@ void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int 
> irq)
>  
>      if ( !list_empty(&n->inflight) )
>      {
> -        gic_raise_inflight_irq(v, irq);
> +        gic_raise_inflight_irq(v, virq);
>          goto out;
>      }
>  
> @@ -413,7 +413,7 @@ void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int 
> irq)
>  
>      /* the irq is enabled */
>      if ( test_bit(GIC_IRQ_GUEST_ENABLED, &n->status) )
> -        gic_raise_guest_irq(v, irq, priority);
> +        gic_raise_guest_irq(v, virq, priority);
>  
>      list_for_each_entry ( iter, &v->arch.vgic.inflight_irqs, inflight )
>      {
> @@ -433,15 +433,15 @@ out:
>          smp_send_event_check_mask(cpumask_of(v->processor));
>  }
>  
> -void vgic_vcpu_inject_spi(struct domain *d, unsigned int irq)
> +void vgic_vcpu_inject_spi(struct domain *d, unsigned int virq)
>  {
>      struct vcpu *v;
>  
>      /* the IRQ needs to be an SPI */
> -    ASSERT(irq >= 32 && irq <= gic_number_lines());
> +    ASSERT(virq >= 32 && virq <= vgic_num_irqs(d));
>  
> -    v = vgic_get_target_vcpu(d->vcpu[0], irq);
> -    vgic_vcpu_inject_irq(v, irq);
> +    v = vgic_get_target_vcpu(d->vcpu[0], virq);
> +    vgic_vcpu_inject_irq(v, virq);
>  }
>  
>  void arch_evtchn_inject(struct vcpu *v)
> diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
> index 6286c71..cf9f257 100644
> --- a/xen/include/asm-arm/gic.h
> +++ b/xen/include/asm-arm/gic.h
> @@ -213,7 +213,8 @@ extern enum gic_version gic_hw_version(void);
>  /* Program the GIC to route an interrupt */
>  extern void gic_route_irq_to_xen(struct irq_desc *desc, const cpumask_t 
> *cpu_mask,
>                                   unsigned int priority);
> -extern void gic_route_irq_to_guest(struct domain *, struct irq_desc *desc,
> +extern void gic_route_irq_to_guest(struct domain *, unsigned int virq,
> +                                   struct irq_desc *desc,
>                                     const cpumask_t *cpu_mask,
>                                     unsigned int priority);
>  
> diff --git a/xen/include/asm-arm/irq.h b/xen/include/asm-arm/irq.h
> index 435dfcd..f00eb11 100644
> --- a/xen/include/asm-arm/irq.h
> +++ b/xen/include/asm-arm/irq.h
> @@ -40,8 +40,8 @@ void do_IRQ(struct cpu_user_regs *regs, unsigned int irq, 
> int is_fiq);
>  void init_IRQ(void);
>  void init_secondary_IRQ(void);
>  
> -int route_irq_to_guest(struct domain *d, unsigned int irq,
> -                       const char *devname);
> +int route_irq_to_guest(struct domain *d, unsigned int virq,
> +                       unsigned int irq, const char *devname);
>  void arch_move_irqs(struct vcpu *v);
>  
>  /* Set IRQ type for an SPI */
> diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
> index 8582d9d..1cd7808 100644
> --- a/xen/include/asm-arm/vgic.h
> +++ b/xen/include/asm-arm/vgic.h
> @@ -181,8 +181,8 @@ extern int domain_vgic_init(struct domain *d);
>  extern void domain_vgic_free(struct domain *d);
>  extern int vcpu_vgic_init(struct vcpu *v);
>  extern struct vcpu *vgic_get_target_vcpu(struct vcpu *v, unsigned int irq);
> -extern void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq);
> -extern void vgic_vcpu_inject_spi(struct domain *d, unsigned int irq);
> +extern void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int virq);
> +extern void vgic_vcpu_inject_spi(struct domain *d, unsigned int virq);
>  extern void vgic_clear_pending_irqs(struct vcpu *v);
>  extern struct pending_irq *irq_to_pending(struct vcpu *v, unsigned int irq);
>  extern struct vgic_irq_rank *vgic_rank_offset(struct vcpu *v, int b, int n, 
> int s);
> -- 
> 2.1.4
> 

_______________________________________________
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®.