hvmloader: reduce unnecessary e820 reservations for SeaBIOS
authorIan Campbell <ian.campbell@citrix.com>
Wed, 8 Jun 2011 12:40:23 +0000 (13:40 +0100)
committerIan Campbell <ian.campbell@citrix.com>
Wed, 8 Jun 2011 12:40:23 +0000 (13:40 +0100)
SeaBIOS will reserve memory in the e820 as necessary, including BIOS
data structures such as the EBDA, any tables it creates or copies into
pleace etc.  Therefore arrange that the memory map provided by
hvmloader to SeaBIOS reserves only things which HVMloader has created.

Since ROMBIOS is more tightly coupled with hvmloader we retain the
ability to reserve BIOS regions in the hvmloader produced e820 and use
that from the ROMBIOS backend.

The code for this could probably have been simpler but the existing
code avoids overlapping e820 areas and so the new code does the same
(many guest OSes sanitize the e820 map to handle this, but I wouldn't
trust that all do, so I didn't take the risk)

For ROMBIOS the resulting e820 map as seen by the guest is the same
except the reserved regions at 0x9e000-0x9fc00,0x9fc00-0xa0000 are
merged into a single region 0x9e000-0xa0000 (Linux guests sanitize the
e820 to look like this anyway).

For SeaBIOS the result is that the lowmem reserved region is from
0x9f000-0xa0000 rather than 0x9e000-0xa0000 which correctly reflects
SeaBIOS's actual usage.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
tools/firmware/hvmloader/config.h
tools/firmware/hvmloader/e820.c
tools/firmware/hvmloader/rombios.c
tools/firmware/hvmloader/seabios.c
tools/firmware/hvmloader/util.h

index d916442ce360f70a1fd92af59796d8e18467ff23..989dd345cdac585cff96621a3bdeff76c505f4ab 100644 (file)
@@ -66,6 +66,9 @@ extern unsigned long pci_mem_start, pci_mem_end;
 #define VGABIOS_PHYSICAL_ADDRESS      0x000C0000
 #define HVMLOADER_PHYSICAL_ADDRESS    0x00100000
 
+#define ACPI_INFO_SIZE                     0xC00
+#define ACPI_INFO_PHYSICAL_END (ACPI_INFO_PHYSICAL_ADDRESS + ACPI_INFO_SIZE)
+
 extern unsigned long scratch_start;
 
 #endif /* __HVMLOADER_CONFIG_H__ */
index 9ab5380a6b83105d6d307047a2efdc49ba93eca7..710532f7613ddc58b4a7b3531b24335cbd316000 100644 (file)
@@ -69,28 +69,67 @@ void dump_e820_table(struct e820entry *e820, unsigned int nr)
 }
 
 /* Create an E820 table based on memory parameters provided in hvm_info. */
