Loading arch/parisc/Kconfig +10 −0 Original line number Diff line number Diff line Loading @@ -359,6 +359,16 @@ config KEXEC shutdown, so do not be surprised if this code does not initially work for you. config KEXEC_FILE bool "kexec file based system call" select KEXEC_CORE select KEXEC_ELF help This enables the kexec_file_load() System call. This is file based and takes file descriptors as system call argument for kernel and initramfs as opposed to list of segments as accepted by previous system call. endmenu Loading arch/parisc/kernel/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -38,3 +38,4 @@ obj-$(CONFIG_JUMP_LABEL) += jump_label.o obj-$(CONFIG_KGDB) += kgdb.o obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_KEXEC) += kexec.o relocate_kernel.o obj-$(CONFIG_KEXEC_FILE) += kexec_file.o arch/parisc/kernel/kexec.c +7 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,13 @@ static void kexec_image_info(const struct kimage *kimage) for (i = 0; i < kimage->nr_segments; i++) kexec_show_segment_info(kimage, i); #ifdef CONFIG_KEXEC_FILE if (kimage->file_mode) { pr_debug("cmdline: %.*s\n", (int)kimage->cmdline_buf_len, kimage->cmdline_buf); } #endif } void machine_kexec_cleanup(struct kimage *kimage) Loading arch/parisc/kernel/kexec_file.c 0 → 100644 +86 −0 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0 /* * Load ELF vmlinux file for the kexec_file_load syscall. * * Copyright (c) 2019 Sven Schnelle <svens@stackframe.org> * */ #include <linux/elf.h> #include <linux/kexec.h> #include <linux/libfdt.h> #include <linux/module.h> #include <linux/of_fdt.h> #include <linux/slab.h> #include <linux/types.h> static void *elf_load(struct kimage *image, char *kernel_buf, unsigned long kernel_len, char *initrd, unsigned long initrd_len, char *cmdline, unsigned long cmdline_len) { int ret, i; unsigned long kernel_load_addr; struct elfhdr ehdr; struct kexec_elf_info elf_info; struct kexec_buf kbuf = { .image = image, .buf_min = 0, .buf_max = -1UL, }; ret = kexec_build_elf_info(kernel_buf, kernel_len, &ehdr, &elf_info); if (ret) goto out; ret = kexec_elf_load(image, &ehdr, &elf_info, &kbuf, &kernel_load_addr); if (ret) goto out; image->start = __pa(elf_info.ehdr->e_entry); for (i = 0; i < image->nr_segments; i++) image->segment[i].mem = __pa(image->segment[i].mem); pr_debug("Loaded the kernel at 0x%lx, entry at 0x%lx\n", kernel_load_addr, image->start); if (initrd != NULL) { kbuf.buffer = initrd; kbuf.bufsz = kbuf.memsz = initrd_len; kbuf.buf_align = PAGE_SIZE; kbuf.top_down = false; kbuf.mem = KEXEC_BUF_MEM_UNKNOWN; ret = kexec_add_buffer(&kbuf); if (ret) goto out; pr_debug("Loaded initrd at 0x%lx\n", kbuf.mem); image->arch.initrd_start = kbuf.mem; image->arch.initrd_end = kbuf.mem + initrd_len; } if (cmdline != NULL) { kbuf.buffer = cmdline; kbuf.bufsz = kbuf.memsz = ALIGN(cmdline_len, 8); kbuf.buf_align = PAGE_SIZE; kbuf.top_down = false; kbuf.buf_min = PAGE0->mem_free + PAGE_SIZE; kbuf.buf_max = kernel_load_addr; kbuf.mem = KEXEC_BUF_MEM_UNKNOWN; ret = kexec_add_buffer(&kbuf); if (ret) goto out; pr_debug("Loaded cmdline at 0x%lx\n", kbuf.mem); image->arch.cmdline = kbuf.mem; } out: return NULL; } const struct kexec_file_ops kexec_elf_ops = { .probe = kexec_elf_probe, .load = elf_load, }; const struct kexec_file_ops * const kexec_file_loaders[] = { &kexec_elf_ops, NULL }; Loading
arch/parisc/Kconfig +10 −0 Original line number Diff line number Diff line Loading @@ -359,6 +359,16 @@ config KEXEC shutdown, so do not be surprised if this code does not initially work for you. config KEXEC_FILE bool "kexec file based system call" select KEXEC_CORE select KEXEC_ELF help This enables the kexec_file_load() System call. This is file based and takes file descriptors as system call argument for kernel and initramfs as opposed to list of segments as accepted by previous system call. endmenu Loading
arch/parisc/kernel/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -38,3 +38,4 @@ obj-$(CONFIG_JUMP_LABEL) += jump_label.o obj-$(CONFIG_KGDB) += kgdb.o obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_KEXEC) += kexec.o relocate_kernel.o obj-$(CONFIG_KEXEC_FILE) += kexec_file.o
arch/parisc/kernel/kexec.c +7 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,13 @@ static void kexec_image_info(const struct kimage *kimage) for (i = 0; i < kimage->nr_segments; i++) kexec_show_segment_info(kimage, i); #ifdef CONFIG_KEXEC_FILE if (kimage->file_mode) { pr_debug("cmdline: %.*s\n", (int)kimage->cmdline_buf_len, kimage->cmdline_buf); } #endif } void machine_kexec_cleanup(struct kimage *kimage) Loading
arch/parisc/kernel/kexec_file.c 0 → 100644 +86 −0 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0 /* * Load ELF vmlinux file for the kexec_file_load syscall. * * Copyright (c) 2019 Sven Schnelle <svens@stackframe.org> * */ #include <linux/elf.h> #include <linux/kexec.h> #include <linux/libfdt.h> #include <linux/module.h> #include <linux/of_fdt.h> #include <linux/slab.h> #include <linux/types.h> static void *elf_load(struct kimage *image, char *kernel_buf, unsigned long kernel_len, char *initrd, unsigned long initrd_len, char *cmdline, unsigned long cmdline_len) { int ret, i; unsigned long kernel_load_addr; struct elfhdr ehdr; struct kexec_elf_info elf_info; struct kexec_buf kbuf = { .image = image, .buf_min = 0, .buf_max = -1UL, }; ret = kexec_build_elf_info(kernel_buf, kernel_len, &ehdr, &elf_info); if (ret) goto out; ret = kexec_elf_load(image, &ehdr, &elf_info, &kbuf, &kernel_load_addr); if (ret) goto out; image->start = __pa(elf_info.ehdr->e_entry); for (i = 0; i < image->nr_segments; i++) image->segment[i].mem = __pa(image->segment[i].mem); pr_debug("Loaded the kernel at 0x%lx, entry at 0x%lx\n", kernel_load_addr, image->start); if (initrd != NULL) { kbuf.buffer = initrd; kbuf.bufsz = kbuf.memsz = initrd_len; kbuf.buf_align = PAGE_SIZE; kbuf.top_down = false; kbuf.mem = KEXEC_BUF_MEM_UNKNOWN; ret = kexec_add_buffer(&kbuf); if (ret) goto out; pr_debug("Loaded initrd at 0x%lx\n", kbuf.mem); image->arch.initrd_start = kbuf.mem; image->arch.initrd_end = kbuf.mem + initrd_len; } if (cmdline != NULL) { kbuf.buffer = cmdline; kbuf.bufsz = kbuf.memsz = ALIGN(cmdline_len, 8); kbuf.buf_align = PAGE_SIZE; kbuf.top_down = false; kbuf.buf_min = PAGE0->mem_free + PAGE_SIZE; kbuf.buf_max = kernel_load_addr; kbuf.mem = KEXEC_BUF_MEM_UNKNOWN; ret = kexec_add_buffer(&kbuf); if (ret) goto out; pr_debug("Loaded cmdline at 0x%lx\n", kbuf.mem); image->arch.cmdline = kbuf.mem; } out: return NULL; } const struct kexec_file_ops kexec_elf_ops = { .probe = kexec_elf_probe, .load = elf_load, }; const struct kexec_file_ops * const kexec_file_loaders[] = { &kexec_elf_ops, NULL };