Skip to contentSkip to conversation

arm64 initrd mapping/relocation

RFC PATCH New Ard Biesheuvel 5 participants 11 messages Feb 2, 2016 – Feb 8, 2016

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover arm64 initrd mapping/relocation

After discussing in linux-efi with Mark, and on #armlinux with Will, this is a proposal for dealing with initrd memory that is potentially not covered by the linear region.

Note that this will look slightly differently when some of the KASLR work gets merged, but this should only affect the way we deal with the initrd if it sits outside of the linear region.

Mostly intended for discussion, not tested at all.

Ard Biesheuvel (3):
memblock: add routine to clear the MEMBLOCK_NOMAP flag for a region
arm64: add the initrd region to the linear mapping explicitly
arm64: remove the now unneeded relocate_initrd()

 arch/arm64/kernel/setup.c | 64 --------------------
 arch/arm64/mm/init.c      | 16 ++++-
 include/linux/memblock.h  |  1 +
 mm/memblock.c             | 12 ++++
 4 files changed, 27 insertions(+), 66 deletions(-)
Signature · 1 line
2.5.0
#1 lore raw

RFC PATCH 1/3 memblock: add routine to clear the MEMBLOCK_NOMAP flag for a region

In addition to the existing memblock_mark_nomap(), this implements memblock_clear_nomap() to do the converse.

---
 include/linux/memblock.h |  1 +
 mm/memblock.c            | 12 ++++++++++++
 2 files changed, 13 insertions(+)
include/linux/memblock.h +1 -0
index 3106ac1c895e..f7d2c8dc2f0d 100644
@@ -92,6 +92,7 @@ int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size);
 int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size);
 int memblock_mark_mirror(phys_addr_t base, phys_addr_t size);
 int memblock_mark_nomap(phys_addr_t base, phys_addr_t size);
+int memblock_clear_nomap(phys_addr_t base, phys_addr_t size);
 ulong choose_memblock_flags(void);
 
 /* Low level functions */
mm/memblock.c +12 -0
index 335a145b75cd..ffa7ab127641 100644
@@ -835,6 +835,18 @@ int __init_memblock memblock_mark_nomap(phys_addr_t base, phys_addr_t size)
 }
 
 /**
+ * memblock_clear_nomap - Clear flag MEMBLOCK_NOMAP for a specified region.
+ * @base: the base phys addr of the region
+ * @size: the size of the region
+ *
+ * Return 0 on success, -errno on failure.
+ */
+int __init_memblock memblock_clear_nomap(phys_addr_t base, phys_addr_t size)
+{
+	return memblock_setclr_flag(base, size, 0, MEMBLOCK_NOMAP);
+}
+
+/**
  * __next_reserved_mem_region - next function for for_each_reserved_region()
  * @idx: pointer to u64 loop variable
  * @out_start: ptr to phys_addr_t for start address of the region, can be %NULL
Signature · 1 line
2.5.0
#2 lore raw

RFC PATCH 2/3 arm64: add the initrd region to the linear mapping explicitly

In reply to Ard Biesheuvel

Instead of going out of our way to relocate the initrd if it turns out to occupy memory that is not covered by the linear mapping, just add the initrd to the linear mapping. This puts the burden on the bootloader to pass initrd= and mem= options that are mutually consistent.

---
 arch/arm64/mm/init.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)
arch/arm64/mm/init.c +14 -2
index f3b061e67bfe..5dd083161810 100644
@@ -167,8 +167,20 @@ void __init arm64_memblock_init(void)
 	 */
 	memblock_reserve(__pa(_text), _end - _text);
 #ifdef CONFIG_BLK_DEV_INITRD
-	if (initrd_start)
-		memblock_reserve(__virt_to_phys(initrd_start), initrd_end - initrd_start);
+	if (initrd_start) {
+		u64 base = __virt_to_phys(initrd_start);
+		u64 size = initrd_end - initrd_start;
+
+		/*
+		 * The initrd needs to be accessible via the linear mapping. So
+		 * add the memory covered by the initrd explicitly, since it may
+		 * have been clipped or otherwise left out when we traversed the
+		 * DT memory nodes or the UEFI memory map.
+		 */
+		memblock_add(base, size);
+		memblock_clear_nomap(base, size);
+		memblock_reserve(base, size);
+	}
 #endif
 
 	early_init_fdt_scan_reserved_mem();
Signature · 1 line
2.5.0
#3 lore raw

RFC PATCH 3/3 arm64: remove the now unneeded relocate_initrd()

In reply to Ard Biesheuvel
---
 arch/arm64/kernel/setup.c | 64 --------------------
 1 file changed, 64 deletions(-)
