diff mbox series

efi_loader: Omit memory with "no-map" when returning memory map.

Message ID 20210827075505.25506-2-kristian.amlie@northern.tech
State Rejected, archived
Delegated to: Heinrich Schuchardt
Headers show
Series efi_loader: Omit memory with "no-map" when returning memory map. | expand

Commit Message

Kristian Amlie Aug. 27, 2021, 7:55 a.m. UTC
efi_reserve_memory() states that memory marked with "no-map" shall not
be accessed by the UEFI payload. Make sure efi_get_memory_map() honors
this.

This helps the case when booting vexpress_ca9x4 under QEMU. Because
the kernel wants to use an address in the lowest 128MiB of the range,
but this range is reserved with "no-map", the kernel complains that it
can not allocate the low memory it needs. In reality the actual usable
memory starts much higher, which is reflected correctly in the memory
map after this fix.

Signed-off-by: Kristian Amlie <kristian.amlie@northern.tech>
---
 lib/efi_loader/efi_memory.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

Comments

Heinrich Schuchardt Aug. 31, 2021, 6:41 a.m. UTC | #1
On 8/27/21 9:55 AM, Kristian Amlie wrote:

You can use scripts/get_maintainer.pl to find the right addressees for
your patches.

> efi_reserve_memory() states that memory marked with "no-map" shall not
> be accessed by the UEFI payload. Make sure efi_get_memory_map() honors
> this.
>
> This helps the case when booting vexpress_ca9x4 under QEMU. Because
> the kernel wants to use an address in the lowest 128MiB of the range,
> but this range is reserved with "no-map", the kernel complains that it
> can not allocate the low memory it needs. In reality the actual usable
> memory starts much higher, which is reflected correctly in the memory
> map after this fix.

The 'no-map' requirement needs to be fulfilled by the kernel.

The GetMemoryMap() boot time service must comply to the UEFI specification.

The Devicetree Specification has this clarification:

"Reserved regions with the no-map property must be listed in the memory
map with type EfiReservedMemoryType. All other reserved regions must be
listed with type EfiBootServicesData."
https://devicetree-specification.readthedocs.io/en/latest/chapter3-devicenodes.html

Should the kernel calculate its internal 128 MiB requirement incorrectly
this needs be fixed in the kernel EFI stub. Does the problem exist with
kernel 5.14?

I wonder if the 128 MiB requirement of the kernel can be lifted for
32bit ARM as we already did for RISC-V. Cf.

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v5.14&id=c79e89ecaa246c880292ba68cbe08c9c30db77e3

Cc Ard, maintainer of the kernel EFI stub.

Best regards

Heinrich

>
> Signed-off-by: Kristian Amlie <kristian.amlie@northern.tech>
> ---
>   lib/efi_loader/efi_memory.c | 14 +++++++++++++-
>   1 file changed, 13 insertions(+), 1 deletion(-)
>
> diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
> index f4acbee4f9..7f8543143a 100644
> --- a/lib/efi_loader/efi_memory.c
> +++ b/lib/efi_loader/efi_memory.c
> @@ -646,8 +646,16 @@ efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size,
>
>   	provided_map_size = *memory_map_size;
>
> -	list_for_each(lhandle, &efi_mem)
> +	list_for_each(lhandle, &efi_mem) {
> +		struct efi_mem_list *lmem;
> +
> +		lmem = list_entry(lhandle, struct efi_mem_list, link);
> +
> +		if (lmem->desc.type == EFI_RESERVED_MEMORY_TYPE)
> +			continue;
> +
>   		map_entries++;
> +	}
>
>   	map_size = map_entries * sizeof(struct efi_mem_desc);
>
> @@ -672,6 +680,10 @@ efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size,
>   		struct efi_mem_list *lmem;
>
>   		lmem = list_entry(lhandle, struct efi_mem_list, link);
> +
> +		if (lmem->desc.type == EFI_RESERVED_MEMORY_TYPE)
> +			continue;
> +
>   		*memory_map = lmem->desc;
>   		memory_map--;
>   	}
>
diff mbox series

Patch

diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index f4acbee4f9..7f8543143a 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -646,8 +646,16 @@  efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size,
 
 	provided_map_size = *memory_map_size;
 
-	list_for_each(lhandle, &efi_mem)
+	list_for_each(lhandle, &efi_mem) {
+		struct efi_mem_list *lmem;
+
+		lmem = list_entry(lhandle, struct efi_mem_list, link);
+
+		if (lmem->desc.type == EFI_RESERVED_MEMORY_TYPE)
+			continue;
+
 		map_entries++;
+	}
 
 	map_size = map_entries * sizeof(struct efi_mem_desc);
 
@@ -672,6 +680,10 @@  efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size,
 		struct efi_mem_list *lmem;
 
 		lmem = list_entry(lhandle, struct efi_mem_list, link);
+
+		if (lmem->desc.type == EFI_RESERVED_MEMORY_TYPE)
+			continue;
+
 		*memory_map = lmem->desc;
 		memory_map--;
 	}