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

[Xen-changelog] [xen master] xen: arm: handle initrd addresses above the 4G boundary



commit ae5d5fb58dcacaf7e2d5fbfbe7b565f401c62808
Author:     Ian Campbell <ian.campbell@xxxxxxxxxx>
AuthorDate: Mon Dec 9 11:43:35 2013 +0000
Commit:     Ian Campbell <ian.campbell@xxxxxxxxxx>
CommitDate: Mon Dec 9 15:28:55 2013 +0000

    xen: arm: handle initrd addresses above the 4G boundary
    
    The Xgene platform has no RAM below 4G.
    
    The /chosen/linux,initrd-* properties do not have "reg" semantics and
    therefore #*-size are not used when interpreting. Instead they are are 
simply
    numbers which are interpreted according to the properties length.
    
    Fix this both when parsing the entry in the host DTB and when creating the
    dom0 DTB. For dom0 we simply hardcode a 64-bit size, this is acceptable
    even for a 32-bit guest.
    
    Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
    Acked-by: Julien Grall <julien.grall@xxxxxxxxxx>
---
 xen/arch/arm/domain_build.c   |   19 +++++++++++++------
 xen/common/device_tree.c      |   37 ++++++++++++++++++++++++++++++++-----
 xen/include/xen/device_tree.h |    8 +++++++-
 3 files changed, 52 insertions(+), 12 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index d50658b..fb1ec87 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -222,11 +222,12 @@ static int write_properties(struct domain *d, struct 
kernel_info *kinfo,
          */
         if ( early_info.modules.module[MOD_INITRD].size )
         {
-            res = fdt_property_cell(kinfo->fdt, "linux,initrd-start", 0);
+            u64 a = 0;
+            res = fdt_property(kinfo->fdt, "linux,initrd-start", &a, 
sizeof(a));
             if ( res )
                 return res;
 
-            res = fdt_property_cell(kinfo->fdt, "linux,initrd-end", 0);
+            res = fdt_property(kinfo->fdt, "linux,initrd-end", &a, sizeof(a));
             if ( res )
                 return res;
         }
@@ -926,6 +927,8 @@ static void initrd_load(struct kernel_info *kinfo)
     unsigned long offs;
     int node;
     int res;
+    __be32 val[2];
+    __be32 *cellp;
 
     if ( !len )
         return;
@@ -938,13 +941,17 @@ static void initrd_load(struct kernel_info *kinfo)
     if ( node < 0 )
         panic("Cannot find the /chosen node");
 
-    res = fdt_setprop_inplace_cell(kinfo->fdt, node, "linux,initrd-start",
-                                   load_addr);
+    cellp = (__be32 *)val;
+    dt_set_cell(&cellp, ARRAY_SIZE(val), load_addr);
+    res = fdt_setprop_inplace(kinfo->fdt, node, "linux,initrd-start",
+                              val, sizeof(val));
     if ( res )
         panic("Cannot fix up \"linux,initrd-start\" property");
 
-    res = fdt_setprop_inplace_cell(kinfo->fdt, node, "linux,initrd-end",
-                                   load_addr + len);
+    cellp = (__be32 *)val;
+    dt_set_cell(&cellp, ARRAY_SIZE(val), load_addr + len);
+    res = fdt_setprop_inplace(kinfo->fdt, node, "linux,initrd-end",
+                              val, sizeof(val));
     if ( res )
         panic("Cannot fix up \"linux,initrd-end\" property");
 
diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
index 943b181..84e709d 100644
--- a/xen/common/device_tree.c
+++ b/xen/common/device_tree.c
@@ -390,18 +390,45 @@ static void __init process_chosen_node(const void *fdt, 
int node,
                                        const char *name,
                                        u32 address_cells, u32 size_cells)
 {
+    const struct fdt_property *prop;
     struct dt_mb_module *mod = &early_info.modules.module[MOD_INITRD];
-    u32 start, end;
+    paddr_t start, end;
+    int len;
 
     dt_printk("Checking for initrd in /chosen\n");
 
-    start = device_tree_get_u32(fdt, node, "linux,initrd-start", 0);
-    end = device_tree_get_u32(fdt, node, "linux,initrd-end", 0);
+    prop = fdt_get_property(fdt, node, "linux,initrd-start", &len);
+    if ( !prop )
+        /* No initrd present. */
+        return;
+    if ( len != sizeof(u32) && len != sizeof(u64) )
+    {
+        dt_printk("linux,initrd-start property has invalid length %d\n", len);
+        return;
+    }
+    start = dt_read_number((void *)&prop->data, dt_size_to_cells(len));
 
-    if ( !start || !end || (start >= end) )
+    prop = fdt_get_property(fdt, node, "linux,initrd-end", &len);
+    if ( !prop )
+    {
+        dt_printk("linux,initrd-end not present but -start was\n");
         return;
+    }
+    if ( len != sizeof(u32) && len != sizeof(u64) )
+    {
+        dt_printk("linux,initrd-end property has invalid length %d\n", len);
+        return;
+    }
+    end = dt_read_number((void *)&prop->data, dt_size_to_cells(len));
+
+    if ( start >= end )
+    {
+        dt_printk("linux,initrd limits invalid: %"PRIpaddr" >= %"PRIpaddr"\n",
+                  start, end);
+        return;
+    }
 
-    dt_printk("Initrd 0x%x-0x%x\n", start, end);
+    dt_printk("Initrd %"PRIpaddr"-%"PRIpaddr"\n", start, end);
 
     mod->start = start;
     mod->size = end - start;
diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
index da78c9f..9a8c3de 100644
--- a/xen/include/xen/device_tree.h
+++ b/xen/include/xen/device_tree.h
@@ -256,12 +256,18 @@ static inline u64 dt_read_number(const __be32 *cell, int 
size)
     return r;
 }
 
-/* Helper to convert a number of cells in bytes */
+/* Helper to convert a number of cells to bytes */
 static inline int dt_cells_to_size(int size)
 {
     return (size * sizeof (u32));
 }
 
+/* Helper to convert a number of bytes to cells, rounds down */
+static inline int dt_size_to_cells(int bytes)
+{
+    return (bytes / sizeof(u32));
+}
+
 static inline u64 dt_next_cell(int s, const __be32 **cellp)
 {
     const __be32 *p = *cellp;
--
generated by git-patchbot for /home/xen/git/xen.git#master

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
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®.