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