Author: jhb
Date: Mon Dec  7 16:29:43 2009
New Revision: 200219
URL: http://svn.freebsd.org/changeset/base/200219

Log:
  Improve the algorithm the loader uses to choose a memory range for its
  heap when using a range above 1MB.
  
  Previously the loader would always use the last 3MB in the first memory
  range above 1MB for the heap.  However, this memory range is also where the
  kernel and any modules are loaded.  If this memory range is "small", then
  using the high 3MB for the heap may not leave enough room for the kernel
  and modules.
  
  Now the loader will use any range below 4GB for the heap, and the logic to
  choose the "high" heap region has moved into biosmem.c.  It sets two
  variables that the loader can use for a high heap if it desires.  When a
  high heap is enabled (BZIP2, FireWire, GPT, or ZFS), then the following
  memory ranges are preferred for the heap in order from best to worst:
  - The largest memory region in the SMAP with a start address greater than
    1MB.  The memory region must be at least 3MB in length.  This leaves the
    region starting at 1MB purely for use by the kernel and modules.
  - The last 3MB of the memory region starting at 1MB if it is at least 3MB
    in size.  This matches the current behavior except that the current loader
    would break horribly if the first region was not at least 3MB in size.
  - The memory range from the end of the loader up to the 640k window.  This
    is the range the loader uses when none of the high-heap-requesting options
    are enabled.
  
  Tested by:    hrs
  MFC after:    1 week

Modified:
  head/sys/boot/i386/libi386/biosmem.c
  head/sys/boot/i386/libi386/libi386.h
  head/sys/boot/i386/loader/main.c

Modified: head/sys/boot/i386/libi386/biosmem.c
==============================================================================
--- head/sys/boot/i386/libi386/biosmem.c        Mon Dec  7 16:23:25 2009        
(r200218)
+++ head/sys/boot/i386/libi386/biosmem.c        Mon Dec  7 16:29:43 2009        
(r200219)
@@ -35,14 +35,20 @@ __FBSDID("$FreeBSD$");
 #include "libi386.h"
 #include "btxv86.h"
 
-vm_offset_t    memtop, memtop_copyin;
-uint32_t       bios_basemem, bios_extmem;
+vm_offset_t    memtop, memtop_copyin, high_heap_base;
+uint32_t       bios_basemem, bios_extmem, high_heap_size;
 
 static struct bios_smap smap;
 
+/*
+ * The minimum amount of memory to reserve in bios_extmem for the heap.
+ */
+#define        HEAP_MIN        (3 * 1024 * 1024)
+
 void
 bios_getmem(void)
 {
+    uint64_t size;
 
     /* Parse system memory map */
     v86.ebx = 0;
@@ -65,6 +71,26 @@ bios_getmem(void)
        if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base == 0x100000)) {
            bios_extmem = smap.length;
        }
+
+       /*
+        * Look for the largest segment in 'extended' memory beyond
+        * 1MB but below 4GB.
+        */
+       if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base > 0x100000) &&
+           (smap.base < 0x100000000ull)) {
+           size = smap.length;
+
+           /*
+            * If this segment crosses the 4GB boundary, truncate it.
+            */
+           if (smap.base + size > 0x100000000ull)
+               size = 0x100000000ull - smap.base;
+
+           if (size > high_heap_size) {
+               high_heap_size = size;
+               high_heap_base = smap.base;
+           }
+       }
     } while (v86.ebx != 0);
 
     /* Fall back to the old compatibility function for base memory */
@@ -97,4 +123,13 @@ bios_getmem(void)
     /* Set memtop to actual top of memory */
     memtop = memtop_copyin = 0x100000 + bios_extmem;
 
+    /*
+     * If we have extended memory and did not find a suitable heap
+     * region in the SMAP, use the last 3MB of 'extended' memory as a
+     * high heap candidate.
+     */
+    if (bios_extmem >= HEAP_MIN && high_heap_size < HEAP_MIN) {
+       high_heap_size = HEAP_MIN;
+       high_heap_base = memtop - HEAP_MIN;
+    }
 }    

Modified: head/sys/boot/i386/libi386/libi386.h
==============================================================================
--- head/sys/boot/i386/libi386/libi386.h        Mon Dec  7 16:23:25 2009        
(r200218)
+++ head/sys/boot/i386/libi386/libi386.h        Mon Dec  7 16:29:43 2009        
(r200219)
@@ -99,6 +99,8 @@ extern vm_offset_t    memtop_copyin;  /* mem
                                        /*  when heap is at the top of         
*/
                                        /*  extended memory; for other cases   
*/
                                        /*  just the same as memtop            
*/
+extern uint32_t                high_heap_size; /* extended memory region 
available */
+extern vm_offset_t     high_heap_base; /* for use as the heap */
 
 int biospci_find_devclass(uint32_t class, int index, uint32_t *locator);
 int biospci_write_config(uint32_t locator, int offset, int width, uint32_t 
val);

Modified: head/sys/boot/i386/loader/main.c
==============================================================================
--- head/sys/boot/i386/loader/main.c    Mon Dec  7 16:23:25 2009        
(r200218)
+++ head/sys/boot/i386/loader/main.c    Mon Dec  7 16:29:43 2009        
(r200219)
@@ -104,13 +104,17 @@ main(void)
 
 #if defined(LOADER_BZIP2_SUPPORT) || defined(LOADER_FIREWIRE_SUPPORT) || \
     defined(LOADER_GPT_SUPPORT) || defined(LOADER_ZFS_SUPPORT)
-    heap_top = PTOV(memtop_copyin);
-    memtop_copyin -= 0x300000;
-    heap_bottom = PTOV(memtop_copyin);
-#else
-    heap_top = (void *)bios_basemem;
-    heap_bottom = (void *)end;
+    if (high_heap_size > 0) {
+       heap_top = PTOV(high_heap_base + high_heap_size);
+       heap_bottom = PTOV(high_heap_base);
+       if (high_heap_base < memtop_copyin)
+           memtop_copyin = high_heap_base;
+    } else
 #endif
+    {
+       heap_top = (void *)PTOV(bios_basemem);
+       heap_bottom = (void *)end;
+    }
     setheap(heap_bottom, heap_top);
 
     /* 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to