From patchwork Mon Jan 30 18:31:28 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 9545893 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 15B1360415 for ; Mon, 30 Jan 2017 18:33:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0C2BD27F7F for ; Mon, 30 Jan 2017 18:33:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 01085281C3; Mon, 30 Jan 2017 18:33:15 +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 30CBD27F7F for ; Mon, 30 Jan 2017 18:33:15 +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 1cYGiw-0007by-Hi; Mon, 30 Jan 2017 18:30:42 +0000 Received: from mail6.bemta6.messagelabs.com ([193.109.254.103]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cYGiv-0007Zz-I3 for xen-devel@lists.xenproject.org; Mon, 30 Jan 2017 18:30:41 +0000 Received: from [85.158.143.35] by server-2.bemta-6.messagelabs.com id 7B/C8-22326-0568F885; Mon, 30 Jan 2017 18:30:40 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrKLMWRWlGSWpSXmKPExsVysyfVTTegrT/ C4NZiVovvWyYzOTB6HP5whSWAMYo1My8pvyKBNeP/30UsBZuyK9qmtrE0MDYHdTFycQgJbGaU uPd3JSOEs5xRYt/CH0AOJwebgK7EjpuvmUFsEYFQiTk/HwHZHBzMAl4SX957g4SFgcz9s3ewg NgsAqoSk9/3gdm8AtYSj861g9kSAnISDefvg43hFLCRmL35NxOILQRU869nOeMERu4FjAyrGN WLU4vKUot0LfSSijLTM0pyEzNzdA0NzPRyU4uLE9NTcxKTivWS83M3MQK9ywAEOxhnX/Y/xCj JwaQkytv3sS9CiC8pP6UyI7E4I76oNCe1+BCjDAeHkgSvVGt/hJBgUWp6akVaZg4wzGDSEhw8 SiK8n1uA0rzFBYm5xZnpEKlTjIpS4rw/QBICIImM0jy4NlhoX2KUlRLmZQQ6RIinILUoN7MEV f4VozgHo5Iw702QKTyZeSVw018BLWYCWuz+qg9kcUkiQkqqgdE057rJe8m9J+vChI/JWC14G2 O11NomZnU3w9rAP7szYxiXzPTJvJD7Mj6Ap4ejLma6wP6Jny7eO7NaRmD+4+W3PoW8V0vmf6j QutLYf4Jr6xKXC+smc2XOkl/zIHXPjC6tGV3sP1Yx3ptVtViLSzjtfOApgck5zuZ/Lp9z+sty SdAhK9Aw4LISS3FGoqEWc1FxIgBMyVCFaAIAAA== X-Env-Sender: andre.przywara@arm.com X-Msg-Ref: server-6.tower-21.messagelabs.com!1485801039!32180705!1 X-Originating-IP: [217.140.101.70] X-SpamReason: No, hits=0.0 required=7.0 tests=UPPERCASE_25_50 X-StarScan-Received: X-StarScan-Version: 9.1.1; banners=-,-,- X-VirusChecked: Checked Received: (qmail 43415 invoked from network); 30 Jan 2017 18:30:39 -0000 Received: from foss.arm.com (HELO foss.arm.com) (217.140.101.70) by server-6.tower-21.messagelabs.com with SMTP; 30 Jan 2017 18:30:39 -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 192A41595; Mon, 30 Jan 2017 10:30:39 -0800 (PST) Received: from e104803-lin.lan (unknown [10.1.207.46]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 36D1D3F24D; Mon, 30 Jan 2017 10:30:38 -0800 (PST) From: Andre Przywara To: Stefano Stabellini , Julien Grall Date: Mon, 30 Jan 2017 18:31:28 +0000 Message-Id: <20170130183153.28566-4-andre.przywara@arm.com> X-Mailer: git-send-email 2.9.0 In-Reply-To: <20170130183153.28566-1-andre.przywara@arm.com> References: <20170130183153.28566-1-andre.przywara@arm.com> Cc: xen-devel@lists.xenproject.org, Vijay Kilari Subject: [Xen-devel] [PATCH 03/28] ARM: GICv3: allocate LPI pending and property table 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 The ARM GICv3 provides a new kind of interrupt called LPIs. The pending bits and the configuration data (priority, enable bits) for those LPIs are stored in tables in normal memory, which software has to provide to the hardware. Allocate the required memory, initialize it and hand it over to each redistributor. The maximum number of LPIs to be used can be adjusted with the command line option "max_lpi_bits", which defaults to a compile time constant exposed in Kconfig. Signed-off-by: Andre Przywara --- xen/arch/arm/Kconfig | 15 +++++ xen/arch/arm/Makefile | 1 + xen/arch/arm/gic-v3-lpi.c | 129 ++++++++++++++++++++++++++++++++++++++ xen/arch/arm/gic-v3.c | 44 +++++++++++++ xen/include/asm-arm/bitops.h | 1 + xen/include/asm-arm/gic.h | 2 + xen/include/asm-arm/gic_v3_defs.h | 52 ++++++++++++++- xen/include/asm-arm/gic_v3_its.h | 22 ++++++- 8 files changed, 264 insertions(+), 2 deletions(-) create mode 100644 xen/arch/arm/gic-v3-lpi.c diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig index bf64c61..71734a1 100644 --- a/xen/arch/arm/Kconfig +++ b/xen/arch/arm/Kconfig @@ -49,6 +49,21 @@ config HAS_ITS bool "GICv3 ITS MSI controller support" depends on HAS_GICV3 +config MAX_PHYS_LPI_BITS + depends on HAS_ITS + int "Maximum bits for GICv3 host LPIs (14-32)" + range 14 32 + default "20" + help + Specifies the maximum number of LPIs (in bits) Xen should take + care of. The host ITS may provide support for a very large number + of supported LPIs, for all of which we may not want to allocate + memory, so this number here allows to limit this. + Xen itself does not know how many LPIs domains will ever need + beforehand. + This can be overriden on the command line with the max_lpi_bits + parameter. + endmenu menu "ARM errata workaround via the alternative framework" diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile index 5f4ff23..4ccf2eb 100644 --- a/xen/arch/arm/Makefile +++ b/xen/arch/arm/Makefile @@ -19,6 +19,7 @@ obj-y += gic.o obj-y += gic-v2.o obj-$(CONFIG_HAS_GICV3) += gic-v3.o obj-$(CONFIG_HAS_ITS) += gic-v3-its.o +obj-$(CONFIG_HAS_ITS) += gic-v3-lpi.o obj-y += guestcopy.o obj-y += hvm.o obj-y += io.o diff --git a/xen/arch/arm/gic-v3-lpi.c b/xen/arch/arm/gic-v3-lpi.c new file mode 100644 index 0000000..e2fc901 --- /dev/null +++ b/xen/arch/arm/gic-v3-lpi.c @@ -0,0 +1,129 @@ +/* + * xen/arch/arm/gic-v3-lpi.c + * + * ARM GICv3 Locality-specific Peripheral Interrupts (LPI) support + * + * Copyright (C) 2016,2017 - ARM Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Global state */ +static struct { + uint8_t *lpi_property; + unsigned int host_lpi_bits; +} lpi_data; + +/* Pending table for each redistributor */ +static DEFINE_PER_CPU(void *, pending_table); + +#define MAX_PHYS_LPIS (BIT_ULL(lpi_data.host_lpi_bits) - LPI_OFFSET) + +uint64_t gicv3_lpi_allocate_pendtable(void) +{ + uint64_t reg; + void *pendtable; + + reg = GIC_BASER_CACHE_RaWaWb << GICR_PENDBASER_INNER_CACHEABILITY_SHIFT; + reg |= GIC_BASER_CACHE_SameAsInner << GICR_PENDBASER_OUTER_CACHEABILITY_SHIFT; + reg |= GIC_BASER_InnerShareable << GICR_PENDBASER_SHAREABILITY_SHIFT; + + if ( !this_cpu(pending_table) ) + { + /* + * The pending table holds one bit per LPI and even covers bits for + * interrupt IDs below 8192, so we allocate the full range. + * The GICv3 imposes a 64KB alignment requirement. + */ + pendtable = _xmalloc(BIT_ULL(lpi_data.host_lpi_bits) / 8, SZ_64K); + if ( !pendtable ) + return 0; + + memset(pendtable, 0, BIT_ULL(lpi_data.host_lpi_bits) / 8); + __flush_dcache_area(pendtable, BIT_ULL(lpi_data.host_lpi_bits) / 8); + + this_cpu(pending_table) = pendtable; + } + else + { + pendtable = this_cpu(pending_table); + } + + reg |= GICR_PENDBASER_PTZ; + + ASSERT(!(virt_to_maddr(pendtable) & ~GENMASK(51, 16))); + reg |= virt_to_maddr(pendtable); + + return reg; +} + +uint64_t gicv3_lpi_get_proptable(void) +{ + uint64_t reg; + + reg = GIC_BASER_CACHE_RaWaWb << GICR_PENDBASER_INNER_CACHEABILITY_SHIFT; + reg |= GIC_BASER_CACHE_SameAsInner << GICR_PENDBASER_OUTER_CACHEABILITY_SHIFT; + reg |= GIC_BASER_InnerShareable << GICR_PENDBASER_SHAREABILITY_SHIFT; + + /* + * The property table is shared across all redistributors, so allocate + * this only once, but return the same value on subsequent calls. + */ + if ( !lpi_data.lpi_property ) + { + /* The property table holds one byte per LPI. */ + void *table = alloc_xenheap_pages(lpi_data.host_lpi_bits - PAGE_SHIFT, + 0); + + if ( !table ) + return 0; + + memset(table, GIC_PRI_IRQ | LPI_PROP_RES1, MAX_PHYS_LPIS); + __flush_dcache_area(table, MAX_PHYS_LPIS); + lpi_data.lpi_property = table; + } + + reg |= ((lpi_data.host_lpi_bits - 1) << 0); + + ASSERT(!(virt_to_maddr(lpi_data.lpi_property) & ~GENMASK(51, 12))); + reg |= virt_to_maddr(lpi_data.lpi_property); + + return reg; +} + +static unsigned int max_lpi_bits = CONFIG_MAX_PHYS_LPI_BITS; +integer_param("max_lpi_bits", max_lpi_bits); + +int gicv3_lpi_init_host_lpis(unsigned int hw_lpi_bits) +{ + lpi_data.host_lpi_bits = min(hw_lpi_bits, max_lpi_bits); + + printk("GICv3: using at most %lld LPIs on the host.\n", MAX_PHYS_LPIS); + + return 0; +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c index 838dd11..fcb86c8 100644 --- a/xen/arch/arm/gic-v3.c +++ b/xen/arch/arm/gic-v3.c @@ -546,6 +546,9 @@ static void __init gicv3_dist_init(void) type = readl_relaxed(GICD + GICD_TYPER); nr_lines = 32 * ((type & GICD_TYPE_LINES) + 1); + if ( type & GICD_TYPE_LPIS ) + gicv3_lpi_init_host_lpis(((type >> GICD_TYPE_ID_BITS_SHIFT) & 0x1f) + 1); + printk("GICv3: %d lines, (IID %8.8x).\n", nr_lines, readl_relaxed(GICD + GICD_IIDR)); @@ -616,6 +619,33 @@ static int gicv3_enable_redist(void) return 0; } +static int gicv3_rdist_init_lpis(void __iomem * rdist_base) +{ + uint32_t reg; + uint64_t table_reg; + + /* We don't support LPIs without an ITS. */ + if ( list_empty(&host_its_list) ) + return -ENODEV; + + /* Make sure LPIs are disabled before setting up the tables. */ + reg = readl_relaxed(rdist_base + GICR_CTLR); + if ( reg & GICR_CTLR_ENABLE_LPIS ) + return -EBUSY; + + table_reg = gicv3_lpi_allocate_pendtable(); + if ( !table_reg ) + return -ENOMEM; + writeq_relaxed(table_reg, rdist_base + GICR_PENDBASER); + + table_reg = gicv3_lpi_get_proptable(); + if ( !table_reg ) + return -ENOMEM; + writeq_relaxed(table_reg, rdist_base + GICR_PROPBASER); + + return 0; +} + static int __init gicv3_populate_rdist(void) { int i; @@ -658,6 +688,20 @@ static int __init gicv3_populate_rdist(void) if ( (typer >> 32) == aff ) { this_cpu(rbase) = ptr; + + if ( typer & GICR_TYPER_PLPIS ) + { + int ret; + + ret = gicv3_rdist_init_lpis(ptr); + if ( ret && ret != -ENODEV ) + { + printk("GICv3: CPU%d: Cannot initialize LPIs: %d\n", + smp_processor_id(), ret); + break; + } + } + printk("GICv3: CPU%d: Found redistributor in region %d @%p\n", smp_processor_id(), i, ptr); return 0; diff --git a/xen/include/asm-arm/bitops.h b/xen/include/asm-arm/bitops.h index bda8898..1cbfb9e 100644 --- a/xen/include/asm-arm/bitops.h +++ b/xen/include/asm-arm/bitops.h @@ -24,6 +24,7 @@ #define BIT(nr) (1UL << (nr)) #define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_WORD)) #define BIT_WORD(nr) ((nr) / BITS_PER_WORD) +#define BIT_ULL(nr) (1ULL << (nr)) #define BITS_PER_BYTE 8 #define ADDR (*(volatile int *) addr) diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h index 836a103..12bd155 100644 --- a/xen/include/asm-arm/gic.h +++ b/xen/include/asm-arm/gic.h @@ -220,6 +220,8 @@ enum gic_version { GIC_V3, }; +#define LPI_OFFSET 8192 + extern enum gic_version gic_hw_version(void); /* Program the IRQ type into the GIC */ diff --git a/xen/include/asm-arm/gic_v3_defs.h b/xen/include/asm-arm/gic_v3_defs.h index 6bd25a5..b307322 100644 --- a/xen/include/asm-arm/gic_v3_defs.h +++ b/xen/include/asm-arm/gic_v3_defs.h @@ -44,7 +44,8 @@ #define GICC_SRE_EL2_ENEL1 (1UL << 3) /* Additional bits in GICD_TYPER defined by GICv3 */ -#define GICD_TYPE_ID_BITS_SHIFT 19 +#define GICD_TYPE_ID_BITS_SHIFT 19 +#define GICD_TYPE_LPIS (1U << 17) #define GICD_CTLR_RWP (1UL << 31) #define GICD_CTLR_ARE_NS (1U << 4) @@ -95,12 +96,61 @@ #define GICR_IGRPMODR0 (0x0D00) #define GICR_NSACR (0x0E00) +#define GICR_CTLR_ENABLE_LPIS (1U << 0) + #define GICR_TYPER_PLPIS (1U << 0) #define GICR_TYPER_VLPIS (1U << 1) #define GICR_TYPER_LAST (1U << 4) +/* For specifying the inner cacheability type only */ +#define GIC_BASER_CACHE_nCnB 0ULL +/* For specifying the outer cacheability type only */ +#define GIC_BASER_CACHE_SameAsInner 0ULL +#define GIC_BASER_CACHE_nC 1ULL +#define GIC_BASER_CACHE_RaWt 2ULL +#define GIC_BASER_CACHE_RaWb 3ULL +#define GIC_BASER_CACHE_WaWt 4ULL +#define GIC_BASER_CACHE_WaWb 5ULL +#define GIC_BASER_CACHE_RaWaWt 6ULL +#define GIC_BASER_CACHE_RaWaWb 7ULL +#define GIC_BASER_CACHE_MASK 7ULL + +#define GIC_BASER_NonShareable 0ULL +#define GIC_BASER_InnerShareable 1ULL +#define GIC_BASER_OuterShareable 2ULL + +#define GICR_PROPBASER_SHAREABILITY_SHIFT 10 +#define GICR_PROPBASER_INNER_CACHEABILITY_SHIFT 7 +#define GICR_PROPBASER_OUTER_CACHEABILITY_SHIFT 56 +#define GICR_PROPBASER_SHAREABILITY_MASK \ + (3UL << GICR_PROPBASER_SHAREABILITY_SHIFT) +#define GICR_PROPBASER_INNER_CACHEABILITY_MASK \ + (7UL << GICR_PROPBASER_INNER_CACHEABILITY_SHIFT) +#define GICR_PROPBASER_OUTER_CACHEABILITY_MASK \ + (7UL << GICR_PROPBASER_OUTER_CACHEABILITY_SHIFT) +#define GICR_PROPBASER_RES0_MASK \ + (GENMASK(63, 59) | GENMASK(55, 52) | GENMASK(6, 5)) + +#define GICR_PENDBASER_SHAREABILITY_SHIFT 10 +#define GICR_PENDBASER_INNER_CACHEABILITY_SHIFT 7 +#define GICR_PENDBASER_OUTER_CACHEABILITY_SHIFT 56 +#define GICR_PENDBASER_SHAREABILITY_MASK \ + (3UL << GICR_PENDBASER_SHAREABILITY_SHIFT) +#define GICR_PENDBASER_INNER_CACHEABILITY_MASK \ + (7UL << GICR_PENDBASER_INNER_CACHEABILITY_SHIFT) +#define GICR_PENDBASER_OUTER_CACHEABILITY_MASK \ + (7UL << GICR_PENDBASER_OUTER_CACHEABILITY_SHIFT) +#define GICR_PENDBASER_PTZ BIT(62) +#define GICR_PENDBASER_RES0_MASK \ + (BIT(63) | GENMASK(61, 59) | GENMASK(55, 52) | \ + GENMASK(15, 12) | GENMASK(6, 0)) + #define DEFAULT_PMR_VALUE 0xff +#define LPI_PROP_PRIO_MASK 0xfc +#define LPI_PROP_RES1 (1 << 1) +#define LPI_PROP_ENABLED (1 << 0) + #define GICH_VMCR_EOI (1 << 9) #define GICH_VMCR_VENG1 (1 << 1) diff --git a/xen/include/asm-arm/gic_v3_its.h b/xen/include/asm-arm/gic_v3_its.h index 2f5c51c..a66b6be 100644 --- a/xen/include/asm-arm/gic_v3_its.h +++ b/xen/include/asm-arm/gic_v3_its.h @@ -36,12 +36,32 @@ extern struct list_head host_its_list; /* Parse the host DT and pick up all host ITSes. */ void gicv3_its_dt_init(const struct dt_device_node *node); +/* Allocate and initialize tables for each host redistributor. + * Returns the respective {PROP,PEND}BASER register value. + */ +uint64_t gicv3_lpi_get_proptable(void); +uint64_t gicv3_lpi_allocate_pendtable(void); + +/* Initialize the host structures for LPIs. */ +int gicv3_lpi_init_host_lpis(unsigned int nr_lpis); + #else static inline void gicv3_its_dt_init(const struct dt_device_node *node) { } - +static inline uint64_t gicv3_lpi_get_proptable(void) +{ + return 0; +} +static inline uint64_t gicv3_lpi_allocate_pendtable(void) +{ + return 0; +} +static inline int gicv3_lpi_init_host_lpis(unsigned int nr_lpis) +{ + return 0; +} #endif /* CONFIG_HAS_ITS */ #endif /* __ASSEMBLY__ */