aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2012-09-13 19:04:01 +0100
committerCatalin Marinas <catalin.marinas@arm.com>2012-09-14 14:55:51 +0100
commit806e33fff465a3c1133173b094017962c9bdbd62 (patch)
tree3ce8f647675a8f02fc9d0245228878dfc52c66e4
parent65d99854ebf3099d9594b81230b15fb44588b4d4 (diff)
downloadlinux-aarch64-806e33fff465a3c1133173b094017962c9bdbd62.tar.gz
arm64: mm: register zone holes with page allocator
Ensure that we register any holes with the page allocator so that the corresponding memmap is freed correctly. Signed-off-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
-rw-r--r--arch/arm64/mm/init.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 31428cadcf1..5f719ba949b 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -71,12 +71,12 @@ early_param("initrd", early_initrd);
static void __init zone_sizes_init(unsigned long min, unsigned long max)
{
- unsigned long zone_size[MAX_NR_ZONES];
+ struct memblock_region *reg;
+ unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
unsigned long max_dma32 = min;
memset(zone_size, 0, sizeof(zone_size));
- zone_size[0] = max - min;
#ifdef CONFIG_ZONE_DMA32
/* 4GB maximum for 32-bit only capable devices */
max_dma32 = min(max, MAX_DMA32_PFN);
@@ -84,7 +84,28 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
#endif
zone_size[ZONE_NORMAL] = max - max_dma32;
- free_area_init(zone_size);
+ memcpy(zhole_size, zone_size, sizeof(zhole_size));
+
+ for_each_memblock(memory, reg) {
+ unsigned long start = memblock_region_memory_base_pfn(reg);
+ unsigned long end = memblock_region_memory_end_pfn(reg);
+
+ if (start >= max)
+ continue;
+#ifdef CONFIG_ZONE_DMA32
+ if (start < max_dma32) {
+ unsigned long dma_end = min(end, max_dma32);
+ zhole_size[ZONE_DMA32] -= dma_end - start;
+ }
+#endif
+ if (end > max_dma32) {
+ unsigned long normal_end = min(end, max);
+ unsigned long normal_start = max(start, max_dma32);
+ zhole_size[ZONE_NORMAL] -= normal_end - normal_start;
+ }
+ }
+
+ free_area_init_node(0, zone_size, min, zhole_size);
}
#ifdef CONFIG_HAVE_ARCH_PFN_VALID