mips: bootmem: Don't use memory holes for page bitmap
RFC PATCH 1/1 mips: bootmem: Don't use memory holes for page bitmap
Commit f9a7febd leads to a fact that mapstart and therefore a page bitmap for bootmem allocator immediately follows initrd_end. This doesn't always work well on Octeon, where there are holes in PFN ranges (refer to 5b3b1688 and 4MB-aligned PFN allocation). Depending on the inird location it could happen, that mapstart would be in an area not allocated by plat_mem_setup() in arch/mips/cavium-octeon/setup.c, but in the alignment hole between initrd and the next PFN area. Later on this memory will be unconditionally made available to buddy allocator at the end of free_all_bootmem_core() (mm/bootmem.c). All of this results in Linux using the memory not designated for Linux in Octeon's plat_mem_setup(), which in turn means corruption of the memory used by another OS/baremetal code on the same SoC.
It doesn't look to me as a problem of Octeon platform code, but rather as an inability of f9a7febd to deal correctly with the fragmented memory-mappings. Proposed fix moves the check for initrd address to the same calculation-loop in bootmem_init() (arch/mips/kernel/setup.c), which also accounts for kernel code location. This should result in mapstart located starting from the first PFN area after kernel code AND initrd.
---
Tested on CN63xx (Octeon2) -based HW.
arch/mips/kernel/setup.c | 13 +++++-------- 1 files changed, 5 insertions(+), 8 deletions(-)
arch/mips/kernel/setup.c +5 -8
@@ -337,6 +337,11 @@ static void __init bootmem_init(void) min_low_pfn = start;if (end <= reserved_end)continue ; +#ifdef CONFIG_BLK_DEV_INITRD +/* mapstart should be after initrd_end */ +if (initrd_end && end <= (unsigned long )PFN_UP (__pa (initrd_end))) +continue ; +#endif if (start >= mapstart)continue ; mapstart =max (reserved_end, start);
@@ -366,14 +371,6 @@ static void __init bootmem_init(void) max_low_pfn =PFN_DOWN (HIGHMEM_START ); } -#ifdef CONFIG_BLK_DEV_INITRD -/* -* mapstart should be after initrd_end -*/ -if (initrd_end) - mapstart =max (mapstart, (unsigned long )PFN_UP (__pa (initrd_end))); -#endif -/* * Initialize the boot-time allocator with low memory only. */
Quoted 12 lines · Alexander Sverdlin
Commit
f9a7febdleads to a fact that mapstart and therefore a page bitmap for bootmem allocator immediately followsinitrd_end. This doesn't always work well on Octeon, where there are holes in PFN ranges (refer to5b3b1688and 4MB-aligned PFN allocation). Depending on the inird location it could happen, that mapstart would be in an area not allocated byplat_mem_setup()inarch/mips/cavium-octeon/setup.c, but in the alignment hole between initrd and the next PFN area. Later on this memory will be unconditionally made available to buddy allocator at the end offree_all_bootmem_core()(mm/bootmem.c). All of this results in Linux using the memory not designated for Linux in Octeon'splat_mem_setup(), which in turn means corruption of the memory used by another OS/baremetal code on the same SoC.
Quoted 8 lines
It doesn't look to me as a problem of Octeon platform code, but rather as an inability of
f9a7febdto deal correctly with the fragmented memory-mappings. Proposed fix moves the check for initrd address to the same calculation-loop inbootmem_init()(arch/mips/kernel/setup.c), which also accounts for kernel code location. This should result in mapstart located starting from the first PFN area after kernel code AND initrd.Signed-off-by Alexander Sverdlin <[email protected]>
Appears reasonable. Applied.
Thanks,
Ralf