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

[Xen-devel] [PATCH RFC 03/15] xen: arm: allocate dom0 memory separately from preparing the dtb



Mixing these two together is a pain, it forces us to prepare the dtb before
processing the kernel which means we don't know whether the guest is 32- or
64-bit while we construct its DTB.

Instead split out the memory allocation (including 1:1 workaround handling)
and p2m setup into a seaprate phase and then fill in the memory nodes in the
DTB based on the result while generating the DTB.

This allows us to move kernel parsing before DTB setup.

Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
---
 xen/arch/arm/domain_build.c |   94 ++++++++++++++++++++++++++++++-------------
 1 file changed, 65 insertions(+), 29 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index fb1fa56..1287934 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -63,11 +63,8 @@ struct vcpu *__init alloc_dom0_vcpu0(void)
     return alloc_vcpu(dom0, 0, 0);
 }
 
-static int set_memory_reg_11(struct domain *d, struct kernel_info *kinfo,
-                             const struct dt_property *pp,
-                             const struct dt_device_node *np, __be32 *new_cell)
+static int allocate_memory_11(struct domain *d, struct kernel_info *kinfo)
 {
-    int reg_size = dt_cells_to_size(dt_n_addr_cells(np) + dt_n_size_cells(np));
     paddr_t start;
     paddr_t size;
     struct page_info *pg;
@@ -91,40 +88,53 @@ static int set_memory_reg_11(struct domain *d, struct 
kernel_info *kinfo,
     if ( res )
         panic("Unable to add pages in DOM0: %d\n", res);
 
-    dt_set_range(&new_cell, np, start, size);
-
     kinfo->mem.bank[0].start = start;
     kinfo->mem.bank[0].size = size;
     kinfo->mem.nr_banks = 1;
 
-    return reg_size;
+    kinfo->unassigned_mem -= size;
+
+    return 0;
 }
 
-static int set_memory_reg(struct domain *d, struct kernel_info *kinfo,
-                          const struct dt_property *pp,
-                          const struct dt_device_node *np, __be32 *new_cell)
+static int allocate_memory(struct domain *d, struct kernel_info *kinfo)
 {
-    int reg_size = dt_cells_to_size(dt_n_addr_cells(np) + dt_n_size_cells(np));
-    int l = 0;
+
+    const struct dt_device_node *memory;
+    const void *reg;
+    u32 reg_len, reg_size;
+    int l = 0, ret;
     unsigned int bank = 0;
-    u64 start;
-    u64 size;
-    int ret;
 
     if ( platform_has_quirk(PLATFORM_QUIRK_DOM0_MAPPING_11) )
-        return set_memory_reg_11(d, kinfo, pp, np, new_cell);
+        return allocate_memory_11(d, kinfo);
+
+    memory = dt_find_node_by_type(NULL, "memory");
+    if ( memory == NULL )
+    {
+        panic("No host memory node when building dom0!\n");
+    }
+
+    reg_size = dt_cells_to_size(dt_n_addr_cells(memory) + 
dt_n_size_cells(memory));
 
-    while ( kinfo->unassigned_mem > 0 && l + reg_size <= pp->length
+    reg = dt_get_property(memory, "reg", &reg_len);
+    if ( reg == NULL )
+    {
+        panic("Memory node has now reg property!\n");
+    }
+
+    while ( kinfo->unassigned_mem > 0 && l + reg_size <= reg_len
             && kinfo->mem.nr_banks < NR_MEM_BANKS )
     {
-        ret = dt_device_get_address(np, bank, &start, &size);
+        paddr_t start, size;
+
+        ret = dt_device_get_address(memory, bank, &start, &size);
         if ( ret )
             panic("Unable to retrieve the bank %u for %s\n",
-                  bank, dt_node_full_name(np));
+                  bank, dt_node_full_name(memory));
 
         if ( size > kinfo->unassigned_mem )
             size = kinfo->unassigned_mem;
-        dt_set_range(&new_cell, np, start, size);
 
         printk("Populate P2M %#"PRIx64"->%#"PRIx64"\n", start, start + size);
         if ( p2m_populate_ram(d, start, start + size) < 0 )
@@ -132,12 +142,34 @@ static int set_memory_reg(struct domain *d, struct 
kernel_info *kinfo,
         kinfo->mem.bank[kinfo->mem.nr_banks].start = start;
         kinfo->mem.bank[kinfo->mem.nr_banks].size = size;
         kinfo->mem.nr_banks++;
+
         kinfo->unassigned_mem -= size;
 
         l += reg_size;
     }
+    return 0;
+}
 
-    return l;
+static int set_memory_reg(struct domain *d, struct kernel_info *kinfo,
+                          const struct dt_device_node *np, __be32 *new_cell)
+{
+    int reg_size = dt_cells_to_size(dt_n_addr_cells(np) + dt_n_size_cells(np));
+    u64 start;
+    u64 size;
+    int i;
+
+    for ( i = 0 ; i < kinfo->mem.nr_banks; i++ )
+    {
+        start = kinfo->mem.bank[i].start;
+        size = kinfo->mem.bank[i].size;
+
+        DPRINT("Memory Bank %d: %#"PRIx64"->%#"PRIx64"\n",
+                i, start, start + size);
+
+        dt_set_range(&new_cell, np, start, size);
+    }
+
+    return kinfo->mem.nr_banks * reg_size;
 }
 
 static int write_properties(struct domain *d, struct kernel_info *kinfo,
@@ -194,7 +226,7 @@ static int write_properties(struct domain *d, struct 
kernel_info *kinfo,
                 if ( new_data  == NULL )
                     return -FDT_ERR_XEN(ENOMEM);
 
-                prop_len = set_memory_reg(d, kinfo, pp, np,
+                prop_len = set_memory_reg(d, kinfo, np,
                                           (__be32 *)new_data);
                 prop_data = new_data;
             }
@@ -768,8 +800,6 @@ static int prepare_dtb(struct domain *d, struct kernel_info 
*kinfo)
 
     ASSERT(dt_host && (dt_host->sibling == NULL));
 
-    kinfo->unassigned_mem = dom0_mem;
-
     fdt = device_tree_flattened;
 
     new_size = fdt_totalsize(fdt) + DOM0_FDT_EXTRA_SIZE;
@@ -858,7 +888,9 @@ int construct_dom0(struct domain *d)
 
     d->max_pages = ~0U;
 
-    rc = prepare_dtb(d, &kinfo);
+    kinfo.unassigned_mem = dom0_mem;
+
+    rc = allocate_memory(d, &kinfo);
     if ( rc < 0 )
         return rc;
 
@@ -866,6 +898,14 @@ int construct_dom0(struct domain *d)
     if ( rc < 0 )
         return rc;
 
+#ifdef CONFIG_ARM_64
+    d->arch.type = kinfo.type;
+#endif
+
+    rc = prepare_dtb(d, &kinfo);
+    if ( rc < 0 )
+        return rc;
+
     rc = platform_specific_mapping(d);
     if ( rc < 0 )
         return rc;
@@ -888,10 +928,6 @@ int construct_dom0(struct domain *d)
 
     regs->pc = (register_t)kinfo.entry;
 
-#ifdef CONFIG_ARM_64
-    d->arch.type = kinfo.type;
-#endif
-
     if ( is_pv32_domain(d) )
     {
         regs->cpsr = PSR_GUEST32_INIT;
-- 
1.7.10.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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