Skip to contentSkip to conversation

x86-64, NUMA: bring sanity to NUMA configuration

PATCH New Tejun Heo 5 participants 77 messages Feb 12, 2011 – Feb 16, 2011

Subsystems (3)
lore
Share & tools
lore

Tejun Heo

author
#0 lore raw

PATCH 1/1 x86-64, NUMA: bring sanity to NUMA configuration

Hello,

Currently, x86-64 NUMA configuration is unnecessarily complicated with srat_64, amdtopology_64, dummy and emulation all doing about the same things in slightly different ways. This makes the code difficult to comprehend, maintain and extend.

The worst offender is the NUMA emulation which maps and reverse maps things in quite chaotic ways. For example, CPU node remapping is done by finding out the node the CPU is mapped to, taking the start address and looking up the containing physical node, and then again looking for emulated nodes which fall in the physical node. Another interesting example is node distance remapping whem the system is using amdtopology - it generates pseudo ACPI PXM mapping.

This is the first of two patchset series. This one cleans up x86-64 NUMA configuration so that specific implementations - srat, amdtopology and dummy - only have to supply the information about the actul configuration. All the mangling and massaging are done inside numa_64.c proper using the provided information.

This patchset implements all the infrastructure to make NUMA emulation sane but doesn't actually update NUMA emulation. It will be done by the next patchset. As it still retains old code and glues to keep them working, LOC is increased by 60 lines. After the second patchset, the net LOC change will be -123 lines.

Once the x86-64 update is settled, x86-32 will be moved over to share the new infrastructure.

This patchset is on top of the current tip/x86/numa[1] and contains the following 26 patches.

Tested on an opteron NUMA machine which can do both ACPI and AMD configs. All NUMA configs, emulation, !NUMA and UP work as expected.

0001-x86-64-NUMA-Make-dummy-node-initialization-path-simi.patch 0002-x86-64-NUMA-Simplify-hotplug-node-handling-in-acpi_n.patch 0003-x86-64-NUMA-Drop-start-last_pfn-from-initmem_init.patch 0004-x86-64-NUMA-Unify-acpi-amd-_-numa_init-scan_nodes-ar.patch 0005-x86-64-NUMA-Wrap-acpi_numa_init-so-that-failure-can-.patch 0006-x86-64-NUMA-Move-_numa_init-invocations-into-initmem.patch 0007-x86-64-NUMA-Restructure-initmem_init.patch 0008-x86-64-NUMA-Use-common-cpu-mem-_nodes_parsed.patch 0009-x86-64-NUMA-Remove-local-variable-found-from-amd_num.patch 0010-x86-64-NUMA-Move-apicid-to-numa-mapping-initializati.patch 0011-x86-64-NUMA-Use-common-numa_nodes.patch 0012-x86-64-NUMA-Kill-acpi-amd-_get_nodes.patch 0013-x86-64-NUMA-Factor-out-memblk-handling-into-numa_-ad.patch 0014-x86-64-NUMA-Unify-use-of-memblk-in-all-init-methods.patch 0015-x86-64-NUMA-Unify-the-rest-of-memblk-registration.patch 0016-x86-64-NUMA-Kill-acpi-amd-dummy-_scan_nodes.patch 0017-x86-64-NUMA-Remove-NULL-nodeids-handling-from-comput.patch 0018-x86-64-NUMA-Introduce-struct-numa_meminfo.patch 0019-x86-64-NUMA-Separate-out-numa_cleanup_meminfo.patch 0020-x86-64-NUMA-make-numa_cleanup_meminfo-prettier.patch 0021-x86-64-NUMA-consolidate-and-improve-memblk-sanity-ch.patch 0022-x86-64-NUMA-Add-common-find_node_by_addr.patch 0023-x86-64-NUMA-kill-numa_nodes.patch 0024-x86-64-NUMA-Rename-cpu_nodes_parsed-to-numa_nodes_pa.patch 0025-x86-64-NUMA-Kill-mem_nodes_parsed.patch 0026-x86-64-NUMA-Implement-generic-node-distance-handling.patch

The patchset is also available in the following git branch.

git://git.kernel.org/pub/scm/linux/kernel/git/tj/misc.git x86_64-numa-unify

Diffstat follows.

 arch/x86/include/asm/acpi.h       |    6 
 arch/x86/include/asm/amd_nb.h     |    4 
 arch/x86/include/asm/numa_64.h    |   11 
 arch/x86/include/asm/page_types.h |    3 
 arch/x86/include/asm/topology.h   |    2 
 arch/x86/kernel/setup.c           |   16 -
 arch/x86/mm/amdtopology_64.c      |  117 ++------
 arch/x86/mm/init_64.c             |    5 
 arch/x86/mm/numa_64.c             |  507 ++++++++++++++++++++++++++++++++------
 arch/x86/mm/srat_64.c             |  290 +--------------------
 drivers/acpi/numa.c               |    9 
 11 files changed, 515 insertions(+), 455 deletions(-)

Thanks.

--
tejun

[1] eff9073790e1286aa12bf1c65814d3e0132b12e1 (x86: Rename incorrectly named parameter of numa_cpu_node())

author
#1 lore raw

PATCH 1/26 x86-64, NUMA: Make dummy node initialization path similar to non-dummy ones

Dummy node initialization in initmem_init() didn't initialize apicid to node mapping and set cpu to node mapping directly by caling numa_set_node(), which is different from non-dummy init paths.

Update it such that they behave similarly. Initialize apicid to node mapping and call numa_init_array(). The actual cpu to node mapping is handled by init_cpu_to_node() later.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/mm/numa_64.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)
arch/x86/mm/numa_64.c +3 -2
index f548fbf..ea5dd48 100644
@@ -623,10 +623,11 @@ void __init initmem_init(unsigned long start_pfn, unsigned long last_pfn,
 	memnodemap[0] = 0;
 	node_set_online(0);
 	node_set(0, node_possible_map);
-	for (i = 0; i < nr_cpu_ids; i++)
-		numa_set_node(i, 0);
+	for (i = 0; i < MAX_LOCAL_APIC; i++)
+		set_apicid_to_node(i, NUMA_NO_NODE);
 	memblock_x86_register_active_regions(0, start_pfn, last_pfn);
 	setup_node_bootmem(0, start_pfn << PAGE_SHIFT, last_pfn << PAGE_SHIFT);
+	numa_init_array();
 }
 
 unsigned long __init numa_free_all_bootmem(void)
Signature · 1 line
1.7.1
Acked-by on v1 1/26
#2 lore raw

Re: [PATCH 01/26] x86-64, NUMA: Make dummy node initialization path similar to non-dummy ones

Quoted 28 lines · Tejun Heo

Dummy node initialization in initmem_init() didn't initialize apicid to node mapping and set cpu to node mapping directly by caling numa_set_node(), which is different from non-dummy init paths.

Update it such that they behave similarly. Initialize apicid to node mapping and call numa_init_array(). The actual cpu to node mapping is handled by init_cpu_to_node() later.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/mm/numa_64.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)
arch/x86/mm/numa_64.c +0 -0
index f548fbf..ea5dd48 100644
@@ -623,10 +623,11 @@ void __init initmem_init(unsigned long start_pfn, unsigned long last_pfn,
 	memnodemap[0] = 0;
 	node_set_online(0);
 	node_set(0, node_possible_map);

arch/x86/mm/numa_64.c void __init initmem_init(unsigned long start_pfn, unsigned long last_pfn, · line 633

Quoted 10 lines
arch/x86/mm/numa_64.c +3 -2
-	for (i = 0; i < nr_cpu_ids; i++)
-		numa_set_node(i, 0);
+	for (i = 0; i < MAX_LOCAL_APIC; i++)
+		set_apicid_to_node(i, NUMA_NO_NODE);
 	memblock_x86_register_active_regions(0, start_pfn, last_pfn);
 	setup_node_bootmem(0, start_pfn << PAGE_SHIFT, last_pfn << PAGE_SHIFT);
+	numa_init_array();
 }
 
 unsigned long __init numa_free_all_bootmem(void)
author
#3 lore raw

PATCH 2/26 x86-64, NUMA: Simplify hotplug node handling in acpi_numa_memory_affinity_init()

In reply to Tejun Heo

Hotplug node handling in acpi_numa_memory_affinity_init() was unnecessarily complicated with storing the original nodes[] entry and restoring it afterwards. Simplify it by not modifying the nodes[] entry for hotplug nodes from the beginning.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/mm/srat_64.c |   31 +++++++++++++------------------
 1 files changed, 13 insertions(+), 18 deletions(-)
arch/x86/mm/srat_64.c +13 -18
index 9a97261..e3e0dd3 100644
@@ -251,7 +251,7 @@ update_nodes_add(int node, unsigned long start, unsigned long end)
 void __init
 acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
 {
-	struct bootnode *nd, oldnode;
+	struct bootnode *nd;
 	unsigned long start, end;
 	int node, pxm;
 	int i;
@@ -289,28 +289,23 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
 		bad_srat();
 		return;
 	}
-	nd = &nodes[node];
-	oldnode = *nd;
-	if (!node_test_and_set(node, nodes_parsed)) {
-		nd->start = start;
-		nd->end = end;
-	} else {
-		if (start < nd->start)
-			nd->start = start;
-		if (nd->end < end)
-			nd->end = end;
-	}
 
 	printk(KERN_INFO "SRAT: Node %u PXM %u %lx-%lx\n", node, pxm,
 	       start, end);
 
-	if (ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) {
+	if (!(ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)) {
+		nd = &nodes[node];
+		if (!node_test_and_set(node, nodes_parsed)) {
+			nd->start = start;
+			nd->end = end;
+		} else {
+			if (start < nd->start)
+				nd->start = start;
+			if (nd->end < end)
+				nd->end = end;
+		}
+	} else
 		update_nodes_add(node, start, end);
-		/* restore nodes[node] */
-		*nd = oldnode;
-		if ((nd->start | nd->end) == 0)
-			node_clear(node, nodes_parsed);
-	}
 
 	node_memblk_range[num_node_memblks].start = start;
 	node_memblk_range[num_node_memblks].end = end;
Signature · 1 line
1.7.1
#4 lore raw

Re: [PATCH 02/26] x86-64, NUMA: Simplify hotplug node handling in acpi_numa_memory_affinity_init()

Quoted 61 lines · Tejun Heo

Hotplug node handling in acpi_numa_memory_affinity_init() was unnecessarily complicated with storing the original nodes[] entry and restoring it afterwards. Simplify it by not modifying the nodes[] entry for hotplug nodes from the beginning.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/mm/srat_64.c |   31 +++++++++++++------------------
 1 files changed, 13 insertions(+), 18 deletions(-)
arch/x86/mm/srat_64.c +12 -13
index 9a97261..e3e0dd3 100644
@@ -251,7 +251,7 @@ update_nodes_add(int node, unsigned long start, unsigned long end)
 void __init
 acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
 {
-	struct bootnode *nd, oldnode;
+	struct bootnode *nd;
 	unsigned long start, end;
 	int node, pxm;
 	int i;
@@ -289,28 +289,23 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
 		bad_srat();
 		return;
 	}
-	nd = &nodes[node];
-	oldnode = *nd;
-	if (!node_test_and_set(node, nodes_parsed)) {
-		nd->start = start;
-		nd->end = end;
-	} else {
-		if (start < nd->start)
-			nd->start = start;
-		if (nd->end < end)
-			nd->end = end;
-	}
 
 	printk(KERN_INFO "SRAT: Node %u PXM %u %lx-%lx\n", node, pxm,
 	       start, end);
 
-	if (ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) {
+	if (!(ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)) {
+		nd = &nodes[node];
+		if (!node_test_and_set(node, nodes_parsed)) {
+			nd->start = start;
+			nd->end = end;
+		} else {
+			if (start < nd->start)
+				nd->start = start;
+			if (nd->end < end)
+				nd->end = end;
+		}

arch/x86/mm/srat_64.c acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) · line 311

Quoted 10 lines
arch/x86/mm/srat_64.c +1 -5
+	} else
 		update_nodes_add(node, start, end);
-		/* restore nodes[node] */
-		*nd = oldnode;
-		if ((nd->start | nd->end) == 0)
-			node_clear(node, nodes_parsed);
-	}
 
 	node_memblk_range[num_node_memblks].start = start;
 	node_memblk_range[num_node_memblks].end = end;

after change
looks like nodes_parsed is not set anymore for node that only have hotplug memory.

Thanks

Yinghai

author
#5 lore raw

Re: [PATCH 02/26] x86-64, NUMA: Simplify hotplug node handling in acpi_numa_memory_affinity_init()

Quoted 5 lines · Yinghai Lu
Quoted 2 lines

-             if ((nd->start | nd->end) == 0)
-                     node_clear(node, nodes_parsed);

after change
looks like nodes_parsed is not set anymore for node that only have hotplug memory.

Yeap, which matches the above node_clear(). If the node was already occupied, the bit would already be set. If not, the above node_clear() would clear it, so the same result. The code was quite convoluted.

Thanks.

Signature · 1 line
tejun
#6 lore raw

Re: [PATCH 02/26] x86-64, NUMA: Simplify hotplug node handling in acpi_numa_memory_affinity_init()

Quoted 11 lines · Tejun Heo
Quoted 5 lines · Yinghai Lu

arch/x86/mm/srat_64.c acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) · line 312

Quoted 2 lines
arch/x86/mm/srat_64.c +0 -2
-             if ((nd->start | nd->end) == 0)
-                     node_clear(node, nodes_parsed);

after change
looks like nodes_parsed is not set anymore for node that only have hotplug memory.

Yeap, which matches the above node_clear(). If the node was already occupied, the bit would already be set. If not, the above node_clear() would clear it, so the same result. The code was quite convoluted.

no. if the node only have hotplug mem.
then nd->start and nd->end will be set to that hot plug range. and old code does not clear nodes_parsed...

Yinghai

author
#7 lore raw

Re: [PATCH 02/26] x86-64, NUMA: Simplify hotplug node handling in acpi_numa_memory_affinity_init()

Quoted 3 lines · Yinghai Lu

no. if the node only have hotplug mem.
then nd->start and nd->end will be set to that hot plug range. and old code does not clear nodes_parsed...

Eh? The oldnode thing will restore the node to initial state thus fulfilling the node empty condition. Am I missing something?

Signature · 1 line
tejun
#8 lore raw

Re: [PATCH 02/26] x86-64, NUMA: Simplify hotplug node handling in acpi_numa_memory_affinity_init()

Quoted 8 lines · Tejun Heo
Quoted 3 lines · Yinghai Lu

no. if the node only have hotplug mem.
then nd->start and nd->end will be set to that hot plug range. and old code does not clear nodes_parsed...

Eh? The oldnode thing will restore the node to initial state thus fulfilling the node empty condition. Am I missing something?

yes. nd get restored, but it keep node_parsed set for that kind of node.

Yinghai

author
#9 lore raw

Re: [PATCH 02/26] x86-64, NUMA: Simplify hotplug node handling in acpi_numa_memory_affinity_init()

Hello, Yinghai.

Quoted 5 lines · Yinghai Lu
Quoted 3 lines

Eh? The oldnode thing will restore the node to initial state thus fulfilling the node empty condition. Am I missing something?

yes. nd get restored, but it keep node_parsed set for that kind of node.

So, this is the code snippet. Both @nd->start and end are zero and nodes_parsed for @node is clear.

	nd = &nodes[node];
	oldnode = *nd;

@oldnode->start, end == 0.

	if (!node_test_and_set(node, nodes_parsed)) {
		nd->start = start;
		nd->end = end;
This path is taken and @nd->start and end are set.
	} else {
		if (start < nd->start)
			nd->start = start;
		if (nd->end < end)
			nd->end = end;
	}

	printk(KERN_INFO "SRAT: Node %u PXM %u %lx-%lx\n", node, pxm,
	       start, end);

	if (ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) {
		update_nodes_add(node, start, end);
		/* restore nodes[node] */
		*nd = oldnode;
@nd->start and end are restored to zero.
		if ((nd->start | nd->end) == 0)
			node_clear(node, nodes_parsed);
and @nodes_parsed is cleared.
	}

So, what the hell am I missing?

Signature · 1 line
tejun
#10 lore raw

Re: [PATCH 02/26] x86-64, NUMA: Simplify hotplug node handling in acpi_numa_memory_affinity_init()

Quoted 31 lines · Tejun Heo

Hello, Yinghai.

Quoted 5 lines · Yinghai Lu
Quoted 3 lines

Eh?  The oldnode thing will restore the node to initial state thus fulfilling the node empty condition.  Am I missing something?

yes. nd get restored, but it keep node_parsed set for that kind of node.

So, this is the code snippet.  Both @nd->start and end are zero and nodes_parsed for @node is clear.

       nd = &nodes[node];
       oldnode = *nd;

@oldnode->start, end == 0.

       if (!node_test_and_set(node, nodes_parsed)) { nd->start = start;
               nd->end = end;
This path is taken and @nd->start and end are set. } else {
               if (start < nd->start) nd->start = start;
               if (nd->end < end)
                       nd->end = end;
       }

       printk(KERN_INFO "SRAT: Node %u PXM %u %lx-%lx\n", node, pxm, start, end);

Quoted 8 lines

       if (ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) { update_nodes_add(node, start, end); /* restore nodes[node] */
               *nd = oldnode;
@nd->start and end are restored to zero.
               if ((nd->start | nd->end) == 0) node_clear(node, nodes_parsed); and @nodes_parsed is cleared.

oh, i missed that restore happen first...

sorry.

Yinghai

author
#11 lore raw

PATCH 3/26 x86-64, NUMA: Drop @start/last_pfn from initmem_init()

In reply to Tejun Heo

initmem_init() extensively accesses and modifies global data structures and the parameters aren't even followed depending on which path is being used. Drop @start/last_pfn and let it deal with @max_pfn directly. This is in preparation for further NUMA init cleanups.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/include/asm/page_types.h |    3 +--
 arch/x86/kernel/setup.c           |    2 +-
 arch/x86/mm/init_64.c             |    5 ++---
 arch/x86/mm/numa_64.c             |   21 ++++++++-------------
 4 files changed, 12 insertions(+), 19 deletions(-)
arch/x86/include/asm/page_types.h +1 -2
index 1df6621..95892a1 100644
@@ -48,8 +48,7 @@ extern unsigned long max_pfn_mapped;
 extern unsigned long init_memory_mapping(unsigned long start,
 					 unsigned long end);
 
-extern void initmem_init(unsigned long start_pfn, unsigned long end_pfn,
-				int acpi, int k8);
+extern void initmem_init(int acpi, int k8);
 extern void free_initmem(void);
 
 #endif	/* !__ASSEMBLY__ */
arch/x86/kernel/setup.c +1 -1
index 1202341..c50ba3d 100644
@@ -996,7 +996,7 @@ void __init setup_arch(char **cmdline_p)
 		amd = !amd_numa_init(0, max_pfn);
 #endif
 
-	initmem_init(0, max_pfn, acpi, amd);
+	initmem_init(acpi, amd);
 	memblock_find_dma_reserve();
 	dma32_reserve_bootmem();
 
arch/x86/mm/init_64.c +2 -3
index 71a5929..26e4e73 100644
@@ -612,10 +612,9 @@ kernel_physical_mapping_init(unsigned long start,
 }
 
 #ifndef CONFIG_NUMA
-void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn,
-				int acpi, int k8)
+void __init initmem_init(int acpi, int k8)
 {
-	memblock_x86_register_active_regions(0, start_pfn, end_pfn);
+	memblock_x86_register_active_regions(0, 0, max_pfn);
 }
 #endif
 
arch/x86/mm/numa_64.c +8 -13
index ea5dd48..f534feb 100644
@@ -578,8 +578,7 @@ static int __init numa_emulation(unsigned long start_pfn,
 }
 #endif /* CONFIG_NUMA_EMU */
 
-void __init initmem_init(unsigned long start_pfn, unsigned long last_pfn,
-				int acpi, int amd)
+void __init initmem_init(int acpi, int amd)
 {
 	int i;
 
@@ -587,19 +586,16 @@ void __init initmem_init(unsigned long start_pfn, unsigned long last_pfn,
 	nodes_clear(node_online_map);
 
 #ifdef CONFIG_NUMA_EMU
-	setup_physnodes(start_pfn << PAGE_SHIFT, last_pfn << PAGE_SHIFT,
-			acpi, amd);
-	if (cmdline && !numa_emulation(start_pfn, last_pfn, acpi, amd))
+	setup_physnodes(0, max_pfn << PAGE_SHIFT, acpi, amd);
+	if (cmdline && !numa_emulation(0, max_pfn, acpi, amd))
 		return;
-	setup_physnodes(start_pfn << PAGE_SHIFT, last_pfn << PAGE_SHIFT,
-			acpi, amd);
+	setup_physnodes(0, max_pfn << PAGE_SHIFT, acpi, amd);
 	nodes_clear(node_possible_map);
 	nodes_clear(node_online_map);
 #endif
 
 #ifdef CONFIG_ACPI_NUMA
-	if (!numa_off && acpi && !acpi_scan_nodes(start_pfn << PAGE_SHIFT,
-						  last_pfn << PAGE_SHIFT))
+	if (!numa_off && acpi && !acpi_scan_nodes(0, max_pfn << PAGE_SHIFT))
 		return;
 	nodes_clear(node_possible_map);
 	nodes_clear(node_online_map);
@@ -615,8 +611,7 @@ void __init initmem_init(unsigned long start_pfn, unsigned long last_pfn,
 	       numa_off ? "NUMA turned off" : "No NUMA configuration found");
 
 	printk(KERN_INFO "Faking a node at %016lx-%016lx\n",
-	       start_pfn << PAGE_SHIFT,
-	       last_pfn << PAGE_SHIFT);
+	       0LU, max_pfn << PAGE_SHIFT);
 	/* setup dummy node covering all memory */
 	memnode_shift = 63;
 	memnodemap = memnode.embedded_map;
@@ -625,8 +620,8 @@ void __init initmem_init(unsigned long start_pfn, unsigned long last_pfn,
 	node_set(0, node_possible_map);
 	for (i = 0; i < MAX_LOCAL_APIC; i++)
 		set_apicid_to_node(i, NUMA_NO_NODE);
-	memblock_x86_register_active_regions(0, start_pfn, last_pfn);
-	setup_node_bootmem(0, start_pfn << PAGE_SHIFT, last_pfn << PAGE_SHIFT);
+	memblock_x86_register_active_regions(0, 0, max_pfn);
+	setup_node_bootmem(0, 0, max_pfn << PAGE_SHIFT);
 	numa_init_array();
 }
 
Signature · 1 line
1.7.1
#12 lore raw

Re: [PATCH 03/26] x86-64, NUMA: Drop @start/last_pfn from initmem_init()

Quoted 14 lines · Tejun Heo

initmem_init() extensively accesses and modifies global data structures and the parameters aren't even followed depending on which path is being used. Drop @start/last_pfn and let it deal with @max_pfn directly. This is in preparation for further NUMA init cleanups.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
Quoted 6 lines
---
 arch/x86/include/asm/page_types.h |    3 +--
 arch/x86/kernel/setup.c           |    2 +-
 arch/x86/mm/init_64.c             |    5 ++---
 arch/x86/mm/numa_64.c             |   21 ++++++++-------------
 4 files changed, 12 insertions(+), 19 deletions(-)

it will break 32bit.

Yinghai

author
#13 lore raw

Re: [PATCH 03/26] x86-64, NUMA: Drop @start/last_pfn from initmem_init()

Quoted 1 line · Yinghai Lu

it will break 32bit.

Ah, right. Forgot that part was shared with 32bit. Will update. Thanks.

Signature · 1 line
tejun
author
#14 lore raw

PATCH 3/26 x86, NUMA: Drop @start/last_pfn from initmem_init() initmem_init()

In reply to Tejun Heo

initmem_init() extensively accesses and modifies global data structures and the parameters aren't even followed depending on which path is being used. Drop @start/last_pfn and let it deal with @max_pfn directly. This is in preparation for further NUMA init cleanups.

* x86-32 initmem_init() weren't updated breaking 32bit builds. Fixed.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>

---
Updated to convert 32bit initmem_init()'s which didn't use the two parameters at all. git tree updated accordingly.

Thanks.

 arch/x86/include/asm/page_types.h |    3 +--
 arch/x86/kernel/setup.c           |    2 +-
 arch/x86/mm/init_32.c             |    3 +--
 arch/x86/mm/init_64.c             |    5 ++---
 arch/x86/mm/numa_32.c             |    3 +--
 arch/x86/mm/numa_64.c             |   21 ++++++++-------------
 6 files changed, 14 insertions(+), 23 deletions(-)
arch/x86/include/asm/page_types.h +1 -2
index 1df6621..95892a1 100644
@@ -48,8 +48,7 @@ extern unsigned long max_pfn_mapped;
 extern unsigned long init_memory_mapping(unsigned long start,
 					 unsigned long end);
 
-extern void initmem_init(unsigned long start_pfn, unsigned long end_pfn,
-				int acpi, int k8);
+extern void initmem_init(int acpi, int k8);
 extern void free_initmem(void);
 
 #endif	/* !__ASSEMBLY__ */
arch/x86/kernel/setup.c +1 -1
index 1202341..c50ba3d 100644
@@ -996,7 +996,7 @@ void __init setup_arch(char **cmdline_p)
 		amd = !amd_numa_init(0, max_pfn);
 #endif
 
-	initmem_init(0, max_pfn, acpi, amd);
+	initmem_init(acpi, amd);
 	memblock_find_dma_reserve();
 	dma32_reserve_bootmem();
 
arch/x86/mm/init_32.c +1 -2
index c821074..16adb66 100644
@@ -644,8 +644,7 @@ void __init find_low_pfn_range(void)
 }
 
 #ifndef CONFIG_NEED_MULTIPLE_NODES
