# 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
|