From patchwork Mon Apr 3 20:28:06 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 9660565 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 AA57B60364 for ; Mon, 3 Apr 2017 20:29:06 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9C33F28403 for ; Mon, 3 Apr 2017 20:29:06 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 911332841C; Mon, 3 Apr 2017 20:29:06 +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 F010528418 for ; Mon, 3 Apr 2017 20:29:05 +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 1cv8Yh-0004ui-49; Mon, 03 Apr 2017 20:26:39 +0000 Received: from mail6.bemta6.messagelabs.com ([193.109.254.103]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cv8Yg-0004tp-12 for xen-devel@lists.xenproject.org; Mon, 03 Apr 2017 20:26:38 +0000 Received: from [193.109.254.147] by server-8.bemta-6.messagelabs.com id F6/1D-03648-DFFA2E85; Mon, 03 Apr 2017 20:26:37 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrGLMWRWlGSWpSXmKPExsVysyfVTffP+kc RBnN7dCy+b5nM5MDocfjDFZYAxijWzLyk/IoE1oyrR34zFjxyqti6cQlrA+NHwy5GLg4hgc2M EtOunmWEcJYzSlxa9J+ti5GTg01AV2LHzdfMILaIQKjE0wXfwWxmASWJ/WevMYLYwgJ+Ei9Wr mQCsVkEVCXurOsEs3kFrCT+PL8EVi8hICfRcP4+mM0pYC3R+vEoWK8QUM2Eh01MExi5FzAyrG JUL04tKkst0rXQSyrKTM8oyU3MzNE1NDDTy00tLk5MT81JTCrWS87P3cQI9C8DEOxgnH3Z/xC jJAeTkiiv+qRHEUJ8SfkplRmJxRnxRaU5qcWHGGU4OJQkeI+tA8oJFqWmp1akZeYAAw0mLcHB oyTCuxkkzVtckJhbnJkOkTrFqCglzssPDE8hAZBERmkeXBssuC8xykoJ8zICHSLEU5BalJtZg ir/ilGcg1FJmPcGyHiezLwSuOmvgBYzAS1+cuchyOKSRISUVAOjbcJ2q3MGdzmF1thunl1Yz9 igNjvuj8uyf4t/fZTRvcnkpz//wPz+kOCl53/vs/Z++3KBdPWuUytKVp7vZ87n7lY7dsE+gLP y7gv/kOZ4C/epUd/mf///5XJc9Kae+cI5/leb+qPXG+7f2HXs6KE15Rs66s4s5e/s+mbDHrBg fd9cra0JLT/dlViKMxINtZiLihMBqeWYbmkCAAA= X-Env-Sender: andre.przywara@arm.com X-Msg-Ref: server-13.tower-27.messagelabs.com!1491251194!85888546!2 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.2.3; banners=-,-,- X-VirusChecked: Checked Received: (qmail 24061 invoked from network); 3 Apr 2017 20:26:36 -0000 Received: from foss.arm.com (HELO foss.arm.com) (217.140.101.70) by server-13.tower-27.messagelabs.com with SMTP; 3 Apr 2017 20:26:36 -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 31D351991; Mon, 3 Apr 2017 13:26:36 -0700 (PDT) Received: from e104803-lin.lan (unknown [10.1.207.46]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 6E7B93F4FF; Mon, 3 Apr 2017 13:26:35 -0700 (PDT) From: Andre Przywara To: Julien Grall , Stefano Stabellini Date: Mon, 3 Apr 2017 21:28:06 +0100 Message-Id: <20170403202829.7278-5-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 04/27] ARM: GICv3 ITS: allocate device and collection 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 Each ITS maps a pair of a DeviceID (for instance derived from a PCI b/d/f triplet) and an EventID (the MSI payload or interrupt ID) to a pair of LPI number and collection ID, which points to the target CPU. This mapping is stored in the device and collection tables, which software has to provide for the ITS to use. Allocate the required memory and hand it to the ITS. The maximum number of devices can be limited to a compile-time variable. Signed-off-by: Andre Przywara Reviewed-by: Stefano Stabellini --- xen/arch/arm/gic-v3-its.c | 132 +++++++++++++++++++++++++++++++++++++++ xen/include/asm-arm/gic_v3_its.h | 32 ++++++++++ 2 files changed, 164 insertions(+) diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c index 58c6ac0..00a1f7b 100644 --- a/xen/arch/arm/gic-v3-its.c +++ b/xen/arch/arm/gic-v3-its.c @@ -35,6 +35,105 @@ bool gicv3_its_host_has_its(void) return !list_empty(&host_its_list); } +#define BASER_ATTR_MASK \ + ((0x3UL << GITS_BASER_SHAREABILITY_SHIFT) | \ + (0x7UL << GITS_BASER_OUTER_CACHEABILITY_SHIFT) | \ + (0x7UL << GITS_BASER_INNER_CACHEABILITY_SHIFT)) +#define BASER_RO_MASK (GENMASK_ULL(58, 56) | GENMASK_ULL(52, 48)) + +/* Check that the physical address can be encoded in the PROPBASER register. */ +static bool check_baser_phys_addr(void *vaddr, unsigned int page_bits) +{ + paddr_t paddr = virt_to_maddr(vaddr); + + return (!(paddr & ~GENMASK_ULL(page_bits < 16 ? 47 : 51, page_bits))); +} + +static uint64_t encode_baser_phys_addr(paddr_t addr, unsigned int page_bits) +{ + uint64_t ret = addr & GENMASK_ULL(47, page_bits); + + if ( page_bits < 16 ) + return ret; + + /* For 64K pages address bits 51-48 are encoded in bits 15-12. */ + return ret | ((addr & GENMASK_ULL(51, 48)) >> (48 - 12)); +} + +/* The ITS BASE registers work with page sizes of 4K, 16K or 64K. */ +#define BASER_PAGE_BITS(sz) ((sz) * 2 + 12) + +static int its_map_baser(void __iomem *basereg, uint64_t regc, + unsigned int nr_items) +{ + uint64_t attr, reg; + unsigned int entry_size = GITS_BASER_ENTRY_SIZE(regc); + unsigned int pagesz = 2; /* try 64K pages first, then go down. */ + unsigned int table_size; + void *buffer; + + attr = GIC_BASER_InnerShareable << GITS_BASER_SHAREABILITY_SHIFT; + attr |= GIC_BASER_CACHE_SameAsInner << GITS_BASER_OUTER_CACHEABILITY_SHIFT; + attr |= GIC_BASER_CACHE_RaWaWb << GITS_BASER_INNER_CACHEABILITY_SHIFT; + + /* + * Setup the BASE register with the attributes that we like. Then read + * it back and see what sticks (page size, cacheability and shareability + * attributes), retrying if necessary. + */ +retry: + table_size = ROUNDUP(nr_items * entry_size, BIT(BASER_PAGE_BITS(pagesz))); + /* The BASE registers support at most 256 pages. */ + table_size = min(table_size, 256U << BASER_PAGE_BITS(pagesz)); + + buffer = _xzalloc(table_size, BIT(BASER_PAGE_BITS(pagesz))); + if ( !buffer ) + return -ENOMEM; + + if ( !check_baser_phys_addr(buffer, BASER_PAGE_BITS(pagesz)) ) + { + xfree(buffer); + return -ERANGE; + } + + reg = attr; + reg |= (pagesz << GITS_BASER_PAGE_SIZE_SHIFT); + reg |= (table_size >> BASER_PAGE_BITS(pagesz)) - 1; + reg |= regc & BASER_RO_MASK; + reg |= GITS_VALID_BIT; + reg |= encode_baser_phys_addr(virt_to_maddr(buffer), + BASER_PAGE_BITS(pagesz)); + + writeq_relaxed(reg, basereg); + regc = readq_relaxed(basereg); + + /* The host didn't like our attributes, just use what it returned. */ + if ( (regc & BASER_ATTR_MASK) != attr ) + { + /* If we can't map it shareable, drop cacheability as well. */ + if ( (regc & GITS_BASER_SHAREABILITY_MASK) == GIC_BASER_NonShareable ) + { + regc &= ~GITS_BASER_INNER_CACHEABILITY_MASK; + writeq_relaxed(regc, basereg); + } + attr = regc & BASER_ATTR_MASK; + } + if ( (regc & GITS_BASER_INNER_CACHEABILITY_MASK) <= GIC_BASER_CACHE_nC ) + clean_and_invalidate_dcache_va_range(buffer, table_size); + + /* If the host accepted our page size, we are done. */ + if ( ((regc >> GITS_BASER_PAGE_SIZE_SHIFT) & 0x3UL) == pagesz ) + return 0; + + xfree(buffer); + + if ( pagesz-- > 0 ) + goto retry; + + /* None of the page sizes was accepted, give up */ + return -EINVAL; +} + /* Allow a user to limit the number of devices. */ static unsigned int max_its_device_bits = 32; integer_param("max_its_device_bits", max_its_device_bits); @@ -42,6 +141,7 @@ integer_param("max_its_device_bits", max_its_device_bits); static int gicv3_its_init_single_its(struct host_its *hw_its) { uint64_t reg; + int i, ret; hw_its->its_base = ioremap_nocache(hw_its->addr, hw_its->size); if ( !hw_its->its_base ) @@ -53,6 +153,38 @@ static int gicv3_its_init_single_its(struct host_its *hw_its) hw_its->evid_bits = GITS_TYPER_EVENT_ID_BITS(reg); hw_its->itte_size = GITS_TYPER_ITT_SIZE(reg); + for ( i = 0; i < GITS_BASER_NR_REGS; i++ ) + { + void __iomem *basereg = hw_its->its_base + GITS_BASER0 + i * 8; + unsigned int type; + + reg = readq_relaxed(basereg); + type = (reg & GITS_BASER_TYPE_MASK) >> GITS_BASER_TYPE_SHIFT; + switch ( type ) + { + case GITS_BASER_TYPE_NONE: + continue; + case GITS_BASER_TYPE_DEVICE: + ret = its_map_baser(basereg, reg, BIT(hw_its->devid_bits)); + if ( ret ) + return ret; + break; + case GITS_BASER_TYPE_COLLECTION: + ret = its_map_baser(basereg, reg, num_possible_cpus()); + if ( ret ) + return ret; + break; + /* In case this is a GICv4, provide a (dummy) vPE table as well. */ + case GITS_BASER_TYPE_VCPU: + ret = its_map_baser(basereg, reg, 1); + if ( ret ) + return ret; + break; + default: + continue; + } + } + return 0; } diff --git a/xen/include/asm-arm/gic_v3_its.h b/xen/include/asm-arm/gic_v3_its.h index 7c5a2fa..c7d8766 100644 --- a/xen/include/asm-arm/gic_v3_its.h +++ b/xen/include/asm-arm/gic_v3_its.h @@ -37,6 +37,11 @@ #define GITS_BASER7 0x138 /* Register bits */ +#define GITS_VALID_BIT BIT_ULL(63) + +#define GITS_CTLR_QUIESCENT BIT(31) +#define GITS_CTLR_ENABLE BIT(0) + #define GITS_TYPER_DEVIDS_SHIFT 13 #define GITS_TYPER_DEVIDS_MASK (0x1fUL << GITS_TYPER_DEVIDS_SHIFT) #define GITS_TYPER_DEVICE_ID_BITS(r) (((r & GITS_TYPER_DEVIDS_MASK) >> \ @@ -52,6 +57,33 @@ #define GITS_TYPER_ITT_SIZE(r) ((((r) & GITS_TYPER_ITT_SIZE_MASK) >> \ GITS_TYPER_ITT_SIZE_SHIFT) + 1) +#define GITS_IIDR_VALUE 0x34c + +#define GITS_BASER_INDIRECT BIT_ULL(62) +#define GITS_BASER_INNER_CACHEABILITY_SHIFT 59 +#define GITS_BASER_TYPE_SHIFT 56 +#define GITS_BASER_TYPE_MASK (7ULL << GITS_BASER_TYPE_SHIFT) +#define GITS_BASER_OUTER_CACHEABILITY_SHIFT 53 +#define GITS_BASER_TYPE_NONE 0UL +#define GITS_BASER_TYPE_DEVICE 1UL +#define GITS_BASER_TYPE_VCPU 2UL +#define GITS_BASER_TYPE_CPU 3UL +#define GITS_BASER_TYPE_COLLECTION 4UL +#define GITS_BASER_TYPE_RESERVED5 5UL +#define GITS_BASER_TYPE_RESERVED6 6UL +#define GITS_BASER_TYPE_RESERVED7 7UL +#define GITS_BASER_ENTRY_SIZE_SHIFT 48 +#define GITS_BASER_ENTRY_SIZE(reg) \ + (((reg >> GITS_BASER_ENTRY_SIZE_SHIFT) & 0x1f) + 1) +#define GITS_BASER_SHAREABILITY_SHIFT 10 +#define GITS_BASER_PAGE_SIZE_SHIFT 8 +#define GITS_BASER_RO_MASK (GITS_BASER_TYPE_MASK | \ + (31UL << GITS_BASER_ENTRY_SIZE_SHIFT) |\ + GITS_BASER_INDIRECT) +#define GITS_BASER_SHAREABILITY_MASK (0x3ULL << GITS_BASER_SHAREABILITY_SHIFT) +#define GITS_BASER_OUTER_CACHEABILITY_MASK (0x7ULL << GITS_BASER_OUTER_CACHEABILITY_SHIFT) +#define GITS_BASER_INNER_CACHEABILITY_MASK (0x7ULL << GITS_BASER_INNER_CACHEABILITY_SHIFT) + #include /* data structure for each hardware ITS */