Re: [PATCH v2 2/6] powerpc: kexec_file: Add buffer hand-over support for the next kernel

2016-08-23 Thread Thiago Jung Bauermann
Am Montag, 22 August 2016, 15:22:00 schrieb Dave Young:
> On 08/22/16 at 12:38am, Thiago Jung Bauermann wrote:
> > Am Montag, 22 August 2016, 11:21:35 schrieb Dave Young:
> > > On 08/13/16 at 12:18am, Thiago Jung Bauermann wrote:
> > > > diff --git a/arch/powerpc/kernel/machine_kexec_64.c
> > > > b/arch/powerpc/kernel/machine_kexec_64.c index
> > > > a484a6346146..190c652e49b7 100644
> > > > --- a/arch/powerpc/kernel/machine_kexec_64.c
> > > > +++ b/arch/powerpc/kernel/machine_kexec_64.c
> > > > @@ -490,6 +490,60 @@ int arch_kimage_file_post_load_cleanup(struct
> > > > kimage *image)>
> > > > 
> > > > return image->fops->cleanup(image->image_loader_data);
> > > >  
> > > >  }
> > > > 
> > > > +bool kexec_can_hand_over_buffer(void)
> > > > +{
> > > > +   return true;
> > > > +}
> > > > +
> > > > +int arch_kexec_add_handover_buffer(struct kimage *image,
> > > > +  unsigned long load_addr, unsigned 
long
> > 
> > size)
> > 
> > > > +{
> > > > +   image->arch.handover_buffer_addr = load_addr;
> > > > +   image->arch.handover_buffer_size = size;
> > > > +
> > > > +   return 0;
> > > > +}
> > > > +
> > > > +int kexec_get_handover_buffer(void **addr, unsigned long *size)
> > > > +{
> > > > +   int ret;
> > > > +   u64 start_addr, end_addr;
> > > > +
> > > > +   ret = of_property_read_u64(of_chosen,
> > > > +  "linux,kexec-handover-buffer-
start",
> > > > +  _addr);
> > > > +   if (ret == -EINVAL)
> > > > +   return -ENOENT;
> > > > +   else if (ret)
> > > > +   return -EINVAL;
> > > > +
> > > > +   ret = of_property_read_u64(of_chosen,
> > > > "linux,kexec-handover-buffer-end", +
> > 
> > _addr);
> > 
> > > > +   if (ret == -EINVAL)
> > > > +   return -ENOENT;
> > > > +   else if (ret)
> > > > +   return -EINVAL;
> > > > +
> > > > +   *addr =  __va(start_addr);
> > > > +   /* -end is the first address after the buffer. */
> > > > +   *size = end_addr - start_addr;
> > > > +
> > > > +   return 0;
> > > > +}
> > > 
> > > This depends on dtb, so if IMA want to extend it to arches like x86 in
> > > the future you will have to think about other way to pass it.
> > > 
> > > How about think about a general way now?
> > 
> > The only general way I can think of is by adding a kernel command line
> > parameter which the first kernel would pass to the second kernel, but
> > IMHO that is ugly, because such parameter wouldn't be useful to a user,
> > and it would also be something that, from the perspective of the user,
> > would magically appear in the kernel command line of the second
> > kernel...
> Sorry I just brought up the question, actually I have no idea either.
> Maybe we have to do this with arch specific ways..

Actually, I don't think it's possible to avoid arch-specific code because 
the first kernel has to put the buffer memory region in a reserved memory 
map, and that is arch-specific.

On powerpc, this is done by adding it to the device tree memory reservation 
map. On x86, I believe this would be done added to the e820 map.

-- 
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [PATCH v2 2/6] powerpc: kexec_file: Add buffer hand-over support for the next kernel

