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

[Xen-devel] [PATCH 2/8] xen/arm: Retrieve the correct number of cells when building dom0 DT



The function dt_n_*_cells will retrieve the number of cells for a given
node. Those numbers may not be correct to use for the child "reg"
property if the parent is passed.

This is fine today because the parent is always the root node which
means there is no upper parent.

Introduce new helpers dt_child_n_*_cells to retrieve the number of
cells for the address and size that can be used to create the "reg"
property of a child of a given parent.

Use the new helpers when creating the hypervisor and memory node where
we only have the parent in hand. This is because those nodes are
recreated from scratch by Xen and therefore we don't have a
dt_device_node for them. The only thing we have is a pointer to there
future parent.

We also have to modify dt_set_range to take a parent in parameter rather
than an HW DT node that we will replicated in the DOM0 DT.

Signed-off-by: Julien Grall <julien.grall@xxxxxxxxxx>
---
 xen/arch/arm/domain_build.c   |  6 +++---
 xen/arch/arm/gic-v3.c         |  4 ++--
 xen/common/device_tree.c      | 38 +++++++++++++++++++++++++++++++-------
 xen/include/xen/device_tree.h | 23 +++++++++++++++++++++--
 4 files changed, 57 insertions(+), 14 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index a059de6..f7ea240 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -569,7 +569,7 @@ static int make_memory_node(const struct domain *d,
                             const struct kernel_info *kinfo)
 {
     int res, i;
-    int reg_size = dt_n_addr_cells(parent) + dt_n_size_cells(parent);
+    int reg_size = dt_child_n_addr_cells(parent) + 
dt_child_n_size_cells(parent);
     int nr_cells = reg_size*kinfo->mem.nr_banks;
     __be32 reg[nr_cells];
     __be32 *cells;
@@ -617,8 +617,8 @@ static int make_hypervisor_node(const struct kernel_info 
*kinfo,
     __be32 *cells;
     int res;
     /* Convenience alias */
-    int addrcells = dt_n_addr_cells(parent);
-    int sizecells = dt_n_size_cells(parent);
+    int addrcells = dt_child_n_addr_cells(parent);
+    int sizecells = dt_child_n_size_cells(parent);
     void *fdt = kinfo->fdt;
 
     DPRINT("Create hypervisor node\n");
diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index 0df4baf..957e491 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -1096,10 +1096,10 @@ static int gicv3_make_hwdom_dt_node(const struct domain 
*d,
 
     tmp = new_cells;
 
-    dt_set_range(&tmp, gic, d->arch.vgic.dbase, SZ_64K);
+    dt_set_range(&tmp, gic->parent, d->arch.vgic.dbase, SZ_64K);
 
     for ( i = 0; i < d->arch.vgic.nr_regions; i++ )
-        dt_set_range(&tmp, gic, d->arch.vgic.rdist_regions[i].base,
+        dt_set_range(&tmp, gic->parent, d->arch.vgic.rdist_regions[i].base,
                      d->arch.vgic.rdist_regions[i].size);
 
     res = fdt_property(fdt, "reg", new_cells, len);
diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
index 18cdb6f..845cc77 100644
--- a/xen/common/device_tree.c
+++ b/xen/common/device_tree.c
@@ -110,11 +110,11 @@ void dt_set_cell(__be32 **cellp, int size, u64 val)
     (*cellp) += cells;
 }
 
-void dt_set_range(__be32 **cellp, const struct dt_device_node *np,
+void dt_set_range(__be32 **cellp, const struct dt_device_node *parent,
                   u64 address, u64 size)
 {
-    dt_set_cell(cellp, dt_n_addr_cells(np), address);
-    dt_set_cell(cellp, dt_n_size_cells(np), size);
+    dt_set_cell(cellp, dt_child_n_addr_cells(parent), address);
+    dt_set_cell(cellp, dt_child_n_size_cells(parent), size);
 }
 
 static void __init *unflatten_dt_alloc(unsigned long *mem, unsigned long size,
@@ -386,13 +386,15 @@ dt_find_matching_node(struct dt_device_node *from,
     return NULL;
 }
 
-int dt_n_addr_cells(const struct dt_device_node *np)
+static int __dt_n_addr_cells(const struct dt_device_node *np, bool_t parent)
 {
     const __be32 *ip;
 
     do {
-        if ( np->parent )
+        if ( np->parent && !parent )
             np = np->parent;
+        parent = false;
+
         ip = dt_get_property(np, "#address-cells", NULL);
         if ( ip )
             return be32_to_cpup(ip);
@@ -401,13 +403,15 @@ int dt_n_addr_cells(const struct dt_device_node *np)
     return DT_ROOT_NODE_ADDR_CELLS_DEFAULT;
 }
 
-int dt_n_size_cells(const struct dt_device_node *np)
+int __dt_n_size_cells(const struct dt_device_node *np, bool_t parent)
 {
     const __be32 *ip;
 
     do {
-        if ( np->parent )
+        if ( np->parent && !parent )
             np = np->parent;
+        parent = false;
+
         ip = dt_get_property(np, "#size-cells", NULL);
         if ( ip )
             return be32_to_cpup(ip);
@@ -416,6 +420,26 @@ int dt_n_size_cells(const struct dt_device_node *np)
     return DT_ROOT_NODE_SIZE_CELLS_DEFAULT;
 }
 
+int dt_n_addr_cells(const struct dt_device_node *np)
+{
+    return __dt_n_addr_cells(np, false);
+}
+
+int dt_n_size_cells(const struct dt_device_node *np)
+{
+    return __dt_n_size_cells(np, false);
+}
+
+int dt_child_n_addr_cells(const struct dt_device_node *parent)
+{
+    return __dt_n_addr_cells(parent, true);
+}
+
+int dt_child_n_size_cells(const struct dt_device_node *parent)
+{
+    return __dt_n_size_cells(parent, true);
+}
+
 /*
  * These are defined in Linux where much of this code comes from, but
  * are currently unused outside this file in the context of Xen.
diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
index 46c5ba8..8618ca7 100644
--- a/xen/include/xen/device_tree.h
+++ b/xen/include/xen/device_tree.h
@@ -584,6 +584,25 @@ int dt_n_size_cells(const struct dt_device_node *np);
 int dt_n_addr_cells(const struct dt_device_node *np);
 
 /**
+ * dt_child_n_size_cells - Helper to retrieve the number of cell for the size
+ * @parent: parent of the child to get the value
+ *
+ * This function retrieves for a given device-tree node the number of
+ * cell for the size field of there child
+ */
+int dt_child_n_size_cells(const struct dt_device_node *parent);
+
+/**
+ * dt_child_n_addr_cells - Helper to retrieve the number of cell for the
+ * address
+ * @parent: parent of the child to get the value
+ *
+ * This function retrieves for a given device-tree node the number of
+ * cell for the address field of there child
+ */
+int dt_child_n_addr_cells(const struct dt_device_node *parent);
+
+/**
  * dt_device_is_available - Check if a device is available for use
  *
  * @device: Node to check for availability
@@ -644,14 +663,14 @@ void dt_set_cell(__be32 **cellp, int size, u64 val);
  * dt_set_range - Write range into a series of cells
  *
  * @cellp: Pointer to cells
- * @np: Node which contains the encoding for the address and the size
+ * @parent: Parent node which contains the encode for the address and the size
  * @address: Start of range
  * @size: Size of the range
  *
  * Write a range into a series of cells and update cellp to point to the
  * cell just after.
  */
-void dt_set_range(__be32 **cellp, const struct dt_device_node *np,
+void dt_set_range(__be32 **cellp, const struct dt_device_node *parent,
                   u64 address, u64 size);
 
 /**
-- 
2.1.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®.