[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] hvmloader: Reserve BIOS memory and VGA memory at top of 4GB memory hole.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1231433961 0
# Node ID 67ffce500feb0c815404b5d25ab8ff9472c8e9e3
# Parent  61dc77689daf1f9d2697c93f10decb57e8f57f7e
hvmloader: Reserve BIOS memory and VGA memory at top of 4GB memory hole.

To make memory management easier in hvmloader, defer building a
generic E820 map until the end of hvmloader bootstrap.

Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 tools/firmware/hvmloader/32bitbios_support.c |    2 
 tools/firmware/hvmloader/acpi/build.c        |   11 +--
 tools/firmware/hvmloader/config.h            |    4 +
 tools/firmware/hvmloader/hvmloader.c         |   52 +++++---------
 tools/firmware/hvmloader/smbios.c            |   22 +-----
 tools/firmware/hvmloader/util.c              |   99 +++++++++++++--------------
 tools/firmware/hvmloader/util.h              |    5 -
 7 files changed, 89 insertions(+), 106 deletions(-)

diff -r 61dc77689daf -r 67ffce500feb 
tools/firmware/hvmloader/32bitbios_support.c
--- a/tools/firmware/hvmloader/32bitbios_support.c      Thu Jan 08 16:53:15 
2009 +0000
+++ b/tools/firmware/hvmloader/32bitbios_support.c      Thu Jan 08 16:59:21 
2009 +0000
@@ -76,7 +76,7 @@ static void relocate_32bitbios(char *elf
      */
     reloc_size = reloc_off;
     printf("%d bytes of ROMBIOS high-memory extensions:\n", reloc_size);
-    highbiosarea = (char *)(long)e820_malloc(reloc_size, 0);
+    highbiosarea = mem_alloc(reloc_size, 0);
     BUG_ON(highbiosarea == NULL);
     printf("  Relocating to 0x%x-0x%x ... ",
            (uint32_t)&highbiosarea[0],
diff -r 61dc77689daf -r 67ffce500feb tools/firmware/hvmloader/acpi/build.c
--- a/tools/firmware/hvmloader/acpi/build.c     Thu Jan 08 16:53:15 2009 +0000
+++ b/tools/firmware/hvmloader/acpi/build.c     Thu Jan 08 16:59:21 2009 +0000
@@ -199,6 +199,7 @@ static int construct_secondary_tables(ui
     struct acpi_20_tcpa *tcpa;
     static const uint16_t tis_signature[] = {0x0001, 0x0001, 0x0001};
     uint16_t *tis_hdr;
+    void *lasa;
 
     /* MADT. */
     if ( (hvm_info->nr_vcpus > 1) || hvm_info->apic_mode )
@@ -246,11 +247,11 @@ static int construct_secondary_tables(ui
         tcpa->header.oem_revision = ACPI_OEM_REVISION;
         tcpa->header.creator_id   = ACPI_CREATOR_ID;
         tcpa->header.creator_revision = ACPI_CREATOR_REVISION;
-        tcpa->lasa = e820_malloc(ACPI_2_0_TCPA_LAML_SIZE, 0);
-        if ( tcpa->lasa )
-        {
+        if ( (lasa = mem_alloc(ACPI_2_0_TCPA_LAML_SIZE, 0)) != NULL )
+        {
+            tcpa->lasa = virt_to_phys(lasa);
             tcpa->laml = ACPI_2_0_TCPA_LAML_SIZE;
-            memset((char *)(unsigned long)tcpa->lasa, 0, tcpa->laml);
+            memset(lasa, 0, tcpa->laml);
             set_checksum(tcpa,
                          offsetof(struct acpi_header, checksum),
                          tcpa->header.length);
@@ -376,7 +377,7 @@ void acpi_build_tables(void)
     memset(buf, 0, high_sz);
 
     /* Allocate data area and set up ACPI tables there. */
-    buf = (uint8_t *)e820_malloc(high_sz, 0);
+    buf = mem_alloc(high_sz, 0);
     __acpi_build_tables(buf, &low_sz, &high_sz);
 
     printf(" - Lo data: %08lx-%08lx\n"
diff -r 61dc77689daf -r 67ffce500feb tools/firmware/hvmloader/config.h
--- a/tools/firmware/hvmloader/config.h Thu Jan 08 16:53:15 2009 +0000
+++ b/tools/firmware/hvmloader/config.h Thu Jan 08 16:59:21 2009 +0000
@@ -16,6 +16,10 @@
 
 #define PCI_MEMBASE         0xf0000000
 #define PCI_MEMSIZE         0x0c000000
+
+/* We reserve 16MB at the top of the 4GB memory hole. */
+#define RESERVED_MEMBASE    0xff000000
+#define RESERVED_MEMSIZE    0x01000000
 
 #define ROMBIOS_SEG            0xF000
 #define ROMBIOS_BEGIN          0x000F0000
diff -r 61dc77689daf -r 67ffce500feb tools/firmware/hvmloader/hvmloader.c
--- a/tools/firmware/hvmloader/hvmloader.c      Thu Jan 08 16:53:15 2009 +0000
+++ b/tools/firmware/hvmloader/hvmloader.c      Thu Jan 08 16:59:21 2009 +0000
@@ -488,22 +488,13 @@ static int pci_load_option_roms(uint32_t
 /* Replace possibly erroneous memory-size CMOS fields with correct values. */
 static void cmos_write_memory_size(void)
 {
-    struct e820entry *map = E820;
-    int i, nr = *E820_NR;
-    uint32_t base_mem = 640, ext_mem = 0, alt_mem = 0;
-
-    for ( i = 0; i < nr; i++ )
-        if ( (map[i].addr >= 0x100000) && (map[i].type == E820_RAM) )
-            break;
-
-    if ( i != nr )
-    {
-        alt_mem = ext_mem = map[i].addr + map[i].size;
-        ext_mem = (ext_mem > 0x0100000) ? (ext_mem - 0x0100000) >> 10 : 0;
-        if ( ext_mem > 0xffff )
-            ext_mem = 0xffff;
-        alt_mem = (alt_mem > 0x1000000) ? (alt_mem - 0x1000000) >> 16 : 0;
-    }
+    uint32_t base_mem = 640, ext_mem, alt_mem;
+
+    alt_mem = ext_mem = hvm_info->low_mem_pgend << PAGE_SHIFT;
+    ext_mem = (ext_mem > 0x0100000) ? (ext_mem - 0x0100000) >> 10 : 0;
+    if ( ext_mem > 0xffff )
+        ext_mem = 0xffff;
+    alt_mem = (alt_mem > 0x1000000) ? (alt_mem - 0x1000000) >> 16 : 0;
 
     /* All BIOSes: conventional memory (CMOS *always* reports 640kB). */
     cmos_outb(0x15, (uint8_t)(base_mem >> 0));
@@ -548,16 +539,16 @@ static uint16_t init_xen_platform_io_bas
  */
 static void init_vm86_tss(void)
 {
-    uint32_t tss;
+    void *tss;
     struct xen_hvm_param p;
 
-    tss = e820_malloc(128, 128);
-    memset((char *)tss, 0, 128);
+    tss = mem_alloc(128, 128);
+    memset(tss, 0, 128);
     p.domid = DOMID_SELF;
     p.index = HVM_PARAM_VM86_TSS;
-    p.value = tss;
+    p.value = virt_to_phys(tss);
     hypercall_hvm_op(HVMOP_set_param, &p);
-    printf("vm86 TSS at %08x\n", tss);
+    printf("vm86 TSS at %08lx\n", virt_to_phys(tss));
 }
 
 /* Create an E820 table based on memory parameters provided in hvm_info. */
@@ -603,14 +594,11 @@ static void build_e820_table(void)
     e820[nr].type = E820_RAM;
     nr++;
 
-    if ( hvm_info->reserved_mem_pgstart )
-    {
-        /* Explicitly reserve space for special pages. */
-        e820[nr].addr = hvm_info->reserved_mem_pgstart << PAGE_SHIFT;
-        e820[nr].size = (uint32_t)-e820[nr].addr;
-        e820[nr].type = E820_RESERVED;
-        nr++;
-    }
+    /* Explicitly reserve space for special pages. */
+    e820[nr].addr = RESERVED_MEMBASE;
+    e820[nr].size = (uint32_t)-e820[nr].addr;
+    e820[nr].type = E820_RESERVED;
+    nr++;
 
     if ( hvm_info->high_mem_pgend )
     {
@@ -632,8 +620,6 @@ int main(void)
     uint16_t xen_pfiob;
 
     printf("HVM Loader\n");
-
-    build_e820_table();
 
     init_hypercalls();
 
@@ -680,7 +666,7 @@ int main(void)
 
     if ( virtual_vga != VGA_none )
     {
-        vga_ram = e820_malloc(8 << 20, 4096);
+        vga_ram = virt_to_phys(mem_alloc(8 << 20, 4096));
         printf("VGA RAM at %08x\n", vga_ram);
     }
 
@@ -728,6 +714,8 @@ int main(void)
     if ( xen_pfiob && vga_ram )
         outl(xen_pfiob + 4, vga_ram);
 
+    build_e820_table();
+
     printf("Invoking ROMBIOS ...\n");
     return 0;
 }
diff -r 61dc77689daf -r 67ffce500feb tools/firmware/hvmloader/smbios.c
--- a/tools/firmware/hvmloader/smbios.c Thu Jan 08 16:53:15 2009 +0000
+++ b/tools/firmware/hvmloader/smbios.c Thu Jan 08 16:59:21 2009 +0000
@@ -143,28 +143,18 @@ static uint64_t
 static uint64_t
 get_memsize(void)
 {
-    struct e820entry *map = E820;
-    uint8_t num_entries = *E820_NR;
-    uint64_t memsize = 0;
-    int i;
-
-    /*
-     * Walk through e820map, ignoring any entries that aren't marked
-     * as usable or reserved.
-     */
-    for ( i = 0; i < num_entries; i++ )
-    {
-        if ( (map->type == E820_RAM) || (map->type == E820_RESERVED) )
-            memsize += map->size;
-        map++;
-    }
+    uint64_t sz;
+
+    sz = (uint64_t)hvm_info->low_mem_pgend << PAGE_SHIFT;
+    if ( hvm_info->high_mem_pgend )
+        sz += (hvm_info->high_mem_pgend << PAGE_SHIFT) - (1ull << 32);
 
     /*
      * Round up to the nearest MB.  The user specifies domU pseudo-physical 
      * memory in megabytes, so not doing this could easily lead to reporting 
      * one less MB than the user specified.
      */
-    return (memsize + (1 << 20) - 1) >> 20;
+    return (sz + (1ul << 20) - 1) >> 20;
 }
 
 int
diff -r 61dc77689daf -r 67ffce500feb tools/firmware/hvmloader/util.c
--- a/tools/firmware/hvmloader/util.c   Thu Jan 08 16:53:15 2009 +0000
+++ b/tools/firmware/hvmloader/util.c   Thu Jan 08 16:59:21 2009 +0000
@@ -303,63 +303,62 @@ uuid_to_string(char *dest, uint8_t *uuid
     *p = '\0';
 }
 
-static void e820_collapse(void)
-{
-    int i = 0;
-    struct e820entry *ent = E820;
-
-    while ( i < (*E820_NR-1) )
-    {
-        if ( (ent[i].type == ent[i+1].type) &&
-             ((ent[i].addr + ent[i].size) == ent[i+1].addr) )
-        {
-            ent[i].size += ent[i+1].size;
-            memcpy(&ent[i+1], &ent[i+2], (*E820_NR-i-2) * sizeof(*ent));
-            (*E820_NR)--;
-        }
-        else
-        {
-            i++;
-        }
-    }
-}
-
-uint32_t e820_malloc(uint32_t size, uint32_t align)
-{
-    uint32_t addr;
-    int i;
-    struct e820entry *ent = E820;
+void *mem_alloc(uint32_t size, uint32_t align)
+{
+    static uint32_t reserve = RESERVED_MEMBASE - 1;
+    static int over_allocated;
+    struct xen_memory_reservation xmr;
+    xen_pfn_t mfn;
+    uint32_t s, e;
 
     /* Align to at least one kilobyte. */
     if ( align < 1024 )
         align = 1024;
 
-    for ( i = *E820_NR - 1; i >= 0; i-- )
-    {
-        addr = (ent[i].addr + ent[i].size - size) & ~(align-1);
-        if ( (ent[i].type != E820_RAM) || /* not ram? */
-             (addr < ent[i].addr) ||      /* too small or starts above 4gb? */
-             ((addr + size) < addr) )     /* ends above 4gb? */
+    s = (reserve + align) & ~(align - 1);
+    e = s + size - 1;
+
+    BUG_ON((e < s) || (e >> PAGE_SHIFT) >= hvm_info->reserved_mem_pgstart);
+
+    while ( (reserve >> PAGE_SHIFT) != (e >> PAGE_SHIFT) )
+    {
+        reserve += PAGE_SIZE;
+
+        /* Try to allocate another page in the reserved area. */
+        xmr.domid = DOMID_SELF;
+        xmr.mem_flags = 0;
+        xmr.extent_order = 0;
+        xmr.nr_extents = 1;
+        set_xen_guest_handle(xmr.extent_start, &mfn);
+        mfn = reserve >> PAGE_SHIFT;
+        if ( !over_allocated &&
+             (hypercall_memory_op(XENMEM_populate_physmap, &xmr) == 1) )
             continue;
 
-        if ( addr != ent[i].addr )
-        {
-            memmove(&ent[i+1], &ent[i], (*E820_NR-i) * sizeof(*ent));
-            (*E820_NR)++;
-            ent[i].size = addr - ent[i].addr;
-            ent[i+1].addr = addr;
-            ent[i+1].size -= ent[i].size;
-            i++;
-        }
-
-        ent[i].type = E820_RESERVED;
-
-        e820_collapse();
-
-        return addr;
-    }
-
-    return 0;
+        /* If we fail, steal a page from the ordinary RAM map. */
+        over_allocated = 1;
+        if ( hvm_info->high_mem_pgend )
+        {
+            mfn = --hvm_info->high_mem_pgend;
+            if ( mfn == (1ull << (32 - PAGE_SHIFT)) )
+                hvm_info->high_mem_pgend = 0;
+        }
+        else
+        {
+            mfn = --hvm_info->low_mem_pgend;
+        }
+        if ( hypercall_memory_op(XENMEM_decrease_reservation, &xmr) != 1 )
+            BUG();
+
+        /* Now try the allocation again. Must not fail. */
+        mfn = reserve >> PAGE_SHIFT;
+        if ( hypercall_memory_op(XENMEM_populate_physmap, &xmr) != 1 )
+            BUG();
+    }
+
+    reserve = e;
+
+    return (void *)(unsigned long)s;
 }
 
 uint32_t ioapic_read(uint32_t reg)
diff -r 61dc77689daf -r 67ffce500feb tools/firmware/hvmloader/util.h
--- a/tools/firmware/hvmloader/util.h   Thu Jan 08 16:53:15 2009 +0000
+++ b/tools/firmware/hvmloader/util.h   Thu Jan 08 16:59:21 2009 +0000
@@ -131,8 +131,9 @@ int printf(const char *fmt, ...) __attri
 int printf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
 int vprintf(const char *fmt, va_list ap);
 
-/* Reserve a RAM region in the e820 table. */
-uint32_t e820_malloc(uint32_t size, uint32_t align);
+/* Allocate memory in a reserved region below 4GB. */
+void *mem_alloc(uint32_t size, uint32_t align);
+#define virt_to_phys(v) ((unsigned long)(v))
 
 /* Prepare the 32bit BIOS */
 void highbios_setup(void);

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.