From patchwork Mon Feb 1 09:26:34 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: vijayak@caviumnetworks.com X-Patchwork-Id: 8177421 Return-Path: X-Original-To: patchwork-xen-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id E56A99F4DD for ; Mon, 1 Feb 2016 09:33:36 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 55E002041A for ; Mon, 1 Feb 2016 09:33:35 +0000 (UTC) Received: from lists.xen.org (lists.xenproject.org [50.57.142.19]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 9F77120412 for ; Mon, 1 Feb 2016 09:33:33 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xen.org) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1aQAob-0006wB-Bo; Mon, 01 Feb 2016 09:30:33 +0000 Received: from mail6.bemta14.messagelabs.com ([193.109.254.103]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1aQAnr-0006mB-0L for xen-devel@lists.xen.org; Mon, 01 Feb 2016 09:29:47 +0000 Received: from [193.109.254.147] by server-7.bemta-14.messagelabs.com id 07/26-28221-A852FA65; Mon, 01 Feb 2016 09:29:46 +0000 X-Env-Sender: Vijaya.Kumar@caviumnetworks.com X-Msg-Ref: server-3.tower-27.messagelabs.com!1454318982!20180954!1 X-Originating-IP: [157.56.110.74] X-SpamReason: No, hits=0.0 required=7.0 tests= X-StarScan-Received: X-StarScan-Version: 7.35.1; banners=-,-,- X-VirusChecked: Checked Received: (qmail 48801 invoked from network); 1 Feb 2016 09:29:43 -0000 Received: from mail-bn1on0074.outbound.protection.outlook.com (HELO na01-bn1-obe.outbound.protection.outlook.com) (157.56.110.74) by server-3.tower-27.messagelabs.com with AES256-SHA256 encrypted SMTP; 1 Feb 2016 09:29:43 -0000 Received: from cavium-Vostro-2520.caveonetworks.com (111.93.218.67) by BN3PR0701MB1688.namprd07.prod.outlook.com (10.163.39.154) with Microsoft SMTP Server (TLS) id 15.1.396.15; Mon, 1 Feb 2016 09:29:38 +0000 From: To: , , , , , Date: Mon, 1 Feb 2016 14:56:34 +0530 Message-ID: <1454318798-31913-25-git-send-email-vijayak@caviumnetworks.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1454318798-31913-1-git-send-email-vijayak@caviumnetworks.com> References: <1454318798-31913-1-git-send-email-vijayak@caviumnetworks.com> MIME-Version: 1.0 X-Originating-IP: [111.93.218.67] X-ClientProxiedBy: BM1PR01CA0026.INDPRD01.PROD.OUTLOOK.COM (25.163.198.161) To BN3PR0701MB1688.namprd07.prod.outlook.com (25.163.39.154) X-Microsoft-Exchange-Diagnostics: 1; BN3PR0701MB1688; 2:M9LAHH/X3G0DfsrVb6CUnbqQCYP5jkQIqN0sKQa1pLzlC1fGFQGRE6oRqbiq+ZT1E9XBxDuUVG5nsKo3UWyjw875NRBCdNvvjNJu0hwwQG98MasvxVB/3gqO/vU7EuQoeMDAtktWFQ4KVUXC5hPP5Q==; 3:Tgb9kKAXUOw/WKNP4K+dIhIYwG8SYogeMhN7YRDhzI9DK3ylrp5TDUPpYWB1aLmQU4/UTMXP1zCzIDE4dh7pmF8FcSwGKyxVDuRdsSUPHeRCT4p2shjycP0dPFesYXZR; 25:uwxnNIaUwNrEBvhEUOks8gfGka2KjJf10itFJRqsQQrWS13XspcQCi8PSRMDM69IGjoSk60Y4fI0hkIsT5UWcvO2KP5TKz1wx6dXa2TPIGQnIdMuDJve+w+jz2W0p84Pls5hXFYYzN3bJ1iqCMYJOUJgQ1e4g+OeFbeiPkWwtrf/aeJbIikcmWtM8QmZOvQg7gqODXaJbwAExso4QIQvIVp7JccSIXPhOXFxss/5NJ9rVcJ/ppVbluAv6KTtzICu X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BN3PR0701MB1688; X-MS-Office365-Filtering-Correlation-Id: 7130d583-088e-4515-a89e-08d32aea36a1 X-Microsoft-Exchange-Diagnostics: 1; BN3PR0701MB1688; 20:saLVl5G6nToWD7EsxMaPC+9G7jLItnjm4lNLIf8Qivy5dq3RJo7vOD0XFmipFrUSDQynCmOUh3yrIAYCUL7oE267A+nbbp6JE0VDIF5ojjviGNMNoPQr1RDVGGwHnZ9S0UASdhIFTn7wURtytaKLwtzuWUrTxYw1isHDoz9DO3piPh2PxhUhq9lKpjntySODaC6e3ZMPddvezcyHFuAJ4wGrzpwhK28kgCeTfmL3c75VCtXSM2YNFVv43K/6Sbw6yB5gUBpKM25rcCwJoKqxMcAOBzyKoaLJKgMliZhdI9jFOhqtd5CzSryiFLzAlUGUBZcEBWhmfZW01O26KWx3SselEUggdfkU83kPYXF1aDl4FA0lGbEBsyF9B4FsMI1LhCu/wpng5sAppvaRENK/QvH149G57OYmcjpi0BpfU9BiewDDUnVRMFdqsSJ604BNpyfo5qv+Jv1i6Wq1XY9wjmo574hxltY8jiJQz3Xf6EuC6ouHHtW2Sup9UWUKYuRHVjDb2GXqn3CSObTCpbITv+yCaccR9X3QjYihHXGjJw5X++54WMJrRIWdG3A3w3IIDtLIYup/CpURQzNkcVNMKS6fK2TIq3Aiwx2iug8a0K8= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(2401047)(5005006)(8121501046)(3002001)(10201501046); SRVR:BN3PR0701MB1688; BCL:0; PCL:0; RULEID:; SRVR:BN3PR0701MB1688; X-Microsoft-Exchange-Diagnostics: 1; BN3PR0701MB1688; 4:hNWVr73lO2mqdkdxTXnhpfJGLufYHidzM2n29w51glcgsun118SHt+/eO2I8sZWjYYmwiXo9KGRhQ3aYGG/CukZwniCCRmXAEpTCJtYz0Wf8WSMxZAalYnzlw+HBePAvz614rcECyQkKOh/71uOrP8ix0Px6Fk+wiLRwacZqZXsozuyOSX3l6jZqVCZEE58If2PmaPyQrOD4lQN2453/7E0eaEiZTF15jtolr6CXsm8tK4/SyR1aK5u2GaumSH4EcWWMnut8/EFZC4HkX3ziI2MOr8oSHnMBnXt5bxttLi8vG2S3CP/NoamuOnZzDNXifEqc6ufXbzGC04mhK+O+ibOcQWgG7UEmwvYaiv1fkwQYldv9aes0SPP/+HutIUYt X-Forefront-PRVS: 0839D067E7 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(6009001)(3846002)(5009440100003)(4001430100002)(586003)(1096002)(76176999)(50986999)(36756003)(189998001)(92566002)(5004730100002)(2950100001)(229853001)(50226001)(87976001)(86152002)(107886002)(2201001)(5001960100002)(77096005)(53416004)(48376002)(19580395003)(19580405001)(5003940100001)(5001770100001)(42186005)(33646002)(66066001)(47776003)(2906002)(2876002)(4326007)(122386002)(3470700001)(5008740100001)(50466002)(575784001)(40100003)(7099028)(7059030)(2101003); DIR:OUT; SFP:1101; SCL:1; SRVR:BN3PR0701MB1688; H:cavium-Vostro-2520.caveonetworks.com; FPR:; SPF:None; MLV:sfv; LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BN3PR0701MB1688; 23:6547RoMzv6vyTi/ZZd/042bSDjGosPCUPswQCvg?= =?us-ascii?Q?5L7RzsywJgJ4NAJ+sGbHozSiFjqjFR01KyewsS8i73gEAwKq2KJO6+Zphd19?= =?us-ascii?Q?YCL2CGq6sQ0VOxk1Wf64ZqKwYsdh8j1ltN8yeKoRZYIYpGift9HAJ/HgPKsa?= =?us-ascii?Q?yrbHOpCR1FdcIW1YtLOeMB2pAt8dl6MHXwQ21pkSRQVJB/BA1vCfN3NaHbcH?= =?us-ascii?Q?/11zLgutJc6JuCQxfY4QyOqJWFeW6mNLnqMC5meQuGYwhlCzuwWjysSIHCxu?= =?us-ascii?Q?mVF5HK0eOY++tXh3VWfeTWlxMVa9UatRmX7CdXdLIJOt1gpy5vFwGBnVvsiE?= =?us-ascii?Q?xk3OHrMrRTBdU7w2C25L167XfYxIbs3f2p4zAZRbUO0yoxwDGk+g7KHjbpTI?= =?us-ascii?Q?yYt1k5he1XyXXcY1sH7d5rj4kZcY8oY9lD3oJ2tcnuUaOZIw4qjWqhUNw3fC?= =?us-ascii?Q?h24DmuDke/bn4KwutCndeeurdNpE7ZKnnF242e+P26xxwzjgTCJwkR5VJhKW?= =?us-ascii?Q?RJJbIZhcdZXsnlPI8mvHmT7VebXIxxW3Yl1k8c+KzYjFsM6X/ca5Fq4uUK1P?= =?us-ascii?Q?bAj9VpdioD3cgbNFZKO1w7qVWHAJFuMLflX5DT3mAfygAwDwfoI/Ig0rHHnP?= =?us-ascii?Q?+NuYw6GqHNt0zhmzCSsnQSlWmBuDhOxOUIJEbwVALUdNPkeVDGZZhkXqug8v?= =?us-ascii?Q?+V94GGYkRi5foPztWShBi8LlJkJTtsqBxLgCJjlNmZQxUgUgqPOshUqYAp9Z?= =?us-ascii?Q?Hu9fqWIxA6xBaUmqWeFbAAyrupbtm/MtyPyiTX1XuSnbo1LJ0sqKlXyJ0kIG?= =?us-ascii?Q?9ZQrnqH2ef7auNe8ENQ3uCMWn/uwjzyAphd+SlZQtK4GBs4h7K4GzgFS29YR?= =?us-ascii?Q?J1WcUVpC5VcYD7Pwkrezvbu8pZXv5dysjj6O9eedWlUPlfyak1LpROx93pgh?= =?us-ascii?Q?ZHQJbJu3kAqxmF5lQp1g2lMZDUR7GXMiNoqS5T7si/dEw6a38+28SN43ne9T?= =?us-ascii?Q?esthHYS9NNRdmmCPC3C1BwT1cToqPE/klW+9XNyPPHW6TeU5ICpRTgQME1pK?= =?us-ascii?Q?2gdSKalGd8Q6qHkGBZ0Isl7ybGCDXg4WYt7FdC1R+vkzVzhJj1HIFiRHyyUO?= =?us-ascii?Q?owIfcT86lHF56gRYPQ74y8Mp3WuSDJHnnSA9a+eiEEp7yQ/LrEtbnng=3D?= =?us-ascii?Q?=3D?= X-Microsoft-Exchange-Diagnostics: 1; BN3PR0701MB1688; 5:Hn/UXdXPc8yRUriB2JLfngfb4X0gP76TK9bcVKVlwowqq+dNWA66IOUcqKvz+CtLzM1CfXNvWt04eH2wQXUjDlixVtXRYZusJ5I7VNKfolEXZP2mbyy9iwx2YPoQdU8+/MGm/x/jUZ/I1NMy7vJAHQ==; 24:YA+6sGamG/lYcD8RALCLUp0UKnJegt1A2X4iFx+23/iAEuWK3tOwlFk22hHRWv7inu7vHyZJNGMx4k10C9KgGSTNPo0anW24COdqXV0qmjE= SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: caviumnetworks.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 01 Feb 2016 09:29:38.0519 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN3PR0701MB1688 X-Mailman-Approved-At: Mon, 01 Feb 2016 09:30:20 +0000 Cc: Prasun.Kapoor@caviumnetworks.com, manish.jaggi@caviumnetworks.com, Vijaya Kumar K , vijay.kilari@gmail.com Subject: [Xen-devel] [PATCH v8 24/28] xen/arm: ITS: Route LPIs X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAD_ENC_HEADER,BAYES_00, RCVD_IN_DNSWL_MED, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Vijaya Kumar K Allocate and initialize irq descriptor for LPIs and route LPIs to guest For LPIs deactivation is not required. Hence GICH_LR.HW is not required to set. Signed-off-by: Vijaya Kumar K --- v7: - Subtract 8192 from irq number to index to lpi property table to read priority v6: - Moved ITS specific code from irq.c to vgic.c and introduced vgic_vcpu_raise_lpi() - Renamed gicv3_set_properties to gicv3_set_irq_properties - Always Inject LPI to vcpu0 - Changed route_lpi_to_guest definition --- xen/arch/arm/gic-v3-its.c | 17 ++++++- xen/arch/arm/gic-v3.c | 16 ++++-- xen/arch/arm/gic.c | 32 +++++++++++- xen/arch/arm/irq.c | 112 ++++++++++++++++++++++++++++++++++++++--- xen/arch/arm/vgic-v3-its.c | 2 +- xen/arch/arm/vgic.c | 103 +++++++++++++++++++++++++++++++++++-- xen/include/asm-arm/gic-its.h | 3 ++ xen/include/asm-arm/gic.h | 8 ++- xen/include/asm-arm/irq.h | 2 + xen/include/asm-arm/vgic.h | 3 ++ 10 files changed, 276 insertions(+), 22 deletions(-) diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c index 1dcfc39..cbf517a 100644 --- a/xen/arch/arm/gic-v3-its.c +++ b/xen/arch/arm/gic-v3-its.c @@ -475,6 +475,21 @@ static void its_flush_and_invalidate_prop(struct irq_desc *desc, const u8 *cfg) its_send_inv(its_dev, vid); } +void its_set_lpi_properties(struct irq_desc *desc, + const cpumask_t *cpu_mask, + unsigned int priority) +{ + unsigned long flags; + u8 *cfg; + + spin_lock_irqsave(&its_lock, flags); + cfg = gic_rdists->prop_page + desc->irq - FIRST_GIC_LPI; + *cfg = (*cfg & 3) | (priority & LPI_PRIORITY_MASK) ; + + its_flush_and_invalidate_prop(desc, cfg); + spin_unlock_irqrestore(&its_lock, flags); +} + static void its_set_lpi_state(struct irq_desc *desc, int enable) { u8 *cfg; @@ -920,7 +935,7 @@ int its_assign_device(struct domain *d, u32 vdevid, u32 pdevid) for ( i = 0; i < pdev->event_map.nr_lpis; i++ ) { plpi = its_get_plpi(pdev, i); - /* TODO: Route lpi */ + route_lpi_to_guest(d, plpi, "LPI"); } return 0; diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c index 73b2708..47e6b8a 100644 --- a/xen/arch/arm/gic-v3.c +++ b/xen/arch/arm/gic-v3.c @@ -498,9 +498,9 @@ static inline uint64_t gicv3_mpidr_to_affinity(int cpu) MPIDR_AFFINITY_LEVEL(mpidr, 0)); } -static void gicv3_set_irq_properties(struct irq_desc *desc, - const cpumask_t *cpu_mask, - unsigned int priority) +static void gicv3_set_line_properties(struct irq_desc *desc, + const cpumask_t *cpu_mask, + unsigned int priority) { uint32_t cfg, actual, edgebit; uint64_t affinity; @@ -564,6 +564,16 @@ static int gicv3_dist_supports_lpis(void) return readl_relaxed(GICD + GICD_TYPER) & GICD_TYPER_LPIS_SUPPORTED; } +static void gicv3_set_irq_properties(struct irq_desc *desc, + const cpumask_t *cpu_mask, + unsigned int priority) +{ + if ( gic_is_lpi(desc->irq) ) + its_set_lpi_properties(desc, cpu_mask, priority); + else + gicv3_set_line_properties(desc, cpu_mask, priority); +} + static void __init gicv3_dist_init(void) { uint32_t type; diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c index d54bba9..ca115c3 100644 --- a/xen/arch/arm/gic.c +++ b/xen/arch/arm/gic.c @@ -72,6 +72,13 @@ bool_t gic_is_lpi(unsigned int irq) return (irq >= FIRST_GIC_LPI && irq < gic_nr_irq_ids()); } +/* Validates PPIs/SGIs/SPIs/LPIs supported */ +bool_t gic_is_valid_irq(unsigned int irq) +{ + return (irq < gic_hw_ops->info->nr_lines || gic_is_lpi(irq)); +} + +/* Returns number of PPIs/SGIs/SPIs supported */ unsigned int gic_number_lines(void) { return gic_hw_ops->info->nr_lines; @@ -124,7 +131,8 @@ void gic_route_irq_to_xen(struct irq_desc *desc, const cpumask_t *cpu_mask, unsigned int priority) { ASSERT(priority <= 0xff); /* Only 8 bits of priority */ - ASSERT(desc->irq < gic_number_lines());/* Can't route interrupts that don't exist */ + /* Can't route interrupts that don't exist */ + ASSERT(gic_is_valid_irq(desc->irq)); ASSERT(test_bit(_IRQ_DISABLED, &desc->status)); ASSERT(spin_is_locked(&desc->lock)); @@ -173,6 +181,26 @@ out: return res; } +int gic_route_lpi_to_guest(struct domain *d, struct irq_desc *desc, + unsigned int priority) +{ + ASSERT(spin_is_locked(&desc->lock)); + + desc->handler = gic_hw_ops->gic_get_guest_irq_type(desc->irq); + set_bit(_IRQ_GUEST, &desc->status); + + /* Set cpumask to current processor */ + gic_set_irq_properties(desc, cpumask_of(smp_processor_id()), priority); + + /* + * Enable LPI by default. Each pLPI is enabled and routed + * when device is assigned. + */ + desc->handler->enable(desc); + + return 0; +} + /* This function only works with SPIs for now */ int gic_remove_irq_from_guest(struct domain *d, unsigned int virq, struct irq_desc *desc) @@ -653,7 +681,7 @@ void gic_interrupt(struct cpu_user_regs *regs, int is_fiq) /* Reading IRQ will ACK it */ irq = gic_hw_ops->read_irq(); - if ( likely(irq >= 16 && irq < 1020) ) + if ( likely((irq >= 16 && irq < 1020) || gic_is_lpi(irq)) ) { local_irq_enable(); do_IRQ(regs, irq, is_fiq); diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c index e4c6019..bcb5e0d 100644 --- a/xen/arch/arm/irq.c +++ b/xen/arch/arm/irq.c @@ -209,7 +209,7 @@ int request_irq(unsigned int irq, unsigned int irqflags, * which interrupt is which (messes up the interrupt freeing * logic etc). */ - if ( irq >= nr_irqs ) + if ( !gic_is_valid_irq(irq) ) return -EINVAL; if ( !handler ) return -EINVAL; @@ -267,11 +267,16 @@ void do_IRQ(struct cpu_user_regs *regs, unsigned int irq, int is_fiq) set_bit(_IRQ_INPROGRESS, &desc->status); - /* - * The irq cannot be a PPI, we only support delivery of SPIs to - * guests. - */ - vgic_vcpu_inject_spi(info->d, info->virq); +#ifdef CONFIG_HAS_GICV3 + if ( gic_is_lpi(irq) ) + vgic_vcpu_raise_lpi(info->d, desc); + else +#endif + /* + * The irq cannot be a PPI, we only support delivery of SPIs to + * guests + */ + vgic_vcpu_inject_spi(info->d, info->virq); goto out_no_end; } @@ -356,6 +361,9 @@ void release_irq(unsigned int irq, const void *dev_id) /* Wait to make sure it's not being used on another CPU */ do { smp_mb(); } while ( test_bit(_IRQ_INPROGRESS, &desc->status) ); + if ( gic_is_lpi(irq) ) + xfree(desc->msi_desc); + if ( action->free_on_release ) xfree(action); } @@ -437,9 +445,97 @@ err: bool_t is_assignable_irq(unsigned int irq) { - /* For now, we can only route SPIs to the guest */ - return ((irq >= NR_LOCAL_IRQS) && (irq < gic_number_lines())); + /* For now, we can only route SPI/LPIs to the guest */ + return (((irq >= NR_LOCAL_IRQS) && (irq < gic_number_lines())) || + gic_is_lpi(irq)); +} + +#ifdef CONFIG_HAS_GICV3 +/* + * Route an LPI to a specific guest. + */ +int route_lpi_to_guest(struct domain *d, unsigned int plpi, const char *devname) +{ + struct irqaction *action; + struct irq_guest *info; + struct irq_desc *desc; + unsigned long flags; + int retval = 0; + + if ( !gic_is_lpi(plpi) ) + { + printk(XENLOG_G_ERR "Only LPI can be routed \n"); + return -EINVAL; + } + + action = xmalloc(struct irqaction); + if ( !action ) + return -ENOMEM; + + info = xmalloc(struct irq_guest); + if ( !info ) + { + xfree(action); + return -ENOMEM; + } + info->d = d; + + action->dev_id = info; + action->name = devname; + action->free_on_release = 1; + + desc = irq_to_desc(plpi); + spin_lock_irqsave(&desc->lock, flags); + + ASSERT(desc->msi_desc != NULL); + + if ( desc->arch.type == DT_IRQ_TYPE_INVALID ) + { + printk(XENLOG_G_ERR "LPI %u has not been configured\n", plpi); + retval = -EIO; + goto out; + } + + /* If the IRQ is already used by same domain, do not setup again.*/ + if ( desc->action != NULL ) + { + struct domain *ad = irq_get_domain(desc); + + if ( test_bit(_IRQ_GUEST, &desc->status) && d == ad ) + { + printk(XENLOG_G_ERR + "d%u: LPI %u is already assigned to domain %u\n", + d->domain_id, plpi, d->domain_id); + retval = -EBUSY; + goto out; + } + } + + retval = __setup_irq(desc, 0, action); + if ( retval ) + goto out; + + retval = gic_route_lpi_to_guest(d, desc, GIC_PRI_IRQ); + + spin_unlock_irqrestore(&desc->lock, flags); + + if ( retval ) + { + release_irq(desc->irq, info); + goto free_info; + } + + return 0; + +out: + spin_unlock_irqrestore(&desc->lock, flags); + xfree(action); +free_info: + xfree(info); + + return retval; } +#endif /* * Route an IRQ to a specific guest. diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c index 41e0b2a..a265452 100644 --- a/xen/arch/arm/vgic-v3-its.c +++ b/xen/arch/arm/vgic-v3-its.c @@ -354,7 +354,7 @@ static int vits_process_int(struct vcpu *v, struct vgic_its *vits, DPRINTK("%pv: vITS: INT: Device 0x%"PRIx32" id %"PRIu32"\n", v, dev_id, event); - /* TODO: Inject LPI */ + vgic_vcpu_inject_lpi(v->domain, dev_id, event); return 0; } diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c index 5b81583..e0ae5a5 100644 --- a/xen/arch/arm/vgic.c +++ b/xen/arch/arm/vgic.c @@ -31,7 +31,9 @@ #include #include +#include #include +#include static inline struct vgic_irq_rank *vgic_get_rank(struct vcpu *v, int rank) { @@ -266,13 +268,41 @@ 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; + int priority = 0; - vgic_lock_rank(v, rank, flags); - priority = rank->priority[virq & INTERRUPT_RANK_MASK]; - vgic_unlock_rank(v, rank, flags); + if ( !gic_is_lpi(virq) ) + { + 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); + } + else if ( vgic_is_domain_lpi(v->domain, virq) ) + { + /* + * Guest can receive LPI before availability of LPI property table. + * Hence assert is wrong. + * TODO: Handle LPI which is valid and does not have LPI property + * table entry and remove below assert. + */ + ASSERT(virq < v->domain->arch.vgic.prop_size); + + spin_lock_irqsave(&v->domain->arch.vgic.prop_lock, flags); + /* + * LPI property table always starts from 0 (==8192 LPI). + * So, subtract 8192 from irq value. + */ + priority = *((u8*)v->domain->arch.vgic.prop_page + virq - FIRST_GIC_LPI); + /* + * Bits[7:2] specify priority with bits[1:0] of priority + * is set to zero. Hence only mask bits[7:2] + */ + priority &= LPI_PRIORITY_MASK; + spin_unlock_irqrestore(&v->domain->arch.vgic.prop_lock, flags); + } return priority; } @@ -545,6 +575,69 @@ void vgic_vcpu_inject_spi(struct domain *d, unsigned int virq) vgic_vcpu_inject_irq(v, virq); } +#ifdef CONFIG_HAS_GICV3 +void vgic_vcpu_inject_lpi(struct domain *d, unsigned int vdevid, + unsigned int eventID) +{ + struct vdevice_table dt_entry; + struct vitt vitt_entry; + uint32_t col_id; + + if ( vits_get_vdevice_entry(d, vdevid, &dt_entry) ) + { + dprintk(XENLOG_WARNING, + "Failed to read dt entry for dev 0x%"PRIx32" ..dropping\n", + vdevid); + return; + } + + if ( dt_entry.vitt_ipa == INVALID_PADDR ) + { + dprintk(XENLOG_WARNING, + "Event %"PRId32" of dev 0x%"PRIx32" is invalid..dropping\n", + eventID, vdevid); + return; + } + + if ( vits_get_vitt_entry(d, vdevid, eventID, &vitt_entry) ) + { + dprintk(XENLOG_WARNING, + "Event %"PRId32" of dev 0x%"PRIx32" is invalid..dropping\n", + eventID, vdevid); + return; + } + + col_id = vitt_entry.vcollection; + + if ( !vitt_entry.valid || !is_valid_collection(d, col_id) || + !vgic_is_domain_lpi(d, vitt_entry.vlpi) ) + { + dprintk(XENLOG_WARNING, + "vlpi %"PRId32" for dev 0x%"PRIx32" is not valid..dropping\n", + vitt_entry.vlpi, vdevid); + return; + } + + /* + * We don't have vlpi to plpi mapping and hence we cannot + * have target on which corresponding vlpi is enabled. + * So for now we are always injecting vlpi on vcpu0. + * (See vgic_vcpu_inject_lpi() function) and so we get pending_irq + * structure on vcpu0. + * TODO: Get correct target vcpu + */ + vgic_vcpu_inject_irq(d->vcpu[0], vitt_entry.vlpi); +} + +void vgic_vcpu_raise_lpi(struct domain *d, struct irq_desc *desc) +{ + struct its_device *dev = irqdesc_get_its_device(desc); + unsigned int eventID = irqdesc_get_lpi_event(desc); + + vgic_vcpu_inject_lpi(d, dev->virt_device_id, eventID); +} +#endif + void arch_evtchn_inject(struct vcpu *v) { vgic_vcpu_inject_irq(v, v->domain->arch.evtchn_irq); diff --git a/xen/include/asm-arm/gic-its.h b/xen/include/asm-arm/gic-its.h index aad51fa..44919ee 100644 --- a/xen/include/asm-arm/gic-its.h +++ b/xen/include/asm-arm/gic-its.h @@ -303,6 +303,9 @@ int its_init(struct rdist_prop *rdists); int its_cpu_init(void); int its_add_device(u32 devid, u32 nr_ites, struct dt_device_node *dt_its); int its_assign_device(struct domain *d, u32 vdevid, u32 pdevid); +void its_set_lpi_properties(struct irq_desc *desc, + const cpumask_t *cpu_mask, + unsigned int priority); #endif /* __ASM_ARM_GIC_ITS_H__ */ /* diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h index bdcb189..2007e51 100644 --- a/xen/include/asm-arm/gic.h +++ b/xen/include/asm-arm/gic.h @@ -230,6 +230,9 @@ extern void gic_route_irq_to_xen(struct irq_desc *desc, const cpumask_t *cpu_mas extern int gic_route_irq_to_guest(struct domain *, unsigned int virq, struct irq_desc *desc, unsigned int priority); +extern int gic_route_lpi_to_guest(struct domain *d, + struct irq_desc *desc, + unsigned int priority); /* Remove an IRQ passthrough to a guest */ int gic_remove_irq_from_guest(struct domain *d, unsigned int virq, @@ -286,9 +289,10 @@ extern void send_SGI_allbutself(enum gic_sgi sgi); /* print useful debug info */ extern void gic_dump_info(struct vcpu *v); -/* Number of interrupt lines */ +/* Number of interrupt lines (PPIs + SGIs + SPIs)*/ extern unsigned int gic_number_lines(void); - +/* Check if irq is valid */ +bool_t gic_is_valid_irq(unsigned int irq); /* IRQ translation function for the device tree */ int gic_irq_xlate(const u32 *intspec, unsigned int intsize, unsigned int *out_hwirq, unsigned int *out_type); diff --git a/xen/include/asm-arm/irq.h b/xen/include/asm-arm/irq.h index 323f6c0..7a6fb1c 100644 --- a/xen/include/asm-arm/irq.h +++ b/xen/include/asm-arm/irq.h @@ -49,6 +49,8 @@ bool_t is_assignable_irq(unsigned int irq); void init_IRQ(void); void init_secondary_IRQ(void); +int route_lpi_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); int release_guest_irq(struct domain *d, unsigned int irq); diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h index 4711d3a..5e194b7 100644 --- a/xen/include/asm-arm/vgic.h +++ b/xen/include/asm-arm/vgic.h @@ -305,6 +305,9 @@ extern int vcpu_vgic_init(struct vcpu *v); extern struct vcpu *vgic_get_target_vcpu(struct vcpu *v, unsigned int virq); 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_vcpu_inject_lpi(struct domain *d, unsigned int devid, + unsigned int eventID); +extern void vgic_vcpu_raise_lpi(struct domain *d, struct irq_desc *desc); extern void vgic_clear_pending_irqs(struct vcpu *v); extern struct pending_irq *irq_to_pending(struct vcpu *v, unsigned int irq); extern struct pending_irq *spi_to_pending(struct domain *d, unsigned int irq);