aboutsummaryrefslogtreecommitdiffstats
path: root/mm/page_alloc.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2011-12-08 13:22:09 -0500
committerTejun Heo <tj@kernel.org>2011-12-08 13:22:09 -0500
commit0ee332c1451869963626bf9cac88f165a90990e1 (patch)
treea40e6c9c6cfe39ecbca37a08019be3c9e56a4a9b /mm/page_alloc.c
parenta2bf79e7dcc97b4e9654f273453f9264f49e41ff (diff)
memblock: Kill early_node_map[]
Now all ARCH_POPULATES_NODE_MAP archs select HAVE_MEBLOCK_NODE_MAP - there's no user of early_node_map[] left. Kill early_node_map[] and replace ARCH_POPULATES_NODE_MAP with HAVE_MEMBLOCK_NODE_MAP. Also, relocate for_each_mem_pfn_range() and helper from mm.h to memblock.h as page_alloc.c would no longer host an alternative implementation. This change is ultimately one to one mapping and shouldn't cause any observable difference; however, after the recent changes, there are some functions which now would fit memblock.c better than page_alloc.c and dependency on HAVE_MEMBLOCK_NODE_MAP instead of HAVE_MEMBLOCK doesn't make much sense on some of them. Further cleanups for functions inside HAVE_MEMBLOCK_NODE_MAP in mm.h would be nice. -v2: Fix compile bug introduced by mis-spelling CONFIG_HAVE_MEMBLOCK_NODE_MAP to CONFIG_MEMBLOCK_HAVE_NODE_MAP in mmzone.h. Reported by Stephen Rothwell. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Stephen Rothwell <sfr@canb.auug.org.au> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Yinghai Lu <yinghai@kernel.org> Cc: Tony Luck <tony.luck@intel.com> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: Chen Liqin <liqin.chen@sunplusct.com> Cc: Paul Mundt <lethal@linux-sh.org> Cc: "David S. Miller" <davem@davemloft.net> Cc: "H. Peter Anvin" <hpa@zytor.com>
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r--mm/page_alloc.c259
1 files changed, 18 insertions, 241 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 6ce27331834c..63ff8dab433a 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -181,42 +181,17 @@ static unsigned long __meminitdata nr_kernel_pages;
181static unsigned long __meminitdata nr_all_pages; 181static unsigned long __meminitdata nr_all_pages;
182static unsigned long __meminitdata dma_reserve; 182static unsigned long __meminitdata dma_reserve;
183 183
184#ifdef CONFIG_ARCH_POPULATES_NODE_MAP 184#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
185 #ifndef CONFIG_HAVE_MEMBLOCK_NODE_MAP 185static unsigned long __meminitdata arch_zone_lowest_possible_pfn[MAX_NR_ZONES];
186 /* 186static unsigned long __meminitdata arch_zone_highest_possible_pfn[MAX_NR_ZONES];
187 * MAX_ACTIVE_REGIONS determines the maximum number of distinct ranges 187static unsigned long __initdata required_kernelcore;
188 * of memory (RAM) that may be registered with add_active_range(). 188static unsigned long __initdata required_movablecore;
189 * Ranges passed to add_active_range() will be merged if possible so 189static unsigned long __meminitdata zone_movable_pfn[MAX_NUMNODES];
190 * the number of times add_active_range() can be called is related to 190
191 * the number of nodes and the number of holes 191/* movable_zone is the "real" zone pages in ZONE_MOVABLE are taken from */
192 */ 192int movable_zone;
193 #ifdef CONFIG_MAX_ACTIVE_REGIONS 193EXPORT_SYMBOL(movable_zone);
194 /* Allow an architecture to set MAX_ACTIVE_REGIONS to save memory */ 194#endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
195 #define MAX_ACTIVE_REGIONS CONFIG_MAX_ACTIVE_REGIONS
196 #else
197 #if MAX_NUMNODES >= 32
198 /* If there can be many nodes, allow up to 50 holes per node */
199 #define MAX_ACTIVE_REGIONS (MAX_NUMNODES*50)
200 #else
201 /* By default, allow up to 256 distinct regions */
202 #define MAX_ACTIVE_REGIONS 256
203 #endif
204 #endif
205
206 static struct node_active_region __meminitdata early_node_map[MAX_ACTIVE_REGIONS];
207 static int __meminitdata nr_nodemap_entries;
208#endif /* !CONFIG_HAVE_MEMBLOCK_NODE_MAP */
209
210 static unsigned long __meminitdata arch_zone_lowest_possible_pfn[MAX_NR_ZONES];
211 static unsigned long __meminitdata arch_zone_highest_possible_pfn[MAX_NR_ZONES];
212 static unsigned long __initdata required_kernelcore;
213 static unsigned long __initdata required_movablecore;
214 static unsigned long __meminitdata zone_movable_pfn[MAX_NUMNODES];
215
216 /* movable_zone is the "real" zone pages in ZONE_MOVABLE are taken from */
217 int movable_zone;
218 EXPORT_SYMBOL(movable_zone);
219#endif /* CONFIG_ARCH_POPULATES_NODE_MAP */
220 195
221#if MAX_NUMNODES > 1 196#if MAX_NUMNODES > 1
222int nr_node_ids __read_mostly = MAX_NUMNODES; 197int nr_node_ids __read_mostly = MAX_NUMNODES;
@@ -3734,7 +3709,7 @@ __meminit int init_currently_empty_zone(struct zone *zone,
3734 return 0; 3709 return 0;
3735} 3710}
3736 3711
3737#ifdef CONFIG_ARCH_POPULATES_NODE_MAP 3712#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
3738#ifndef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID 3713#ifndef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
3739/* 3714/*
3740 * Required by SPARSEMEM. Given a PFN, return what node the PFN is on. 3715 * Required by SPARSEMEM. Given a PFN, return what node the PFN is on.
@@ -4002,7 +3977,7 @@ static unsigned long __meminit zone_absent_pages_in_node(int nid,
4002 return __absent_pages_in_range(nid, zone_start_pfn, zone_end_pfn); 3977 return __absent_pages_in_range(nid, zone_start_pfn, zone_end_pfn);
4003} 3978}
4004 3979
4005#else 3980#else /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
4006static inline unsigned long __meminit zone_spanned_pages_in_node(int nid, 3981static inline unsigned long __meminit zone_spanned_pages_in_node(int nid,
4007 unsigned long zone_type, 3982 unsigned long zone_type,
4008 unsigned long *zones_size) 3983 unsigned long *zones_size)
@@ -4020,7 +3995,7 @@ static inline unsigned long __meminit zone_absent_pages_in_node(int nid,
4020 return zholes_size[zone_type]; 3995 return zholes_size[zone_type];
4021} 3996}
4022 3997
4023#endif 3998#endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
4024 3999
4025static void __meminit calculate_node_totalpages(struct pglist_data *pgdat, 4000static void __meminit calculate_node_totalpages(struct pglist_data *pgdat,
4026 unsigned long *zones_size, unsigned long *zholes_size) 4001 unsigned long *zones_size, unsigned long *zholes_size)
@@ -4243,10 +4218,10 @@ static void __init_refok alloc_node_mem_map(struct pglist_data *pgdat)
4243 */ 4218 */
4244 if (pgdat == NODE_DATA(0)) { 4219 if (pgdat == NODE_DATA(0)) {
4245 mem_map = NODE_DATA(0)->node_mem_map; 4220 mem_map = NODE_DATA(0)->node_mem_map;
4246#ifdef CONFIG_ARCH_POPULATES_NODE_MAP 4221#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
4247 if (page_to_pfn(mem_map) != pgdat->node_start_pfn) 4222 if (page_to_pfn(mem_map) != pgdat->node_start_pfn)
4248 mem_map -= (pgdat->node_start_pfn - ARCH_PFN_OFFSET); 4223 mem_map -= (pgdat->node_start_pfn - ARCH_PFN_OFFSET);
4249#endif /* CONFIG_ARCH_POPULATES_NODE_MAP */ 4224#endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
4250 } 4225 }
4251#endif 4226#endif
4252#endif /* CONFIG_FLAT_NODE_MEM_MAP */ 4227#endif /* CONFIG_FLAT_NODE_MEM_MAP */
@@ -4271,7 +4246,7 @@ void __paginginit free_area_init_node(int nid, unsigned long *zones_size,
4271 free_area_init_core(pgdat, zones_size, zholes_size); 4246 free_area_init_core(pgdat, zones_size, zholes_size);
4272} 4247}
4273 4248
4274#ifdef CONFIG_ARCH_POPULATES_NODE_MAP 4249#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
4275 4250
4276#if MAX_NUMNODES > 1 4251#if MAX_NUMNODES > 1
4277/* 4252/*
@@ -4292,201 +4267,6 @@ static inline void setup_nr_node_ids(void)
4292} 4267}
4293#endif 4268#endif
4294 4269
4295#ifndef CONFIG_HAVE_MEMBLOCK_NODE_MAP
4296/*
4297 * Common iterator interface used to define for_each_mem_pfn_range().
4298 */
4299void __meminit __next_mem_pfn_range(int *idx, int nid,
4300 unsigned long *out_start_pfn,
4301 unsigned long *out_end_pfn, int *out_nid)
4302{
4303 struct node_active_region *r = NULL;
4304
4305 while (++*idx < nr_nodemap_entries) {
4306 if (nid == MAX_NUMNODES || nid == early_node_map[*idx].nid) {
4307 r = &early_node_map[*idx];
4308 break;
4309 }
4310 }
4311 if (!r) {
4312 *idx = -1;
4313 return;
4314 }
4315
4316 if (out_start_pfn)
4317 *out_start_pfn = r->start_pfn;
4318 if (out_end_pfn)
4319 *out_end_pfn = r->end_pfn;
4320 if (out_nid)
4321 *out_nid = r->nid;
4322}
4323
4324/**
4325 * add_active_range - Register a range of PFNs backed by physical memory
4326 * @nid: The node ID the range resides on
4327 * @start_pfn: The start PFN of the available physical memory
4328 * @end_pfn: The end PFN of the available physical memory
4329 *
4330 * These ranges are stored in an early_node_map[] and later used by
4331 * free_area_init_nodes() to calculate zone sizes and holes. If the
4332 * range spans a memory hole, it is up to the architecture to ensure
4333 * the memory is not freed by the bootmem allocator. If possible
4334 * the range being registered will be merged with existing ranges.
4335 */
4336void __init add_active_range(unsigned int nid, unsigned long start_pfn,
4337 unsigned long end_pfn)
4338{
4339 int i;
4340
4341 mminit_dprintk(MMINIT_TRACE, "memory_register",
4342 "Entering add_active_range(%d, %#lx, %#lx) "
4343 "%d entries of %d used\n",
4344 nid, start_pfn, end_pfn,
4345 nr_nodemap_entries, MAX_ACTIVE_REGIONS);
4346
4347 mminit_validate_memmodel_limits(&start_pfn, &end_pfn);
4348
4349 /* Merge with existing active regions if possible */
4350 for (i = 0; i < nr_nodemap_entries; i++) {
4351 if (early_node_map[i].nid != nid)
4352 continue;
4353
4354 /* Skip if an existing region covers this new one */
4355 if (start_pfn >= early_node_map[i].start_pfn &&
4356 end_pfn <= early_node_map[i].end_pfn)
4357 return;
4358
4359 /* Merge forward if suitable */
4360 if (start_pfn <= early_node_map[i].end_pfn &&
4361 end_pfn > early_node_map[i].end_pfn) {
4362 early_node_map[i].end_pfn = end_pfn;
4363 return;
4364 }
4365
4366 /* Merge backward if suitable */
4367 if (start_pfn < early_node_map[i].start_pfn &&
4368 end_pfn >= early_node_map[i].start_pfn) {
4369 early_node_map[i].start_pfn = start_pfn;
4370 return;
4371 }
4372 }
4373
4374 /* Check that early_node_map is large enough */
4375 if (i >= MAX_ACTIVE_REGIONS) {
4376 printk(KERN_CRIT "More than %d memory regions, truncating\n",
4377 MAX_ACTIVE_REGIONS);
4378 return;
4379 }
4380
4381 early_node_map[i].nid = nid;
4382 early_node_map[i].start_pfn = start_pfn;
4383 early_node_map[i].end_pfn = end_pfn;
4384 nr_nodemap_entries = i + 1;
4385}
4386
4387/**
4388 * remove_active_range - Shrink an existing registered range of PFNs
4389 * @nid: The node id the range is on that should be shrunk
4390 * @start_pfn: The new PFN of the range
4391 * @end_pfn: The new PFN of the range
4392 *
4393 * i386 with NUMA use alloc_remap() to store a node_mem_map on a local node.
4394 * The map is kept near the end physical page range that has already been
4395 * registered. This function allows an arch to shrink an existing registered
4396 * range.
4397 */
4398void __init remove_active_range(unsigned int nid, unsigned long start_pfn,
4399 unsigned long end_pfn)
4400{
4401 unsigned long this_start_pfn, this_end_pfn;
4402 int i, j;
4403 int removed = 0;
4404
4405 printk(KERN_DEBUG "remove_active_range (%d, %lu, %lu)\n",
4406 nid, start_pfn, end_pfn);
4407
4408 /* Find the old active region end and shrink */
4409 for_each_mem_pfn_range(i, nid, &this_start_pfn, &this_end_pfn, NULL) {
4410 if (this_start_pfn >= start_pfn && this_end_pfn <= end_pfn) {
4411 /* clear it */
4412 early_node_map[i].start_pfn = 0;
4413 early_node_map[i].end_pfn = 0;
4414 removed = 1;
4415 continue;
4416 }
4417 if (this_start_pfn < start_pfn && this_end_pfn > start_pfn) {
4418 early_node_map[i].end_pfn = start_pfn;
4419 if (this_end_pfn > end_pfn)
4420 add_active_range(nid, end_pfn, this_end_pfn);
4421 continue;
4422 }
4423 if (this_start_pfn >= start_pfn && this_end_pfn > end_pfn &&
4424 this_start_pfn < end_pfn) {
4425 early_node_map[i].start_pfn = end_pfn;
4426 continue;
4427 }
4428 }
4429
4430 if (!removed)
4431 return;
4432
4433 /* remove the blank ones */
4434 for (i = nr_nodemap_entries - 1; i > 0; i--) {
4435 if (early_node_map[i].nid != nid)
4436 continue;
4437 if (early_node_map[i].end_pfn)
4438 continue;
4439 /* we found it, get rid of it */
4440 for (j = i; j < nr_nodemap_entries - 1; j++)
4441 memcpy(&early_node_map[j], &early_node_map[j+1],
4442 sizeof(early_node_map[j]));
4443 j = nr_nodemap_entries - 1;
4444 memset(&early_node_map[j], 0, sizeof(early_node_map[j]));
4445 nr_nodemap_entries--;
4446 }
4447}
4448
4449/**
4450 * remove_all_active_ranges - Remove all currently registered regions
4451 *
4452 * During discovery, it may be found that a table like SRAT is invalid
4453 * and an alternative discovery method must be used. This function removes
4454 * all currently registered regions.
4455 */
4456void __init remove_all_active_ranges(void)
4457{
4458 memset(early_node_map, 0, sizeof(early_node_map));
4459 nr_nodemap_entries = 0;
4460}
4461
4462/* Compare two active node_active_regions */
4463static int __init cmp_node_active_region(const void *a, const void *b)
4464{
4465 struct node_active_region *arange = (struct node_active_region *)a;
4466 struct node_active_region *brange = (struct node_active_region *)b;
4467
4468 /* Done this way to avoid overflows */
4469 if (arange->start_pfn > brange->start_pfn)
4470 return 1;
4471 if (arange->start_pfn < brange->start_pfn)
4472 return -1;
4473
4474 return 0;
4475}
4476
4477/* sort the node_map by start_pfn */
4478void __init sort_node_map(void)
4479{
4480 sort(early_node_map, (size_t)nr_nodemap_entries,
4481 sizeof(struct node_active_region),
4482 cmp_node_active_region, NULL);
4483}
4484#else /* !CONFIG_HAVE_MEMBLOCK_NODE_MAP */
4485static inline void sort_node_map(void)
4486{
4487}
4488#endif
4489
4490/** 4270/**
4491 * node_map_pfn_alignment - determine the maximum internode alignment 4271 * node_map_pfn_alignment - determine the maximum internode alignment
4492 * 4272 *
@@ -4764,9 +4544,6 @@ void __init free_area_init_nodes(unsigned long *max_zone_pfn)
4764 unsigned long start_pfn, end_pfn; 4544 unsigned long start_pfn, end_pfn;
4765 int i, nid; 4545 int i, nid;
4766 4546
4767 /* Sort early_node_map as initialisation assumes it is sorted */
4768 sort_node_map();
4769
4770 /* Record where the zone boundaries are */ 4547 /* Record where the zone boundaries are */
4771 memset(arch_zone_lowest_possible_pfn, 0, 4548 memset(arch_zone_lowest_possible_pfn, 0,
4772 sizeof(arch_zone_lowest_possible_pfn)); 4549 sizeof(arch_zone_lowest_possible_pfn));
@@ -4867,7 +4644,7 @@ static int __init cmdline_parse_movablecore(char *p)
4867early_param("kernelcore", cmdline_parse_kernelcore); 4644early_param("kernelcore", cmdline_parse_kernelcore);
4868early_param("movablecore", cmdline_parse_movablecore); 4645early_param("movablecore", cmdline_parse_movablecore);
4869 4646
4870#endif /* CONFIG_ARCH_POPULATES_NODE_MAP */ 4647#endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
4871 4648
4872/** 4649/**
4873 * set_dma_reserve - set the specified number of pages reserved in the first zone 4650 * set_dma_reserve - set the specified number of pages reserved in the first zone