From patchwork Fri Aug 24 23:05:59 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shuah X-Patchwork-Id: 10575977 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 39C6113B8 for ; Fri, 24 Aug 2018 23:06:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 27D142C4C1 for ; Fri, 24 Aug 2018 23:06:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1B9B92CBA8; Fri, 24 Aug 2018 23:06:28 +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=-2.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 957412C4C1 for ; Fri, 24 Aug 2018 23:06:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: References:List-Owner; bh=SsgV9b6pfMxfrrbjhfgDTputlHDjhWH2Ag8x8aO8Cio=; b=Z+r O2tGfgZjzPXCtu6cbccx7UpMu010+iXWxbnKfDHYuvFQ0GPMvowaEUpPy8/d8eLG5ATmTzgqgPHKb J/ZeLidyE4rf1fbRT06WUDjsw7ny7u0rvQTZzsLkUrmSJlkD/MAwJyhdrg30WVVFTtihhq5WunTpk RZhKvFoiO9klfmZlkKxNTzzu7g4gRdkhPwjhIpPiXC5fC+ZNtA/Bn4tOvd0NJUcprORX6qfo4tfrC Za0nv9LpV0jUOsBU1Q13pbWLppnI06O/2q12FCGylMfobWbGg2XhlZGWfPScltamNsENf5JmxV1t4 Jok3qLEEA5gsh6NOc6irv+pibijD4mA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1ftL9u-0003Wj-NP; Fri, 24 Aug 2018 23:06:26 +0000 Received: from mailout.easymail.ca ([64.68.200.34]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1ftL9r-0003UE-MN for linux-arm-kernel@lists.infradead.org; Fri, 24 Aug 2018 23:06:25 +0000 Received: from localhost (localhost [127.0.0.1]) by mailout.easymail.ca (Postfix) with ESMTP id 7EFABC1022; Fri, 24 Aug 2018 23:06:11 +0000 (UTC) Received: from mailout.easymail.ca ([127.0.0.1]) by localhost (emo01-pco.easydns.vpn [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id pSgbcUFEc4A8; Fri, 24 Aug 2018 23:06:11 +0000 (UTC) Received: from localhost.localdomain (c-24-9-64-241.hsd1.co.comcast.net [24.9.64.241]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mailout.easymail.ca (Postfix) with ESMTPSA id 58AD2C0869; Fri, 24 Aug 2018 23:06:00 +0000 (UTC) From: "Shuah Khan (Samsung OSG)" To: catalin.marinas@arm.com, will.deacon@arm.com, sudeep.holla@arm.com, ganapatrao.kulkarni@cavium.com Subject: [PATCH] arm64: add NUMA emulation support Date: Fri, 24 Aug 2018 17:05:59 -0600 Message-Id: <20180824230559.32336-1-shuah@kernel.org> X-Mailer: git-send-email 2.17.1 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180824_160623_851977_1126B47D X-CRM114-Status: GOOD ( 20.97 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: "Shuah Khan \(Samsung OSG\)" , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Add NUMA emulation support to emulate NUMA on non-NUMA platforms. A new CONFIG_NUMA_EMU option enables NUMA emulation and a new kernel command line option "numa=fake=N" allows users to specify the configuration for emulation. When NUMA emulation is enabled, a flat (non-NUMA) machine will be split into virtual NUMA nodes when booted with "numa=fake=N", where N is the number of nodes, the system RAM will be split into N equal chunks and assigned to each node. Emulated nodes are bounded by MAX_NUMNODES and the number of memory block count to avoid splitting memory blocks across NUMA nodes. If NUMA emulation init fails, it will fall back to dummy NUMA init. This is tested on Raspberry Pi3b+ with ltp NUMA test suite, numactl, and numastat tools. In addition, tested in conjunction with cpuset cgroup to verify cpuset.cpus and cpuset.mems assignments. Signed-off-by: Shuah Khan (Samsung OSG) --- arch/arm64/Kconfig | 9 +++ arch/arm64/include/asm/numa.h | 8 +++ arch/arm64/mm/Makefile | 1 + arch/arm64/mm/numa.c | 4 ++ arch/arm64/mm/numa_emu.c | 109 ++++++++++++++++++++++++++++++++++ 5 files changed, 131 insertions(+) create mode 100644 arch/arm64/mm/numa_emu.c diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 29e75b47becd..6e74d9995d24 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -740,6 +740,15 @@ config NUMA local memory of the CPU and add some more NUMA awareness to the kernel. +config NUMA_EMU + bool "NUMA emulation" + depends on NUMA + help + Enable NUMA emulation. A flat machine will be split into virtual + nodes when booted with "numa=fake=N", where N is the number of + nodes, the system RAM will be split into N equal chunks, and + assigned to each node. + config NODES_SHIFT int "Maximum NUMA Nodes (as a power of 2)" range 1 10 diff --git a/arch/arm64/include/asm/numa.h b/arch/arm64/include/asm/numa.h index 626ad01e83bf..16e8cc035872 100644 --- a/arch/arm64/include/asm/numa.h +++ b/arch/arm64/include/asm/numa.h @@ -29,6 +29,14 @@ static inline const struct cpumask *cpumask_of_node(int node) } #endif +#ifdef CONFIG_NUMA_EMU +void arm64_numa_emu_cmdline(char *str); +extern int arm64_numa_emu_init(void); +#else +static inline void arm64_numa_emu_cmdline(char *str) {} +static inline int arm64_numa_emu_init(void) { return -1; } +#endif /* CONFIG_NUMA_EMU */ + void __init arm64_numa_init(void); int __init numa_add_memblk(int nodeid, u64 start, u64 end); void __init numa_set_distance(int from, int to, int distance); diff --git a/arch/arm64/mm/Makefile b/arch/arm64/mm/Makefile index 849c1df3d214..2c8634daeffa 100644 --- a/arch/arm64/mm/Makefile +++ b/arch/arm64/mm/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_ARM64_PTDUMP_CORE) += dump.o obj-$(CONFIG_ARM64_PTDUMP_DEBUGFS) += ptdump_debugfs.o obj-$(CONFIG_NUMA) += numa.o obj-$(CONFIG_DEBUG_VIRTUAL) += physaddr.o +obj-$(CONFIG_NUMA_EMU) += numa_emu.o KASAN_SANITIZE_physaddr.o += n obj-$(CONFIG_KASAN) += kasan_init.o diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c index 146c04ceaa51..9232f18e3992 100644 --- a/arch/arm64/mm/numa.c +++ b/arch/arm64/mm/numa.c @@ -43,6 +43,8 @@ static __init int numa_parse_early_param(char *opt) return -EINVAL; if (!strncmp(opt, "off", 3)) numa_off = true; + if (!strncmp(opt, "fake=", 5)) + arm64_numa_emu_cmdline(opt + 5); return 0; } @@ -460,6 +462,8 @@ void __init arm64_numa_init(void) return; if (acpi_disabled && !numa_init(of_numa_init)) return; + if (!numa_init(arm64_numa_emu_init)) + return; } numa_init(dummy_numa_init); diff --git a/arch/arm64/mm/numa_emu.c b/arch/arm64/mm/numa_emu.c new file mode 100644 index 000000000000..97217adb029e --- /dev/null +++ b/arch/arm64/mm/numa_emu.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * NUMA Emulation for non-NUMA platforms. + */ + +#include +#include +#include +#include +#include + +#include + +static char *emu_cmdline __initdata; + +/* + * arm64_numa_emu_cmdline - parse early NUMA Emulation params. + */ +void __init arm64_numa_emu_cmdline(char *str) +{ + emu_cmdline = str; +} + +/* + * arm64_numa_emu_init - Initialize NUMA Emulation + * + * Used when NUMA Emulation is enabled on a platform without underlying + * NUMA architecture. + */ +int __init arm64_numa_emu_init(void) +{ + u64 node_size; + int node_cnt = 0; + int mblk_cnt = 0; + int node = 0; + struct memblock_region *mblk; + bool split = false; + int ret; + + pr_info("NUMA emulation init begin\n"); + + if (!emu_cmdline) + return -EINVAL; + /* + * Split the system RAM into N equal chunks. + */ + ret = kstrtoint(emu_cmdline, 0, &node_cnt); + if (ret || node_cnt <= 0) + return -EINVAL; + + if (node_cnt > MAX_NUMNODES) + node_cnt = MAX_NUMNODES; + + node_size = PFN_PHYS(max_pfn) / node_cnt; + pr_info("NUMA emu: Node Size = %#018Lx Node = %d\n", + node_size, node_cnt); + + for_each_memblock(memory, mblk) + mblk_cnt++; + + /* + * Size the node count to match the memory block count to avoid + * splitting memory blocks across nodes. If there is only one + * memory block split it. + */ + if (mblk_cnt <= node_cnt) { + pr_info("NUMA emu: Nodes (%d) >= Memblocks (%d)\n", + node_cnt, mblk_cnt); + if (mblk_cnt == 1) { + split = true; + pr_info("NUMA emu: Splitting single Memory Block\n"); + } else { + node_cnt = mblk_cnt; + pr_info("NUMA emu: Adjust Nodes = Memory Blocks\n"); + } + } + + for_each_memblock(memory, mblk) { + + if (split) { + for (node = 0; node < node_cnt; node++) { + u64 start, end; + + start = mblk->base + node * node_size; + end = start + node_size; + pr_info("Adding an emulation node %d for [mem %#018Lx-%#018Lx]\n", + node, start, end); + ret = numa_add_memblk(node, start, end); + if (!ret) + continue; + pr_err("NUMA emulation init failed\n"); + return ret; + } + break; + } + pr_info("Adding a emulation node %d for [mem %#018Lx-%#018Lx]\n", + node, mblk->base, mblk->base + mblk->size); + ret = numa_add_memblk(node, mblk->base, + mblk->base + mblk->size); + if (!ret) + continue; + pr_err("NUMA emulation init failed\n"); + return ret; + } + pr_info("NUMA: added %d emulation nodes of %#018Lx size each\n", + node_cnt, node_size); + + return 0; +}