From patchwork Tue Jun 7 16:48:42 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julien Grall X-Patchwork-Id: 69563 Delivered-To: patch@linaro.org Received: by 10.140.106.246 with SMTP id e109csp2075627qgf; Tue, 7 Jun 2016 09:50:40 -0700 (PDT) X-Received: by 10.31.52.204 with SMTP id b195mr165209vka.112.1465318225437; Tue, 07 Jun 2016 09:50:25 -0700 (PDT) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org. [192.237.175.120]) by mx.google.com with ESMTPS id a192si6881408vkf.47.2016.06.07.09.50.25 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Jun 2016 09:50:25 -0700 (PDT) Received-SPF: neutral (google.com: 192.237.175.120 is neither permitted nor denied by best guess record for domain of xen-devel-bounces@lists.xen.org) client-ip=192.237.175.120; Authentication-Results: mx.google.com; spf=neutral (google.com: 192.237.175.120 is neither permitted nor denied by best guess record for domain of xen-devel-bounces@lists.xen.org) smtp.mailfrom=xen-devel-bounces@lists.xen.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bAKBe-0000Si-IN; Tue, 07 Jun 2016 16:49:06 +0000 Received: from mail6.bemta14.messagelabs.com ([193.109.254.103]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bAKBd-0000QZ-04 for xen-devel@lists.xen.org; Tue, 07 Jun 2016 16:49:05 +0000 Received: from [193.109.254.147] by server-1.bemta-14.messagelabs.com id 6D/60-28808-00BF6575; Tue, 07 Jun 2016 16:49:04 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrMLMWRWlGSWpSXmKPExsVysyfVTff/r7B wg6cnDS2WfFzM4sDocXT3b6YAxijWzLyk/IoE1owz12+wFPwyrLhy/TdLA+NljS5GLg4hgQ2M Et0nD7B2MXICOacZJe49NAKx2QQ0Je58/sQEYosISEtc+3yZEaSBWWAeo8SZhTvZQRLCAr4SW z60gdksAqoSt/ruMILYvALOEqsv9oLZEgJyEiePTQZbwCngIvHy+UsWiGXOEg8adjFPYORewM iwilGjOLWoLLVI19BQL6koMz2jJDcxMwfIM9HLTS0uTkxPzUlMKtZLzs/dxAj0MAMQ7GA8s8L 5EKMkB5OSKO/Tb2HhQnxJ+SmVGYnFGfFFpTmpxYcYNTg4BDavXX2BUYolLz8vVUmCd8ZPoDrB otT01Iq0zBxgCMKUSnDwKInwZr0DSvMWFyTmFmemQ6ROMSpKifPqgCQEQBIZpXlwbbCwv8QoK yXMywh0lBBPQWpRbmYJqvwrRnEORiVhXg+Q7TyZeSVw018BLWYCWszyFWxxSSJCSqqBccUbz4 LFS05v2y+yxn7LBR71nQe2yaXx7rvxSHeb7aMYnUOndxjeYOgQeTfpi1vF9odH7ZgULJSkUm/ 3JO5tVXctz1Oe+bsx/MhxF8O1bL460qK/zvseniQbHe0QHbD896+zOT1M0zZc3ihXcEtw9fqZ D7IvTHu24s3xBwc715pGW5dej3eZYqHEUpyRaKjFXFScCAD0DVSPdgIAAA== X-Env-Sender: julien.grall@arm.com X-Msg-Ref: server-8.tower-27.messagelabs.com!1465318142!42645190!1 X-Originating-IP: [217.140.101.70] X-SpamReason: No, hits=0.0 required=7.0 tests= X-StarScan-Received: X-StarScan-Version: 8.46; banners=-,-,- X-VirusChecked: Checked Received: (qmail 47034 invoked from network); 7 Jun 2016 16:49:03 -0000 Received: from foss.arm.com (HELO foss.arm.com) (217.140.101.70) by server-8.tower-27.messagelabs.com with SMTP; 7 Jun 2016 16:49:03 -0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 2AB29F; Tue, 7 Jun 2016 09:49:37 -0700 (PDT) Received: from e108454-lin.cambridge.arm.com (e108454-lin.cambridge.arm.com [10.1.215.28]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 72B663F246; Tue, 7 Jun 2016 09:49:01 -0700 (PDT) From: Julien Grall To: xen-devel@lists.xen.org Date: Tue, 7 Jun 2016 17:48:42 +0100 Message-Id: <1465318123-3090-8-git-send-email-julien.grall@arm.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1465318123-3090-1-git-send-email-julien.grall@arm.com> References: <1465318123-3090-1-git-send-email-julien.grall@arm.com> Cc: sstabellini@kernel.org, wei.chen@arm.com, steve.capper@arm.com, Julien Grall , shannon.zhao@linaro.org, shankerd@codeaurora.org Subject: [Xen-devel] [RFC 7/8] xen/arm: Allow DOM0 to set the irq type when ACPI is inuse X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" The function route_irq_to_guest mandates the IRQ type, stored in desc->arch.type, to be valid. However, in case of ACPI, these information is not part of the static tables. Therefore Xen needs to rely on DOM0 to provide a valid type based on the firmware tables. A new helper, irq_type_set_by_domain is provided to check whether a domain is allowed to set the IRQ type. For now, only DOM0 is allowed to configure it when ACPI is inuse. When the helper returns 1, the routing function will not check whether the IRQ type is correctly set and configure the GIC. Instead, this will be done when the domain will enable the interrupt. Note that irq_set_spi_type is not called because it validates the type and does not allow it the domain to change the type after the first write. It means that desc->arch.type will never be set, which is fine because the field is only used to configure the type during the routing. Signed-off-by: Julien Grall --- I am thinking to at least extend the behavior to DOM0 using DT. This would make us resilient to a DT not providing the correct type without having to workaround them in Xen. Furthermore, it might be possible to let any domain configuring the IRQ type (could be useful when passthrough an IRQ with ACPI). However, we would need to consider any potential security impact beforehand. --- xen/arch/arm/gic.c | 5 +++-- xen/arch/arm/irq.c | 14 +++++++++++++- xen/arch/arm/vgic.c | 21 +++++++++++++++++++++ xen/include/asm-arm/gic.h | 3 +++ xen/include/asm-arm/irq.h | 6 ++++++ 5 files changed, 46 insertions(+), 3 deletions(-) diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c index 27cd177..80d93a8 100644 --- a/xen/arch/arm/gic.c +++ b/xen/arch/arm/gic.c @@ -97,7 +97,7 @@ void gic_restore_state(struct vcpu *v) } /* desc->irq needs to be disabled before calling this function */ -static void gic_set_irq_type(struct irq_desc *desc, unsigned int type) +void gic_set_irq_type(struct irq_desc *desc, unsigned int type) { /* * IRQ must be disabled before configuring it (see 4.3.13 in ARM IHI @@ -162,7 +162,8 @@ int gic_route_irq_to_guest(struct domain *d, unsigned int virq, desc->handler = gic_hw_ops->gic_guest_irq_type; set_bit(_IRQ_GUEST, &desc->status); - gic_set_irq_type(desc, desc->arch.type); + if ( !irq_type_set_by_domain(d) ) + gic_set_irq_type(desc, desc->arch.type); gic_set_irq_priority(desc, priority); p->desc = desc; diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c index 2f8af72..b9d7749 100644 --- a/xen/arch/arm/irq.c +++ b/xen/arch/arm/irq.c @@ -27,6 +27,7 @@ #include #include +#include static unsigned int local_irqs_type[NR_LOCAL_IRQS]; static DEFINE_SPINLOCK(local_irqs_type_lock); @@ -395,6 +396,17 @@ bool_t is_assignable_irq(unsigned int irq) } /* + * When ACPI is inuse, only the hardware domain knows the interrupt + * type. + * + * XXX: See whether it is possible to let any domain configure the type. + */ +bool_t irq_type_set_by_domain(const struct domain *d) +{ + return ((d == hardware_domain) && !acpi_disabled); +} + +/* * Route an IRQ to a specific guest. * For now only SPIs are assignable to the guest. */ @@ -449,7 +461,7 @@ int route_irq_to_guest(struct domain *d, unsigned int virq, spin_lock_irqsave(&desc->lock, flags); - if ( desc->arch.type == IRQ_TYPE_INVALID ) + if ( desc->arch.type == IRQ_TYPE_INVALID && !irq_type_set_by_domain(d) ) { printk(XENLOG_G_ERR "IRQ %u has not been configured\n", irq); retval = -EIO; diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c index ee35683..3e1c572 100644 --- a/xen/arch/arm/vgic.c +++ b/xen/arch/arm/vgic.c @@ -249,6 +249,24 @@ static int vgic_get_virq_priority(struct vcpu *v, unsigned int virq) return priority; } +#define NR_CFG_PER_ICFGR 16 +#define NR_BITS_PER_CFG (32U / NR_CFG_PER_ICFGR) + +/* The function should be called witht the rank lock taken. */ +static int __vgic_get_virq_type(struct vcpu *v, unsigned int virq) +{ + struct vgic_irq_rank *rank = vgic_rank_irq(v, virq); + uint8_t index = virq & INTERRUPT_RANK_MASK; + uint32_t reg = rank->icfg[index / NR_CFG_PER_ICFGR]; + uint8_t val; + + ASSERT(spin_is_locked(&rank->lock)); + + val = reg >> ((index % NR_CFG_PER_ICFGR) * NR_BITS_PER_CFG); + + return (val & 0x2) ? IRQ_TYPE_EDGE_RISING : IRQ_TYPE_LEVEL_HIGH; +} + void vgic_migrate_irq(struct vcpu *old, struct vcpu *new, unsigned int irq) { unsigned long flags; @@ -342,6 +360,7 @@ void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n) unsigned long flags; int i = 0; struct vcpu *v_target; + struct domain *d = v->domain; while ( (i = find_next_bit(&mask, 32, i)) < 32 ) { irq = i + (32 * n); @@ -356,6 +375,8 @@ void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n) { irq_set_affinity(p->desc, cpumask_of(v_target->processor)); spin_lock_irqsave(&p->desc->lock, flags); + if ( irq_type_set_by_domain(d) ) + gic_set_irq_type(p->desc, __vgic_get_virq_type(v, irq)); p->desc->handler->enable(p->desc); spin_unlock_irqrestore(&p->desc->lock, flags); } diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h index ddc45a8..44b9ef6 100644 --- a/xen/include/asm-arm/gic.h +++ b/xen/include/asm-arm/gic.h @@ -222,6 +222,9 @@ enum gic_version { extern enum gic_version gic_hw_version(void); +/* Program the IRQ type into the GIC */ +void gic_set_irq_type(struct irq_desc *desc, unsigned int type); + /* 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); diff --git a/xen/include/asm-arm/irq.h b/xen/include/asm-arm/irq.h index 493773c..8f7a167 100644 --- a/xen/include/asm-arm/irq.h +++ b/xen/include/asm-arm/irq.h @@ -58,6 +58,12 @@ int platform_get_irq(const struct dt_device_node *device, int index); void irq_set_affinity(struct irq_desc *desc, const cpumask_t *cpu_mask); +/* + * Use this helper in places that need to know whether the IRQ type is + * set by the domain. + */ +bool_t irq_type_set_by_domain(const struct domain *d); + #endif /* _ASM_HW_IRQ_H */ /* * Local variables: