From 3f247eab7ad21aa61c39a584a4513663cf025d5d Mon Sep 17 00:00:00 2001 From: Toomas Soome Date: Mon, 18 Sep 2017 15:17:01 +0000 Subject: [PATCH] loader: biosmem allocate heap just below 4GB The current biosmem code is walking bios smap entries and looking for smap entry just below 4GB line, if there is such entry, its base and size is set for heap base and size. Instead of entry base, we should use last HEAP_MIN (currently 64MB) bytes just below 4GB, to make maximum space for kernel and modules. The problem was revealed on ASUS B350M-A system board, an AMD Ryzen 3 1200 CPU memory map: SMAP type=01 base=0000000000000000 len=000000000009d400 attr=01 SMAP type=02 base=000000000009d400 len=0000000000002c00 attr=01 SMAP type=02 base=00000000000e0000 len=0000000000020000 attr=01 SMAP type=01 base=0000000000100000 len=0000000009c00000 attr=01 SMAP type=02 base=0000000009d00000 len=0000000000300000 attr=01 SMAP type=01 base=000000000a000000 len=00000000be69b000 attr=01 SMAP type=03 base=00000000c869b000 len=0000000000016000 attr=01 SMAP type=01 base=00000000c86b1000 len=00000000124e7000 attr=01 SMAP type=02 base=00000000dab98000 len=0000000000138000 attr=01 SMAP type=03 base=00000000dacd0000 len=0000000000008000 attr=01 SMAP type=01 base=00000000dacd8000 len=0000000000100000 attr=01 SMAP type=04 base=00000000dadd8000 len=00000000003b3000 attr=01 SMAP type=02 base=00000000db18b000 len=0000000000d42000 attr=01 SMAP type=01 base=00000000dbecd000 len=0000000002133000 attr=01 SMAP type=01 base=0000000100000000 len=000000011f380000 attr=01 SMAP type=02 base=00000000de000000 len=0000000002000000 attr=01 SMAP type=02 base=00000000f8000000 len=0000000004000000 attr=01 SMAP type=02 base=00000000fdf00000 len=0000000000100000 attr=01 SMAP type=02 base=00000000fea00000 len=0000000000010000 attr=01 SMAP type=02 base=00000000feb80000 len=0000000000082000 attr=01 SMAP type=02 base=00000000fec10000 len=0000000000001000 attr=01 SMAP type=02 base=00000000fec30000 len=0000000000001000 attr=01 SMAP type=02 base=00000000fed00000 len=0000000000001000 attr=01 SMAP type=02 base=00000000fed40000 len=0000000000005000 attr=01 SMAP type=02 base=00000000fed80000 len=0000000000010000 attr=01 SMAP type=02 base=00000000fedc2000 len=000000000000e000 attr=01 SMAP type=02 base=00000000fedd4000 len=0000000000002000 attr=01 SMAP type=02 base=00000000fee00000 len=0000000000100000 attr=01 SMAP type=02 base=00000000ff000000 len=0000000001000000 attr=01 Reviewed by: imp Differential Revision: https://reviews.freebsd.org/D12368 --- sys/boot/i386/libi386/biosmem.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/sys/boot/i386/libi386/biosmem.c b/sys/boot/i386/libi386/biosmem.c index 572826f24c3..7105757e810 100644 --- a/sys/boot/i386/libi386/biosmem.c +++ b/sys/boot/i386/libi386/biosmem.c @@ -125,7 +125,7 @@ bios_getmem(void) } /* - * Look for the largest segment in 'extended' memory beyond + * Look for the highest segment in 'extended' memory beyond * 1MB but below 4GB. */ if ((smap.type == SMAP_TYPE_MEMORY) && @@ -140,9 +140,13 @@ bios_getmem(void) if (smap.base + size > 0x100000000ull) size = 0x100000000ull - smap.base; - if (size > high_heap_size) { - high_heap_size = size; - high_heap_base = smap.base; + /* + * To make maximum space for the kernel and the modules, + * set heap to use highest HEAP_MIN bytes below 4GB. + */ + if (high_heap_base < smap.base && size >= HEAP_MIN) { + high_heap_base = smap.base + size - HEAP_MIN; + high_heap_size = HEAP_MIN; } } } while (v86.ebx != 0); @@ -203,7 +207,11 @@ bios_getmem(void) } /* Set memtop to actual top of memory */ - memtop = memtop_copyin = 0x100000 + bios_extmem; + if (high_heap_size != 0) { + memtop = memtop_copyin = high_heap_base; + } else { + memtop = memtop_copyin = 0x100000 + bios_extmem; + } /* * If we have extended memory and did not find a suitable heap @@ -213,6 +221,7 @@ bios_getmem(void) if (bios_extmem >= HEAP_MIN && high_heap_size < HEAP_MIN) { high_heap_size = HEAP_MIN; high_heap_base = memtop - HEAP_MIN; + memtop = memtop_copyin = high_heap_base; } }