Skip to content

Commit

Permalink
parisc: add support for kexec_file_load() syscall
Browse files Browse the repository at this point in the history
Signed-off-by: Sven Schnelle <svens@stackframe.org>
Signed-off-by: Helge Deller <deller@gmx.de>
  • Loading branch information
svenschnelle authored and hdeller committed Sep 8, 2019
1 parent 3be6e58 commit 1191cf4
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 0 deletions.
10 changes: 10 additions & 0 deletions arch/parisc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down
1 change: 1 addition & 0 deletions arch/parisc/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
7 changes: 7 additions & 0 deletions arch/parisc/kernel/kexec.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
86 changes: 86 additions & 0 deletions arch/parisc/kernel/kexec_file.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// 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
};

0 comments on commit 1191cf4

Please sign in to comment.