nalika / rpms / grub2

Forked from rpms/grub2 2 years ago
Clone

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

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