All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] xen: arm: handle initrd addresses above the 4G boundary
@ 2013-12-09 11:43 Ian Campbell
  2013-12-09 15:05 ` Julien Grall
  0 siblings, 1 reply; 3+ messages in thread
From: Ian Campbell @ 2013-12-09 11:43 UTC (permalink / raw)
  To: xen-devel; +Cc: julien.grall, tim, Ian Campbell, stefano.stabellini

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@citrix.com>
---
v2: improve error messages
    only accept start and end addresses which are exaclty u32 or u64 sized.
    correct parameter name in dt_size_to_cells and comment on the rounding
    down behaviour which it has.
---
 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 213b3ac..532f39c6 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;
+    u32 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;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v2] xen: arm: handle initrd addresses above the 4G boundary
  2013-12-09 11:43 [PATCH v2] xen: arm: handle initrd addresses above the 4G boundary Ian Campbell
@ 2013-12-09 15:05 ` Julien Grall
  2013-12-09 15:47   ` Ian Campbell
  0 siblings, 1 reply; 3+ messages in thread
From: Julien Grall @ 2013-12-09 15:05 UTC (permalink / raw)
  To: Ian Campbell; +Cc: stefano.stabellini, tim, xen-devel

On 12/09/2013 11:43 AM, Ian Campbell wrote:
> 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@citrix.com>
> ---
> v2: improve error messages
>     only accept start and end addresses which are exaclty u32 or u64 sized.
>     correct parameter name in dt_size_to_cells and comment on the rounding
>     down behaviour which it has.
> ---
>  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 213b3ac..532f39c6 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;
> +    u32 val[2];

Shouldn't it be __be32?

With this fix and given your answer on the previous version:

Acked-by: Julien Grall <julien.grall@linaro.org>

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v2] xen: arm: handle initrd addresses above the 4G boundary
  2013-12-09 15:05 ` Julien Grall
@ 2013-12-09 15:47   ` Ian Campbell
  0 siblings, 0 replies; 3+ messages in thread
From: Ian Campbell @ 2013-12-09 15:47 UTC (permalink / raw)
  To: Julien Grall; +Cc: stefano.stabellini, tim, xen-devel

On Mon, 2013-12-09 at 15:05 +0000, Julien Grall wrote:
> > @@ -926,6 +927,8 @@ static void initrd_load(struct kernel_info *kinfo)
> >      unsigned long offs;
> >      int node;
> >      int res;
> > +    u32 val[2];
> 
> Shouldn't it be __be32?

Yes, done.

> With this fix and given your answer on the previous version:
> 
> Acked-by: Julien Grall <julien.grall@linaro.org>

Thanks, applied.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2013-12-09 15:47 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-12-09 11:43 [PATCH v2] xen: arm: handle initrd addresses above the 4G boundary Ian Campbell
2013-12-09 15:05 ` Julien Grall
2013-12-09 15:47   ` Ian Campbell

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.