[RFC] MIPS: Communicate reserved memblock regions to the page allocator

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Reserved memblock regions were not being communicated to the page allocator.
Our systems use memblock to reserve memory regions to not be used by linux.
The regions of reserved memory in memblock do not seem to be communicated to
the page allocator.

Their are two regions we are concerned with lowmem (region < max_low_pfn) and
highmem (max_low_pfn < region < max_pfn).

Lowmem is managed by bootmem. Reserved memblock regions were already communicated
to bootmem, however in bootmem only regions in lowmem are valid. When trying to
reserve_bootmem regions higher then lowmem the kernel crashes. Fixed this problem
by checking memblock reserved regions before reserving them in bootmem.

Highmem is freed by mem_init_free_highmem(). Memblock reserved regions were being
freed without coordinating with memblock. Fixed this problem by checking with
memblock before freeing pages.

Signed-off-by: Justin Chen <justinpopo6@xxxxxxxxx>
---
 arch/mips/kernel/setup.c | 21 +++++++++++++++------
 arch/mips/mm/init.c      |  3 ++-
 2 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 6e63a62..9e2330d 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -695,15 +695,24 @@ static void __init arch_mem_init(char **cmdline_p)
 	plat_swiotlb_setup();
 	paging_init();
 
-	dma_contiguous_reserve(PFN_PHYS(max_low_pfn));
-	/* Tell bootmem about cma reserved memblock section */
-	for_each_memblock(reserved, reg)
-		if (reg->size != 0)
-			reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT);
-
 #ifdef CONFIG_BRCMSTB_MEMORY_API
 	brcmstb_memory_init();
 #endif
+
+	dma_contiguous_reserve(PFN_PHYS(max_low_pfn));
+	/* Tell bootmem about reserved memory blocks in memblock */
+	for_each_memblock(reserved, reg) {
+		if (reg->size != 0)
+			continue;
+		/*
+		 * Bootmem does not have knowledge of high mem, however memblock
+		 * does. Make sure the regions we are reserving reside in bootmem
+		 * range. Bootmem range is anything < max_low_pfn.
+		 */
+		if ((reg->base < PFN_PHYS(max_low_pfn)) &&
+		    ((reg->base + reg->size) <= PFN_PHYS(max_low_pfn)))
+			reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT);
+	}
 }
 
 static void __init resource_init(void)
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index faa5c98..b17ebf3 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -30,6 +30,7 @@
 #include <linux/hardirq.h>
 #include <linux/gfp.h>
 #include <linux/kcore.h>
+#include <linux/memblock.h>
 
 #include <asm/asm-offsets.h>
 #include <asm/bootinfo.h>
@@ -323,7 +324,7 @@ static inline void mem_init_free_highmem(void)
 	for (tmp = highstart_pfn; tmp < highend_pfn; tmp++) {
 		struct page *page = pfn_to_page(tmp);
 
-		if (!page_is_ram(tmp))
+		if (!page_is_ram(tmp) || memblock_is_reserved(PFN_PHYS(tmp)))
 			SetPageReserved(page);
 		else
 			free_highmem_page(page);
-- 
2.10.1





[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux