[SeaBIOS] [PATCH 1/8] Use the e-segment instead of the 9-segment for bios "low mem".

Kevin O'Connor kevin at koconnor.net
Mon May 14 05:33:59 CEST 2012


Use the e-segment for ZoneLow allocations.  There is plenty of
e-segment space (there has been since SeaBIOS supported code
relocation), while using the 9-segment space can impact old real-mode
applications.

Signed-off-by: Kevin O'Connor <kevin at koconnor.net>
---
 src/config.h     |    1 +
 src/optionroms.c |   14 +-----
 src/pmm.c        |  116 ++++++++++++-----------------------------------------
 src/shadow.c     |    4 +-
 src/util.h       |    2 +-
 5 files changed, 34 insertions(+), 103 deletions(-)

diff --git a/src/config.h b/src/config.h
index bbacae7..521469b 100644
--- a/src/config.h
+++ b/src/config.h
@@ -38,6 +38,7 @@
 #define BUILD_ROM_START           0xc0000
 #define BUILD_BIOS_ADDR           0xf0000
 #define BUILD_BIOS_SIZE           0x10000
+#define BUILD_LOWMEM_SIZE         0x8000
 // 32KB for shadow ram copying (works around emulator deficiencies)
 #define BUILD_BIOS_TMP_ADDR       0x30000
 #define BUILD_SMM_INIT_ADDR       0x38000
diff --git a/src/optionroms.c b/src/optionroms.c
index 06db1c1..5ce8af8 100644
--- a/src/optionroms.c
+++ b/src/optionroms.c
@@ -16,12 +16,10 @@
 #include "paravirt.h" // qemu_cfg_*
 #include "optionroms.h" // struct rom_header
 
-/****************************************************************
- * Definitions
- ****************************************************************/
-
 // The end of the last deployed rom.
 u32 RomEnd = BUILD_ROM_START;
+// The maximum memory location a rom may extend to.
+u32 RomTop;
 
 
 /****************************************************************
@@ -120,15 +118,9 @@ get_pci_rom(struct rom_header *rom)
     return pd;
 }
 
-// Return start of code in 0xc0000-0xf0000 space.
-static inline u32 _max_rom(void) {
-    extern u8 code32flat_start[], code32init_end[];
-    return CONFIG_RELOCATE_INIT ? (u32)code32init_end : (u32)code32flat_start;
-}
 // Return the memory position up to which roms may be located.
 static inline u32 max_rom(void) {
-    u32 end = _max_rom();
-    return end > BUILD_BIOS_ADDR ? BUILD_BIOS_ADDR : end;
+    return RomTop;
 }
 
 // Copy a rom to its permanent location below 1MiB
diff --git a/src/pmm.c b/src/pmm.c
index c649fd8..1648bf2 100644
--- a/src/pmm.c
+++ b/src/pmm.c
@@ -9,6 +9,7 @@
 #include "memmap.h" // struct e820entry
 #include "farptr.h" // GET_FARVAR
 #include "biosvar.h" // GET_BDA
+#include "optionroms.h" // OPTION_ROM_ALIGN
 
 // Information on a reserved area.
 struct allocinfo_s {
@@ -164,6 +165,15 @@ findLast(struct zone_s *zone)
  * Setup
  ****************************************************************/
 
+// Return start of code in 0xc0000-0xf0000 space.
+static inline u32 lowmemend(void) {
+    extern u8 code32flat_start[], code32init_end[];
+    u32 end = CONFIG_RELOCATE_INIT ? (u32)code32init_end : (u32)code32flat_start;
+    return end > BUILD_BIOS_ADDR ? BUILD_BIOS_ADDR : end;
+}
+
+#define OPROM_HEADER_RESERVE 16
+
 void
 malloc_setup(void)
 {
@@ -194,7 +204,9 @@ malloc_setup(void)
     // Populate other regions
     addSpace(&ZoneTmpLow, (void*)BUILD_STACK_ADDR, (void*)BUILD_EBDA_MINIMUM);
     addSpace(&ZoneFSeg, BiosTableSpace, &BiosTableSpace[CONFIG_MAX_BIOSTABLE]);
-    addSpace(&ZoneLow, (void*)BUILD_LOWRAM_END, (void*)BUILD_LOWRAM_END);
+    u32 lowend = lowmemend();
+    RomTop = ALIGN_DOWN(lowend-BUILD_LOWMEM_SIZE, OPTION_ROM_ALIGN);
+    addSpace(&ZoneLow, (void*)RomTop + OPROM_HEADER_RESERVE, (void*)lowend);
     if (highram) {
         addSpace(&ZoneHigh, (void*)highram
                  , (void*)highram + CONFIG_MAX_HIGHTABLE);
@@ -232,12 +244,21 @@ malloc_finalize(void)
     ASSERT32FLAT();
     dprintf(3, "malloc finalize\n");
 
-    // Reserve more low-mem if needed.
-    u32 endlow = GET_BDA(mem_size_kb)*1024;
-    add_e820(endlow, BUILD_LOWRAM_END-endlow, E820_RESERVED);
+    // Place an optionrom signature around used low mem area.
+    struct allocinfo_s *info = findLast(&ZoneLow);
+    u32 base = BUILD_BIOS_ADDR;
+    if (info && info->allocend < (void*)BUILD_BIOS_ADDR) {
+        base = ALIGN_DOWN((u32)info->allocend - OPROM_HEADER_RESERVE
+                          , OPTION_ROM_ALIGN);
+        struct rom_header *dummyrom = (void*)base;
+        dummyrom->signature = OPTION_ROM_SIGNATURE;
+        dummyrom->size = (BUILD_BIOS_ADDR - base) / 512;
+    }
+    memset((void*)RomEnd, 0, base-RomEnd);
+    dprintf(1, "Space available for UMB: %08x-%08x\n", RomEnd, base);
 
     // Give back unused high ram.
-    struct allocinfo_s *info = findLast(&ZoneHigh);
+    info = findLast(&ZoneHigh);
     if (info) {
         u32 giveback = ALIGN_DOWN(info->allocend - info->dataend, PAGE_SIZE);
         add_e820((u32)info->dataend, giveback, E820_RAM);
@@ -247,89 +268,6 @@ malloc_finalize(void)
 
 
 /****************************************************************
- * ebda movement
- ****************************************************************/
-
-// Move ebda
-static int
-relocate_ebda(u32 newebda, u32 oldebda, u8 ebda_size)
-{
-    u32 lowram = GET_BDA(mem_size_kb) * 1024;
-    if (oldebda != lowram)
-        // EBDA isn't at end of ram - give up.
-        return -1;
-
-    // Do copy
-    memmove((void*)newebda, (void*)oldebda, ebda_size * 1024);
-
-    // Update indexes
-    dprintf(1, "ebda moved from %x to %x\n", oldebda, newebda);
-    SET_BDA(mem_size_kb, newebda / 1024);
-    SET_BDA(ebda_seg, FLATPTR_TO_SEG(newebda));
-    return 0;
-}
-
-// Support expanding the ZoneLow dynamically.
-static void
-zonelow_expand(u32 size, u32 align)
-{
-    struct allocinfo_s *info = findLast(&ZoneLow);
-    if (!info)
-        return;
-    u32 oldpos = (u32)info->allocend;
-    u32 newpos = ALIGN_DOWN(oldpos - size, align);
-    u32 bottom = (u32)info->dataend;
-    if (newpos >= bottom && newpos <= oldpos)
-        // Space already present.
-        return;
-    u16 ebda_seg = get_ebda_seg();
-    u32 ebda_pos = (u32)MAKE_FLATPTR(ebda_seg, 0);
-    u8 ebda_size = GET_EBDA2(ebda_seg, size);
-    u32 ebda_end = ebda_pos + ebda_size * 1024;
-    if (ebda_end != bottom)
-        // Something else is after ebda - can't use any existing space.
-        newpos = ALIGN_DOWN(ebda_end - size, align);
-    u32 newbottom = ALIGN_DOWN(newpos, 1024);
-    u32 newebda = ALIGN_DOWN(newbottom - ebda_size * 1024, 1024);
-    if (newebda < BUILD_EBDA_MINIMUM)
-        // Not enough space.
-        return;
-
-    // Move ebda
-    int ret = relocate_ebda(newebda, ebda_pos, ebda_size);
-    if (ret)
-        return;
-
-    // Update zone
-    if (ebda_end == bottom) {
-        info->data = (void*)newbottom;
-        info->dataend = (void*)newbottom;
-    } else
-        addSpace(&ZoneLow, (void*)newbottom, (void*)ebda_end);
-}
-
-// Check if can expand the given zone to fulfill an allocation
-static void *
-allocExpandSpace(struct zone_s *zone, u32 size, u32 align
-                 , struct allocinfo_s *fill)
-{
-    void *data = allocSpace(zone, size, align, fill);
-    if (data || zone != &ZoneLow)
-        return data;
-
-    // Make sure to not move ebda while an optionrom is running.
-    if (unlikely(wait_preempt())) {
-        data = allocSpace(zone, size, align, fill);
-        if (data)
-            return data;
-    }
-
-    zonelow_expand(size, align);
-    return allocSpace(zone, size, align, fill);
-}
-
-
-/****************************************************************
  * tracked memory allocations
  ****************************************************************/
 
@@ -352,7 +290,7 @@ pmm_malloc(struct zone_s *zone, u32 handle, u32 size, u32 align)
     }
 
     // Find and reserve space for main allocation
-    void *data = allocExpandSpace(zone, size, align, &detail->datainfo);
+    void *data = allocSpace(zone, size, align, &detail->datainfo);
     if (!data) {
         freeSpace(&detail->detailinfo);
         return NULL;
diff --git a/src/shadow.c b/src/shadow.c
index c0c8cc2..70f04c5 100644
--- a/src/shadow.c
+++ b/src/shadow.c
@@ -83,8 +83,8 @@ make_bios_readonly_intel(u16 bdf, u32 pam0)
     for (i=0; i<6; i++) {
         u32 mem = BUILD_ROM_START + i * 32*1024;
         u32 pam = pam0 + 1 + i;
-        if (RomEnd <= mem + 16*1024) {
-            if (RomEnd > mem)
+        if (RomEnd <= mem + 16*1024 || RomTop <= mem + 32*1024) {
+            if (RomEnd > mem && RomTop > mem + 16*1024)
                 pci_config_writeb(bdf, pam, 0x31);
             break;
         }
diff --git a/src/util.h b/src/util.h
index 70d3c4c..04de66b 100644
--- a/src/util.h
+++ b/src/util.h
@@ -400,7 +400,7 @@ void call_bcv(u16 seg, u16 ip);
 void optionrom_setup(void);
 void vga_setup(void);
 void s3_resume_vga_init(void);
-extern u32 RomEnd;
+extern u32 RomEnd, RomTop;
 extern int ScreenAndDebug;
 
 // bootsplash.c
-- 
1.7.6.5




More information about the SeaBIOS mailing list