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

[Xen-changelog] [xen-unstable] [IA64] memmap: introduce memmap_info_t



# HG changeset patch
# User Alex Williamson <alex.williamson@xxxxxx>
# Date 1179763831 21600
# Node ID c2768258711da6dadd021a5aad883fff949e255d
# Parent  caafa45d24b3cbf05ab97ab33235e5b91ac44323
[IA64] memmap: introduce memmap_info_t

Signed-off-by: Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
---
 tools/libxc/xc_dom_ia64.c      |   64 +++++++++++
 xen/arch/ia64/xen/dom_fw.c     |  223 ++++++++++++++++++++++++++++++++++++++---
 xen/include/public/arch-ia64.h |    7 +
 3 files changed, 279 insertions(+), 15 deletions(-)

diff -r caafa45d24b3 -r c2768258711d tools/libxc/xc_dom_ia64.c
--- a/tools/libxc/xc_dom_ia64.c Mon May 21 10:09:33 2007 -0600
+++ b/tools/libxc/xc_dom_ia64.c Mon May 21 10:10:31 2007 -0600
@@ -77,6 +77,8 @@ static int shared_info_ia64(struct xc_do
     for (i = 0; i < MAX_VIRT_CPUS; i++)
         shared_info->vcpu_info[i].evtchn_upcall_mask = 1;
     shared_info->arch.start_info_pfn = dom->start_info_pfn;
+    shared_info->arch.memmap_info_num_pages = 1;
+    shared_info->arch.memmap_info_pfn = dom->start_info_pfn - 1;
     return 0;
 }
 
@@ -129,6 +131,8 @@ static void __init register_arch_hooks(v
     xc_dom_register_arch_hooks(&xc_dom_arch_ia64be);
 }
 
