diff options
-rw-r--r-- | arch/x86_64/mm/srat.c | 2 | ||||
-rw-r--r-- | include/linux/mm.h | 2 | ||||
-rw-r--r-- | mm/page_alloc.c | 67 |
3 files changed, 71 insertions, 0 deletions
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c index db1b2e11cf8f..f8c04d6935c9 100644 --- a/arch/x86_64/mm/srat.c +++ b/arch/x86_64/mm/srat.c | |||
@@ -324,6 +324,8 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma) | |||
324 | nd->start, nd->end); | 324 | nd->start, nd->end); |
325 | e820_register_active_regions(node, nd->start >> PAGE_SHIFT, | 325 | e820_register_active_regions(node, nd->start >> PAGE_SHIFT, |
326 | nd->end >> PAGE_SHIFT); | 326 | nd->end >> PAGE_SHIFT); |
327 | push_node_boundaries(node, nd->start >> PAGE_SHIFT, | ||
328 | nd->end >> PAGE_SHIFT); | ||
327 | 329 | ||
328 | #ifdef RESERVE_HOTADD | 330 | #ifdef RESERVE_HOTADD |
329 | if (ma->flags.hot_pluggable && reserve_hotadd(node, start, end) < 0) { | 331 | if (ma->flags.hot_pluggable && reserve_hotadd(node, start, end) < 0) { |
diff --git a/include/linux/mm.h b/include/linux/mm.h index 22936e1fcdf2..9d046db31e76 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -970,6 +970,8 @@ extern void add_active_range(unsigned int nid, unsigned long start_pfn, | |||
970 | unsigned long end_pfn); | 970 | unsigned long end_pfn); |
971 | extern void shrink_active_range(unsigned int nid, unsigned long old_end_pfn, | 971 | extern void shrink_active_range(unsigned int nid, unsigned long old_end_pfn, |
972 | unsigned long new_end_pfn); | 972 | unsigned long new_end_pfn); |
973 | extern void push_node_boundaries(unsigned int nid, unsigned long start_pfn, | ||
974 | unsigned long end_pfn); | ||
973 | extern void remove_all_active_ranges(void); | 975 | extern void remove_all_active_ranges(void); |
974 | extern unsigned long absent_pages_in_range(unsigned long start_pfn, | 976 | extern unsigned long absent_pages_in_range(unsigned long start_pfn, |
975 | unsigned long end_pfn); | 977 | unsigned long end_pfn); |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 75133e1dc4b1..acbf58f8a1b7 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -131,6 +131,10 @@ static unsigned long __initdata dma_reserve; | |||
131 | int __initdata nr_nodemap_entries; | 131 | int __initdata nr_nodemap_entries; |
132 | unsigned long __initdata arch_zone_lowest_possible_pfn[MAX_NR_ZONES]; | 132 | unsigned long __initdata arch_zone_lowest_possible_pfn[MAX_NR_ZONES]; |
133 | unsigned long __initdata arch_zone_highest_possible_pfn[MAX_NR_ZONES]; | 133 | unsigned long __initdata arch_zone_highest_possible_pfn[MAX_NR_ZONES]; |
134 | #ifdef CONFIG_MEMORY_HOTPLUG_RESERVE | ||
135 | unsigned long __initdata node_boundary_start_pfn[MAX_NUMNODES]; | ||
136 | unsigned long __initdata node_boundary_end_pfn[MAX_NUMNODES]; | ||
137 | #endif /* CONFIG_MEMORY_HOTPLUG_RESERVE */ | ||
134 | #endif /* CONFIG_ARCH_POPULATES_NODE_MAP */ | 138 | #endif /* CONFIG_ARCH_POPULATES_NODE_MAP */ |
135 | 139 | ||
136 | #ifdef CONFIG_DEBUG_VM | 140 | #ifdef CONFIG_DEBUG_VM |
@@ -2095,6 +2099,62 @@ void __init sparse_memory_present_with_active_regions(int nid) | |||
2095 | } | 2099 | } |
2096 | 2100 | ||
2097 | /** | 2101 | /** |
2102 | * push_node_boundaries - Push node boundaries to at least the requested boundary | ||
2103 | * @nid: The nid of the node to push the boundary for | ||
2104 | * @start_pfn: The start pfn of the node | ||
2105 | * @end_pfn: The end pfn of the node | ||
2106 | * | ||
2107 | * In reserve-based hot-add, mem_map is allocated that is unused until hotadd | ||
2108 | * time. Specifically, on x86_64, SRAT will report ranges that can potentially | ||
2109 | * be hotplugged even though no physical memory exists. This function allows | ||
2110 | * an arch to push out the node boundaries so mem_map is allocated that can | ||
2111 | * be used later. | ||
2112 | */ | ||
2113 | #ifdef CONFIG_MEMORY_HOTPLUG_RESERVE | ||
2114 | void __init push_node_boundaries(unsigned int nid, | ||
2115 | unsigned long start_pfn, unsigned long end_pfn) | ||
2116 | { | ||
2117 | printk(KERN_DEBUG "Entering push_node_boundaries(%u, %lu, %lu)\n", | ||
2118 | nid, start_pfn, end_pfn); | ||
2119 | |||
2120 | /* Initialise the boundary for this node if necessary */ | ||
2121 | if (node_boundary_end_pfn[nid] == 0) | ||
2122 | node_boundary_start_pfn[nid] = -1UL; | ||
2123 | |||
2124 | /* Update the boundaries */ | ||
2125 | if (node_boundary_start_pfn[nid] > start_pfn) | ||
2126 | node_boundary_start_pfn[nid] = start_pfn; | ||
2127 | if (node_boundary_end_pfn[nid] < end_pfn) | ||
2128 | node_boundary_end_pfn[nid] = end_pfn; | ||
2129 | } | ||
2130 | |||
2131 | /* If necessary, push the node boundary out for reserve hotadd */ | ||
2132 | static void __init account_node_boundary(unsigned int nid, | ||
2133 | unsigned long *start_pfn, unsigned long *end_pfn) | ||
2134 | { | ||
2135 | printk(KERN_DEBUG "Entering account_node_boundary(%u, %lu, %lu)\n", | ||
2136 | nid, *start_pfn, *end_pfn); | ||
2137 | |||
2138 | /* Return if boundary information has not been provided */ | ||
2139 | if (node_boundary_end_pfn[nid] == 0) | ||
2140 | return; | ||
2141 | |||
2142 | /* Check the boundaries and update if necessary */ | ||
2143 | if (node_boundary_start_pfn[nid] < *start_pfn) | ||
2144 | *start_pfn = node_boundary_start_pfn[nid]; | ||
2145 | if (node_boundary_end_pfn[nid] > *end_pfn) | ||
2146 | *end_pfn = node_boundary_end_pfn[nid]; | ||
2147 | } | ||
2148 | #else | ||
2149 | void __init push_node_boundaries(unsigned int nid, | ||
2150 | unsigned long start_pfn, unsigned long end_pfn) {} | ||
2151 | |||
2152 | static void __init account_node_boundary(unsigned int nid, | ||
2153 | unsigned long *start_pfn, unsigned long *end_pfn) {} | ||
2154 | #endif | ||
2155 | |||
2156 | |||
2157 | /** | ||
2098 | * get_pfn_range_for_nid - Return the start and end page frames for a node | 2158 | * get_pfn_range_for_nid - Return the start and end page frames for a node |
2099 | * @nid: The nid to return the range for. If MAX_NUMNODES, the min and max PFN are returned | 2159 | * @nid: The nid to return the range for. If MAX_NUMNODES, the min and max PFN are returned |
2100 | * @start_pfn: Passed by reference. On return, it will have the node start_pfn | 2160 | * @start_pfn: Passed by reference. On return, it will have the node start_pfn |
@@ -2121,6 +2181,9 @@ void __init get_pfn_range_for_nid(unsigned int nid, | |||
2121 | printk(KERN_WARNING "Node %u active with no memory\n", nid); | 2181 | printk(KERN_WARNING "Node %u active with no memory\n", nid); |
2122 | *start_pfn = 0; | 2182 | *start_pfn = 0; |
2123 | } | 2183 | } |
2184 | |||
2185 | /* Push the node boundaries out if requested */ | ||
2186 | account_node_boundary(nid, start_pfn, end_pfn); | ||
2124 | } | 2187 | } |
2125 | 2188 | ||
2126 | /* | 2189 | /* |
@@ -2527,6 +2590,10 @@ void __init remove_all_active_ranges() | |||
2527 | { | 2590 | { |
2528 | memset(early_node_map, 0, sizeof(early_node_map)); | 2591 | memset(early_node_map, 0, sizeof(early_node_map)); |
2529 | nr_nodemap_entries = 0; | 2592 | nr_nodemap_entries = 0; |
2593 | #ifdef CONFIG_MEMORY_HOTPLUG_RESERVE | ||
2594 | memset(node_boundary_start_pfn, 0, sizeof(node_boundary_start_pfn)); | ||
2595 | memset(node_boundary_end_pfn, 0, sizeof(node_boundary_end_pfn)); | ||
2596 | #endif /* CONFIG_MEMORY_HOTPLUG_RESERVE */ | ||
2530 | } | 2597 | } |
2531 | 2598 | ||
2532 | /* Compare two active node_active_regions */ | 2599 | /* Compare two active node_active_regions */ |