grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 2/2] kern/efi/mm: Allocate the initial heap based on the availabl


From: Gary Lin
Subject: [PATCH 2/2] kern/efi/mm: Allocate the initial heap based on the available memory
Date: Tue, 6 Sep 2022 16:22:56 +0800

We currently request 1MB memory as the initial heap and then request
pages on demand. However, it caused some noticeable delays(*) due to the
small heap size. To mitigate the delays, this patch reimplements the
previous heap size: a quarter of the available memory. The setting may
not be ideal but already works for years, so it would fulfill the known
good cases and the dynamic allocation mechanism could cover the
additional memory demands.

(*) https://lists.gnu.org/archive/html/grub-devel/2022-09/msg00005.html
    https://bugzilla.opensuse.org/show_bug.cgi?id=1202438#c20

Signed-off-by: Gary Lin <glin@suse.com>
---
 grub-core/kern/efi/mm.c | 81 +++++++++++++++++++++++++++++++++++++++--
 1 file changed, 78 insertions(+), 3 deletions(-)

diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
index 8fd89b7d4..11f0852b2 100644
--- a/grub-core/kern/efi/mm.c
+++ b/grub-core/kern/efi/mm.c
@@ -38,8 +38,9 @@
    a multiplier of 4KB.  */
 #define MEMORY_MAP_SIZE        0x3000
 
-/* The default heap size for GRUB itself in bytes.  */
-#define DEFAULT_HEAP_SIZE      0x100000
+/* The minimum and maximum heap size for GRUB itself.  */
+#define MIN_HEAP_SIZE  0x100000
+#define MAX_HEAP_SIZE  (1600 * 0x100000)
 
 static void *finish_mmap_buf = 0;
 static grub_efi_uintn_t finish_mmap_size = 0;
@@ -661,10 +662,84 @@ grub_efi_mm_add_regions (grub_size_t required_bytes, 
unsigned int flags)
   return GRUB_ERR_NONE;
 }
 
+/* Return the total number of pages.  */
+static grub_efi_uint64_t
+get_total_pages (grub_efi_memory_descriptor_t *memory_map,
+                grub_efi_uintn_t desc_size,
+                grub_efi_memory_descriptor_t *memory_map_end)
+{
+  grub_efi_memory_descriptor_t *desc;
+  grub_efi_uint64_t total = 0;
+
+  for (desc = memory_map;
+       desc < memory_map_end;
+       desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
+    total += desc->num_pages;
+
+  return total;
+}
+
+static grub_err_t
+grub_efi_mm_add_first_region (void)
+{
+  grub_efi_memory_descriptor_t *memory_map = NULL;
+  grub_efi_memory_descriptor_t *filtered_memory_map = NULL;
+  grub_efi_memory_descriptor_t *filtered_memory_map_end = NULL;
+  grub_efi_uintn_t desc_size = 0;
+  grub_efi_uint64_t total_pages;
+  grub_efi_uint64_t required_pages;
+  grub_err_t err;
+
+  err = get_filtered_memory_map (&memory_map, &filtered_memory_map,
+                                 &filtered_memory_map_end, &desc_size);
+  if (err != GRUB_ERR_NONE)
+    return err;
+
+  /* By default, request a quarter of the available memory.  */
+  total_pages = get_total_pages (filtered_memory_map, desc_size,
+                                filtered_memory_map_end);
+  required_pages = (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))
+    required_pages = BYTES_TO_PAGES (MAX_HEAP_SIZE);
+
+  /* Sort the filtered descriptors, so that GRUB can allocate pages
+     from smaller regions.  */
+  sort_memory_map (filtered_memory_map, desc_size, filtered_memory_map_end);
+
+  /* Allocate memory regions for GRUB's memory management.  */
+  err = add_memory_regions (filtered_memory_map, desc_size,
+                           filtered_memory_map_end,
+                           required_pages,
+                           GRUB_MM_ADD_REGION_NONE);
+  if (err != GRUB_ERR_NONE)
+    return err;
+
+#if 0
+  /* For debug.  */
+  map_size = MEMORY_MAP_SIZE;
+
+  if (grub_efi_get_memory_map (&map_size, memory_map, 0, &desc_size, 0) < 0)
+    grub_fatal ("cannot get memory map");
+
+  grub_printf ("printing memory map\n");
+  print_memory_map (memory_map, desc_size,
+                   NEXT_MEMORY_DESCRIPTOR (memory_map, map_size));
+  grub_fatal ("Debug. ");
+#endif
+
+  /* Release the memory maps.  */
+  grub_efi_free_pages ((grub_addr_t) memory_map,
+                      2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE));
+
+  return GRUB_ERR_NONE;
+}
+
 void
 grub_efi_mm_init (void)
 {
-  if (grub_efi_mm_add_regions (DEFAULT_HEAP_SIZE, GRUB_MM_ADD_REGION_NONE) != 
GRUB_ERR_NONE)
+  if (grub_efi_mm_add_first_region () != GRUB_ERR_NONE)
     grub_fatal ("%s", grub_errmsg);
   grub_mm_add_region_fn = grub_efi_mm_add_regions;
 }
-- 
2.35.3




reply via email to

[Prev in Thread] Current Thread [Next in Thread]