2016-08-22 Thread Dave Young
On 08/22/16 at 12:38am, Thiago Jung Bauermann wrote:
> Am Montag, 22 August 2016, 11:21:35 schrieb Dave Young:
> > On 08/13/16 at 12:18am, Thiago Jung Bauermann wrote:
> > > diff --git a/arch/powerpc/kernel/machine_kexec_64.c
> > > b/arch/powerpc/kernel/machine_kexec_64.c index
> > > a484a6346146..190c652e49b7 100644
> > > --- a/arch/powerpc/kernel/machine_kexec_64.c
> > > +++ b/arch/powerpc/kernel/machine_kexec_64.c
> > > @@ -490,6 +490,60 @@ int arch_kimage_file_post_load_cleanup(struct
> > > kimage *image)> 
> > >   return image->fops->cleanup(image->image_loader_data);
> > >  
> > >  }
> > > 
> > > +bool kexec_can_hand_over_buffer(void)
> > > +{
> > > + return true;
> > > +}
> > > +
> > > +int arch_kexec_add_handover_buffer(struct kimage *image,
> > > +unsigned long load_addr, unsigned long 
> size)
> > > +{
> > > + image->arch.handover_buffer_addr = load_addr;
> > > + image->arch.handover_buffer_size = size;
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +int kexec_get_handover_buffer(void **addr, unsigned long *size)
> > > +{
> > > + int ret;
> > > + u64 start_addr, end_addr;
> > > +
> > > + ret = of_property_read_u64(of_chosen,
> > > +"linux,kexec-handover-buffer-start",
> > > +_addr);
> > > + if (ret == -EINVAL)
> > > + return -ENOENT;
> > > + else if (ret)
> > > + return -EINVAL;
> > > +
> > > + ret = of_property_read_u64(of_chosen,
> > > "linux,kexec-handover-buffer-end", + 
> _addr);
> > > + if (ret == -EINVAL)
> > > + return -ENOENT;
> > > + else if (ret)
> > > + return -EINVAL;
> > > +
> > > + *addr =  __va(start_addr);
> > > + /* -end is the first address after the buffer. */
> > > + *size = end_addr - start_addr;
> > > +
> > > + return 0;
> > > +}
> > 
> > This depends on dtb, so if IMA want to extend it to arches like x86 in
> > the future you will have to think about other way to pass it.
> > 
> > How about think about a general way now?
> 
> The only general way I can think of is by adding a kernel command line 
> parameter which the first kernel would pass to the second kernel, but IMHO 
> that is ugly, because such parameter wouldn't be useful to a user, and it 
> would also be something that, from the perspective of the user, would 
> magically appear in the kernel command line of the second kernel...

Sorry I just brought up the question, actually I have no idea either.
Maybe we have to do this with arch specific ways..

Thanks
Dave

___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [PATCH v2 2/6] powerpc: kexec_file: Add buffer hand-over support for the next kernel

2016-08-22 Thread Thiago Jung Bauermann
Am Montag, 22 August 2016, 11:21:35 schrieb Dave Young:
> On 08/13/16 at 12:18am, Thiago Jung Bauermann wrote:
> > diff --git a/arch/powerpc/kernel/machine_kexec_64.c
> > b/arch/powerpc/kernel/machine_kexec_64.c index
> > a484a6346146..190c652e49b7 100644
> > --- a/arch/powerpc/kernel/machine_kexec_64.c
> > +++ b/arch/powerpc/kernel/machine_kexec_64.c
> > @@ -490,6 +490,60 @@ int arch_kimage_file_post_load_cleanup(struct
> > kimage *image)> 
> > return image->fops->cleanup(image->image_loader_data);
> >  
> >  }
> > 
> > +bool kexec_can_hand_over_buffer(void)
> > +{
> > +   return true;
> > +}
> > +
> > +int arch_kexec_add_handover_buffer(struct kimage *image,
> > +  unsigned long load_addr, unsigned long 
size)
> > +{
> > +   image->arch.handover_buffer_addr = load_addr;
> > +   image->arch.handover_buffer_size = size;
> > +
> > +   return 0;
> > +}
> > +
> > +int kexec_get_handover_buffer(void **addr, unsigned long *size)
> > +{
> > +   int ret;
> > +   u64 start_addr, end_addr;
> > +
> > +   ret = of_property_read_u64(of_chosen,
> > +  "linux,kexec-handover-buffer-start",
> > +  _addr);
> > +   if (ret == -EINVAL)
> > +   return -ENOENT;
> > +   else if (ret)
> > +   return -EINVAL;
> > +
> > +   ret = of_property_read_u64(of_chosen,
> > "linux,kexec-handover-buffer-end", +   
_addr);
> > +   if (ret == -EINVAL)
> > +   return -ENOENT;
> > +   else if (ret)
> > +   return -EINVAL;
> > +
> > +   *addr =  __va(start_addr);
> > +   /* -end is the first address after the buffer. */
> > +   *size = end_addr - start_addr;
> > +
> > +   return 0;
> > +}
> 
> This depends on dtb, so if IMA want to extend it to arches like x86 in
> the future you will have to think about other way to pass it.
> 
> How about think about a general way now?

