On 12/03/2023 19:11:49, Sourabh Jain wrote: > Move update_cpus_node and get_crash_memory_ranges functions from > kexec/file_load.c to kexec/core_64.c to make these functions usable file_load_64.c > by other kexec compoenets. components > > Later in the series, these functions are utilized to do in-kernel update to > kexec segments on CPU/Memory hotplug events for both kexec_load and > kexec_file_load syscalls. > > No functional change intended. > FWIW, despite the 2 minor typos above, Reviewed-by: Laurent Dufour <laurent.dufour@xxxxxxxxxx> > Signed-off-by: Sourabh Jain <sourabhjain@xxxxxxxxxxxxx> > --- > arch/powerpc/include/asm/kexec.h | 6 ++ > arch/powerpc/kexec/core_64.c | 166 ++++++++++++++++++++++++++++++ > arch/powerpc/kexec/file_load_64.c | 162 ----------------------------- > 3 files changed, 172 insertions(+), 162 deletions(-) > > diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h > index a1ddba01e7d13..8090ad7d97d9d 100644 > --- a/arch/powerpc/include/asm/kexec.h > +++ b/arch/powerpc/include/asm/kexec.h > @@ -99,6 +99,12 @@ void relocate_new_kernel(unsigned long indirection_page, unsigned long reboot_co > > void kexec_copy_flush(struct kimage *image); > > +#ifdef CONFIG_PPC64 > +struct crash_mem; > +int update_cpus_node(void *fdt); > +int get_crash_memory_ranges(struct crash_mem **mem_ranges); > +#endif > + > #if defined(CONFIG_CRASH_DUMP) && defined(CONFIG_PPC_RTAS) > void crash_free_reserved_phys_range(unsigned long begin, unsigned long end); > #define crash_free_reserved_phys_range crash_free_reserved_phys_range > diff --git a/arch/powerpc/kexec/core_64.c b/arch/powerpc/kexec/core_64.c > index a79e28c91e2be..0b292f93a74cc 100644 > --- a/arch/powerpc/kexec/core_64.c > +++ b/arch/powerpc/kexec/core_64.c > @@ -17,6 +17,8 @@ > #include <linux/cpu.h> > #include <linux/hardirq.h> > #include <linux/of.h> > +#include <linux/libfdt.h> > +#include <linux/memblock.h> > > #include <asm/page.h> > #include <asm/current.h> > @@ -30,6 +32,8 @@ > #include <asm/hw_breakpoint.h> > #include <asm/svm.h> > #include <asm/ultravisor.h> > +#include <asm/kexec_ranges.h> > +#include <asm/crashdump-ppc64.h> > > int machine_kexec_prepare(struct kimage *image) > { > @@ -377,6 +381,168 @@ void default_machine_kexec(struct kimage *image) > /* NOTREACHED */ > } > > +/** > + * get_crash_memory_ranges - Get crash memory ranges. This list includes > + * first/crashing kernel's memory regions that > + * would be exported via an elfcore. > + * @mem_ranges: Range list to add the memory ranges to. > + * > + * Returns 0 on success, negative errno on error. > + */ > +int get_crash_memory_ranges(struct crash_mem **mem_ranges) > +{ > + phys_addr_t base, end; > + struct crash_mem *tmem; > + u64 i; > + int ret; > + > + for_each_mem_range(i, &base, &end) { > + u64 size = end - base; > + > + /* Skip backup memory region, which needs a separate entry */ > + if (base == BACKUP_SRC_START) { > + if (size > BACKUP_SRC_SIZE) { > + base = BACKUP_SRC_END + 1; > + size -= BACKUP_SRC_SIZE; > + } else > + continue; > + } > + > + ret = add_mem_range(mem_ranges, base, size); > + if (ret) > + goto out; > + > + /* Try merging adjacent ranges before reallocation attempt */ > + if ((*mem_ranges)->nr_ranges == (*mem_ranges)->max_nr_ranges) > + sort_memory_ranges(*mem_ranges, true); > + } > + > + /* Reallocate memory ranges if there is no space to split ranges */ > + tmem = *mem_ranges; > + if (tmem && (tmem->nr_ranges == tmem->max_nr_ranges)) { > + tmem = realloc_mem_ranges(mem_ranges); > + if (!tmem) > + goto out; > + } > + > + /* Exclude crashkernel region */ > + ret = crash_exclude_mem_range(tmem, crashk_res.start, crashk_res.end); > + if (ret) > + goto out; > + > + /* > + * FIXME: For now, stay in parity with kexec-tools but if RTAS/OPAL > + * regions are exported to save their context at the time of > + * crash, they should actually be backed up just like the > + * first 64K bytes of memory. > + */ > + ret = add_rtas_mem_range(mem_ranges); > + if (ret) > + goto out; > + > + ret = add_opal_mem_range(mem_ranges); > + if (ret) > + goto out; > + > + /* create a separate program header for the backup region */ > + ret = add_mem_range(mem_ranges, BACKUP_SRC_START, BACKUP_SRC_SIZE); > + if (ret) > + goto out; > + > + sort_memory_ranges(*mem_ranges, false); > +out: > + if (ret) > + pr_err("Failed to setup crash memory ranges\n"); > + return ret; > +} > + > +/** > + * add_node_props - Reads node properties from device node structure and add > + * them to fdt. > + * @fdt: Flattened device tree of the kernel > + * @node_offset: offset of the node to add a property at > + * @dn: device node pointer > + * > + * Returns 0 on success, negative errno on error. > + */ > +static int add_node_props(void *fdt, int node_offset, const struct device_node *dn) > +{ > + int ret = 0; > + struct property *pp; > + > + if (!dn) > + return -EINVAL; > + > + for_each_property_of_node(dn, pp) { > + ret = fdt_setprop(fdt, node_offset, pp->name, pp->value, pp->length); > + if (ret < 0) { > + pr_err("Unable to add %s property: %s\n", pp->name, fdt_strerror(ret)); > + return ret; > + } > + } > + return ret; > +} > + > +/** > + * update_cpus_node - Update cpus node of flattened device tree using of_root > + * device node. > + * @fdt: Flattened device tree of the kernel. > + * > + * Returns 0 on success, negative errno on error. > + */ > +int update_cpus_node(void *fdt) > +{ > + struct device_node *cpus_node, *dn; > + int cpus_offset, cpus_subnode_offset, ret = 0; > + > + cpus_offset = fdt_path_offset(fdt, "/cpus"); > + if (cpus_offset < 0 && cpus_offset != -FDT_ERR_NOTFOUND) { > + pr_err("Malformed device tree: error reading /cpus node: %s\n", > + fdt_strerror(cpus_offset)); > + return cpus_offset; > + } > + > + if (cpus_offset > 0) { > + ret = fdt_del_node(fdt, cpus_offset); > + if (ret < 0) { > + pr_err("Error deleting /cpus node: %s\n", fdt_strerror(ret)); > + return -EINVAL; > + } > + } > + > + /* Add cpus node to fdt */ > + cpus_offset = fdt_add_subnode(fdt, fdt_path_offset(fdt, "/"), "cpus"); > + if (cpus_offset < 0) { > + pr_err("Error creating /cpus node: %s\n", fdt_strerror(cpus_offset)); > + return -EINVAL; > + } > + > + /* Add cpus node properties */ > + cpus_node = of_find_node_by_path("/cpus"); > + ret = add_node_props(fdt, cpus_offset, cpus_node); > + of_node_put(cpus_node); > + if (ret < 0) > + return ret; > + > + /* Loop through all subnodes of cpus and add them to fdt */ > + for_each_node_by_type(dn, "cpu") { > + cpus_subnode_offset = fdt_add_subnode(fdt, cpus_offset, dn->full_name); > + if (cpus_subnode_offset < 0) { > + pr_err("Unable to add %s subnode: %s\n", dn->full_name, > + fdt_strerror(cpus_subnode_offset)); > + ret = cpus_subnode_offset; > + goto out; > + } > + > + ret = add_node_props(fdt, cpus_subnode_offset, dn); > + if (ret < 0) > + goto out; > + } > +out: > + of_node_put(dn); > + return ret; > +} > + > #ifdef CONFIG_PPC_64S_HASH_MMU > /* Values we need to export to the second kernel via the device tree. */ > static unsigned long htab_base; > diff --git a/arch/powerpc/kexec/file_load_64.c b/arch/powerpc/kexec/file_load_64.c > index 110d28bede2a7..5b0b3f61e0e72 100644 > --- a/arch/powerpc/kexec/file_load_64.c > +++ b/arch/powerpc/kexec/file_load_64.c > @@ -133,81 +133,6 @@ static int get_usable_memory_ranges(struct crash_mem **mem_ranges) > return ret; > } > > -/** > - * get_crash_memory_ranges - Get crash memory ranges. This list includes > - * first/crashing kernel's memory regions that > - * would be exported via an elfcore. > - * @mem_ranges: Range list to add the memory ranges to. > - * > - * Returns 0 on success, negative errno on error. > - */ > -static int get_crash_memory_ranges(struct crash_mem **mem_ranges) > -{ > - phys_addr_t base, end; > - struct crash_mem *tmem; > - u64 i; > - int ret; > - > - for_each_mem_range(i, &base, &end) { > - u64 size = end - base; > - > - /* Skip backup memory region, which needs a separate entry */ > - if (base == BACKUP_SRC_START) { > - if (size > BACKUP_SRC_SIZE) { > - base = BACKUP_SRC_END + 1; > - size -= BACKUP_SRC_SIZE; > - } else > - continue; > - } > - > - ret = add_mem_range(mem_ranges, base, size); > - if (ret) > - goto out; > - > - /* Try merging adjacent ranges before reallocation attempt */ > - if ((*mem_ranges)->nr_ranges == (*mem_ranges)->max_nr_ranges) > - sort_memory_ranges(*mem_ranges, true); > - } > - > - /* Reallocate memory ranges if there is no space to split ranges */ > - tmem = *mem_ranges; > - if (tmem && (tmem->nr_ranges == tmem->max_nr_ranges)) { > - tmem = realloc_mem_ranges(mem_ranges); > - if (!tmem) > - goto out; > - } > - > - /* Exclude crashkernel region */ > - ret = crash_exclude_mem_range(tmem, crashk_res.start, crashk_res.end); > - if (ret) > - goto out; > - > - /* > - * FIXME: For now, stay in parity with kexec-tools but if RTAS/OPAL > - * regions are exported to save their context at the time of > - * crash, they should actually be backed up just like the > - * first 64K bytes of memory. > - */ > - ret = add_rtas_mem_range(mem_ranges); > - if (ret) > - goto out; > - > - ret = add_opal_mem_range(mem_ranges); > - if (ret) > - goto out; > - > - /* create a separate program header for the backup region */ > - ret = add_mem_range(mem_ranges, BACKUP_SRC_START, BACKUP_SRC_SIZE); > - if (ret) > - goto out; > - > - sort_memory_ranges(*mem_ranges, false); > -out: > - if (ret) > - pr_err("Failed to setup crash memory ranges\n"); > - return ret; > -} > - > /** > * get_reserved_memory_ranges - Get reserve memory ranges. This list includes > * memory regions that should be added to the > @@ -1018,93 +943,6 @@ unsigned int kexec_extra_fdt_size_ppc64(struct kimage *image) > return extra_size; > } > > -/** > - * add_node_props - Reads node properties from device node structure and add > - * them to fdt. > - * @fdt: Flattened device tree of the kernel > - * @node_offset: offset of the node to add a property at > - * @dn: device node pointer > - * > - * Returns 0 on success, negative errno on error. > - */ > -static int add_node_props(void *fdt, int node_offset, const struct device_node *dn) > -{ > - int ret = 0; > - struct property *pp; > - > - if (!dn) > - return -EINVAL; > - > - for_each_property_of_node(dn, pp) { > - ret = fdt_setprop(fdt, node_offset, pp->name, pp->value, pp->length); > - if (ret < 0) { > - pr_err("Unable to add %s property: %s\n", pp->name, fdt_strerror(ret)); > - return ret; > - } > - } > - return ret; > -} > - > -/** > - * update_cpus_node - Update cpus node of flattened device tree using of_root > - * device node. > - * @fdt: Flattened device tree of the kernel. > - * > - * Returns 0 on success, negative errno on error. > - */ > -static int update_cpus_node(void *fdt) > -{ > - struct device_node *cpus_node, *dn; > - int cpus_offset, cpus_subnode_offset, ret = 0; > - > - cpus_offset = fdt_path_offset(fdt, "/cpus"); > - if (cpus_offset < 0 && cpus_offset != -FDT_ERR_NOTFOUND) { > - pr_err("Malformed device tree: error reading /cpus node: %s\n", > - fdt_strerror(cpus_offset)); > - return cpus_offset; > - } > - > - if (cpus_offset > 0) { > - ret = fdt_del_node(fdt, cpus_offset); > - if (ret < 0) { > - pr_err("Error deleting /cpus node: %s\n", fdt_strerror(ret)); > - return -EINVAL; > - } > - } > - > - /* Add cpus node to fdt */ > - cpus_offset = fdt_add_subnode(fdt, fdt_path_offset(fdt, "/"), "cpus"); > - if (cpus_offset < 0) { > - pr_err("Error creating /cpus node: %s\n", fdt_strerror(cpus_offset)); > - return -EINVAL; > - } > - > - /* Add cpus node properties */ > - cpus_node = of_find_node_by_path("/cpus"); > - ret = add_node_props(fdt, cpus_offset, cpus_node); > - of_node_put(cpus_node); > - if (ret < 0) > - return ret; > - > - /* Loop through all subnodes of cpus and add them to fdt */ > - for_each_node_by_type(dn, "cpu") { > - cpus_subnode_offset = fdt_add_subnode(fdt, cpus_offset, dn->full_name); > - if (cpus_subnode_offset < 0) { > - pr_err("Unable to add %s subnode: %s\n", dn->full_name, > - fdt_strerror(cpus_subnode_offset)); > - ret = cpus_subnode_offset; > - goto out; > - } > - > - ret = add_node_props(fdt, cpus_subnode_offset, dn); > - if (ret < 0) > - goto out; > - } > -out: > - of_node_put(dn); > - return ret; > -} > - > static int copy_property(void *fdt, int node_offset, const struct device_node *dn, > const char *propname) > { _______________________________________________ kexec mailing list kexec@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/kexec