aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Rudo <prudo@linux.vnet.ibm.com>2017-06-19 04:45:33 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2018-04-16 03:10:22 -0400
commit71406883fd35794d573b3085433c41d0a3bf6c21 (patch)
tree757865f09f0b8a41357c2c1ec7b1df915b057cbf
parent840798a1f52994c172270893bd2ec6013cc92e40 (diff)
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>
-rw-r--r--arch/s390/Kconfig13
-rw-r--r--arch/s390/configs/default_defconfig1
-rw-r--r--arch/s390/kernel/Makefile2
-rw-r--r--arch/s390/kernel/compat_wrapper.c1
-rw-r--r--arch/s390/kernel/machine_kexec_file.c126
-rw-r--r--arch/s390/kernel/syscalls/syscall.tbl1
6 files changed, 144 insertions, 0 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 5b8d0859b317..3223ce0680c0 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -51,6 +51,19 @@ config KEXEC
51 def_bool y 51 def_bool y
52 select KEXEC_CORE 52 select KEXEC_CORE
53 53
54config KEXEC_FILE
55 bool "kexec file based system call"
56 select KEXEC_CORE
57 select BUILD_BIN2C
58 depends on CRYPTO
59 depends on CRYPTO_SHA256
60 depends on CRYPTO_SHA256_S390
61 ---help---
62 This is new version of kexec system call. This system call is
63 file based and takes file descriptors as system call argument
64 for kernel and initramfs as opposed to list of segments as
65 accepted by previous system call.
66
54config ARCH_HAS_KEXEC_PURGATORY 67config ARCH_HAS_KEXEC_PURGATORY
55 def_bool y 68 def_bool y
56 depends on KEXEC_FILE 69 depends on KEXEC_FILE
diff --git a/arch/s390/configs/default_defconfig b/arch/s390/configs/default_defconfig
index 5af8458951cf..2310315b0744 100644
--- a/arch/s390/configs/default_defconfig
+++ b/arch/s390/configs/default_defconfig
@@ -719,3 +719,4 @@ CONFIG_APPLDATA_BASE=y
719CONFIG_KVM=m 719CONFIG_KVM=m
720CONFIG_KVM_S390_UCONTROL=y 720CONFIG_KVM_S390_UCONTROL=y
721CONFIG_VHOST_NET=m 721CONFIG_VHOST_NET=m
722CONFIG_KEXEC_FILE=y
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index b06a6f79c1ec..35bec1ab84e3 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -82,6 +82,8 @@ obj-$(CONFIG_FUNCTION_TRACER) += mcount.o ftrace.o
82obj-$(CONFIG_CRASH_DUMP) += crash_dump.o 82obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
83obj-$(CONFIG_UPROBES) += uprobes.o 83obj-$(CONFIG_UPROBES) += uprobes.o
84 84
85obj-$(CONFIG_KEXEC_FILE) += machine_kexec_file.o
86
85obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_cpum_cf.o perf_cpum_sf.o 87obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_cpum_cf.o perf_cpum_sf.o
86obj-$(CONFIG_PERF_EVENTS) += perf_cpum_cf_events.o perf_regs.o 88obj-$(CONFIG_PERF_EVENTS) += perf_cpum_cf_events.o perf_regs.o
87 89
diff --git a/arch/s390/kernel/compat_wrapper.c b/arch/s390/kernel/compat_wrapper.c
index 11e9d8b5c1b0..607c5e9fba3d 100644
--- a/arch/s390/kernel/compat_wrapper.c
+++ b/arch/s390/kernel/compat_wrapper.c
@@ -182,3 +182,4 @@ COMPAT_SYSCALL_WRAP6(copy_file_range, int, fd_in, loff_t __user *, off_in, int,
182COMPAT_SYSCALL_WRAP2(s390_guarded_storage, int, command, struct gs_cb *, gs_cb); 182COMPAT_SYSCALL_WRAP2(s390_guarded_storage, int, command, struct gs_cb *, gs_cb);
183COMPAT_SYSCALL_WRAP5(statx, int, dfd, const char __user *, path, unsigned, flags, unsigned, mask, struct statx __user *, buffer); 183COMPAT_SYSCALL_WRAP5(statx, int, dfd, const char __user *, path, unsigned, flags, unsigned, mask, struct statx __user *, buffer);
184COMPAT_SYSCALL_WRAP4(s390_sthyi, unsigned long, code, void __user *, info, u64 __user *, rc, unsigned long, flags); 184COMPAT_SYSCALL_WRAP4(s390_sthyi, unsigned long, code, void __user *, info, u64 __user *, rc, unsigned long, flags);
185COMPAT_SYSCALL_WRAP5(kexec_file_load, int, kernel_fd, int, initrd_fd, unsigned long, cmdline_len, const char __user *, cmdline_ptr, unsigned long, flags)
diff --git a/arch/s390/kernel/machine_kexec_file.c b/arch/s390/kernel/machine_kexec_file.c
new file mode 100644
index 000000000000..d9b4f9d23e9f
--- /dev/null
+++ b/arch/s390/kernel/machine_kexec_file.c
@@ -0,0 +1,126 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * s390 code for kexec_file_load system call
4 *
5 * Copyright IBM Corp. 2018
6 *
7 * Author(s): Philipp Rudo <prudo@linux.vnet.ibm.com>
8 */
9
10#include <linux/elf.h>
11#include <linux/kexec.h>
12#include <asm/setup.h>
13
14const struct kexec_file_ops * const kexec_file_loaders[] = {
15 NULL,
16};
17
18/*
19 * The kernel is loaded to a fixed location. Turn off kexec_locate_mem_hole
20 * and provide kbuf->mem by hand.
21 */
22int arch_kexec_walk_mem(struct kexec_buf *kbuf,
23 int (*func)(struct resource *, void *))
24{
25 return 1;
26}
27
28int arch_kexec_apply_relocations_add(struct purgatory_info *pi,
29 Elf_Shdr *section,
30 const Elf_Shdr *relsec,
31 const Elf_Shdr *symtab)
32{
33 Elf_Rela *relas;
34 int i;
35
36 relas = (void *)pi->ehdr + relsec->sh_offset;
37
38 for (i = 0; i < relsec->sh_size / sizeof(*relas); i++) {
39 const Elf_Sym *sym; /* symbol to relocate */
40 unsigned long addr; /* final location after relocation */
41 unsigned long val; /* relocated symbol value */
42 void *loc; /* tmp location to modify */
43
44 sym = (void *)pi->ehdr + symtab->sh_offset;
45 sym += ELF64_R_SYM(relas[i].r_info);
46
47 if (sym->st_shndx == SHN_UNDEF)
48 return -ENOEXEC;
49
50 if (sym->st_shndx == SHN_COMMON)
51 return -ENOEXEC;
52
53 if (sym->st_shndx >= pi->ehdr->e_shnum &&
54 sym->st_shndx != SHN_ABS)
55 return -ENOEXEC;
56
57 loc = pi->purgatory_buf;
58 loc += section->sh_offset;
59 loc += relas[i].r_offset;
60
61 val = sym->st_value;
62 if (sym->st_shndx != SHN_ABS)
63 val += pi->sechdrs[sym->st_shndx].sh_addr;
64 val += relas[i].r_addend;
65
66 addr = section->sh_addr + relas[i].r_offset;
67
68 switch (ELF64_R_TYPE(relas[i].r_info)) {
69 case R_390_8: /* Direct 8 bit. */
70 *(u8 *)loc = val;
71 break;
72 case R_390_12: /* Direct 12 bit. */
73 *(u16 *)loc &= 0xf000;
74 *(u16 *)loc |= val & 0xfff;
75 break;
76 case R_390_16: /* Direct 16 bit. */
77 *(u16 *)loc = val;
78 break;
79 case R_390_20: /* Direct 20 bit. */
80 *(u32 *)loc &= 0xf00000ff;
81 *(u32 *)loc |= (val & 0xfff) << 16; /* DL */
82 *(u32 *)loc |= (val & 0xff000) >> 4; /* DH */
83 break;
84 case R_390_32: /* Direct 32 bit. */
85 *(u32 *)loc = val;
86 break;
87 case R_390_64: /* Direct 64 bit. */
88 *(u64 *)loc = val;
89 break;
90 case R_390_PC16: /* PC relative 16 bit. */
91 *(u16 *)loc = (val - addr);
92 break;
93 case R_390_PC16DBL: /* PC relative 16 bit shifted by 1. */
94 *(u16 *)loc = (val - addr) >> 1;
95 break;
96 case R_390_PC32DBL: /* PC relative 32 bit shifted by 1. */
97 *(u32 *)loc = (val - addr) >> 1;
98 break;
99 case R_390_PC32: /* PC relative 32 bit. */
100 *(u32 *)loc = (val - addr);
101 break;
102 case R_390_PC64: /* PC relative 64 bit. */
103 *(u64 *)loc = (val - addr);
104 break;
105 default:
106 break;
107 }
108 }
109 return 0;
110}
111
112int arch_kexec_kernel_image_probe(struct kimage *image, void *buf,
113 unsigned long buf_len)
114{
115 /* A kernel must be at least large enough to contain head.S. During
116 * load memory in head.S will be accessed, e.g. to register the next
117 * command line. If the next kernel were smaller the current kernel
118 * will panic at load.
119 *
120 * 0x11000 = sizeof(head.S)
121 */
122 if (buf_len < 0x11000)
123 return -ENOEXEC;
124
125 return kexec_image_probe_default(image, buf, buf_len);
126}
diff --git a/arch/s390/kernel/syscalls/syscall.tbl b/arch/s390/kernel/syscalls/syscall.tbl
index b38d48464368..8b210ead7956 100644
--- a/arch/s390/kernel/syscalls/syscall.tbl
+++ b/arch/s390/kernel/syscalls/syscall.tbl
@@ -388,3 +388,4 @@
388378 common s390_guarded_storage sys_s390_guarded_storage compat_sys_s390_guarded_storage 388378 common s390_guarded_storage sys_s390_guarded_storage compat_sys_s390_guarded_storage
389379 common statx sys_statx compat_sys_statx 389379 common statx sys_statx compat_sys_statx
390380 common s390_sthyi sys_s390_sthyi compat_sys_s390_sthyi 390380 common s390_sthyi sys_s390_sthyi compat_sys_s390_sthyi
391381 common kexec_file_load sys_kexec_file_load compat_sys_kexec_file_load