The only general way I can think of is by adding a kernel command line 
parameter which the first kernel would pass to the second kernel, but IMHO 
that is ugly, because such parameter wouldn't be useful to a user, and it 
would also be something that, from the perspective of the user, would 
magically appear in the kernel command line of the second kernel...

-- 
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [PATCH v2 2/6] powerpc: kexec_file: Add buffer hand-over support for the next kernel

2016-08-22 Thread Dave Young
On 08/13/16 at 12:18am, Thiago Jung Bauermann wrote:
> The buffer hand-over mechanism allows the currently running kernel to pass
> data to kernel that will be kexec'd via a kexec segment. The second kernel
> can check whether the previous kernel sent data and retrieve it.
> 
> This is the architecture-specific part.
> 
> Signed-off-by: Thiago Jung Bauermann 
> ---
>  arch/powerpc/include/asm/kexec.h   |  12 +++-
>  arch/powerpc/kernel/kexec_elf_64.c |   2 +-
>  arch/powerpc/kernel/machine_kexec_64.c | 114 
> +++--
>  3 files changed, 120 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/kexec.h 
> b/arch/powerpc/include/asm/kexec.h
> index 31bc64e07c8f..b20738df26f8 100644
> --- a/arch/powerpc/include/asm/kexec.h
> +++ b/arch/powerpc/include/asm/kexec.h
> @@ -92,12 +92,20 @@ static inline bool kdump_in_progress(void)
>  }
>  
>  #ifdef CONFIG_KEXEC_FILE
> +#define ARCH_HAS_KIMAGE_ARCH
> +
> +struct kimage_arch {
> + phys_addr_t handover_buffer_addr;
> + unsigned long handover_buffer_size;
> +};
> +
>  int setup_purgatory(struct kimage *image, const void *slave_code,
>   const void *fdt, unsigned long kernel_load_addr,
>   unsigned long fdt_load_addr, unsigned long stack_top,
>   int debug);
> -int setup_new_fdt(void *fdt, unsigned long initrd_load_addr,
> -   unsigned long initrd_len, const char *cmdline);
> +int setup_new_fdt(const struct kimage *image, void *fdt,
> +   unsigned long initrd_load_addr, unsigned long initrd_len,
> +   const char *cmdline);
>  bool find_debug_console(const void *fdt, int chosen_node);
>  int merge_partial_dtb(void *to, const void *from);
>  #endif /* CONFIG_KEXEC_FILE */
> diff --git a/arch/powerpc/kernel/kexec_elf_64.c 
> b/arch/powerpc/kernel/kexec_elf_64.c
> index 1b902ad66e2a..22afc7b5ee73 100644
> --- a/arch/powerpc/kernel/kexec_elf_64.c
> +++ b/arch/powerpc/kernel/kexec_elf_64.c
> @@ -219,7 +219,7 @@ void *elf64_load(struct kimage *image, char *kernel_buf,
>   }
>   }
>  
> - ret = setup_new_fdt(fdt, initrd_load_addr, initrd_len, cmdline);
> + ret = setup_new_fdt(image, fdt, initrd_load_addr, initrd_len, cmdline);
>   if (ret)
>   goto out;
>  
> diff --git a/arch/powerpc/kernel/machine_kexec_64.c 
> b/arch/powerpc/kernel/machine_kexec_64.c
> index a484a6346146..190c652e49b7 100644
> --- a/arch/powerpc/kernel/machine_kexec_64.c
> +++ b/arch/powerpc/kernel/machine_kexec_64.c
> @@ -490,6 +490,60 @@ int arch_kimage_file_post_load_cleanup(struct kimage 
> *image)
>   return image->fops->cleanup(image->image_loader_data);
>  }
>  
> +bool kexec_can_hand_over_buffer(void)
> +{
> + return true;
> +}
> +
> +int arch_kexec_add_handover_buffer(struct kimage *image,
> +unsigned long load_addr, unsigned long size)
> +{
> + image->arch.handover_buffer_addr = load_addr;
> + image->arch.handover_buffer_size = size;
> +
> + return 0;
> +}
> +
> +int kexec_get_handover_buffer(void **addr, unsigned long *size)
> +{
> + int ret;
> + u64 start_addr, end_addr;
> +
> + ret = of_property_read_u64(of_chosen,
> +"linux,kexec-handover-buffer-start",
> +_addr);
> + if (ret == -EINVAL)
> + return -ENOENT;
> + else if (ret)
> + return -EINVAL;
> +
> + ret = of_property_read_u64(of_chosen, "linux,kexec-handover-buffer-end",
> +_addr);
> + if (ret == -EINVAL)
> + return -ENOENT;
> + else if (ret)
> + return -EINVAL;
> +
> + *addr =  __va(start_addr);
> + /* -end is the first address after the buffer. */
> + *size = end_addr - start_addr;
> +
> + return 0;
> +}

