WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] [IA64] Allow dynamic allocation of dom0 f

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [IA64] Allow dynamic allocation of dom0 fw_tables
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Sat, 16 Jun 2007 05:44:06 -0700
Delivery-date: Sat, 16 Jun 2007 05:42:36 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Alex Williamson <alex.williamson@xxxxxx>
# Date 1180987028 21600
# Node ID c0cdcebc0377f817155587cd83da79b234f769a5
# Parent  b46c2ff6dfb0de75e17fee01f0adc4d35d5e8322
[IA64] Allow dynamic allocation of dom0 fw_tables

This address Xensource bugzilla #980

Signed-off-by: Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
---
 tools/libxc/ia64/xc_dom_ia64_util.c  |   29 ++++-
 tools/libxc/ia64/xc_dom_ia64_util.h  |    2 
 xen/arch/ia64/xen/dom_fw_common.c    |   44 ++++----
 xen/arch/ia64/xen/dom_fw_dom0.c      |  183 ++++++++++++++++++++---------------
 xen/arch/ia64/xen/dom_fw_domu.c      |   75 ++++++++------
 xen/arch/ia64/xen/dom_fw_utils.c     |  160 ++++++++++++++++++++++++------
 xen/include/asm-ia64/dom_fw.h        |    5 
 xen/include/asm-ia64/dom_fw_common.h |   14 ++
 xen/include/asm-ia64/dom_fw_dom0.h   |    6 -
 xen/include/asm-ia64/dom_fw_domu.h   |    2 
 xen/include/asm-ia64/dom_fw_utils.h  |    4 
 11 files changed, 351 insertions(+), 173 deletions(-)

diff -r b46c2ff6dfb0 -r c0cdcebc0377 tools/libxc/ia64/xc_dom_ia64_util.c
--- a/tools/libxc/ia64/xc_dom_ia64_util.c       Thu May 31 14:47:08 2007 -0600
+++ b/tools/libxc/ia64/xc_dom_ia64_util.c       Mon Jun 04 13:57:08 2007 -0600
@@ -18,6 +18,7 @@
  *
  */
 
+#include <assert.h>
 #include "xg_private.h"
 #include "xc_dom.h"
 #include "asm/dom_fw.h"
