x86-64, NUMA: bring sanity to NUMA configuration
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())
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.
--- arch/x86/mm/numa_64.c | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-)
arch/x86/mm/numa_64.c +3 -2
@@ -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
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 calingnuma_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 byinit_cpu_to_node()later.Signed-off-by Tejun Heo <[email protected]>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@@ -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 )
PATCH 2/26 x86-64, NUMA: Simplify hotplug node handling in acpi_numa_memory_affinity_init()
In reply to Tejun HeoHotplug 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.
--- arch/x86/mm/srat_64.c | 31 +++++++++++++------------------ 1 files changed, 13 insertions(+), 18 deletions(-)
arch/x86/mm/srat_64.c +13 -18
@@ -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
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.Signed-off-by Tejun Heo <[email protected]>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@@ -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
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 likenodes_parsedis 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
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 likenodes_parsedis 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 abovenode_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
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.
thennd->startandnd->endwill be set to that hot plug range. and old code does not clearnodes_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
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.
thennd->startandnd->endwill be set to that hot plug range. and old code does not clearnodes_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
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_parsedset 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
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_parsedset for that kind of node.So, this is the code snippet. Both @nd->start and end are zero and
nodes_parsedfor @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
PATCH 3/26 x86-64, NUMA: Drop @start/last_pfn from initmem_init()
In reply to Tejun Heoinitmem_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.
--- 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
@@ -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
@@ -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
@@ -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
@@ -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
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.Signed-off-by Tejun Heo <[email protected]>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
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
PATCH 3/26 x86, NUMA: Drop @start/last_pfn from initmem_init() initmem_init()
In reply to Tejun Heoinitmem_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.
---
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
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
Signed-off-by Tejun Heo <[email protected]>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
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:
Reported-by Yinghai Lu <[email protected]>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
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:
Reported-by Yinghai Lu <[email protected]>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
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
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 YinghaiAlright, updated accordingly in the git tree.
Yeah, that kind of tag is fine too, or:
Build-bug-in-v1-found-by: ...
:-)
Thanks,
Ingo
PATCH 4/26 x86-64, NUMA: Unify {acpi|amd}_{numa_init|scan_nodes}() arguments and return values
In reply to Tejun HeoThe 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.
--- 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
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.Signed-off-by Tejun Heo <[email protected]>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@@ -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@@ -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@@ -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@@ -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@@ -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@@ -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@@ -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
-1acpi_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
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
-0int acpi_get_pxm (acpi_handle h)it will break AMD system that does not have SRAT.
your change will treat
NO_SRATas 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
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_SRATas 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
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
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,-ENOENTis returned.
return 0;
The function returns 0 iff cnt > 0.
oh, I missed it again.
Yinghai
PATCH 5/26 x86-64, NUMA: Wrap acpi_numa_init() so that failure can be indicated by return value
In reply to Tejun HeoBecause 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.
--- 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
@@ -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
@@ -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
@@ -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
PATCH 6/26 x86-64, NUMA: Move *_numa_init() invocations into initmem_init()
In reply to Tejun HeoThere's no reason for these to live in setup_arch(). Move them inside initmem_init().
--- 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
@@ -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
@@ -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
@@ -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
@@ -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
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 insideinitmem_init().Signed-off-by Tejun Heo <[email protected]>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
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 insideinitmem_init().Signed-off-by Tejun Heo <[email protected]>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
PATCH 6/26 x86, NUMA: Move *_numa_init() invocations into initmem_init()
In reply to Tejun HeoThere'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.
---
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
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 insideinitmem_init().* x86-32
initmem_init()weren't updated breaking 32bit builds. Fixed.Signed-off-by Tejun Heo <[email protected]>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 32bitinitmem_init()too. Both parameters weren't being used in 32bit versions. git tree updated accordingly.
This commit is missing a:
tag.
Thanks,
Ingo
PATCH 7/26 x86-64, NUMA: Restructure initmem_init()
In reply to Tejun HeoReorganize 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.
--- 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
@@ -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
@@ -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
PATCH 8/26 x86-64, NUMA: Use common {cpu|mem}_nodes_parsed
In reply to Tejun HeoACPI 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.
--- 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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH 9/26 x86-64, NUMA: Remove local variable found from amd_numa_init()
In reply to Tejun HeoUse weight count on mem_nodes_parsed instead.
--- arch/x86/mm/amdtopology_64.c | 6 ++---- 1 files changed, 2 insertions(+), 4 deletions(-)
arch/x86/mm/amdtopology_64.c +2 -4
@@ -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
PATCH 10/26 x86-64, NUMA: Move apicid to numa mapping initialization from amd_scan_nodes() to amd_numa_init()
In reply to Tejun HeoThis brings amd initialization behavior closer to that of acpi.
--- arch/x86/mm/amdtopology_64.c | 40 ++++++++++++++++++++++------------------ 1 files changed, 22 insertions(+), 18 deletions(-)
arch/x86/mm/amdtopology_64.c +22 -18
@@ -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
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.
Signed-off-by Tejun Heo<[email protected]>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@@ -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
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_baseconditional assignment is
redundant here (boot_cpu_physical_apicidis 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
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_baseconditional assignment is
redundant here (boot_cpu_physical_apicidis unsigned int) so we might have something likeQuoted 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; }
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_baseconditional assignment is
redundant here (boot_cpu_physical_apicidis unsigned int) so we might have
something likeQuoted 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_apicidremains =-1U and then we betterBUG_ONinstead of possible access of out-of-range__apicid_to_nodearray. If MADT is parsed successfullyboot_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 forset_apicid_to_node(apicid, )never exceedMAX_LOCAL_APICas well.Yinghai am I missing something?
--
Cyrill---
x86, numa: amd -- Check for screwed MADT tableIn case if MADT table is corrupted we might end up with
boot_cpu_physical_apicid= -1U, corebits > 0 and get out of__apicid_to_nodearray bound access. Check forboot_cpu_physical_apicidbeing 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
=====================================================================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
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
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;
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 GorcunovQuoted 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
PATCH 11/26 x86-64, NUMA: Use common numa_nodes[]
In reply to Tejun HeoACPI 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.
--- 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
@@ -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
@@ -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
@@ -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
PATCH 12/26 x86-64, NUMA: Kill {acpi|amd}_get_nodes()
In reply to Tejun HeoWith common numa_nodes[], common code in numa_64.c can access it directly. Copy directly and kill {acpi|amd}_get_nodes().
--- 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH 13/26 x86-64, NUMA: Factor out memblk handling into numa_{add|register}_memblk()
In reply to Tejun HeoFactor 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.
--- 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
@@ -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
@@ -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
PATCH 14/26 x86-64, NUMA: Unify use of memblk in all init methods
In reply to Tejun HeoMake 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.
--- 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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH 15/26 x86-64, NUMA: Unify the rest of memblk registration
In reply to Tejun HeoMove 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().
--- 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
@@ -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
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()tonuma_register_memblks()andinitmem_init().This applies
nodes_cover_memory()sanity check, memory node sorting andnode_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 frombad_srat().Signed-off-by Tejun Heo <[email protected]>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@@ -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@@ -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@@ -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 ; }
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_bootmemcalling intonuma_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
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_bootmemcalling intonuma_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_meminfoanyway so maybe it's better to rename it tonuma_register_meminfo().
No, I don't like ***_register_*** take care of calling setup_bootmem.
Yinghai
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_meminfoanyway so maybe it's better to rename it tonuma_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
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_meminfoanyway so maybe it's better to rename it tonuma_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
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 structnuma_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
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 structnuma_meminfo.No, register meminfo doesn't create
numa_meminfo. It sets up system states according to the configuration information innuma_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
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 maybeinit_memory_mapping_high...) out that__register__function.that
__register__function do some sth likememblock_registerto 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
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 maybeinit_memory_mapping_high...) out that__register__function.that
__register__function do some sth likememblock_registerto 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
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
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
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
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
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.cwith 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
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.cwith 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.gitx86_64-numa-unify
git://git.kernel.org/pub/scm/linux/kernel/git/tj/misc.gitx86_64-numa-emu-unifyThe 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
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.harch/x86/include/asm/page_types.harch/x86/mm/amdtopology_64.carch/x86/mm/init_64.carch/x86/mm/numa_64.carch/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
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
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
PATCH 16/26 x86-64, NUMA: Kill {acpi|amd|dummy}_scan_nodes()
In reply to Tejun HeoThey are empty now. Kill them.
--- 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH 17/26 x86-64, NUMA: Remove %NULL @nodeids handling from compute_hash_shift()
In reply to Tejun Heonuma_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.
--- arch/x86/mm/numa_64.c | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-)
arch/x86/mm/numa_64.c +7 -7
@@ -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
PATCH 18/26 x86-64, NUMA: Introduce struct numa_meminfo
In reply to Tejun HeoArrays 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.
--- arch/x86/mm/numa_64.c | 145 +++++++++++++++++++++++++------------------------ 1 files changed, 75 insertions(+), 70 deletions(-)
arch/x86/mm/numa_64.c +75 -70
@@ -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
PATCH 19/26 x86-64, NUMA: Separate out numa_cleanup_meminfo()
In reply to Tejun HeoSeparate 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.
--- arch/x86/mm/numa_64.c | 83 +++++++++++++++++++++++++++---------------------- 1 files changed, 46 insertions(+), 37 deletions(-)
arch/x86/mm/numa_64.c +46 -37
@@ -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
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.
--- arch/x86/mm/numa_64.c | 36 +++++++++++++++++++----------------- 1 files changed, 19 insertions(+), 17 deletions(-)
arch/x86/mm/numa_64.c +19 -17
@@ -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
PATCH 21/26 x86-64, NUMA: consolidate and improve memblk sanity checks
In reply to Tejun Heomemblk 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.
--- arch/x86/mm/numa_64.c | 99 ++++++++++++++++++++++++------------------------- 1 files changed, 49 insertions(+), 50 deletions(-)
arch/x86/mm/numa_64.c +49 -50
@@ -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
PATCH 22/26 x86-64, NUMA: Add common find_node_by_addr()
In reply to Tejun Heosrat_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.
--- 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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH 23/26 x86-64, NUMA: kill numa_nodes[]
In reply to Tejun Heonuma_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.
--- 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
@@ -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
@@ -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
@@ -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
PATCH 24/26 x86-64, NUMA: Rename cpu_nodes_parsed to numa_nodes_parsed
In reply to Tejun HeoIt'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.
--- 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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH 25/26 x86-64, NUMA: Kill mem_nodes_parsed
In reply to Tejun HeoWith 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.
--- 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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH 26/26 x86-64, NUMA: Implement generic node distance handling
In reply to Tejun HeoNode 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.
--- 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
@@ -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
@@ -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
@@ -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
@@ -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