From mboxrd@z Thu Jan 1 00:00:00 1970 From: Julien Grall Subject: [PATCH v2 06/21] xen/arm: Allow virq != irq Date: Thu, 31 Jul 2014 16:00:37 +0100 Message-ID: <1406818852-31856-7-git-send-email-julien.grall@linaro.org> References: <1406818852-31856-1-git-send-email-julien.grall@linaro.org> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: Received: from mail6.bemta5.messagelabs.com ([195.245.231.135]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1XCrqx-0000Xc-W5 for xen-devel@lists.xenproject.org; Thu, 31 Jul 2014 15:01:12 +0000 Received: by mail-wi0-f177.google.com with SMTP id ho1so4306696wib.10 for ; Thu, 31 Jul 2014 08:01:08 -0700 (PDT) In-Reply-To: <1406818852-31856-1-git-send-email-julien.grall@linaro.org> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: xen-devel@lists.xenproject.org Cc: stefano.stabellini@citrix.com, Julien Grall , tim@xen.org, ian.campbell@citrix.com List-Id: xen-devel@lists.xenproject.org Actually Xen is assuming that the virtual IRQ will always be equal the IRQ. Modify, route_guest_irq to take the virtual IRQ in parameter and let Xen assigned a different IRQ number. Also store the vIRQ in the desc action to retrieve easily the IRQ target when we need to inject the interrupt. As DOM0 will get most the device, the vIRQ is equal to the IRQ. Signed-off-by: Julien Grall --- 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/include/asm-arm/gic.h | 3 ++- xen/include/asm-arm/irq.h | 4 ++-- 5 files changed, 42 insertions(+), 19 deletions(-) diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c index 47d114f..0dfe223 100644 --- a/xen/arch/arm/domain_build.c +++ b/xen/arch/arm/domain_build.c @@ -1009,7 +1009,7 @@ static int handle_device(struct domain *d, struct dt_device_node *dev) if ( available ) { - 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 6611ba0..8ef8764 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; +}; + 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/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h index a0c07bf..89816cd 100644 --- a/xen/include/asm-arm/gic.h +++ b/xen/include/asm-arm/gic.h @@ -196,7 +196,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 e877334..9bc3492 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 */ -- 1.7.10.4