aboutsummaryrefslogtreecommitdiff
path: root/sys/boot
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2009-12-18 20:28:04 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2009-12-18 20:28:04 +0000
commit5f0cb0c9cd41b07a32d1cd39b82dcea1eb5ad97b (patch)
treeda03e4442874aa1e474407c189b3139a099e7e94 /sys/boot
parent08c59cc33e2ab071496d41c250a686de58b552f6 (diff)
Notes
Diffstat (limited to 'sys/boot')
-rw-r--r--sys/boot/i386/libi386/biosmem.c40
-rw-r--r--sys/boot/i386/libi386/libi386.h17
-rw-r--r--sys/boot/i386/loader/main.c19
3 files changed, 59 insertions, 17 deletions
diff --git a/sys/boot/i386/libi386/biosmem.c b/sys/boot/i386/libi386/biosmem.c
index 3c2205ed46c2..bae68131b87b 100644
--- a/sys/boot/i386/libi386/biosmem.c
+++ b/sys/boot/i386/libi386/biosmem.c
@@ -35,14 +35,20 @@ __FBSDID("$FreeBSD$");
#include "libi386.h"
#include "btxv86.h"
-vm_offset_t memtop, memtop_copyin;
-u_int32_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,5 +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;
+ }
}
-
diff --git a/sys/boot/i386/libi386/libi386.h b/sys/boot/i386/libi386/libi386.h
index 4ac5cb569fb2..ebf1b4ce9494 100644
--- a/sys/boot/i386/libi386/libi386.h
+++ b/sys/boot/i386/libi386/libi386.h
@@ -78,9 +78,9 @@ int bc_add(int biosdev); /* Register CD booted from. */
int bc_getdev(struct i386_devdesc *dev); /* return dev_t for (dev) */
int bc_bios2unit(int biosdev); /* xlate BIOS device -> bioscd unit */
int bc_unit2bios(int unit); /* xlate bioscd unit -> BIOS device */
-u_int32_t bd_getbigeom(int bunit); /* return geometry in bootinfo format */
-int bd_bios2unit(int biosdev); /* xlate BIOS device -> biosdisk unit */
-int bd_unit2bios(int unit); /* xlate biosdisk unit -> BIOS device */
+uint32_t bd_getbigeom(int bunit); /* return geometry in bootinfo format */
+int bd_bios2unit(int biosdev); /* xlate BIOS device -> biosdisk unit */
+int bd_unit2bios(int unit); /* xlate biosdisk unit -> BIOS device */
int bd_getdev(struct i386_devdesc *dev); /* return dev_t for (dev) */
ssize_t i386_copyin(const void *src, vm_offset_t dest, const size_t len);
@@ -92,12 +92,15 @@ void bios_addsmapdata(struct preloaded_file *);
void bios_getsmap(void);
void bios_getmem(void);
-extern u_int32_t bios_basemem; /* base memory in bytes */
-extern u_int32_t bios_extmem; /* extended memory in bytes */
+extern uint32_t bios_basemem; /* base memory in bytes */
+extern uint32_t bios_extmem; /* extended memory in bytes */
extern vm_offset_t memtop; /* last address of physical memory + 1 */
extern vm_offset_t memtop_copyin; /* memtop less heap size for the cases */
- /* when heap is at the top of extended memory */
- /* for other cases - just the same as memtop */
+ /* 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);
diff --git a/sys/boot/i386/loader/main.c b/sys/boot/i386/loader/main.c
index 701dd3a12228..75d5dbcb6ec5 100644
--- a/sys/boot/i386/loader/main.c
+++ b/sys/boot/i386/loader/main.c
@@ -102,14 +102,19 @@ main(void)
*/
bios_getmem();
-#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 defined(LOADER_BZIP2_SUPPORT) || defined(LOADER_FIREWIRE_SUPPORT) || \
+ defined(LOADER_GPT_SUPPORT) || defined(LOADER_ZFS_SUPPORT)
+ 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);
/*