patch [1/1] x86_64 numa aware sparsemem add_memory functinality
RFC 1/1 patch [1/1] x86_64 numa aware sparsemem add_memory functinality
Hello all,
This patch is an attempt to add a numa ware add_memory functionality
to x86_64 using CONFIG_SPARSEMEM. The add memory function today just grabs the pgdat from node 0 and adds the memory there. On a numa system this is functional but not optimal/correct.
The SRAT can expose future memory locality. This information is
already tracked by the nodes_add data structure (it keeps the memory/node locality information) from the SRAT code. The code in srat.c is built around RESERVE_HOTADD. This patch is a little subtle in the way it uses the existing code for use with sparsemem. Perhaps acpi_numa_memory_affinity_init needs a larger refactor to fit both RESERVE_HOTADD and sparsemem.
This patch still hotadd_percent as a flag to the whole srat parsing
code to disable and contain broken bios. It's functionality is retained and an on off switch to sparsemem hot-add. Without changing the safety mechanisms build into the current SRAT code I have provided a path for the sparsemem hot-add path to get to the nodes_add data for use at runtime.
This is a 1st run at the patch, it works with 2.6.17
arch/x86_64/mm/init.c +1 -1
@@ -553,7 +553,7 @@*/ int add_memory (u64 start,u64 size) { -struct pglist_data *pgdat =NODE_DATA (0 ); +struct pglist_data *pgdat =NODE_DATA (new_memory_to_node (start,start+size));struct zone *zone = pgdat->node_zones +MAX_NR_ZONES -2 ;unsigned long start_pfn = start >>PAGE_SHIFT ;unsigned long nr_pages = size >>PAGE_SHIFT ;
arch/x86_64/mm/srat.c +23 -14
@@ -32,10 +32,10 @@static nodemask_t nodes_parsed__initdata ;static nodemask_t nodes_found__initdata ;static struct bootnode nodes[MAX_NUMNODES ]__initdata ; -static struct bootnode nodes_add[MAX_NUMNODES ]__initdata ; +static struct bootnode nodes_add[MAX_NUMNODES ];static int found_add_area__initdata ;int hotadd_percent__initdata =0 ; -#ifndef RESERVE_HOTADD +#if !defined(RESERVE_HOTADD ) && !defined(CONFIG_MEMORY_HOTPLUG )#define hotadd_percent 0/* Ignore all settings */ #endif static u8 pxm2node[256 ] = { [0 ...255 ] =0xff };
@@ -219,9 +219,9 @@ allocated += mem; return 1; } - +#endif /* -* It is fine to add this area to the nodes data it will be used later +* It is fine to add this area to the nodes_add data it will be used later * This code supports one contigious hot add area per node. */ static int reserve_hotadd (int node,unsigned long start,unsigned long end)
@@ -247,15 +247,14 @@printk (KERN_ERR "SRAT: Hotplug area has existing memory\n" );return -1 ; } - +#ifdef RESERVE_HOTADD if (!hotadd_enough_memory (&nodes_add[node])) {printk (KERN_ERR "SRAT: Hotplug area too large\n" );return -1 ; } - +#endif /* Looks good */ - found_add_area =1 ;if (nd->start == nd->end) { nd->start = start; nd->end = end;
@@ -273,14 +272,16 @@printk (KERN_ERR "SRAT: Hotplug zone not continuous. Partly ignored\n" ); } -if ((nd->end >>PAGE_SHIFT ) > end_pfn) - end_pfn = nd->end >>PAGE_SHIFT ; -if (changed)printk (KERN_INFO "SRAT: hot plug zone found %Lx - %Lx\n" , nd->start, nd->end); +#ifdef RESERVE_HOTADD + found_add_area =1 ; +if ((nd->end >>PAGE_SHIFT ) > end_pfn) + end_pfn = nd->end >>PAGE_SHIFT ;return 0 ; +#endif +return -1 ; } -#endif /* Callback for parsing of the Proximity Domain <-> Memory Area mappings */ void __init
@@ -338,7 +339,6 @@printk (KERN_INFO "SRAT: Node %u PXM %u %Lx-%Lx\n" , node, pxm, nd->start, nd->end); -#ifdef RESERVE_HOTADD if (ma->flags.hot_pluggable &&reserve_hotadd (node, start, end) <0 ) {/* Ignore hotadd region. Undo damage */ printk (KERN_NOTICE "SRAT: Hotplug region ignored\n" );
@@ -346,7 +346,6 @@if ((nd->start | nd->end) ==0 )node_clear (node, nodes_parsed); } -#endif }/* Sanity check to catch more bad SRATs (they are amazingly common).
@@ -479,5 +478,15 @@ index = acpi_slit->localities *node_to_pxm (a);return acpi_slit->entry[index +node_to_pxm (b)]; } -EXPORT_SYMBOL (__node_distance); + +int new_memory_to_node (unsigned long start,unsigned long end) { +int i,ret; + ret=0 ; +for_each_node (i){ +if (nodes_add[i].start <= start && nodes_add[i].end >= end) + ret = i; + } +return ret; +} +EXPORT_SYMBOL (new_memory_to_node);
Quoted 6 lines · On Tue, 20 Jun 2006 22:43:01 -0700 keith mannthey <[email protected]> wrote:
Hello all,
This patch is an attempt to add a numa wareadd_memoryfunctionality
tox86_64usingCONFIG_SPARSEMEM. The add memory function today just grabs the pgdat from node 0 and adds the memory there. On a numa system this is functional but not optimal/correct.
At first, sorry for confusing. reserve_hotadd()/memory-hot-add with preallocated mem_map things are maintained by x86_64 and Andi Kleen (maybe).
So we (lhms people) are not familiar with this.
And yes, mem_map should be allocated from local node.
I'm now preparing "dynamic local mem_map allocation" for lhms's memory hotplug, which doesn't depend on SRAT.
Regards,
-Kame
Quoted 15 lines
The SRAT can expose future memory locality. This information is
already tracked by thenodes_adddata structure (it keeps the memory/node locality information) from the SRAT code. The code insrat.cis built aroundRESERVE_HOTADD. This patch is a little subtle in the way it uses the existing code for use with sparsemem. Perhapsacpi_numa_memory_affinity_initneeds a larger refactor to fit bothRESERVE_HOTADDand sparsemem.This patch still
hotadd_percentas a flag to the whole srat parsing
code to disable and contain broken bios. It's functionality is retained and an on off switch to sparsemem hot-add. Without changing the safety mechanisms build into the current SRAT code I have provided a path for the sparsemem hot-add path to get to thenodes_adddata for use at runtime.
Quoted 4 lines
This is a 1st run at the patch, it works with 2.6.17
Signed-off-by Keith Mannthey <[email protected]>
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 10 lines · KAMEZAWA Hiroyuki
Quoted 6 lines · On Tue, 20 Jun 2006 22:43:01 -0700 keith mannthey <[email protected]> wrote:
Hello all,
This patch is an attempt to add a numa wareadd_memoryfunctionality
tox86_64usingCONFIG_SPARSEMEM. The add memory function today just grabs the pgdat from node 0 and adds the memory there. On a numa system this is functional but not optimal/correct.
Quoted 4 lines
At first, sorry for confusing. reserve_hotadd()/memory-hot-add with preallocated
mem_mapthings are maintained byx86_64and Andi Kleen (maybe).
So we (lhms people) are not familiar with this.
Agreeded. I don't expect lhms to know much about reserve_hotadd().
Right now SPARSEMEM adds all it's memory to node 0 in x86_64. This is
the problem I am trying to fix. I doesn't make sense to me to rewrite the SRAT code when RESERVE_HOTADD has done most of the work already.
Quoted 3 lines
And yes,
mem_mapshould be allocated from local node.
I'm now preparing "dynamic localmem_mapallocation" for lhms's memory hotplug, which doesn't depend on SRAT.
How do you know which node to add the memory too without something like the SRAT that define memory locality of hot-add zones? SPARSEMEM doesn't depend on SRAT (it just needs to use to to know what zone to add to.)
This patch isn't about mem_map allocation rather what zone to add the memory to when doing SPASEMEM hot-add. A numa aware mem_map allocation would belong in generic SPARSEMEM code.
Quoted 27 lines
Quoted 16 lines
The SRAT can expose future memory locality. This information is
already tracked by thenodes_adddata structure (it keeps the memory/node locality information) from the SRAT code. The code insrat.cis built aroundRESERVE_HOTADD. This patch is a little subtle in the way it uses the existing code for use with sparsemem. Perhapsacpi_numa_memory_affinity_initneeds a larger refactor to fit bothRESERVE_HOTADDand sparsemem.This patch still
hotadd_percentas a flag to the whole srat parsing
code to disable and contain broken bios. It's functionality is retained and an on off switch to sparsemem hot-add. Without changing the safety mechanisms build into the current SRAT code I have provided a path for the sparsemem hot-add path to get to thenodes_adddata for use at runtime.Quoted 4 lines
This is a 1st run at the patch, it works with 2.6.17
Signed-off-by Keith Mannthey <[email protected]>_______________________________________________
Lhms-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/lhms-devel
Signature · 8 lines
keith mannthey <[email protected]> Linux Technology Center IBM -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 8 lines · On Tue, 20 Jun 2006 23:25:01 -0700 keith mannthey <[email protected]> wrote:
Quoted 3 lines
And yes,
mem_mapshould be allocated from local node.
I'm now preparing "dynamic localmem_mapallocation" for lhms's memory hotplug, which doesn't depend on SRAT.How do you know which node to add the memory too without something like the SRAT that define memory locality of hot-add zones? SPARSEMEM doesn't depend on SRAT (it just needs to use to to know what zone to add to.)
Now, acpi's _PXM method is supported by acpi-memory-hotadd. (See -mm.) I'll use it. and current add_memory() -mm is this.
==
int arch_add_memory(int nid, u64 start, u64 size)
{
struct pglist_data *pgdat = NODE_DATA(nid);
struct zone *zone = pgdat->node_zones + MAX_NR_ZONES-2;
unsigned long start_pfn = start >> PAGE_SHIFT;
unsigned long nr_pages = size >> PAGE_SHIFT;==
nid is passed by caller.
Quoted 4 lines
This patch isn't about
mem_mapallocation rather what zone to add the memory to when doing SPASEMEM hot-add. A numa awaremem_mapallocation would belong in generic SPARSEMEM code.
I also need to do NUMA-aware
- pgdat allocation , wait table allocation ..and so on...
I'll add memory allocater which allocates memory from newly-added-memory.
-Kame
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 10 lines
Quoted 6 lines · On Tue, 20 Jun 2006 22:43:01 -0700 keith mannthey <[email protected]> wrote:
Hello all,
This patch is an attempt to add a numa wareadd_memoryfunctionality
tox86_64usingCONFIG_SPARSEMEM. The add memory function today just grabs the pgdat from node 0 and adds the memory there. On a numa system this is functional but not optimal/correct.
Quoted 8 lines
At first, sorry for confusing. reserve_hotadd()/memory-hot-add with preallocated
mem_mapthings are maintained byx86_64and Andi Kleen (maybe).
So we (lhms people) are not familiar with this.And yes,
mem_mapshould be allocated from local node.
I'm now preparing "dynamic localmem_mapallocation" for lhms's memory hotplug, which doesn't depend on SRAT.
I wrote patches for NUMA aware memory hotplug with sparsemem. It is already included in current -mm.
He means he would like to make the patch for -mm. Could you check it? But, I've not try it with RESERVE_HOT_ADD. I just try it with sparsemem. Sorry. :-(
In my patch, if new memory is in new node, new node id is decided by PXM in dsdt. So, it must work even if srat does not define hot-add area.
Thanks.
Signature · 8 lines
Yasunori Goto -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
arch/x86_64/mm/init.c line 557
Quoted 5 lines
int
add_memory(u64 start, u64 size)
{arch/x86_64/mm/init.c +1
-1-struct pglist_data *pgdat =NODE_DATA (0 ); +struct pglist_data *pgdat =NODE_DATA (new_memory_to_node (start,start+size));struct zone *zone = pgdat->node_zones +MAX_NR_ZONES -2 ;
How about just having new_memory_to_node() take the range and return the pgdat? Should make that line a bit shorter.
arch/x86_64/mm/srat.c line 223
Quoted 12 lines
arch/x86_64/mm/srat.c +2
-2-#ifndef RESERVE_HOTADD +#if !defined(RESERVE_HOTADD ) && !defined(CONFIG_MEMORY_HOTPLUG )#define hotadd_percent 0/* Ignore all settings */ #endif static u8 pxm2node[256 ] = { [0 ...255 ] =0xff };@@ -219,9 +219,9 @@ allocated += mem; return 1; } - +#endif /*
Could this use another Kconfig option which gives a name to this condition?
arch/x86_64/mm/srat.c line 255
Quoted 7 lines
arch/x86_64/mm/srat.c +2
-1+#ifdef RESERVE_HOTADD if (!hotadd_enough_memory (&nodes_add[node])) {printk (KERN_ERR "SRAT: Hotplug area too large\n" );return -1 ; } - +#endif
This #ifdef is probably better handled by an #ifdef in the header for hotadd_enough_memory().
-- Dave
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 8 lines · Dave Hansen
arch/x86_64/mm/init.c line 557
Quoted 5 lines
int
add_memory(u64 start, u64 size)
{arch/x86_64/mm/init.c +1
-1-struct pglist_data *pgdat =NODE_DATA (0 ); +struct pglist_data *pgdat =NODE_DATA (new_memory_to_node (start,start+size));struct zone *zone = pgdat->node_zones +MAX_NR_ZONES -2 ;How about just having
new_memory_to_node()take the range and return the pgdat? Should make that line a bit shorter.
In the -mm tree things are a little different. The acpi layer (and something for ppc) is passing the nid down the a generic add memory call.
This int add_memory(u64 start, u64 size) is going away with something
more like int add_memory(int nid, u64 start, u64 size) this changes things some.
I have patches against the -mm stack but I had a little trouble with
my testbox's file-system last night so I should have them out this afternoon.
Quoted 7 lines
Quoted 7 lines
arch/x86_64/mm/srat.c +1
-1-#ifndef RESERVE_HOTADD +#if !defined(RESERVE_HOTADD ) && !defined(CONFIG_MEMORY_HOTPLUG )#define hotadd_percent 0/* Ignore all settings */ #endif static u8 pxm2node[256 ] = { [0 ...255 ] =0xff };@@ -219,9 +219,9 @@ allocated += mem;
Quoted 8 lines
arch/x86_64/mm/srat.c line 223
Quoted 5 lines
arch/x86_64/mm/srat.c +1
-1return 1; } - +#endif /* Could this use another
Kconfigoption which gives a name to this condition?
This is sort of a redundant force off. I am not sure if there is a
code path to the SRAT code without RESERVE_HOTADD or CONFIG_MEMORY_HOTPLUG defined.
hotadd_percent can only change from 0 with an explicit command-line
numa=hotadd=XXX boot so maybe taking this
#define hotadd_percent 0
out all together might be the better way to go if the code patch is going to be shared.
Quoted 11 lines
arch/x86_64/mm/srat.c line 255
Quoted 8 lines
arch/x86_64/mm/srat.c +2
-1+#ifdef RESERVE_HOTADD if (!hotadd_enough_memory (&nodes_add[node])) {printk (KERN_ERR "SRAT: Hotplug area too large\n" );return -1 ; } - +#endif This #ifdef is probably better handled by an #ifdef in the header for
hotadd_enough_memory().
hotadd_enough_memory is static there is no header entry for it.
Thanks for the feedback,
Keith
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
RFC 1/1 Patch [1/4] x86_64 sparsmem add- save nodes_add data for later
In reply to Dave HansenHello All,
The following patch reserves the nodes_add data for use later. It
retains the bulk of the hotadd_precent defense that is built into the SRAT code. It is a little subtle but it gets the job done.
The code saves off the hot-add area ranges without extending the end
of memory. It then creates arch_find_node which will be use in the next patch.
arch_find_node is passed a memory range and it looks for a nodes_add
area it fits into. If no area is found it returns 0.
With this and the other 3 patches I can do SPARSEMEM x86_64 hot-add on
my hardware. (the first 2 patches are one I consider real the other 2 are more to point out issues)
It is built against 2.6.17-mm1 x86_64 and the current memory_hotplug
work but should apply on any current srat.c
arch/x86_64/mm/srat.c +21 -14
@@ -34,9 +34,6 @@static struct bootnode nodes_add[MAX_NUMNODES ]__initdata ;static int found_add_area__initdata ;int hotadd_percent__initdata =0 ; -#ifndef RESERVE_HOTADD -#define hotadd_percent 0/* Ignore all settings */ -#endif /* Too small nodes confuse the VM badly. Usually they result from BIOS bugs. */
@@ -199,9 +196,9 @@ allocated += mem; return 1; } - +#endif /* -* It is fine to add this area to the nodes data it will be used later +* It is fine to add this area to the nodes_add data it will be used later * This code supports one contigious hot add area per node. */ static int reserve_hotadd (int node,unsigned long start,unsigned long end)
@@ -227,15 +224,14 @@printk (KERN_ERR "SRAT: Hotplug area has existing memory\n" );return -1 ; } - +#ifdef RESERVE_HOTADD if (!hotadd_enough_memory (&nodes_add[node])) {printk (KERN_ERR "SRAT: Hotplug area too large\n" );return -1 ; } - +#endif /* Looks good */ - found_add_area =1 ;if (nd->start == nd->end) { nd->start = start; nd->end = end;
@@ -253,14 +249,16 @@printk (KERN_ERR "SRAT: Hotplug zone not continuous. Partly ignored\n" ); } -if ((nd->end >>PAGE_SHIFT ) > end_pfn) - end_pfn = nd->end >>PAGE_SHIFT ; -if (changed)printk (KERN_INFO "SRAT: hot plug zone found %Lx - %Lx\n" , nd->start, nd->end); +#ifdef RESERVE_HOTADD + found_add_area =1 ; +if ((nd->end >>PAGE_SHIFT ) > end_pfn) + end_pfn = nd->end >>PAGE_SHIFT ;return 0 ; +#endif +return -1 ; } -#endif /* Callback for parsing of the Proximity Domain <-> Memory Area mappings */ void __init
@@ -318,7 +316,6 @@printk (KERN_INFO "SRAT: Node %u PXM %u %Lx-%Lx\n" , node, pxm, nd->start, nd->end); -#ifdef RESERVE_HOTADD if (ma->flags.hot_pluggable &&reserve_hotadd (node, start, end) <0 ) {/* Ignore hotadd region. Undo damage */ printk (KERN_NOTICE "SRAT: Hotplug region ignored\n" );
@@ -326,7 +323,6 @@if ((nd->start | nd->end) ==0 )node_clear (node, nodes_parsed); } -#endif }/* Sanity check to catch more bad SRATs (they are amazingly common).
@@ -450,3 +446,14 @@ }EXPORT_SYMBOL (__node_distance); + +int arch_find_node (unsigned long start,unsigned long size) { +int i, ret =0 ; +unsigned long end = start+size; + +for_each_node (i){ +if (nodes_add[i].start <= start && nodes_add[i].end >= end) + ret = i; + } +return ret; +}