Loading arch/arm64/include/asm/kexec.h +4 −0 Original line number Diff line number Diff line Loading @@ -96,6 +96,10 @@ static inline void crash_post_resume(void) {} struct kimage_arch { void *dtb; unsigned long dtb_mem; /* Core ELF header buffer */ void *elf_headers; unsigned long elf_headers_mem; unsigned long elf_headers_sz; }; extern const struct kexec_file_ops kexec_image_ops; Loading arch/arm64/kernel/kexec_image.c +0 −4 Original line number Diff line number Diff line Loading @@ -47,10 +47,6 @@ static void *image_load(struct kimage *image, struct kexec_segment *kernel_segment; int ret; /* We don't support crash kernels yet. */ if (image->type == KEXEC_TYPE_CRASH) return ERR_PTR(-EOPNOTSUPP); /* * We require a kernel with an unambiguous Image header. Per * Documentation/arm64/booting.rst, this is the case when image_size Loading arch/arm64/kernel/machine_kexec_file.c +102 −4 Original line number Diff line number Diff line Loading @@ -17,12 +17,15 @@ #include <linux/memblock.h> #include <linux/of_fdt.h> #include <linux/random.h> #include <linux/slab.h> #include <linux/string.h> #include <linux/types.h> #include <linux/vmalloc.h> #include <asm/byteorder.h> /* relevant device tree properties */ #define FDT_PROP_KEXEC_ELFHDR "linux,elfcorehdr" #define FDT_PROP_MEM_RANGE "linux,usable-memory-range" #define FDT_PROP_INITRD_START "linux,initrd-start" #define FDT_PROP_INITRD_END "linux,initrd-end" #define FDT_PROP_BOOTARGS "bootargs" Loading @@ -40,6 +43,10 @@ int arch_kimage_file_post_load_cleanup(struct kimage *image) vfree(image->arch.dtb); image->arch.dtb = NULL; vfree(image->arch.elf_headers); image->arch.elf_headers = NULL; image->arch.elf_headers_sz = 0; return kexec_image_post_load_cleanup_default(image); } Loading @@ -55,6 +62,31 @@ static int setup_dtb(struct kimage *image, off = ret; ret = fdt_delprop(dtb, off, FDT_PROP_KEXEC_ELFHDR); if (ret && ret != -FDT_ERR_NOTFOUND) goto out; ret = fdt_delprop(dtb, off, FDT_PROP_MEM_RANGE); if (ret && ret != -FDT_ERR_NOTFOUND) goto out; if (image->type == KEXEC_TYPE_CRASH) { /* add linux,elfcorehdr */ ret = fdt_appendprop_addrrange(dtb, 0, off, FDT_PROP_KEXEC_ELFHDR, image->arch.elf_headers_mem, image->arch.elf_headers_sz); if (ret) return (ret == -FDT_ERR_NOSPACE ? -ENOMEM : -EINVAL); /* add linux,usable-memory-range */ ret = fdt_appendprop_addrrange(dtb, 0, off, FDT_PROP_MEM_RANGE, crashk_res.start, crashk_res.end - crashk_res.start + 1); if (ret) return (ret == -FDT_ERR_NOSPACE ? -ENOMEM : -EINVAL); } /* add bootargs */ if (cmdline) { ret = fdt_setprop_string(dtb, off, FDT_PROP_BOOTARGS, cmdline); Loading Loading @@ -125,8 +157,8 @@ static int setup_dtb(struct kimage *image, } /* * More space needed so that we can add initrd, bootargs, kaslr-seed, and * rng-seed. * More space needed so that we can add initrd, bootargs, kaslr-seed, * rng-seed, userable-memory-range and elfcorehdr. */ #define DTB_EXTRA_SPACE 0x1000 Loading Loading @@ -174,6 +206,43 @@ static int create_dtb(struct kimage *image, } } static int prepare_elf_headers(void **addr, unsigned long *sz) { struct crash_mem *cmem; unsigned int nr_ranges; int ret; u64 i; phys_addr_t start, end; nr_ranges = 1; /* for exclusion of crashkernel region */ for_each_mem_range(i, &memblock.memory, NULL, NUMA_NO_NODE, MEMBLOCK_NONE, &start, &end, NULL) nr_ranges++; cmem = kmalloc(sizeof(struct crash_mem) + sizeof(struct crash_mem_range) * nr_ranges, GFP_KERNEL); if (!cmem) return -ENOMEM; cmem->max_nr_ranges = nr_ranges; cmem->nr_ranges = 0; for_each_mem_range(i, &memblock.memory, NULL, NUMA_NO_NODE, MEMBLOCK_NONE, &start, &end, NULL) { cmem->ranges[cmem->nr_ranges].start = start; cmem->ranges[cmem->nr_ranges].end = end - 1; cmem->nr_ranges++; } /* Exclude crashkernel region */ ret = crash_exclude_mem_range(cmem, crashk_res.start, crashk_res.end); if (!ret) ret = crash_prepare_elf64_headers(cmem, true, addr, sz); kfree(cmem); return ret; } int load_other_segments(struct kimage *image, unsigned long kernel_load_addr, unsigned long kernel_size, Loading @@ -181,14 +250,43 @@ int load_other_segments(struct kimage *image, char *cmdline) { struct kexec_buf kbuf; void *dtb = NULL; unsigned long initrd_load_addr = 0, dtb_len; void *headers, *dtb = NULL; unsigned long headers_sz, initrd_load_addr = 0, dtb_len; int ret = 0; kbuf.image = image; /* not allocate anything below the kernel */ kbuf.buf_min = kernel_load_addr + kernel_size; /* load elf core header */ if (image->type == KEXEC_TYPE_CRASH) { ret = prepare_elf_headers(&headers, &headers_sz); if (ret) { pr_err("Preparing elf core header failed\n"); goto out_err; } kbuf.buffer = headers; kbuf.bufsz = headers_sz; kbuf.mem = KEXEC_BUF_MEM_UNKNOWN; kbuf.memsz = headers_sz; kbuf.buf_align = SZ_64K; /* largest supported page size */ kbuf.buf_max = ULONG_MAX; kbuf.top_down = true; ret = kexec_add_buffer(&kbuf); if (ret) { vfree(headers); goto out_err; } image->arch.elf_headers = headers; image->arch.elf_headers_mem = kbuf.mem; image->arch.elf_headers_sz = headers_sz; pr_debug("Loaded elf core header at 0x%lx bufsz=0x%lx memsz=0x%lx\n", image->arch.elf_headers_mem, headers_sz, headers_sz); } /* load initrd */ if (initrd) { kbuf.buffer = initrd; Loading Loading
arch/arm64/include/asm/kexec.h +4 −0 Original line number Diff line number Diff line Loading @@ -96,6 +96,10 @@ static inline void crash_post_resume(void) {} struct kimage_arch { void *dtb; unsigned long dtb_mem; /* Core ELF header buffer */ void *elf_headers; unsigned long elf_headers_mem; unsigned long elf_headers_sz; }; extern const struct kexec_file_ops kexec_image_ops; Loading
arch/arm64/kernel/kexec_image.c +0 −4 Original line number Diff line number Diff line Loading @@ -47,10 +47,6 @@ static void *image_load(struct kimage *image, struct kexec_segment *kernel_segment; int ret; /* We don't support crash kernels yet. */ if (image->type == KEXEC_TYPE_CRASH) return ERR_PTR(-EOPNOTSUPP); /* * We require a kernel with an unambiguous Image header. Per * Documentation/arm64/booting.rst, this is the case when image_size Loading
arch/arm64/kernel/machine_kexec_file.c +102 −4 Original line number Diff line number Diff line Loading @@ -17,12 +17,15 @@ #include <linux/memblock.h> #include <linux/of_fdt.h> #include <linux/random.h> #include <linux/slab.h> #include <linux/string.h> #include <linux/types.h> #include <linux/vmalloc.h> #include <asm/byteorder.h> /* relevant device tree properties */ #define FDT_PROP_KEXEC_ELFHDR "linux,elfcorehdr" #define FDT_PROP_MEM_RANGE "linux,usable-memory-range" #define FDT_PROP_INITRD_START "linux,initrd-start" #define FDT_PROP_INITRD_END "linux,initrd-end" #define FDT_PROP_BOOTARGS "bootargs" Loading @@ -40,6 +43,10 @@ int arch_kimage_file_post_load_cleanup(struct kimage *image) vfree(image->arch.dtb); image->arch.dtb = NULL; vfree(image->arch.elf_headers); image->arch.elf_headers = NULL; image->arch.elf_headers_sz = 0; return kexec_image_post_load_cleanup_default(image); } Loading @@ -55,6 +62,31 @@ static int setup_dtb(struct kimage *image, off = ret; ret = fdt_delprop(dtb, off, FDT_PROP_KEXEC_ELFHDR); if (ret && ret != -FDT_ERR_NOTFOUND) goto out; ret = fdt_delprop(dtb, off, FDT_PROP_MEM_RANGE); if (ret && ret != -FDT_ERR_NOTFOUND) goto out; if (image->type == KEXEC_TYPE_CRASH) { /* add linux,elfcorehdr */ ret = fdt_appendprop_addrrange(dtb, 0, off, FDT_PROP_KEXEC_ELFHDR, image->arch.elf_headers_mem, image->arch.elf_headers_sz); if (ret) return (ret == -FDT_ERR_NOSPACE ? -ENOMEM : -EINVAL); /* add linux,usable-memory-range */ ret = fdt_appendprop_addrrange(dtb, 0, off, FDT_PROP_MEM_RANGE, crashk_res.start, crashk_res.end - crashk_res.start + 1); if (ret) return (ret == -FDT_ERR_NOSPACE ? -ENOMEM : -EINVAL); } /* add bootargs */ if (cmdline) { ret = fdt_setprop_string(dtb, off, FDT_PROP_BOOTARGS, cmdline); Loading Loading @@ -125,8 +157,8 @@ static int setup_dtb(struct kimage *image, } /* * More space needed so that we can add initrd, bootargs, kaslr-seed, and * rng-seed. * More space needed so that we can add initrd, bootargs, kaslr-seed, * rng-seed, userable-memory-range and elfcorehdr. */ #define DTB_EXTRA_SPACE 0x1000 Loading Loading @@ -174,6 +206,43 @@ static int create_dtb(struct kimage *image, } } static int prepare_elf_headers(void **addr, unsigned long *sz) { struct crash_mem *cmem; unsigned int nr_ranges; int ret; u64 i; phys_addr_t start, end; nr_ranges = 1; /* for exclusion of crashkernel region */ for_each_mem_range(i, &memblock.memory, NULL, NUMA_NO_NODE, MEMBLOCK_NONE, &start, &end, NULL) nr_ranges++; cmem = kmalloc(sizeof(struct crash_mem) + sizeof(struct crash_mem_range) * nr_ranges, GFP_KERNEL); if (!cmem) return -ENOMEM; cmem->max_nr_ranges = nr_ranges; cmem->nr_ranges = 0; for_each_mem_range(i, &memblock.memory, NULL, NUMA_NO_NODE, MEMBLOCK_NONE, &start, &end, NULL) { cmem->ranges[cmem->nr_ranges].start = start; cmem->ranges[cmem->nr_ranges].end = end - 1; cmem->nr_ranges++; } /* Exclude crashkernel region */ ret = crash_exclude_mem_range(cmem, crashk_res.start, crashk_res.end); if (!ret) ret = crash_prepare_elf64_headers(cmem, true, addr, sz); kfree(cmem); return ret; } int load_other_segments(struct kimage *image, unsigned long kernel_load_addr, unsigned long kernel_size, Loading @@ -181,14 +250,43 @@ int load_other_segments(struct kimage *image, char *cmdline) { struct kexec_buf kbuf; void *dtb = NULL; unsigned long initrd_load_addr = 0, dtb_len; void *headers, *dtb = NULL; unsigned long headers_sz, initrd_load_addr = 0, dtb_len; int ret = 0; kbuf.image = image; /* not allocate anything below the kernel */ kbuf.buf_min = kernel_load_addr + kernel_size; /* load elf core header */ if (image->type == KEXEC_TYPE_CRASH) { ret = prepare_elf_headers(&headers, &headers_sz); if (ret) { pr_err("Preparing elf core header failed\n"); goto out_err; } kbuf.buffer = headers; kbuf.bufsz = headers_sz; kbuf.mem = KEXEC_BUF_MEM_UNKNOWN; kbuf.memsz = headers_sz; kbuf.buf_align = SZ_64K; /* largest supported page size */ kbuf.buf_max = ULONG_MAX; kbuf.top_down = true; ret = kexec_add_buffer(&kbuf); if (ret) { vfree(headers); goto out_err; } image->arch.elf_headers = headers; image->arch.elf_headers_mem = kbuf.mem; image->arch.elf_headers_sz = headers_sz; pr_debug("Loaded elf core header at 0x%lx bufsz=0x%lx memsz=0x%lx\n", image->arch.elf_headers_mem, headers_sz, headers_sz); } /* load initrd */ if (initrd) { kbuf.buffer = initrd; Loading