mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-28 14:44:10 +08:00
s390/kexec_file: Add kexec_file_load system call
This patch adds the kexec_file_load system call to s390 as well as the arch specific functions common code requires to work. Loaders for the different file types will be added later. Signed-off-by: Philipp Rudo <prudo@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
parent
840798a1f5
commit
71406883fd
@ -51,6 +51,19 @@ config KEXEC
|
||||
def_bool y
|
||||
select KEXEC_CORE
|
||||
|
||||
config KEXEC_FILE
|
||||
bool "kexec file based system call"
|
||||
select KEXEC_CORE
|
||||
select BUILD_BIN2C
|
||||
depends on CRYPTO
|
||||
depends on CRYPTO_SHA256
|
||||
depends on CRYPTO_SHA256_S390
|
||||
---help---
|
||||
This is new version of kexec system call. This system call 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.
|
||||
|
||||
config ARCH_HAS_KEXEC_PURGATORY
|
||||
def_bool y
|
||||
depends on KEXEC_FILE
|
||||
|
@ -719,3 +719,4 @@ CONFIG_APPLDATA_BASE=y
|
||||
CONFIG_KVM=m
|
||||
CONFIG_KVM_S390_UCONTROL=y
|
||||
CONFIG_VHOST_NET=m
|
||||
CONFIG_KEXEC_FILE=y
|
||||
|
@ -82,6 +82,8 @@ obj-$(CONFIG_FUNCTION_TRACER) += mcount.o ftrace.o
|
||||
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
|
||||
obj-$(CONFIG_UPROBES) += uprobes.o
|
||||
|
||||
obj-$(CONFIG_KEXEC_FILE) += machine_kexec_file.o
|
||||
|
||||
obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_cpum_cf.o perf_cpum_sf.o
|
||||
obj-$(CONFIG_PERF_EVENTS) += perf_cpum_cf_events.o perf_regs.o
|
||||
|
||||
|
@ -182,3 +182,4 @@ COMPAT_SYSCALL_WRAP6(copy_file_range, int, fd_in, loff_t __user *, off_in, int,
|
||||
COMPAT_SYSCALL_WRAP2(s390_guarded_storage, int, command, struct gs_cb *, gs_cb);
|
||||
COMPAT_SYSCALL_WRAP5(statx, int, dfd, const char __user *, path, unsigned, flags, unsigned, mask, struct statx __user *, buffer);
|
||||
COMPAT_SYSCALL_WRAP4(s390_sthyi, unsigned long, code, void __user *, info, u64 __user *, rc, unsigned long, flags);
|
||||
COMPAT_SYSCALL_WRAP5(kexec_file_load, int, kernel_fd, int, initrd_fd, unsigned long, cmdline_len, const char __user *, cmdline_ptr, unsigned long, flags)
|
||||
|
126
arch/s390/kernel/machine_kexec_file.c
Normal file
126
arch/s390/kernel/machine_kexec_file.c
Normal file
@ -0,0 +1,126 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* s390 code for kexec_file_load system call
|
||||
*
|
||||
* Copyright IBM Corp. 2018
|
||||
*
|
||||
* Author(s): Philipp Rudo <prudo@linux.vnet.ibm.com>
|
||||
*/
|
||||
|
||||
#include <linux/elf.h>
|
||||
#include <linux/kexec.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
const struct kexec_file_ops * const kexec_file_loaders[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
/*
|
||||
* The kernel is loaded to a fixed location. Turn off kexec_locate_mem_hole
|
||||
* and provide kbuf->mem by hand.
|
||||
*/
|
||||
int arch_kexec_walk_mem(struct kexec_buf *kbuf,
|
||||
int (*func)(struct resource *, void *))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int arch_kexec_apply_relocations_add(struct purgatory_info *pi,
|
||||
Elf_Shdr *section,
|
||||
const Elf_Shdr *relsec,
|
||||
const Elf_Shdr *symtab)
|
||||
{
|
||||
Elf_Rela *relas;
|
||||
int i;
|
||||
|
||||
relas = (void *)pi->ehdr + relsec->sh_offset;
|
||||
|
||||
for (i = 0; i < relsec->sh_size / sizeof(*relas); i++) {
|
||||
const Elf_Sym *sym; /* symbol to relocate */
|
||||
unsigned long addr; /* final location after relocation */
|
||||
unsigned long val; /* relocated symbol value */
|
||||
void *loc; /* tmp location to modify */
|
||||
|
||||
sym = (void *)pi->ehdr + symtab->sh_offset;
|
||||
sym += ELF64_R_SYM(relas[i].r_info);
|
||||
|
||||
if (sym->st_shndx == SHN_UNDEF)
|
||||
return -ENOEXEC;
|
||||
|
||||
if (sym->st_shndx == SHN_COMMON)
|
||||
return -ENOEXEC;
|
||||
|
||||
if (sym->st_shndx >= pi->ehdr->e_shnum &&
|
||||
sym->st_shndx != SHN_ABS)
|
||||
return -ENOEXEC;
|
||||
|
||||
loc = pi->purgatory_buf;
|
||||
loc += section->sh_offset;
|
||||
loc += relas[i].r_offset;
|
||||
|
||||
val = sym->st_value;
|
||||
if (sym->st_shndx != SHN_ABS)
|
||||
val += pi->sechdrs[sym->st_shndx].sh_addr;
|
||||
val += relas[i].r_addend;
|
||||
|
||||
addr = section->sh_addr + relas[i].r_offset;
|
||||
|
||||
switch (ELF64_R_TYPE(relas[i].r_info)) {
|
||||
case R_390_8: /* Direct 8 bit. */
|
||||
*(u8 *)loc = val;
|
||||
break;
|
||||
case R_390_12: /* Direct 12 bit. */
|
||||
*(u16 *)loc &= 0xf000;
|
||||
*(u16 *)loc |= val & 0xfff;
|
||||
break;
|
||||
case R_390_16: /* Direct 16 bit. */
|
||||
*(u16 *)loc = val;
|
||||
break;
|
||||
case R_390_20: /* Direct 20 bit. */
|
||||
*(u32 *)loc &= 0xf00000ff;
|
||||
*(u32 *)loc |= (val & 0xfff) << 16; /* DL */
|
||||
*(u32 *)loc |= (val & 0xff000) >> 4; /* DH */
|
||||
break;
|
||||
case R_390_32: /* Direct 32 bit. */
|
||||
*(u32 *)loc = val;
|
||||
break;
|
||||
case R_390_64: /* Direct 64 bit. */
|
||||
*(u64 *)loc = val;
|
||||
break;
|
||||
case R_390_PC16: /* PC relative 16 bit. */
|
||||
*(u16 *)loc = (val - addr);
|
||||
break;
|
||||
case R_390_PC16DBL: /* PC relative 16 bit shifted by 1. */
|
||||
*(u16 *)loc = (val - addr) >> 1;
|
||||
break;
|
||||
case R_390_PC32DBL: /* PC relative 32 bit shifted by 1. */
|
||||
*(u32 *)loc = (val - addr) >> 1;
|
||||
break;
|
||||
case R_390_PC32: /* PC relative 32 bit. */
|
||||
*(u32 *)loc = (val - addr);
|
||||
break;
|
||||
case R_390_PC64: /* PC relative 64 bit. */
|
||||
*(u64 *)loc = (val - addr);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arch_kexec_kernel_image_probe(struct kimage *image, void *buf,
|
||||
unsigned long buf_len)
|
||||
{
|
||||
/* A kernel must be at least large enough to contain head.S. During
|
||||
* load memory in head.S will be accessed, e.g. to register the next
|
||||
* command line. If the next kernel were smaller the current kernel
|
||||
* will panic at load.
|
||||
*
|
||||
* 0x11000 = sizeof(head.S)
|
||||
*/
|
||||
if (buf_len < 0x11000)
|
||||
return -ENOEXEC;
|
||||
|
||||
return kexec_image_probe_default(image, buf, buf_len);
|
||||
}
|
@ -388,3 +388,4 @@
|
||||
378 common s390_guarded_storage sys_s390_guarded_storage compat_sys_s390_guarded_storage
|
||||
379 common statx sys_statx compat_sys_statx
|
||||
380 common s390_sthyi sys_s390_sthyi compat_sys_s390_sthyi
|
||||
381 common kexec_file_load sys_kexec_file_load compat_sys_kexec_file_load
|
||||
|
Loading…
Reference in New Issue
Block a user