On PowerVM and KVM on Power use the new memory allocation function that
honors restrictions on which memory GRUB can actually use. In the request
structure indicate the request for a single memory block along with
address alignment restrictions. Request direct usage of the memory block
by setting init_region to false (prevent it from being added to GRUB's
heap). Initialize the found addr to '-1', so that '-1' will be returned
to the loader in case no memory could be allocated.

Report an out-of-memory error in case the initrd could not be loaded.

Signed-off-by: Stefan Berger <stef...@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.ki...@oracle.com>
Cc: Hari Bathini <hbath...@linux.ibm.com>
Cc: Pavithra Prakash <pavra...@in.ibm.com>
Cc: Michael Ellerman <m...@ellerman.id.au>
Cc: Carolyn Scherrer <cpsch...@us.ibm.com>
Cc: Mahesh Salgaonkar <mah...@linux.ibm.com>
Cc: Sourabh Jain <sourabhj...@linux.ibm.com>
---
 grub-core/loader/powerpc/ieee1275/linux.c | 55 +++++++++++++++++++----
 1 file changed, 46 insertions(+), 9 deletions(-)

diff --git a/grub-core/loader/powerpc/ieee1275/linux.c 
b/grub-core/loader/powerpc/ieee1275/linux.c
index e6d071508..de174416d 100644
--- a/grub-core/loader/powerpc/ieee1275/linux.c
+++ b/grub-core/loader/powerpc/ieee1275/linux.c
@@ -30,6 +30,7 @@
 #include <grub/lib/cmdline.h>
 #include <grub/cache.h>
 #include <grub/linux.h>
+#include <grub/powerpc/ieee1275/alloc.h>
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
@@ -116,6 +117,22 @@ grub_linux_claimmap_iterate (grub_addr_t target, 
grub_size_t size,
   return ctx.found_addr;
 }
 
+static grub_addr_t
+grub_linux_claimmap_iterate_restricted (grub_size_t size, grub_size_t align)
+{
+  struct regions_claim_request rcr = {
+    .flags = GRUB_MM_ADD_REGION_CONSECUTIVE,
+    .total = size,
+    .init_region = false,
+    .addr = (grub_uint64_t) -1,
+    .align = align,
+  };
+
+  grub_machine_mmap_iterate (grub_regions_claim, &rcr);
+
+  return rcr.addr;
+}
+
 static grub_err_t
 grub_linux_boot (void)
 {
@@ -227,10 +244,18 @@ grub_linux_load64 (grub_elf_t elf, const char *filename)
   offset = entry - base_addr;
   /* Linux's incorrectly contains a virtual address.  */
 
-  /* On some systems, firmware occupies the memory we're trying to use.
-   * Happily, Linux can be loaded anywhere (it relocates itself).  Iterate
-   * until we find an open area.  */
-  seg_addr = grub_linux_claimmap_iterate (base_addr & ~ELF64_LOADMASK, 
linux_size, align);
+  if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_POWER_VM) ||
+      grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_POWER_KVM))
+    {
+      seg_addr = grub_linux_claimmap_iterate_restricted (linux_size, align);
+    }
+  else
+    {
+      /* On some systems, firmware occupies the memory we're trying to use.
+       * Happily, Linux can be loaded anywhere (it relocates itself).  Iterate
+       * until we find an open area.  */
+      seg_addr = grub_linux_claimmap_iterate (base_addr & ~ELF64_LOADMASK, 
linux_size, align);
+    }
   if (seg_addr == (grub_addr_t) -1)
     return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't claim memory");
 
@@ -339,13 +364,25 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ 
((unused)),
 
   size = grub_get_initrd_size (&initrd_ctx);
 
-  first_addr = linux_addr + linux_size;
 
-  /* Attempt to claim at a series of addresses until successful in
-     the same way that grub_rescue_cmd_linux does.  */
-  addr = grub_linux_claimmap_iterate (first_addr, size, 0x100000);
+  if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_POWER_VM) ||
+      grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_POWER_KVM))
+    {
+      addr = grub_linux_claimmap_iterate_restricted (size, 0x100000);
+    }
+  else
+    {
+      /* Attempt to claim at a series of addresses until successful in
+         the same way that grub_rescue_cmd_linux does.  */
+      first_addr = linux_addr + linux_size;
+      addr = grub_linux_claimmap_iterate (first_addr, size, 0x100000);
+    }
+
   if (addr == (grub_addr_t) -1)
-     goto fail;
+    {
+      grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
+      goto fail;
+    }
 
   grub_dprintf ("loader", "Loading initrd at 0x%x, size 0x%x\n", addr, size);
 
-- 
2.25.1


_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to