aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mm/init.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2017-01-16 10:21:05 -0500
committerRussell King <rmk+kernel@armlinux.org.uk>2017-02-28 06:06:22 -0500
commitcdcc5fa0415d943288c6316bd32e76befb1027c5 (patch)
treed44af6eb1705ca33d8b073e27d3bcfef1243d917 /arch/arm/mm/init.c
parent68b32f361f3892fc376051b1702954b2dc692d13 (diff)
ARM: mm: round the initrd reservation to page boundaries
Round the initrd memblock reservation to page boundaries to prevent other data sharing the initrd pages. This prevents an allocation possibly overlapping with the initrd, which would later get trampled on in free_initrd_mem(). Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Diffstat (limited to 'arch/arm/mm/init.c')
-rw-r--r--arch/arm/mm/init.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 15739a95552a..d1e26610977d 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -231,6 +231,9 @@ phys_addr_t __init arm_memblock_steal(phys_addr_t size, phys_addr_t align)
231static void __init arm_initrd_init(void) 231static void __init arm_initrd_init(void)
232{ 232{
233#ifdef CONFIG_BLK_DEV_INITRD 233#ifdef CONFIG_BLK_DEV_INITRD
234 phys_addr_t start;
235 unsigned long size;
236
234 /* FDT scan will populate initrd_start */ 237 /* FDT scan will populate initrd_start */
235 if (initrd_start && !phys_initrd_size) { 238 if (initrd_start && !phys_initrd_size) {
236 phys_initrd_start = __virt_to_phys(initrd_start); 239 phys_initrd_start = __virt_to_phys(initrd_start);
@@ -242,19 +245,29 @@ static void __init arm_initrd_init(void)
242 if (!phys_initrd_size) 245 if (!phys_initrd_size)
243 return; 246 return;
244 247
245 if (!memblock_is_region_memory(phys_initrd_start, phys_initrd_size)) { 248 /*
249 * Round the memory region to page boundaries as per free_initrd_mem()
250 * This allows us to detect whether the pages overlapping the initrd
251 * are in use, but more importantly, reserves the entire set of pages
252 * as we don't want these pages allocated for other purposes.
253 */
254 start = round_down(phys_initrd_start, PAGE_SIZE);
255 size = phys_initrd_size + (phys_initrd_start - start);
256 size = round_up(size, PAGE_SIZE);
257
258 if (!memblock_is_region_memory(start, size)) {
246 pr_err("INITRD: 0x%08llx+0x%08lx is not a memory region - disabling initrd\n", 259 pr_err("INITRD: 0x%08llx+0x%08lx is not a memory region - disabling initrd\n",
247 (u64)phys_initrd_start, phys_initrd_size); 260 (u64)start, size);
248 return; 261 return;
249 } 262 }
250 263
251 if (memblock_is_region_reserved(phys_initrd_start, phys_initrd_size)) { 264 if (memblock_is_region_reserved(start, size)) {
252 pr_err("INITRD: 0x%08llx+0x%08lx overlaps in-use memory region - disabling initrd\n", 265 pr_err("INITRD: 0x%08llx+0x%08lx overlaps in-use memory region - disabling initrd\n",
253 (u64)phys_initrd_start, phys_initrd_size); 266 (u64)start, size);
254 return; 267 return;
255 } 268 }
256 269
257 memblock_reserve(phys_initrd_start, phys_initrd_size); 270 memblock_reserve(start, size);
258 271
259 /* Now convert initrd to virtual addresses */ 272 /* Now convert initrd to virtual addresses */
260 initrd_start = __phys_to_virt(phys_initrd_start); 273 initrd_start = __phys_to_virt(phys_initrd_start);