[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |