Skip to content

Commit 1a2db30

Browse files
Ganapatrao Kulkarniwildea01
Ganapatrao Kulkarni
authored andcommitted
arm64, numa: Add NUMA support for arm64 platforms.
Attempt to get the memory and CPU NUMA node via of_numa. If that fails, default the dummy NUMA node and map all memory and CPUs to node 0. Tested-by: Shannon Zhao <shannon.zhao@linaro.org> Reviewed-by: Robert Richter <rrichter@cavium.com> Signed-off-by: Ganapatrao Kulkarni <gkulkarni@caviumnetworks.com> Signed-off-by: David Daney <david.daney@cavium.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
1 parent 3194ac6 commit 1a2db30

File tree

10 files changed

+538
-5
lines changed

10 files changed

+538
-5
lines changed

arch/arm64/Kconfig

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ config ARM64
7676
select HAVE_HW_BREAKPOINT if PERF_EVENTS
7777
select HAVE_IRQ_TIME_ACCOUNTING
7878
select HAVE_MEMBLOCK
79+
select HAVE_MEMBLOCK_NODE_MAP if NUMA
7980
select HAVE_PATA_PLATFORM
8081
select HAVE_PERF_EVENTS
8182
select HAVE_PERF_REGS
@@ -98,6 +99,7 @@ config ARM64
9899
select SYSCTL_EXCEPTION_TRACE
99100
select HAVE_CONTEXT_TRACKING
100101
select HAVE_ARM_SMCCC
102+
select OF_NUMA if NUMA && OF
101103
help
102104
ARM 64-bit (AArch64) Linux support.
103105

@@ -546,6 +548,30 @@ config HOTPLUG_CPU
546548
Say Y here to experiment with turning CPUs off and on. CPUs
547549
can be controlled through /sys/devices/system/cpu.
548550

551+
# Common NUMA Features
552+
config NUMA
553+
bool "Numa Memory Allocation and Scheduler Support"
554+
depends on SMP
555+
help
556+
Enable NUMA (Non Uniform Memory Access) support.
557+
558+
The kernel will try to allocate memory used by a CPU on the
559+
local memory of the CPU and add some more
560+
NUMA awareness to the kernel.
561+
562+
config NODES_SHIFT
563+
int "Maximum NUMA Nodes (as a power of 2)"
564+
range 1 10
565+
default "2"
566+
depends on NEED_MULTIPLE_NODES
567+
help
568+
Specify the maximum number of NUMA Nodes available on the target
569+
system. Increases memory reserved to accommodate various tables.
570+
571+
config USE_PERCPU_NUMA_NODE_ID
572+
def_bool y
573+
depends on NUMA
574+
549575
source kernel/Kconfig.preempt
550576
source kernel/Kconfig.hz
551577

arch/arm64/include/asm/mmzone.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#ifndef __ASM_MMZONE_H
2+
#define __ASM_MMZONE_H
3+
4+
#ifdef CONFIG_NUMA
5+
6+
#include <asm/numa.h>
7+
8+
extern struct pglist_data *node_data[];
9+
#define NODE_DATA(nid) (node_data[(nid)])
10+
11+
#endif /* CONFIG_NUMA */
12+
#endif /* __ASM_MMZONE_H */

