Skip to content

Commit

Permalink
efi: make the default arena most of ram
Browse files Browse the repository at this point in the history
Currently when populating the initial memory arena on EFI systems, we
count the available regions below GRUB_EFI_MAX_ALLOCATION_ADDRESS from
the EFI memory map and then allocates one quarter of that for our arena.

Because many systems come up without IOMMUs, we currently set
GRUB_EFI_MAX_ALLOCATION_ADDRESS to 0x7fffffff, i.e. all addresses
allocated must be below 2G[0].  Due to firmware and other
considerations, this makes the most memory we can possibly have in our
arena 512M.

Because our EFI loader doesn't get kernel and initrd memory from grub's
allocator, but rather reserves it directly from UEFI and then simply
marks those as allocated if they're within grub's arena, it was
historically possible to have initrds that are larger than 512M, because
we could use any memory region below 4G, without concern for grub's
choice of arena size.

Unfortunately, when we switched to using the "verifiers" API (and thus
the file_filter_t API) to do measurement of kernel and initrd, this
introduced a pattern that allocates the entire file when we call
grub_file_open(), and buffers it to pass to the filter.  This results in
needing to have enough space for the initramfs in the grub arena.

This is bad.

Since it's unlikely you're going to do anything *other* than loading a
kernel and initramfs that takes much of the available free memory from
UEFI, this patch introduces a workaround by changing the amount we give
to the arena be three quarters of the available memory, rather than one
quarter, thus changing our theoretical initrd limit to 1.5G.  In
practice, it may still be smaller than that depending on allocation
fragmentation, but generally it will be most of it.

Note that this doesn't fix the underlying flaw, which is that there is
no safe way to do the validation correctly using the "verifiers" system
with the current file API without buffering the whole file before
grub_file_read() is ever called, and thus you can't set an allocation
policy for the initial buffer of the file at all, so unless we raise the
allocation limit to >4G, it can't be allocated in the big region.

[0] I'm not sure there was a good reason not to pick 4G, but even if we
    had, at least one common firmware routes the first 2G of physical
    RAM to 0x0, and any additional memory starting at 0x100000000.

Related: rhbz#2112134

Signed-off-by: Peter Jones <pjones@redhat.com>
  • Loading branch information
vathpela committed Aug 1, 2022
1 parent d3d6518 commit 005a0aa
Showing 1 changed file with 2 additions and 2 deletions.
4 changes: 2 additions & 2 deletions grub-core/kern/efi/mm.c
Original file line number Diff line number Diff line change
Expand Up @@ -737,10 +737,10 @@ grub_efi_mm_init (void)
filtered_memory_map_end = filter_memory_map (memory_map, filtered_memory_map,
desc_size, memory_map_end);

/* By default, request a quarter of the available memory. */
/* By default, request three quarters of the available memory. */
total_pages = get_total_pages (filtered_memory_map, desc_size,
filtered_memory_map_end);
required_pages = (total_pages >> 2);
required_pages = (total_pages >> 1) + (total_pages >> 2);
if (required_pages < BYTES_TO_PAGES (MIN_HEAP_SIZE))
required_pages = BYTES_TO_PAGES (MIN_HEAP_SIZE);
else if (required_pages > BYTES_TO_PAGES (MAX_HEAP_SIZE))
Expand Down

0 comments on commit 005a0aa

Please sign in to comment.