-int build_e820_table(struct e820entry *e820)
+int build_e820_table(struct e820entry *e820,
+                     unsigned int lowmem_reserved_base,
+                     unsigned int bios_image_base)
 {
     unsigned int nr = 0;
 
-    /* 0x0-0x9E000: Ordinary RAM. */
-    /* (Must be at least 512K to keep Windows happy) */
-    e820[nr].addr = 0x00000;
-    e820[nr].size = 0x9E000;
-    e820[nr].type = E820_RAM;
-    nr++;
+    if ( !lowmem_reserved_base )
+            lowmem_reserved_base = 0xA0000;
 
-    /* 0x9E000-0x9FC00: Reserved for internal use. */
-    e820[nr].addr = 0x9E000;
-    e820[nr].size = 0x01C00;
-    e820[nr].type = E820_RESERVED;
-    nr++;
+    /* Lowmem must be at least 512K to keep Windows happy) */
+    ASSERT ( lowmem_reserved_base > 512<<10 );
 
-    /* 0x9FC00-0xA0000: Extended BIOS Data Area (EBDA). */
-    e820[nr].addr = 0x9FC00;
-    e820[nr].size = 0x400;
-    e820[nr].type = E820_RESERVED;
-    nr++;
+    /*
+     * Lowmem reservation must either cover the ACPI info region
+     * entirely or not at all. Sitting half way through suggests
+     * something funny is going on.
+     */
+    ASSERT ( lowmem_reserved_base < ACPI_INFO_PHYSICAL_ADDRESS ||
+             lowmem_reserved_base > ACPI_INFO_PHYSICAL_END );
+
+    ASSERT ( bios_image_base < 0x100000 );
+
+    if ( lowmem_reserved_base < ACPI_INFO_PHYSICAL_ADDRESS ) {
+        /*
+         * 0x0-lowmem_reserved_base: Ordinary RAM.
+         */
+        e820[nr].addr = 0x00000;
+        e820[nr].size = lowmem_reserved_base;
+        e820[nr].type = E820_RAM;
+        nr++;
+    }
+    else
+    {
+        /* 0x0-ACPI_INFO: Ordinary RAM. */
+        e820[nr].addr = 0x00000;
+        e820[nr].size = ACPI_INFO_PHYSICAL_ADDRESS;
+        e820[nr].type = E820_RAM;
+        nr++;
+
+        /* ACPI INFO: Reserved. */
+        e820[nr].addr = ACPI_INFO_PHYSICAL_ADDRESS;
+        e820[nr].size = ACPI_INFO_SIZE;
+        e820[nr].type = E820_RESERVED;
+        nr++;
+
+        /* ACPI_INFO-lowmem_reserved_base: Ordinary RAM. */
+        e820[nr].addr = ACPI_INFO_PHYSICAL_END;
+        e820[nr].size = lowmem_reserved_base - ACPI_INFO_PHYSICAL_END;
+        e820[nr].type = E820_RAM;
+        nr++;
+    }
+
+    /* lowmem_reserved_base-0xa00000: reserved by BIOS implementation. */
+    if ( lowmem_reserved_base < 0xA0000 )
+    {
+            /* Reserved for internal use. */
+            e820[nr].addr = lowmem_reserved_base;
+            e820[nr].size = 0xA0000-lowmem_reserved_base;
+            e820[nr].type = E820_RESERVED;
+            nr++;
+    }
 
     /*
      * Following regions are standard regions of the PC memory map.
@@ -101,12 +140,10 @@ int build_e820_table(struct e820entry *e820)
      */
 
     /*
-     * 0xE0000-0x0F0000: PC-specific area. We place various tables here.
-     * 0xF0000-0x100000: System BIOS.
-     * TODO: free pages which turn out to be unused.
+     * BIOS region.
      */
-    e820[nr].addr = 0xE0000;
-    e820[nr].size = 0x20000;
+    e820[nr].addr = bios_image_base;
+    e820[nr].size = 0x100000-bios_image_base;
     e820[nr].type = E820_RESERVED;
     nr++;
 
index 137167386d64a05d529c252bbad104456e662f36..96ba718f3fbdd579baa9525b734e3f2f5c3dc920 100644 (file)
@@ -61,7 +61,15 @@ static void rombios_init_vm86_tss(void)
 
 static void rombios_setup_e820(void)
 {
-    *E820_NR = build_e820_table(E820);
+    /*
+     * 0x9E000-0x09F000: Stack.
+     * 0x9F000-0x09C000: ACPI info.
+     * 0x9FC00-0x0A0000: Extended BIOS Data Area (EBDA).
+     * ...
+     * 0xE0000-0x0F0000: PC-specific area. We place various tables here.
+     * 0xF0000-0x100000: System BIOS.
+     */
+    *E820_NR = build_e820_table(E820, 0x9E000, 0xE0000);
     dump_e820_table(E820, *E820_NR);
 }
 
index 7297f511ff8f674efbb2cf2f752b75f3915d6030..8cd01085f72022180a55c6dc2f25c9025f2353dd 100644 (file)
@@ -117,7 +117,9 @@ static void seabios_setup_e820(void)
     struct seabios_info *info = (void *)BIOS_INFO_PHYSICAL_ADDRESS;
     struct e820entry *e820 = scratch_alloc(sizeof(struct e820entry)*16, 0);
     info->e820 = (uint32_t)e820;
-    info->e820_nr = build_e820_table(e820);
+
+    /* SeaBIOS reserves memory in e820 as necessary so no low reservation. */
+    info->e820_nr = build_e820_table(e820, 0, 0x100000-sizeof(seabios));
     dump_e820_table(e820, info->e820_nr);
 }
 
index 27c7f90ab9ceb84a6883f50936889755a098beae..3eb6845be91bf29f631b6bc6fb0d3f1be5d9493e 100644 (file)
@@ -200,7 +200,9 @@ unsigned long create_pir_tables(void);
 void smp_initialise(void);
 
 #include "e820.h"
-int build_e820_table(struct e820entry *e820);
+int build_e820_table(struct e820entry *e820,
+                    unsigned int lowmem_reserved_base,
+                    unsigned int bios_image_base);
 void dump_e820_table(struct e820entry *e820, unsigned int nr);
 
 #ifndef NDEBUG