[PATCH v17 04/10] powerpc: Use common of_kexec_alloc_and_setup_fdt()

2021-02-09 Thread Lakshmi Ramasubramanian
From: Rob Herring 

The code for setting up the /chosen node in the device tree
and updating the memory reservation for the next kernel has been
moved to of_kexec_alloc_and_setup_fdt() defined in "drivers/of/kexec.c".

Use the common of_kexec_alloc_and_setup_fdt() to setup the device tree
and update the memory reservation for kexec for powerpc.

Signed-off-by: Rob Herring 
Signed-off-by: Lakshmi Ramasubramanian 
---
 arch/powerpc/include/asm/kexec.h  |   1 +
 arch/powerpc/kexec/elf_64.c   |  29 ---
 arch/powerpc/kexec/file_load.c| 132 +-
 arch/powerpc/kexec/file_load_64.c |   3 +
 4 files changed, 25 insertions(+), 140 deletions(-)

diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h
index dbf09d2f36d0..bdd0ddb9ac4d 100644
--- a/arch/powerpc/include/asm/kexec.h
+++ b/arch/powerpc/include/asm/kexec.h
@@ -111,6 +111,7 @@ struct kimage_arch {
unsigned long elf_headers_mem;
unsigned long elf_headers_sz;
void *elf_headers;
+   void *fdt;
 
 #ifdef CONFIG_IMA_KEXEC
phys_addr_t ima_buffer_addr;
diff --git a/arch/powerpc/kexec/elf_64.c b/arch/powerpc/kexec/elf_64.c
index d0e459bb2f05..bfabd06f99b1 100644
--- a/arch/powerpc/kexec/elf_64.c
+++ b/arch/powerpc/kexec/elf_64.c
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -29,7 +30,6 @@ static void *elf64_load(struct kimage *image, char 
*kernel_buf,
unsigned long cmdline_len)
 {
int ret;
-   unsigned int fdt_size;
unsigned long kernel_load_addr;
unsigned long initrd_load_addr = 0, fdt_load_addr;
void *fdt;
@@ -102,19 +102,13 @@ static void *elf64_load(struct kimage *image, char 
*kernel_buf,
pr_debug("Loaded initrd at 0x%lx\n", initrd_load_addr);
}
 
-   fdt_size = fdt_totalsize(initial_boot_params) * 2;
-   fdt = kmalloc(fdt_size, GFP_KERNEL);
+   fdt = of_kexec_alloc_and_setup_fdt(image, initrd_load_addr,
+  initrd_len, cmdline);
if (!fdt) {
pr_err("Not enough memory for the device tree.\n");
ret = -ENOMEM;
goto out;
}
-   ret = fdt_open_into(initial_boot_params, fdt, fdt_size);
-   if (ret < 0) {
-   pr_err("Error setting up the new device tree.\n");
-   ret = -EINVAL;
-   goto out;
-   }
 
ret = setup_new_fdt_ppc64(image, fdt, initrd_load_addr,
  initrd_len, cmdline);
@@ -124,13 +118,17 @@ static void *elf64_load(struct kimage *image, char 
*kernel_buf,
fdt_pack(fdt);
 
kbuf.buffer = fdt;
-   kbuf.bufsz = kbuf.memsz = fdt_size;
+   kbuf.bufsz = kbuf.memsz = fdt_totalsize(fdt);
kbuf.buf_align = PAGE_SIZE;
kbuf.top_down = true;
kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
ret = kexec_add_buffer(&kbuf);
if (ret)
goto out;
+
+   /* FDT will be freed in arch_kimage_file_post_load_cleanup */
+   image->arch.fdt = fdt;
+
fdt_load_addr = kbuf.mem;
 
pr_debug("Loaded device tree at 0x%lx\n", fdt_load_addr);
@@ -145,8 +143,15 @@ static void *elf64_load(struct kimage *image, char 
*kernel_buf,
kfree(modified_cmdline);
kexec_free_elf_info(&elf_info);
 
-   /* Make kimage_file_post_load_cleanup free the fdt buffer for us. */
-   return ret ? ERR_PTR(ret) : fdt;
+   /*
+* Once FDT buffer has been successfully passed to kexec_add_buffer(),
+* the FDT buffer address is saved in image->arch.fdt. In that case,
+* the memory cannot be freed here in case of any other error.
+*/
+   if (ret && !image->arch.fdt)
+   kvfree(fdt);
+
+   return ret ? ERR_PTR(ret) : NULL;
 }
 
 const struct kexec_file_ops kexec_elf64_ops = {
diff --git a/arch/powerpc/kexec/file_load.c b/arch/powerpc/kexec/file_load.c
index e452b11df631..d23e2969395c 100644
--- a/arch/powerpc/kexec/file_load.c
+++ b/arch/powerpc/kexec/file_load.c
@@ -156,135 +156,11 @@ int setup_new_fdt(const struct kimage *image, void *fdt,
  unsigned long initrd_load_addr, unsigned long initrd_len,
  const char *cmdline)
 {
-   int ret, chosen_node;
-   const void *prop;
-
-   /* Remove memory reservation for the current device tree. */
-   ret = delete_fdt_mem_rsv(fdt, __pa(initial_boot_params),
-fdt_totalsize(initial_boot_params));
-   if (ret == 0)
-   pr_debug("Removed old device tree reservation.\n");
-   else if (ret != -ENOENT)
-   return ret;
-
-   chosen_node = fdt_path_offset(fdt, "/chosen");
-   if (chosen_node == -FDT_ERR_NOTFOUND) {
-   chosen_node = fdt_add_subnode(fdt, fdt_path_offset(fdt, "/"),
- "chosen");
-   if (chosen_node < 0) {

Re: [PATCH v17 04/10] powerpc: Use common of_kexec_alloc_and_setup_fdt()

2021-02-10 Thread Thiago Jung Bauermann


Lakshmi Ramasubramanian  writes:

> From: Rob Herring 
>
> The code for setting up the /chosen node in the device tree
> and updating the memory reservation for the next kernel has been
> moved to of_kexec_alloc_and_setup_fdt() defined in "drivers/of/kexec.c".
>
> Use the common of_kexec_alloc_and_setup_fdt() to setup the device tree
> and update the memory reservation for kexec for powerpc.
>
> Signed-off-by: Rob Herring 
> Signed-off-by: Lakshmi Ramasubramanian 
> ---
>  arch/powerpc/include/asm/kexec.h  |   1 +
>  arch/powerpc/kexec/elf_64.c   |  29 ---
>  arch/powerpc/kexec/file_load.c| 132 +-
>  arch/powerpc/kexec/file_load_64.c |   3 +
>  4 files changed, 25 insertions(+), 140 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/kexec.h 
> b/arch/powerpc/include/asm/kexec.h
> index dbf09d2f36d0..bdd0ddb9ac4d 100644
> --- a/arch/powerpc/include/asm/kexec.h
> +++ b/arch/powerpc/include/asm/kexec.h
> @@ -111,6 +111,7 @@ struct kimage_arch {
>   unsigned long elf_headers_mem;
>   unsigned long elf_headers_sz;
>   void *elf_headers;
> + void *fdt;
>  
>  #ifdef CONFIG_IMA_KEXEC
>   phys_addr_t ima_buffer_addr;
> diff --git a/arch/powerpc/kexec/elf_64.c b/arch/powerpc/kexec/elf_64.c
> index d0e459bb2f05..bfabd06f99b1 100644
> --- a/arch/powerpc/kexec/elf_64.c
> +++ b/arch/powerpc/kexec/elf_64.c
> @@ -19,6 +19,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -29,7 +30,6 @@ static void *elf64_load(struct kimage *image, char 
> *kernel_buf,
>   unsigned long cmdline_len)
>  {
>   int ret;
> - unsigned int fdt_size;
>   unsigned long kernel_load_addr;
>   unsigned long initrd_load_addr = 0, fdt_load_addr;
>   void *fdt;
> @@ -102,19 +102,13 @@ static void *elf64_load(struct kimage *image, char 
> *kernel_buf,
>   pr_debug("Loaded initrd at 0x%lx\n", initrd_load_addr);
>   }
>  
> - fdt_size = fdt_totalsize(initial_boot_params) * 2;
> - fdt = kmalloc(fdt_size, GFP_KERNEL);
> + fdt = of_kexec_alloc_and_setup_fdt(image, initrd_load_addr,
> +initrd_len, cmdline);
>   if (!fdt) {
>   pr_err("Not enough memory for the device tree.\n");

This error string can be a bit misleading now, since
of_kexec_alloc_and_setup_fdt() can fail for reasons other than lack of
memory. I suggest changing it to the error string from fdt_open_into()
below:

pr_err("Error setting up the new device tree.\n");

With this change:

Reviewed-by: Thiago Jung Bauermann 

And also:

Tested-by: Thiago Jung Bauermann 

-- 
Thiago Jung Bauermann
IBM Linux Technology Center


Re: [PATCH v17 04/10] powerpc: Use common of_kexec_alloc_and_setup_fdt()

2021-02-10 Thread Lakshmi Ramasubramanian

On 2/10/21 5:42 PM, Thiago Jung Bauermann wrote:


Lakshmi Ramasubramanian  writes:


From: Rob Herring 

The code for setting up the /chosen node in the device tree
and updating the memory reservation for the next kernel has been
moved to of_kexec_alloc_and_setup_fdt() defined in "drivers/of/kexec.c".

Use the common of_kexec_alloc_and_setup_fdt() to setup the device tree
and update the memory reservation for kexec for powerpc.

Signed-off-by: Rob Herring 
Signed-off-by: Lakshmi Ramasubramanian 
---
  arch/powerpc/include/asm/kexec.h  |   1 +
  arch/powerpc/kexec/elf_64.c   |  29 ---
  arch/powerpc/kexec/file_load.c| 132 +-
  arch/powerpc/kexec/file_load_64.c |   3 +
  4 files changed, 25 insertions(+), 140 deletions(-)

diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h
index dbf09d2f36d0..bdd0ddb9ac4d 100644
--- a/arch/powerpc/include/asm/kexec.h
+++ b/arch/powerpc/include/asm/kexec.h
@@ -111,6 +111,7 @@ struct kimage_arch {
unsigned long elf_headers_mem;
unsigned long elf_headers_sz;
void *elf_headers;
+   void *fdt;
  
  #ifdef CONFIG_IMA_KEXEC

phys_addr_t ima_buffer_addr;
diff --git a/arch/powerpc/kexec/elf_64.c b/arch/powerpc/kexec/elf_64.c
index d0e459bb2f05..bfabd06f99b1 100644
--- a/arch/powerpc/kexec/elf_64.c
+++ b/arch/powerpc/kexec/elf_64.c
@@ -19,6 +19,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -29,7 +30,6 @@ static void *elf64_load(struct kimage *image, char 
*kernel_buf,
unsigned long cmdline_len)
  {
int ret;
-   unsigned int fdt_size;
unsigned long kernel_load_addr;
unsigned long initrd_load_addr = 0, fdt_load_addr;
void *fdt;
@@ -102,19 +102,13 @@ static void *elf64_load(struct kimage *image, char 
*kernel_buf,
pr_debug("Loaded initrd at 0x%lx\n", initrd_load_addr);
}
  
-	fdt_size = fdt_totalsize(initial_boot_params) * 2;

-   fdt = kmalloc(fdt_size, GFP_KERNEL);
+   fdt = of_kexec_alloc_and_setup_fdt(image, initrd_load_addr,
+  initrd_len, cmdline);
if (!fdt) {
pr_err("Not enough memory for the device tree.\n");


This error string can be a bit misleading now, since
of_kexec_alloc_and_setup_fdt() can fail for reasons other than lack of
memory. I suggest changing it to the error string from fdt_open_into()
below:

pr_err("Error setting up the new device tree.\n");

With this change:

Agreed - I will make this change.



Reviewed-by: Thiago Jung Bauermann 

And also:

Tested-by: Thiago Jung Bauermann 



Thanks a lot for your help Thiago.

 -lakshmi