arch/arm64/include/asm/numa.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#ifndef __ASM_NUMA_H
2+
#define __ASM_NUMA_H
3+
4+
#include <asm/topology.h>
5+
6+
#ifdef CONFIG_NUMA
7+
8+
/* currently, arm64 implements flat NUMA topology */
9+
#define parent_node(node) (node)
10+
11+
int __node_distance(int from, int to);
12+
#define node_distance(a, b) __node_distance(a, b)
13+
14+
extern nodemask_t numa_nodes_parsed __initdata;
15+
16+
/* Mappings between node number and cpus on that node. */
17+
extern cpumask_var_t node_to_cpumask_map[MAX_NUMNODES];
18+
void numa_clear_node(unsigned int cpu);
19+
20+
#ifdef CONFIG_DEBUG_PER_CPU_MAPS
21+
const struct cpumask *cpumask_of_node(int node);
22+
#else
23+
/* Returns a pointer to the cpumask of CPUs on Node 'node'. */
24+
static inline const struct cpumask *cpumask_of_node(int node)
25+
{
26+
return node_to_cpumask_map[node];
27+
}
28+
#endif
29+
30+
void __init arm64_numa_init(void);
31+
int __init numa_add_memblk(int nodeid, u64 start, u64 end);
32+
void __init numa_set_distance(int from, int to, int distance);
33+
void __init numa_free_distance(void);
34+
void __init early_map_cpu_to_node(unsigned int cpu, int nid);
35+
void numa_store_cpu_info(unsigned int cpu);
36+
37+
#else /* CONFIG_NUMA */
38+
39+
static inline void numa_store_cpu_info(unsigned int cpu) { }
40+
static inline void arm64_numa_init(void) { }
41+
static inline void early_map_cpu_to_node(unsigned int cpu, int nid) { }
42+
43+
#endif /* CONFIG_NUMA */
44+
45+
#endif /* __ASM_NUMA_H */

arch/arm64/include/asm/topology.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,16 @@ void init_cpu_topology(void);
2222
void store_cpu_topology(unsigned int cpuid);
2323
const struct cpumask *cpu_coregroup_mask(int cpu);
2424

25+
#ifdef CONFIG_NUMA
26+
27+
struct pci_bus;
28+
int pcibus_to_node(struct pci_bus *bus);
29+
#define cpumask_of_pcibus(bus) (pcibus_to_node(bus) == -1 ? \
30+
cpu_all_mask : \
31+
cpumask_of_node(pcibus_to_node(bus)))
32+
33+
#endif /* CONFIG_NUMA */
34+
2535
#include <asm-generic/topology.h>
2636

2737
#endif /* _ASM_ARM_TOPOLOGY_H */

arch/arm64/kernel/pci.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,16 @@ int raw_pci_write(unsigned int domain, unsigned int bus,
7474
return -ENXIO;
7575
}
7676

77+
#ifdef CONFIG_NUMA
78+
79+
int pcibus_to_node(struct pci_bus *bus)
80+
{
81+
return dev_to_node(&bus->dev);
82+
}
83+
EXPORT_SYMBOL(pcibus_to_node);
84+
85+
#endif
86+
7787
#ifdef CONFIG_ACPI
7888
/* Root bridge scanning */
7989
struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)

