arch, mm: pull out allocation of NODE_DATA to generic code
Architectures that support NUMA duplicate the code that allocates NODE_DATA on the node-local memory with slight variations in reporting of the addresses where the memory was allocated. Use x86 version as the basis for the generic alloc_node_data() function and call this function in architecture specific numa initialization. Round up node data size to SMP_CACHE_BYTES rather than to PAGE_SIZE like x86 used to do since the bootmem era when allocation granularity was PAGE_SIZE anyway. Link: https://lkml.kernel.org/r/20240807064110.1003856-10-rppt@kernel.org Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org> Acked-by: David Hildenbrand <david@redhat.com> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Tested-by: Zi Yan <ziy@nvidia.com> # for x86_64 and arm64 Tested-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> [arm64 + CXL via QEMU] Acked-by: Dan Williams <dan.j.williams@intel.com> Cc: Alexander Gordeev <agordeev@linux.ibm.com> Cc: Andreas Larsson <andreas@gaisler.com> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Borislav Petkov <bp@alien8.de> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Christophe Leroy <christophe.leroy@csgroup.eu> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: Davidlohr Bueso <dave@stgolabs.net> Cc: David S. Miller <davem@davemloft.net> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Heiko Carstens <hca@linux.ibm.com> Cc: Huacai Chen <chenhuacai@kernel.org> Cc: Ingo Molnar <mingo@redhat.com> Cc: Jiaxun Yang <jiaxun.yang@flygoat.com> Cc: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Michael Ellerman <mpe@ellerman.id.au> Cc: Palmer Dabbelt <palmer@dabbelt.com> Cc: Rafael J. Wysocki <rafael@kernel.org> Cc: Rob Herring (Arm) <robh@kernel.org> Cc: Samuel Holland <samuel.holland@sifive.com> Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Vasily Gorbik <gor@linux.ibm.com> Cc: Will Deacon <will@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
ec164cf1dd
commit
3515863d9f
@ -187,24 +187,6 @@ int __init numa_add_memblk(int nid, u64 start, u64 end)
|
|||||||
return numa_add_memblk_to(nid, start, end, &numa_meminfo);
|
return numa_add_memblk_to(nid, start, end, &numa_meminfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __init alloc_node_data(int nid)
|
|
||||||
{
|
|
||||||
void *nd;
|
|
||||||
unsigned long nd_pa;
|
|
||||||
size_t nd_sz = roundup(sizeof(pg_data_t), PAGE_SIZE);
|
|
||||||
|
|
||||||
nd_pa = memblock_phys_alloc_try_nid(nd_sz, SMP_CACHE_BYTES, nid);
|
|
||||||
if (!nd_pa) {
|
|
||||||
pr_err("Cannot find %zu Byte for node_data (initial node: %d)\n", nd_sz, nid);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nd = __va(nd_pa);
|
|
||||||
|
|
||||||
node_data[nid] = nd;
|
|
||||||
memset(nd, 0, sizeof(pg_data_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __init node_mem_init(unsigned int node)
|
static void __init node_mem_init(unsigned int node)
|
||||||
{
|
{
|
||||||
unsigned long start_pfn, end_pfn;
|
unsigned long start_pfn, end_pfn;
|
||||||
|
@ -81,12 +81,8 @@ static void __init init_topology_matrix(void)
|
|||||||
|
|
||||||
static void __init node_mem_init(unsigned int node)
|
static void __init node_mem_init(unsigned int node)
|
||||||
{
|
{
|
||||||
struct pglist_data *nd;
|
|
||||||
unsigned long node_addrspace_offset;
|
unsigned long node_addrspace_offset;
|
||||||
unsigned long start_pfn, end_pfn;
|
unsigned long start_pfn, end_pfn;
|
||||||
unsigned long nd_pa;
|
|
||||||
int tnid;
|
|
||||||
const size_t nd_size = roundup(sizeof(pg_data_t), SMP_CACHE_BYTES);
|
|
||||||
|
|
||||||
node_addrspace_offset = nid_to_addrbase(node);
|
node_addrspace_offset = nid_to_addrbase(node);
|
||||||
pr_info("Node%d's addrspace_offset is 0x%lx\n",
|
pr_info("Node%d's addrspace_offset is 0x%lx\n",
|
||||||
@ -96,16 +92,8 @@ static void __init node_mem_init(unsigned int node)
|
|||||||
pr_info("Node%d: start_pfn=0x%lx, end_pfn=0x%lx\n",
|
pr_info("Node%d: start_pfn=0x%lx, end_pfn=0x%lx\n",
|
||||||
node, start_pfn, end_pfn);
|
node, start_pfn, end_pfn);
|
||||||
|
|
||||||
nd_pa = memblock_phys_alloc_try_nid(nd_size, SMP_CACHE_BYTES, node);
|
alloc_node_data(node);
|
||||||
if (!nd_pa)
|
|
||||||
panic("Cannot allocate %zu bytes for node %d data\n",
|
|
||||||
nd_size, node);
|
|
||||||
nd = __va(nd_pa);
|
|
||||||
memset(nd, 0, sizeof(struct pglist_data));
|
|
||||||
tnid = early_pfn_to_nid(nd_pa >> PAGE_SHIFT);
|
|
||||||
if (tnid != node)
|
|
||||||
pr_info("NODE_DATA(%d) on node %d\n", node, tnid);
|
|
||||||
node_data[node] = nd;
|
|
||||||
NODE_DATA(node)->node_start_pfn = start_pfn;
|
NODE_DATA(node)->node_start_pfn = start_pfn;
|
||||||
NODE_DATA(node)->node_spanned_pages = end_pfn - start_pfn;
|
NODE_DATA(node)->node_spanned_pages = end_pfn - start_pfn;
|
||||||
|
|
||||||
|
@ -1093,27 +1093,9 @@ void __init dump_numa_cpu_topology(void)
|
|||||||
static void __init setup_node_data(int nid, u64 start_pfn, u64 end_pfn)
|
static void __init setup_node_data(int nid, u64 start_pfn, u64 end_pfn)
|
||||||
{
|
{
|
||||||
u64 spanned_pages = end_pfn - start_pfn;
|
u64 spanned_pages = end_pfn - start_pfn;
|
||||||
const size_t nd_size = roundup(sizeof(pg_data_t), SMP_CACHE_BYTES);
|
|
||||||
u64 nd_pa;
|
|
||||||
void *nd;
|
|
||||||
int tnid;
|
|
||||||
|
|
||||||
nd_pa = memblock_phys_alloc_try_nid(nd_size, SMP_CACHE_BYTES, nid);
|
alloc_node_data(nid);
|
||||||
if (!nd_pa)
|
|
||||||
panic("Cannot allocate %zu bytes for node %d data\n",
|
|
||||||
nd_size, nid);
|
|
||||||
|
|
||||||
nd = __va(nd_pa);
|
|
||||||
|
|
||||||
/* report and initialize */
|
|
||||||
pr_info(" NODE_DATA [mem %#010Lx-%#010Lx]\n",
|
|
||||||
nd_pa, nd_pa + nd_size - 1);
|
|
||||||
tnid = early_pfn_to_nid(nd_pa >> PAGE_SHIFT);
|
|
||||||
if (tnid != nid)
|
|
||||||
pr_info(" NODE_DATA(%d) on node %d\n", nid, tnid);
|
|
||||||
|
|
||||||
node_data[nid] = nd;
|
|
||||||
memset(NODE_DATA(nid), 0, sizeof(pg_data_t));
|
|
||||||
NODE_DATA(nid)->node_id = nid;
|
NODE_DATA(nid)->node_id = nid;
|
||||||
NODE_DATA(nid)->node_start_pfn = start_pfn;
|
NODE_DATA(nid)->node_start_pfn = start_pfn;
|
||||||
NODE_DATA(nid)->node_spanned_pages = spanned_pages;
|
NODE_DATA(nid)->node_spanned_pages = spanned_pages;
|
||||||
|
@ -212,12 +212,7 @@ void __init allocate_pgdat(unsigned int nid)
|
|||||||
get_pfn_range_for_nid(nid, &start_pfn, &end_pfn);
|
get_pfn_range_for_nid(nid, &start_pfn, &end_pfn);
|
||||||
|
|
||||||
#ifdef CONFIG_NUMA
|
#ifdef CONFIG_NUMA
|
||||||
NODE_DATA(nid) = memblock_alloc_try_nid(
|
alloc_node_data(nid);
|
||||||
sizeof(struct pglist_data),
|
|
||||||
SMP_CACHE_BYTES, MEMBLOCK_LOW_LIMIT,
|
|
||||||
MEMBLOCK_ALLOC_ACCESSIBLE, nid);
|
|
||||||
if (!NODE_DATA(nid))
|
|
||||||
panic("Can't allocate pgdat for node %d\n", nid);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NODE_DATA(nid)->node_start_pfn = start_pfn;
|
NODE_DATA(nid)->node_start_pfn = start_pfn;
|
||||||
|
@ -1075,14 +1075,9 @@ static void __init allocate_node_data(int nid)
|
|||||||
{
|
{
|
||||||
struct pglist_data *p;
|
struct pglist_data *p;
|
||||||
unsigned long start_pfn, end_pfn;
|
unsigned long start_pfn, end_pfn;
|
||||||
#ifdef CONFIG_NUMA
|
|
||||||
|
|
||||||
NODE_DATA(nid) = memblock_alloc_node(sizeof(struct pglist_data),
|
#ifdef CONFIG_NUMA
|
||||||
SMP_CACHE_BYTES, nid);
|
alloc_node_data(nid);
|
||||||
if (!NODE_DATA(nid)) {
|
|
||||||
prom_printf("Cannot allocate pglist_data for nid[%d]\n", nid);
|
|
||||||
prom_halt();
|
|
||||||
}
|
|
||||||
|
|
||||||
NODE_DATA(nid)->node_id = nid;
|
NODE_DATA(nid)->node_id = nid;
|
||||||
#endif
|
#endif
|
||||||
|
@ -191,39 +191,6 @@ int __init numa_add_memblk(int nid, u64 start, u64 end)
|
|||||||
return numa_add_memblk_to(nid, start, end, &numa_meminfo);
|
return numa_add_memblk_to(nid, start, end, &numa_meminfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate NODE_DATA for a node on the local memory */
|
|
||||||
static void __init alloc_node_data(int nid)
|
|
||||||
{
|
|
||||||
const size_t nd_size = roundup(sizeof(pg_data_t), PAGE_SIZE);
|
|
||||||
u64 nd_pa;
|
|
||||||
void *nd;
|
|
||||||
int tnid;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Allocate node data. Try node-local memory and then any node.
|
|
||||||
* Never allocate in DMA zone.
|
|
||||||
*/
|
|
||||||
nd_pa = memblock_phys_alloc_try_nid(nd_size, SMP_CACHE_BYTES, nid);
|
|
||||||
if (!nd_pa) {
|
|
||||||
pr_err("Cannot find %zu bytes in any node (initial node: %d)\n",
|
|
||||||
nd_size, nid);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
nd = __va(nd_pa);
|
|
||||||
|
|
||||||
/* report and initialize */
|
|
||||||
printk(KERN_INFO "NODE_DATA(%d) allocated [mem %#010Lx-%#010Lx]\n", nid,
|
|
||||||
nd_pa, nd_pa + nd_size - 1);
|
|
||||||
tnid = early_pfn_to_nid(nd_pa >> PAGE_SHIFT);
|
|
||||||
if (tnid != nid)
|
|
||||||
printk(KERN_INFO " NODE_DATA(%d) on node %d\n", nid, tnid);
|
|
||||||
|
|
||||||
node_data[nid] = nd;
|
|
||||||
memset(NODE_DATA(nid), 0, sizeof(pg_data_t));
|
|
||||||
|
|
||||||
node_set_online(nid);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* numa_cleanup_meminfo - Cleanup a numa_meminfo
|
* numa_cleanup_meminfo - Cleanup a numa_meminfo
|
||||||
* @mi: numa_meminfo to clean up
|
* @mi: numa_meminfo to clean up
|
||||||
@ -571,6 +538,7 @@ static int __init numa_register_memblks(struct numa_meminfo *mi)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
alloc_node_data(nid);
|
alloc_node_data(nid);
|
||||||
|
node_set_online(nid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dump memblock with node info and return. */
|
/* Dump memblock with node info and return. */
|
||||||
|
@ -216,30 +216,11 @@ int __init numa_add_memblk(int nid, u64 start, u64 end)
|
|||||||
*/
|
*/
|
||||||
static void __init setup_node_data(int nid, u64 start_pfn, u64 end_pfn)
|
static void __init setup_node_data(int nid, u64 start_pfn, u64 end_pfn)
|
||||||
{
|
{
|
||||||
const size_t nd_size = roundup(sizeof(pg_data_t), SMP_CACHE_BYTES);
|
|
||||||
u64 nd_pa;
|
|
||||||
void *nd;
|
|
||||||
int tnid;
|
|
||||||
|
|
||||||
if (start_pfn >= end_pfn)
|
if (start_pfn >= end_pfn)
|
||||||
pr_info("Initmem setup node %d [<memory-less node>]\n", nid);
|
pr_info("Initmem setup node %d [<memory-less node>]\n", nid);
|
||||||
|
|
||||||
nd_pa = memblock_phys_alloc_try_nid(nd_size, SMP_CACHE_BYTES, nid);
|
alloc_node_data(nid);
|
||||||
if (!nd_pa)
|
|
||||||
panic("Cannot allocate %zu bytes for node %d data\n",
|
|
||||||
nd_size, nid);
|
|
||||||
|
|
||||||
nd = __va(nd_pa);
|
|
||||||
|
|
||||||
/* report and initialize */
|
|
||||||
pr_info("NODE_DATA [mem %#010Lx-%#010Lx]\n",
|
|
||||||
nd_pa, nd_pa + nd_size - 1);
|
|
||||||
tnid = early_pfn_to_nid(nd_pa >> PAGE_SHIFT);
|
|
||||||
if (tnid != nid)
|
|
||||||
pr_info("NODE_DATA(%d) on node %d\n", nid, tnid);
|
|
||||||
|
|
||||||
node_data[nid] = nd;
|
|
||||||
memset(NODE_DATA(nid), 0, sizeof(pg_data_t));
|
|
||||||
NODE_DATA(nid)->node_id = nid;
|
NODE_DATA(nid)->node_id = nid;
|
||||||
NODE_DATA(nid)->node_start_pfn = start_pfn;
|
NODE_DATA(nid)->node_start_pfn = start_pfn;
|
||||||
NODE_DATA(nid)->node_spanned_pages = end_pfn - start_pfn;
|
NODE_DATA(nid)->node_spanned_pages = end_pfn - start_pfn;
|
||||||
|
@ -33,6 +33,7 @@ static inline bool numa_valid_node(int nid)
|
|||||||
extern struct pglist_data *node_data[];
|
extern struct pglist_data *node_data[];
|
||||||
#define NODE_DATA(nid) (node_data[nid])
|
#define NODE_DATA(nid) (node_data[nid])
|
||||||
|
|
||||||
|
void __init alloc_node_data(int nid);
|
||||||
void __init alloc_offline_node_data(int nid);
|
void __init alloc_offline_node_data(int nid);
|
||||||
|
|
||||||
/* Generic implementation available */
|
/* Generic implementation available */
|
||||||
|
27
mm/numa.c
27
mm/numa.c
@ -1,11 +1,38 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <linux/memblock.h>
|
||||||
#include <linux/printk.h>
|
#include <linux/printk.h>
|
||||||
#include <linux/numa.h>
|
#include <linux/numa.h>
|
||||||
|
|
||||||
struct pglist_data *node_data[MAX_NUMNODES];
|
struct pglist_data *node_data[MAX_NUMNODES];
|
||||||
EXPORT_SYMBOL(node_data);
|
EXPORT_SYMBOL(node_data);
|
||||||
|
|
||||||
|
/* Allocate NODE_DATA for a node on the local memory */
|
||||||
|
void __init alloc_node_data(int nid)
|
||||||
|
{
|
||||||
|
const size_t nd_size = roundup(sizeof(pg_data_t), SMP_CACHE_BYTES);
|
||||||
|
u64 nd_pa;
|
||||||
|
void *nd;
|
||||||
|
int tnid;
|
||||||
|
|
||||||
|
/* Allocate node data. Try node-local memory and then any node. */
|
||||||
|
nd_pa = memblock_phys_alloc_try_nid(nd_size, SMP_CACHE_BYTES, nid);
|
||||||
|
if (!nd_pa)
|
||||||
|
panic("Cannot allocate %zu bytes for node %d data\n",
|
||||||
|
nd_size, nid);
|
||||||
|
nd = __va(nd_pa);
|
||||||
|
|
||||||
|
/* report and initialize */
|
||||||
|
pr_info("NODE_DATA(%d) allocated [mem %#010Lx-%#010Lx]\n", nid,
|
||||||
|
nd_pa, nd_pa + nd_size - 1);
|
||||||
|
tnid = early_pfn_to_nid(nd_pa >> PAGE_SHIFT);
|
||||||
|
if (tnid != nid)
|
||||||
|
pr_info(" NODE_DATA(%d) on node %d\n", nid, tnid);
|
||||||
|
|
||||||
|
node_data[nid] = nd;
|
||||||
|
memset(NODE_DATA(nid), 0, sizeof(pg_data_t));
|
||||||
|
}
|
||||||
|
|
||||||
void __init alloc_offline_node_data(int nid)
|
void __init alloc_offline_node_data(int nid)
|
||||||
{
|
{
|
||||||
pg_data_t *pgdat;
|
pg_data_t *pgdat;
|
||||||
|
Loading…
Reference in New Issue
Block a user