This depends on dtb, so if IMA want to extend it to arches like x86 in
the future you will have to think about other way to pass it.

How about think about a general way now?

> +
> +int kexec_free_handover_buffer(void)
> +{
> + int ret;
> + void *addr;
> + unsigned long size;
> +
> + ret = kexec_get_handover_buffer(, );
> + if (ret)
> + return ret;
> +
> + return memblock_free((phys_addr_t) addr, size);
> +}
> +
>  /**
>   * arch_kexec_walk_mem() - call func(data) for each unreserved memory block
>   * @kbuf:Context info for the search. Also passed to @func.
> @@ -687,9 +741,52 @@ int setup_purgatory(struct kimage *image, const void 
> *slave_code,
>   return 0;
>  }
>  
> -/*
> - * setup_new_fdt() - modify /chosen and memory reservation for the next 
> kernel
> - * @fdt:
> +/**
> + * setup_handover_buffer() - add properties and reservation for the handover 
> buffer
> + * @image:   kexec image being loaded.
> + * @fdt: Flattened device tree for the next kernel.
> + * @chosen_node: Offset to the chosen node.
> + *
> + 

[PATCH v2 2/6] powerpc: kexec_file: Add buffer hand-over support for the next kernel

2016-08-15 Thread Thiago Jung Bauermann
The buffer hand-over mechanism allows the currently running kernel to pass
data to kernel that will be kexec'd via a kexec segment. The second kernel
can check whether the previous kernel sent data and retrieve it.

This is the architecture-specific part.

Signed-off-by: Thiago Jung Bauermann 
---
 arch/powerpc/include/asm/kexec.h   |  12 +++-
 arch/powerpc/kernel/kexec_elf_64.c |   2 +-
 arch/powerpc/kernel/machine_kexec_64.c | 114 +++--
 3 files changed, 120 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h
index 31bc64e07c8f..b20738df26f8 100644
--- a/arch/powerpc/include/asm/kexec.h
+++ b/arch/powerpc/include/asm/kexec.h
@@ -92,12 +92,20 @@ static inline bool kdump_in_progress(void)
 }
 
 #ifdef CONFIG_KEXEC_FILE
+#define ARCH_HAS_KIMAGE_ARCH
+
+struct kimage_arch {
+   phys_addr_t handover_buffer_addr;
+   unsigned long handover_buffer_size;
+};
+
 int setup_purgatory(struct kimage *image, const void *slave_code,
const void *fdt, unsigned long kernel_load_addr,
unsigned long fdt_load_addr, unsigned long stack_top,
int debug);
-int setup_new_fdt(void *fdt, unsigned long initrd_load_addr,
- unsigned long initrd_len, const char *cmdline);
+int setup_new_fdt(const struct kimage *image, void *fdt,
+ unsigned long initrd_load_addr, unsigned long initrd_len,
+ const char *cmdline);
 bool find_debug_console(const void *fdt, int chosen_node);
 int merge_partial_dtb(void *to, const void *from);
 #endif /* CONFIG_KEXEC_FILE */
