[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] x86, hvm: Move E820 table creation into hvmloader, extend
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1231428440 0 # Node ID 8c894687c2a5e01567a526865ad8f79b48786718 # Parent 0d119f6287952a2503835cb1946f00edc3ebff94 x86, hvm: Move E820 table creation into hvmloader, extend hvm_info_table to describe memory parameters in a simpler form from domain builder to hvmloader. Also move reserved special page mappings immediately below the 4GB boundary. Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx> --- tools/firmware/hvmloader/config.h | 3 tools/firmware/hvmloader/hvmloader.c | 72 ++++++++++-- tools/firmware/hvmloader/util.c | 35 +++--- tools/libxc/xc_hvm_build.c | 185 +++++++++++--------------------- tools/python/xen/lowlevel/xc/xc.c | 10 - xen/include/public/hvm/hvm_info_table.h | 28 ++++ 6 files changed, 183 insertions(+), 150 deletions(-) diff -r 0d119f628795 -r 8c894687c2a5 tools/firmware/hvmloader/config.h --- a/tools/firmware/hvmloader/config.h Thu Jan 08 15:18:30 2009 +0000 +++ b/tools/firmware/hvmloader/config.h Thu Jan 08 15:27:20 2009 +0000 @@ -1,5 +1,8 @@ #ifndef __HVMLOADER_CONFIG_H__ #define __HVMLOADER_CONFIG_H__ + +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1ul << PAGE_SHIFT) #define IOAPIC_BASE_ADDRESS 0xfec00000 #define IOAPIC_ID 0x01 diff -r 0d119f628795 -r 8c894687c2a5 tools/firmware/hvmloader/hvmloader.c --- a/tools/firmware/hvmloader/hvmloader.c Thu Jan 08 15:18:30 2009 +0000 +++ b/tools/firmware/hvmloader/hvmloader.c Thu Jan 08 15:27:20 2009 +0000 @@ -560,15 +560,67 @@ static void init_vm86_tss(void) printf("vm86 TSS at %08x\n", tss); } -/* - * Copy the E820 table provided by the HVM domain builder into the correct - * place in the memory map we share with the rombios. - */ -static void copy_e820_table(void) -{ - uint8_t nr = *(uint8_t *)(HVM_E820_PAGE + HVM_E820_NR_OFFSET); - BUG_ON(nr > 16); - memcpy(E820, (char *)HVM_E820_PAGE + HVM_E820_OFFSET, nr * sizeof(*E820)); +/* Create an E820 table based on memory parameters provided in hvm_info. */ +static void build_e820_table(void) +{ + struct e820entry *e820 = E820; + unsigned int nr = 0; + + /* 0x0-0x9FC00: Ordinary RAM. */ + e820[nr].addr = 0x0; + e820[nr].size = 0x9FC00; + e820[nr].type = E820_RAM; + nr++; + + /* 0x9FC00-0xA0000: Extended BIOS Data Area (EBDA). */ + e820[nr].addr = 0x9FC00; + e820[nr].size = 0x400; + e820[nr].type = E820_RESERVED; + nr++; + + /* + * Following regions are standard regions of the PC memory map. + * They are not covered by e820 regions. OSes will not use as RAM. + * 0xA0000-0xC0000: VGA memory-mapped I/O. Not covered by E820. + * 0xC0000-0xE0000: 16-bit devices, expansion ROMs (inc. vgabios). + * TODO: free pages which turn out to be unused. + */ + + /* + * 0xE0000-0x0F0000: PC-specific area. We place various tables here. + * 0xF0000-0x100000: System BIOS. + * TODO: free pages which turn out to be unused. + */ + e820[nr].addr = 0xE0000; + e820[nr].size = 0x20000; + e820[nr].type = E820_RESERVED; + nr++; + + /* Low RAM goes here. Reserve space for special pages. */ + BUG_ON((hvm_info->low_mem_pgend << PAGE_SHIFT) < (2u << 20)); + e820[nr].addr = 0x100000; + e820[nr].size = (hvm_info->low_mem_pgend << PAGE_SHIFT) - e820[nr].addr; + 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++; + } + + if ( hvm_info->high_mem_pgend ) + { + e820[nr].addr = ((uint64_t)1 << 32); + e820[nr].size = + ((uint64_t)hvm_info->high_mem_pgend << PAGE_SHIFT) - e820[nr].addr; + e820[nr].type = E820_RAM; + nr++; + } + *E820_NR = nr; } @@ -581,7 +633,7 @@ int main(void) printf("HVM Loader\n"); - copy_e820_table(); + build_e820_table(); init_hypercalls(); diff -r 0d119f628795 -r 8c894687c2a5 tools/firmware/hvmloader/util.c --- a/tools/firmware/hvmloader/util.c Thu Jan 08 15:18:30 2009 +0000 +++ b/tools/firmware/hvmloader/util.c Thu Jan 08 15:27:20 2009 +0000 @@ -542,27 +542,32 @@ void __bug(char *file, int line) asm volatile ( "ud2" ); } -static int validate_hvm_info(struct hvm_info_table *t) -{ - char signature[] = "HVM INFO"; +static void validate_hvm_info(struct hvm_info_table *t) +{ uint8_t *ptr = (uint8_t *)t; uint8_t sum = 0; int i; - /* strncmp(t->signature, "HVM INFO", 8) */ - for ( i = 0; i < 8; i++ ) - { - if ( signature[i] != t->signature[i] ) - { - printf("Bad hvm info signature\n"); - return 0; - } + if ( strncmp(t->signature, "HVM INFO", 8) ) + { + printf("Bad hvm info signature\n"); + BUG(); + } + + if ( t->length < sizeof(struct hvm_info_table) ) + { + printf("Bad hvm info length\n"); + BUG(); } for ( i = 0; i < t->length; i++ ) sum += ptr[i]; - return (sum == 0); + if ( sum != 0 ) + { + printf("Bad hvm info checksum\n"); + BUG(); + } } struct hvm_info_table *get_hvm_info_table(void) @@ -575,11 +580,7 @@ struct hvm_info_table *get_hvm_info_tabl t = (struct hvm_info_table *)HVM_INFO_PADDR; - if ( !validate_hvm_info(t) ) - { - printf("Bad hvm info table\n"); - BUG(); - } + validate_hvm_info(t); table = t; diff -r 0d119f628795 -r 8c894687c2a5 tools/libxc/xc_hvm_build.c --- a/tools/libxc/xc_hvm_build.c Thu Jan 08 15:18:30 2009 +0000 +++ b/tools/libxc/xc_hvm_build.c Thu Jan 08 15:27:20 2009 +0000 @@ -15,100 +15,55 @@ #include <xen/foreign/x86_64.h> #include <xen/hvm/hvm_info_table.h> #include <xen/hvm/params.h> -#include "xc_e820.h" +#include <xen/hvm/e820.h> #include <xen/libelf/libelf.h> #define SUPERPAGE_PFN_SHIFT 9 #define SUPERPAGE_NR_PFNS (1UL << SUPERPAGE_PFN_SHIFT) -#define SCRATCH_PFN 0xFFFFF - -#define SPECIALPAGE_GUARD 0 -#define SPECIALPAGE_BUFIOREQ 1 -#define SPECIALPAGE_XENSTORE 2 -#define SPECIALPAGE_IOREQ 3 -#define SPECIALPAGE_IDENT_PT 4 +#define SPECIALPAGE_BUFIOREQ 0 +#define SPECIALPAGE_XENSTORE 1 +#define SPECIALPAGE_IOREQ 2 +#define SPECIALPAGE_IDENT_PT 3 +#define SPECIALPAGE_SHINFO 4 #define NR_SPECIAL_PAGES 5 - -static void build_e820map(void *e820_page, unsigned long long mem_size) -{ - struct e820entry *e820entry = - (struct e820entry *)(((unsigned char *)e820_page) + HVM_E820_OFFSET); - unsigned long long extra_mem_size = 0; - unsigned char nr_map = 0; - - /* - * Physical address space from HVM_BELOW_4G_RAM_END to 4G is reserved - * for PCI devices MMIO. So if HVM has more than HVM_BELOW_4G_RAM_END - * RAM, memory beyond HVM_BELOW_4G_RAM_END will go to 4G above. - */ - if ( mem_size > HVM_BELOW_4G_RAM_END ) - { - extra_mem_size = mem_size - HVM_BELOW_4G_RAM_END; - mem_size = HVM_BELOW_4G_RAM_END; - } - - /* 0x0-0x9FC00: Ordinary RAM. */ - e820entry[nr_map].addr = 0x0; - e820entry[nr_map].size = 0x9FC00; - e820entry[nr_map].type = E820_RAM; - nr_map++; - - /* 0x9FC00-0xA0000: Extended BIOS Data Area (EBDA). */ - e820entry[nr_map].addr = 0x9FC00; - e820entry[nr_map].size = 0x400; - e820entry[nr_map].type = E820_RESERVED; - nr_map++; - - /* - * Following regions are standard regions of the PC memory map. - * They are not covered by e820 regions. OSes will not use as RAM. - * 0xA0000-0xC0000: VGA memory-mapped I/O. Not covered by E820. - * 0xC0000-0xE0000: 16-bit devices, expansion ROMs (inc. vgabios). - * TODO: hvmloader should free pages which turn out to be unused. - */ - - /* - * 0xE0000-0x0F0000: PC-specific area. We place ACPI tables here. - * We *cannot* mark as E820_ACPI, for two reasons: - * 1. ACPI spec. says that E820_ACPI regions below - * 16MB must clip INT15h 0x88 and 0xe801 queries. - * Our rombios doesn't do this. - * 2. The OS is allowed to reclaim ACPI memory after - * parsing the tables. But our FACS is in this - * region and it must not be reclaimed (it contains - * the ACPI global lock!). - * 0xF0000-0x100000: System BIOS. - * TODO: hvmloader should free pages which turn out to be unused. - */ - e820entry[nr_map].addr = 0xE0000; - e820entry[nr_map].size = 0x20000; - e820entry[nr_map].type = E820_RESERVED; - nr_map++; - - /* Low RAM goes here. Reserve space for special pages. */ - e820entry[nr_map].addr = 0x100000; - e820entry[nr_map].size = (mem_size - 0x100000 - - PAGE_SIZE * NR_SPECIAL_PAGES); - e820entry[nr_map].type = E820_RAM; - nr_map++; - - /* Explicitly reserve space for special pages (excluding guard page). */ - e820entry[nr_map].addr = mem_size - PAGE_SIZE * (NR_SPECIAL_PAGES - 1); - e820entry[nr_map].size = PAGE_SIZE * (NR_SPECIAL_PAGES - 1); - e820entry[nr_map].type = E820_RESERVED; - nr_map++; - - if ( extra_mem_size ) - { - e820entry[nr_map].addr = (1ULL << 32); - e820entry[nr_map].size = extra_mem_size; - e820entry[nr_map].type = E820_RAM; - nr_map++; - } - - *(((unsigned char *)e820_page) + HVM_E820_NR_OFFSET) = nr_map; +#define special_pfn(x) (0x100000u - NR_SPECIAL_PAGES + (x)) + +static void build_hvm_info(void *hvm_info_page, uint64_t mem_size) +{ + struct hvm_info_table *hvm_info = (struct hvm_info_table *) + (((unsigned char *)hvm_info_page) + HVM_INFO_OFFSET); + uint64_t lowmem_end = mem_size, highmem_end = 0; + uint8_t sum; + int i; + + if ( lowmem_end > HVM_BELOW_4G_RAM_END ) + { + highmem_end = lowmem_end + (1ull<<32) - HVM_BELOW_4G_RAM_END; + lowmem_end = HVM_BELOW_4G_RAM_END; + } + + memset(hvm_info_page, 0, PAGE_SIZE); + + /* Fill in the header. */ + strncpy(hvm_info->signature, "HVM INFO", 8); + hvm_info->length = sizeof(struct hvm_info_table); + + /* Sensible defaults: these can be overridden by the caller. */ + hvm_info->acpi_enabled = 1; + hvm_info->apic_mode = 1; + hvm_info->nr_vcpus = 1; + + /* Memory parameters. */ + hvm_info->low_mem_pgend = lowmem_end >> PAGE_SHIFT; + hvm_info->high_mem_pgend = highmem_end >> PAGE_SHIFT; + hvm_info->reserved_mem_pgstart = special_pfn(0); + + /* Finish with the checksum. */ + for ( i = 0, sum = 0; i < hvm_info->length; i++ ) + sum += ((uint8_t *)hvm_info)[i]; + hvm_info->checksum = -sum; } static int loadelfimage( @@ -153,10 +108,10 @@ static int setup_guest(int xc_handle, unsigned long i, nr_pages = (unsigned long)memsize << (20 - PAGE_SHIFT); unsigned long target_pages = (unsigned long)target << (20 - PAGE_SHIFT); unsigned long pod_pages = 0; - unsigned long special_page_nr, entry_eip, cur_pages; + unsigned long entry_eip, cur_pages; struct xen_add_to_physmap xatp; struct shared_info *shared_info; - void *e820_page; + void *hvm_info_page; uint32_t *ident_pt; struct elf_binary elf; uint64_t v_start, v_end; @@ -289,23 +244,22 @@ static int setup_guest(int xc_handle, if ( loadelfimage(&elf, xc_handle, dom, page_array) != 0 ) goto error_out; - if ( (e820_page = xc_map_foreign_range( + if ( (hvm_info_page = xc_map_foreign_range( xc_handle, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, - HVM_E820_PAGE >> PAGE_SHIFT)) == NULL ) - goto error_out; - memset(e820_page, 0, PAGE_SIZE); - build_e820map(e820_page, v_end); - munmap(e820_page, PAGE_SIZE); + HVM_INFO_PFN)) == NULL ) + goto error_out; + build_hvm_info(hvm_info_page, v_end); + munmap(hvm_info_page, PAGE_SIZE); /* Map and initialise shared_info page. */ xatp.domid = dom; xatp.space = XENMAPSPACE_shared_info; xatp.idx = 0; - xatp.gpfn = SCRATCH_PFN; + xatp.gpfn = special_pfn(SPECIALPAGE_SHINFO); if ( (xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp) != 0) || ((shared_info = xc_map_foreign_range( xc_handle, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, - SCRATCH_PFN)) == NULL) ) + special_pfn(SPECIALPAGE_SHINFO))) == NULL) ) goto error_out; memset(shared_info, 0, PAGE_SIZE); /* NB. evtchn_upcall_mask is unused: leave as zero. */ @@ -313,31 +267,28 @@ static int setup_guest(int xc_handle, sizeof(shared_info->evtchn_mask)); munmap(shared_info, PAGE_SIZE); - special_page_nr = (((v_end > HVM_BELOW_4G_RAM_END) - ? (HVM_BELOW_4G_RAM_END >> PAGE_SHIFT) - : (v_end >> PAGE_SHIFT)) - - NR_SPECIAL_PAGES); - - /* Paranoia: clean special pages. */ + /* Allocate and clear special pages. */ for ( i = 0; i < NR_SPECIAL_PAGES; i++ ) - if ( xc_clear_domain_page(xc_handle, dom, special_page_nr + i) ) + { + xen_pfn_t pfn = special_pfn(i); + if ( i == SPECIALPAGE_SHINFO ) + continue; + rc = xc_domain_memory_populate_physmap(xc_handle, dom, 1, 0, 0, &pfn); + if ( rc != 0 ) + { + PERROR("Could not allocate %d'th special page.\n", i); goto error_out; - - /* Free the guard page that separates low RAM from special pages. */ - rc = xc_domain_memory_decrease_reservation( - xc_handle, dom, 1, 0, &page_array[special_page_nr]); - if ( rc != 0 ) - { - PERROR("Could not deallocate guard page for HVM guest.\n"); - goto error_out; + } + if ( xc_clear_domain_page(xc_handle, dom, special_pfn(i)) ) + goto error_out; } xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, - special_page_nr + SPECIALPAGE_XENSTORE); + special_pfn(SPECIALPAGE_XENSTORE)); xc_set_hvm_param(xc_handle, dom, HVM_PARAM_BUFIOREQ_PFN, - special_page_nr + SPECIALPAGE_BUFIOREQ); + special_pfn(SPECIALPAGE_BUFIOREQ)); xc_set_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN, - special_page_nr + SPECIALPAGE_IOREQ); + special_pfn(SPECIALPAGE_IOREQ)); /* * Identity-map page table is required for running with CR0.PG=0 when @@ -345,14 +296,14 @@ static int setup_guest(int xc_handle, */ if ( (ident_pt = xc_map_foreign_range( xc_handle, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, - special_page_nr + SPECIALPAGE_IDENT_PT)) == NULL ) + special_pfn(SPECIALPAGE_IDENT_PT))) == NULL ) goto error_out; for ( i = 0; i < PAGE_SIZE / sizeof(*ident_pt); i++ ) ident_pt[i] = ((i << 22) | _PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_PSE); munmap(ident_pt, PAGE_SIZE); xc_set_hvm_param(xc_handle, dom, HVM_PARAM_IDENT_PT, - (special_page_nr + SPECIALPAGE_IDENT_PT) << PAGE_SHIFT); + special_pfn(SPECIALPAGE_IDENT_PT) << PAGE_SHIFT); /* Insert JMP <rel32> instruction at address 0x0 to reach entry point. */ entry_eip = elf_uval(&elf, elf.ehdr, e_entry); diff -r 0d119f628795 -r 8c894687c2a5 tools/python/xen/lowlevel/xc/xc.c --- a/tools/python/xen/lowlevel/xc/xc.c Thu Jan 08 15:18:30 2009 +0000 +++ b/tools/python/xen/lowlevel/xc/xc.c Thu Jan 08 15:27:20 2009 +0000 @@ -903,26 +903,24 @@ static PyObject *pyxc_hvm_build(XcObject if ( target == -1 ) target = memsize; - if ( xc_hvm_build_target_mem(self->xc_handle, dom, memsize, target, image) != 0 ) + if ( xc_hvm_build_target_mem(self->xc_handle, dom, memsize, + target, image) != 0 ) return pyxc_error_to_exception(); #if !defined(__ia64__) - /* Set up the HVM info table. */ + /* Fix up the HVM info table. */ va_map = xc_map_foreign_range(self->xc_handle, dom, XC_PAGE_SIZE, PROT_READ | PROT_WRITE, HVM_INFO_PFN); if ( va_map == NULL ) return PyErr_SetFromErrno(xc_error_obj); va_hvm = (struct hvm_info_table *)(va_map + HVM_INFO_OFFSET); - memset(va_hvm, 0, sizeof(*va_hvm)); - strncpy(va_hvm->signature, "HVM INFO", 8); - va_hvm->length = sizeof(struct hvm_info_table); va_hvm->acpi_enabled = acpi; va_hvm->apic_mode = apic; va_hvm->nr_vcpus = vcpus; for ( i = 0, sum = 0; i < va_hvm->length; i++ ) sum += ((uint8_t *)va_hvm)[i]; - va_hvm->checksum = -sum; + va_hvm->checksum -= sum; munmap(va_map, XC_PAGE_SIZE); #endif diff -r 0d119f628795 -r 8c894687c2a5 xen/include/public/hvm/hvm_info_table.h --- a/xen/include/public/hvm/hvm_info_table.h Thu Jan 08 15:18:30 2009 +0000 +++ b/xen/include/public/hvm/hvm_info_table.h Thu Jan 08 15:27:20 2009 +0000 @@ -33,9 +33,37 @@ struct hvm_info_table { char signature[8]; /* "HVM INFO" */ uint32_t length; uint8_t checksum; + + /* Should firmware build ACPI tables? */ uint8_t acpi_enabled; + + /* Should firmware build APIC descriptors (APIC MADT / MP BIOS)? */ uint8_t apic_mode; + + /* How many CPUs does this domain have? */ uint32_t nr_vcpus; + + /* + * MEMORY MAP provided by HVM domain builder. + * Notes: + * 1. page_to_phys(x) = x << 12 + * 2. If a field is zero, the corresponding range does not exist. + */ + /* + * 0x0 to page_to_phys(low_mem_pgend)-1: + * RAM below 4GB (except for VGA hole 0xA0000-0xBFFFF) + */ + uint32_t low_mem_pgend; + /* + * page_to_phys(reserved_mem_pgstart) to 0xFFFFFFFF: + * Reserved for special memory mappings + */ + uint32_t reserved_mem_pgstart; + /* + * 0x100000000 to page_to_phys(high_mem_pgend)-1: + * RAM above 4GB + */ + uint32_t high_mem_pgend; }; #endif /* __XEN_PUBLIC_HVM_HVM_INFO_TABLE_H__ */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |