From patchwork Wed Apr 27 18:07:15 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Daney X-Patchwork-Id: 8961141 Return-Path: X-Original-To: patchwork-linux-acpi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id B19BBBF29F for ; Wed, 27 Apr 2016 18:10:10 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 96C8320259 for ; Wed, 27 Apr 2016 18:10:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 2866920138 for ; Wed, 27 Apr 2016 18:10:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753877AbcD0SJF (ORCPT ); Wed, 27 Apr 2016 14:09:05 -0400 Received: from mail-pa0-f66.google.com ([209.85.220.66]:35890 "EHLO mail-pa0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753637AbcD0SHs (ORCPT ); Wed, 27 Apr 2016 14:07:48 -0400 Received: by mail-pa0-f66.google.com with SMTP id i5so5678995pag.3; Wed, 27 Apr 2016 11:07:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=mWV5Mm9f8s2kbcGEZeGzQnDIylxlGZVR9K95RSg4kpU=; b=vt132qN0YE/RjLfeUV+Zhbtki3T7evRS0eg8jfBzTEtLrOdeXfORgNWeIYrNZv68WM u9HD4zNxDfRrF7MmgDmux2457Moe4RuOfCyHoTsbsN+nKaE+FHzMuJRmLt3zcpFT0bhm Dv3HW7QA7GNUxVT/kgZIHcHtZAk+FKOqF78JWQOpxjkR2kdAedVLETINgfMjaZ69l9R6 RhYDzznjS3YZ8yhCFpBS28zfJMOvGtz0lUg6JUAip/j1AVzd4y7Us0hWW3WvO1m1KQUY oBRSMAuokL4pxHEDYszcjbDupYNC8PujVhtnk5tBlnQO5auEsPyMZvJIfBTidPM4PZNP BV4g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=mWV5Mm9f8s2kbcGEZeGzQnDIylxlGZVR9K95RSg4kpU=; b=nKesMYbsS0mzJZgZgSU+nGFmgAJ59bGrrcJa7qGXBBr70erWSwxyUVmkTiJfd9/I0n HDYBfARiqrbunv2auah6NVUwnQD/iKwhtS6yTKEF19XOKN0paVfUdO+l336t9M0/KdP0 qwZKPOtzOeqaepd1hP2gVsRybecIvny4kNIVhgWUssnp3t+b9S+0iyMBOfAF0CYUuYyH HV4xmTq7MF+XgX8YKi5ufMWPQnuKYA/COGHpiKQttYn/AiecPNN0ZOwztJj0XYmpaWZj VgNqyjeEhD7OSate2V9AmoLEJd0KmR/VepPW9StQHGzcasf5H84wYXWNAPRUsDgAkqwN WxUA== X-Gm-Message-State: AOPr4FXdx9KO2faY+pliF9pEnUfPJyaXrZ5pg6P5UergwU+xdww9cJ3WCusJJshV6JEc8A== X-Received: by 10.66.246.165 with SMTP id xx5mr13988240pac.87.1461780467189; Wed, 27 Apr 2016 11:07:47 -0700 (PDT) Received: from dl.caveonetworks.com ([64.2.3.194]) by smtp.gmail.com with ESMTPSA id ez6sm8497802pab.12.2016.04.27.11.07.35 (version=TLS1 cipher=AES128-SHA bits=128/128); Wed, 27 Apr 2016 11:07:40 -0700 (PDT) Received: from dl.caveonetworks.com (localhost.localdomain [127.0.0.1]) by dl.caveonetworks.com (8.14.5/8.14.5) with ESMTP id u3RI7Y5s027283; Wed, 27 Apr 2016 11:07:34 -0700 Received: (from ddaney@localhost) by dl.caveonetworks.com (8.14.5/8.14.5/Submit) id u3RI7Yv9027282; Wed, 27 Apr 2016 11:07:34 -0700 From: David Daney To: Will Deacon , linux-arm-kernel@lists.infradead.org, Mark Rutland , Catalin Marinas , Tony Luck , Fenghua Yu , Thomas Gleixner , Ingo Molnar , "H. Peter Anvin" , x86@kernel.org, "Rafael J. Wysocki" , Len Brown , Rob Herring , Frank Rowand , Grant Likely , Robert Moore , Lv Zheng , Hanjun Guo , Marc Zyngier , linux-ia64@vger.kernel.org, linux-acpi@vger.kernel.org, devel@acpica.org Cc: linux-kernel@vger.kernel.org, Robert Richter , Ganapatrao Kulkarni , David Daney Subject: [PATCH v6 13/14] arm64, acpi, numa: NUMA support based on SRAT and SLIT Date: Wed, 27 Apr 2016 11:07:15 -0700 Message-Id: <1461780436-27182-14-git-send-email-ddaney.cavm@gmail.com> X-Mailer: git-send-email 1.7.11.7 In-Reply-To: <1461780436-27182-1-git-send-email-ddaney.cavm@gmail.com> References: <1461780436-27182-1-git-send-email-ddaney.cavm@gmail.com> Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Spam-Status: No, score=-7.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, 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: Hanjun Guo Introduce a new file to hold ACPI based NUMA information parsing from SRAT and SLIT. SRAT includes the CPU ACPI ID to Proximity Domain mappings and memory ranges to Proximity Domain mapping. SLIT has the information of inter node distances(relative number for access latency). Signed-off-by: Hanjun Guo Signed-off-by: Ganapatrao Kulkarni [rrichter@cavium.com Reworked for numa v10 series ] Signed-off-by: Robert Richter [david.daney@cavium.com reorderd and combinded with other patches in Hanjun Guo's original set] Signed-off-by: David Daney --- arch/arm64/include/asm/acpi.h | 8 +++ arch/arm64/include/asm/numa.h | 2 + arch/arm64/kernel/Makefile | 1 + arch/arm64/kernel/acpi_numa.c | 149 ++++++++++++++++++++++++++++++++++++++++++ arch/arm64/kernel/smp.c | 2 + arch/arm64/mm/numa.c | 5 +- 6 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/kernel/acpi_numa.c diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h index aee323b..4b13ecd 100644 --- a/arch/arm64/include/asm/acpi.h +++ b/arch/arm64/include/asm/acpi.h @@ -113,4 +113,12 @@ static inline const char *acpi_get_enable_method(int cpu) pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr); #endif +#ifdef CONFIG_ACPI_NUMA +int arm64_acpi_numa_init(void); +int acpi_numa_get_nid(unsigned int cpu, u64 hwid); +#else +static inline int arm64_acpi_numa_init(void) { return -ENOSYS; } +static inline int acpi_numa_get_nid(unsigned int cpu, u64 hwid) { return NUMA_NO_NODE; } +#endif /* CONFIG_ACPI_NUMA */ + #endif /*_ASM_ACPI_H*/ diff --git a/arch/arm64/include/asm/numa.h b/arch/arm64/include/asm/numa.h index e9b4f29..600887e 100644 --- a/arch/arm64/include/asm/numa.h +++ b/arch/arm64/include/asm/numa.h @@ -5,6 +5,8 @@ #ifdef CONFIG_NUMA +#define NR_NODE_MEMBLKS (MAX_NUMNODES * 2) + /* currently, arm64 implements flat NUMA topology */ #define parent_node(node) (node) diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 3793003..69569c6 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -42,6 +42,7 @@ arm64-obj-$(CONFIG_EFI) += efi.o efi-entry.stub.o arm64-obj-$(CONFIG_PCI) += pci.o arm64-obj-$(CONFIG_ARMV8_DEPRECATED) += armv8_deprecated.o arm64-obj-$(CONFIG_ACPI) += acpi.o +arm64-obj-$(CONFIG_ACPI_NUMA) += acpi_numa.o arm64-obj-$(CONFIG_ARM64_ACPI_PARKING_PROTOCOL) += acpi_parking_protocol.o arm64-obj-$(CONFIG_PARAVIRT) += paravirt.o arm64-obj-$(CONFIG_RANDOMIZE_BASE) += kaslr.o diff --git a/arch/arm64/kernel/acpi_numa.c b/arch/arm64/kernel/acpi_numa.c new file mode 100644 index 0000000..94a6b35 --- /dev/null +++ b/arch/arm64/kernel/acpi_numa.c @@ -0,0 +1,149 @@ +/* + * ACPI 5.1 based NUMA setup for ARM64 + * Lots of code was borrowed from arch/x86/mm/srat.c + * + * Copyright 2004 Andi Kleen, SuSE Labs. + * Copyright (C) 2013-2016, Linaro Ltd. + * Author: Hanjun Guo + * + * Reads the ACPI SRAT table to figure out what memory belongs to which CPUs. + * + * Called from acpi_numa_init while reading the SRAT and SLIT tables. + * Assumes all memory regions belonging to a single proximity domain + * are in one chunk. Holes between them will be included in the node. + */ + +#define pr_fmt(fmt) "ACPI: NUMA: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static int cpus_in_srat; + +struct __node_cpu_hwid { + u32 node_id; /* logical node containing this CPU */ + u64 cpu_hwid; /* MPIDR for this CPU */ +}; + +static struct __node_cpu_hwid early_node_cpu_hwid[NR_CPUS] = { +[0 ... NR_CPUS - 1] = {NUMA_NO_NODE, PHYS_CPUID_INVALID} }; + +int acpi_numa_get_nid(unsigned int cpu, u64 hwid) +{ + int i; + + for (i = 0; i < cpus_in_srat; i++) { + if (hwid == early_node_cpu_hwid[i].cpu_hwid) + return early_node_cpu_hwid[i].node_id; + } + + return NUMA_NO_NODE; +} + +static int __init get_mpidr_in_madt(int acpi_id, u64 *mpidr) +{ + unsigned long madt_end, entry; + struct acpi_table_madt *madt; + acpi_size tbl_size; + + if (ACPI_FAILURE(acpi_get_table_with_size(ACPI_SIG_MADT, 0, + (struct acpi_table_header **)&madt, &tbl_size))) + return -ENODEV; + + entry = (unsigned long)madt; + madt_end = entry + madt->header.length; + + /* Parse all entries looking for a match. */ + entry += sizeof(struct acpi_table_madt); + while (entry + sizeof(struct acpi_subtable_header) < madt_end) { + struct acpi_subtable_header *header = + (struct acpi_subtable_header *)entry; + + if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) { + struct acpi_madt_generic_interrupt *gicc = + container_of(header, + struct acpi_madt_generic_interrupt, header); + + if ((gicc->flags & ACPI_MADT_ENABLED) && + (gicc->uid == acpi_id)) { + *mpidr = gicc->arm_mpidr; + early_acpi_os_unmap_memory(madt, tbl_size); + return 0; + } + } + entry += header->length; + } + + early_acpi_os_unmap_memory(madt, tbl_size); + return -ENODEV; +} + +/* Callback for Proximity Domain -> ACPI processor UID mapping */ +void __init acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa) +{ + int pxm, node; + u64 mpidr; + + if (srat_disabled()) + return; + + if (pa->header.length < sizeof(struct acpi_srat_gicc_affinity)) { + pr_err("SRAT: Invalid SRAT header length: %d\n", + pa->header.length); + bad_srat(); + return; + } + + if (!(pa->flags & ACPI_SRAT_GICC_ENABLED)) + return; + + if (cpus_in_srat >= NR_CPUS) { + pr_warn_once("SRAT: cpu_to_node_map[%d] is too small, may not be able to use all cpus\n", + NR_CPUS); + return; + } + + pxm = pa->proximity_domain; + node = acpi_map_pxm_to_node(pxm); + + if (node == NUMA_NO_NODE || node >= MAX_NUMNODES) { + pr_err("SRAT: Too many proximity domains %d\n", pxm); + bad_srat(); + return; + } + + if (get_mpidr_in_madt(pa->acpi_processor_uid, &mpidr)) { + pr_err("SRAT: PXM %d with ACPI ID %d has no valid MPIDR in MADT\n", + pxm, pa->acpi_processor_uid); + bad_srat(); + return; + } + + early_node_cpu_hwid[cpus_in_srat].node_id = node; + early_node_cpu_hwid[cpus_in_srat].cpu_hwid = mpidr; + node_set(node, numa_nodes_parsed); + cpus_in_srat++; + pr_info("SRAT: PXM %d -> MPIDR 0x%Lx -> Node %d\n", + pxm, mpidr, node); +} + +int __init arm64_acpi_numa_init(void) +{ + int ret; + + ret = acpi_numa_init(); + if (ret) + return ret; + + return srat_disabled() ? -EINVAL : 0; +} diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index fef2e73..fe85940 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -562,6 +562,8 @@ acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor) */ acpi_set_mailbox_entry(cpu_count, processor); + early_map_cpu_to_node(cpu_count, acpi_numa_get_nid(cpu_count, hwid)); + cpu_count++; } diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c index 1def1de..c7fe3ec 100644 --- a/arch/arm64/mm/numa.c +++ b/arch/arm64/mm/numa.c @@ -17,6 +17,7 @@ * along with this program. If not, see . */ +#include #include #include #include @@ -391,7 +392,9 @@ static int __init dummy_numa_init(void) void __init arm64_numa_init(void) { if (!numa_off) { - if (!numa_init(of_numa_init)) + if (!acpi_disabled && !numa_init(arm64_acpi_numa_init)) + return; + if (acpi_disabled && !numa_init(of_numa_init)) return; }