arch/arm64/kernel/setup.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#include <asm/cpufeature.h>
5454
#include <asm/cpu_ops.h>
5555
#include <asm/kasan.h>
56+
#include <asm/numa.h>
5657
#include <asm/sections.h>
5758
#include <asm/setup.h>
5859
#include <asm/smp_plat.h>
@@ -319,6 +320,9 @@ static int __init topology_init(void)
319320
{
320321
int i;
321322

323+
for_each_online_node(i)
324+
register_one_node(i);
325+
322326
for_each_possible_cpu(i) {
323327
struct cpu *cpu = &per_cpu(cpu_data.cpu, i);
324328
cpu->hotpluggable = 1;

arch/arm64/kernel/smp.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include <asm/cputype.h>
4646
#include <asm/cpu_ops.h>
4747
#include <asm/mmu_context.h>
48+
#include <asm/numa.h>
4849
#include <asm/pgtable.h>
4950
#include <asm/pgalloc.h>
5051
#include <asm/processor.h>
@@ -203,6 +204,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
203204
static void smp_store_cpu_info(unsigned int cpuid)
204205
{
205206
store_cpu_topology(cpuid);
207+
numa_store_cpu_info(cpuid);
206208
}
207209

208210
/*
@@ -633,6 +635,8 @@ static void __init of_parse_and_init_cpus(void)
633635

634636
pr_debug("cpu logical map 0x%llx\n", hwid);
635637
cpu_logical_map(cpu_count) = hwid;
638+
639+
early_map_cpu_to_node(cpu_count, of_node_to_nid(dn));
636640
next:
637641
cpu_count++;
638642
}

arch/arm64/mm/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ obj-y := dma-mapping.o extable.o fault.o init.o \
44
context.o proc.o pageattr.o
55
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
66
obj-$(CONFIG_ARM64_PTDUMP) += dump.o
7+
obj-$(CONFIG_NUMA) += numa.o
78

89
obj-$(CONFIG_KASAN) += kasan_init.o
910
KASAN_SANITIZE_kasan_init.o := n

arch/arm64/mm/init.c

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include <asm/kasan.h>
4141
#include <asm/kernel-pgtable.h>
4242
#include <asm/memory.h>
43+
#include <asm/numa.h>
4344
#include <asm/sections.h>
4445
#include <asm/setup.h>
4546
#include <asm/sizes.h>
@@ -86,6 +87,21 @@ static phys_addr_t __init max_zone_dma_phys(void)
8687
return min(offset + (1ULL << 32), memblock_end_of_DRAM());
8788
}
8889

90+
#ifdef CONFIG_NUMA
91+
92+
static void __init zone_sizes_init(unsigned long min, unsigned long max)
93+
{
94+
unsigned long max_zone_pfns[MAX_NR_ZONES] = {0};
95+
96+
if (IS_ENABLED(CONFIG_ZONE_DMA))
97+
max_zone_pfns[ZONE_DMA] = PFN_DOWN(max_zone_dma_phys());
98+
max_zone_pfns[ZONE_NORMAL] = max;
99+
100+
free_area_init_nodes(max_zone_pfns);
101+
}
102+
103+
#else
104+
89105
static void __init zone_sizes_init(unsigned long min, unsigned long max)
90106
{
91107
struct memblock_region *reg;
@@ -126,6 +142,8 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
126142
free_area_init_node(0, zone_size, min, zhole_size);
127143
}
128144

145+
#endif /* CONFIG_NUMA */
146+
129147
#ifdef CONFIG_HAVE_ARCH_PFN_VALID
130148
int pfn_valid(unsigned long pfn)
131149
{
@@ -142,10 +160,15 @@ static void __init arm64_memory_present(void)
142160
static void __init arm64_memory_present(void)
143161
{
144162
struct memblock_region *reg;
163+
int nid = 0;
145164

146-
for_each_memblock(memory, reg)
147-
memory_present(0, memblock_region_memory_base_pfn(reg),
148-
memblock_region_memory_end_pfn(reg));
165+
for_each_memblock(memory, reg) {
166+
#ifdef CONFIG_NUMA
167+
nid = reg->nid;
168+
#endif
169+
memory_present(nid, memblock_region_memory_base_pfn(reg),
170+
memblock_region_memory_end_pfn(reg));
171+
}
149172
}
150173
#endif
151174

@@ -278,7 +301,6 @@ void __init arm64_memblock_init(void)
278301
dma_contiguous_reserve(arm64_dma_phys_limit);
279302

280303
memblock_allow_resize();
281-
memblock_dump_all();
282304
}
283305

284306
void __init bootmem_init(void)
@@ -290,6 +312,9 @@ void __init bootmem_init(void)
290312

291313
early_memtest(min << PAGE_SHIFT, max << PAGE_SHIFT);
292314

315+
max_pfn = max_low_pfn = max;
316+
317+
arm64_numa_init();
293318
/*
294319
* Sparsemem tries to allocate bootmem in memory_present(), so must be
295320
* done after the fixed reservations.
@@ -300,7 +325,7 @@ void __init bootmem_init(void)
300325
zone_sizes_init(min, max);
301326

302327
high_memory = __va((max << PAGE_SHIFT) - 1) + 1;
303-
max_pfn = max_low_pfn = max;
328+
memblock_dump_all();
304329
}
305330

306331
#ifndef CONFIG_SPARSEMEM_VMEMMAP

0 commit comments

Comments
 (0)