diff --git a/arch/powerpc/kernel/kexec_elf_64.c 
b/arch/powerpc/kernel/kexec_elf_64.c
index 1b902ad66e2a..22afc7b5ee73 100644
--- a/arch/powerpc/kernel/kexec_elf_64.c
+++ b/arch/powerpc/kernel/kexec_elf_64.c
@@ -219,7 +219,7 @@ void *elf64_load(struct kimage *image, char *kernel_buf,
}
}
 
-   ret = setup_new_fdt(fdt, initrd_load_addr, initrd_len, cmdline);
+   ret = setup_new_fdt(image, fdt, initrd_load_addr, initrd_len, cmdline);
if (ret)
goto out;
 
diff --git a/arch/powerpc/kernel/machine_kexec_64.c 
b/arch/powerpc/kernel/machine_kexec_64.c
index a484a6346146..190c652e49b7 100644
--- a/arch/powerpc/kernel/machine_kexec_64.c
+++ b/arch/powerpc/kernel/machine_kexec_64.c
@@ -490,6 +490,60 @@ int arch_kimage_file_post_load_cleanup(struct kimage 
*image)
return image->fops->cleanup(image->image_loader_data);
 }
 
+bool kexec_can_hand_over_buffer(void)
+{
+   return true;
+}
+
+int arch_kexec_add_handover_buffer(struct kimage *image,
+  unsigned long load_addr, unsigned long size)
+{
+   image->arch.handover_buffer_addr = load_addr;
+   image->arch.handover_buffer_size = size;
+
+   return 0;
+}
+
+int kexec_get_handover_buffer(void **addr, unsigned long *size)
+{
+   int ret;
+   u64 start_addr, end_addr;
+
+   ret = of_property_read_u64(of_chosen,
+  "linux,kexec-handover-buffer-start",
+  _addr);
+   if (ret == -EINVAL)
+   return -ENOENT;
+   else if (ret)
+   return -EINVAL;
+
+   ret = of_property_read_u64(of_chosen, "linux,kexec-handover-buffer-end",
+  _addr);
+   if (ret == -EINVAL)
+   return -ENOENT;
+   else if (ret)
+   return -EINVAL;
+
+   *addr =  __va(start_addr);
+   /* -end is the first address after the buffer. */
+   *size = end_addr - start_addr;
+
+   return 0;
+}
+
+int kexec_free_handover_buffer(void)
+{
+   int ret;
+   void *addr;
+   unsigned long size;
+
+   ret = kexec_get_handover_buffer(, );
+   if (ret)
+   return ret;
+
+   return memblock_free((phys_addr_t) addr, size);
+}
+
 /**
  * arch_kexec_walk_mem() - call func(data) for each unreserved memory block
  * @kbuf:  Context info for the search. Also passed to @func.
@@ -687,9 +741,52 @@ int setup_purgatory(struct kimage *image, const void 
*slave_code,
return 0;
 }
 
-/*
- * setup_new_fdt() - modify /chosen and memory reservation for the next kernel
- * @fdt:
+/**
+ * setup_handover_buffer() - add properties and reservation for the handover 
buffer
+ * @image: kexec image being loaded.
+ * @fdt:   Flattened device tree for the next kernel.
+ * @chosen_node:   Offset to the chosen node.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+static int setup_handover_buffer(const struct kimage *image, void *fdt,
+int chosen_node)
+{
+   int ret;
+
+   if (image->arch.handover_buffer_addr == 0)
+   return 0;
+
+   ret = fdt_setprop_u64(fdt, chosen_node,
+ "linux,kexec-handover-buffer-start",
+