Re: [PATCH v18 05/11] powerpc: Use common of_kexec_alloc_and_setup_fdt()

2021-02-15 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   |  30 ---
>  arch/powerpc/kexec/file_load.c| 132 +-
>  arch/powerpc/kexec/file_load_64.c |   3 +
>  4 files changed, 26 insertions(+), 140 deletions(-)

Reviewed-by: Thiago Jung Bauermann 

-- 
Thiago Jung Bauermann
IBM Linux Technology Center


[PATCH v18 05/11] powerpc: Use common of_kexec_alloc_and_setup_fdt()

2021-02-13 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   |  30 ---
 arch/powerpc/kexec/file_load.c| 132 +-
 arch/powerpc/kexec/file_load_64.c |   3 +
 4 files changed, 26 insertions(+), 140 deletions(-)

diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h
index 4d9b250cf1e6..f59946c6f9e6 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_load_addr;
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..87e34611f93d 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,15 +102,10 @@ 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,
+  fdt_totalsize(initial_boot_params));
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;
@@ -124,13 +119,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();
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 +144,15 @@ static void *elf64_load(struct kimage *image, char 
*kernel_buf,
kfree(modified_cmdline);
kexec_free_elf_info(_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 f7c31daf8a2e..af5a4724a70e 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) {
-   pr_err("Error creating /chosen.\n");
-