@@ -114,12 +115,12 @@ xen_ia64_dom_fw_setup(struct xc_dom_imag
 {
     int rc = 0;
     void *imva_hypercall_base = NULL;
-    void *imva_tables_base = NULL;
+    struct fw_tables *fw_tables = NULL;
     struct fake_acpi_tables *imva = NULL;
     struct xen_ia64_boot_param *bp = NULL;
 
     BUILD_BUG_ON(sizeof(struct fw_tables) >
-                 (FW_TABLES_END_PADDR - FW_TABLES_BASE_PADDR));
+                 (FW_TABLES_END_PADDR_MIN - FW_TABLES_BASE_PADDR));
 
     /* Create page for hypercalls.  */
     imva_hypercall_base = xen_ia64_dom_fw_map(d, FW_HYPERCALL_BASE_PADDR);
@@ -129,11 +130,17 @@ xen_ia64_dom_fw_setup(struct xc_dom_imag
     }
 
     /* Create page for FW tables.  */
-    imva_tables_base = xen_ia64_dom_fw_map(d, FW_TABLES_BASE_PADDR);
-    if (imva_tables_base == NULL) {
+    fw_tables = (struct fw_tables*)xen_ia64_dom_fw_map(d, 
FW_TABLES_BASE_PADDR);
+    if (fw_tables == NULL) {
         rc = -errno;
         goto out;
     }
+    memset(fw_tables, 0, FW_TABLES_END_PADDR_MIN - FW_TABLES_BASE_PADDR);
+    BUILD_BUG_ON(FW_END_PADDR_MIN != FW_TABLES_END_PADDR_MIN);
+    fw_tables->fw_tables_size = FW_TABLES_END_PADDR_MIN - FW_TABLES_BASE_PADDR;
+    fw_tables->fw_end_paddr = FW_END_PADDR_MIN;
+    fw_tables->fw_tables_end_paddr = FW_TABLES_END_PADDR_MIN;
+    fw_tables->num_mds = 0;
         
     /* Create page for acpi tables.  */
     imva = (struct fake_acpi_tables *)
@@ -150,14 +157,22 @@ xen_ia64_dom_fw_setup(struct xc_dom_imag
         rc = -errno;
         goto out;
     }
-    rc = dom_fw_init(d, brkimm, bp, imva_tables_base,
+    rc = dom_fw_init(d, brkimm, bp, fw_tables,
                      (unsigned long)imva_hypercall_base, maxmem);
+    BUG_ON(fw_tables->fw_tables_size < sizeof(*fw_tables) +
+           sizeof(fw_tables->efi_memmap[0]) * fw_tables->num_mds);
 
+    /* clear domain builder internal use member */
+    fw_tables->fw_tables_size = 0;
+    fw_tables->fw_end_paddr = 0;
+    fw_tables->fw_tables_end_paddr = 0;
+    fw_tables->num_mds = 0;
+    
  out:
     if (imva_hypercall_base != NULL)
         xen_ia64_dom_fw_unmap(d, imva_hypercall_base);
-    if (imva_tables_base != NULL)
-        xen_ia64_dom_fw_unmap(d, imva_tables_base);
+    if (fw_tables != NULL)
+        xen_ia64_dom_fw_unmap(d, fw_tables);
     if (imva != NULL)
         xen_ia64_dom_fw_unmap(d, imva);
     if (bp != NULL)
diff -r b46c2ff6dfb0 -r c0cdcebc0377 tools/libxc/ia64/xc_dom_ia64_util.h
--- a/tools/libxc/ia64/xc_dom_ia64_util.h       Thu May 31 14:47:08 2007 -0600
+++ b/tools/libxc/ia64/xc_dom_ia64_util.h       Mon Jun 04 13:57:08 2007 -0600
@@ -14,6 +14,6 @@ xen_ia64_dom_fw_setup(struct xc_dom_imag
 xen_ia64_dom_fw_setup(struct xc_dom_image *d, uint64_t brkimm,
                       unsigned long bp_mpa, unsigned long maxmem);
 #define efi_systable_init_dom0(tables) assert(0)
-#define complete_dom0_memmap(d, tables, maxmem, num_mds) ({assert(0);0;})
+#define complete_dom0_memmap(d, tables) ({assert(0);0;})
 
 #endif /* XC_IA64_DOM_IA64_UTIL_H */
diff -r b46c2ff6dfb0 -r c0cdcebc0377 xen/arch/ia64/xen/dom_fw_common.c
--- a/xen/arch/ia64/xen/dom_fw_common.c Thu May 31 14:47:08 2007 -0600
+++ b/xen/arch/ia64/xen/dom_fw_common.c Mon Jun 04 13:57:08 2007 -0600
@@ -35,22 +35,17 @@
 #include <asm/dom_fw_domu.h>
 
 void
-xen_ia64_efi_make_md(struct fw_tables *tables, int *index,
+xen_ia64_efi_make_md(efi_memory_desc_t *md,
                     uint32_t type, uint64_t attr, 
                     uint64_t start, uint64_t end)
 {
-       efi_memory_desc_t *md = &tables->efi_memmap[*index];
        md->type = type;
        md->pad = 0;
        md->phys_addr = start;
        md->virt_addr = 0;
        md->num_pages = (end - start) >> EFI_PAGE_SHIFT;
        md->attribute = attr;
-
-       (*index)++;
-}
-#define MAKE_MD(typ, attr, start, end) \
-       xen_ia64_efi_make_md((tables), &(i), (typ), (attr), (start), (end))
+}
 
 #define EFI_HYPERCALL_PATCH(tgt, call)                                 \
        do {                                                            \
@@ -422,7 +417,7 @@ dom_fw_init(domain_t *d,
        int num_mds, i;
        int fpswa_supported = 0;
 
-       memset(tables, 0, sizeof(struct fw_tables));
+       /* Caller must zero-clear fw_tables */
 
        /* EFI systab.  */
        tables->efi_systab.hdr.signature = EFI_SYSTEM_TABLE_SIGNATURE;
@@ -514,17 +509,25 @@ dom_fw_init(domain_t *d,
                        (void *)FW_HYPERCALL_FPSWA_ENTRY_PADDR;
        }
 
-       i = 0; /* Used by MAKE_MD */
-
+       tables->num_mds = 0;
        /* hypercall patches live here, masquerade as reserved PAL memory */
-       MAKE_MD(EFI_PAL_CODE,EFI_MEMORY_WB|EFI_MEMORY_RUNTIME,
-               FW_HYPERCALL_BASE_PADDR, FW_HYPERCALL_END_PADDR);
+       xen_ia64_efi_make_md(&tables->efi_memmap[tables->num_mds],
+                            EFI_PAL_CODE, EFI_MEMORY_WB | EFI_MEMORY_RUNTIME,
+                            FW_HYPERCALL_BASE_PADDR, FW_HYPERCALL_END_PADDR);
+       tables->num_mds++;
 
        /* Create dom0/domu md entry for fw and cpi tables area.  */
-       MAKE_MD(EFI_ACPI_MEMORY_NVS, EFI_MEMORY_WB | EFI_MEMORY_RUNTIME,
-               FW_ACPI_BASE_PADDR, FW_ACPI_END_PADDR);
-       MAKE_MD(EFI_RUNTIME_SERVICES_DATA, EFI_MEMORY_WB | EFI_MEMORY_RUNTIME,
-               FW_TABLES_BASE_PADDR, FW_TABLES_END_PADDR);
+       xen_ia64_efi_make_md(&tables->efi_memmap[tables->num_mds],
+                            EFI_ACPI_MEMORY_NVS,
+                            EFI_MEMORY_WB | EFI_MEMORY_RUNTIME,
+                            FW_ACPI_BASE_PADDR, FW_ACPI_END_PADDR);
+       tables->num_mds++;
+       xen_ia64_efi_make_md(&tables->efi_memmap[tables->num_mds],
+                            EFI_RUNTIME_SERVICES_DATA,
+                            EFI_MEMORY_WB | EFI_MEMORY_RUNTIME,
+                            FW_TABLES_BASE_PADDR,
+                            tables->fw_tables_end_paddr);
+       tables->num_mds++;
 
        if (!xen_ia64_is_dom0(d) || xen_ia64_is_running_on_sim(d)) {
                /* DomU (or hp-ski).
@@ -536,26 +539,27 @@ dom_fw_init(domain_t *d,
                 * and console page.
                 * see ia64_setup_memmap() @ xc_dom_boot.c
                 */
-               num_mds = complete_domu_memmap(d, tables, maxmem, i,
+               num_mds = complete_domu_memmap(d, tables, maxmem,
                                               XEN_IA64_MEMMAP_INFO_PFN(bp),
                                               
XEN_IA64_MEMMAP_INFO_NUM_PAGES(bp));
        } else {
                /* Dom0.
                   We must preserve ACPI data from real machine,
                   as well as IO areas.  */
-               num_mds = complete_dom0_memmap(d, tables, maxmem, i);
+               num_mds = complete_dom0_memmap(d, tables);
        }
        if (num_mds < 0)
                return num_mds;
+       BUG_ON(num_mds != tables->num_mds);
 
        /* Display memmap.  */
-       for (i = 0 ; i < num_mds; i++)
+       for (i = 0 ; i < tables->num_mds; i++)
                print_md(&tables->efi_memmap[i]);
 
        /* Fill boot_param  */
        bp->efi_systab = FW_FIELD_MPA(efi_systab);
        bp->efi_memmap = FW_FIELD_MPA(efi_memmap);
-       bp->efi_memmap_size = num_mds * sizeof(efi_memory_desc_t);
+       bp->efi_memmap_size = tables->num_mds * sizeof(efi_memory_desc_t);
        bp->efi_memdesc_size = sizeof(efi_memory_desc_t);
        bp->efi_memdesc_version = EFI_MEMDESC_VERSION;
        bp->command_line = 0;
diff -r b46c2ff6dfb0 -r c0cdcebc0377 xen/arch/ia64/xen/dom_fw_dom0.c
--- a/xen/arch/ia64/xen/dom_fw_dom0.c   Thu May 31 14:47:08 2007 -0600
+++ b/xen/arch/ia64/xen/dom_fw_dom0.c   Mon Jun 04 13:57:08 2007 -0600
@@ -32,6 +32,7 @@
 #include <asm/dom_fw.h>
 #include <asm/dom_fw_common.h>
 #include <asm/dom_fw_dom0.h>
+#include <asm/dom_fw_utils.h>
 
 #include <linux/sort.h>
 
@@ -158,21 +159,26 @@ void __init efi_systable_init_dom0(struc
 }
 
 static void __init
-setup_dom0_memmap_info(struct domain *d, struct fw_tables *tables, int 
*num_mds)
+setup_dom0_memmap_info(struct domain *d, struct fw_tables *tables)
 {
        int i;
+       size_t size;
+       unsigned int num_pages;
        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--) {
+       size = sizeof(*memmap_info) +
+               (tables->num_mds + 1) * sizeof(tables->efi_memmap[0]);
+       num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+       for (i = tables->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))) {
+                   ((num_pages + 1) << (PAGE_SHIFT - EFI_PAGE_SHIFT))) {
                        last_mem_md = md;
                        break;
                }
@@ -186,45 +192,71 @@ setup_dom0_memmap_info(struct domain *d,
        }
        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)++;
+       paddr_start = (paddr_end - (num_pages << PAGE_SHIFT)) & PAGE_MASK;
+       last_mem_md->num_pages -= (paddr_end - paddr_start) >> EFI_PAGE_SHIFT;
+
+       md = &tables->efi_memmap[tables->num_mds];
+       tables->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->num_pages = num_pages << (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);
-
+       BUG_ON(tables->fw_tables_size <
+              sizeof(*tables) +
+              sizeof(tables->efi_memmap[0]) * tables->num_mds);
+       /* with this sort, md doesn't point memmap table */
+       sort(tables->efi_memmap, tables->num_mds,
+            sizeof(efi_memory_desc_t), efi_mdt_cmp, NULL);
+
+       memmap_info = domain_mpa_to_imva(d, paddr_start);
        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);
+       memmap_info->efi_memmap_size = tables->num_mds * sizeof(md[0]);
+       dom_fw_copy_to(d,
+                      paddr_start + offsetof(xen_ia64_memmap_info_t, memdesc),
+                      &tables->efi_memmap[0], memmap_info->efi_memmap_size);
+       d->shared_info->arch.memmap_info_num_pages = num_pages;
+       d->shared_info->arch.memmap_info_pfn = paddr_start >> PAGE_SHIFT;
+}
+
+/* setup_guest() @ libxc/xc_linux_build() arranges memory for domU.
+ * however no one arranges memory for dom0,
+ * instead we allocate pages manually.
+ */
+static void
+assign_new_domain0_range(struct domain *d, const efi_memory_desc_t * md)
+{
+       if (md->type == EFI_PAL_CODE ||
+           md->type == EFI_RUNTIME_SERVICES_DATA ||
+           md->type == EFI_CONVENTIONAL_MEMORY) {
+               unsigned long start = md->phys_addr & PAGE_MASK;
+               unsigned long end =
+                       md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
+               unsigned long addr;
+
+               if (end == start) {
+                       /* md->num_pages = 0 is allowed. */
+                       return;
+               }
+
+               for (addr = start; addr < end; addr += PAGE_SIZE)
+                       assign_new_domain0_page(d, addr);
+       }
 }
 
 /* Complete the dom0 memmap.  */
 int __init
-complete_dom0_memmap(struct domain *d,
-                    struct fw_tables *tables,
-                    unsigned long maxmem, int num_mds)
-{
-       efi_memory_desc_t *md;
+complete_dom0_memmap(struct domain *d, struct fw_tables *tables)
+{
        u64 addr;
        void *efi_map_start, *efi_map_end, *p;
        u64 efi_desc_size;
        int i;
-       unsigned long dom_mem = maxmem - (d->tot_pages << PAGE_SHIFT);
+
+       for (i = 0; i < tables->num_mds; i++)
+               assign_new_domain0_range(d, &tables->efi_memmap[i]);
 
        /* Walk through all MDT entries.
           Copy all interesting entries.  */
@@ -234,7 +266,7 @@ complete_dom0_memmap(struct domain *d,
 
        for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
                const efi_memory_desc_t *md = p;
-               efi_memory_desc_t *dom_md = &tables->efi_memmap[num_mds];
+               efi_memory_desc_t *dom_md = 
&tables->efi_memmap[tables->num_mds];
                u64 start = md->phys_addr;
                u64 size = md->num_pages << EFI_PAGE_SHIFT;
                u64 end = start + size;
@@ -267,7 +299,7 @@ complete_dom0_memmap(struct domain *d,
                        /* Copy descriptor.  */
                        *dom_md = *md;
                        dom_md->virt_addr = 0;
-                       num_mds++;
+                       tables->num_mds++;
                        break;
 
                case EFI_MEMORY_MAPPED_IO_PORT_SPACE:
@@ -288,31 +320,55 @@ complete_dom0_memmap(struct domain *d,
                        *dom_md = *md;
                        dom_md->phys_addr = mpaddr;
                        dom_md->virt_addr = 0;
-                       num_mds++;
+                       tables->num_mds++;
                        break;
 
                case EFI_CONVENTIONAL_MEMORY:
                case EFI_LOADER_CODE:
                case EFI_LOADER_DATA:
                case EFI_BOOT_SERVICES_CODE:
-               case EFI_BOOT_SERVICES_DATA:
+               case EFI_BOOT_SERVICES_DATA: {
+                       u64 dom_md_start;
+                       u64 dom_md_end;
+                       unsigned long left_mem =
+                               (unsigned long)(d->max_pages - d->tot_pages) <<
+                               PAGE_SHIFT;
+
                        if (!(md->attribute & EFI_MEMORY_WB))
                                break;
 
-                       start = max(FW_END_PADDR, start);
-                       end = min(start + dom_mem, end);
-                       if (end <= start)
-                               break;
-
-                       dom_md->type = EFI_CONVENTIONAL_MEMORY;
-                       dom_md->phys_addr = start;
-                       dom_md->virt_addr = 0;
-                       dom_md->num_pages = (end - start) >> EFI_PAGE_SHIFT;
-                       dom_md->attribute = EFI_MEMORY_WB;
-                       num_mds++;
-
-                       dom_mem -= dom_md->num_pages << EFI_PAGE_SHIFT;
-                       break;
+                       dom_md_start = max(tables->fw_end_paddr, start);
+                       dom_md_end = dom_md_start;
+                       do {
+                               dom_md_end = min(dom_md_end + left_mem, end);
+                               if (dom_md_end < dom_md_start + PAGE_SIZE)
+                                       break;
+
+                               dom_md->type = EFI_CONVENTIONAL_MEMORY;
+                               dom_md->phys_addr = dom_md_start;
+                               dom_md->virt_addr = 0;
+                               dom_md->num_pages =
+                                       (dom_md_end - dom_md_start) >>
+                                       EFI_PAGE_SHIFT;
+                               dom_md->attribute = EFI_MEMORY_WB;
+
+                               assign_new_domain0_range(d, dom_md);
+                               /*
+                                * recalculate left_mem.
+                                * we might already allocated memory in
+                                * this region because of kernel loader.
+                                * So we might consumed less than
+                                * (dom_md_end - dom_md_start) above.
+                                */
+                               left_mem = (unsigned long)
+                                       (d->max_pages - d->tot_pages) <<
+                                       PAGE_SHIFT;
+                       } while (left_mem > 0 && dom_md_end < end);
+
+                       if (!(dom_md_end < dom_md_start + PAGE_SIZE))
+                               tables->num_mds++;
+                       break;
+               }
 
                case EFI_UNUSABLE_MEMORY:
                case EFI_PAL_CODE:
@@ -326,7 +382,7 @@ complete_dom0_memmap(struct domain *d,
                        dom_md->virt_addr = 0;
                        dom_md->num_pages = (end - start) >> EFI_PAGE_SHIFT;
                        dom_md->attribute = EFI_MEMORY_WB;
-                       num_mds++;
+                       tables->num_mds++;
                        break;
 
                default:
@@ -335,34 +391,13 @@ complete_dom0_memmap(struct domain *d,
                               "unhandled MDT entry type %u\n", md->type);
                }
        }
-       BUG_ON(num_mds > NUM_MEM_DESCS);
-
-       sort(tables->efi_memmap, num_mds, sizeof(efi_memory_desc_t),
+       BUG_ON(tables->fw_tables_size <
+              sizeof(*tables) +
+              sizeof(tables->efi_memmap[0]) * tables->num_mds);
+
+       sort(tables->efi_memmap, tables->num_mds, sizeof(efi_memory_desc_t),
             efi_mdt_cmp, NULL);
 
-       /* setup_guest() @ libxc/xc_linux_build() arranges memory for domU.
-        * however no one arranges memory for dom0,
-        * instead we allocate pages manually.
-        */
-       for (i = 0; i < num_mds; i++) {
-               md = &tables->efi_memmap[i];
-
-               if (md->type == EFI_LOADER_DATA ||
-                   md->type == EFI_PAL_CODE ||
-                   md->type == EFI_CONVENTIONAL_MEMORY) {
-                       unsigned long start = md->phys_addr & PAGE_MASK;
-                       unsigned long end = md->phys_addr +
-                           (md->num_pages << EFI_PAGE_SHIFT);
-
-                       if (end == start) {
-                               /* md->num_pages = 0 is allowed. */
-                               continue;
-                       }
-
-                       for (addr = start; addr < end; addr += PAGE_SIZE)
-                               assign_new_domain0_page(d, addr);
-               }
-       }
        // Map low-memory holes & unmapped MMIO for legacy drivers
        for (addr = 0; addr < ONE_MB; addr += PAGE_SIZE) {
                if (domain_page_mapped(d, addr))
@@ -375,8 +410,8 @@ complete_dom0_memmap(struct domain *d,
                                                flags);
                }
        }
-       setup_dom0_memmap_info(d, tables, &num_mds);
-       return num_mds;
+       setup_dom0_memmap_info(d, tables);
+       return tables->num_mds;
 }
 
 /*
diff -r b46c2ff6dfb0 -r c0cdcebc0377 xen/arch/ia64/xen/dom_fw_domu.c
--- a/xen/arch/ia64/xen/dom_fw_domu.c   Thu May 31 14:47:08 2007 -0600
+++ b/xen/arch/ia64/xen/dom_fw_domu.c   Mon Jun 04 13:57:08 2007 -0600
@@ -61,19 +61,14 @@ void efi_systable_init_domu(struct fw_ta
        BUG_ON(i > NUM_EFI_SYS_TABLES);
 }
 
-#define MAKE_MD(typ, attr, start, end) \
-       xen_ia64_efi_make_md((tables), &(i), (typ), (attr), (start), (end))
-
 int
 complete_domu_memmap(domain_t * d,
                     struct fw_tables *tables,
                     unsigned long maxmem,
-                    int num_mds,
                     unsigned long memmap_info_pfn,
                     unsigned long memmap_info_num_pages)
 {
        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 memmap_info_size;
@@ -142,12 +137,12 @@ complete_domu_memmap(domain_t * d,
                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;
+               md->type = EFI_CONVENTIONAL_MEMORY;
+               md->pad = 0;
+               md->phys_addr = 0;
+               md->virt_addr = 0;
+               md->num_pages = maxmem >> EFI_PAGE_SHIFT;
+               md->attribute = EFI_MEMORY_WB;
        }
 
        memmap_start = &memmap_info->memdesc;
@@ -175,43 +170,61 @@ complete_domu_memmap(domain_t * d,
                start = md->phys_addr;
                end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
 
-               if (start < FW_END_PADDR)
-                       start = FW_END_PADDR;
+               if (start < tables->fw_end_paddr)
+                       start = tables->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);
+                       xen_ia64_efi_make_md(&tables->
+                                            efi_memmap[tables->num_mds],
+                                            EFI_CONVENTIONAL_MEMORY,
+                                            EFI_MEMORY_WB, start, end);
+                       tables->num_mds++;
                } else if (paddr_start <= start && paddr_end < end) {
-                       MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB,
-                               paddr_end, end);
+                       xen_ia64_efi_make_md(&tables->
+                                            efi_memmap[tables->num_mds],
+                                            EFI_CONVENTIONAL_MEMORY,
+                                            EFI_MEMORY_WB, paddr_end, end);
+                       tables->num_mds++;
                } else if (start < paddr_start && end <= paddr_end) {
-                       MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB, start,
-                               paddr_start);
+                       xen_ia64_efi_make_md(&tables->
+                                            efi_memmap[tables->num_mds],
+                                            EFI_CONVENTIONAL_MEMORY,
+                                            EFI_MEMORY_WB, start, paddr_start);
+                       tables->num_mds++;
                } else {
-                       MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB, start,
-                               paddr_start);
-                       MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB,
-                               paddr_end, end);
+                       xen_ia64_efi_make_md(&tables->
+                                            efi_memmap[tables->num_mds],
+                                            EFI_CONVENTIONAL_MEMORY,
+                                            EFI_MEMORY_WB, start, paddr_start);
+                       tables->num_mds++;
+                       xen_ia64_efi_make_md(&tables->
+                                            efi_memmap[tables->num_mds],
+                                            EFI_CONVENTIONAL_MEMORY,
+                                            EFI_MEMORY_WB, paddr_end, end);
+                       tables->num_mds++;
                }
        }
 
        /* memmap info page. */
-       MAKE_MD(EFI_RUNTIME_SERVICES_DATA, EFI_MEMORY_WB, paddr_start,
-               paddr_end);
+       xen_ia64_efi_make_md(&tables->efi_memmap[tables->num_mds],
+                            EFI_RUNTIME_SERVICES_DATA, EFI_MEMORY_WB,
+                            paddr_start, paddr_end);
+       tables->num_mds++;
 
        /* 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),
+       xen_ia64_efi_make_md(&tables->efi_memmap[tables->num_mds],
+                            EFI_MEMORY_MAPPED_IO_PORT_SPACE, EFI_MEMORY_UC,
+                            IO_PORTS_PADDR, IO_PORTS_PADDR + IO_PORTS_SIZE);
+       tables->num_mds++;
+
+       sort(tables->efi_memmap, tables->num_mds, sizeof(efi_memory_desc_t),
             efi_mdt_cmp, NULL);
 
        xen_ia64_dom_fw_unmap(d, memmap_info);
-       return num_mds;
+       return tables->num_mds;
 }
 
 /*
diff -r b46c2ff6dfb0 -r c0cdcebc0377 xen/arch/ia64/xen/dom_fw_utils.c
--- a/xen/arch/ia64/xen/dom_fw_utils.c  Thu May 31 14:47:08 2007 -0600
+++ b/xen/arch/ia64/xen/dom_fw_utils.c  Mon Jun 04 13:57:08 2007 -0600
@@ -27,6 +27,7 @@
 #include <asm/fpswa.h>
 #include <asm/dom_fw.h>
 #include <asm/dom_fw_common.h>
+#include <asm/dom_fw_utils.h>
 
 #include <linux/sort.h>
 
@@ -70,6 +71,8 @@ static void dom_fw_domain_init(struct do
 
 static int dom_fw_set_convmem_end(struct domain *d)
 {
+       unsigned long gpaddr;
+       size_t size;
        xen_ia64_memmap_info_t *memmap_info;
        efi_memory_desc_t *md;
        void *p;
@@ -79,26 +82,23 @@ static int dom_fw_set_convmem_end(struct
        if (d->shared_info->arch.memmap_info_pfn == 0)
                return -EINVAL;
 
-       memmap_info =
-           domain_mpa_to_imva(d,
-                              d->shared_info->arch.
-                              memmap_info_pfn << PAGE_SHIFT);
-       if (memmap_info->efi_memmap_size == 0
-           || memmap_info->efi_memdesc_size != sizeof(*md)
-           || memmap_info->efi_memdesc_version !=
-           EFI_MEMORY_DESCRIPTOR_VERSION)
+       gpaddr = d->shared_info->arch.memmap_info_pfn << PAGE_SHIFT;
+       size = d->shared_info->arch.memmap_info_num_pages << PAGE_SHIFT;
+       memmap_info = _xmalloc(size, __alignof__(*memmap_info));
+       if (memmap_info == NULL)
+               return -ENOMEM;
+       dom_fw_copy_from(memmap_info, d, gpaddr, size);
+       if (memmap_info->efi_memmap_size == 0 ||
+           memmap_info->efi_memdesc_size != sizeof(*md) ||
+           memmap_info->efi_memdesc_version != EFI_MEMORY_DESCRIPTOR_VERSION ||
+           sizeof(*memmap_info) + memmap_info->efi_memmap_size > size ||
+           memmap_info->efi_memmap_size / memmap_info->efi_memdesc_size == 0) {
+               xfree(memmap_info);
                return -EINVAL;
-
-       /* only 1page case is supported */
-       if (d->shared_info->arch.memmap_info_num_pages != 1)
-               return -ENOSYS;
+       }
 
        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
@@ -122,6 +122,9 @@ static int dom_fw_set_convmem_end(struct
                    md->num_pages > 0 && d->arch.convmem_end < end)
                        d->arch.convmem_end = end;
        }
+
+       dom_fw_copy_to(d, gpaddr, memmap_info, size);
+       xfree(memmap_info);
        return 0;
 }
 
@@ -135,22 +138,62 @@ assign_new_domain_page_if_dom0(struct do
                assign_new_domain0_page(d, mpaddr);
 }
 
-static void
-dom_fw_setup_for_domain_restore(domain_t *d, unsigned long maxmem)
+static void dom_fw_setup_for_domain_restore(domain_t * d, unsigned long maxmem)
 {
        assign_new_domain_page(d, FW_HYPERCALL_BASE_PADDR);
        dom_fw_domain_init(d, domain_mpa_to_imva(d, FW_TABLES_BASE_PADDR));
        d->arch.convmem_end = maxmem;
 }
 
+/* copy memory range to domain pseudo physical address space */
+void
+dom_fw_copy_to(struct domain *d, unsigned long dest_gpaddr,
+              void *src, size_t size)
+{
+       while (size > 0) {
+               unsigned long page_offset = dest_gpaddr & ~PAGE_MASK;
+               size_t copy_size = size;
+               void *dest;
+
+               if (page_offset + copy_size > PAGE_SIZE)
+                       copy_size = PAGE_SIZE - page_offset;
+               dest = domain_mpa_to_imva(d, dest_gpaddr);
+               memcpy(dest, src, copy_size);
+
+               src += copy_size;
+               dest_gpaddr += copy_size;
+               size -= copy_size;
+       }
+}
+
+/* copy memory range from domain pseudo physical address space */
+void
+dom_fw_copy_from(void *dest, struct domain *d, unsigned long src_gpaddr,
+                size_t size)
+{
+       while (size > 0) {
+               unsigned long page_offset = src_gpaddr & ~PAGE_MASK;
+               size_t copy_size = size;
+               void *src;
+
+               if (page_offset + copy_size > PAGE_SIZE)
+                       copy_size = PAGE_SIZE - page_offset;
+               src = domain_mpa_to_imva(d, src_gpaddr);
+               memcpy(dest, src, copy_size);
+
+               dest += copy_size;
+               src_gpaddr += copy_size;
+               size -= copy_size;
+       }
+}
+
 int dom_fw_setup(domain_t * d, unsigned long bp_mpa, unsigned long maxmem)
 {
        int old_domu_builder = 0;
        struct xen_ia64_boot_param *bp;
-       struct fw_tables *imva_tables_base;
 
        BUILD_BUG_ON(sizeof(struct fw_tables) >
-                    (FW_TABLES_END_PADDR - FW_TABLES_BASE_PADDR));
+                    (FW_TABLES_END_PADDR_MIN - FW_TABLES_BASE_PADDR));
 
        if (bp_mpa == 0) {
                /* bp_mpa == 0 means this is domain restore case. */
@@ -190,10 +233,6 @@ int dom_fw_setup(domain_t * d, unsigned 
                }
        }
 
-       /* Create page for FW tables.  */
-       assign_new_domain_page_if_dom0(d, FW_TABLES_BASE_PADDR);
-       imva_tables_base = (struct fw_tables *)domain_mpa_to_imva
-           (d, FW_TABLES_BASE_PADDR);
        /* Create page for acpi tables.  */
        if (d != dom0 && old_domu_builder) {
                struct fake_acpi_tables *imva;
@@ -203,20 +242,81 @@ int dom_fw_setup(domain_t * d, unsigned 
        if (d == dom0 || old_domu_builder) {
                int ret;
                unsigned long imva_hypercall_base;
+               size_t fw_tables_size;
+               struct fw_tables *fw_tables;
+               unsigned long gpaddr;
 
                /* Create page for hypercalls.  */
                assign_new_domain_page_if_dom0(d, FW_HYPERCALL_BASE_PADDR);
                imva_hypercall_base = (unsigned long)domain_mpa_to_imva
                    (d, FW_HYPERCALL_BASE_PADDR);
 
+               /* Estimate necessary efi memmap size and allocate memory */
+               fw_tables_size = sizeof(*fw_tables) +
+                       (ia64_boot_param->efi_memmap_size /
+                        ia64_boot_param->efi_memdesc_size + NUM_MEM_DESCS) *
+                       sizeof(fw_tables->efi_memmap[0]);
+               if (fw_tables_size <
+                   FW_TABLES_END_PADDR_MIN - FW_TABLES_BASE_PADDR)
+                       fw_tables_size =
+                           FW_TABLES_END_PADDR_MIN - FW_TABLES_BASE_PADDR;
+               fw_tables_size = (fw_tables_size + ((1UL << EFI_PAGE_SHIFT) - 
1))
+                       & ~((1UL << EFI_PAGE_SHIFT) - 1);
+               fw_tables =
+                   (struct fw_tables *)_xmalloc(fw_tables_size,
+                                                __alignof__(*fw_tables));
+               if (fw_tables == NULL) {
+                       dprintk(XENLOG_INFO,
+                               "can't allocate fw_tables memory size = %ld\n",
+                               fw_tables_size);
+                       return -ENOMEM;
+               }
+               memset(fw_tables, 0, fw_tables_size);
+               BUILD_BUG_ON(FW_END_PADDR_MIN != FW_TABLES_END_PADDR_MIN);
+               fw_tables->fw_tables_size = fw_tables_size;
+               fw_tables->fw_end_paddr = FW_TABLES_BASE_PADDR + fw_tables_size;
+               fw_tables->fw_tables_end_paddr =
+                       FW_TABLES_BASE_PADDR + fw_tables_size;
+               fw_tables->num_mds = 0;
+
+               /* It is necessary to allocate pages before dom_fw_init()
+                * dom_fw_init() uses up page to d->max_pages.
+                */
+               for (gpaddr = FW_TABLES_BASE_PADDR;
+                    gpaddr < fw_tables->fw_end_paddr; gpaddr += PAGE_SIZE)
+                       assign_new_domain_page_if_dom0(d, gpaddr);
+
                ret = dom_fw_init(d, d->arch.breakimm, bp,
-                                 imva_tables_base, imva_hypercall_base,
-                                 maxmem);
-               if (ret < 0)
+                                 fw_tables, imva_hypercall_base, maxmem);
+               if (ret < 0) {
+                       xfree(fw_tables);
                        return ret;
-       }
-
-       dom_fw_domain_init(d, imva_tables_base);
+               }
+               if (sizeof(*fw_tables) +
+                   fw_tables->num_mds * sizeof(fw_tables->efi_memmap[0]) >
+                   fw_tables_size) {
+                       panic("EFI memmap too large. Increase NUM_MEM_DESCS.\n"
+                             "fw_table_size %ld > %ld num_mds %ld "
+                             "NUM_MEM_DESCS %d.\n",
+                             fw_tables_size, fw_tables->fw_tables_size,
+                             fw_tables->num_mds, NUM_MEM_DESCS);
+               }
+               fw_tables_size = sizeof(*fw_tables) +
+                       fw_tables->num_mds * sizeof(fw_tables->efi_memmap[0]);
+
+               /* clear domain builder internal use member */
+               fw_tables->fw_tables_size = 0;
+               fw_tables->fw_end_paddr = 0;
+               fw_tables->fw_tables_end_paddr = 0;
+               fw_tables->num_mds = 0;
+
+               /* copy fw_tables into domain pseudo physical address space */
+               dom_fw_copy_to(d, FW_TABLES_BASE_PADDR, fw_tables,
+                              fw_tables_size);
+               xfree(fw_tables);
+       }
+
+       dom_fw_domain_init(d, domain_mpa_to_imva(d, FW_TABLES_BASE_PADDR));
        return dom_fw_set_convmem_end(d);
 }
 
diff -r b46c2ff6dfb0 -r c0cdcebc0377 xen/include/asm-ia64/dom_fw.h
--- a/xen/include/asm-ia64/dom_fw.h     Thu May 31 14:47:08 2007 -0600
+++ b/xen/include/asm-ia64/dom_fw.h     Mon Jun 04 13:57:08 2007 -0600
@@ -8,7 +8,8 @@
 /* Portion of guest physical memory space reserved for PAL/SAL/EFI/ACPI
    data and code.  */
 #define FW_BASE_PADDR          0x0000UL
-#define FW_END_PADDR           0x3000UL
+/* It is assumed that FW_END_PADDR_MIN = FW_TABLES_END_PADDR_MIN */
+#define FW_END_PADDR_MIN       0x3000UL
 
 /* This is used to determined the portion of a domain's metaphysical memory
    space reserved for the hypercall patch table. */
@@ -29,7 +30,7 @@
 
 /* Base and end guest physical address of EFI and SAL (non-ACPI) tables.  */
 #define FW_TABLES_BASE_PADDR   0x2000UL
-#define FW_TABLES_END_PADDR    0x3000UL
+#define FW_TABLES_END_PADDR_MIN        0x3000UL
 
 
 /* Hypercalls number have a low part and a high part.
diff -r b46c2ff6dfb0 -r c0cdcebc0377 xen/include/asm-ia64/dom_fw_common.h
--- a/xen/include/asm-ia64/dom_fw_common.h      Thu May 31 14:47:08 2007 -0600
+++ b/xen/include/asm-ia64/dom_fw_common.h      Mon Jun 04 13:57:08 2007 -0600
@@ -64,16 +64,26 @@ struct fw_tables {
     /* End of SAL descriptors.  Do not forget to update checkum bound.  */
 
     fpswa_interface_t                   fpswa_inf;
-    efi_memory_desc_t                   efi_memmap[NUM_MEM_DESCS];
     unsigned long                       func_ptrs[2*NFUNCPTRS];
     struct xen_sal_data                 sal_data;
     unsigned char                       fw_vendor[sizeof(FW_VENDOR)];
+
+    /*
+     * These four member for domain builder internal use at virtualized
+     * efi memmap creation. They should be zero-cleared after use.
+     */
+    unsigned long                       fw_tables_size;
+    unsigned long                       fw_end_paddr;   
+    unsigned long                       fw_tables_end_paddr;
+    unsigned long                       num_mds;
+
+    efi_memory_desc_t                   efi_memmap[0];
 };
 #define FW_FIELD_MPA(field)                                     \
     FW_TABLES_BASE_PADDR + offsetof(struct fw_tables, field)
 
 void
-xen_ia64_efi_make_md(struct fw_tables *tables, int *index,
+xen_ia64_efi_make_md(efi_memory_desc_t *md,
                      uint32_t type, uint64_t attr, 
                      uint64_t start, uint64_t end);
 uint8_t generate_acpi_checksum(void *tbl, unsigned long len);
diff -r b46c2ff6dfb0 -r c0cdcebc0377 xen/include/asm-ia64/dom_fw_dom0.h
--- a/xen/include/asm-ia64/dom_fw_dom0.h        Thu May 31 14:47:08 2007 -0600
+++ b/xen/include/asm-ia64/dom_fw_dom0.h        Mon Jun 04 13:57:08 2007 -0600
@@ -25,11 +25,7 @@ struct domain;
 struct domain;
 
 void efi_systable_init_dom0(struct fw_tables *tables);
-int
-complete_dom0_memmap(struct domain *d,
-                     struct fw_tables *tables,
-                     unsigned long maxmem,
-                     int num_mds);
+int complete_dom0_memmap(struct domain *d, struct fw_tables *tables);
 
 #endif /* __ASM_IA64_DOM_FW_DOM0_H__ */
 /*
diff -r b46c2ff6dfb0 -r c0cdcebc0377 xen/include/asm-ia64/dom_fw_domu.h
--- a/xen/include/asm-ia64/dom_fw_domu.h        Thu May 31 14:47:08 2007 -0600
+++ b/xen/include/asm-ia64/dom_fw_domu.h        Mon Jun 04 13:57:08 2007 -0600
@@ -29,9 +29,9 @@ complete_domu_memmap(domain_t *d,
 complete_domu_memmap(domain_t *d,
                      struct fw_tables *tables,
                      unsigned long maxmem,
-                     int num_mds,
                      unsigned long memmap_info_pfn,
                      unsigned long reserved_size);
+
 #endif /* __ASM_IA64_DOM_FW_DOMU_H__ */
 /*
  * Local variables:
diff -r b46c2ff6dfb0 -r c0cdcebc0377 xen/include/asm-ia64/dom_fw_utils.h
--- a/xen/include/asm-ia64/dom_fw_utils.h       Thu May 31 14:47:08 2007 -0600
+++ b/xen/include/asm-ia64/dom_fw_utils.h       Mon Jun 04 13:57:08 2007 -0600
@@ -26,6 +26,10 @@ int xen_ia64_is_vcpu_allocated(struct do
 int xen_ia64_is_vcpu_allocated(struct domain *d, uint32_t vcpu); 
 int xen_ia64_is_running_on_sim(struct domain *unused);
 int xen_ia64_is_dom0(struct domain *d);
+void dom_fw_copy_to(struct domain *d, unsigned long dest_gpaddr,
+                    void *src, size_t size); 
+void dom_fw_copy_from(void* dest, struct domain *d, unsigned long src_gpaddr,
+                      size_t size); 
 
 #endif /* __ASM_XEN_IA64_DOM_FW_UTILS_H__ */
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] [IA64] Allow dynamic allocation of dom0 fw_tables, Xen patchbot-unstable <=