-void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn,
-				int acpi, int k8)
+void __init initmem_init(int acpi, int k8)
 {
 #ifdef CONFIG_HIGHMEM
 	highstart_pfn = highend_pfn = max_pfn;
arch/x86/mm/init_64.c +2 -3
index 71a5929..26e4e73 100644
@@ -612,10 +612,9 @@ kernel_physical_mapping_init(unsigned long start,
 }
 
 #ifndef CONFIG_NUMA
-void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn,
-				int acpi, int k8)
+void __init initmem_init(int acpi, int k8)
 {
-	memblock_x86_register_active_regions(0, start_pfn, end_pfn);
+	memblock_x86_register_active_regions(0, 0, max_pfn);
 }
 #endif
 
arch/x86/mm/numa_32.c +1 -2
index 505bb04..3249b37 100644
@@ -352,8 +352,7 @@ static void init_remap_allocator(int nid)
 		(ulong) node_remap_end_vaddr[nid]);
 }
 
-void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn,
-				int acpi, int k8)
+void __init initmem_init(int acpi, int k8)
 {
 	int nid;
 	long kva_target_pfn;
arch/x86/mm/numa_64.c +8 -13
index ea5dd48..f534feb 100644
@@ -578,8 +578,7 @@ static int __init numa_emulation(unsigned long start_pfn,
 }
 #endif /* CONFIG_NUMA_EMU */
 
-void __init initmem_init(unsigned long start_pfn, unsigned long last_pfn,
-				int acpi, int amd)
+void __init initmem_init(int acpi, int amd)
 {
 	int i;
 
@@ -587,19 +586,16 @@ void __init initmem_init(unsigned long start_pfn, unsigned long last_pfn,
 	nodes_clear(node_online_map);
 
 #ifdef CONFIG_NUMA_EMU
-	setup_physnodes(start_pfn << PAGE_SHIFT, last_pfn << PAGE_SHIFT,
-			acpi, amd);
-	if (cmdline && !numa_emulation(start_pfn, last_pfn, acpi, amd))
+	setup_physnodes(0, max_pfn << PAGE_SHIFT, acpi, amd);
+	if (cmdline && !numa_emulation(0, max_pfn, acpi, amd))
 		return;
-	setup_physnodes(start_pfn << PAGE_SHIFT, last_pfn << PAGE_SHIFT,
-			acpi, amd);
+	setup_physnodes(0, max_pfn << PAGE_SHIFT, acpi, amd);
 	nodes_clear(node_possible_map);
 	nodes_clear(node_online_map);
 #endif
 
 #ifdef CONFIG_ACPI_NUMA
-	if (!numa_off && acpi && !acpi_scan_nodes(start_pfn << PAGE_SHIFT,
-						  last_pfn << PAGE_SHIFT))
+	if (!numa_off && acpi && !acpi_scan_nodes(0, max_pfn << PAGE_SHIFT))
 		return;
 	nodes_clear(node_possible_map);
 	nodes_clear(node_online_map);
@@ -615,8 +611,7 @@ void __init initmem_init(unsigned long start_pfn, unsigned long last_pfn,
 	       numa_off ? "NUMA turned off" : "No NUMA configuration found");
 
 	printk(KERN_INFO "Faking a node at %016lx-%016lx\n",
-	       start_pfn << PAGE_SHIFT,
-	       last_pfn << PAGE_SHIFT);
+	       0LU, max_pfn << PAGE_SHIFT);
 	/* setup dummy node covering all memory */
 	memnode_shift = 63;
 	memnodemap = memnode.embedded_map;
@@ -625,8 +620,8 @@ void __init initmem_init(unsigned long start_pfn, unsigned long last_pfn,
 	node_set(0, node_possible_map);
 	for (i = 0; i < MAX_LOCAL_APIC; i++)
 		set_apicid_to_node(i, NUMA_NO_NODE);
-	memblock_x86_register_active_regions(0, start_pfn, last_pfn);
-	setup_node_bootmem(0, start_pfn << PAGE_SHIFT, last_pfn << PAGE_SHIFT);
+	memblock_x86_register_active_regions(0, 0, max_pfn);
+	setup_node_bootmem(0, 0, max_pfn << PAGE_SHIFT);
 	numa_init_array();
 }
 
Signature · 1 line
1.7.1
#15 lore raw

Re: [PATCH UPDATED 03/26] x86, NUMA: Drop @start/last_pfn from initmem_init() initmem_init()

Quoted 8 lines · Tejun Heo

initmem_init() extensively accesses and modifies global data structures and the parameters aren't even followed depending on which path is being used. Drop @start/last_pfn and let it deal with @max_pfn directly. This is in preparation for further NUMA init cleanups.

* x86-32 initmem_init() weren't updated breaking 32bit builds. Fixed.

Quoted 8 lines
Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>

You forgot to add:

The kernel development process is review and testing limited and we have a clear oversupply in development power. So we want to encourage review and testing feedback as much as possible, so adding all the Reported-by / Tested-by tags is absolutely vital to being able to do more development.

Thanks,

Ingo

author
#16 lore raw

Re: [PATCH UPDATED 03/26] x86, NUMA: Drop @start/last_pfn from initmem_init() initmem_init()

Quoted 8 lines · Ingo Molnar

You forgot to add:

The kernel development process is review and testing limited and we have a clear oversupply in development power. So we want to encourage review and testing feedback as much as possible, so adding all the Reported-by / Tested-by tags is absolutely vital to being able to do more development.

git tree updated accordingly, but Reported-by? I use that to identify the person who found out the root problem the commit is addressing. Once review cycle is complete, Reviewed/Acked-by's will be added so I'm not sure adding Reported-by serves any purpose.

Thanks.

Signature · 1 line
tejun
#17 lore raw

Re: [PATCH UPDATED 03/26] x86, NUMA: Drop @start/last_pfn from initmem_init() initmem_init()

Quoted 10 lines · Tejun Heo
Quoted 8 lines · Ingo Molnar

You forgot to add:

The kernel development process is review and testing limited and we have a clear oversupply in development power. So we want to encourage review and testing feedback as much as possible, so adding all the Reported-by / Tested-by tags is absolutely vital to being able to do more development.

Quoted 4 lines

git tree updated accordingly, but Reported-by? I use that to identify the person who found out the root problem the commit is addressing. Once review cycle is complete, Reviewed/Acked-by's will be added so I'm not sure adding Reported-by serves any purpose.

could be something in change log for -v2

initmem_init() extensively accesses and modifies global data structures and the parameters aren't even followed depending on which path is being used. Drop @start/last_pfn and let it deal with @max_pfn directly. This is in preparation for further NUMA init cleanups.

-v2: x86-32 initmem_init() weren't updated breaking 32bit builds. Fixed.
Found by Yinghai

author
#18 lore raw

Re: [PATCH UPDATED 03/26] x86, NUMA: Drop @start/last_pfn from initmem_init() initmem_init()

Quoted 8 lines · Yinghai Lu

initmem_init() extensively accesses and modifies global data structures and the parameters aren't even followed depending on which path is being used. Drop @start/last_pfn and let it deal with @max_pfn directly. This is in preparation for further NUMA init cleanups.

-v2: x86-32 initmem_init() weren't updated breaking 32bit builds. Fixed.
Found by Yinghai

Alright, updated accordingly in the git tree.

Thanks.

Signature · 1 line
tejun
#19 lore raw

Re: [PATCH UPDATED 03/26] x86, NUMA: Drop @start/last_pfn from initmem_init() initmem_init()

Quoted 11 lines · Tejun Heo
Quoted 8 lines · Yinghai Lu

initmem_init() extensively accesses and modifies global data structures and the parameters aren't even followed depending on which path is being used. Drop @start/last_pfn and let it deal with @max_pfn directly. This is in preparation for further NUMA init cleanups.

-v2: x86-32 initmem_init() weren't updated breaking 32bit builds. Fixed.
Found by Yinghai

Alright, updated accordingly in the git tree.

Yeah, that kind of tag is fine too, or:

Build-bug-in-v1-found-by: ...

:-)

Thanks,

Ingo

author
#20 lore raw

PATCH 4/26 x86-64, NUMA: Unify {acpi|amd}_{numa_init|scan_nodes}() arguments and return values

In reply to Tejun Heo

The functions used during NUMA initialization - *_numa_init() and *_scan_nodes() - have different arguments and return values. Unify them such that they all take no argument and return 0 on success and -errno on failure. This is in preparation for further NUMA init cleanups.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/include/asm/acpi.h   |    2 +-
 arch/x86/include/asm/amd_nb.h |    2 +-
 arch/x86/kernel/setup.c       |    4 ++--
 arch/x86/mm/amdtopology_64.c  |   18 +++++++++---------
 arch/x86/mm/numa_64.c         |    2 +-
 arch/x86/mm/srat_64.c         |    4 ++--
 drivers/acpi/numa.c           |    9 ++++++---
 7 files changed, 22 insertions(+), 19 deletions(-)
arch/x86/include/asm/acpi.h +1 -1
index 211ca3f..4e5dff9 100644
@@ -187,7 +187,7 @@ struct bootnode;
 extern int acpi_numa;
 extern void acpi_get_nodes(struct bootnode *physnodes, unsigned long start,
 				unsigned long end);
-extern int acpi_scan_nodes(unsigned long start, unsigned long end);
+extern int acpi_scan_nodes(void);
 #define NR_NODE_MEMBLKS (MAX_NUMNODES*2)
 
 #ifdef CONFIG_NUMA_EMU
arch/x86/include/asm/amd_nb.h +1 -1
index 64dc82e..72abf65 100644
@@ -16,7 +16,7 @@ struct bootnode;
 extern int early_is_amd_nb(u32 value);
 extern int amd_cache_northbridges(void);
 extern void amd_flush_garts(void);
-extern int amd_numa_init(unsigned long start_pfn, unsigned long end_pfn);
+extern int amd_numa_init(void);
 extern int amd_scan_nodes(void);
 
 #ifdef CONFIG_NUMA_EMU
arch/x86/kernel/setup.c +2 -2
index c50ba3d..1870a59 100644
@@ -988,12 +988,12 @@ void __init setup_arch(char **cmdline_p)
 	/*
 	 * Parse SRAT to discover nodes.
 	 */
-	acpi = acpi_numa_init();
+	acpi = !acpi_numa_init();
 #endif
 
 #ifdef CONFIG_AMD_NUMA
 	if (!acpi)
-		amd = !amd_numa_init(0, max_pfn);
+		amd = !amd_numa_init();
 #endif
 
 	initmem_init(acpi, amd);
arch/x86/mm/amdtopology_64.c +9 -9
index c7fae38..ee70257 100644
@@ -51,7 +51,7 @@ static __init int find_northbridge(void)
 		return num;
 	}
 
-	return -1;
+	return -ENOENT;
 }
 
 static __init void early_get_boot_cpu_id(void)
@@ -69,17 +69,17 @@ static __init void early_get_boot_cpu_id(void)
 #endif
 }
 
-int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn)
+int __init amd_numa_init(void)
 {
-	unsigned long start = PFN_PHYS(start_pfn);
-	unsigned long end = PFN_PHYS(end_pfn);
+	unsigned long start = PFN_PHYS(0);
+	unsigned long end = PFN_PHYS(max_pfn);
 	unsigned numnodes;
 	unsigned long prevbase;
 	int i, nb, found = 0;
 	u32 nodeid, reg;
 
 	if (!early_pci_allowed())
-		return -1;
+		return -EINVAL;
 
 	nb = find_northbridge();
 	if (nb < 0)
@@ -90,7 +90,7 @@ int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn)
 	reg = read_pci_config(0, nb, 0, 0x60);
 	numnodes = ((reg >> 4) & 0xF) + 1;
 	if (numnodes <= 1)
-		return -1;
+		return -ENOENT;
 
 	pr_info("Number of physical nodes %d\n", numnodes);
 
@@ -121,7 +121,7 @@ int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn)
 		if ((base >> 8) & 3 || (limit >> 8) & 3) {
 			pr_err("Node %d using interleaving mode %lx/%lx\n",
 			       nodeid, (base >> 8) & 3, (limit >> 8) & 3);
-			return -1;
+			return -EINVAL;
 		}
 		if (node_isset(nodeid, nodes_parsed)) {
 			pr_info("Node %d already present, skipping\n",
@@ -160,7 +160,7 @@ int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn)
 		if (prevbase > base) {
 			pr_err("Node map not sorted %lx,%lx\n",
 			       prevbase, base);
-			return -1;
+			return -EINVAL;
 		}
 
 		pr_info("Node %d MemBase %016lx Limit %016lx\n",
@@ -177,7 +177,7 @@ int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn)
 	}
 
 	if (!found)
-		return -1;
+		return -ENOENT;
 	return 0;
 }
 
arch/x86/mm/numa_64.c +1 -1
index f534feb..85561d1 100644
@@ -595,7 +595,7 @@ void __init initmem_init(int acpi, int amd)
 #endif
 
 #ifdef CONFIG_ACPI_NUMA
-	if (!numa_off && acpi && !acpi_scan_nodes(0, max_pfn << PAGE_SHIFT))
+	if (!numa_off && acpi && !acpi_scan_nodes())
 		return;
 	nodes_clear(node_possible_map);
 	nodes_clear(node_online_map);
arch/x86/mm/srat_64.c +2 -2
index e3e0dd3..19652dd 100644
@@ -359,7 +359,7 @@ void __init acpi_get_nodes(struct bootnode *physnodes, unsigned long start,
 #endif /* CONFIG_NUMA_EMU */
 
 /* Use the information discovered above to actually set up the nodes. */
-int __init acpi_scan_nodes(unsigned long start, unsigned long end)
+int __init acpi_scan_nodes(void)
 {
 	int i;
 
@@ -368,7 +368,7 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
 
 	/* First clean up the node list */
 	for (i = 0; i < MAX_NUMNODES; i++)
-		cutoff_node(i, start, end);
+		cutoff_node(i, 0, max_pfn << PAGE_SHIFT);
 
 	/*
 	 * Join together blocks on the same node, holes between
drivers/acpi/numa.c +6 -3
index 5eb25eb..3b5c318 100644
@@ -274,7 +274,7 @@ acpi_table_parse_srat(enum acpi_srat_type id,
 
 int __init acpi_numa_init(void)
 {
-	int ret = 0;
+	int cnt = 0;
 
 	/*
 	 * Should not limit number with cpu num that is from NR_CPUS or nr_cpus=
@@ -288,7 +288,7 @@ int __init acpi_numa_init(void)
 				     acpi_parse_x2apic_affinity, 0);
 		acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY,
 				     acpi_parse_processor_affinity, 0);
-		ret = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
+		cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
 					    acpi_parse_memory_affinity,
 					    NR_NODE_MEMBLKS);
 	}
@@ -297,7 +297,10 @@ int __init acpi_numa_init(void)
 	acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);
 
 	acpi_numa_arch_fixup();
-	return ret;
+
+	if (cnt <= 0)
+		return cnt ?: -ENOENT;
+	return 0;
 }
 
 int acpi_get_pxm(acpi_handle h)
Signature · 1 line
1.7.1
#21 lore raw

Re: [PATCH 04/26] x86-64, NUMA: Unify {acpi|amd}_{numa_init|scan_nodes}() arguments and return values

Quoted 199 lines · Tejun Heo

The functions used during NUMA initialization - *_numa_init() and *_scan_nodes() - have different arguments and return values. Unify them such that they all take no argument and return 0 on success and -errno on failure. This is in preparation for further NUMA init cleanups.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/include/asm/acpi.h   |    2 +-
 arch/x86/include/asm/amd_nb.h |    2 +-
 arch/x86/kernel/setup.c       |    4 ++--
 arch/x86/mm/amdtopology_64.c  |   18 +++++++++---------
 arch/x86/mm/numa_64.c         |    2 +-
 arch/x86/mm/srat_64.c         |    4 ++--
 drivers/acpi/numa.c           |    9 ++++++---
 7 files changed, 22 insertions(+), 19 deletions(-)
arch/x86/include/asm/acpi.h +1 -1
index 211ca3f..4e5dff9 100644
@@ -187,7 +187,7 @@ struct bootnode;
 extern int acpi_numa;
 extern void acpi_get_nodes(struct bootnode *physnodes, unsigned long start,
 				unsigned long end);
-extern int acpi_scan_nodes(unsigned long start, unsigned long end);
+extern int acpi_scan_nodes(void);
 #define NR_NODE_MEMBLKS (MAX_NUMNODES*2)
 
 #ifdef CONFIG_NUMA_EMU
arch/x86/include/asm/amd_nb.h +1 -1
index 64dc82e..72abf65 100644
@@ -16,7 +16,7 @@ struct bootnode;
 extern int early_is_amd_nb(u32 value);
 extern int amd_cache_northbridges(void);
 extern void amd_flush_garts(void);
-extern int amd_numa_init(unsigned long start_pfn, unsigned long end_pfn);
+extern int amd_numa_init(void);
 extern int amd_scan_nodes(void);
 
 #ifdef CONFIG_NUMA_EMU
arch/x86/kernel/setup.c +2 -2
index c50ba3d..1870a59 100644
@@ -988,12 +988,12 @@ void __init setup_arch(char **cmdline_p)
 	/*
 	 * Parse SRAT to discover nodes.
 	 */
-	acpi = acpi_numa_init();
+	acpi = !acpi_numa_init();
 #endif
 
 #ifdef CONFIG_AMD_NUMA
 	if (!acpi)
-		amd = !amd_numa_init(0, max_pfn);
+		amd = !amd_numa_init();
 #endif
 
 	initmem_init(acpi, amd);
arch/x86/mm/amdtopology_64.c +9 -9
index c7fae38..ee70257 100644
@@ -51,7 +51,7 @@ static __init int find_northbridge(void)
 		return num;
 	}
 
-	return -1;
+	return -ENOENT;
 }
 
 static __init void early_get_boot_cpu_id(void)
@@ -69,17 +69,17 @@ static __init void early_get_boot_cpu_id(void)
 #endif
 }
 
-int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn)
+int __init amd_numa_init(void)
 {
-	unsigned long start = PFN_PHYS(start_pfn);
-	unsigned long end = PFN_PHYS(end_pfn);
+	unsigned long start = PFN_PHYS(0);
+	unsigned long end = PFN_PHYS(max_pfn);
 	unsigned numnodes;
 	unsigned long prevbase;
 	int i, nb, found = 0;
 	u32 nodeid, reg;
 
 	if (!early_pci_allowed())
-		return -1;
+		return -EINVAL;
 
 	nb = find_northbridge();
 	if (nb < 0)
@@ -90,7 +90,7 @@ int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn)
 	reg = read_pci_config(0, nb, 0, 0x60);
 	numnodes = ((reg >> 4) & 0xF) + 1;
 	if (numnodes <= 1)
-		return -1;
+		return -ENOENT;
 
 	pr_info("Number of physical nodes %d\n", numnodes);
 
@@ -121,7 +121,7 @@ int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn)
 		if ((base >> 8) & 3 || (limit >> 8) & 3) {
 			pr_err("Node %d using interleaving mode %lx/%lx\n",
 			       nodeid, (base >> 8) & 3, (limit >> 8) & 3);
-			return -1;
+			return -EINVAL;
 		}
 		if (node_isset(nodeid, nodes_parsed)) {
 			pr_info("Node %d already present, skipping\n",
@@ -160,7 +160,7 @@ int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn)
 		if (prevbase > base) {
 			pr_err("Node map not sorted %lx,%lx\n",
 			       prevbase, base);
-			return -1;
+			return -EINVAL;
 		}
 
 		pr_info("Node %d MemBase %016lx Limit %016lx\n",
@@ -177,7 +177,7 @@ int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn)
 	}
 
 	if (!found)
-		return -1;
+		return -ENOENT;
 	return 0;
 }
 
arch/x86/mm/numa_64.c +1 -1
index f534feb..85561d1 100644
@@ -595,7 +595,7 @@ void __init initmem_init(int acpi, int amd)
 #endif
 
 #ifdef CONFIG_ACPI_NUMA
-	if (!numa_off && acpi && !acpi_scan_nodes(0, max_pfn << PAGE_SHIFT))
+	if (!numa_off && acpi && !acpi_scan_nodes())
 		return;
 	nodes_clear(node_possible_map);
 	nodes_clear(node_online_map);
arch/x86/mm/srat_64.c +2 -2
index e3e0dd3..19652dd 100644
@@ -359,7 +359,7 @@ void __init acpi_get_nodes(struct bootnode *physnodes, unsigned long start,
 #endif /* CONFIG_NUMA_EMU */
 
 /* Use the information discovered above to actually set up the nodes. */
-int __init acpi_scan_nodes(unsigned long start, unsigned long end)
+int __init acpi_scan_nodes(void)
 {
 	int i;
 
@@ -368,7 +368,7 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
 
 	/* First clean up the node list */
 	for (i = 0; i < MAX_NUMNODES; i++)
-		cutoff_node(i, start, end);
+		cutoff_node(i, 0, max_pfn << PAGE_SHIFT);
 
 	/*
 	 * Join together blocks on the same node, holes between
drivers/acpi/numa.c +2 -2
index 5eb25eb..3b5c318 100644
@@ -274,7 +274,7 @@ acpi_table_parse_srat(enum acpi_srat_type id,
 
 int __init acpi_numa_init(void)
 {
-	int ret = 0;
+	int cnt = 0;
 
 	/*
 	 * Should not limit number with cpu num that is from NR_CPUS or nr_cpus=
@@ -288,7 +288,7 @@ int __init acpi_numa_init(void)
 				     acpi_parse_x2apic_affinity, 0);
 		acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY,
 				     acpi_parse_processor_affinity, 0);
-		ret = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
+		cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
 					    acpi_parse_memory_affinity,
 					    NR_NODE_MEMBLKS);
 	}
@@ -297,7 +297,10 @@ int __init acpi_numa_init(void)
 	acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);

drivers/acpi/numa.c int __init acpi_numa_init(void) · line 306

Quoted 10 lines
drivers/acpi/numa.c +4 -1
 
 	acpi_numa_arch_fixup();
-	return ret;
+
+	if (cnt <= 0)
+		return cnt ?: -ENOENT;
+	return 0;
 }
 
 int acpi_get_pxm(acpi_handle h)

it will break AMD system that does not have SRAT.

your change will treat NO_SRAT as SRAT is there.

Yinghai

author
#22 lore raw

Re: [PATCH 04/26] x86-64, NUMA: Unify {acpi|amd}_{numa_init|scan_nodes}() arguments and return values

Quoted 11 lines · Yinghai Lu
Quoted 11 lines
drivers/acpi/numa.c +4 -1
@@ -297,7 +297,10 @@ int __init acpi_numa_init(void)
 	acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);
 
 	acpi_numa_arch_fixup();
-	return ret;
+
+	if (cnt <= 0)
+		return cnt ?: -ENOENT;
+	return 0;
 }
 
Quoted 6 lines

drivers/acpi/numa.c int __init acpi_numa_init(void) · line 306

Quoted 1 line
drivers/acpi/numa.c +0 -0
 int acpi_get_pxm(acpi_handle h)

it will break AMD system that does not have SRAT.

your change will treat NO_SRAT as SRAT is there.

Can you please elaborate a bit? Yinghai, there's brevity and there's being cryptic. I appreciate your reviews but don't want to spend time trying to decipher what you mean. If it doesn't hurt your fingers too much, please put a bit more effort into explaining.

Thank you.

Signature · 1 line
tejun
#23 lore raw

Re: [PATCH 04/26] x86-64, NUMA: Unify {acpi|amd}_{numa_init|scan_nodes}() arguments and return values

Quoted 17 lines · Tejun Heo
Quoted 16 lines · Yinghai Lu

drivers/acpi/numa.c int __init acpi_numa_init(void) · line 306

Quoted 12 lines
drivers/acpi/numa.c +4 -1
@@ -297,7 +297,10 @@ int __init acpi_numa_init(void)
     acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);
 
     acpi_numa_arch_fixup();
-   return ret;
+
+   if (cnt <= 0)
+           return cnt ?: -ENOENT;
+   return 0;
  }
 
  int acpi_get_pxm(acpi_handle h)

it will break AMD system that does not have SRAT.

Quoted 6 lines
Quoted 1 line

your change will treat NO_SRAT as SRAT is there.

Can you please elaborate a bit?  Yinghai, there's brevity and there's being cryptic.  I appreciate your reviews but don't want to spend time trying to decipher what you mean.  If it doesn't hurt your fingers too much, please put a bit more effort into explaining.

when system have acpi support but SRAT is NOT there, new acpi_numa_init() will return 0 just like SRAT is there and correct. So it will skip AMD node scanning.

Yinghai

author
#24 lore raw

Re: [PATCH 04/26] x86-64, NUMA: Unify {acpi|amd}_{numa_init|scan_nodes}() arguments and return values

Quoted 3 lines · Yinghai Lu

when system have acpi support but SRAT is NOT there, new acpi_numa_init() will return 0 just like SRAT is there and correct. So it will skip AMD node scanning.

How does it return 0?

...

		cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
					    acpi_parse_memory_affinity,
					    NR_NODE_MEMBLKS);
If there's no srat, cnt is zero.
	}

	/* SLIT: System Locality Information Table */
	acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);

	acpi_numa_arch_fixup();

	if (cnt <= 0)
if cnt is zero, the if is taken
		return cnt ?: -ENOENT;
and as cnt is zero, -ENOENT is returned.
	return 0;

The function returns 0 iff cnt > 0.

Signature · 1 line
tejun
#25 lore raw

Re: [PATCH 04/26] x86-64, NUMA: Unify {acpi|amd}_{numa_init|scan_nodes}() arguments and return values

Quoted 17 lines · Tejun Heo
Quoted 3 lines · Yinghai Lu

when system have acpi support  but SRAT is NOT there,  new acpi_numa_init() will return 0 just like SRAT is there and correct. So it will skip AMD node scanning.

How does it return 0?

...
               cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY, acpi_parse_memory_affinity, NR_NODE_MEMBLKS); If there's no srat, cnt is zero.
       }

       /* SLIT: System Locality Information Table */ acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);