arch/arm64/kernel/setup.c +0 -64
index 8119479147db..1a8ef35b03d4 100644
@@ -223,69 +223,6 @@ static void __init request_standard_resources(void)
 	}
 }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-/*
- * Relocate initrd if it is not completely within the linear mapping.
- * This would be the case if mem= cuts out all or part of it.
- */
-static void __init relocate_initrd(void)
-{
-	phys_addr_t orig_start = __virt_to_phys(initrd_start);
-	phys_addr_t orig_end = __virt_to_phys(initrd_end);
-	phys_addr_t ram_end = memblock_end_of_DRAM();
-	phys_addr_t new_start;
-	unsigned long size, to_free = 0;
-	void *dest;
-
-	if (orig_end <= ram_end)
-		return;
-
-	/*
-	 * Any of the original initrd which overlaps the linear map should
-	 * be freed after relocating.
-	 */
-	if (orig_start < ram_end)
-		to_free = ram_end - orig_start;
-
-	size = orig_end - orig_start;
-	if (!size)
-		return;
-
-	/* initrd needs to be relocated completely inside linear mapping */
-	new_start = memblock_find_in_range(0, PFN_PHYS(max_pfn),
-					   size, PAGE_SIZE);
-	if (!new_start)
-		panic("Cannot relocate initrd of size %ld\n", size);
-	memblock_reserve(new_start, size);
-
-	initrd_start = __phys_to_virt(new_start);
-	initrd_end   = initrd_start + size;
-
-	pr_info("Moving initrd from [%llx-%llx] to [%llx-%llx]\n",
-		orig_start, orig_start + size - 1,
-		new_start, new_start + size - 1);
-
-	dest = (void *)initrd_start;
-
-	if (to_free) {
-		memcpy(dest, (void *)__phys_to_virt(orig_start), to_free);
-		dest += to_free;
-	}
-
-	copy_from_early_mem(dest, orig_start + to_free, size - to_free);
-
-	if (to_free) {
-		pr_info("Freeing original RAMDISK from [%llx-%llx]\n",
-			orig_start, orig_start + to_free - 1);
-		memblock_free(orig_start, to_free);
-	}
-}
-#else
-static inline void __init relocate_initrd(void)
-{
-}
-#endif
-
 u64 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = INVALID_HWID };
 
 void __init setup_arch(char **cmdline_p)
@@ -320,7 +257,6 @@ void __init setup_arch(char **cmdline_p)
 	acpi_boot_table_init();
 
 	paging_init();
-	relocate_initrd();
 
 	kasan_init();
 
Signature · 1 line
2.5.0
#4 lore raw

cover arm64 initrd mapping/relocation

In reply to Ard Biesheuvel
Quoted 9 lines · Ard Biesheuvel

After discussing in linux-efi with Mark, and on #armlinux with Will, this is a proposal for dealing with initrd memory that is potentially not covered by the linear region.

Note that this will look slightly differently when some of the KASLR work gets merged, but this should only affect the way we deal with the initrd if it sits outside of the linear region.

Mostly intended for discussion, not tested at all.

Thanks Ard, this looks like a much better approach to me. Mark -- does the general idea work for you too?

Will

#5 lore raw

cover arm64 initrd mapping/relocation

Quoted 5 lines · Will Deacon
Quoted 4 lines · Ard Biesheuvel

After discussing in linux-efi with Mark, and on #armlinux with Will, this is a proposal for dealing with initrd memory that is potentially not covered by the linear region.

Quoted 8 lines
Quoted 5 lines

Note that this will look slightly differently when some of the KASLR work gets merged, but this should only affect the way we deal with the initrd if it sits outside of the linear region.

Mostly intended for discussion, not tested at all.

Thanks Ard, this looks like a much better approach to me. Mark -- does the general idea work for you too?

I'm not quite the right Mark but Mark Salter is on vacation and I was the one who discovered this bug. These patches do fix the problem and it looks like they tidy up some code. Will they be in v4.5-rc3?

--Mark Langsdorf

#6 lore raw

cover arm64 initrd mapping/relocation

In reply to Will Deacon
Quoted 9 lines · Will Deacon
Quoted 8 lines · Ard Biesheuvel

After discussing in linux-efi with Mark, and on #armlinux with Will, this is a proposal for dealing with initrd memory that is potentially not covered by the linear region.

Note that this will look slightly differently when some of the KASLR work gets merged, but this should only affect the way we deal with the initrd if it sits outside of the linear region.

Quoted 6 lines
Quoted 1 line

Mostly intended for discussion, not tested at all.

Thanks Ard, this looks like a much better approach to me. Mark -- does the general idea work for you too?

Will

