Quoting from the multiboot spec:
"Lower memory starts at address 0, and upper memory starts at address
1 megabyte. The maximum possible value for lower memory is 640
kilobytes. The value returned for upper memory is maximally the
address of the first upper memory hole minus 1 megabyte."

The value of mem_upper on a machine having a memory hole close to the
middle of the DIRECTMAP range is much lower than the DIRECTMAP
limit. The biosmem heap is consequently restricted to this narrow
range even though a larger range of memory might be available just
after the hole to the limit itself. The reduced size of the heap
prevents boot allocations which should succeed.

biosmem_map_build_simple() uses mem_upper to build a memory map in the
case where multiboot didn't supply one. biosmem_setup_allocator()
therefore always has a memory map available which can be used without
reference to mem_upper at all.
---
 i386/i386at/biosmem.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/i386/i386at/biosmem.c b/i386/i386at/biosmem.c
index b6887eff..85ee223f 100644
--- a/i386/i386at/biosmem.c
+++ b/i386/i386at/biosmem.c
@@ -626,7 +626,7 @@ biosmem_find_avail(phys_addr_t start, phys_addr_t end,
 #ifndef MACH_HYP
 
 static void __boot
-biosmem_setup_allocator(const uint32_t mem_upper)
+biosmem_setup_allocator(void)
 {
     phys_addr_t heap_start, heap_end, max_heap_start, max_heap_end;
     phys_addr_t start, end;
@@ -636,14 +636,10 @@ biosmem_setup_allocator(const uint32_t mem_upper)
      * Find some memory for the heap. Look for the largest unused area in
      * upper memory, carefully avoiding all boot data.
      */
-    end = vm_page_trunc((mem_upper + 1024) << 10);
-
-    if (end > VM_PAGE_DIRECTMAP_LIMIT)
-        end = VM_PAGE_DIRECTMAP_LIMIT;
-
     max_heap_start = 0;
     max_heap_end = 0;
     start = BIOSMEM_END;
+    end = VM_PAGE_DIRECTMAP_LIMIT;
 
     for (;;) {
         error = biosmem_find_avail(start, end, &heap_start, &heap_end);
@@ -803,7 +799,7 @@ biosmem_mb1_bootstrap(const struct multiboot_raw_info *mbi)
         biosmem_map_build_simple(mbi->mem_lower, mbi->mem_upper);
 
     biosmem_bootstrap_common();
-    biosmem_setup_allocator(mbi->mem_upper);
+    biosmem_setup_allocator();
 }
 
 void __boot
@@ -878,7 +874,7 @@ biosmem_mb2_bootstrap(const struct multiboot2_raw_info* mbi)
     biosmem_map_build_simple(bi_tag->mem_lower, bi_tag->mem_upper);
 
   biosmem_bootstrap_common();
-  biosmem_setup_allocator(bi_tag->mem_upper);
+  biosmem_setup_allocator();
 }
 
 #endif /* MACH_HYP */
-- 
2.47.3


Reply via email to