Quoted 8 lines

       acpi_numa_arch_fixup();

       if (cnt <= 0)
if cnt is zero, the if is taken
               return cnt ?: -ENOENT;
and as cnt is zero, -ENOENT is returned.
       return 0;
The function returns 0 iff cnt > 0.

oh, I missed it again.

Yinghai

author
#26 lore raw

PATCH 5/26 x86-64, NUMA: Wrap acpi_numa_init() so that failure can be indicated by return value

In reply to Tejun Heo

Because of the way ACPI tables are parsed, the generic acpi_numa_init() couldn't return failure when error was detected by arch hooks. Instead, the failure state was recorded and later arch dependent init hook - acpi_scan_nodes() - would fail.

Wrap acpi_numa_init() with x86_acpi_numa_init() so that failure can be indicated as return value immediately. This is in preparation for further NUMA init cleanups.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/include/asm/acpi.h |    1 +
 arch/x86/kernel/setup.c     |    2 +-
 arch/x86/mm/srat_64.c       |   10 ++++++++++
 3 files changed, 12 insertions(+), 1 deletions(-)
arch/x86/include/asm/acpi.h +1 -0
index 4e5dff9..06fb786 100644
@@ -187,6 +187,7 @@ struct bootnode;
 extern int acpi_numa;
 extern void acpi_get_nodes(struct bootnode *physnodes, unsigned long start,
 				unsigned long end);
+extern int x86_acpi_numa_init(void);
 extern int acpi_scan_nodes(void);
 #define NR_NODE_MEMBLKS (MAX_NUMNODES*2)
 
arch/x86/kernel/setup.c +1 -1
index 1870a59..f69d838 100644
@@ -988,7 +988,7 @@ void __init setup_arch(char **cmdline_p)
 	/*
 	 * Parse SRAT to discover nodes.
 	 */
-	acpi = !acpi_numa_init();
+	acpi = !x86_acpi_numa_init();
 #endif
 
 #ifdef CONFIG_AMD_NUMA
arch/x86/mm/srat_64.c +10 -0
index 19652dd..8d145ae 100644
@@ -358,6 +358,16 @@ void __init acpi_get_nodes(struct bootnode *physnodes, unsigned long start,
 }
 #endif /* CONFIG_NUMA_EMU */
 