Yeah, much simpler. I like it in concept but am I missing something or is it adding memory to the system beyond the mem= limit? But even that may not be a big deal. And I need to look at the KASLR work and understand the issues with it and mem= if any. I'm traveling right now and can't really try it out until tomorrow...

#7 lore raw

cover arm64 initrd mapping/relocation

Quoted 12 lines · Mark Salter
Quoted 11 lines · Will Deacon
Quoted 9 lines · Ard Biesheuvel

After discussing in linux-efi with Mark, and on #armlinux with Will, this is a proposal for dealing with initrd memory that is potentially not covered by the linear region.

Note that this will look slightly differently when some of the KASLR work gets merged, but this should only affect the way we deal with the initrd if it sits outside of the linear region.

Mostly intended for discussion, not tested at all.

Quoted 7 lines
Quoted 4 lines

Thanks Ard, this looks like a much better approach to me. Mark -- does the general idea work for you too?

Will

Yeah, much simpler. I like it in concept but am I missing something or is it adding memory to the system beyond the mem= limit?

Indeed. I think it is reasonable to require that if you pass both mem= and initrd= *and* you need your memory limit to be honored strictly, it is up to you to ensure that the initrd does not live in the memory you are throwing away.

Quoted 5 lines

But even that may not be
a big deal. And I need to look at the KASLR work and understand the issues with it and mem= if any. I'm traveling right now and can't really try it out until tomorrow...

No worries. My estimation is that Will is not going to take this as a fix anyway, so we have plenty of time to test and/or discuss

Thanks,
Ard.

#8 lore raw

cover arm64 initrd mapping/relocation

Quoted 26 lines · Ard Biesheuvel
Quoted 12 lines · Mark Salter
Quoted 11 lines · Will Deacon
Quoted 9 lines · Ard Biesheuvel

After discussing in linux-efi with Mark, and on #armlinux with Will, this is a proposal for dealing with initrd memory that is potentially not covered by the linear region.

Note that this will look slightly differently when some of the KASLR work gets merged, but this should only affect the way we deal with the initrd if it sits outside of the linear region.

Mostly intended for discussion, not tested at all.

Quoted 7 lines
Quoted 4 lines

Thanks Ard, this looks like a much better approach to me. Mark -- does the general idea work for you too?

Will

Yeah, much simpler. I like it in concept but am I missing something or is it adding memory to the system beyond the mem= limit?

Indeed. I think it is reasonable to require that if you pass both mem= and initrd= *and* you need your memory limit to be honored strictly, it is up to you to ensure that the initrd does not live in the memory you are throwing away.

Quoted 8 lines
Quoted 5 lines

But even that may not be
a big deal. And I need to look at the KASLR work and understand the issues with it and mem= if any. I'm traveling right now and can't really try it out until tomorrow...

No worries. My estimation is that Will is not going to take this as a fix anyway, so we have plenty of time to test and/or discuss

I needed these patches to successfully boot a JunoR2 with a recent tianocore firmware.

Thanks,

#9 lore raw

cover arm64 initrd mapping/relocation

In reply to Ard Biesheuvel
Quoted 8 lines · Ard Biesheuvel

After discussing in linux-efi with Mark, and on #armlinux with Will, this is a proposal for dealing with initrd memory that is potentially not covered by the linear region.

Note that this will look slightly differently when some of the KASLR work gets merged, but this should only affect the way we deal with the initrd if it sits outside of the linear region.

Quoted 6 lines

Mostly intended for discussion, not tested at all.

Ard Biesheuvel (3):
memblock: add routine to clear the MEMBLOCK_NOMAP flag for a region
arm64: add the initrd region to the linear mapping explicitly
arm64: remove the now unneeded relocate_initrd()

I discovered the original problem on AMD Seattle and these patches fixed it for me.

#10 lore raw

cover arm64 initrd mapping/relocation

Quoted 22 lines · Mark Langsdorf
Quoted 13 lines · Ard Biesheuvel

After discussing in linux-efi with Mark, and on #armlinux with Will, this is
a proposal for dealing with initrd memory that is potentially not covered by
the linear region.

Note that this will look slightly differently when some of the KASLR work gets
merged, but this should only affect the way we deal with the initrd if it sits
outside of the linear region.

Quoted 6 lines

Mostly intended for discussion, not tested at all.

Ard Biesheuvel (3):
memblock: add routine to clear the MEMBLOCK_NOMAP flag for a region
arm64: add the initrd region to the linear mapping explicitly
arm64: remove the now unneeded relocate_initrd()

Quoted 5 lines

I discovered the original problem on AMD Seattle and these patches fixed it for me.

Thanks Mark.

I will let Will confirm when and how these patches will be merged.

Signature · 1 line
Ard.