nalika / rpms / grub2

Forked from rpms/grub2 2 years ago
Clone

Blame SOURCES/0557-efi-split-allocation-policy-for-kernel-vs-initrd-mem.patch

c6c771
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
c6c771
From: Peter Jones <pjones@redhat.com>
c6c771
Date: Mon, 1 Aug 2022 14:24:39 -0400
c6c771
Subject: [PATCH] efi: split allocation policy for kernel vs initrd memories.
c6c771
c6c771
Currently in our kernel allocator, we use the same set of choices for
c6c771
all of our various kernel and initramfs allocations, though they do not
c6c771
have exactly the same constraints.
c6c771
c6c771
This patch adds the concept of an allocation purpose, which currently
c6c771
can be KERNEL_MEM or INITRD_MEM, and updates kernel_alloc() calls
c6c771
appropriately, but does not change any current policy decision.  It
c6c771
also adds a few debug prints.
c6c771
c6c771
Signed-off-by: Peter Jones <pjones@redhat.com>
c6c771
(cherry picked from commit 36307bed28cd838116fc4af26a30719660d62d4c)
c6c771
(cherry picked from commit dc1196350b0cbe89582832f44df0fce67e0c9fb2)
c6c771
---
c6c771
 grub-core/loader/i386/efi/linux.c | 35 +++++++++++++++++++++++++++--------
c6c771
 1 file changed, 27 insertions(+), 8 deletions(-)
c6c771
c6c771
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
c6c771
index 23b27f6507..09e7596064 100644
c6c771
--- a/grub-core/loader/i386/efi/linux.c
c6c771
+++ b/grub-core/loader/i386/efi/linux.c
c6c771
@@ -55,7 +55,14 @@ struct grub_linuxefi_context {
c6c771
 
c6c771
 #define BYTES_TO_PAGES(bytes)   (((bytes) + 0xfff) >> 12)
c6c771
 
c6c771
+typedef enum {
c6c771
+    NO_MEM,
c6c771
+    KERNEL_MEM,
c6c771
+    INITRD_MEM,
c6c771
+} kernel_alloc_purpose_t;
c6c771
+
c6c771
 struct allocation_choice {
c6c771
+    kernel_alloc_purpose_t purpose;
c6c771
     grub_efi_physical_address_t addr;
c6c771
     grub_efi_allocate_type_t alloc_type;
c6c771
 };
c6c771
@@ -64,6 +71,7 @@ enum {
c6c771
     KERNEL_PREF_ADDRESS,
c6c771
     KERNEL_4G_LIMIT,
c6c771
     KERNEL_NO_LIMIT,
c6c771
+    INITRD_MAX_ADDRESS,
c6c771
 };
c6c771
 
c6c771
 static struct allocation_choice max_addresses[] =
c6c771
@@ -71,14 +79,17 @@ static struct allocation_choice max_addresses[] =
c6c771
     /* the kernel overrides this one with pref_address and
c6c771
      * GRUB_EFI_ALLOCATE_ADDRESS */
c6c771
     [KERNEL_PREF_ADDRESS] =
c6c771
-      { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
c6c771
+      { KERNEL_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
c6c771
     /* If the flag in params is set, this one gets changed to be above 4GB. */
c6c771
     [KERNEL_4G_LIMIT] =
c6c771
-      { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
c6c771
+      { KERNEL_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
c6c771
     /* this one is always below 4GB, which we still *prefer* even if the flag
c6c771
      * is set. */
c6c771
     [KERNEL_NO_LIMIT] =
c6c771
-      { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
c6c771
+      { KERNEL_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
c6c771
+    /* this is for the initrd */
c6c771
+    [INITRD_MAX_ADDRESS] =
c6c771
+      { INITRD_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
c6c771
     { NO_MEM, 0, 0 }
c6c771
   };
c6c771
 static struct allocation_choice saved_addresses[4];
c6c771
@@ -95,7 +106,8 @@ kernel_free(void *addr, grub_efi_uintn_t size)
c6c771
 }
c6c771
 
c6c771
 static void *
c6c771
-kernel_alloc(grub_efi_uintn_t size,
c6c771
+kernel_alloc(kernel_alloc_purpose_t purpose,
c6c771
+	     grub_efi_uintn_t size,
c6c771
 	     grub_efi_memory_type_t memtype,
c6c771
 	     const char * const errmsg)
c6c771
 {
c6c771
@@ -108,6 +120,9 @@ kernel_alloc(grub_efi_uintn_t size,
c6c771
       grub_uint64_t max = max_addresses[i].addr;
c6c771
       grub_efi_uintn_t pages;
c6c771
 
c6c771
+      if (purpose != max_addresses[i].purpose)
c6c771
+	continue;
c6c771
+
c6c771
       /*
c6c771
        * When we're *not* loading the kernel, or >4GB allocations aren't
c6c771
        * supported, these entries are basically all the same, so don't re-try
c6c771
@@ -262,7 +277,8 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[])
c6c771
 	}
c6c771
     }
c6c771
 
c6c771
-  initrd_mem = kernel_alloc(size, GRUB_EFI_RUNTIME_SERVICES_DATA,
c6c771
+  grub_dprintf ("linux", "Trying to allocate initrd mem\n");
c6c771
+  initrd_mem = kernel_alloc(INITRD_MEM, size, GRUB_EFI_RUNTIME_SERVICES_DATA,
c6c771
 			    N_("can't allocate initrd"));
c6c771
   if (initrd_mem == NULL)
c6c771
     goto fail;
c6c771
@@ -440,7 +456,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
c6c771
     }
c6c771
 #endif
c6c771
 
c6c771
-  params = kernel_alloc (sizeof(*params), GRUB_EFI_RUNTIME_SERVICES_DATA,
c6c771
+  params = kernel_alloc (KERNEL_MEM, sizeof(*params),
c6c771
+			 GRUB_EFI_RUNTIME_SERVICES_DATA,
c6c771
 			 "cannot allocate kernel parameters");
c6c771
   if (!params)
c6c771
     goto fail;
c6c771
@@ -462,7 +479,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
c6c771
   grub_dprintf ("linux", "new lh is at %p\n", lh);
c6c771
 
c6c771
   grub_dprintf ("linux", "setting up cmdline\n");
c6c771
-  cmdline = kernel_alloc (lh->cmdline_size + 1,
c6c771
+  cmdline = kernel_alloc (KERNEL_MEM, lh->cmdline_size + 1,
c6c771
 			  GRUB_EFI_RUNTIME_SERVICES_DATA,
c6c771
 			  N_("can't allocate cmdline"));
c6c771
   if (!cmdline)
c6c771
@@ -510,7 +527,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
c6c771
   max_addresses[KERNEL_4G_LIMIT].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS;
c6c771
   max_addresses[KERNEL_NO_LIMIT].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS;
c6c771
   kernel_size = lh->init_size;
c6c771
-  kernel_mem = kernel_alloc (kernel_size, GRUB_EFI_RUNTIME_SERVICES_CODE,
c6c771
+  grub_dprintf ("linux", "Trying to allocate kernel mem\n");
c6c771
+  kernel_mem = kernel_alloc (KERNEL_MEM, kernel_size,
c6c771
+			     GRUB_EFI_RUNTIME_SERVICES_CODE,
c6c771
 			     N_("can't allocate kernel"));
c6c771
   restore_addresses();
c6c771
   if (!kernel_mem)