From patchwork Wed Jul 27 13:58:28 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julien Grall X-Patchwork-Id: 72875 Delivered-To: patch@linaro.org Received: by 10.140.29.52 with SMTP id a49csp328909qga; Wed, 27 Jul 2016 07:01:33 -0700 (PDT) X-Received: by 10.107.139.194 with SMTP id n185mr36766449iod.159.1469628093680; Wed, 27 Jul 2016 07:01:33 -0700 (PDT) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org. [192.237.175.120]) by mx.google.com with ESMTPS id i68si7491038iod.98.2016.07.27.07.01.33 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 27 Jul 2016 07:01:33 -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 1bSPMI-0006Ne-Cv; Wed, 27 Jul 2016 13:58:50 +0000 Received: from mail6.bemta14.messagelabs.com ([193.109.254.103]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bSPMH-0006Mx-Pe for xen-devel@lists.xen.org; Wed, 27 Jul 2016 13:58:49 +0000 Received: from [193.109.254.147] by server-7.bemta-14.messagelabs.com id FF/13-06589-91EB8975; Wed, 27 Jul 2016 13:58:49 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrILMWRWlGSWpSXmKPExsVysyfVTVdi34x wg4vbRSyWfFzM4sDocXT3b6YAxijWzLyk/IoE1oxHq26yF6w2q9i3QLiBcY12FyMXh5DARkaJ ruUHGCGc04wSpw7cZ+9i5ORgE9CUuPP5ExOILSIgLXHt82VGEJtZYCGjxNvdISC2sIC9xKMp3 5lBbBYBVYnGMy2sIDavgLPEi02TwWwJATmJk8cgbE4BF4neS5fA5ggB1Zz5u5F1AiP3AkaGVY zqxalFZalFupZ6SUWZ6RkluYmZObqGhiZ6uanFxYnpqTmJScV6yfm5mxiB3mUAgh2M/VOcDzF KcjApifIucpwRLsSXlJ9SmZFYnBFfVJqTWnyIUYODQ2Dz2tUXGKVY8vLzUpUkeG/uAaoTLEpN T61Iy8wBhh9MqQQHj5II78zdQGne4oLE3OLMdIjUKUZFKXHeXpA+AZBERmkeXBss5C8xykoJ8 zICHSXEU5BalJtZgir/ilGcg1FJmLcOZApPZl4J3PRXQIuZgBYXx4ItLklESEk1MCYLZi59db jTznmCoHWawnsJd+FTlxVS3jc1KUplzXiSejlN4b7X4ehv9nadbJvZdV6kzJO9I/Ba88aBBXe OPzu7+mfRkdPCDjtXXXG7xWIoecqL+4ABz6PVF/Ll6086Sc3+lz7b5kL+jsXaOZP+fcl/l1KV 6zNBeNn1cN0vZ7w3OzjvePM6xEaJpTgj0VCLuag4EQBGFNQddAIAAA== X-Env-Sender: julien.grall@arm.com X-Msg-Ref: server-6.tower-27.messagelabs.com!1469627927!56367039!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.77; banners=-,-,- X-VirusChecked: Checked Received: (qmail 2464 invoked from network); 27 Jul 2016 13:58:48 -0000 Received: from foss.arm.com (HELO foss.arm.com) (217.140.101.70) by server-6.tower-27.messagelabs.com with SMTP; 27 Jul 2016 13:58:48 -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 BD1FB2F; Wed, 27 Jul 2016 07:00:03 -0700 (PDT) Received: from e108454-lin.cambridge.arm.com (e108454-lin.cambridge.arm.com [10.1.218.32]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 3FDA23F25F; Wed, 27 Jul 2016 06:58:46 -0700 (PDT) From: Julien Grall To: xen-devel@lists.xen.org Date: Wed, 27 Jul 2016 14:58:28 +0100 Message-Id: <1469627910-3902-8-git-send-email-julien.grall@arm.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1469627910-3902-1-git-send-email-julien.grall@arm.com> References: <1469627910-3902-1-git-send-email-julien.grall@arm.com> Cc: sstabellini@kernel.org, steve.capper@arm.com, Julien Grall , shannon.zhao@linaro.org, shankerd@codeaurora.org, wei.chen@linaro.org Subject: [Xen-devel] [PATCH v3 7/9] xen/arm: Allow DOM0 to set the IRQ type 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. 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 may never be set, which is fine because the field is only used to configure the type during the routing. Based on 4.3.13 in ARM IHI 0048B.b, changing the value of Int_config is UNPREDICTABLE when the corresponding interrupt is not disabled. Therefore, setting the IRQ type when the guest is writing into ICFGR would require more work to make sure the IRQ has been disabled before writing into the host ICFGR. As the behavior is UNPREDICTABLE, the type will be set before enabling the physical IRQ associated to the virtual IRQ. Signed-off-by: Julien Grall Tested-by: Shanker Donthineni --- It might be possible to let any domain configure the IRQ type (could be useful when passthrough an IRQ with ACPI). However, we would need to consider any potential security impact beforehand. Changes in v3: - The current code only handle SPIs, add an assert to catch any support PPIs without modifying this code. - Tested by Shanker on QDF2XXX server Changes in v2: - Rename the patch - Allow any DOM0 to set the IRQ type - Re-use in part of vgic_get_virq_type from "Configure SPI interrupt type and route to Dom0 dynamically". - Add rationale why the IRQ type is set in enable --- xen/arch/arm/gic.c | 5 +++-- xen/arch/arm/irq.c | 13 ++++++++++++- xen/arch/arm/vgic.c | 24 ++++++++++++++++++++++++ xen/include/asm-arm/gic.h | 3 +++ xen/include/asm-arm/irq.h | 6 ++++++ 5 files changed, 48 insertions(+), 3 deletions(-) diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c index 72bb885..63c744a 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 @@ -160,7 +160,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 3fc22f2..06d4843 100644 --- a/xen/arch/arm/irq.c +++ b/xen/arch/arm/irq.c @@ -395,6 +395,17 @@ bool_t is_assignable_irq(unsigned int irq) } /* + * Only the hardware domain is allowed to set the configure the + * interrupt type for now. + * + * 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); +} + +/* * Route an IRQ to a specific guest. * For now only SPIs are assignable to the guest. */ @@ -449,7 +460,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 ( !irq_type_set_by_domain(d) && desc->arch.type == IRQ_TYPE_INVALID ) { 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 938bc7d..0965119 100644 --- a/xen/arch/arm/vgic.c +++ b/xen/arch/arm/vgic.c @@ -340,6 +340,22 @@ void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n) } } +#define VGIC_ICFG_MASK(intr) (1 << ((2 * ((intr) % 16)) + 1)) + +/* The function should be called with the rank lock taken */ +static inline unsigned int vgic_get_virq_type(struct vcpu *v, int n, int index) +{ + struct vgic_irq_rank *r = vgic_get_rank(v, n); + uint32_t tr = r->icfg[index >> 4]; + + ASSERT(spin_is_locked(&r->lock)); + + if ( tr & VGIC_ICFG_MASK(index) ) + return IRQ_TYPE_EDGE_RISING; + else + return IRQ_TYPE_LEVEL_HIGH; +} + void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n) { const unsigned long mask = r; @@ -348,6 +364,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); @@ -362,6 +379,13 @@ 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); + /* + * The irq cannot be a PPI, we only support delivery of SPIs + * to guests. + */ + ASSERT(irq >= 32); + if ( irq_type_set_by_domain(d) ) + gic_set_irq_type(p->desc, vgic_get_virq_type(v, n, i)); 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 2214e87..836a103 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, unsigned int priority); extern int gic_route_irq_to_guest(struct domain *, unsigned int virq, 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: