From patchwork Mon Apr 3 20:28:12 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 9660593 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id C637F6032D for ; Mon, 3 Apr 2017 20:29:30 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B800328403 for ; Mon, 3 Apr 2017 20:29:30 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AD08D28425; Mon, 3 Apr 2017 20:29:30 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 3E00328403 for ; Mon, 3 Apr 2017 20:29:30 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cv8Yn-0004yP-3A; Mon, 03 Apr 2017 20:26:45 +0000 Received: from mail6.bemta6.messagelabs.com ([193.109.254.103]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cv8Ym-0004xF-6l for xen-devel@lists.xenproject.org; Mon, 03 Apr 2017 20:26:44 +0000 Received: from [85.158.143.35] by server-7.bemta-6.messagelabs.com id 59/20-04817-300B2E85; Mon, 03 Apr 2017 20:26:43 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrOLMWRWlGSWpSXmKPExsVysyfVTZdpw6M Ig6bLNhbft0xmcmD0OPzhCksAYxRrZl5SfkUCa0b7/6WMBfc1K470bGJsYHyl0MXIxSEksIlR YvnfjYwQznJGidbnx4EcTg42AV2JHTdfM4PYIgKhEk8XfAezmQWUJPafvQZWIyzgInGrbTIri M0ioCqxaG8TWA2vgLXE5e+7wOISAnISDefvg8U5geKtH4+C9QoJWElMeNjENIGRewEjwypGje LUorLUIl1jA72kosz0jJLcxMwcXUMDM73c1OLixPTUnMSkYr3k/NxNjEAPMwDBDsa/awMPMUp yMCmJ8qpPehQhxJeUn1KZkVicEV9UmpNafIhRhoNDSYL32DqgnGBRanpqRVpmDjDUYNISHDxK IrybQdK8xQWJucWZ6RCpU4yKUuK8GSAJAZBERmkeXBssvC8xykoJ8zICHSLEU5BalJtZgir/i lGcg1FJmPcGyBSezLwSuOmvgBYzAS1+cuchyOKSRISUVANjgdbNv7PvzN4ZJRV+hLcybdID92 23GE43nPRRfD1deXIPf53usYvKD04+bj4puf2/0pqHPVMnHt8WKRJwzfHk5D3nU/uUrkRMjV7 fdJrzm/aflMipuofCnvBmbj1w/H7xlocW8omsk1weJcVYc/3aynDRNKEo0iOoeevcHxsUuNcf 9z++8Pr6BiWW4oxEQy3mouJEAPSzNIVqAgAA X-Env-Sender: andre.przywara@arm.com X-Msg-Ref: server-8.tower-21.messagelabs.com!1491251202!61773175!1 X-Originating-IP: [217.140.101.70] X-SpamReason: No, hits=0.0 required=7.0 tests= X-StarScan-Received: X-StarScan-Version: 9.2.3; banners=-,-,- X-VirusChecked: Checked Received: (qmail 57524 invoked from network); 3 Apr 2017 20:26:42 -0000 Received: from foss.arm.com (HELO foss.arm.com) (217.140.101.70) by server-8.tower-21.messagelabs.com with SMTP; 3 Apr 2017 20:26:42 -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 2488280D; Mon, 3 Apr 2017 13:26:42 -0700 (PDT) Received: from e104803-lin.lan (unknown [10.1.207.46]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 640643F4FF; Mon, 3 Apr 2017 13:26:41 -0700 (PDT) From: Andre Przywara To: Julien Grall , Stefano Stabellini Date: Mon, 3 Apr 2017 21:28:12 +0100 Message-Id: <20170403202829.7278-11-andre.przywara@arm.com> X-Mailer: git-send-email 2.9.0 In-Reply-To: <20170403202829.7278-1-andre.przywara@arm.com> References: <20170403202829.7278-1-andre.przywara@arm.com> Cc: xen-devel@lists.xenproject.org Subject: [Xen-devel] [PATCH v4 10/27] ARM: GICv3: forward pending LPIs to guests 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" X-Virus-Scanned: ClamAV using ClamSMTP Upon receiving an LPI, we need to find the right VCPU and virtual IRQ number to get this IRQ injected. Iterate our two-level LPI table to find this information quickly when the host takes an LPI. Call the existing injection function to let the GIC emulation deal with this interrupt. Signed-off-by: Andre Przywara --- xen/arch/arm/gic-v3-lpi.c | 42 ++++++++++++++++++++++++++++++++++++++++++ xen/arch/arm/gic.c | 8 +++++++- xen/arch/arm/vgic-v3.c | 11 +++++++++++ xen/arch/arm/vgic.c | 9 ++++++++- xen/include/asm-arm/irq.h | 2 ++ xen/include/asm-arm/vgic.h | 2 ++ 6 files changed, 72 insertions(+), 2 deletions(-) diff --git a/xen/arch/arm/gic-v3-lpi.c b/xen/arch/arm/gic-v3-lpi.c index d3ee141..ad89863 100644 --- a/xen/arch/arm/gic-v3-lpi.c +++ b/xen/arch/arm/gic-v3-lpi.c @@ -125,6 +125,48 @@ uint64_t gicv3_get_redist_address(unsigned int cpu, bool use_pta) return per_cpu(lpi_redist, cpu).redist_id << 16; } +/* + * Handle incoming LPIs, which are a bit special, because they are potentially + * numerous and also only get injected into guests. Treat them specially here, + * by just looking up their target vCPU and virtual LPI number and hand it + * over to the injection function. + */ +void do_LPI(unsigned int lpi) +{ + struct domain *d; + union host_lpi *hlpip, hlpi; + struct vcpu *vcpu; + + WRITE_SYSREG32(lpi, ICC_EOIR1_EL1); + + hlpip = gic_get_host_lpi(lpi); + if ( !hlpip ) + return; + + hlpi.data = read_u64_atomic(&hlpip->data); + + /* Unmapped events are marked with an invalid LPI ID. */ + if ( hlpi.virt_lpi == INVALID_LPI ) + return; + + d = rcu_lock_domain_by_id(hlpi.dom_id); + if ( !d ) + return; + + /* Make sure we don't step beyond the vcpu array. */ + if ( hlpi.vcpu_id >= d->max_vcpus ) + { + rcu_unlock_domain(d); + return; + } + + vcpu = d->vcpu[hlpi.vcpu_id]; + + vgic_vcpu_inject_irq(vcpu, hlpi.virt_lpi); + + rcu_unlock_domain(d); +} + static int gicv3_lpi_allocate_pendtable(uint64_t *reg) { uint64_t val; diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c index 3ed6f81..a6037d4 100644 --- a/xen/arch/arm/gic.c +++ b/xen/arch/arm/gic.c @@ -709,7 +709,13 @@ void gic_interrupt(struct cpu_user_regs *regs, int is_fiq) do_IRQ(regs, irq, is_fiq); local_irq_disable(); } - else if (unlikely(irq < 16)) +#ifdef CONFIG_HAS_ITS + else if ( is_lpi(irq) ) + { + do_LPI(irq); + } +#endif + else if ( unlikely(irq < 16) ) { do_sgi(regs, irq); } diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c index 95fa0ba..797fd86 100644 --- a/xen/arch/arm/vgic-v3.c +++ b/xen/arch/arm/vgic-v3.c @@ -347,6 +347,17 @@ struct pending_irq *lpi_to_pending(struct domain *d, unsigned int lpi) return pirq; } +/* Retrieve the priority of an LPI from its struct pending_irq. */ +int vgic_lpi_get_priority(struct domain *d, uint32_t vlpi) +{ + struct pending_irq *p = lpi_to_pending(d, vlpi); + + if ( !p ) + return GIC_PRI_IRQ; + + return p->lpi_priority; +} + static int __vgic_v3_rdistr_rd_mmio_write(struct vcpu *v, mmio_info_t *info, uint32_t gicr_reg, register_t r) diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c index 28f6f66..4720f46 100644 --- a/xen/arch/arm/vgic.c +++ b/xen/arch/arm/vgic.c @@ -226,10 +226,17 @@ struct vcpu *vgic_get_target_vcpu(struct vcpu *v, unsigned int virq) static int vgic_get_virq_priority(struct vcpu *v, unsigned int virq) { - struct vgic_irq_rank *rank = vgic_rank_irq(v, virq); + struct vgic_irq_rank *rank; unsigned long flags; int priority; +#ifdef CONFIG_HAS_ITS + /* LPIs don't have a rank, also store their priority separately. */ + if ( is_lpi(virq) ) + return vgic_lpi_get_priority(v->domain, virq); +#endif + + rank = vgic_rank_irq(v, virq); vgic_lock_rank(v, rank, flags); priority = rank->priority[virq & INTERRUPT_RANK_MASK]; vgic_unlock_rank(v, rank, flags); diff --git a/xen/include/asm-arm/irq.h b/xen/include/asm-arm/irq.h index 2f7ee8a..0cd0117 100644 --- a/xen/include/asm-arm/irq.h +++ b/xen/include/asm-arm/irq.h @@ -46,6 +46,8 @@ static inline bool is_lpi(unsigned int irq) return irq >= LPI_OFFSET; } +void do_LPI(unsigned int irq); + #define domain_pirq_to_irq(d, pirq) (pirq) bool_t is_assignable_irq(unsigned int irq); diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h index 69ef160..a24a971 100644 --- a/xen/include/asm-arm/vgic.h +++ b/xen/include/asm-arm/vgic.h @@ -66,12 +66,14 @@ struct pending_irq #define GIC_IRQ_GUEST_VISIBLE 2 #define GIC_IRQ_GUEST_ENABLED 3 #define GIC_IRQ_GUEST_MIGRATING 4 +#define GIC_IRQ_GUEST_LPI_PENDING 5 unsigned long status; struct irq_desc *desc; /* only set it the irq corresponds to a physical irq */ unsigned int irq; #define GIC_INVALID_LR (uint8_t)~0 uint8_t lr; uint8_t priority; + uint8_t lpi_priority; /* Caches the priority if this is an LPI. */ /* inflight is used to append instances of pending_irq to * vgic.inflight_irqs */ struct list_head inflight;