+int __init x86_acpi_numa_init(void)
+{
+	int ret;
+
+	ret = acpi_numa_init();
+	if (ret < 0)
+		return ret;
+	return srat_disabled() ? -EINVAL : 0;
+}
+
 /* Use the information discovered above to actually set up the nodes. */
 int __init acpi_scan_nodes(void)
 {
Signature · 1 line
1.7.1
author
#27 lore raw

PATCH 6/26 x86-64, NUMA: Move *_numa_init() invocations into initmem_init()

In reply to Tejun Heo

There's no reason for these to live in setup_arch(). Move them inside initmem_init().

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/include/asm/page_types.h |    2 +-
 arch/x86/kernel/setup.c           |   16 +---------------
 arch/x86/mm/init_64.c             |    2 +-
 arch/x86/mm/numa_64.c             |   16 +++++++++++++++-
 4 files changed, 18 insertions(+), 18 deletions(-)
arch/x86/include/asm/page_types.h +1 -1
index 95892a1..c157986 100644
@@ -48,7 +48,7 @@ extern unsigned long max_pfn_mapped;
 extern unsigned long init_memory_mapping(unsigned long start,
 					 unsigned long end);
 
-extern void initmem_init(int acpi, int k8);
+extern void initmem_init(void);
 extern void free_initmem(void);
 
 #endif	/* !__ASSEMBLY__ */
arch/x86/kernel/setup.c +1 -15
index f69d838..9907b45 100644
@@ -704,8 +704,6 @@ static u64 __init get_max_mapped(void)
 
 void __init setup_arch(char **cmdline_p)
 {
-	int acpi = 0;
-	int amd = 0;
 	unsigned long flags;
 
 #ifdef CONFIG_X86_32
@@ -984,19 +982,7 @@ void __init setup_arch(char **cmdline_p)
 
 	early_acpi_boot_init();
 
-#ifdef CONFIG_ACPI_NUMA
-	/*
-	 * Parse SRAT to discover nodes.
-	 */
-	acpi = !x86_acpi_numa_init();
-#endif
-
-#ifdef CONFIG_AMD_NUMA
-	if (!acpi)
-		amd = !amd_numa_init();
-#endif
-
-	initmem_init(acpi, amd);
+	initmem_init();
 	memblock_find_dma_reserve();
 	dma32_reserve_bootmem();
 
arch/x86/mm/init_64.c +1 -1
index 26e4e73..2f333d4 100644
@@ -612,7 +612,7 @@ kernel_physical_mapping_init(unsigned long start,
 }
 
 #ifndef CONFIG_NUMA
-void __init initmem_init(int acpi, int k8)
+void __init initmem_init(void)
 {
 	memblock_x86_register_active_regions(0, 0, max_pfn);
 }
arch/x86/mm/numa_64.c +15 -1
index 85561d1..4105728 100644
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/nodemask.h>
 #include <linux/sched.h>
+#include <linux/acpi.h>
 
 #include <asm/e820.h>
 #include <asm/proto.h>
@@ -578,10 +579,23 @@ static int __init numa_emulation(unsigned long start_pfn,
 }
 #endif /* CONFIG_NUMA_EMU */
 
-void __init initmem_init(int acpi, int amd)
+void __init initmem_init(void)
 {
+	int acpi = 0, amd = 0;
 	int i;
 
+#ifdef CONFIG_ACPI_NUMA
+	/*
+	 * Parse SRAT to discover nodes.
+	 */
+	acpi = !x86_acpi_numa_init();
+#endif
+
+#ifdef CONFIG_AMD_NUMA
+	if (!acpi)
+		amd = !amd_numa_init();
+#endif
+
 	nodes_clear(node_possible_map);
 	nodes_clear(node_online_map);
 
Signature · 1 line
1.7.1
#28 lore raw

Re: [PATCH 06/26] x86-64, NUMA: Move *_numa_init() invocations into initmem_init()

Hi,

Quoted 11 lines · Tejun Heo

There's no reason for these to live in setup_arch(). Move them inside initmem_init().

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
Quoted 7 lines
---
 arch/x86/include/asm/page_types.h |    2 +-
 arch/x86/kernel/setup.c           |   16 +---------------
 arch/x86/mm/init_64.c             |    2 +-
 arch/x86/mm/numa_64.c             |   16 +++++++++++++++-
 4 files changed, 18 insertions(+), 18 deletions(-)

This will break 32bits.

Signature · 5 lines
Regards,
Ankita Garg ([email protected])
Linux Technology Center
IBM India Systems & Technology Labs,
Bangalore, India
author
#29 lore raw

Re: [PATCH 06/26] x86-64, NUMA: Move *_numa_init() invocations into initmem_init()

Quoted 22 lines · Ankita Garg

Hi,

Quoted 11 lines · Tejun Heo

There's no reason for these to live in setup_arch(). Move them inside initmem_init().

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
Quoted 7 lines
---
 arch/x86/include/asm/page_types.h |    2 +-
 arch/x86/kernel/setup.c           |   16 +---------------
 arch/x86/mm/init_64.c             |    2 +-
 arch/x86/mm/numa_64.c             |   16 +++++++++++++++-
 4 files changed, 18 insertions(+), 18 deletions(-)
Quoted 1 line

This will break 32bits.

Yeap along with the previous patch. Will update 32bit accordingly.

Thanks.

Signature · 1 line
tejun
author
#30 lore raw

PATCH 6/26 x86, NUMA: Move *_numa_init() invocations into initmem_init()

In reply to Tejun Heo

There's no reason for these to live in setup_arch(). Move them inside initmem_init().

* x86-32 initmem_init() weren't updated breaking 32bit builds. Fixed.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Ankita Garg <[email protected]>

---
Updated to convert 32bit initmem_init() too. Both parameters weren't being used in 32bit versions. git tree updated accordingly.

Thanks.

 arch/x86/include/asm/page_types.h |    2 +-
 arch/x86/kernel/setup.c           |   16 +---------------
 arch/x86/mm/init_32.c             |    2 +-
 arch/x86/mm/init_64.c             |    2 +-
 arch/x86/mm/numa_32.c             |    2 +-
 arch/x86/mm/numa_64.c             |   16 +++++++++++++++-
 6 files changed, 20 insertions(+), 20 deletions(-)
arch/x86/include/asm/page_types.h +1 -1
index 95892a1..c157986 100644
@@ -48,7 +48,7 @@ extern unsigned long max_pfn_mapped;
 extern unsigned long init_memory_mapping(unsigned long start,
 					 unsigned long end);
 
-extern void initmem_init(int acpi, int k8);
+extern void initmem_init(void);
 extern void free_initmem(void);
 
 #endif	/* !__ASSEMBLY__ */
arch/x86/kernel/setup.c +1 -15
index f69d838..9907b45 100644
@@ -704,8 +704,6 @@ static u64 __init get_max_mapped(void)
 
 void __init setup_arch(char **cmdline_p)
 {
-	int acpi = 0;
-	int amd = 0;
 	unsigned long flags;
 
 #ifdef CONFIG_X86_32
@@ -984,19 +982,7 @@ void __init setup_arch(char **cmdline_p)
 
 	early_acpi_boot_init();
 
-#ifdef CONFIG_ACPI_NUMA
-	/*
-	 * Parse SRAT to discover nodes.
-	 */
-	acpi = !x86_acpi_numa_init();
-#endif
-
-#ifdef CONFIG_AMD_NUMA
-	if (!acpi)
-		amd = !amd_numa_init();
-#endif
-
-	initmem_init(acpi, amd);
+	initmem_init();
 	memblock_find_dma_reserve();
 	dma32_reserve_bootmem();
 
arch/x86/mm/init_32.c +1 -1
index 16adb66..5d43fa5 100644
@@ -644,7 +644,7 @@ void __init find_low_pfn_range(void)
 }
 
 #ifndef CONFIG_NEED_MULTIPLE_NODES
-void __init initmem_init(int acpi, int k8)
+void __init initmem_init(void)
 {
 #ifdef CONFIG_HIGHMEM
 	highstart_pfn = highend_pfn = max_pfn;
arch/x86/mm/init_64.c +1 -1
index 26e4e73..2f333d4 100644
@@ -612,7 +612,7 @@ kernel_physical_mapping_init(unsigned long start,
 }
 
 #ifndef CONFIG_NUMA
-void __init initmem_init(int acpi, int k8)
+void __init initmem_init(void)
 {
 	memblock_x86_register_active_regions(0, 0, max_pfn);
 }
arch/x86/mm/numa_32.c +1 -1
index 3249b37..bde3906 100644
@@ -352,7 +352,7 @@ static void init_remap_allocator(int nid)
 		(ulong) node_remap_end_vaddr[nid]);
 }
 
-void __init initmem_init(int acpi, int k8)
+void __init initmem_init(void)
 {
 	int nid;
 	long kva_target_pfn;
arch/x86/mm/numa_64.c +15 -1
index 85561d1..4105728 100644
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/nodemask.h>
 #include <linux/sched.h>
+#include <linux/acpi.h>
 
 #include <asm/e820.h>
 #include <asm/proto.h>
@@ -578,10 +579,23 @@ static int __init numa_emulation(unsigned long start_pfn,
 }
 #endif /* CONFIG_NUMA_EMU */
 
-void __init initmem_init(int acpi, int amd)
+void __init initmem_init(void)
 {
+	int acpi = 0, amd = 0;
 	int i;
 
+#ifdef CONFIG_ACPI_NUMA
+	/*
+	 * Parse SRAT to discover nodes.
+	 */
+	acpi = !x86_acpi_numa_init();
+#endif
+
+#ifdef CONFIG_AMD_NUMA
+	if (!acpi)
+		amd = !amd_numa_init();
+#endif
+
 	nodes_clear(node_possible_map);
 	nodes_clear(node_online_map);
 
Signature · 1 line
1.7.1
#31 lore raw

Re: [PATCH UPDATED 06/26] x86, NUMA: Move *_numa_init() invocations into initmem_init()

Quoted 14 lines · Tejun Heo

There's no reason for these to live in setup_arch(). Move them inside initmem_init().

* x86-32 initmem_init() weren't updated breaking 32bit builds. Fixed.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Ankita Garg <[email protected]>
Quoted 3 lines

---
Updated to convert 32bit initmem_init() too. Both parameters weren't being used in 32bit versions. git tree updated accordingly.

This commit is missing a:

tag.

Thanks,

Ingo

author
#32 lore raw

PATCH 7/26 x86-64, NUMA: Restructure initmem_init()

In reply to Tejun Heo

Reorganize initmem_init() such that,

* Different NUMA init methods are iterated in a consistent way.

* Each iteration re-initializes all the parameters and different method can be tried after a failure.

* Dummy init is handled the same as other methods.

Apart from how retry after failure, this patch doesn't change the behavior. The call sequences are kept equivalent across the conversion.

After the change, bad_srat() doesn't need to clear apic to node mapping or worry about numa_off. Simplified accordingly.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/mm/numa_64.c |   94 ++++++++++++++++++++++++++----------------------
 arch/x86/mm/srat_64.c |    4 +--
 2 files changed, 52 insertions(+), 46 deletions(-)
arch/x86/mm/numa_64.c +51 -43
index 4105728..ba7e5b6 100644
@@ -579,64 +579,72 @@ static int __init numa_emulation(unsigned long start_pfn,
 }
 #endif /* CONFIG_NUMA_EMU */
 
-void __init initmem_init(void)
+static int dummy_numa_init(void)
 {
-	int acpi = 0, amd = 0;
-	int i;
-
-#ifdef CONFIG_ACPI_NUMA
-	/*
-	 * Parse SRAT to discover nodes.
-	 */
-	acpi = !x86_acpi_numa_init();
-#endif
-
-#ifdef CONFIG_AMD_NUMA
-	if (!acpi)
-		amd = !amd_numa_init();
-#endif
-
-	nodes_clear(node_possible_map);
-	nodes_clear(node_online_map);
-
-#ifdef CONFIG_NUMA_EMU
-	setup_physnodes(0, max_pfn << PAGE_SHIFT, acpi, amd);
-	if (cmdline && !numa_emulation(0, max_pfn, acpi, amd))
-		return;
-	setup_physnodes(0, max_pfn << PAGE_SHIFT, acpi, amd);
-	nodes_clear(node_possible_map);
-	nodes_clear(node_online_map);
-#endif
-
-#ifdef CONFIG_ACPI_NUMA
-	if (!numa_off && acpi && !acpi_scan_nodes())
-		return;
-	nodes_clear(node_possible_map);
-	nodes_clear(node_online_map);
-#endif
+	return 0;
+}
 
-#ifdef CONFIG_AMD_NUMA
-	if (!numa_off && amd && !amd_scan_nodes())
-		return;
-	nodes_clear(node_possible_map);
-	nodes_clear(node_online_map);
-#endif
+static int dummy_scan_nodes(void)
+{
 	printk(KERN_INFO "%s\n",
 	       numa_off ? "NUMA turned off" : "No NUMA configuration found");
-
 	printk(KERN_INFO "Faking a node at %016lx-%016lx\n",
 	       0LU, max_pfn << PAGE_SHIFT);
+
 	/* setup dummy node covering all memory */
 	memnode_shift = 63;
 	memnodemap = memnode.embedded_map;
 	memnodemap[0] = 0;
 	node_set_online(0);
 	node_set(0, node_possible_map);
-	for (i = 0; i < MAX_LOCAL_APIC; i++)
-		set_apicid_to_node(i, NUMA_NO_NODE);
 	memblock_x86_register_active_regions(0, 0, max_pfn);
 	setup_node_bootmem(0, 0, max_pfn << PAGE_SHIFT);
 	numa_init_array();
+
+	return 0;
+}
+
+void __init initmem_init(void)
+{
+	int (*numa_init[])(void) = { [2] = dummy_numa_init };
+	int (*scan_nodes[])(void) = { [2] = dummy_scan_nodes };
+	int i, j;
+
+	if (!numa_off) {
+#ifdef CONFIG_ACPI_NUMA
+		numa_init[0] = x86_acpi_numa_init;
+		scan_nodes[0] = acpi_scan_nodes;
+#endif
+#ifdef CONFIG_AMD_NUMA
+		numa_init[1] = amd_numa_init;
+		scan_nodes[1] = amd_scan_nodes;
+#endif
+	}
+
+	for (i = 0; i < ARRAY_SIZE(numa_init); i++) {
+		if (!numa_init[i])
+			continue;
+
+		for (j = 0; j < MAX_LOCAL_APIC; j++)
+			set_apicid_to_node(j, NUMA_NO_NODE);
+
+		nodes_clear(node_possible_map);
+		nodes_clear(node_online_map);
+
+		if (numa_init[i]() < 0)
+			continue;
+#ifdef CONFIG_NUMA_EMU
+		setup_physnodes(0, max_pfn << PAGE_SHIFT, i == 0, i == 1);
+		if (cmdline && !numa_emulation(0, max_pfn, i == 0, i == 1))
+			return;
+		setup_physnodes(0, max_pfn << PAGE_SHIFT, i == 0, i == 1);
+		nodes_clear(node_possible_map);
+		nodes_clear(node_online_map);
+#endif
+		if (!scan_nodes[i]())
+			return;
+	}
+	BUG();
 }
 
 unsigned long __init numa_free_all_bootmem(void)
arch/x86/mm/srat_64.c +1 -3
index 8d145ae..2da8b65 100644
@@ -78,8 +78,6 @@ static __init void bad_srat(void)
 	int i;
 	printk(KERN_ERR "SRAT: SRAT not used.\n");
 	acpi_numa = -1;
-	for (i = 0; i < MAX_LOCAL_APIC; i++)
-		set_apicid_to_node(i, NUMA_NO_NODE);
 	for (i = 0; i < MAX_NUMNODES; i++) {
 		nodes[i].start = nodes[i].end = 0;
 		nodes_add[i].start = nodes_add[i].end = 0;
@@ -89,7 +87,7 @@ static __init void bad_srat(void)
 
 static __init inline int srat_disabled(void)
 {
-	return numa_off || acpi_numa < 0;
+	return acpi_numa < 0;
 }
 
 /* Callback for SLIT parsing */
Signature · 1 line
1.7.1
author
#33 lore raw

PATCH 8/26 x86-64, NUMA: Use common {cpu|mem}_nodes_parsed

In reply to Tejun Heo

ACPI and amd are using separate nodes_parsed masks. Add {cpu|mem}_nodes_parsed and use them in all NUMA init methods. Initialization of the masks and building node_possible_map are now handled commonly by initmem_init().

dummy_numa_init() is updated to set node 0 on both masks. While at it, move the info messages from scan to init.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/include/asm/numa_64.h |    3 +++
 arch/x86/mm/amdtopology_64.c   |   10 ++++------
 arch/x86/mm/numa_64.c          |   25 ++++++++++++++++++-------
 arch/x86/mm/srat_64.c          |   17 ++++++-----------
 4 files changed, 31 insertions(+), 24 deletions(-)
arch/x86/include/asm/numa_64.h +3 -0
index 2819afa..de45936 100644
@@ -27,6 +27,9 @@ extern void setup_node_bootmem(int nodeid, unsigned long start,
  */
 #define NODE_MIN_SIZE (4*1024*1024)
 
+extern nodemask_t cpu_nodes_parsed __initdata;
+extern nodemask_t mem_nodes_parsed __initdata;
+
 extern int __cpuinit numa_cpu_node(int cpu);
 
 #ifdef CONFIG_NUMA_EMU
arch/x86/mm/amdtopology_64.c +4 -6
index ee70257..3180d96 100644
@@ -28,7 +28,6 @@
 
 static struct bootnode __initdata nodes[8];
 static unsigned char __initdata nodeids[8];
-static nodemask_t __initdata nodes_parsed = NODE_MASK_NONE;
 
 static __init int find_northbridge(void)
 {
@@ -123,7 +122,7 @@ int __init amd_numa_init(void)
 			       nodeid, (base >> 8) & 3, (limit >> 8) & 3);
 			return -EINVAL;
 		}
-		if (node_isset(nodeid, nodes_parsed)) {
+		if (node_isset(nodeid, mem_nodes_parsed)) {
 			pr_info("Node %d already present, skipping\n",
 				nodeid);
 			continue;
@@ -173,7 +172,8 @@ int __init amd_numa_init(void)
 
 		prevbase = base;
 
-		node_set(nodeid, nodes_parsed);
+		node_set(nodeid, mem_nodes_parsed);
+		node_set(nodeid, cpu_nodes_parsed);
 	}
 
 	if (!found)
@@ -190,7 +190,7 @@ void __init amd_get_nodes(struct bootnode *physnodes)
 {
 	int i;
 
-	for_each_node_mask(i, nodes_parsed) {
+	for_each_node_mask(i, mem_nodes_parsed) {
 		physnodes[i].start = nodes[i].start;
 		physnodes[i].end = nodes[i].end;
 	}
@@ -258,8 +258,6 @@ int __init amd_scan_nodes(void)
 	unsigned int apicid_base;
 	int i;
 
-	BUG_ON(nodes_empty(nodes_parsed));
-	node_possible_map = nodes_parsed;
 	memnode_shift = compute_hash_shift(nodes, 8, NULL);
 	if (memnode_shift < 0) {
 		pr_err("No NUMA node hash function found. Contact maintainer\n");
arch/x86/mm/numa_64.c +18 -7
index ba7e5b6..86be8e3 100644
@@ -25,6 +25,9 @@
 struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
 EXPORT_SYMBOL(node_data);
 
+nodemask_t cpu_nodes_parsed __initdata;
+nodemask_t mem_nodes_parsed __initdata;
+
 struct memnode memnode;
 
 static unsigned long __initdata nodemap_addr;
@@ -581,22 +584,23 @@ static int __init numa_emulation(unsigned long start_pfn,
 
 static int dummy_numa_init(void)
 {
-	return 0;
-}
-
-static int dummy_scan_nodes(void)
-{
 	printk(KERN_INFO "%s\n",
 	       numa_off ? "NUMA turned off" : "No NUMA configuration found");
 	printk(KERN_INFO "Faking a node at %016lx-%016lx\n",
 	       0LU, max_pfn << PAGE_SHIFT);
 
+	node_set(0, cpu_nodes_parsed);
+	node_set(0, mem_nodes_parsed);
+
+	return 0;
+}
+
+static int dummy_scan_nodes(void)
+{
 	/* setup dummy node covering all memory */
 	memnode_shift = 63;
 	memnodemap = memnode.embedded_map;
 	memnodemap[0] = 0;
-	node_set_online(0);
-	node_set(0, node_possible_map);
 	memblock_x86_register_active_regions(0, 0, max_pfn);
 	setup_node_bootmem(0, 0, max_pfn << PAGE_SHIFT);
 	numa_init_array();
@@ -628,6 +632,8 @@ void __init initmem_init(void)
 		for (j = 0; j < MAX_LOCAL_APIC; j++)
 			set_apicid_to_node(j, NUMA_NO_NODE);
 
+		nodes_clear(cpu_nodes_parsed);
+		nodes_clear(mem_nodes_parsed);
 		nodes_clear(node_possible_map);
 		nodes_clear(node_online_map);
 
@@ -641,6 +647,11 @@ void __init initmem_init(void)
 		nodes_clear(node_possible_map);
 		nodes_clear(node_online_map);
 #endif
+		/* Account for nodes with cpus and no memory */
+		nodes_or(node_possible_map, mem_nodes_parsed, cpu_nodes_parsed);
+		if (WARN_ON(nodes_empty(node_possible_map)))
+			continue;
+
 		if (!scan_nodes[i]())
 			return;
 	}
arch/x86/mm/srat_64.c +6 -11
index 2da8b65..822bd68 100644
@@ -28,8 +28,6 @@ int acpi_numa __initdata;
 
 static struct acpi_table_slit *acpi_slit;
 
-static nodemask_t nodes_parsed __initdata;
-static nodemask_t cpu_nodes_parsed __initdata;
 static struct bootnode nodes[MAX_NUMNODES] __initdata;
 static struct bootnode nodes_add[MAX_NUMNODES];
 
@@ -293,7 +291,7 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
 
 	if (!(ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)) {
 		nd = &nodes[node];
-		if (!node_test_and_set(node, nodes_parsed)) {
+		if (!node_test_and_set(node, mem_nodes_parsed)) {
 			nd->start = start;
 			nd->end = end;
 		} else {
@@ -319,7 +317,7 @@ static int __init nodes_cover_memory(const struct bootnode *nodes)
 	unsigned long pxmram, e820ram;
 
 	pxmram = 0;
-	for_each_node_mask(i, nodes_parsed) {
+	for_each_node_mask(i, mem_nodes_parsed) {
 		unsigned long s = nodes[i].start >> PAGE_SHIFT;
 		unsigned long e = nodes[i].end >> PAGE_SHIFT;
 		pxmram += e - s;
@@ -348,7 +346,7 @@ void __init acpi_get_nodes(struct bootnode *physnodes, unsigned long start,
 {
 	int i;
 
-	for_each_node_mask(i, nodes_parsed) {
+	for_each_node_mask(i, mem_nodes_parsed) {
 		cutoff_node(i, start, end);
 		physnodes[i].start = nodes[i].start;
 		physnodes[i].end = nodes[i].end;
@@ -447,9 +445,6 @@ int __init acpi_scan_nodes(void)
 		return -1;
 	}
 
-	/* Account for nodes with cpus and no memory */
-	nodes_or(node_possible_map, nodes_parsed, cpu_nodes_parsed);
-
 	/* Finally register nodes */
 	for_each_node_mask(i, node_possible_map)
 		setup_node_bootmem(i, nodes[i].start, nodes[i].end);
@@ -483,7 +478,7 @@ static int __init find_node_by_addr(unsigned long addr)
 	int ret = NUMA_NO_NODE;
 	int i;
 
-	for_each_node_mask(i, nodes_parsed) {
+	for_each_node_mask(i, mem_nodes_parsed) {
 		/*
 		 * Find the real node that this emulated node appears on.  For
 		 * the sake of simplicity, we only use a real node's starting
@@ -543,10 +538,10 @@ void __init acpi_fake_nodes(const struct bootnode *fake_nodes, int num_nodes)
 		__acpi_map_pxm_to_node(fake_node_to_pxm_map[i], i);
 	memcpy(__apicid_to_node, fake_apicid_to_node, sizeof(__apicid_to_node));
 
-	nodes_clear(nodes_parsed);
+	nodes_clear(mem_nodes_parsed);
 	for (i = 0; i < num_nodes; i++)
 		if (fake_nodes[i].start != fake_nodes[i].end)
-			node_set(i, nodes_parsed);
+			node_set(i, mem_nodes_parsed);
 }
 
 static int null_slit_node_compare(int a, int b)
Signature · 1 line
1.7.1
author
#34 lore raw

PATCH 9/26 x86-64, NUMA: Remove local variable found from amd_numa_init()

In reply to Tejun Heo

Use weight count on mem_nodes_parsed instead.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/mm/amdtopology_64.c |    6 ++----
 1 files changed, 2 insertions(+), 4 deletions(-)
arch/x86/mm/amdtopology_64.c +2 -4
index 3180d96..c5eddfa 100644
@@ -74,7 +74,7 @@ int __init amd_numa_init(void)
 	unsigned long end = PFN_PHYS(max_pfn);
 	unsigned numnodes;
 	unsigned long prevbase;
-	int i, nb, found = 0;
+	int i, nb;
 	u32 nodeid, reg;
 
 	if (!early_pci_allowed())
@@ -165,8 +165,6 @@ int __init amd_numa_init(void)
 		pr_info("Node %d MemBase %016lx Limit %016lx\n",
 			nodeid, base, limit);
 
-		found++;
-
 		nodes[nodeid].start = base;
 		nodes[nodeid].end = limit;
 
@@ -176,7 +174,7 @@ int __init amd_numa_init(void)
 		node_set(nodeid, cpu_nodes_parsed);
 	}
 
-	if (!found)
+	if (!nodes_weight(mem_nodes_parsed))
 		return -ENOENT;
 	return 0;
 }
Signature · 1 line
1.7.1
author
#35 lore raw

PATCH 10/26 x86-64, NUMA: Move apicid to numa mapping initialization from amd_scan_nodes() to amd_numa_init()

In reply to Tejun Heo

This brings amd initialization behavior closer to that of acpi.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/mm/amdtopology_64.c |   40 ++++++++++++++++++++++------------------
 1 files changed, 22 insertions(+), 18 deletions(-)
arch/x86/mm/amdtopology_64.c +22 -18
index c5eddfa..4056333 100644
@@ -74,8 +74,9 @@ int __init amd_numa_init(void)
 	unsigned long end = PFN_PHYS(max_pfn);
 	unsigned numnodes;
 	unsigned long prevbase;
-	int i, nb;
+	int i, j, nb;
 	u32 nodeid, reg;
+	unsigned int bits, cores, apicid_base;
 
 	if (!early_pci_allowed())
 		return -EINVAL;
@@ -176,6 +177,26 @@ int __init amd_numa_init(void)
 
 	if (!nodes_weight(mem_nodes_parsed))
 		return -ENOENT;
+
+	/*
+	 * We seem to have valid NUMA configuration.  Map apicids to nodes
+	 * using the coreid bits from early_identify_cpu.
+	 */
+	bits = boot_cpu_data.x86_coreid_bits;
+	cores = 1 << bits;
+	apicid_base = 0;
+
+	/* get the APIC ID of the BSP early for systems with apicid lifting */
+	early_get_boot_cpu_id();
+	if (boot_cpu_physical_apicid > 0) {
+		pr_info("BSP APIC ID: %02x\n", boot_cpu_physical_apicid);
+		apicid_base = boot_cpu_physical_apicid;
+	}
+
+	for_each_node_mask(i, cpu_nodes_parsed)
+		for (j = apicid_base; j < cores + apicid_base; j++)
+			set_apicid_to_node((i << bits) + j, i);
+
 	return 0;
 }
 
@@ -251,9 +272,6 @@ void __init amd_fake_nodes(const struct bootnode *nodes, int nr_nodes)
 
 int __init amd_scan_nodes(void)
 {
-	unsigned int bits;
-	unsigned int cores;
-	unsigned int apicid_base;
 	int i;
 
 	memnode_shift = compute_hash_shift(nodes, 8, NULL);
@@ -264,24 +282,10 @@ int __init amd_scan_nodes(void)
 	pr_info("Using node hash shift of %d\n", memnode_shift);
 
 	/* use the coreid bits from early_identify_cpu */
-	bits = boot_cpu_data.x86_coreid_bits;
-	cores = (1<<bits);
-	apicid_base = 0;
-	/* get the APIC ID of the BSP early for systems with apicid lifting */
-	early_get_boot_cpu_id();
-	if (boot_cpu_physical_apicid > 0) {
-		pr_info("BSP APIC ID: %02x\n", boot_cpu_physical_apicid);
-		apicid_base = boot_cpu_physical_apicid;
-	}
-
 	for_each_node_mask(i, node_possible_map) {
-		int j;
-
 		memblock_x86_register_active_regions(i,
 				nodes[i].start >> PAGE_SHIFT,
 				nodes[i].end >> PAGE_SHIFT);
-		for (j = apicid_base; j < cores + apicid_base; j++)
-			set_apicid_to_node((i << bits) + j, i);
 		setup_node_bootmem(i, nodes[i].start, nodes[i].end);
 	}
 
Signature · 1 line
1.7.1
#36 lore raw

Re: [PATCH 10/26] x86-64, NUMA: Move apicid to numa mapping initialization from amd_scan_nodes() to amd_numa_init()

Quoted 37 lines · Tejun Heo

This brings amd initialization behavior closer to that of acpi.

Cc Yinghai Lu<[email protected]>
Cc Brian Gerst<[email protected]>
Cc Cyrill Gorcunov<[email protected]>
Cc Shaohui Zheng<[email protected]>
Cc David Rientjes<[email protected]>
Cc Ingo Molnar<[email protected]>
Cc H. Peter Anvin<[email protected]>
---
  arch/x86/mm/amdtopology_64.c |   40 ++++++++++++++++++++++------------------
  1 files changed, 22 insertions(+), 18 deletions(-)
arch/x86/mm/amdtopology_64.c +6 -1
index c5eddfa..4056333 100644
@@ -74,8 +74,9 @@ int __init amd_numa_init(void)
  	unsigned long end = PFN_PHYS(max_pfn);
  	unsigned numnodes;
  	unsigned long prevbase;
-	int i, nb;
+	int i, j, nb;
  	u32 nodeid, reg;
+	unsigned int bits, cores, apicid_base;
 
  	if (!early_pci_allowed())
  		return -EINVAL;
@@ -176,6 +177,26 @@ int __init amd_numa_init(void)
 
  	if (!nodes_weight(mem_nodes_parsed))
  		return -ENOENT;
+
+	/*
+	 * We seem to have valid NUMA configuration.  Map apicids to nodes
+	 * using the coreid bits from early_identify_cpu.

arch/x86/mm/amdtopology_64.c int __init amd_numa_init(void) · line 193

Quoted 10 lines
arch/x86/mm/amdtopology_64.c +10 -0
+	 */
+	bits = boot_cpu_data.x86_coreid_bits;
+	cores = 1<<  bits;
+	apicid_base = 0;
+
+	/* get the APIC ID of the BSP early for systems with apicid lifting */
+	early_get_boot_cpu_id();
+	if (boot_cpu_physical_apicid>  0) {
+		pr_info("BSP APIC ID: %02x\n", boot_cpu_physical_apicid);
+		apicid_base = boot_cpu_physical_apicid;
		^^^

arch/x86/mm/amdtopology_64.c int __init amd_numa_init(void) · line 202

Quoted 9 lines
arch/x86/mm/amdtopology_64.c +6 -0
+	}
+
+	for_each_node_mask(i, cpu_nodes_parsed)
+		for (j = apicid_base; j<  cores + apicid_base; j++)
+			set_apicid_to_node((i<<  bits) + j, i);
+
  	return 0;
  }
 

Hi Tejun, while you at it, it seems apicid_base conditional assignment is
redundant here (boot_cpu_physical_apicid is unsigned int) so we might have something like

	apicid_start	= boot_cpu_physical_apicid;
	apicid_end	= apicid_start + cores;

	for_each_node_mask(i, cpu_nodes_parsed) {
		for (j = apicid_start; j <  apicid_end; j++)
			set_apicid_to_node((i <<  bits) + j, i);
	}

But of course it should be considered as followup update just to not
mess the things. (probably need to check if we ever may reach this point with boot_cpu_physical_apicid = -1U). Just a thought.

Signature · 1 line
    Cyrill
author
#37 lore raw

Re: [PATCH 10/26] x86-64, NUMA: Move apicid to numa mapping initialization from amd_scan_nodes() to amd_numa_init()

Hello, Cyrill.

Quoted 20 lines · Cyrill Gorcunov

arch/x86/mm/amdtopology_64.c int __init amd_numa_init(void) · line 193

Quoted 5 lines
arch/x86/mm/amdtopology_64.c +5 -0
+	/* get the APIC ID of the BSP early for systems with apicid lifting */
+	early_get_boot_cpu_id();
+	if (boot_cpu_physical_apicid>  0) {
+		pr_info("BSP APIC ID: %02x\n", boot_cpu_physical_apicid);
+		apicid_base = boot_cpu_physical_apicid;
		^^^

arch/x86/mm/amdtopology_64.c int __init amd_numa_init(void) · line 201

Quoted 9 lines
arch/x86/mm/amdtopology_64.c +6 -0
+	}
+
+	for_each_node_mask(i, cpu_nodes_parsed)
+		for (j = apicid_base; j<  cores + apicid_base; j++)
+			set_apicid_to_node((i<<  bits) + j, i);
+
 	return 0;
 }

Hi Tejun, while you at it, it seems apicid_base conditional assignment is
redundant here (boot_cpu_physical_apicid is unsigned int) so we might have something like

Quoted 7 lines
	apicid_start	= boot_cpu_physical_apicid;
	apicid_end	= apicid_start + cores;

	for_each_node_mask(i, cpu_nodes_parsed) {
		for (j = apicid_start; j <  apicid_end; j++)
			set_apicid_to_node((i <<  bits) + j, i);
	}

Right, I think the intention there was

	if (boot_cpu_physical_apicid == -1U)

because that's the initial value and we don't really want to index the apicid nid table with -1U. Care to send a patch? I'm gonna have to rebase anyway and can put the patch at the front.

Thanks.

Signature · 1 line
tejun
#38 lore raw

Re: [PATCH 10/26] x86-64, NUMA: Move apicid to numa mapping initialization from amd_scan_nodes() to amd_numa_init()

On 02/15/2011 12:36 PM, Tejun Heo wrote:
...

Quoted 15 lines
Quoted 5 lines

Hi Tejun, while you at it, it seems apicid_base conditional assignment is
redundant here (boot_cpu_physical_apicid is unsigned int) so we might have something like

Quoted 7 lines
	apicid_start	= boot_cpu_physical_apicid;
	apicid_end	= apicid_start + cores;

	for_each_node_mask(i, cpu_nodes_parsed) {
		for (j = apicid_start; j<   apicid_end; j++)
			set_apicid_to_node((i<<   bits) + j, i);
	}

Right, I think the intention there was

Quoted 8 lines
	if (boot_cpu_physical_apicid == -1U)

because that's the initial value and we don't really want to index the apicid nid table with -1U. Care to send a patch? I'm gonna have to rebase anyway and can put the patch at the front.

Thanks.

Hi Tejun again :) I've looked some more and if I'm not missing something
(Yinghai?) the code is broken in another way. We might have AMD system with corrupted MADT table so boot_cpu_physical_apicid remains =-1U and then we better BUG_ON instead of possible access of out-of-range __apicid_to_node array. If MADT is parsed successfully boot_cpu_physical_apicid will have correct value. So I think we rather should add something like the patch below. Again better Yinghai check it first so I would not _miss_ the point that such situation is impossible at all. (And if I'm right we need to check for set_apicid_to_node(apicid, ) never exceed MAX_LOCAL_APIC as well.

Yinghai am I missing something?

Signature · 35 lines
    Cyrill

---
x86, numa: amd -- Check for screwed MADT table

In case if MADT table is corrupted we might end up
with boot_cpu_physical_apicid = -1U, corebits > 0 and
get out of __apicid_to_node array bound access. Check for
boot_cpu_physical_apicid being not default value.

Signed-off-by: Cyrill Gorcunov <[email protected]>
---
 arch/x86/mm/amdtopology_64.c |    7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

Index: linux-2.6.git/arch/x86/mm/amdtopology_64.c
=====================================================================
--- linux-2.6.git.orig/arch/x86/mm/amdtopology_64.c
+++ linux-2.6.git/arch/x86/mm/amdtopology_64.c
@@ -271,9 +271,14 @@ int __init amd_scan_nodes(void)
 	bits = boot_cpu_data.x86_coreid_bits;
 	cores = (1<<bits);
 	apicid_base = 0;
+
 	/* get the APIC ID of the BSP early for systems with apicid lifting */
 	early_get_boot_cpu_id();
-	if (boot_cpu_physical_apicid > 0) {
+	if (boot_cpu_physical_apicid == -1U || ) {
+		pr_err("BAD APIC ID: %02x, NUMA node scaning canceled\n",
+			boot_cpu_physical_apicid);
+		return -1;
+	} else if (boot_cpu_physical_apicid > 0) {
 		pr_info("BSP APIC ID: %02x\n", boot_cpu_physical_apicid);
 		apicid_base = boot_cpu_physical_apicid;
 	}
#39 lore raw

Re: [PATCH 10/26] x86-64, NUMA: Move apicid to numa mapping initialization from amd_scan_nodes() to amd_numa_init()

Quoted 77 lines · Cyrill Gorcunov

On 02/15/2011 12:36 PM, Tejun Heo wrote:
...

Quoted 17 lines
Quoted 7 lines

  Hi Tejun, while you at it, it seems apicid_base conditional assignment is
redundant here (boot_cpu_physical_apicid is unsigned int) so we might have
something like

Quoted 7 lines

       apicid_start    = boot_cpu_physical_apicid; apicid_end      = apicid_start + cores;

       for_each_node_mask(i, cpu_nodes_parsed) {
               for (j = apicid_start; j<   apicid_end; j++) set_apicid_to_node((i<<   bits) + j, i); }

Right, I think the intention there was

Quoted 8 lines

       if (boot_cpu_physical_apicid == -1U)

because that's the initial value and we don't really want to index the apicid nid table with -1U.  Care to send a patch?  I'm gonna have to rebase anyway and can put the patch at the front.

Thanks.

 Hi Tejun again :) I've looked some more and if I'm not missing something (Yinghai?) the code is broken in another way. We might have AMD system with corrupted MADT table so boot_cpu_physical_apicid remains =-1U and then we better BUG_ON instead of possible access of out-of-range __apicid_to_node array. If MADT is parsed successfully boot_cpu_physical_apicid
will have correct value. So I think we rather should add something like the patch below. Again better Yinghai check it first so I would not _miss_ the point that such situation is impossible at all. (And if I'm right we need to check for set_apicid_to_node(apicid, ) never exceed MAX_LOCAL_APIC as well.

Yinghai am I missing something?

--
   Cyrill

---
x86, numa: amd -- Check for screwed MADT table

In case if MADT table is corrupted we might end up with boot_cpu_physical_apicid = -1U, corebits > 0 and get out of __apicid_to_node array bound access. Check for boot_cpu_physical_apicid being not default value.

---
 arch/x86/mm/amdtopology_64.c |    7 ++++++-

 1 file changed, 6 insertions(+), 1 deletion(-)

Index: linux-2.6.git/arch/x86/mm/amdtopology_64.c
=====================================================================

arch/x86/mm/amdtopology_64.c +6 -1
@@ -271,9 +271,14 @@ int __init amd_scan_nodes(void)
        bits = boot_cpu_data.x86_coreid_bits;
        cores = (1<<bits);
        apicid_base = 0;
+
        /* get the APIC ID of the BSP early for systems with apicid lifting
 */
        early_get_boot_cpu_id();
-       if (boot_cpu_physical_apicid > 0) {
+       if (boot_cpu_physical_apicid == -1U || ) {
+               pr_err("BAD APIC ID: %02x, NUMA node scaning canceled\n",
+                       boot_cpu_physical_apicid);
+               return -1;
+       } else if (boot_cpu_physical_apicid > 0) {
                pr_info("BSP APIC ID: %02x\n", boot_cpu_physical_apicid);
                apicid_base = boot_cpu_physical_apicid;
Quoted 1 line

       }

could just change

- if (boot_cpu_physical_apicid > 0) {

 +       if (boot_cpu_physical_apicid != -1U) {
                pr_info("BSP APIC ID: %02x\n", boot_cpu_physical_apicid);
                apicid_base = boot_cpu_physical_apicid;
        }

Thanks

Yinghai

#40 lore raw

Re: [PATCH 10/26] x86-64, NUMA: Move apicid to numa mapping initialization from amd_scan_nodes() to amd_numa_init()

On 02/15/2011 08:54 PM, Yinghai Lu wrote:
...

Quoted 9 lines

could just change

  -       if (boot_cpu_physical_apicid>  0) {
  +       if (boot_cpu_physical_apicid != -1U) {
                 pr_info("BSP APIC ID: %02x\n", boot_cpu_physical_apicid);
                 apicid_base = boot_cpu_physical_apicid;
         }
Quoted 3 lines

Thanks

Yinghai

yup, that is exactly what Tejun suggested in first place ;) I'll update to this form and add your Acked-by then, ok?

Signature · 1 line
    Cyrill
#41 lore raw

Re: [PATCH 10/26] x86-64, NUMA: Move apicid to numa mapping initialization from amd_scan_nodes() to amd_numa_init()

Quoted 11 lines · Cyrill Gorcunov

On 02/15/2011 08:54 PM, Yinghai Lu wrote:
...

Quoted 9 lines

could just change

- if (boot_cpu_physical_apicid> 0) {
+ if (boot_cpu_physical_apicid != -1U) { pr_info("BSP APIC ID: %02x\n", boot_cpu_physical_apicid); apicid_base = boot_cpu_physical_apicid;
}

Quoted 7 lines
Quoted 3 lines

Thanks

Yinghai

yup, that is exactly what Tejun suggested in first place ;) I'll update to this form and add your Acked-by then, ok?

Tejun I've updated it on top of your tj-numa/x86_64-numa-unify branch and added Acks.

Signature · 37 lines
x86, numa: amd -- Check for screwed MADT table

In case if MADT table is corrupted we might end up
with boot_cpu_physical_apicid = -1U, corebits > 0 and
get out of __apicid_to_node array bound access. Check for
boot_cpu_physical_apicid being a sane value.

Signed-off-by: Cyrill Gorcunov <[email protected]>
Acked-by: Tejun Heo <[email protected]>
Acked-by: Yinghai Lu <[email protected]>
---
 arch/x86/mm/amdtopology_64.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

Index: linux-2.6.git/arch/x86/mm/amdtopology_64.c
=====================================================================
--- linux-2.6.git.orig/arch/x86/mm/amdtopology_64.c
+++ linux-2.6.git/arch/x86/mm/amdtopology_64.c
@@ -212,14 +212,16 @@ void __init amd_fake_nodes(const struct
 {
 	unsigned int bits;
 	unsigned int cores;
-	unsigned int apicid_base = 0;
+	unsigned int apicid_base;
 	int i;

 	bits = boot_cpu_data.x86_coreid_bits;
 	cores = 1 << bits;
 	early_get_boot_cpu_id();
-	if (boot_cpu_physical_apicid > 0)
+	if (boot_cpu_physical_apicid != -1U)
 		apicid_base = boot_cpu_physical_apicid;
+	else
+		apicid_base = 0;

 	for (i = 0; i < nr_nodes; i++) {
 		int index;
#42 lore raw

Re: [PATCH 10/26] x86-64, NUMA: Move apicid to numa mapping initialization from amd_scan_nodes() to amd_numa_init()

In reply to Cyrill Gorcunov
Quoted 12 lines · Cyrill Gorcunov

On 02/15/2011 08:54 PM, Yinghai Lu wrote:
...

Quoted 10 lines

could just change

- if (boot_cpu_physical_apicid> 0) {

  +       if (boot_cpu_physical_apicid != -1U) {
                 pr_info("BSP APIC ID: %02x\n",
boot_cpu_physical_apicid);
                 apicid_base = boot_cpu_physical_apicid;
         }
Quoted 7 lines
Quoted 3 lines

Thanks

Yinghai

yup, that is exactly what Tejun suggested in first place ;) I'll update to this form and add your Acked-by then, ok?

yes.

Thanks

author
#43 lore raw

PATCH 11/26 x86-64, NUMA: Use common numa_nodes[]

In reply to Tejun Heo

ACPI and amd are using separate nodes[] array. Add numa_nodes[] and use them in all NUMA init methods. cutoff_node() cleanup is moved from srat_64.c to numa_64.c and applied in initmem_init() regardless of init methods.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/include/asm/numa_64.h |    1 +
 arch/x86/mm/amdtopology_64.c   |   19 ++++++++---------
 arch/x86/mm/numa_64.c          |   24 ++++++++++++++++++++++
 arch/x86/mm/srat_64.c          |   43 ++++++++++-----------------------------
 4 files changed, 45 insertions(+), 42 deletions(-)
arch/x86/include/asm/numa_64.h +1 -0
index de45936..d3a4514 100644
@@ -29,6 +29,7 @@ extern void setup_node_bootmem(int nodeid, unsigned long start,
 
 extern nodemask_t cpu_nodes_parsed __initdata;
 extern nodemask_t mem_nodes_parsed __initdata;
+extern struct bootnode numa_nodes[MAX_NUMNODES] __initdata;
 
 extern int __cpuinit numa_cpu_node(int cpu);
 
arch/x86/mm/amdtopology_64.c +9 -10
index 4056333..06698b1 100644
@@ -26,7 +26,6 @@
 #include <asm/apic.h>
 #include <asm/amd_nb.h>
 
-static struct bootnode __initdata nodes[8];
 static unsigned char __initdata nodeids[8];
 
 static __init int find_northbridge(void)
@@ -166,8 +165,8 @@ int __init amd_numa_init(void)
 		pr_info("Node %d MemBase %016lx Limit %016lx\n",
 			nodeid, base, limit);
 
-		nodes[nodeid].start = base;
-		nodes[nodeid].end = limit;
+		numa_nodes[nodeid].start = base;
+		numa_nodes[nodeid].end = limit;
 
 		prevbase = base;
 
@@ -210,8 +209,8 @@ void __init amd_get_nodes(struct bootnode *physnodes)
 	int i;
 
 	for_each_node_mask(i, mem_nodes_parsed) {
-		physnodes[i].start = nodes[i].start;
-		physnodes[i].end = nodes[i].end;
+		physnodes[i].start = numa_nodes[i].start;
+		physnodes[i].end = numa_nodes[i].end;
 	}
 }
 
@@ -221,7 +220,7 @@ static int __init find_node_by_addr(unsigned long addr)
 	int i;
 
 	for (i = 0; i < 8; i++)
-		if (addr >= nodes[i].start && addr < nodes[i].end) {
+		if (addr >= numa_nodes[i].start && addr < numa_nodes[i].end) {
 			ret = i;
 			break;
 		}
@@ -274,7 +273,7 @@ int __init amd_scan_nodes(void)
 {
 	int i;
 
-	memnode_shift = compute_hash_shift(nodes, 8, NULL);
+	memnode_shift = compute_hash_shift(numa_nodes, 8, NULL);
 	if (memnode_shift < 0) {
 		pr_err("No NUMA node hash function found. Contact maintainer\n");
 		return -1;
@@ -284,9 +283,9 @@ int __init amd_scan_nodes(void)
 	/* use the coreid bits from early_identify_cpu */
 	for_each_node_mask(i, node_possible_map) {
 		memblock_x86_register_active_regions(i,
-				nodes[i].start >> PAGE_SHIFT,
-				nodes[i].end >> PAGE_SHIFT);
-		setup_node_bootmem(i, nodes[i].start, nodes[i].end);
+				numa_nodes[i].start >> PAGE_SHIFT,
+				numa_nodes[i].end >> PAGE_SHIFT);
+		setup_node_bootmem(i, numa_nodes[i].start, numa_nodes[i].end);
 	}
 
 	numa_init_array();
arch/x86/mm/numa_64.c +24 -0
index 86be8e3..a0bceaa 100644
@@ -33,6 +33,8 @@ struct memnode memnode;
 static unsigned long __initdata nodemap_addr;
 static unsigned long __initdata nodemap_size;
 
+struct bootnode numa_nodes[MAX_NUMNODES] __initdata;
+
 /*
  * Given a shift value, try to populate memnodemap[]
  * Returns :
@@ -182,6 +184,22 @@ static void * __init early_node_mem(int nodeid, unsigned long start,
 	return NULL;
 }
 
+static __init void cutoff_node(int i, unsigned long start, unsigned long end)
+{
+	struct bootnode *nd = &numa_nodes[i];
+
+	if (nd->start < start) {
+		nd->start = start;
+		if (nd->end < nd->start)
+			nd->start = nd->end;
+	}
+	if (nd->end > end) {
+		nd->end = end;
+		if (nd->start > nd->end)
+			nd->start = nd->end;
+	}
+}
+
 /* Initialize bootmem allocator for a node */
 void __init
 setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)
@@ -636,9 +654,15 @@ void __init initmem_init(void)
 		nodes_clear(mem_nodes_parsed);
 		nodes_clear(node_possible_map);
 		nodes_clear(node_online_map);
+		memset(numa_nodes, 0, sizeof(numa_nodes));
 
 		if (numa_init[i]() < 0)
 			continue;
+
+		/* clean up the node list */
+		for (j = 0; j < MAX_NUMNODES; j++)
+			cutoff_node(j, 0, max_pfn << PAGE_SHIFT);
+
 #ifdef CONFIG_NUMA_EMU
 		setup_physnodes(0, max_pfn << PAGE_SHIFT, i == 0, i == 1);
 		if (cmdline && !numa_emulation(0, max_pfn, i == 0, i == 1))
arch/x86/mm/srat_64.c +11 -32

111 lines not on this page · raw message

Signature · 1 line
1.7.1
author
#44 lore raw

PATCH 12/26 x86-64, NUMA: Kill {acpi|amd}_get_nodes()

In reply to Tejun Heo

With common numa_nodes[], common code in numa_64.c can access it directly. Copy directly and kill {acpi|amd}_get_nodes().

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/include/asm/acpi.h   |    2 --
 arch/x86/include/asm/amd_nb.h |    1 -
 arch/x86/mm/amdtopology_64.c  |   10 ----------
 arch/x86/mm/numa_64.c         |   23 ++++++++++-------------
 arch/x86/mm/srat_64.c         |   13 -------------
 5 files changed, 10 insertions(+), 39 deletions(-)
arch/x86/include/asm/acpi.h +0 -2
index 06fb786..446a5b9 100644
@@ -185,8 +185,6 @@ struct bootnode;
 
 #ifdef CONFIG_ACPI_NUMA
 extern int acpi_numa;
-extern void acpi_get_nodes(struct bootnode *physnodes, unsigned long start,
-				unsigned long end);
 extern int x86_acpi_numa_init(void);
 extern int acpi_scan_nodes(void);
 #define NR_NODE_MEMBLKS (MAX_NUMNODES*2)
arch/x86/include/asm/amd_nb.h +0 -1
index 72abf65..765966f 100644
@@ -21,7 +21,6 @@ extern int amd_scan_nodes(void);
 
 #ifdef CONFIG_NUMA_EMU
 extern void amd_fake_nodes(const struct bootnode *nodes, int nr_nodes);
-extern void amd_get_nodes(struct bootnode *nodes);
 #endif
 
 struct amd_northbridge {
arch/x86/mm/amdtopology_64.c +0 -10
index 06698b1..fe93e23 100644
@@ -204,16 +204,6 @@ static s16 fake_apicid_to_node[MAX_LOCAL_APIC] __initdata = {
 	[0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE
 };
 
-void __init amd_get_nodes(struct bootnode *physnodes)
-{
-	int i;
-
-	for_each_node_mask(i, mem_nodes_parsed) {
-		physnodes[i].start = numa_nodes[i].start;
-		physnodes[i].end = numa_nodes[i].end;
-	}
-}
-
 static int __init find_node_by_addr(unsigned long addr)
 {
 	int ret = NUMA_NO_NODE;
arch/x86/mm/numa_64.c +10 -13
index a0bceaa..2d3ee2f 100644
@@ -257,21 +257,18 @@ void __init numa_emu_cmdline(char *str)
 	cmdline = str;
 }
 
-static int __init setup_physnodes(unsigned long start, unsigned long end,
-					int acpi, int amd)
+static int __init setup_physnodes(unsigned long start, unsigned long end)
 {
 	int ret = 0;
 	int i;
 
 	memset(physnodes, 0, sizeof(physnodes));
-#ifdef CONFIG_ACPI_NUMA
-	if (acpi)
-		acpi_get_nodes(physnodes, start, end);
-#endif
-#ifdef CONFIG_AMD_NUMA
-	if (amd)
-		amd_get_nodes(physnodes);
-#endif
+
+	for_each_node_mask(i, mem_nodes_parsed) {
+		physnodes[i].start = numa_nodes[i].start;
+		physnodes[i].end = numa_nodes[i].end;
+	}
+
 	/*
 	 * Basic sanity checking on the physical node map: there may be errors
 	 * if the SRAT or AMD code incorrectly reported the topology or the mem=
@@ -593,7 +590,7 @@ static int __init numa_emulation(unsigned long start_pfn,
 						nodes[i].end >> PAGE_SHIFT);
 		setup_node_bootmem(i, nodes[i].start, nodes[i].end);
 	}
-	setup_physnodes(addr, max_addr, acpi, amd);
+	setup_physnodes(addr, max_addr);
 	fake_physnodes(acpi, amd, num_nodes);
 	numa_init_array();
 	return 0;
@@ -664,10 +661,10 @@ void __init initmem_init(void)
 			cutoff_node(j, 0, max_pfn << PAGE_SHIFT);
 
 #ifdef CONFIG_NUMA_EMU
-		setup_physnodes(0, max_pfn << PAGE_SHIFT, i == 0, i == 1);
+		setup_physnodes(0, max_pfn << PAGE_SHIFT);
 		if (cmdline && !numa_emulation(0, max_pfn, i == 0, i == 1))
 			return;
-		setup_physnodes(0, max_pfn << PAGE_SHIFT, i == 0, i == 1);
+		setup_physnodes(0, max_pfn << PAGE_SHIFT);
 		nodes_clear(node_possible_map);
 		nodes_clear(node_online_map);
 #endif
arch/x86/mm/srat_64.c +0 -13
index abb17d6..d84c983 100644
@@ -323,19 +323,6 @@ static int __init nodes_cover_memory(const struct bootnode *nodes)
 
 void __init acpi_numa_arch_fixup(void) {}
 
-#ifdef CONFIG_NUMA_EMU
-void __init acpi_get_nodes(struct bootnode *physnodes, unsigned long start,
-				unsigned long end)
-{
-	int i;
-
-	for_each_node_mask(i, mem_nodes_parsed) {
-		physnodes[i].start = numa_nodes[i].start;
-		physnodes[i].end = numa_nodes[i].end;
-	}
-}
-#endif /* CONFIG_NUMA_EMU */
-
 int __init x86_acpi_numa_init(void)
 {
 	int ret;
Signature · 1 line
1.7.1
author
#45 lore raw

PATCH 13/26 x86-64, NUMA: Factor out memblk handling into numa_{add|register}_memblk()

In reply to Tejun Heo

Factor out memblk handling from srat_64.c into two functions in numa_64.c. This patch doesn't introduce any behavior change. The next patch will make all init methods use these functions.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/include/asm/acpi.h    |    1 -
 arch/x86/include/asm/numa_64.h |    5 ++-
 arch/x86/mm/numa_64.c          |  109 ++++++++++++++++++++++++++++++++++++++++
 arch/x86/mm/srat_64.c          |   96 +----------------------------------
 4 files changed, 116 insertions(+), 95 deletions(-)
arch/x86/include/asm/acpi.h +0 -1
index 446a5b9..12bd1fd 100644
@@ -187,7 +187,6 @@ struct bootnode;
 extern int acpi_numa;
 extern int x86_acpi_numa_init(void);
 extern int acpi_scan_nodes(void);
-#define NR_NODE_MEMBLKS (MAX_NUMNODES*2)
 
 #ifdef CONFIG_NUMA_EMU
 extern void acpi_fake_nodes(const struct bootnode *fake_nodes,
arch/x86/include/asm/numa_64.h +4 -1
index d3a4514..2b6a1c5 100644
@@ -25,13 +25,16 @@ extern void setup_node_bootmem(int nodeid, unsigned long start,
  * result from BIOS bugs. So dont recognize nodes as standalone
  * NUMA entities that have less than this amount of RAM listed:
  */
-#define NODE_MIN_SIZE (4*1024*1024)
+#define NODE_MIN_SIZE		(4*1024*1024)
+#define NR_NODE_MEMBLKS		(MAX_NUMNODES*2)
 
 extern nodemask_t cpu_nodes_parsed __initdata;
 extern nodemask_t mem_nodes_parsed __initdata;
 extern struct bootnode numa_nodes[MAX_NUMNODES] __initdata;
 
 extern int __cpuinit numa_cpu_node(int cpu);
+extern int __init numa_add_memblk(int nodeid, u64 start, u64 end);
+extern int __init numa_register_memblks(void);
 
 #ifdef CONFIG_NUMA_EMU
 #define FAKE_NODE_MIN_SIZE	((u64)32 << 20)
arch/x86/mm/numa_64.c +109 -0

133 lines not on this page · raw message

arch/x86/mm/srat_64.c +3 -93

135 lines not on this page · raw message

Signature · 1 line
1.7.1
author
#46 lore raw

PATCH 14/26 x86-64, NUMA: Unify use of memblk in all init methods

In reply to Tejun Heo

Make both amd and dummy use numa_add_memblk() to describe the detected memory blocks. This allows initmem_init() to call numa_register_memblk() regardless of init method in use. Drop custom memory registration codes from amd and dummy.

After this change, memblk merge/cleanup in numa_register_memblks() is applied to all init methods.

As this makes compute_hash_shift() and numa_register_memblks() used only inside numa_64.c, make them static.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/include/asm/numa_64.h |    4 ----
 arch/x86/mm/amdtopology_64.c   |   15 ++-------------
 arch/x86/mm/numa_64.c          |   15 +++++++--------
 arch/x86/mm/srat_64.c          |    5 -----
 4 files changed, 9 insertions(+), 30 deletions(-)
arch/x86/include/asm/numa_64.h +0 -4
index 2b6a1c5..fbc9d33 100644
@@ -8,9 +8,6 @@ struct bootnode {
 	u64 end;
 };
 
-extern int compute_hash_shift(struct bootnode *nodes, int numblks,
-			      int *nodeids);
-
 #define ZONE_ALIGN (1UL << (MAX_ORDER+PAGE_SHIFT))
 
 extern int numa_off;
@@ -34,7 +31,6 @@ extern struct bootnode numa_nodes[MAX_NUMNODES] __initdata;
 
 extern int __cpuinit numa_cpu_node(int cpu);
 extern int __init numa_add_memblk(int nodeid, u64 start, u64 end);
-extern int __init numa_register_memblks(void);
 
 #ifdef CONFIG_NUMA_EMU
 #define FAKE_NODE_MIN_SIZE	((u64)32 << 20)
arch/x86/mm/amdtopology_64.c +2 -13
index fe93e23..48ec374 100644
@@ -167,6 +167,7 @@ int __init amd_numa_init(void)
 
 		numa_nodes[nodeid].start = base;
 		numa_nodes[nodeid].end = limit;
+		numa_add_memblk(nodeid, base, limit);
 
 		prevbase = base;
 
@@ -263,20 +264,8 @@ int __init amd_scan_nodes(void)
 {
 	int i;
 
-	memnode_shift = compute_hash_shift(numa_nodes, 8, NULL);
-	if (memnode_shift < 0) {
-		pr_err("No NUMA node hash function found. Contact maintainer\n");
-		return -1;
-	}
-	pr_info("Using node hash shift of %d\n", memnode_shift);
-
-	/* use the coreid bits from early_identify_cpu */
-	for_each_node_mask(i, node_possible_map) {
-		memblock_x86_register_active_regions(i,
-				numa_nodes[i].start >> PAGE_SHIFT,
-				numa_nodes[i].end >> PAGE_SHIFT);
+	for_each_node_mask(i, node_possible_map)
 		setup_node_bootmem(i, numa_nodes[i].start, numa_nodes[i].end);
-	}
 
 	numa_init_array();
 	return 0;
arch/x86/mm/numa_64.c +7 -8
index bbc42ca..2e2ca94 100644
@@ -131,8 +131,8 @@ static int __init extract_lsb_from_nodes(const struct bootnode *nodes,
 	return i;
 }
 
-int __init compute_hash_shift(struct bootnode *nodes, int numnodes,
-			      int *nodeids)
+static int __init compute_hash_shift(struct bootnode *nodes, int numnodes,
+				     int *nodeids)
 {
 	int shift;
 
@@ -287,7 +287,7 @@ setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)
 	node_set_online(nodeid);
 }
 
-int __init numa_register_memblks(void)
+static int __init numa_register_memblks(void)
 {
 	int i;
 
@@ -712,17 +712,13 @@ static int dummy_numa_init(void)
 
 	node_set(0, cpu_nodes_parsed);
 	node_set(0, mem_nodes_parsed);
+	numa_add_memblk(0, 0, (u64)max_pfn << PAGE_SHIFT);
 
 	return 0;
 }
 
 static int dummy_scan_nodes(void)
 {
-	/* setup dummy node covering all memory */
-	memnode_shift = 63;
-	memnodemap = memnode.embedded_map;
-	memnodemap[0] = 0;
-	memblock_x86_register_active_regions(0, 0, max_pfn);
 	setup_node_bootmem(0, 0, max_pfn << PAGE_SHIFT);
 	numa_init_array();
 
@@ -782,6 +778,9 @@ void __init initmem_init(void)
 		if (WARN_ON(nodes_empty(node_possible_map)))
 			continue;
 
+		if (numa_register_memblks() < 0)
+			continue;
+
 		if (!scan_nodes[i]())
 			return;
 	}
arch/x86/mm/srat_64.c +0 -5
index b0f0616..755d157 100644
@@ -308,11 +308,6 @@ int __init acpi_scan_nodes(void)
 	if (acpi_numa <= 0)
 		return -1;
 
-	if (numa_register_memblks() < 0) {
-		bad_srat();
-		return -1;
-	}
-
 	/* for out of order entries in SRAT */
 	sort_node_map();
 	if (!nodes_cover_memory(numa_nodes)) {
Signature · 1 line
1.7.1
author
#47 lore raw

PATCH 15/26 x86-64, NUMA: Unify the rest of memblk registration

In reply to Tejun Heo

Move the remaining memblk registration logic from acpi_scan_nodes() to numa_register_memblks() and initmem_init().

This applies nodes_cover_memory() sanity check, memory node sorting and node_online() checking, which were only applied to acpi, to all init methods.

As all memblk registration is moved to common code, active range clearing is moved to initmem_init() too and removed from bad_srat().

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/mm/amdtopology_64.c |    6 ---
 arch/x86/mm/numa_64.c        |   71 +++++++++++++++++++++++++++++++++++++++---
 arch/x86/mm/srat_64.c        |   59 ----------------------------------
 3 files changed, 66 insertions(+), 70 deletions(-)
arch/x86/mm/amdtopology_64.c +0 -6
index 48ec374..9c9f46a 100644
@@ -262,11 +262,5 @@ void __init amd_fake_nodes(const struct bootnode *nodes, int nr_nodes)
 
 int __init amd_scan_nodes(void)
 {
-	int i;
-
-	for_each_node_mask(i, node_possible_map)
-		setup_node_bootmem(i, numa_nodes[i].start, numa_nodes[i].end);
-
-	numa_init_array();
 	return 0;
 }
arch/x86/mm/numa_64.c +66 -5

107 lines not on this page · raw message

arch/x86/mm/srat_64.c +0 -59

79 lines not on this page · raw message

Signature · 1 line
1.7.1
#48 lore raw

Re: [PATCH 15/26] x86-64, NUMA: Unify the rest of memblk registration

Quoted 97 lines · Tejun Heo

Move the remaining memblk registration logic from acpi_scan_nodes() to numa_register_memblks() and initmem_init().

This applies nodes_cover_memory() sanity check, memory node sorting and node_online() checking, which were only applied to acpi, to all init methods.

As all memblk registration is moved to common code, active range clearing is moved to initmem_init() too and removed from bad_srat().

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/mm/amdtopology_64.c |    6 ---
 arch/x86/mm/numa_64.c        |   71 +++++++++++++++++++++++++++++++++++++++---
 arch/x86/mm/srat_64.c        |   59 ----------------------------------
 3 files changed, 66 insertions(+), 70 deletions(-)
arch/x86/mm/amdtopology_64.c +0 -6
index 48ec374..9c9f46a 100644
@@ -262,11 +262,5 @@ void __init amd_fake_nodes(const struct bootnode *nodes, int nr_nodes)
 
 int __init amd_scan_nodes(void)
 {
-	int i;
-
-	for_each_node_mask(i, node_possible_map)
-		setup_node_bootmem(i, numa_nodes[i].start, numa_nodes[i].end);
-
-	numa_init_array();
 	return 0;
 }
arch/x86/mm/numa_64.c +42 -0
index 2e2ca94..062649d 100644
@@ -287,6 +287,37 @@ setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)
 	node_set_online(nodeid);
 }
 
+/*
+ * Sanity check to catch more bad NUMA configurations (they are amazingly
+ * common).  Make sure the nodes cover all memory.
+ */
+static int __init nodes_cover_memory(const struct bootnode *nodes)
+{
+	unsigned long numaram, e820ram;
+	int i;
+
+	numaram = 0;
+	for_each_node_mask(i, mem_nodes_parsed) {
+		unsigned long s = nodes[i].start >> PAGE_SHIFT;
+		unsigned long e = nodes[i].end >> PAGE_SHIFT;
+		numaram += e - s;
+		numaram -= __absent_pages_in_range(i, s, e);
+		if ((long)numaram < 0)
+			numaram = 0;
+	}
+
+	e820ram = max_pfn -
+		(memblock_x86_hole_size(0, max_pfn<<PAGE_SHIFT) >> PAGE_SHIFT);
+	/* We seem to lose 3 pages somewhere. Allow 1M of slack. */
+	if ((long)(e820ram - numaram) >= (1<<(20 - PAGE_SHIFT))) {
+		printk(KERN_ERR "NUMA: nodes only cover %luMB of your %luMB e820 RAM. Not used.\n",
+			(numaram << PAGE_SHIFT) >> 20,
+			(e820ram << PAGE_SHIFT) >> 20);
+		return 0;
+	}
+	return 1;
+}
+
 static int __init numa_register_memblks(void)
 {
 	int i;
@@ -349,6 +380,25 @@ static int __init numa_register_memblks(void)
 		memblock_x86_register_active_regions(memblk_nodeid[i],
 				node_memblk_range[i].start >> PAGE_SHIFT,
 				node_memblk_range[i].end >> PAGE_SHIFT);
+
+	/* for out of order entries */
+	sort_node_map();
+	if (!nodes_cover_memory(numa_nodes))
+		return -EINVAL;
+
+	/* Finally register nodes. */
+	for_each_node_mask(i, node_possible_map)
+		setup_node_bootmem(i, numa_nodes[i].start, numa_nodes[i].end);
+
+	/*

arch/x86/mm/numa_64.c static int __init numa_register_memblks(void) · line 403

Quoted 10 lines
arch/x86/mm/numa_64.c +8 -0
+	 * Try again in case setup_node_bootmem missed one due to missing
+	 * bootmem.
+	 */
+	for_each_node_mask(i, node_possible_map)
+		if (!node_online(i))
+			setup_node_bootmem(i, numa_nodes[i].start,
+					   numa_nodes[i].end);
+
 	return 0;
 }

please don't put setup_node_bootmem calling into numa_register_memblks() that is not related.

put the calling in initmem_init() directly is more reasonable.

Quoted 135 lines
arch/x86/mm/numa_64.c +16 -5
@@ -713,15 +763,14 @@ static int dummy_numa_init(void)
 	node_set(0, cpu_nodes_parsed);
 	node_set(0, mem_nodes_parsed);
 	numa_add_memblk(0, 0, (u64)max_pfn << PAGE_SHIFT);
+	numa_nodes[0].start = 0;
+	numa_nodes[0].end = (u64)max_pfn << PAGE_SHIFT;
 
 	return 0;
 }
 
 static int dummy_scan_nodes(void)
 {
-	setup_node_bootmem(0, 0, max_pfn << PAGE_SHIFT);
-	numa_init_array();
-
 	return 0;
 }
 
@@ -757,6 +806,7 @@ void __init initmem_init(void)
 		memset(node_memblk_range, 0, sizeof(node_memblk_range));
 		memset(memblk_nodeid, 0, sizeof(memblk_nodeid));
 		memset(numa_nodes, 0, sizeof(numa_nodes));
+		remove_all_active_ranges();
 
 		if (numa_init[i]() < 0)
 			continue;
@@ -781,8 +831,19 @@ void __init initmem_init(void)
 		if (numa_register_memblks() < 0)
 			continue;
 
-		if (!scan_nodes[i]())
-			return;
+		if (scan_nodes[i]() < 0)
+			continue;
+
+		for (j = 0; j < nr_cpu_ids; j++) {
+			int nid = early_cpu_to_node(j);
+
+			if (nid == NUMA_NO_NODE)
+				continue;
+			if (!node_online(nid))
+				numa_clear_node(j);
+		}
+		numa_init_array();
+		return;
 	}
 	BUG();
 }
arch/x86/mm/srat_64.c +0 -59
index 755d157..4a2c33b 100644
@@ -44,7 +44,6 @@ static __init void bad_srat(void)
 		numa_nodes[i].start = numa_nodes[i].end = 0;
 		nodes_add[i].start = nodes_add[i].end = 0;
 	}
-	remove_all_active_ranges();
 }
 
 static __init inline int srat_disabled(void)
@@ -259,35 +258,6 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
 		update_nodes_add(node, start, end);
 }
 
-/* Sanity check to catch more bad SRATs (they are amazingly common).
-   Make sure the PXMs cover all memory. */
-static int __init nodes_cover_memory(const struct bootnode *nodes)
-{
-	int i;
-	unsigned long pxmram, e820ram;
-
-	pxmram = 0;
-	for_each_node_mask(i, mem_nodes_parsed) {
-		unsigned long s = nodes[i].start >> PAGE_SHIFT;
-		unsigned long e = nodes[i].end >> PAGE_SHIFT;
-		pxmram += e - s;
-		pxmram -= __absent_pages_in_range(i, s, e);
-		if ((long)pxmram < 0)
-			pxmram = 0;
-	}
-
-	e820ram = max_pfn - (memblock_x86_hole_size(0, max_pfn<<PAGE_SHIFT)>>PAGE_SHIFT);
-	/* We seem to lose 3 pages somewhere. Allow 1M of slack. */
-	if ((long)(e820ram - pxmram) >= (1<<(20 - PAGE_SHIFT))) {
-		printk(KERN_ERR
-	"SRAT: PXMs only cover %luMB of your %luMB e820 RAM. Not used.\n",
-			(pxmram << PAGE_SHIFT) >> 20,
-			(e820ram << PAGE_SHIFT) >> 20);
-		return 0;
-	}
-	return 1;
-}
-
 void __init acpi_numa_arch_fixup(void) {}
 
 int __init x86_acpi_numa_init(void)
@@ -303,37 +273,8 @@ int __init x86_acpi_numa_init(void)
 /* Use the information discovered above to actually set up the nodes. */
 int __init acpi_scan_nodes(void)
 {
-	int i;
-
 	if (acpi_numa <= 0)
 		return -1;
-
-	/* for out of order entries in SRAT */
-	sort_node_map();
-	if (!nodes_cover_memory(numa_nodes)) {
-		bad_srat();
-		return -1;
-	}
-
-	/* Finally register nodes */
-	for_each_node_mask(i, node_possible_map)
-		setup_node_bootmem(i, numa_nodes[i].start, numa_nodes[i].end);
-	/* Try again in case setup_node_bootmem missed one due
-	   to missing bootmem */
-	for_each_node_mask(i, node_possible_map)
-		if (!node_online(i))
-			setup_node_bootmem(i, numa_nodes[i].start,
-					   numa_nodes[i].end);
-
-	for (i = 0; i < nr_cpu_ids; i++) {
-		int node = early_cpu_to_node(i);
-
-		if (node == NUMA_NO_NODE)
-			continue;
-		if (!node_online(node))
-			numa_clear_node(i);
-	}
-	numa_init_array();
 	return 0;
 }
 
author
#49 lore raw

Re: [PATCH 15/26] x86-64, NUMA: Unify the rest of memblk registration

Hello,

Quoted 4 lines · Yinghai Lu

please don't put setup_node_bootmem calling into numa_register_memblks() that is not related.

put the calling in initmem_init() directly is more reasonable.

No, I don't think so. If you don't like the function name, let's change the name. I think it's better to put all registrations there. Later in the series but function is changed to deal with struct numa_meminfo anyway so maybe it's better to rename it to numa_register_meminfo().

Thanks.

Signature · 1 line
tejun
#50 lore raw

Re: [PATCH 15/26] x86-64, NUMA: Unify the rest of memblk registration

Quoted 6 lines · Tejun Heo

Hello,

Quoted 3 lines · Yinghai Lu

please don't put setup_node_bootmem calling into numa_register_memblks() that is not related.

Quoted 7 lines
Quoted 1 line

put the calling in initmem_init() directly is more reasonable.

No, I don't think so.  If you don't like the function name, let's change the name.  I think it's better to put all registrations there. Later in the series but function is changed to deal with struct numa_meminfo anyway so maybe it's better to rename it to numa_register_meminfo().

No, I don't like ***_register_*** take care of calling setup_bootmem.

Yinghai

author
#51 lore raw

Re: [PATCH 15/26] x86-64, NUMA: Unify the rest of memblk registration

Quoted 7 lines · Yinghai Lu
Quoted 5 lines

No, I don't think so.  If you don't like the function name, let's change the name.  I think it's better to put all registrations there. Later in the series but function is changed to deal with struct numa_meminfo anyway so maybe it's better to rename it to numa_register_meminfo().

No, I don't like ***_register_*** take care of calling setup_bootmem.

Yeah, then, please go ahead and suggest the name you want. I don't really care about the name itself, but I don't want to put it directly in initmem_init() because with double calling and extra loop added later it gets nested too deep. For now, let's move on, okay? We can argue about this for days but there's no clear technical [dis]advantage one way or the other and falls squarely in the scope of bikeshedding.

Thanks.

Signature · 1 line
tejun
#52 lore raw

Re: [PATCH 15/26] x86-64, NUMA: Unify the rest of memblk registration

Quoted 9 lines · Tejun Heo
Quoted 7 lines · Yinghai Lu
Quoted 5 lines

No, I don't think so.  If you don't like the function name, let's change the name.  I think it's better to put all registrations there. Later in the series but function is changed to deal with struct numa_meminfo anyway so maybe it's better to rename it to numa_register_meminfo().

No, I don't like ***_register_*** take care of calling setup_bootmem.

Quoted 8 lines

Yeah, then, please go ahead and suggest the name you want.  I don't really care about the name itself, but I don't want to put it directly in initmem_init() because with double calling and extra loop added later it gets nested too deep.  For now, let's move on, okay?  We can argue about this for days but there's no clear technical [dis]advantage one way or the other and falls squarely in the scope of bikeshedding.

why not do it at first point ?

numa_register_meminfo() should only take care of creating correctly struct numa_meminfo.

Yinghai

author
#53 lore raw

Re: [PATCH 15/26] x86-64, NUMA: Unify the rest of memblk registration

Quoted 4 lines · Yinghai Lu

why not do it at first point ?

numa_register_meminfo() should only take care of creating correctly struct numa_meminfo.

No, register meminfo doesn't create numa_meminfo. It sets up system states according to the configuration information in numa_meminfo, and I really have no idea what you're arguing for or against. What's your point?

Signature · 1 line
tejun
#54 lore raw

Re: [PATCH 15/26] x86-64, NUMA: Unify the rest of memblk registration

Quoted 10 lines · Tejun Heo
Quoted 4 lines · Yinghai Lu

why not do it at first point ?

numa_register_meminfo() should only take care of creating correctly struct numa_meminfo.

No, register meminfo doesn't create numa_meminfo.  It sets up system states according to the configuration information in numa_meminfo, and I really have no idea what you're arguing for or against.  What's your point?

I just want seperate setup_bootmem ( and maybe init_memory_mapping_high...) out that __register__ function.

that __register__ function do some sth like memblock_register to early_node_map[]
looks reasonable.

Yinghai

author
#55 lore raw

Re: [PATCH 15/26] x86-64, NUMA: Unify the rest of memblk registration

Hello,

Quoted 5 lines · Yinghai Lu

I just want seperate setup_bootmem ( and maybe init_memory_mapping_high...) out that __register__ function.

that __register__ function do some sth like memblock_register to early_node_map[] looks reasonable.

Can you please provide some rationales _why_ you think setup_bootmem() should be moved elsewhere? Because it is not apparent to me and I cannot read your mind. I'm not against it given good enough reasons. After all, _technically_ it doesn't make one iota of difference, but I don't want to change it just because you don't like it and I don't think you want that either, so _please_ give me some explanations about what you want and _why_. It's not like we're involved in a romantic relationship and even when I'm in one I suck at that implied communication thing.

Thanks.

Signature · 1 line
tejun
#56 lore raw

Re: [PATCH 15/26] x86-64, NUMA: Unify the rest of memblk registration

Quoted 9 lines · Tejun Heo

Hello,

Quoted 5 lines · Yinghai Lu

I just want seperate setup_bootmem ( and maybe init_memory_mapping_high...) out that __register__ function.

that __register__ function do some sth like memblock_register to early_node_map[] looks reasonable.

Quoted 9 lines

Can you please provide some rationales _why_ you think setup_bootmem() should be moved elsewhere? Because it is not apparent to me and I cannot read your mind. I'm not against it given good enough reasons. After all, _technically_ it doesn't make one iota of difference, but I don't want to change it just because you don't like it and I don't think you want that either, so _please_ give me some explanations about what you want and _why_. It's not like we're involved in a romantic relationship and even when I'm in one I suck at that implied communication thing.

Never mind. will send out patch after your patches get merged into tip.

BTW, you may need to rebase your on top of tip/master.

Thanks

Yinghai

author
#57 lore raw

Re: [PATCH 15/26] x86-64, NUMA: Unify the rest of memblk registration

Quoted 1 line · Yinghai Lu

Never mind. will send out patch after your patches get merged into tip.

Alright, fair enough.

Quoted 1 line

BTW, you may need to rebase your on top of tip/master.

Yeah, I saw a new patch going into the numa branch, but shouldn't this and the next series based on x86/numa? That was how it was done with the previous series.

Thanks.

Signature · 1 line
tejun
#58 lore raw

Re: [PATCH 15/26] x86-64, NUMA: Unify the rest of memblk registration

Quoted 10 lines · Tejun Heo
Quoted 1 line · Yinghai Lu

Never mind. will send out patch after your patches get merged into tip.

Alright, fair enough.

Quoted 1 line

BTW, you may need to rebase your on top of tip/master.

Yeah, I saw a new patch going into the numa branch, but shouldn't this and the next series based on x86/numa? That was how it was done with the previous series.

there is patch about init_memory_mapping_high() in tip/x86/bootmem. it will put pgtable on local nodes.

Yinghai

author
#59 lore raw

Re: [PATCH 15/26] x86-64, NUMA: Unify the rest of memblk registration

Quoted 6 lines · Yinghai Lu
Quoted 5 lines · Tejun Heo
Quoted 1 line · Yinghai Lu

Never mind. will send out patch after your patches get merged into tip.

Alright, fair enough.

Quoted 8 lines
Quoted 5 lines
Quoted 1 line

BTW, you may need to rebase your on top of tip/master.

Yeah, I saw a new patch going into the numa branch, but shouldn't this and the next series based on x86/numa? That was how it was done with the previous series.

there is patch about init_memory_mapping_high() in tip/x86/bootmem. it will put pgtable on local nodes.

Ingo, hpa, how do you guys want to handle this? Maybe you can cherry pick or pull the branch into x86/numa?

Thanks.

Signature · 1 line
tejun
#60 lore raw

Re: [PATCH 15/26] x86-64, NUMA: Unify the rest of memblk registration

Quoted 13 lines · Tejun Heo
Quoted 12 lines · Yinghai Lu
Quoted 10 lines · Tejun Heo
Quoted 1 line · Yinghai Lu

Never mind. will send out patch after your patches get merged into tip.

Alright, fair enough.

Quoted 1 line

BTW, you may need to rebase your on top of tip/master.

Yeah, I saw a new patch going into the numa branch, but shouldn't this and the next series based on x86/numa? That was how it was done with the previous series.

Quoted 5 lines
Quoted 2 lines

there is patch about init_memory_mapping_high() in tip/x86/bootmem. it will put pgtable on local nodes.

Ingo, hpa, how do you guys want to handle this? Maybe you can cherry pick or pull the branch into x86/numa?

Would be nice to have a version against the latest tip:x86/numa tree, the current one conflicts in arch/x86/mm/numa_64.c with your tree. Also, i suspect you want to propagate Yinghai's Acked-by's into the commits?

Thanks,

Ingo

author
#61 lore raw

Re: [PATCH 15/26] x86-64, NUMA: Unify the rest of memblk registration

Quoted 4 lines · Ingo Molnar

Would be nice to have a version against the latest tip:x86/numa tree, the current one conflicts in arch/x86/mm/numa_64.c with your tree. Also, i suspect you want to propagate Yinghai's Acked-by's into the commits?

Acked-by added and rebased on top of the current x86/numa. Only one patch needed to be updated and the udpated version was just posted. The updated git branches are available at

git://git.kernel.org/pub/scm/linux/kernel/git/tj/misc.git x86_64-numa-unify
git://git.kernel.org/pub/scm/linux/kernel/git/tj/misc.git x86_64-numa-emu-unify

The latter one is superset of the former.

If you want the whole series reposted, please let me know.

Thanks.

Signature · 1 line
tejun
#62 lore raw

Re: [PATCH 15/26] x86-64, NUMA: Unify the rest of memblk registration

Quoted 10 lines · Tejun Heo
Quoted 4 lines · Ingo Molnar

Would be nice to have a version against the latest tip:x86/numa tree, the current one conflicts in arch/x86/mm/numa_64.c with your tree. Also, i suspect you want to propagate Yinghai's Acked-by's into the commits?

Acked-by added and rebased on top of the current x86/numa. Only one patch needed to be updated and the udpated version was just posted. The updated git branches are available at

Quoted 6 lines

git://git.kernel.org/pub/scm/linux/kernel/git/tj/misc.git x86_64-numa-unify
git://git.kernel.org/pub/scm/linux/kernel/git/tj/misc.git x86_64-numa-emu-unify

The latter one is superset of the former.

If you want the whole series reposted, please let me know.

No need if the patches did not change - but a diffstat is generally nice with pull requests, so that mismatches between intention on your side and action on my side can be detected sooner. Anyway, pulled it - thanks Tejun!

Ingo

#63 lore raw

Re: [PATCH 15/26] x86-64, NUMA: Unify the rest of memblk registration

Quoted 2 lines
Quoted 2 lines

If you want the whole series reposted, please let me know.

Actually, it would be nice if you could merge your tree to the latest x86/mm tree i have just pushed out :-/

The problem is that your work is so wide that it conflicts with x86/mm, x86/bootmem, x86/amd-nb and x86/mm:

arch/x86/include/asm/amd_nb.h
arch/x86/include/asm/page_types.h
arch/x86/mm/amdtopology_64.c
arch/x86/mm/init_64.c
arch/x86/mm/numa_64.c
arch/x86/mm/srat_64.c

I consolidated all these topics into the generic x86/mm tree which you could use as a base.

I did not recognize the level of conflicts until i tried to pull your tree. You can generally test such interactions with other bits of the x86 tree by test-merging your pending work to tip:master.

Thanks,

Ingo

author
#64 lore raw

Re: [PATCH 15/26] x86-64, NUMA: Unify the rest of memblk registration

Hello,

Quoted 6 lines · Ingo Molnar

I consolidated all these topics into the generic x86/mm tree which you could use as a base.

I did not recognize the level of conflicts until i tried to pull your tree. You can generally test such interactions with other bits of the x86 tree by test-merging your pending work to tip:master.

Alright, I'll just rebase it on top of x86/mm and send a proper pull request.

Thanks.

Signature · 1 line
tejun
#65 lore raw

Re: [PATCH 15/26] x86-64, NUMA: Unify the rest of memblk registration

Quoted 6 lines · Tejun Heo

Hello,

Quoted 3 lines · Ingo Molnar

I consolidated all these topics into the generic x86/mm tree which you could use as a base.

Quoted 6 lines
Quoted 3 lines

I did not recognize the level of conflicts until i tried to pull your tree. You can generally test such interactions with other bits of the x86 tree by test-merging your pending work to tip:master.

Alright, I'll just rebase it on top of x86/mm and send a proper pull request.

The tip of x86/mm is:

275a88d3cf0e: Merge branch 'x86/amd-nb' into x86/mm

Thanks,

Ingo

author
#66 lore raw

PATCH 16/26 x86-64, NUMA: Kill {acpi|amd|dummy}_scan_nodes()

In reply to Tejun Heo

They are empty now. Kill them.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/include/asm/acpi.h   |    1 -
 arch/x86/include/asm/amd_nb.h |    1 -
 arch/x86/mm/amdtopology_64.c  |    5 -----
 arch/x86/mm/numa_64.c         |   11 -----------
 arch/x86/mm/srat_64.c         |    8 --------
 5 files changed, 0 insertions(+), 26 deletions(-)
arch/x86/include/asm/acpi.h +0 -1
index 12bd1fd..cfa3d5c 100644
@@ -186,7 +186,6 @@ struct bootnode;
 #ifdef CONFIG_ACPI_NUMA
 extern int acpi_numa;
 extern int x86_acpi_numa_init(void);
-extern int acpi_scan_nodes(void);
 
 #ifdef CONFIG_NUMA_EMU
 extern void acpi_fake_nodes(const struct bootnode *fake_nodes,
arch/x86/include/asm/amd_nb.h +0 -1
index 765966f..627aff3 100644
@@ -17,7 +17,6 @@ extern int early_is_amd_nb(u32 value);
 extern int amd_cache_northbridges(void);
 extern void amd_flush_garts(void);
 extern int amd_numa_init(void);
-extern int amd_scan_nodes(void);
 
 #ifdef CONFIG_NUMA_EMU
 extern void amd_fake_nodes(const struct bootnode *nodes, int nr_nodes);
arch/x86/mm/amdtopology_64.c +0 -5
index 9c9f46a..90cf297 100644
@@ -259,8 +259,3 @@ void __init amd_fake_nodes(const struct bootnode *nodes, int nr_nodes)
 	memcpy(__apicid_to_node, fake_apicid_to_node, sizeof(__apicid_to_node));
 }
 #endif /* CONFIG_NUMA_EMU */
-
-int __init amd_scan_nodes(void)
-{
-	return 0;
-}
arch/x86/mm/numa_64.c +0 -11
index 062649d..be173c4 100644
@@ -769,25 +769,17 @@ static int dummy_numa_init(void)
 	return 0;
 }
 
-static int dummy_scan_nodes(void)
-{
-	return 0;
-}
-
 void __init initmem_init(void)
 {
 	int (*numa_init[])(void) = { [2] = dummy_numa_init };
-	int (*scan_nodes[])(void) = { [2] = dummy_scan_nodes };
 	int i, j;
 
 	if (!numa_off) {
 #ifdef CONFIG_ACPI_NUMA
 		numa_init[0] = x86_acpi_numa_init;
-		scan_nodes[0] = acpi_scan_nodes;
 #endif
 #ifdef CONFIG_AMD_NUMA
 		numa_init[1] = amd_numa_init;
-		scan_nodes[1] = amd_scan_nodes;
 #endif
 	}
 
@@ -831,9 +823,6 @@ void __init initmem_init(void)
 		if (numa_register_memblks() < 0)
 			continue;
 
-		if (scan_nodes[i]() < 0)
-			continue;
-
 		for (j = 0; j < nr_cpu_ids; j++) {
 			int nid = early_cpu_to_node(j);
 
arch/x86/mm/srat_64.c +0 -8
index 4a2c33b..d56eff8 100644
@@ -270,14 +270,6 @@ int __init x86_acpi_numa_init(void)
 	return srat_disabled() ? -EINVAL : 0;
 }
 
-/* Use the information discovered above to actually set up the nodes. */
-int __init acpi_scan_nodes(void)
-{
-	if (acpi_numa <= 0)
-		return -1;
-	return 0;
-}
-
 #ifdef CONFIG_NUMA_EMU
 static int fake_node_to_pxm_map[MAX_NUMNODES] __initdata = {
 	[0 ... MAX_NUMNODES-1] = PXM_INVAL
Signature · 1 line
1.7.1
author
#67 lore raw

PATCH 17/26 x86-64, NUMA: Remove %NULL @nodeids handling from compute_hash_shift()

In reply to Tejun Heo

numa_emulation() called compute_hash_shift() with %NULL @nodeids which meant identity mapping between index and nodeid. Make numa_emulation() build identity array and drop %NULL @nodeids handling from populate_memnodemap() and thus from compute_hash_shift(). This is to prepare for transition to using memblks instead.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/mm/numa_64.c |   14 +++++++-------
 1 files changed, 7 insertions(+), 7 deletions(-)
arch/x86/mm/numa_64.c +7 -7
index be173c4..1d79cd8 100644
@@ -63,12 +63,7 @@ static int __init populate_memnodemap(const struct bootnode *nodes,
 		do {
 			if (memnodemap[addr >> shift] != NUMA_NO_NODE)
 				return -1;
-
-			if (!nodeids)
-				memnodemap[addr >> shift] = i;
-			else
-				memnodemap[addr >> shift] = nodeids[i];
-
+			memnodemap[addr >> shift] = nodeids[i];
 			addr += (1UL << shift);
 		} while (addr < end);
 		res = 1;
@@ -704,6 +699,7 @@ static int __init split_nodes_size_interleave(u64 addr, u64 max_addr, u64 size)
 static int __init numa_emulation(unsigned long start_pfn,
 			unsigned long last_pfn, int acpi, int amd)
 {
+	static int nodeid[NR_NODE_MEMBLKS] __initdata;
 	u64 addr = start_pfn << PAGE_SHIFT;
 	u64 max_addr = last_pfn << PAGE_SHIFT;
 	int num_nodes;
@@ -728,7 +724,11 @@ static int __init numa_emulation(unsigned long start_pfn,
 
 	if (num_nodes < 0)
 		return num_nodes;
-	memnode_shift = compute_hash_shift(nodes, num_nodes, NULL);
+
+	for (i = 0; i < ARRAY_SIZE(nodeid); i++)
+		nodeid[i] = i;
+
+	memnode_shift = compute_hash_shift(nodes, num_nodes, nodeid);
 	if (memnode_shift < 0) {
 		memnode_shift = 0;
 		printk(KERN_ERR "No NUMA hash function found.  NUMA emulation "
Signature · 1 line
1.7.1
author
#68 lore raw

PATCH 18/26 x86-64, NUMA: Introduce struct numa_meminfo

In reply to Tejun Heo

Arrays for memblks and nodeids and their length lived in separate variables making things unnecessarily cumbersome. Introduce struct numa_meminfo which contains all memory configuration info. This patch doesn't cause any behavior change.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/mm/numa_64.c |  145 +++++++++++++++++++++++++------------------------
 1 files changed, 75 insertions(+), 70 deletions(-)
arch/x86/mm/numa_64.c +75 -70
index 1d79cd8..04ea17b 100644
@@ -22,6 +22,17 @@
 #include <asm/acpi.h>
 #include <asm/amd_nb.h>
 
+struct numa_memblk {
+	u64			start;
+	u64			end;
+	int			nid;
+};
+
+struct numa_meminfo {
+	int			nr_blks;
+	struct numa_memblk	blk[NR_NODE_MEMBLKS];
+};
+
 struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
 EXPORT_SYMBOL(node_data);
 
@@ -33,9 +44,7 @@ struct memnode memnode;
 static unsigned long __initdata nodemap_addr;
 static unsigned long __initdata nodemap_size;
 
-static int num_node_memblks __initdata;
-static struct bootnode node_memblk_range[NR_NODE_MEMBLKS] __initdata;
-static int memblk_nodeid[NR_NODE_MEMBLKS] __initdata;
+static struct numa_meminfo numa_meminfo __initdata;
 
 struct bootnode numa_nodes[MAX_NUMNODES] __initdata;
 
@@ -46,16 +55,15 @@ struct bootnode numa_nodes[MAX_NUMNODES] __initdata;
  * 0 if memnodmap[] too small (of shift too small)
  * -1 if node overlap or lost ram (shift too big)
  */
-static int __init populate_memnodemap(const struct bootnode *nodes,
-				      int numnodes, int shift, int *nodeids)
+static int __init populate_memnodemap(const struct numa_meminfo *mi, int shift)
 {
 	unsigned long addr, end;
 	int i, res = -1;
 
 	memset(memnodemap, 0xff, sizeof(s16)*memnodemapsize);
-	for (i = 0; i < numnodes; i++) {
-		addr = nodes[i].start;
-		end = nodes[i].end;
+	for (i = 0; i < mi->nr_blks; i++) {
+		addr = mi->blk[i].start;
+		end = mi->blk[i].end;
 		if (addr >= end)
 			continue;
 		if ((end >> shift) >= memnodemapsize)
@@ -63,7 +71,7 @@ static int __init populate_memnodemap(const struct bootnode *nodes,
 		do {
 			if (memnodemap[addr >> shift] != NUMA_NO_NODE)
 				return -1;
-			memnodemap[addr >> shift] = nodeids[i];
+			memnodemap[addr >> shift] = mi->blk[i].nid;
 			addr += (1UL << shift);
 		} while (addr < end);
 		res = 1;
@@ -101,16 +109,15 @@ static int __init allocate_cachealigned_memnodemap(void)
  * The LSB of all start and end addresses in the node map is the value of the
  * maximum possible shift.
  */
-static int __init extract_lsb_from_nodes(const struct bootnode *nodes,
-					 int numnodes)
+static int __init extract_lsb_from_nodes(const struct numa_meminfo *mi)
 {
 	int i, nodes_used = 0;
 	unsigned long start, end;
 	unsigned long bitfield = 0, memtop = 0;
 
-	for (i = 0; i < numnodes; i++) {
-		start = nodes[i].start;
-		end = nodes[i].end;
+	for (i = 0; i < mi->nr_blks; i++) {
+		start = mi->blk[i].start;
+		end = mi->blk[i].end;
 		if (start >= end)
 			continue;
 		bitfield |= start;
@@ -126,18 +133,17 @@ static int __init extract_lsb_from_nodes(const struct bootnode *nodes,
 	return i;
 }
 
-static int __init compute_hash_shift(struct bootnode *nodes, int numnodes,
-				     int *nodeids)
+static int __init compute_hash_shift(const struct numa_meminfo *mi)
 {
 	int shift;
 
-	shift = extract_lsb_from_nodes(nodes, numnodes);
+	shift = extract_lsb_from_nodes(mi);
 	if (allocate_cachealigned_memnodemap())
 		return -1;
 	printk(KERN_DEBUG "NUMA: Using %d for the hash shift.\n",
 		shift);
 
-	if (populate_memnodemap(nodes, numnodes, shift, nodeids) != 1) {
+	if (populate_memnodemap(mi, shift) != 1) {
 		printk(KERN_INFO "Your memory is not aligned you need to "
 		       "rebuild your kernel with a bigger NODEMAPSIZE "
 		       "shift=%d\n", shift);
@@ -185,21 +191,25 @@ static void * __init early_node_mem(int nodeid, unsigned long start,
 
 static __init int conflicting_memblks(unsigned long start, unsigned long end)
 {
+	struct numa_meminfo *mi = &numa_meminfo;
 	int i;
-	for (i = 0; i < num_node_memblks; i++) {
-		struct bootnode *nd = &node_memblk_range[i];
-		if (nd->start == nd->end)
+
+	for (i = 0; i < mi->nr_blks; i++) {
+		struct numa_memblk *blk = &mi->blk[i];
+
+		if (blk->start == blk->end)
 			continue;
-		if (nd->end > start && nd->start < end)
-			return memblk_nodeid[i];
-		if (nd->end == end && nd->start == start)
-			return memblk_nodeid[i];
+		if (blk->end > start && blk->start < end)
+			return blk->nid;
+		if (blk->end == end && blk->start == start)
+			return blk->nid;
 	}
 	return -1;
 }
 
 int __init numa_add_memblk(int nid, u64 start, u64 end)
 {
+	struct numa_meminfo *mi = &numa_meminfo;
 	int i;
 
 	i = conflicting_memblks(start, end);
@@ -213,10 +223,10 @@ int __init numa_add_memblk(int nid, u64 start, u64 end)
 		return -EINVAL;
 	}
 
-	node_memblk_range[num_node_memblks].start = start;
-	node_memblk_range[num_node_memblks].end = end;
-	memblk_nodeid[num_node_memblks] = nid;
-	num_node_memblks++;
+	mi->blk[mi->nr_blks].start = start;
+	mi->blk[mi->nr_blks].end = end;
+	mi->blk[mi->nr_blks].nid = nid;
+	mi->nr_blks++;
 	return 0;
 }
 
@@ -315,66 +325,59 @@ static int __init nodes_cover_memory(const struct bootnode *nodes)
 
 static int __init numa_register_memblks(void)
 {
+	struct numa_meminfo *mi = &numa_meminfo;
 	int i;
 
 	/*
 	 * Join together blocks on the same node, holes between
 	 * which don't overlap with memory on other nodes.
 	 */
-	for (i = 0; i < num_node_memblks; ++i) {
+	for (i = 0; i < mi->nr_blks; ++i) {
+		struct numa_memblk *bi = &mi->blk[i];
 		int j, k;
 
-		for (j = i + 1; j < num_node_memblks; ++j) {
+		for (j = i + 1; j < mi->nr_blks; ++j) {
+			struct numa_memblk *bj = &mi->blk[j];
 			unsigned long start, end;
 
-			if (memblk_nodeid[i] != memblk_nodeid[j])
+			if (bi->nid != bj->nid)
 				continue;
-			start = min(node_memblk_range[i].end,
-			            node_memblk_range[j].end);
-			end = max(node_memblk_range[i].start,
-			          node_memblk_range[j].start);
-			for (k = 0; k < num_node_memblks; ++k) {
-				if (memblk_nodeid[i] == memblk_nodeid[k])
+			start = min(bi->end, bj->end);
+			end = max(bi->start, bj->start);
+			for (k = 0; k < mi->nr_blks; ++k) {
+				struct numa_memblk *bk = &mi->blk[k];
+
+				if (bi->nid == bk->nid)
 					continue;
-				if (start < node_memblk_range[k].end &&
-				    end > node_memblk_range[k].start)
+				if (start < bk->end && end > bk->start)
 					break;
 			}
-			if (k < num_node_memblks)
+			if (k < mi->nr_blks)
 				continue;
-			start = min(node_memblk_range[i].start,
-			            node_memblk_range[j].start);
-			end = max(node_memblk_range[i].end,
-			          node_memblk_range[j].end);
+			start = min(bi->start, bj->start);
+			end = max(bi->end, bj->end);
 			printk(KERN_INFO "NUMA: Node %d [%Lx,%Lx) + [%Lx,%Lx) -> [%lx,%lx)\n",
-			       memblk_nodeid[i],
-			       node_memblk_range[i].start,
-			       node_memblk_range[i].end,
-			       node_memblk_range[j].start,
-			       node_memblk_range[j].end,
+			       bi->nid, bi->start, bi->end, bj->start, bj->end,
 			       start, end);
-			node_memblk_range[i].start = start;
-			node_memblk_range[i].end = end;
-			k = --num_node_memblks - j;
-			memmove(memblk_nodeid + j, memblk_nodeid + j+1,
-				k * sizeof(*memblk_nodeid));
-			memmove(node_memblk_range + j, node_memblk_range + j+1,
-				k * sizeof(*node_memblk_range));
+			bi->start = start;
+			bi->end = end;
+			k = --mi->nr_blks - j;
+			memmove(mi->blk + j, mi->blk + j + 1,
+				k * sizeof(mi->blk[0]));
 			--j;
 		}
 	}
 
-	memnode_shift = compute_hash_shift(node_memblk_range, num_node_memblks,
-					   memblk_nodeid);
+	memnode_shift = compute_hash_shift(mi);
 	if (memnode_shift < 0) {
 		printk(KERN_ERR "NUMA: No NUMA node hash function found. Contact maintainer\n");
 		return -EINVAL;
 	}
 
-	for (i = 0; i < num_node_memblks; i++)
-		memblock_x86_register_active_regions(memblk_nodeid[i],
-				node_memblk_range[i].start >> PAGE_SHIFT,
-				node_memblk_range[i].end >> PAGE_SHIFT);
+	for (i = 0; i < mi->nr_blks; i++)
+		memblock_x86_register_active_regions(mi->blk[i].nid,
+					mi->blk[i].start >> PAGE_SHIFT,
+					mi->blk[i].end >> PAGE_SHIFT);
 
 	/* for out of order entries */
 	sort_node_map();
@@ -699,7 +702,7 @@ static int __init split_nodes_size_interleave(u64 addr, u64 max_addr, u64 size)
 static int __init numa_emulation(unsigned long start_pfn,
 			unsigned long last_pfn, int acpi, int amd)
 {
-	static int nodeid[NR_NODE_MEMBLKS] __initdata;
+	static struct numa_meminfo ei __initdata;
 	u64 addr = start_pfn << PAGE_SHIFT;
 	u64 max_addr = last_pfn << PAGE_SHIFT;
 	int num_nodes;
@@ -725,10 +728,14 @@ static int __init numa_emulation(unsigned long start_pfn,
 	if (num_nodes < 0)
 		return num_nodes;
 
-	for (i = 0; i < ARRAY_SIZE(nodeid); i++)
-		nodeid[i] = i;
+	ei.nr_blks = num_nodes;
+	for (i = 0; i < ei.nr_blks; i++) {
+		ei.blk[i].start = nodes[i].start;
+		ei.blk[i].end = nodes[i].end;
+		ei.blk[i].nid = i;
+	}
 
-	memnode_shift = compute_hash_shift(nodes, num_nodes, nodeid);
+	memnode_shift = compute_hash_shift(&ei);
 	if (memnode_shift < 0) {
 		memnode_shift = 0;
 		printk(KERN_ERR "No NUMA hash function found.  NUMA emulation "
@@ -794,9 +801,7 @@ void __init initmem_init(void)
 		nodes_clear(mem_nodes_parsed);
 		nodes_clear(node_possible_map);
 		nodes_clear(node_online_map);
-		num_node_memblks = 0;
-		memset(node_memblk_range, 0, sizeof(node_memblk_range));
-		memset(memblk_nodeid, 0, sizeof(memblk_nodeid));
+		memset(&numa_meminfo, 0, sizeof(numa_meminfo));
 		memset(numa_nodes, 0, sizeof(numa_nodes));
 		remove_all_active_ranges();
 
Signature · 1 line
1.7.1
author
#69 lore raw

PATCH 19/26 x86-64, NUMA: Separate out numa_cleanup_meminfo()

In reply to Tejun Heo

Separate out numa_cleanup_meminfo() from numa_register_memblks(). node_possible_map initialization is moved to the top of the split numa_register_memblks().

This patch doesn't cause behavior change.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/mm/numa_64.c |   83 +++++++++++++++++++++++++++----------------------
 1 files changed, 46 insertions(+), 37 deletions(-)
arch/x86/mm/numa_64.c +46 -37
index 04ea17b..4f173a5 100644
@@ -292,40 +292,8 @@ setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)
 	node_set_online(nodeid);
 }
 
-/*
- * Sanity check to catch more bad NUMA configurations (they are amazingly
- * common).  Make sure the nodes cover all memory.
- */
-static int __init nodes_cover_memory(const struct bootnode *nodes)
+static int __init numa_cleanup_meminfo(struct numa_meminfo *mi)
 {
-	unsigned long numaram, e820ram;
-	int i;
-
-	numaram = 0;
-	for_each_node_mask(i, mem_nodes_parsed) {
-		unsigned long s = nodes[i].start >> PAGE_SHIFT;
-		unsigned long e = nodes[i].end >> PAGE_SHIFT;
-		numaram += e - s;
-		numaram -= __absent_pages_in_range(i, s, e);
-		if ((long)numaram < 0)
-			numaram = 0;
-	}
-
-	e820ram = max_pfn -
-		(memblock_x86_hole_size(0, max_pfn<<PAGE_SHIFT) >> PAGE_SHIFT);
-	/* We seem to lose 3 pages somewhere. Allow 1M of slack. */
-	if ((long)(e820ram - numaram) >= (1<<(20 - PAGE_SHIFT))) {
-		printk(KERN_ERR "NUMA: nodes only cover %luMB of your %luMB e820 RAM. Not used.\n",
-			(numaram << PAGE_SHIFT) >> 20,
-			(e820ram << PAGE_SHIFT) >> 20);
-		return 0;
-	}
-	return 1;
-}
-
-static int __init numa_register_memblks(void)
-{
-	struct numa_meminfo *mi = &numa_meminfo;
 	int i;
 
 	/*
@@ -368,6 +336,49 @@ static int __init numa_register_memblks(void)
 		}
 	}
 
+	return 0;
+}
+
+/*
+ * Sanity check to catch more bad NUMA configurations (they are amazingly
+ * common).  Make sure the nodes cover all memory.
+ */
+static int __init nodes_cover_memory(const struct bootnode *nodes)
+{
+	unsigned long numaram, e820ram;
+	int i;
+
+	numaram = 0;
+	for_each_node_mask(i, mem_nodes_parsed) {
+		unsigned long s = nodes[i].start >> PAGE_SHIFT;
+		unsigned long e = nodes[i].end >> PAGE_SHIFT;
+		numaram += e - s;
+		numaram -= __absent_pages_in_range(i, s, e);
+		if ((long)numaram < 0)
+			numaram = 0;
+	}
+
+	e820ram = max_pfn - (memblock_x86_hole_size(0,
+					max_pfn << PAGE_SHIFT) >> PAGE_SHIFT);
+	/* We seem to lose 3 pages somewhere. Allow 1M of slack. */
+	if ((long)(e820ram - numaram) >= (1 << (20 - PAGE_SHIFT))) {
+		printk(KERN_ERR "NUMA: nodes only cover %luMB of your %luMB e820 RAM. Not used.\n",
+		       (numaram << PAGE_SHIFT) >> 20,
+		       (e820ram << PAGE_SHIFT) >> 20);
+		return 0;
+	}
+	return 1;
+}
+
+static int __init numa_register_memblks(struct numa_meminfo *mi)
+{
+	int i;
+
+	/* Account for nodes with cpus and no memory */
+	nodes_or(node_possible_map, mem_nodes_parsed, cpu_nodes_parsed);
+	if (WARN_ON(nodes_empty(node_possible_map)))
+		return -EINVAL;
+
 	memnode_shift = compute_hash_shift(mi);
 	if (memnode_shift < 0) {
 		printk(KERN_ERR "NUMA: No NUMA node hash function found. Contact maintainer\n");
@@ -820,12 +831,10 @@ void __init initmem_init(void)
 		nodes_clear(node_possible_map);
 		nodes_clear(node_online_map);
 #endif
-		/* Account for nodes with cpus and no memory */
-		nodes_or(node_possible_map, mem_nodes_parsed, cpu_nodes_parsed);
-		if (WARN_ON(nodes_empty(node_possible_map)))
+		if (numa_cleanup_meminfo(&numa_meminfo) < 0)
 			continue;
 
-		if (numa_register_memblks() < 0)
+		if (numa_register_memblks(&numa_meminfo) < 0)
 			continue;
 
 		for (j = 0; j < nr_cpu_ids; j++) {
Signature · 1 line
1.7.1
author
#70 lore raw

PATCH 20/26 x86-64, NUMA: make numa_cleanup_meminfo() prettier

In reply to Tejun Heo

* Factor out numa_remove_memblk_from().

* Hole detection doesn't need separate start/end. Calculate start/end once.

* Relocate comment.

* Define iterators at the top and remove unnecessary prefix increments.

This prepares for further improvements to the function.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/mm/numa_64.c |   36 +++++++++++++++++++-----------------
 1 files changed, 19 insertions(+), 17 deletions(-)
arch/x86/mm/numa_64.c +19 -17
index 4f173a5..62ba1fd 100644
@@ -230,6 +230,13 @@ int __init numa_add_memblk(int nid, u64 start, u64 end)
 	return 0;
 }
 
+static void __init numa_remove_memblk_from(int idx, struct numa_meminfo *mi)
+{
+	mi->nr_blks--;
+	memmove(&mi->blk[idx], &mi->blk[idx + 1],
+		(mi->nr_blks - idx) * sizeof(mi->blk[0]));
+}
+
 static __init void cutoff_node(int i, unsigned long start, unsigned long end)
 {
 	struct bootnode *nd = &numa_nodes[i];
@@ -294,25 +301,25 @@ setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)
 
 static int __init numa_cleanup_meminfo(struct numa_meminfo *mi)
 {
-	int i;
+	int i, j, k;
 
-	/*
-	 * Join together blocks on the same node, holes between
-	 * which don't overlap with memory on other nodes.
-	 */
-	for (i = 0; i < mi->nr_blks; ++i) {
+	for (i = 0; i < mi->nr_blks; i++) {
 		struct numa_memblk *bi = &mi->blk[i];
-		int j, k;
 
-		for (j = i + 1; j < mi->nr_blks; ++j) {
+		for (j = i + 1; j < mi->nr_blks; j++) {
 			struct numa_memblk *bj = &mi->blk[j];
 			unsigned long start, end;
 
+			/*
+			 * Join together blocks on the same node, holes
+			 * between which don't overlap with memory on other
+			 * nodes.
+			 */
 			if (bi->nid != bj->nid)
 				continue;
-			start = min(bi->end, bj->end);
-			end = max(bi->start, bj->start);
-			for (k = 0; k < mi->nr_blks; ++k) {
+			start = min(bi->start, bj->start);
+			end = max(bi->end, bj->end);
+			for (k = 0; k < mi->nr_blks; k++) {
 				struct numa_memblk *bk = &mi->blk[k];
 
 				if (bi->nid == bk->nid)
@@ -322,17 +329,12 @@ static int __init numa_cleanup_meminfo(struct numa_meminfo *mi)
 			}
 			if (k < mi->nr_blks)
 				continue;
-			start = min(bi->start, bj->start);
-			end = max(bi->end, bj->end);
 			printk(KERN_INFO "NUMA: Node %d [%Lx,%Lx) + [%Lx,%Lx) -> [%lx,%lx)\n",
 			       bi->nid, bi->start, bi->end, bj->start, bj->end,
 			       start, end);
 			bi->start = start;
 			bi->end = end;
-			k = --mi->nr_blks - j;
-			memmove(mi->blk + j, mi->blk + j + 1,
-				k * sizeof(mi->blk[0]));
-			--j;
+			numa_remove_memblk_from(j--, mi);
 		}
 	}
 
Signature · 1 line
1.7.1
author
#71 lore raw

PATCH 21/26 x86-64, NUMA: consolidate and improve memblk sanity checks

In reply to Tejun Heo

memblk sanity check was scattered around and incomplete. Consolidate and improve.

* Confliction detection and cutoff_node() logic are moved to numa_cleanup_meminfo().

* numa_cleanup_meminfo() clears the unused memblks before returning.

* Check and warn about invalid input parameters in numa_add_memblk().

* Check the maximum number of memblk isn't exceeded in numa_add_memblk().

* numa_cleanup_meminfo() is now called before numa_emulation() so that the emulation code also uses the cleaned up version.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/mm/numa_64.c |   99 ++++++++++++++++++++++++-------------------------
 1 files changed, 49 insertions(+), 50 deletions(-)
arch/x86/mm/numa_64.c +49 -50
index 62ba1fd..1996ee7 100644
@@ -189,37 +189,23 @@ static void * __init early_node_mem(int nodeid, unsigned long start,
 	return NULL;
 }
 
-static __init int conflicting_memblks(unsigned long start, unsigned long end)
+int __init numa_add_memblk(int nid, u64 start, u64 end)
 {
 	struct numa_meminfo *mi = &numa_meminfo;
-	int i;
 
-	for (i = 0; i < mi->nr_blks; i++) {
-		struct numa_memblk *blk = &mi->blk[i];
+	/* ignore zero length blks */
+	if (start == end)
+		return 0;
 
-		if (blk->start == blk->end)
-			continue;
-		if (blk->end > start && blk->start < end)
-			return blk->nid;
-		if (blk->end == end && blk->start == start)
-			return blk->nid;
+	/* whine about and ignore invalid blks */
+	if (start > end || nid < 0 || nid >= MAX_NUMNODES) {
+		pr_warning("NUMA: Warning: invalid memblk node %d (%Lx-%Lx)\n",
+			   nid, start, end);
+		return 0;
 	}
-	return -1;
-}
-
-int __init numa_add_memblk(int nid, u64 start, u64 end)
-{
-	struct numa_meminfo *mi = &numa_meminfo;
-	int i;
 
-	i = conflicting_memblks(start, end);
-	if (i == nid) {
-		printk(KERN_WARNING "NUMA: Warning: node %d (%Lx-%Lx) overlaps with itself (%Lx-%Lx)\n",
-		       nid, start, end, numa_nodes[i].start, numa_nodes[i].end);
-	} else if (i >= 0) {
-		printk(KERN_ERR "NUMA: node %d (%Lx-%Lx) overlaps with node %d (%Lx-%Lx)\n",
-		       nid, start, end, i,
-		       numa_nodes[i].start, numa_nodes[i].end);
+	if (mi->nr_blks >= NR_NODE_MEMBLKS) {
+		pr_err("NUMA: too many memblk ranges\n");
 		return -EINVAL;
 	}
 
@@ -237,22 +223,6 @@ static void __init numa_remove_memblk_from(int idx, struct numa_meminfo *mi)
 		(mi->nr_blks - idx) * sizeof(mi->blk[0]));
 }
 
-static __init void cutoff_node(int i, unsigned long start, unsigned long end)
-{
-	struct bootnode *nd = &numa_nodes[i];
-
-	if (nd->start < start) {
-		nd->start = start;
-		if (nd->end < nd->start)
-			nd->start = nd->end;
-	}
-	if (nd->end > end) {
-		nd->end = end;
-		if (nd->start > nd->end)
-			nd->start = nd->end;
-	}
-}
-
 /* Initialize bootmem allocator for a node */
 void __init
 setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)
@@ -301,24 +271,53 @@ setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)
 
 static int __init numa_cleanup_meminfo(struct numa_meminfo *mi)
 {
+	const u64 low = 0;
+	const u64 high = (u64)max_pfn << PAGE_SHIFT;
 	int i, j, k;
 
 	for (i = 0; i < mi->nr_blks; i++) {
 		struct numa_memblk *bi = &mi->blk[i];
 
+		/* make sure all blocks are inside the limits */
+		bi->start = max(bi->start, low);
+		bi->end = min(bi->end, high);
+
+		/* and there's no empty block */
+		if (bi->start == bi->end) {
+			numa_remove_memblk_from(i--, mi);
+			continue;
+		}
+
 		for (j = i + 1; j < mi->nr_blks; j++) {
 			struct numa_memblk *bj = &mi->blk[j];
 			unsigned long start, end;
 
 			/*
+			 * See whether there are overlapping blocks.  Whine
+			 * about but allow overlaps of the same nid.  They
+			 * will be merged below.
+			 */
+			if (bi->end > bj->start && bi->start < bj->end) {
+				if (bi->nid != bj->nid) {
+					pr_err("NUMA: node %d (%Lx-%Lx) overlaps with node %d (%Lx-%Lx)\n",
+					       bi->nid, bi->start, bi->end,
+					       bj->nid, bj->start, bj->end);
+					return -EINVAL;
+				}
+				pr_warning("NUMA: Warning: node %d (%Lx-%Lx) overlaps with itself (%Lx-%Lx)\n",
+					   bi->nid, bi->start, bi->end,
+					   bj->start, bj->end);
+			}
+
+			/*
 			 * Join together blocks on the same node, holes
 			 * between which don't overlap with memory on other
 			 * nodes.
 			 */
 			if (bi->nid != bj->nid)
 				continue;
-			start = min(bi->start, bj->start);
-			end = max(bi->end, bj->end);
+			start = max(min(bi->start, bj->start), low);
+			end = min(max(bi->end, bj->end), high);
 			for (k = 0; k < mi->nr_blks; k++) {
 				struct numa_memblk *bk = &mi->blk[k];
 
@@ -338,6 +337,11 @@ static int __init numa_cleanup_meminfo(struct numa_meminfo *mi)
 		}
 	}
 
+	for (i = mi->nr_blks; i < ARRAY_SIZE(mi->blk); i++) {
+		mi->blk[i].start = mi->blk[i].end = 0;
+		mi->blk[i].nid = NUMA_NO_NODE;
+	}
+
 	return 0;
 }
 
@@ -821,10 +825,8 @@ void __init initmem_init(void)
 		if (numa_init[i]() < 0)
 			continue;
 
-		/* clean up the node list */
-		for (j = 0; j < MAX_NUMNODES; j++)
-			cutoff_node(j, 0, max_pfn << PAGE_SHIFT);
-
+		if (numa_cleanup_meminfo(&numa_meminfo) < 0)
+			continue;
 #ifdef CONFIG_NUMA_EMU
 		setup_physnodes(0, max_pfn << PAGE_SHIFT);
 		if (cmdline && !numa_emulation(0, max_pfn, i == 0, i == 1))
@@ -833,9 +835,6 @@ void __init initmem_init(void)
 		nodes_clear(node_possible_map);
 		nodes_clear(node_online_map);
 #endif
-		if (numa_cleanup_meminfo(&numa_meminfo) < 0)
-			continue;
-
 		if (numa_register_memblks(&numa_meminfo) < 0)
 			continue;
 
Signature · 1 line
1.7.1
author
#72 lore raw

PATCH 22/26 x86-64, NUMA: Add common find_node_by_addr()

In reply to Tejun Heo

srat_64.c and amdtopology_64.c had their own versions of find_node_by_addr() which were basically the same. Add common one in numa_64.c and remove the duplicates.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/include/asm/numa_64.h |    1 +
 arch/x86/mm/amdtopology_64.c   |   13 -------------
 arch/x86/mm/numa_64.c          |   19 +++++++++++++++++++
 arch/x86/mm/srat_64.c          |   18 ------------------
 4 files changed, 20 insertions(+), 31 deletions(-)
arch/x86/include/asm/numa_64.h +1 -0
index fbc9d33..867d41b 100644
@@ -36,6 +36,7 @@ extern int __init numa_add_memblk(int nodeid, u64 start, u64 end);
 #define FAKE_NODE_MIN_SIZE	((u64)32 << 20)
 #define FAKE_NODE_MIN_HASH_MASK	(~(FAKE_NODE_MIN_SIZE - 1UL))
 void numa_emu_cmdline(char *);
+int __init find_node_by_addr(unsigned long addr);
 #endif /* CONFIG_NUMA_EMU */
 #else
 static inline int numa_cpu_node(int cpu)		{ return NUMA_NO_NODE; }
arch/x86/mm/amdtopology_64.c +0 -13
index 90cf297..8f7a5eb 100644
@@ -205,19 +205,6 @@ static s16 fake_apicid_to_node[MAX_LOCAL_APIC] __initdata = {
 	[0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE
 };
 
-static int __init find_node_by_addr(unsigned long addr)
-{
-	int ret = NUMA_NO_NODE;
-	int i;
-
-	for (i = 0; i < 8; i++)
-		if (addr >= numa_nodes[i].start && addr < numa_nodes[i].end) {
-			ret = i;
-			break;
-		}
-	return ret;
-}
-
 /*
  * For NUMA emulation, fake proximity domain (_PXM) to node id mappings must be
  * setup to represent the physical topology but reflect the emulated
arch/x86/mm/numa_64.c +19 -0
index 1996ee7..ea3fb52 100644
@@ -428,6 +428,25 @@ void __init numa_emu_cmdline(char *str)
 	cmdline = str;
 }
 
+int __init find_node_by_addr(unsigned long addr)
+{
+	int ret = NUMA_NO_NODE;
+	int i;
+
+	for_each_node_mask(i, mem_nodes_parsed) {
+		/*
+		 * Find the real node that this emulated node appears on.  For
+		 * the sake of simplicity, we only use a real node's starting
+		 * address to determine which emulated node it appears on.
+		 */
+		if (addr >= numa_nodes[i].start && addr < numa_nodes[i].end) {
+			ret = i;
+			break;
+		}
+	}
+	return ret;
+}
+
 static int __init setup_physnodes(unsigned long start, unsigned long end)
 {
 	int ret = 0;
arch/x86/mm/srat_64.c +0 -18
index d56eff8..51d0733 100644
@@ -277,24 +277,6 @@ static int fake_node_to_pxm_map[MAX_NUMNODES] __initdata = {
 static s16 fake_apicid_to_node[MAX_LOCAL_APIC] __initdata = {
 	[0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE
 };
-static int __init find_node_by_addr(unsigned long addr)
-{
-	int ret = NUMA_NO_NODE;
-	int i;
-
-	for_each_node_mask(i, mem_nodes_parsed) {
-		/*
-		 * Find the real node that this emulated node appears on.  For
-		 * the sake of simplicity, we only use a real node's starting
-		 * address to determine which emulated node it appears on.
-		 */
-		if (addr >= numa_nodes[i].start && addr < numa_nodes[i].end) {
-			ret = i;
-			break;
-		}
-	}
-	return ret;
-}
 
 /*
  * In NUMA emulation, we need to setup proximity domain (_PXM) to node ID
Signature · 1 line
1.7.1
author
#73 lore raw

PATCH 23/26 x86-64, NUMA: kill numa_nodes[]

In reply to Tejun Heo

numa_nodes[] doesn't carry any information which isn't present in numa_meminfo. Each entry is simply min/max range of all the memblks for the node. This is not only redundant but also inaccurate when memblks for different nodes interleave - for example, find_node_by_addr() can return the wrong nodeid.

Kill numa_nodes[] and always use numa_meminfo instead.

* nodes_cover_memory() is renamed to numa_meminfo_cover_memory() and now operations on numa_meminfo and returns bool.

* setup_node_bootmem() needs min/max range. Compute the range on the fly. setup_node_bootmem() invocation is restructured to use outer loop instead of hardcoding the double invocations.

* find_node_by_addr() now operates on numa_meminfo.

* setup_physnodes() builds physnodes[] from memblks. This will go away when emulation code is updated to use struct numa_meminfo.

This patch also makes the following misc changes.

* Clearing of nodes_add[] clearing is converted to memset().

* numa_add_memblk() in amd_numa_init() is moved down a bit for consistency.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/include/asm/numa_64.h |    1 -
 arch/x86/mm/amdtopology_64.c   |    6 +--
 arch/x86/mm/numa_64.c          |   82 +++++++++++++++++++++++----------------
 arch/x86/mm/srat_64.c          |   22 ++---------
 4 files changed, 53 insertions(+), 58 deletions(-)
arch/x86/include/asm/numa_64.h +0 -1
index 867d41b..da5c501 100644
@@ -27,7 +27,6 @@ extern void setup_node_bootmem(int nodeid, unsigned long start,
 
 extern nodemask_t cpu_nodes_parsed __initdata;
 extern nodemask_t mem_nodes_parsed __initdata;
-extern struct bootnode numa_nodes[MAX_NUMNODES] __initdata;
 
 extern int __cpuinit numa_cpu_node(int cpu);
 extern int __init numa_add_memblk(int nodeid, u64 start, u64 end);
arch/x86/mm/amdtopology_64.c +1 -5
index 8f7a5eb..0cb59e5 100644
@@ -165,12 +165,8 @@ int __init amd_numa_init(void)
 		pr_info("Node %d MemBase %016lx Limit %016lx\n",
 			nodeid, base, limit);
 
-		numa_nodes[nodeid].start = base;
-		numa_nodes[nodeid].end = limit;
-		numa_add_memblk(nodeid, base, limit);
-
 		prevbase = base;
-
+		numa_add_memblk(nodeid, base, limit);
 		node_set(nodeid, mem_nodes_parsed);
 		node_set(nodeid, cpu_nodes_parsed);
 	}
arch/x86/mm/numa_64.c +48 -34

156 lines not on this page · raw message

arch/x86/mm/srat_64.c +4 -18
index 51d0733..e8b3b3c 100644
@@ -37,13 +37,9 @@ static __init int setup_node(int pxm)
 
 static __init void bad_srat(void)
 {
-	int i;
 	printk(KERN_ERR "SRAT: SRAT not used.\n");
 	acpi_numa = -1;
-	for (i = 0; i < MAX_NUMNODES; i++) {
-		numa_nodes[i].start = numa_nodes[i].end = 0;
-		nodes_add[i].start = nodes_add[i].end = 0;
-	}
+	memset(nodes_add, 0, sizeof(nodes_add));
 }
 
 static __init inline int srat_disabled(void)
@@ -210,7 +206,6 @@ update_nodes_add(int node, unsigned long start, unsigned long end)
 void __init
 acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
 {
-	struct bootnode *nd;
 	unsigned long start, end;
 	int node, pxm;
 
@@ -243,18 +238,9 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
 	printk(KERN_INFO "SRAT: Node %u PXM %u %lx-%lx\n", node, pxm,
 	       start, end);
 
-	if (!(ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)) {
-		nd = &numa_nodes[node];
-		if (!node_test_and_set(node, mem_nodes_parsed)) {
-			nd->start = start;
-			nd->end = end;
-		} else {
-			if (start < nd->start)
-				nd->start = start;
-			if (nd->end < end)
-				nd->end = end;
-		}
-	} else
+	if (!(ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE))
+		node_set(node, mem_nodes_parsed);
+	else
 		update_nodes_add(node, start, end);
 }
 
Signature · 1 line
1.7.1
author
#74 lore raw

PATCH 24/26 x86-64, NUMA: Rename cpu_nodes_parsed to numa_nodes_parsed

In reply to Tejun Heo

It's no longer necessary to keep both cpu_nodes_parsed and mem_nodes_parsed. In preparation for merge, rename cpu_nodes_parsed to numa_nodes_parsed.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/include/asm/numa_64.h |    2 +-
 arch/x86/mm/amdtopology_64.c   |    4 ++--
 arch/x86/mm/numa_64.c          |    8 ++++----
 arch/x86/mm/srat_64.c          |    6 +++---
 4 files changed, 10 insertions(+), 10 deletions(-)
arch/x86/include/asm/numa_64.h +1 -1
index da5c501..da57c70 100644
@@ -25,7 +25,7 @@ extern void setup_node_bootmem(int nodeid, unsigned long start,
 #define NODE_MIN_SIZE		(4*1024*1024)
 #define NR_NODE_MEMBLKS		(MAX_NUMNODES*2)
 
-extern nodemask_t cpu_nodes_parsed __initdata;
+extern nodemask_t numa_nodes_parsed __initdata;
 extern nodemask_t mem_nodes_parsed __initdata;
 
 extern int __cpuinit numa_cpu_node(int cpu);
arch/x86/mm/amdtopology_64.c +2 -2
index 0cb59e5..e76bffa 100644
@@ -168,7 +168,7 @@ int __init amd_numa_init(void)
 		prevbase = base;
 		numa_add_memblk(nodeid, base, limit);
 		node_set(nodeid, mem_nodes_parsed);
-		node_set(nodeid, cpu_nodes_parsed);
+		node_set(nodeid, numa_nodes_parsed);
 	}
 
 	if (!nodes_weight(mem_nodes_parsed))
@@ -189,7 +189,7 @@ int __init amd_numa_init(void)
 		apicid_base = boot_cpu_physical_apicid;
 	}
 
-	for_each_node_mask(i, cpu_nodes_parsed)
+	for_each_node_mask(i, numa_nodes_parsed)
 		for (j = apicid_base; j < cores + apicid_base; j++)
 			set_apicid_to_node((i << bits) + j, i);
 
arch/x86/mm/numa_64.c +4 -4
index c0e45c7..1797392 100644
@@ -36,7 +36,7 @@ struct numa_meminfo {
 struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
 EXPORT_SYMBOL(node_data);
 
-nodemask_t cpu_nodes_parsed __initdata;
+nodemask_t numa_nodes_parsed __initdata;
 nodemask_t mem_nodes_parsed __initdata;
 
 struct memnode memnode;
@@ -379,7 +379,7 @@ static int __init numa_register_memblks(struct numa_meminfo *mi)
 	int i, j, nid;
 
 	/* Account for nodes with cpus and no memory */
-	nodes_or(node_possible_map, mem_nodes_parsed, cpu_nodes_parsed);
+	nodes_or(node_possible_map, mem_nodes_parsed, numa_nodes_parsed);
 	if (WARN_ON(nodes_empty(node_possible_map)))
 		return -EINVAL;
 
@@ -820,7 +820,7 @@ static int dummy_numa_init(void)
 	printk(KERN_INFO "Faking a node at %016lx-%016lx\n",
 	       0LU, max_pfn << PAGE_SHIFT);
 
-	node_set(0, cpu_nodes_parsed);
+	node_set(0, numa_nodes_parsed);
 	node_set(0, mem_nodes_parsed);
 	numa_add_memblk(0, 0, (u64)max_pfn << PAGE_SHIFT);
 
@@ -848,7 +848,7 @@ void __init initmem_init(void)
 		for (j = 0; j < MAX_LOCAL_APIC; j++)
 			set_apicid_to_node(j, NUMA_NO_NODE);
 
-		nodes_clear(cpu_nodes_parsed);
+		nodes_clear(numa_nodes_parsed);
 		nodes_clear(mem_nodes_parsed);
 		nodes_clear(node_possible_map);
 		nodes_clear(node_online_map);
arch/x86/mm/srat_64.c +3 -3
index e8b3b3c..8185189 100644
@@ -94,7 +94,7 @@ acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa)
 		return;
 	}
 	set_apicid_to_node(apic_id, node);
-	node_set(node, cpu_nodes_parsed);
+	node_set(node, numa_nodes_parsed);
 	acpi_numa = 1;
 	printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%04x -> Node %u\n",
 	       pxm, apic_id, node);
@@ -134,7 +134,7 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
 	}
 
 	set_apicid_to_node(apic_id, node);
-	node_set(node, cpu_nodes_parsed);
+	node_set(node, numa_nodes_parsed);
 	acpi_numa = 1;
 	printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%02x -> Node %u\n",
 	       pxm, apic_id, node);
@@ -196,7 +196,7 @@ update_nodes_add(int node, unsigned long start, unsigned long end)
 	}
 
 	if (changed) {
-		node_set(node, cpu_nodes_parsed);
+		node_set(node, numa_nodes_parsed);
 		printk(KERN_INFO "SRAT: hot plug zone found %Lx - %Lx\n",
 				 nd->start, nd->end);
 	}
Signature · 1 line
1.7.1
author
#75 lore raw

PATCH 25/26 x86-64, NUMA: Kill mem_nodes_parsed

In reply to Tejun Heo

With all memory configuration information now carried in numa_meminfo, there's no need to keep mem_nodes_parsed separate. Drop it and use numa_nodes_parsed for CPU / memory-less nodes.

A new helper numa_nodemask_from_meminfo() is added to calculate memnode mask on the fly which is currently used to set node_possible_map.

This simplifies NUMA init methods a bit and removes a source of possible inconsistencies.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/include/asm/numa_64.h |    1 -
 arch/x86/mm/amdtopology_64.c   |    5 ++---
 arch/x86/mm/numa_64.c          |   20 ++++++++++++++++----
 arch/x86/mm/srat_64.c          |    7 ++-----
 4 files changed, 20 insertions(+), 13 deletions(-)
arch/x86/include/asm/numa_64.h +0 -1
index da57c70..04e74d8 100644
@@ -26,7 +26,6 @@ extern void setup_node_bootmem(int nodeid, unsigned long start,
 #define NR_NODE_MEMBLKS		(MAX_NUMNODES*2)
 
 extern nodemask_t numa_nodes_parsed __initdata;
-extern nodemask_t mem_nodes_parsed __initdata;
 
 extern int __cpuinit numa_cpu_node(int cpu);
 extern int __init numa_add_memblk(int nodeid, u64 start, u64 end);
arch/x86/mm/amdtopology_64.c +2 -3
index e76bffa..fd7b609 100644
@@ -122,7 +122,7 @@ int __init amd_numa_init(void)
 			       nodeid, (base >> 8) & 3, (limit >> 8) & 3);
 			return -EINVAL;
 		}
-		if (node_isset(nodeid, mem_nodes_parsed)) {
+		if (node_isset(nodeid, numa_nodes_parsed)) {
 			pr_info("Node %d already present, skipping\n",
 				nodeid);
 			continue;
@@ -167,11 +167,10 @@ int __init amd_numa_init(void)
 
 		prevbase = base;
 		numa_add_memblk(nodeid, base, limit);
-		node_set(nodeid, mem_nodes_parsed);
 		node_set(nodeid, numa_nodes_parsed);
 	}
 
-	if (!nodes_weight(mem_nodes_parsed))
+	if (!nodes_weight(numa_nodes_parsed))
 		return -ENOENT;
 
 	/*
arch/x86/mm/numa_64.c +16 -4
index 1797392..9dd4a34 100644
@@ -37,7 +37,6 @@ struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
 EXPORT_SYMBOL(node_data);
 
 nodemask_t numa_nodes_parsed __initdata;
-nodemask_t mem_nodes_parsed __initdata;
 
 struct memnode memnode;
 
@@ -344,6 +343,20 @@ static int __init numa_cleanup_meminfo(struct numa_meminfo *mi)
 }
 
 /*
+ * Set nodes, which have memory in @mi, in *@nodemask.
+ */
+static void __init numa_nodemask_from_meminfo(nodemask_t *nodemask,
+					      const struct numa_meminfo *mi)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mi->blk); i++)
+		if (mi->blk[i].start != mi->blk[i].end &&
+		    mi->blk[i].nid != NUMA_NO_NODE)
+			node_set(mi->blk[i].nid, *nodemask);
+}
+
+/*
  * Sanity check to catch more bad NUMA configurations (they are amazingly
  * common).  Make sure the nodes cover all memory.
  */
@@ -379,7 +392,8 @@ static int __init numa_register_memblks(struct numa_meminfo *mi)
 	int i, j, nid;
 
 	/* Account for nodes with cpus and no memory */
-	nodes_or(node_possible_map, mem_nodes_parsed, numa_nodes_parsed);
+	node_possible_map = numa_nodes_parsed;
+	numa_nodemask_from_meminfo(&node_possible_map, mi);
 	if (WARN_ON(nodes_empty(node_possible_map)))
 		return -EINVAL;
 
@@ -821,7 +835,6 @@ static int dummy_numa_init(void)
 	       0LU, max_pfn << PAGE_SHIFT);
 
 	node_set(0, numa_nodes_parsed);
-	node_set(0, mem_nodes_parsed);
 	numa_add_memblk(0, 0, (u64)max_pfn << PAGE_SHIFT);
 
 	return 0;
@@ -849,7 +862,6 @@ void __init initmem_init(void)
 			set_apicid_to_node(j, NUMA_NO_NODE);
 
 		nodes_clear(numa_nodes_parsed);
-		nodes_clear(mem_nodes_parsed);
 		nodes_clear(node_possible_map);
 		nodes_clear(node_online_map);
 		memset(&numa_meminfo, 0, sizeof(numa_meminfo));
arch/x86/mm/srat_64.c +2 -5
index 8185189..4f8e6cd 100644
@@ -238,9 +238,7 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
 	printk(KERN_INFO "SRAT: Node %u PXM %u %lx-%lx\n", node, pxm,
 	       start, end);
 
-	if (!(ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE))
-		node_set(node, mem_nodes_parsed);
-	else
+	if (ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)
 		update_nodes_add(node, start, end);
 }
 
@@ -310,10 +308,9 @@ void __init acpi_fake_nodes(const struct bootnode *fake_nodes, int num_nodes)
 		__acpi_map_pxm_to_node(fake_node_to_pxm_map[i], i);
 	memcpy(__apicid_to_node, fake_apicid_to_node, sizeof(__apicid_to_node));
 
-	nodes_clear(mem_nodes_parsed);
 	for (i = 0; i < num_nodes; i++)
 		if (fake_nodes[i].start != fake_nodes[i].end)
-			node_set(i, mem_nodes_parsed);
+			node_set(i, numa_nodes_parsed);
 }
 
 static int null_slit_node_compare(int a, int b)
Signature · 1 line
1.7.1
author
#76 lore raw

PATCH 26/26 x86-64, NUMA: Implement generic node distance handling

In reply to Tejun Heo

Node distance either used direct node comparison, ACPI PXM comparison or ACPI SLIT table lookup. This patch implements generic node distance handling. NUMA init methods can call numa_set_distance() to set distance between nodes and the common __node_distance() implementation will report the set distance.

Due to the way NUMA emulation is implemented, the generic node distance handling is used only when emulation is not used. Later patches will update NUMA emulation to use the generic distance mechanism.

Cc Yinghai Lu <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Cyrill Gorcunov <[email protected]>
Cc Shaohui Zheng <[email protected]>
Cc David Rientjes <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc H. Peter Anvin <[email protected]>
---
 arch/x86/include/asm/acpi.h     |    1 +
 arch/x86/include/asm/numa_64.h  |    1 +
 arch/x86/include/asm/topology.h |    2 +-
 arch/x86/mm/numa_64.c           |   95 +++++++++++++++++++++++++++++++++++++++
 arch/x86/mm/srat_64.c           |   27 +++++-------
 5 files changed, 109 insertions(+), 17 deletions(-)
arch/x86/include/asm/acpi.h +1 -0
index cfa3d5c..9c9fe1b 100644
@@ -190,6 +190,7 @@ extern int x86_acpi_numa_init(void);
 #ifdef CONFIG_NUMA_EMU
 extern void acpi_fake_nodes(const struct bootnode *fake_nodes,
 				   int num_nodes);
+extern int acpi_emu_node_distance(int a, int b);
 #endif
 #endif /* CONFIG_ACPI_NUMA */
 
arch/x86/include/asm/numa_64.h +1 -0
index 04e74d8..972af9d 100644
@@ -29,6 +29,7 @@ extern nodemask_t numa_nodes_parsed __initdata;
 
 extern int __cpuinit numa_cpu_node(int cpu);
 extern int __init numa_add_memblk(int nodeid, u64 start, u64 end);
+extern void __init numa_set_distance(int from, int to, int distance);
 
 #ifdef CONFIG_NUMA_EMU
 #define FAKE_NODE_MIN_SIZE	((u64)32 << 20)
arch/x86/include/asm/topology.h +1 -1
index b101c17..910a708 100644
@@ -138,7 +138,7 @@ extern unsigned long node_remap_size[];
 	.balance_interval	= 1,					\
 }
 
-#ifdef CONFIG_X86_64_ACPI_NUMA
+#ifdef CONFIG_X86_64
 extern int __node_distance(int, int);
 #define node_distance(a, b) __node_distance(a, b)
 #endif
arch/x86/mm/numa_64.c +95 -0

119 lines not on this page · raw message

arch/x86/mm/srat_64.c +11 -16
index 4f8e6cd..d2f53f3 100644
@@ -50,9 +50,16 @@ static __init inline int srat_disabled(void)
 /* Callback for SLIT parsing */
 void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
 {
+	int i, j;
 	unsigned length;
 	unsigned long phys;
 
+	for (i = 0; i < slit->locality_count; i++)
+		for (j = 0; j < slit->locality_count; j++)
+			numa_set_distance(pxm_to_node(i), pxm_to_node(j),
+				slit->entry[slit->locality_count * i + j]);
+
+	/* acpi_slit is used only by emulation */
 	length = slit->header.length;
 	phys = memblock_find_in_range(0, max_pfn_mapped<<PAGE_SHIFT, length,
 		 PAGE_SIZE);
@@ -313,29 +320,17 @@ void __init acpi_fake_nodes(const struct bootnode *fake_nodes, int num_nodes)
 			node_set(i, numa_nodes_parsed);
 }
 
-static int null_slit_node_compare(int a, int b)
-{
-	return node_to_pxm(a) == node_to_pxm(b);
-}
-#else
-static int null_slit_node_compare(int a, int b)
-{
-	return a == b;
-}
-#endif /* CONFIG_NUMA_EMU */
-
-int __node_distance(int a, int b)
+int acpi_emu_node_distance(int a, int b)
 {
 	int index;
 
 	if (!acpi_slit)
-		return null_slit_node_compare(a, b) ? LOCAL_DISTANCE :
-						      REMOTE_DISTANCE;
+		return node_to_pxm(a) == node_to_pxm(b) ?
+			LOCAL_DISTANCE : REMOTE_DISTANCE;
 	index = acpi_slit->locality_count * node_to_pxm(a);
 	return acpi_slit->entry[index + node_to_pxm(b)];
 }
-
-EXPORT_SYMBOL(__node_distance);
+#endif /* CONFIG_NUMA_EMU */
 
 #if defined(CONFIG_MEMORY_HOTPLUG_SPARSE) || defined(CONFIG_ACPI_HOTPLUG_MEMORY)
 int memory_add_physaddr_to_nid(u64 start)
Signature · 1 line
1.7.1