The is the preparative patch for RISC-V kexec Image file support. Separate the elf_riscv_find_pbase() function out to allow kernel_load syscall load Image binary file. Signed-off-by: Song Shuai <songshuaishuai@xxxxxxxxxxx> --- kexec/arch/riscv/kexec-elf-riscv.c | 72 +----------------------------- kexec/arch/riscv/kexec-riscv.c | 55 +++++++++++++++++++++++ kexec/arch/riscv/kexec-riscv.h | 13 ++++++ 3 files changed, 69 insertions(+), 71 deletions(-) diff --git a/kexec/arch/riscv/kexec-elf-riscv.c b/kexec/arch/riscv/kexec-elf-riscv.c index 2b9f66d..49deedb 100644 --- a/kexec/arch/riscv/kexec-elf-riscv.c +++ b/kexec/arch/riscv/kexec-elf-riscv.c @@ -12,76 +12,6 @@ #include "kexec-syscall.h" /* For KEXEC_ON_CRASH */ #include "kexec-riscv.h" - -/*********\ -* HELPERS * -\*********/ - -/* - * Go through the available physical memory regions and - * find one that can hold an image of the specified size. - * Note: This is called after get_memory_ranges so - * info->memory_range[] should be populated. Also note that - * memory ranges are sorted, so we'll return the first region - * that's big enough for holding the image. - */ -static int elf_riscv_find_pbase(struct kexec_info *info, off_t *addr, - off_t size) -{ - int i = 0; - off_t start = 0; - off_t end = 0; - int ret = 0; - - /* - * If this image is for a crash kernel, use the region - * the primary kernel has already reserved for us. - */ - if (info->kexec_flags & KEXEC_ON_CRASH) { - ret = get_crash_kernel_load_range((uint64_t *) &start, - (uint64_t *) &end); - if (!ret) { - /* - * Kernel should be aligned to the nearest - * hugepage (2MB for RV64, 4MB for RV32). - */ -#if __riscv_xlen == 64 - start = _ALIGN_UP(start, 0x200000); -#else - start = _ALIGN_UP(start, 0x400000); -#endif - if (end > start && ((end - start) >= size)) { - *addr = start; - return 0; - } - - return -EFBIG; - } else - return ENOCRASHKERNEL; - } - - for (i = 0; i < info->memory_ranges; i++) { - if (info->memory_range[i].type != RANGE_RAM) - continue; - - start = info->memory_range[i].start; - end = info->memory_range[i].end; - -#if __riscv_xlen == 64 - start = _ALIGN_UP(start, 0x200000); -#else - start = _ALIGN_UP(start, 0x400000); -#endif - - if (end > start && ((end - start) >= size)) { - *addr = start; - return 0; - } - } - - return -EFBIG; -} - /**************\ * ENTRY POINTS * \**************/ @@ -182,7 +112,7 @@ int elf_riscv_load(int argc, char **argv, const char *buf, off_t len, kernel_size / 1024, old_base_addr, old_start_addr); /* Get a continuous physical region that can hold the kernel */ - ret = elf_riscv_find_pbase(info, &new_base_addr, kernel_size); + ret = elf_riscv_find_pbase(info, &new_base_addr, kernel_size, KERNEL_ALIGN); if (ret < 0) { fprintf(stderr, "Could not find a memory region for the " "provided ELF image\n"); diff --git a/kexec/arch/riscv/kexec-riscv.c b/kexec/arch/riscv/kexec-riscv.c index 4500aa9..74feef2 100644 --- a/kexec/arch/riscv/kexec-riscv.c +++ b/kexec/arch/riscv/kexec-riscv.c @@ -51,6 +51,61 @@ static struct fdt_image provided_fdt = {0}; * COMMON HELPERS * \****************/ +/* + * Go through the available physical memory regions and + * find one that can hold an image of the specified size + * and start address should be aligned up with `align`. + * Note: This is called after get_memory_ranges so + * info->memory_range[] should be populated. Also note that + * memory ranges are sorted, so we'll return the first region + * that's big enough for holding the image. + */ +int elf_riscv_find_pbase(struct kexec_info *info, off_t *addr, + off_t size, off_t align) +{ + int i = 0; + off_t start = 0; + off_t end = 0; + int ret = 0; + + /* + * If this image is for a crash kernel, use the region + * the primary kernel has already reserved for us. + */ + if (info->kexec_flags & KEXEC_ON_CRASH) { + ret = get_crash_kernel_load_range((uint64_t *) &start, + (uint64_t *) &end); + if (!ret) { + start = _ALIGN_UP(start, align); + + if (end > start && ((end - start) >= size)) { + *addr = start; + return 0; + } + + return -EFBIG; + } else + return ENOCRASHKERNEL; + } + + for (i = 0; i < info->memory_ranges; i++) { + if (info->memory_range[i].type != RANGE_RAM) + continue; + + start = info->memory_range[i].start; + end = info->memory_range[i].end; + + start = _ALIGN_UP(start, align); + + if (end > start && ((end - start) >= size)) { + *addr = start; + return 0; + } + } + + return -EFBIG; +} + int load_extra_segments(struct kexec_info *info, uint64_t kernel_base, uint64_t kernel_size, uint64_t max_addr) { diff --git a/kexec/arch/riscv/kexec-riscv.h b/kexec/arch/riscv/kexec-riscv.h index f136c7e..233b137 100644 --- a/kexec/arch/riscv/kexec-riscv.h +++ b/kexec/arch/riscv/kexec-riscv.h @@ -4,6 +4,17 @@ * Nick Kossifidis <mick@xxxxxxxxxxxx> */ +/* + * Kernel should be aligned to the nearest + * hugepage (2MB for RV64, 4MB for RV32). + */ + +#if __riscv_xlen == 64 +#define KERNEL_ALIGN 0x200000 +#else +#define KERNEL_ALIGN 0x400000 +#endif + struct fdt_image { char *buf; off_t size; @@ -26,6 +37,8 @@ int load_elfcorehdr(struct kexec_info *info); int prepare_kexec_file_options(struct kexec_info *info); int load_extra_segments(struct kexec_info *info, uint64_t kernel_base, uint64_t kernel_size, uint64_t max_addr); +int elf_riscv_find_pbase(struct kexec_info *info, off_t *addr, + off_t size, off_t align); int elf_riscv_probe(const char *buf, off_t len); void elf_riscv_usage(void); -- 2.20.1 _______________________________________________ kexec mailing list kexec@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/kexec