[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


 


Rackspace

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