[SeaBIOS] [PATCH 15/15] Experiment with SeaBIOS internal memory above 4GB

Kevin O'Connor kevin at koconnor.net
Thu Oct 1 04:04:18 CET 2015


This is a test.  Changes to paravirt.c and stacks.c are not correct.
---
 src/fw/paravirt.c |  8 ++++++++
 src/malloc.c      | 48 +++++++++++++++++++++++++++++-------------------
 src/malloc.h      | 15 +++++++++++----
 src/stacks.c      |  2 +-
 4 files changed, 49 insertions(+), 24 deletions(-)

diff --git a/src/fw/paravirt.c b/src/fw/paravirt.c
index acb44b9..6c71366 100644
--- a/src/fw/paravirt.c
+++ b/src/fw/paravirt.c
@@ -120,6 +120,14 @@ qemu_preinit(void)
     e820_add(0xfffc0000, 256*1024, E820_RESERVED);
 
     dprintf(1, "RamSize: 0x%08x [cmos]\n", RamSize);
+
+    // XXX
+    u64 high = ((rtc_read(CMOS_MEM_HIGHMEM_LOW) << 16)
+                | ((u32)rtc_read(CMOS_MEM_HIGHMEM_MID) << 24)
+                | ((u64)rtc_read(CMOS_MEM_HIGHMEM_HIGH) << 32));
+    RamSizeOver4G = high;
+    e820_add(0x100000000ull, high, E820_RAM);
+    dprintf(1, "RamSizeOver4G: 0x%016llx [cmos]\n", RamSizeOver4G);
 }
 
 void
diff --git a/src/malloc.c b/src/malloc.c
index c6b460e..9a684d6 100644
--- a/src/malloc.c
+++ b/src/malloc.c
@@ -18,7 +18,8 @@
 // Information on a reserved area.
 struct allocinfo_s {
     struct hlist_node node;
-    u32 range_start, range_end, alloc_size;
+    u64 range_start, range_end;
+    u32 alloc_size;
 };
 
 // Information on a tracked memory allocation.
@@ -36,9 +37,10 @@ struct zone_s {
 struct zone_s ZoneLow VARVERIFY32INIT, ZoneHigh VARVERIFY32INIT;
 struct zone_s ZoneFSeg VARVERIFY32INIT;
 struct zone_s ZoneTmpLow VARVERIFY32INIT, ZoneTmpHigh VARVERIFY32INIT;
+struct zone_s ZoneTmpHigh64 VARVERIFY32INIT;
 
 static struct zone_s *Zones[] VARVERIFY32INIT = {
-    &ZoneTmpLow, &ZoneLow, &ZoneFSeg, &ZoneTmpHigh, &ZoneHigh
+    &ZoneTmpLow, &ZoneLow, &ZoneFSeg, &ZoneTmpHigh, &ZoneHigh, &ZoneTmpHigh64
 };
 
 
@@ -47,14 +49,14 @@ static struct zone_s *Zones[] VARVERIFY32INIT = {
  ****************************************************************/
 
 // Find and reserve space from a given zone
-static u32
+static u64
 alloc_new(struct zone_s *zone, u32 size, u32 align, struct allocinfo_s *fill)
 {
     struct allocinfo_s *info;
     hlist_for_each_entry(info, &zone->head, node) {
-        u32 alloc_end = info->range_start + info->alloc_size;
-        u32 range_end = info->range_end;
-        u32 new_range_end = ALIGN_DOWN(range_end - size, align);
+        u64 alloc_end = info->range_start + info->alloc_size;
+        u64 range_end = info->range_end;
+        u64 new_range_end = ALIGN_DOWN(range_end - size, align);
         if (new_range_end >= alloc_end && new_range_end <= range_end) {
             // Found space - now reserve it.
             fill->range_start = new_range_end;
@@ -73,14 +75,18 @@ alloc_new(struct zone_s *zone, u32 size, u32 align, struct allocinfo_s *fill)
 static struct allocdetail_s *
 alloc_new_detail(struct allocdetail_s *temp)
 {
-    u32 detail_addr = alloc_new(&ZoneTmpHigh, sizeof(struct allocdetail_s)
+    u64 detail_addr = alloc_new(&ZoneTmpHigh64, sizeof(struct allocdetail_s)
                                 , MALLOC_MIN_ALIGN, &temp->detailinfo);
     if (!detail_addr) {
-        detail_addr = alloc_new(&ZoneTmpLow, sizeof(struct allocdetail_s)
+        detail_addr = alloc_new(&ZoneTmpHigh, sizeof(struct allocdetail_s)
                                 , MALLOC_MIN_ALIGN, &temp->detailinfo);
         if (!detail_addr) {
-            warn_noalloc();
-            return NULL;
+            detail_addr = alloc_new(&ZoneTmpLow, sizeof(struct allocdetail_s)
+                                    , MALLOC_MIN_ALIGN, &temp->detailinfo);
+            if (!detail_addr) {
+                warn_noalloc();
+                return NULL;
+            }
         }
     }
     struct allocdetail_s *detail = memremap(detail_addr, sizeof(*detail));
@@ -94,7 +100,7 @@ alloc_new_detail(struct allocdetail_s *temp)
 
 // Add new memory to a zone
 static void
-alloc_add(struct zone_s *zone, u32 start, u32 end)
+alloc_add(struct zone_s *zone, u64 start, u64 end)
 {
     // Find position to add space
     struct allocinfo_s *info;
@@ -131,7 +137,7 @@ alloc_free(struct allocinfo_s *info)
 
 // Search all zones for an allocation obtained from alloc_new()
 static struct allocinfo_s *
-alloc_find(u32 data)
+alloc_find(u64 data)
 {
     int i;
     for (i=0; i<ARRAY_SIZE(Zones); i++) {
@@ -232,7 +238,7 @@ zonelow_expand(u32 size, u32 align, struct allocinfo_s *fill)
  ****************************************************************/
 
 // Allocate physical memory from the given zone and track it as a PMM allocation
-u32
+u64
 phys_alloc(struct zone_s *zone, u32 size, u32 align)
 {
     ASSERT32FLAT();
@@ -242,7 +248,7 @@ phys_alloc(struct zone_s *zone, u32 size, u32 align)
     // Find and reserve space for main allocation
     struct allocdetail_s tempdetail;
     tempdetail.handle = MALLOC_DEFAULT_HANDLE;
-    u32 data = alloc_new(zone, size, align, &tempdetail.datainfo);
+    u64 data = alloc_new(zone, size, align, &tempdetail.datainfo);
     if (!CONFIG_MALLOC_UPPERMEMORY && !data && zone == &ZoneLow)
         data = zonelow_expand(size, align, &tempdetail.datainfo);
     if (!data)
@@ -255,7 +261,7 @@ phys_alloc(struct zone_s *zone, u32 size, u32 align)
         return 0;
     }
 
-    dprintf(8, "phys_alloc zone=%p size=%d align=%x ret=%x (detail=%p)\n"
+    dprintf(8, "phys_alloc zone=%p size=%d align=%x ret=%llx (detail=%p)\n"
             , zone, size, align, data, detail);
 
     return data;
@@ -270,7 +276,7 @@ _malloc(struct zone_s *zone, u32 size, u32 align)
 
 // Free a data block allocated with phys_alloc
 int
-phys_free(u32 data)
+phys_free(u64 data)
 {
     ASSERT32FLAT();
     struct allocinfo_s *info = alloc_find(data);
@@ -278,7 +284,7 @@ phys_free(u32 data)
         return -1;
     struct allocdetail_s *detail = container_of(
         info, struct allocdetail_s, datainfo);
-    dprintf(8, "phys_free %x (detail=%p)\n", data, detail);
+    dprintf(8, "phys_free %llx (detail=%p)\n", data, detail);
     alloc_free(info);
     alloc_free(&detail->detailinfo);
     return 0;
@@ -429,8 +435,12 @@ malloc_preinit(void)
         u64 end = en->start + en->size;
         if (end < 1024*1024)
             break;
-        if (en->type != E820_RAM || end > 0xffffffff)
+        if (en->type != E820_RAM)
             continue;
+        if (end > 0xffffffff) {
+            alloc_add(&ZoneTmpHigh64, en->start, end);
+            continue;
+        }
         u32 s = en->start, e = end;
         if (!highram) {
             u32 newe = ALIGN_DOWN(e - BUILD_MAX_HIGHTABLE, MALLOC_MIN_ALIGN);
@@ -548,7 +558,7 @@ malloc_prepboot(void)
     struct allocinfo_s *info = alloc_get_sentinel(&ZoneFSeg);
     u32 size = info->range_end - info->range_start;
     memset(memremap(info->range_start, size), 0, size);
-    dprintf(1, "Space available for UMB: %x-%x, %x-%x\n"
+    dprintf(1, "Space available for UMB: %x-%x, %llx-%llx\n"
             , RomEnd, base, info->range_start, info->range_end);
 
     // Give back unused high ram.
diff --git a/src/malloc.h b/src/malloc.h
index 84c285e..d964361 100644
--- a/src/malloc.h
+++ b/src/malloc.h
@@ -5,6 +5,7 @@
 
 // malloc.c
 extern struct zone_s ZoneLow, ZoneHigh, ZoneFSeg, ZoneTmpLow, ZoneTmpHigh;
+extern struct zone_s ZoneTmpHigh64;
 u32 rom_get_max(void);
 u32 rom_get_last(void);
 struct rom_header *rom_reserve(u32 size);
@@ -15,9 +16,9 @@ void malloc_preinit(void);
 extern u32 LegacyRamSize;
 void malloc_init(void);
 void malloc_prepboot(void);
-u32 phys_alloc(struct zone_s *zone, u32 size, u32 align);
+u64 phys_alloc(struct zone_s *zone, u32 size, u32 align);
 void *_malloc(struct zone_s *zone, u32 size, u32 align);
-int phys_free(u32 data);
+int phys_free(u64 data);
 void free(void *data);
 u32 malloc_getspace(struct zone_s *zone);
 void malloc_sethandle(u32 data, u32 handle);
@@ -43,7 +44,10 @@ static inline void *malloc_tmphigh(u32 size) {
     return _malloc(&ZoneTmpHigh, size, MALLOC_MIN_ALIGN);
 }
 static inline void *malloc_tmp(u32 size) {
-    void *ret = malloc_tmphigh(size);
+    void *ret = _malloc(&ZoneTmpHigh64, size, MALLOC_MIN_ALIGN);
+    if (ret)
+        return ret;
+    ret = malloc_tmphigh(size);
     if (ret)
         return ret;
     return malloc_tmplow(size);
@@ -61,7 +65,10 @@ static inline void *memalign_tmphigh(u32 align, u32 size) {
     return _malloc(&ZoneTmpHigh, size, align);
 }
 static inline void *memalign_tmp(u32 align, u32 size) {
-    void *ret = memalign_tmphigh(align, size);
+    void *ret = _malloc(&ZoneTmpHigh64, size, align);
+    if (ret)
+        return ret;
+    ret = memalign_tmphigh(align, size);
     if (ret)
         return ret;
     return memalign_tmplow(align, size);
diff --git a/src/stacks.c b/src/stacks.c
index a3de397..583b456 100644
--- a/src/stacks.c
+++ b/src/stacks.c
@@ -563,7 +563,7 @@ run_thread(void (*func)(void*), void *data)
     if (! CONFIG_THREADS || ! ThreadControl)
         goto fail;
     struct thread_info *thread;
-    thread = memalign_tmphigh(THREADSTACKSIZE, THREADSTACKSIZE);
+    thread = memalign_tmp(THREADSTACKSIZE, THREADSTACKSIZE); // XXX
     if (!thread)
         goto fail;
 
-- 
2.4.3




More information about the SeaBIOS mailing list