+#include "xc_efi.h"
+
 int arch_setup_meminit(struct xc_dom_image *dom)
 {
     xen_pfn_t pfn;
@@ -146,12 +150,69 @@ int arch_setup_meminit(struct xc_dom_ima
     return rc;
 }
 
+static int ia64_setup_memmap(struct xc_dom_image *dom)
+{
+    unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
+    unsigned long memmap_info_pfn;
+    xen_ia64_memmap_info_t* memmap_info;
+    unsigned int num_mds;
+    efi_memory_desc_t *md;
+
+    char* start_info;
+    struct xen_ia64_boot_param* bp;
+
+    /* setup memmap page */
+    memmap_info_pfn = dom->start_info_pfn - 1;
+    xc_dom_printf("%s: memmap: mfn 0x%" PRIpfn "\n",
+                 __FUNCTION__, memmap_info_pfn);
+    memmap_info = xc_map_foreign_range(dom->guest_xc, dom->guest_domid,
+                                       page_size,
+                                       PROT_READ | PROT_WRITE,
+                                       memmap_info_pfn);
+    if (NULL == memmap_info)
+        return -1;
+    /* [0, total_pages) */
+    memmap_info->efi_memdesc_size = sizeof(md[0]);
+    memmap_info->efi_memdesc_version = EFI_MEMORY_DESCRIPTOR_VERSION;
+    num_mds = 0;
+    md = (efi_memory_desc_t*)&memmap_info->memdesc;
+    md[num_mds].type = EFI_CONVENTIONAL_MEMORY;
+    md[num_mds].pad = 0;
+    md[num_mds].phys_addr = 0;
+    md[num_mds].virt_addr = 0;
+    md[num_mds].num_pages = dom->total_pages << (PAGE_SHIFT - EFI_PAGE_SHIFT);
+    md[num_mds].attribute = EFI_MEMORY_WB;
+    num_mds++;
+    memmap_info->efi_memmap_size = num_mds * sizeof(md[0]);
+    munmap(memmap_info, page_size);
+
+    /* kludge: we need to pass memmap_info page's pfn somehow.
+     * we use xen_ia64_boot_param::efi_memmap for this purpose */
+    start_info = xc_map_foreign_range(dom->guest_xc, dom->guest_domid,
+                                     page_size,
+                                     PROT_READ | PROT_WRITE,
+                                     dom->start_info_pfn);
+    if (NULL == start_info)
+        return -1;
+    bp = (struct xen_ia64_boot_param*)(start_info + sizeof(start_info_t));
+    memset(bp, 0, sizeof(*bp));
+    bp->efi_memmap = memmap_info_pfn;
+    /* 4 = memmap info page, start info page, xenstore page and console page */
+    bp->efi_memmap_size = 4 * PAGE_SIZE;
+    munmap(start_info, page_size);
+    return 0;
+}
+
 int arch_setup_bootearly(struct xc_dom_image *dom)
 {
     DECLARE_DOMCTL;
     int rc;
 
     xc_dom_printf("%s: setup firmware\n", __FUNCTION__);
+
+    rc = ia64_setup_memmap(dom);
+    if (rc)
+        return rc;
 
     memset(&domctl, 0, sizeof(domctl));
     domctl.cmd = XEN_DOMCTL_arch_setup;
@@ -160,8 +221,7 @@ int arch_setup_bootearly(struct xc_dom_i
 
     domctl.u.arch_setup.bp = (dom->start_info_pfn << PAGE_SHIFT)
         + sizeof(start_info_t);
-    /* 3 = start info page, xenstore page and console page */
-    domctl.u.arch_setup.maxmem = (dom->total_pages - 3) << PAGE_SHIFT;
+    domctl.u.arch_setup.maxmem = dom->total_pages << PAGE_SHIFT;
     rc = do_domctl(dom->guest_xc, &domctl);
     return rc;
 }
diff -r caafa45d24b3 -r c2768258711d xen/arch/ia64/xen/dom_fw.c
--- a/xen/arch/ia64/xen/dom_fw.c        Mon May 21 10:09:33 2007 -0600
+++ b/xen/arch/ia64/xen/dom_fw.c        Mon May 21 10:10:31 2007 -0600
@@ -508,6 +508,63 @@ struct fw_tables {
 #define FW_FIELD_MPA(field) \
    FW_TABLES_BASE_PADDR + offsetof(struct fw_tables, field)
 
+static void
+setup_dom0_memmap_info(struct domain *d, struct fw_tables *tables,
+                      int *num_mds)
+{
+       int i;
+       efi_memory_desc_t *md;
+       efi_memory_desc_t *last_mem_md = NULL;
+       xen_ia64_memmap_info_t* memmap_info;
+       unsigned long paddr_start;
+       unsigned long paddr_end;
+
+       for (i = *num_mds - 1; i >= 0; i--) {
+               md = &tables->efi_memmap[i];
+               if (md->attribute == EFI_MEMORY_WB &&
+                   md->type == EFI_CONVENTIONAL_MEMORY &&
+                   md->num_pages >
+                   2 * (1UL << (PAGE_SHIFT - EFI_PAGE_SHIFT))) {
+                       last_mem_md = md;
+                       break;
+               }
+       }
+
+       if (last_mem_md == NULL) {
+               printk("%s: warning: "
+                      "no dom0 contiguous memory to hold memory map\n",
+                      __func__);
+               return;
+       }
+       paddr_end = last_mem_md->phys_addr +
+               (last_mem_md->num_pages << EFI_PAGE_SHIFT);
+       paddr_start = (paddr_end - PAGE_SIZE) & PAGE_MASK;
+       last_mem_md->num_pages -=
+               (paddr_end - paddr_start) / (1UL << EFI_PAGE_SHIFT);
+
+       md = &tables->efi_memmap[*num_mds];
+       (*num_mds)++;
+       md->type = EFI_RUNTIME_SERVICES_DATA;
+       md->phys_addr = paddr_start;
+       md->virt_addr = 0;
+       md->num_pages = 1UL << (PAGE_SHIFT - EFI_PAGE_SHIFT);
+       md->attribute = EFI_MEMORY_WB;
+
+       memmap_info = domain_mpa_to_imva(d, md->phys_addr);
+       BUG_ON(*num_mds > NUM_MEM_DESCS);
+
+       memmap_info->efi_memdesc_size = sizeof(md[0]);
+       memmap_info->efi_memdesc_version = EFI_MEMORY_DESCRIPTOR_VERSION;
+       memmap_info->efi_memmap_size = *num_mds * sizeof(md[0]);
+       memcpy(&memmap_info->memdesc, &tables->efi_memmap[0],
+              memmap_info->efi_memmap_size);
+       d->shared_info->arch.memmap_info_num_pages = 1;
+       d->shared_info->arch.memmap_info_pfn = md->phys_addr >> PAGE_SHIFT;
+
+       sort(tables->efi_memmap, *num_mds, sizeof(efi_memory_desc_t),
+            efi_mdt_cmp, NULL);
+}
+
 /* Complete the dom0 memmap.  */
 static int
 complete_dom0_memmap(struct domain *d,
@@ -672,9 +729,152 @@ complete_dom0_memmap(struct domain *d,
                                                PAGE_SIZE, flags);
                }
        }
+       setup_dom0_memmap_info(d, tables, &num_mds);
        return num_mds;
 }
        
+static int
+complete_domu_memmap(struct domain *d,
+                     struct fw_tables *tables,
+                     unsigned long maxmem,
+                     int num_mds,
+                    unsigned long memmap_info_pfn,
+                    unsigned long memmap_size)
+{
+       efi_memory_desc_t *md;
+       int i = num_mds; /* for MAKE_MD */
+       int create_memmap = 0;
+       xen_ia64_memmap_info_t* memmap_info;
+       unsigned long paddr_start;
+       unsigned long paddr_end;
+       void *p;
+       void *memmap_start;
+       void *memmap_end;
+
+       if (memmap_info_pfn == 0 || memmap_size == 0) {
+               /* old domain builder which doesn't setup
+                * memory map. create it for compatibility */
+               memmap_info_pfn = (maxmem >> PAGE_SHIFT) - 1;
+               /* 4 = memmap info page, start info page, xenstore page and
+                  console page */
+               memmap_size = 4 << PAGE_SHIFT;
+               create_memmap = 1;
+       }
+       paddr_start = memmap_info_pfn << PAGE_SHIFT;
+       paddr_end = paddr_start + memmap_size;
+       memmap_info = domain_mpa_to_imva(d, paddr_start);
+       if (memmap_info->efi_memmap_size == 0) {
+               create_memmap = 1;
+       } else if (memmap_info->efi_memdesc_size != sizeof(md[0]) ||
+                  memmap_info->efi_memdesc_version !=
+                  EFI_MEMORY_DESCRIPTOR_VERSION) {
+               printk(XENLOG_WARNING
+                      "%s: Warning: unknown memory map "
+                      "memmap size %"PRIu64" "
+                      "memdesc size %"PRIu64" "
+                      "version %"PRIu32"\n",
+                      __func__,
+                      memmap_info->efi_memmap_size,
+                      memmap_info->efi_memdesc_size,
+                      memmap_info->efi_memdesc_version);
+               create_memmap = 1;
+       } else if (max(memmap_size, memmap_info->efi_memmap_size) >
+                  PAGE_SIZE - sizeof(*memmap_info)) {
+               /*
+                * curently memmap spanning more than single page isn't
+                * supported.
+                */
+               printk(XENLOG_WARNING
+                      "%s: Warning: too large memmap_size %"PRIu64"\n",
+                      __func__, memmap_size);
+               return -ENOSYS;
+       }
+       
+       if (create_memmap) {
+               /* old domain builder which doesn't setup
+                * memory map. create it for compatibility */
+               memmap_info->efi_memdesc_size = sizeof(md[0]);
+               memmap_info->efi_memdesc_version =
+                       EFI_MEMORY_DESCRIPTOR_VERSION;
+               memmap_info->efi_memmap_size = 1 * sizeof(md[0]);
+               md = (efi_memory_desc_t*)&memmap_info->memdesc;
+               md[num_mds].type = EFI_CONVENTIONAL_MEMORY;
+               md[num_mds].pad = 0;
+               md[num_mds].phys_addr = 0;
+               md[num_mds].virt_addr = 0;
+               md[num_mds].num_pages = maxmem >> EFI_PAGE_SHIFT;
+               md[num_mds].attribute = EFI_MEMORY_WB;
+       }
+       /*
+        * XXX kludge.
+        * when XEN_DOMCTL_arch_setup is called, shared_info can't
+        * be accessed by libxc so that memmap_info_pfn isn't initialized.
+        * But dom_fw_set_convmem_end() requires it, so here we initialize it.
+        */
+       d->shared_info->arch.memmap_info_num_pages = 1;
+       d->shared_info->arch.memmap_info_pfn = memmap_info_pfn;
+
+       memmap_start = &memmap_info->memdesc;
+       memmap_end = memmap_start + memmap_info->efi_memmap_size;
+       /* XXX Currently the table must be in a single page. */
+       if ((unsigned long)memmap_end > (unsigned long)memmap_info + PAGE_SIZE)
+               return -EINVAL;
+
+       /* sort it bofore use
+        * XXX: this is created by user space domain builder so that
+        * we should check its integrity */
+       sort(&memmap_info->memdesc,
+            memmap_info->efi_memmap_size / memmap_info->efi_memdesc_size,
+            memmap_info->efi_memdesc_size,
+            efi_mdt_cmp, NULL);
+
+       for (p = memmap_start; p < memmap_end; p += 
memmap_info->efi_memdesc_size) {
+               unsigned long start;
+               unsigned long end;
+               md = p;
+               start = md->phys_addr;
+               end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
+
+               if (start < FW_END_PADDR)
+                       start = FW_END_PADDR;
+               if (end <= start)
+                       continue;
+
+               /* exclude [paddr_start, paddr_end) */
+               if (paddr_end <= start || end <= paddr_start) {
+                       MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB,
+                               start, end);
+               } else if (paddr_start <= start && paddr_end < end) {
+                       MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB,
+                               paddr_end, end);
+               } else if (start < paddr_start && end <= paddr_end) {
+                       MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB,
+                               start, paddr_start);
+               } else {
+                       MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB,
+                               start, paddr_start);
+                       MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB,
+                               paddr_end, end);
+               }
+               d->arch.convmem_end = end;
+       }
+
+       /* memmap info page. */
+       MAKE_MD(EFI_RUNTIME_SERVICES_DATA, EFI_MEMORY_WB,
+               paddr_start, paddr_end);
+       if (d->arch.convmem_end < paddr_end)
+               d->arch.convmem_end = paddr_end;
+
+       /* Create an entry for IO ports.  */
+       MAKE_MD(EFI_MEMORY_MAPPED_IO_PORT_SPACE, EFI_MEMORY_UC,
+               IO_PORTS_PADDR, IO_PORTS_PADDR + IO_PORTS_SIZE);
+
+       num_mds = i;
+       sort(tables->efi_memmap, num_mds, sizeof(efi_memory_desc_t),
+            efi_mdt_cmp, NULL);
+       return num_mds;
+}
+
 static void
 dom_fw_init(struct domain *d,
             struct ia64_boot_param *bp,
@@ -842,18 +1042,17 @@ dom_fw_init(struct domain *d,
        if (d != dom0 || running_on_sim) {
                /* DomU (or hp-ski).
                   Create a continuous memory area.  */
-               /* Memory.  */
-               MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB,
-                       FW_END_PADDR, maxmem);
-               d->arch.convmem_end = maxmem;
-               
-               /* Create an entry for IO ports.  */
-               MAKE_MD(EFI_MEMORY_MAPPED_IO_PORT_SPACE, EFI_MEMORY_UC,
-                       IO_PORTS_PADDR, IO_PORTS_PADDR + IO_PORTS_SIZE);
-
-               num_mds = i;
-       }
-       else {
+               /* kludge: bp->efi_memmap is used to pass memmap_info
+                * page's pfn and number of pages to reserve. 
+                * Currently the following pages must be reserved.
+                * memmap info page, start info page, xenstore page
+                * and console page.
+                * see ia64_setup_memmap() @ xc_dom_boot.c
+                */
+               num_mds = complete_domu_memmap(d, tables, maxmem, i,
+                                              bp->efi_memmap,
+                                              bp->efi_memmap_size);
+       } else {
                /* Dom0.
                   We must preserve ACPI data from real machine,
                   as well as IO areas.  */
diff -r caafa45d24b3 -r c2768258711d xen/include/public/arch-ia64.h
--- a/xen/include/public/arch-ia64.h    Mon May 21 10:09:33 2007 -0600
+++ b/xen/include/public/arch-ia64.h    Mon May 21 10:10:31 2007 -0600
@@ -339,7 +339,12 @@ struct arch_shared_info {
     /* Interrupt vector for event channel.  */
     int evtchn_vector;
 
-    uint64_t pad[32];
+    /* PFN of memmap_info page */
+    unsigned int memmap_info_num_pages;/* currently only = 1 case is
+                                          supported. */
+    unsigned long memmap_info_pfn;
+
+    uint64_t pad[31];
 };
 typedef struct arch_shared_info arch_shared_info_t;
 

_______________________________________________
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®.