xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] ARM: Support initrd loading
@ 2013-09-16 15:20 Julien Grall
  2013-09-16 15:20 ` [PATCH 1/2] xen/arm: Add support to load initrd in dom0 Julien Grall
  2013-09-16 15:20 ` [PATCH 2/2] xen/dts: Support Linux initrd DT bindings Julien Grall
  0 siblings, 2 replies; 10+ messages in thread
From: Julien Grall @ 2013-09-16 15:20 UTC (permalink / raw)
  To: xen-devel
  Cc: patches, Julien Grall, ian.campbell, andre.przywara,
	stefano.stabellini

Hi,

This small patch series adds support to load initrd in dom0 for ARM.

It depends on the patch series "Allow Xen to boot with a raw device tree"
(http://www.gossamer-threads.com/lists/xen/devel/297786) and the patch
"xen: arm: rework placement of fdt in initial dom0 memory map"
(http://www.gossamer-threads.com/lists/xen/devel/297844).

Cheers,

Julien Grall (2):
  xen/arm: Add support to load initrd in dom0
  xen/dts: Support Linux initrd DT bindings

 xen/arch/arm/domain_build.c |   98 ++++++++++++++++++++++++++++++++++++++-----
 xen/arch/arm/kernel.c       |   20 +++++----
 xen/arch/arm/kernel.h       |    2 +
 xen/common/device_tree.c    |   25 +++++++++++
 4 files changed, 127 insertions(+), 18 deletions(-)

-- 
1.7.10.4

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

* [PATCH 1/2] xen/arm: Add support to load initrd in dom0
  2013-09-16 15:20 [PATCH 0/2] ARM: Support initrd loading Julien Grall
@ 2013-09-16 15:20 ` Julien Grall
  2013-09-25 15:15   ` Ian Campbell
  2013-09-16 15:20 ` [PATCH 2/2] xen/dts: Support Linux initrd DT bindings Julien Grall
  1 sibling, 1 reply; 10+ messages in thread
From: Julien Grall @ 2013-09-16 15:20 UTC (permalink / raw)
  To: xen-devel
  Cc: patches, Julien Grall, ian.campbell, andre.przywara,
	stefano.stabellini

Signed-off-by: Julien Grall <julien.grall@linaro.org>
---
 xen/arch/arm/domain_build.c |   98 ++++++++++++++++++++++++++++++++++++++-----
 xen/arch/arm/kernel.c       |   20 +++++----
 xen/arch/arm/kernel.h       |    2 +
 3 files changed, 102 insertions(+), 18 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index f569e31..f3bb262 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -163,12 +163,16 @@ static int write_properties(struct domain *d, struct kernel_info *kinfo,
          *
          * * remember xen,dom0-bootargs if we don't already have
          *   bootargs (from module #1, above).
-         * * remove bootargs,  xen,dom0-bootargs and xen,xen-bootargs.
+         * * remove bootargs,  xen,dom0-bootargs, xen,xen-bootargs,
+         *   linux,initrd-start and linux,initrd-end.
          */
         if ( dt_node_path_is_equal(np, "/chosen") )
         {
-            if ( dt_property_name_is_equal(pp, "xen,xen-bootargs") )
+            if ( dt_property_name_is_equal(pp, "xen,xen-bootargs") ||
+                 dt_property_name_is_equal(pp, "linux,initrd-start") ||
+                 dt_property_name_is_equal(pp, "linux,initrd-end") )
                 continue;
+
             if ( dt_property_name_is_equal(pp, "xen,dom0-bootargs") )
             {
                 had_dom0_bootargs = 1;
@@ -214,12 +218,22 @@ static int write_properties(struct domain *d, struct kernel_info *kinfo,
                            strlen(bootargs) + 1);
         if ( res )
             return res;
-    }
 
-    /*
-     * XXX should populate /chosen/linux,initrd-{start,end} here if we
-     * have module[2]
-     */
+        /*
+         * If the bootloader provides an initrd, we must create a placeholder
+         * for the initrd properties. The values will be replaced later.
+         */
+        if ( early_info.modules.module[MOD_INITRD].size )
+        {
+            res = fdt_property_cell(kinfo->fdt, "linux,initrd-start", 0);
+            if ( res )
+                return res;
+
+            res = fdt_property_cell(kinfo->fdt, "linux,initrd-end", 0);
+            if ( res )
+                return res;
+        }
+    }
 
     return 0;
 }
@@ -779,6 +793,7 @@ static int prepare_dtb(struct domain *d, struct kernel_info *kinfo)
     int new_size;
     int ret;
     paddr_t end;
+    paddr_t initrd_len;
 
     ASSERT(dt_host && (dt_host->sibling == NULL));
 
@@ -806,7 +821,8 @@ static int prepare_dtb(struct domain *d, struct kernel_info *kinfo)
         goto err;
 
     /* Actual new size */
-    new_size = fdt_totalsize(kinfo->fdt);
+    initrd_len = early_info.modules.module[MOD_INITRD].size;
+    new_size = fdt_totalsize(kinfo->fdt) + initrd_len;
 
     /*
      * DTB must be loaded such that it does not conflict with the
@@ -815,15 +831,20 @@ static int prepare_dtb(struct domain *d, struct kernel_info *kinfo)
      * the recommendation in Documentation/arm64/booting.txt is below
      * 512MB. Place at 128MB, (or, if we have less RAM, as high as
      * possible) in order to satisfy both.
+     * If the bootloader provides an initrd, it will be loaded just
+     * after the DTB.
      */
     end = kinfo->mem.bank[0].start + kinfo->mem.bank[0].size;
     end = MIN(kinfo->mem.bank[0].start + (128<<20) + new_size, end);
 
-    kinfo->dtb_paddr = end - fdt_totalsize(kinfo->fdt);
+    kinfo->initrd_paddr = end - initrd_len;
+    kinfo->initrd_paddr &= ~((1 << 20) - 1);
+
+    kinfo->dtb_paddr = kinfo->initrd_paddr - fdt_totalsize(kinfo->fdt);
     /* Align the address to 2Mb. Linux only requires 4 byte alignment */
     kinfo->dtb_paddr &= ~((2 << 20) - 1);
 
-    if ( fdt_totalsize(kinfo->fdt) > end )
+    if ( new_size > (end - kinfo->mem.bank[0].size) )
     {
         printk(XENLOG_ERR "Not enough memory in the first bank for "
                "the device tree.");
@@ -854,6 +875,61 @@ static void dtb_load(struct kernel_info *kinfo)
     xfree(kinfo->fdt);
 }
 
+static void initrd_load(struct kernel_info *kinfo)
+{
+    paddr_t load_addr = kinfo->initrd_paddr;
+    paddr_t paddr = early_info.modules.module[MOD_INITRD].start;
+    paddr_t len = early_info.modules.module[MOD_INITRD].size;
+    unsigned long offs;
+    int node;
+    int res;
+
+    if ( !len )
+        return;
+
+    printk("Loading dom0 initrd from %"PRIpaddr" to 0x%"PRIpaddr"-0x%"PRIpaddr"\n",
+           paddr, load_addr, load_addr + len);
+
+    /* Fix up linux,initrd-start and linux,initrd-end in /chosen */
+    node = fdt_path_offset(kinfo->fdt, "/chosen");
+    if ( node < 0 )
+        panic("Cannot find the /chosen node");
+
+    res = fdt_setprop_inplace_cell(kinfo->fdt, node, "linux,initrd-start",
+                                   load_addr);
+    if ( res )
+        panic("Cannot fix up \"linux,initrd-start\" property\n");
+
+    res = fdt_setprop_inplace_cell(kinfo->fdt, node, "linux,initrd-end",
+                                   load_addr + len);
+    if ( res )
+        panic("Cannot fix up \"linux,initrd-end\" property\n");
+
+    for ( offs = 0; offs < len; )
+    {
+        int rc;
+        paddr_t s, l, ma;
+        void *dst;
+
+        s = offs & ~PAGE_MASK;
+        l = min(PAGE_SIZE - s, len);
+
+        rc = gvirt_to_maddr(load_addr + offs, &ma);
+        if ( rc )
+        {
+            panic("\nUnable to translate guest address\n");
+            return;
+        }
+
+        dst = map_domain_page(ma>>PAGE_SHIFT);
+
+        copy_from_paddr(dst + s, paddr + offs, l, BUFFERABLE);
+
+        unmap_domain_page(dst);
+        offs += l;
+    }
+}
+
 int construct_dom0(struct domain *d)
 {
     struct kernel_info kinfo = {};
@@ -890,6 +966,8 @@ int construct_dom0(struct domain *d)
     p2m_load_VTTBR(d);
 
     kernel_load(&kinfo);
+    /* initrd_load will fix up the fdt, so call it before dtb_load */
+    initrd_load(&kinfo);
     dtb_load(&kinfo);
 
     discard_initial_modules();
diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c
index e4c0981..84356a1 100644
--- a/xen/arch/arm/kernel.c
+++ b/xen/arch/arm/kernel.c
@@ -71,15 +71,22 @@ static void kernel_zimage_check_overlap(struct kernel_info *info)
 {
     paddr_t zimage_start = info->zimage.load_addr;
     paddr_t zimage_end = info->zimage.load_addr + info->zimage.len;
-    paddr_t dtb_start = info->dtb_paddr;
-    paddr_t dtb_end = info->dtb_paddr + fdt_totalsize(info->fdt);
+    paddr_t start = info->dtb_paddr;
+    paddr_t end;
 
-    if ( (dtb_start > zimage_end) || (dtb_end < zimage_start) )
+    end = info->initrd_paddr + early_info.modules.module[MOD_INITRD].size;
+
+    /*
+     * In the dom0 memory, the initrd will be just after the DTB. So we
+     * only need to check if the zImage range will overlap the
+     * DTB-initrd range.
+     */
+    if ( (start > zimage_end) || (end < zimage_start) )
         return;
 
     panic(XENLOG_ERR "The kernel(0x%"PRIpaddr"-0x%"PRIpaddr
-          ") is overlapping the DTB(0x%"PRIpaddr"-0x%"PRIpaddr")\n",
-          zimage_start, zimage_end, dtb_start, dtb_end);
+          ") is overlapping the DTB-initrd(0x%"PRIpaddr"-0x%"PRIpaddr")\n",
+          zimage_start, zimage_end, start, end);
 }
 
 static void kernel_zimage_load(struct kernel_info *info)
@@ -328,9 +335,6 @@ int kernel_prepare(struct kernel_info *info)
 
     paddr_t start, size;
 
-    if ( early_info.modules.nr_mods > MOD_INITRD )
-        panic("Cannot handle dom0 initrd yet\n");
-
     if ( early_info.modules.nr_mods < MOD_KERNEL )
     {
         printk("No boot modules found, trying flash\n");
diff --git a/xen/arch/arm/kernel.h b/xen/arch/arm/kernel.h
index c900e74..debf590 100644
--- a/xen/arch/arm/kernel.h
+++ b/xen/arch/arm/kernel.h
@@ -21,6 +21,8 @@ struct kernel_info {
     paddr_t dtb_paddr;
     paddr_t entry;
 
+    paddr_t initrd_paddr;
+
     void *kernel_img;
     unsigned kernel_order;
 
-- 
1.7.10.4

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

* [PATCH 2/2] xen/dts: Support Linux initrd DT bindings
  2013-09-16 15:20 [PATCH 0/2] ARM: Support initrd loading Julien Grall
  2013-09-16 15:20 ` [PATCH 1/2] xen/arm: Add support to load initrd in dom0 Julien Grall
@ 2013-09-16 15:20 ` Julien Grall
  2013-09-25 15:16   ` Ian Campbell
  1 sibling, 1 reply; 10+ messages in thread
From: Julien Grall @ 2013-09-16 15:20 UTC (permalink / raw)
  To: xen-devel
  Cc: patches, Julien Grall, ian.campbell, andre.przywara,
	stefano.stabellini

Linux uses the property linux,initrd-start and linux,initrd-end to know where
the initrd lives in memory.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
---
 xen/common/device_tree.c |   25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
index 9a16650..906f9f9 100644
--- a/xen/common/device_tree.c
+++ b/xen/common/device_tree.c
@@ -382,6 +382,29 @@ static void __init process_multiboot_node(const void *fdt, int node,
         early_info.modules.nr_mods = nr;
 }
 
+static void __init process_chosen_node(const void *fdt, int node,
+                                       const char *name,
+                                       u32 address_cells, u32 size_cells)
+{
+    struct dt_mb_module *mod = &early_info.modules.module[MOD_INITRD];
+    u32 start, end;
+
+    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);
+
+    if ( !start || !end || (start >= end) )
+        return;
+
+    dt_printk("Initrd 0x%x-0x%x\n", start, end);
+
+    mod->start = start;
+    mod->size = end - start;
+
+    early_info.modules.nr_mods = MAX(MOD_INITRD, early_info.modules.nr_mods);
+}
+
 static int __init early_scan_node(const void *fdt,
                                   int node, const char *name, int depth,
                                   u32 address_cells, u32 size_cells,
@@ -391,6 +414,8 @@ static int __init early_scan_node(const void *fdt,
         process_memory_node(fdt, node, name, address_cells, size_cells);
     else if ( device_tree_node_compatible(fdt, node, "xen,multiboot-module" ) )
         process_multiboot_node(fdt, node, name, address_cells, size_cells);
+    else if ( depth == 1 && device_tree_node_matches(fdt, node, "chosen") )
+        process_chosen_node(fdt, node, name, address_cells, size_cells);
 
     return 0;
 }
-- 
1.7.10.4

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

* Re: [PATCH 1/2] xen/arm: Add support to load initrd in dom0
  2013-09-16 15:20 ` [PATCH 1/2] xen/arm: Add support to load initrd in dom0 Julien Grall
@ 2013-09-25 15:15   ` Ian Campbell
  2013-09-25 15:23     ` Julien Grall
  0 siblings, 1 reply; 10+ messages in thread
From: Ian Campbell @ 2013-09-25 15:15 UTC (permalink / raw)
  To: Julien Grall; +Cc: stefano.stabellini, andre.przywara, patches, xen-devel

On Mon, 2013-09-16 at 16:20 +0100, Julien Grall wrote:
> @@ -806,7 +821,8 @@ static int prepare_dtb(struct domain *d, struct kernel_info *kinfo)
>          goto err;
>  
>      /* Actual new size */
> -    new_size = fdt_totalsize(kinfo->fdt);
> +    initrd_len = early_info.modules.module[MOD_INITRD].size;

I think you need to check nr_modules here and in write_properties (which
I already trimmed by mistake.

.size may not be initialised otherwise. (in reality it's probably
in .bss not sure I want to rely on that though)

> +    new_size = fdt_totalsize(kinfo->fdt) + initrd_len;
>  
>      /*
>       * DTB must be loaded such that it does not conflict with the
> @@ -815,15 +831,20 @@ static int prepare_dtb(struct domain *d, struct kernel_info *kinfo)
>       * the recommendation in Documentation/arm64/booting.txt is below
>       * 512MB. Place at 128MB, (or, if we have less RAM, as high as
>       * possible) in order to satisfy both.
> +     * If the bootloader provides an initrd, it will be loaded just
> +     * after the DTB.
>       */
>      end = kinfo->mem.bank[0].start + kinfo->mem.bank[0].size;
>      end = MIN(kinfo->mem.bank[0].start + (128<<20) + new_size, end);
>  
> -    kinfo->dtb_paddr = end - fdt_totalsize(kinfo->fdt);
> +    kinfo->initrd_paddr = end - initrd_len;
> +    kinfo->initrd_paddr &= ~((1 << 20) - 1);

1MB aligned, why not 2 like most things?

> +    kinfo->dtb_paddr = kinfo->initrd_paddr - fdt_totalsize(kinfo->fdt);
>      /* Align the address to 2Mb. Linux only requires 4 byte alignment */
>      kinfo->dtb_paddr &= ~((2 << 20) - 1);
>  
> -    if ( fdt_totalsize(kinfo->fdt) > end )
> +    if ( new_size > (end - kinfo->mem.bank[0].size) )
>      {
>          printk(XENLOG_ERR "Not enough memory in the first bank for "
>                 "the device tree.");
> @@ -854,6 +875,61 @@ static void dtb_load(struct kernel_info *kinfo)
>      xfree(kinfo->fdt);
>  }
>  
> +static void initrd_load(struct kernel_info *kinfo)
> +{
> +    paddr_t load_addr = kinfo->initrd_paddr;
> +    paddr_t paddr = early_info.modules.module[MOD_INITRD].start;
> +    paddr_t len = early_info.modules.module[MOD_INITRD].size;
> +    unsigned long offs;
> +    int node;
> +    int res;
> +
> +    if ( !len )
> +        return;
> +
> +    printk("Loading dom0 initrd from %"PRIpaddr" to 0x%"PRIpaddr"-0x%"PRIpaddr"\n",
> +           paddr, load_addr, load_addr + len);
> +
> +    /* Fix up linux,initrd-start and linux,initrd-end in /chosen */
> +    node = fdt_path_offset(kinfo->fdt, "/chosen");
> +    if ( node < 0 )
> +        panic("Cannot find the /chosen node");
> +
> +    res = fdt_setprop_inplace_cell(kinfo->fdt, node, "linux,initrd-start",
> +                                   load_addr);
> +    if ( res )
> +        panic("Cannot fix up \"linux,initrd-start\" property\n");
> +
> +    res = fdt_setprop_inplace_cell(kinfo->fdt, node, "linux,initrd-end",
> +                                   load_addr + len);
> +    if ( res )
> +        panic("Cannot fix up \"linux,initrd-end\" property\n");
> +
> +    for ( offs = 0; offs < len; )

Can you refactor kernel_zimage_load into a more generic function which
can be used here?

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

* Re: [PATCH 2/2] xen/dts: Support Linux initrd DT bindings
  2013-09-16 15:20 ` [PATCH 2/2] xen/dts: Support Linux initrd DT bindings Julien Grall
@ 2013-09-25 15:16   ` Ian Campbell
  0 siblings, 0 replies; 10+ messages in thread
From: Ian Campbell @ 2013-09-25 15:16 UTC (permalink / raw)
  To: Julien Grall; +Cc: stefano.stabellini, andre.przywara, patches, xen-devel

On Mon, 2013-09-16 at 16:20 +0100, Julien Grall wrote:
> Linux uses the property linux,initrd-start and linux,initrd-end to know where
> the initrd lives in memory.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>

Acked-by: Ian Campbell <ian.campbell@citrix.com>

> ---
>  xen/common/device_tree.c |   25 +++++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
> 
> diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
> index 9a16650..906f9f9 100644
> --- a/xen/common/device_tree.c
> +++ b/xen/common/device_tree.c
> @@ -382,6 +382,29 @@ static void __init process_multiboot_node(const void *fdt, int node,
>          early_info.modules.nr_mods = nr;
>  }
>  
> +static void __init process_chosen_node(const void *fdt, int node,
> +                                       const char *name,
> +                                       u32 address_cells, u32 size_cells)
> +{
> +    struct dt_mb_module *mod = &early_info.modules.module[MOD_INITRD];
> +    u32 start, end;
> +
> +    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);
> +
> +    if ( !start || !end || (start >= end) )
> +        return;
> +
> +    dt_printk("Initrd 0x%x-0x%x\n", start, end);
> +
> +    mod->start = start;
> +    mod->size = end - start;
> +
> +    early_info.modules.nr_mods = MAX(MOD_INITRD, early_info.modules.nr_mods);
> +}
> +
>  static int __init early_scan_node(const void *fdt,
>                                    int node, const char *name, int depth,
>                                    u32 address_cells, u32 size_cells,
> @@ -391,6 +414,8 @@ static int __init early_scan_node(const void *fdt,
>          process_memory_node(fdt, node, name, address_cells, size_cells);
>      else if ( device_tree_node_compatible(fdt, node, "xen,multiboot-module" ) )
>          process_multiboot_node(fdt, node, name, address_cells, size_cells);
> +    else if ( depth == 1 && device_tree_node_matches(fdt, node, "chosen") )
> +        process_chosen_node(fdt, node, name, address_cells, size_cells);
>  
>      return 0;
>  }

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

* Re: [PATCH 1/2] xen/arm: Add support to load initrd in dom0
  2013-09-25 15:15   ` Ian Campbell
@ 2013-09-25 15:23     ` Julien Grall
  2013-09-25 15:30       ` Ian Campbell
  0 siblings, 1 reply; 10+ messages in thread
From: Julien Grall @ 2013-09-25 15:23 UTC (permalink / raw)
  To: Ian Campbell; +Cc: stefano.stabellini, andre.przywara, patches, xen-devel

On 09/25/2013 04:15 PM, Ian Campbell wrote:
> On Mon, 2013-09-16 at 16:20 +0100, Julien Grall wrote:
>> @@ -806,7 +821,8 @@ static int prepare_dtb(struct domain *d, struct kernel_info *kinfo)
>>          goto err;
>>  
>>      /* Actual new size */
>> -    new_size = fdt_totalsize(kinfo->fdt);
>> +    initrd_len = early_info.modules.module[MOD_INITRD].size;
> 
> I think you need to check nr_modules here and in write_properties (which
> I already trimmed by mistake.
> 

Even if we check nr_modules, we can't assume MOD_INITRD is the last
modules in the array, so it's possible to have nr_modules greater than
MOD_INITRD but the module is not set. That's why I only choose to rely
on size.

> .size may not be initialised otherwise. (in reality it's probably
> in .bss not sure I want to rely on that though)

It's in .bss, on common/device_tree.c we already rely that this
structure is zeroed (nr_modules is never initialized to 0).


> 
>> +    new_size = fdt_totalsize(kinfo->fdt) + initrd_len;
>>  
>>      /*
>>       * DTB must be loaded such that it does not conflict with the
>> @@ -815,15 +831,20 @@ static int prepare_dtb(struct domain *d, struct kernel_info *kinfo)
>>       * the recommendation in Documentation/arm64/booting.txt is below
>>       * 512MB. Place at 128MB, (or, if we have less RAM, as high as
>>       * possible) in order to satisfy both.
>> +     * If the bootloader provides an initrd, it will be loaded just
>> +     * after the DTB.
>>       */
>>      end = kinfo->mem.bank[0].start + kinfo->mem.bank[0].size;
>>      end = MIN(kinfo->mem.bank[0].start + (128<<20) + new_size, end);
>>  
>> -    kinfo->dtb_paddr = end - fdt_totalsize(kinfo->fdt);
>> +    kinfo->initrd_paddr = end - initrd_len;
>> +    kinfo->initrd_paddr &= ~((1 << 20) - 1);
> 
> 1MB aligned, why not 2 like most things?

A mistake, I will fix it in the next patch series.

> 
>> +    kinfo->dtb_paddr = kinfo->initrd_paddr - fdt_totalsize(kinfo->fdt);
>>      /* Align the address to 2Mb. Linux only requires 4 byte alignment */
>>      kinfo->dtb_paddr &= ~((2 << 20) - 1);
>>  
>> -    if ( fdt_totalsize(kinfo->fdt) > end )
>> +    if ( new_size > (end - kinfo->mem.bank[0].size) )
>>      {
>>          printk(XENLOG_ERR "Not enough memory in the first bank for "
>>                 "the device tree.");
>> @@ -854,6 +875,61 @@ static void dtb_load(struct kernel_info *kinfo)
>>      xfree(kinfo->fdt);
>>  }
>>  
>> +static void initrd_load(struct kernel_info *kinfo)
>> +{
>> +    paddr_t load_addr = kinfo->initrd_paddr;
>> +    paddr_t paddr = early_info.modules.module[MOD_INITRD].start;
>> +    paddr_t len = early_info.modules.module[MOD_INITRD].size;
>> +    unsigned long offs;
>> +    int node;
>> +    int res;
>> +
>> +    if ( !len )
>> +        return;
>> +
>> +    printk("Loading dom0 initrd from %"PRIpaddr" to 0x%"PRIpaddr"-0x%"PRIpaddr"\n",
>> +           paddr, load_addr, load_addr + len);
>> +
>> +    /* Fix up linux,initrd-start and linux,initrd-end in /chosen */
>> +    node = fdt_path_offset(kinfo->fdt, "/chosen");
>> +    if ( node < 0 )
>> +        panic("Cannot find the /chosen node");
>> +
>> +    res = fdt_setprop_inplace_cell(kinfo->fdt, node, "linux,initrd-start",
>> +                                   load_addr);
>> +    if ( res )
>> +        panic("Cannot fix up \"linux,initrd-start\" property\n");
>> +
>> +    res = fdt_setprop_inplace_cell(kinfo->fdt, node, "linux,initrd-end",
>> +                                   load_addr + len);
>> +    if ( res )
>> +        panic("Cannot fix up \"linux,initrd-end\" property\n");
>> +
>> +    for ( offs = 0; offs < len; )
> 
> Can you refactor kernel_zimage_load into a more generic function which
> can be used here?

I will do.

-- 
Julien Grall

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

* Re: [PATCH 1/2] xen/arm: Add support to load initrd in dom0
  2013-09-25 15:23     ` Julien Grall
@ 2013-09-25 15:30       ` Ian Campbell
  2013-09-25 15:36         ` Julien Grall
  0 siblings, 1 reply; 10+ messages in thread
From: Ian Campbell @ 2013-09-25 15:30 UTC (permalink / raw)
  To: Julien Grall; +Cc: stefano.stabellini, andre.przywara, patches, xen-devel

On Wed, 2013-09-25 at 16:23 +0100, Julien Grall wrote:
> On 09/25/2013 04:15 PM, Ian Campbell wrote:
> > On Mon, 2013-09-16 at 16:20 +0100, Julien Grall wrote:
> >> @@ -806,7 +821,8 @@ static int prepare_dtb(struct domain *d, struct kernel_info *kinfo)
> >>          goto err;
> >>  
> >>      /* Actual new size */
> >> -    new_size = fdt_totalsize(kinfo->fdt);
> >> +    initrd_len = early_info.modules.module[MOD_INITRD].size;
> > 
> > I think you need to check nr_modules here and in write_properties (which
> > I already trimmed by mistake.
> > 
> 
> Even if we check nr_modules, we can't assume MOD_INITRD is the last
> modules in the array, so it's possible to have nr_modules greater than
> MOD_INITRD but the module is not set. That's why I only choose to rely
> on size.

Hrm that's true.

> > .size may not be initialised otherwise. (in reality it's probably
> > in .bss not sure I want to rely on that though)
> 
> It's in .bss, on common/device_tree.c we already rely that this
> structure is zeroed (nr_modules is never initialized to 0).

OK, I guess its fine then.

> 
> 
> > 
> >> +    new_size = fdt_totalsize(kinfo->fdt) + initrd_len;
> >>  
> >>      /*
> >>       * DTB must be loaded such that it does not conflict with the
> >> @@ -815,15 +831,20 @@ static int prepare_dtb(struct domain *d, struct kernel_info *kinfo)
> >>       * the recommendation in Documentation/arm64/booting.txt is below
> >>       * 512MB. Place at 128MB, (or, if we have less RAM, as high as
> >>       * possible) in order to satisfy both.
> >> +     * If the bootloader provides an initrd, it will be loaded just
> >> +     * after the DTB.
> >>       */
> >>      end = kinfo->mem.bank[0].start + kinfo->mem.bank[0].size;
> >>      end = MIN(kinfo->mem.bank[0].start + (128<<20) + new_size, end);
> >>  
> >> -    kinfo->dtb_paddr = end - fdt_totalsize(kinfo->fdt);
> >> +    kinfo->initrd_paddr = end - initrd_len;
> >> +    kinfo->initrd_paddr &= ~((1 << 20) - 1);
> > 
> > 1MB aligned, why not 2 like most things?
> 
> A mistake, I will fix it in the next patch series.

Actually, this extra alignment makes me think that maybe new_size needs
to account for the slop too? Does it?

Otherwise start + 128M + new_size doesn't make it such that
{dtb,initrd}_paddr are actually above 128M?

Ian.

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

* Re: [PATCH 1/2] xen/arm: Add support to load initrd in dom0
  2013-09-25 15:30       ` Ian Campbell
@ 2013-09-25 15:36         ` Julien Grall
  2013-09-25 15:44           ` Ian Campbell
  0 siblings, 1 reply; 10+ messages in thread
From: Julien Grall @ 2013-09-25 15:36 UTC (permalink / raw)
  To: Ian Campbell; +Cc: stefano.stabellini, andre.przywara, patches, xen-devel

On 09/25/2013 04:30 PM, Ian Campbell wrote:
> On Wed, 2013-09-25 at 16:23 +0100, Julien Grall wrote:
>> On 09/25/2013 04:15 PM, Ian Campbell wrote:
>>> On Mon, 2013-09-16 at 16:20 +0100, Julien Grall wrote:
>>>> @@ -806,7 +821,8 @@ static int prepare_dtb(struct domain *d, struct kernel_info *kinfo)
>>>>          goto err;
>>>>  
>>>>      /* Actual new size */
>>>> -    new_size = fdt_totalsize(kinfo->fdt);
>>>> +    initrd_len = early_info.modules.module[MOD_INITRD].size;
>>>
>>> I think you need to check nr_modules here and in write_properties (which
>>> I already trimmed by mistake.
>>>
>>
>> Even if we check nr_modules, we can't assume MOD_INITRD is the last
>> modules in the array, so it's possible to have nr_modules greater than
>> MOD_INITRD but the module is not set. That's why I only choose to rely
>> on size.
> 
> Hrm that's true.
> 
>>> .size may not be initialised otherwise. (in reality it's probably
>>> in .bss not sure I want to rely on that though)
>>
>> It's in .bss, on common/device_tree.c we already rely that this
>> structure is zeroed (nr_modules is never initialized to 0).
> 
> OK, I guess its fine then.
> 
>>
>>
>>>
>>>> +    new_size = fdt_totalsize(kinfo->fdt) + initrd_len;
>>>>  
>>>>      /*
>>>>       * DTB must be loaded such that it does not conflict with the
>>>> @@ -815,15 +831,20 @@ static int prepare_dtb(struct domain *d, struct kernel_info *kinfo)
>>>>       * the recommendation in Documentation/arm64/booting.txt is below
>>>>       * 512MB. Place at 128MB, (or, if we have less RAM, as high as
>>>>       * possible) in order to satisfy both.
>>>> +     * If the bootloader provides an initrd, it will be loaded just
>>>> +     * after the DTB.
>>>>       */
>>>>      end = kinfo->mem.bank[0].start + kinfo->mem.bank[0].size;
>>>>      end = MIN(kinfo->mem.bank[0].start + (128<<20) + new_size, end);
>>>>  
>>>> -    kinfo->dtb_paddr = end - fdt_totalsize(kinfo->fdt);
>>>> +    kinfo->initrd_paddr = end - initrd_len;
>>>> +    kinfo->initrd_paddr &= ~((1 << 20) - 1);
>>>
>>> 1MB aligned, why not 2 like most things?
>>
>> A mistake, I will fix it in the next patch series.
> 
> Actually, this extra alignment makes me think that maybe new_size needs
> to account for the slop too? Does it?


> Otherwise start + 128M + new_size doesn't make it such that
> {dtb,initrd}_paddr are actually above 128M?
> 

Right, what about?

#define ALIGN_2MB(size) ((len) + ((1 << 20 - 1)) & (~((1 << 20) - 1))
new_size = ALIGN_2MB(dtb_size) + ALIGN_2MB(initrd_size)

-- 
Julien Grall

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

* Re: [PATCH 1/2] xen/arm: Add support to load initrd in dom0
  2013-09-25 15:36         ` Julien Grall
@ 2013-09-25 15:44           ` Ian Campbell
  2013-09-25 15:48             ` Julien Grall
  0 siblings, 1 reply; 10+ messages in thread
From: Ian Campbell @ 2013-09-25 15:44 UTC (permalink / raw)
  To: Julien Grall; +Cc: patches, xen-devel, andre.przywara, stefano.stabellini

On Wed, 2013-09-25 at 16:36 +0100, Julien Grall wrote:

> Right, what about?
> 
> #define ALIGN_2MB(size) ((len) + ((1 << 20 - 1)) & (~((1 << 20) - 1))
> new_size = ALIGN_2MB(dtb_size) + ALIGN_2MB(initrd_size)

Hard to believe we don't have an ALIGN or ROUNDUP macro already in a
common header! How about we move the one from device_tree.c somewhere
more generic?

We could also add #define MB(x) ((x)<<20) alongside the existing GB(x)?

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

* Re: [PATCH 1/2] xen/arm: Add support to load initrd in dom0
  2013-09-25 15:44           ` Ian Campbell
@ 2013-09-25 15:48             ` Julien Grall
  0 siblings, 0 replies; 10+ messages in thread
From: Julien Grall @ 2013-09-25 15:48 UTC (permalink / raw)
  To: Ian Campbell; +Cc: patches, xen-devel, andre.przywara, stefano.stabellini

On 09/25/2013 04:44 PM, Ian Campbell wrote:
> On Wed, 2013-09-25 at 16:36 +0100, Julien Grall wrote:
> 
>> Right, what about?
>>
>> #define ALIGN_2MB(size) ((len) + ((1 << 20 - 1)) & (~((1 << 20) - 1))
>> new_size = ALIGN_2MB(dtb_size) + ALIGN_2MB(initrd_size)
> 
> Hard to believe we don't have an ALIGN or ROUNDUP macro already in a
> common header! How about we move the one from device_tree.c somewhere
> more generic?
> 
> We could also add #define MB(x) ((x)<<20) alongside the existing GB(x)?
> 

I will send a patch for the both macro and update this patch.

-- 
Julien Grall

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

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

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-09-16 15:20 [PATCH 0/2] ARM: Support initrd loading Julien Grall
2013-09-16 15:20 ` [PATCH 1/2] xen/arm: Add support to load initrd in dom0 Julien Grall
2013-09-25 15:15   ` Ian Campbell
2013-09-25 15:23     ` Julien Grall
2013-09-25 15:30       ` Ian Campbell
2013-09-25 15:36         ` Julien Grall
2013-09-25 15:44           ` Ian Campbell
2013-09-25 15:48             ` Julien Grall
2013-09-16 15:20 ` [PATCH 2/2] xen/dts: Support Linux initrd DT bindings Julien Grall
2013-09-25 15:16   ` Ian Campbell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).