aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Rudo <prudo@linux.vnet.ibm.com>2017-08-30 08:03:38 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2018-04-16 03:10:22 -0400
commite49bb0a27fa3c6ec45cc13e2102a6ec13c4ae697 (patch)
treed4365a12b7eb3e8cf8bd811c4075771ec2e20320
parent71406883fd35794d573b3085433c41d0a3bf6c21 (diff)
s390/kexec_file: Add image loader
Add an image loader for kexec_file_load. For simplicity first skip crash support. The functions defined in machine_kexec_file will later be shared with the ELF loader. Signed-off-by: Philipp Rudo <prudo@linux.vnet.ibm.com> Reviewed-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/include/asm/kexec.h22
-rw-r--r--arch/s390/kernel/Makefile2
-rw-r--r--arch/s390/kernel/kexec_image.c78
-rw-r--r--arch/s390/kernel/machine_kexec_file.c75
4 files changed, 176 insertions, 1 deletions
diff --git a/arch/s390/include/asm/kexec.h b/arch/s390/include/asm/kexec.h
index 1d708a419326..4c9da9974cf4 100644
--- a/arch/s390/include/asm/kexec.h
+++ b/arch/s390/include/asm/kexec.h
@@ -46,4 +46,26 @@
46static inline void crash_setup_regs(struct pt_regs *newregs, 46static inline void crash_setup_regs(struct pt_regs *newregs,
47 struct pt_regs *oldregs) { } 47 struct pt_regs *oldregs) { }
48 48
49struct kimage;
50struct s390_load_data {
51 /* Pointer to the kernel buffer. Used to register cmdline etc.. */
52 void *kernel_buf;
53
54 /* Total size of loaded segments in memory. Used as an offset. */
55 size_t memsz;
56
57 /* Load address of initrd. Used to register INITRD_START in kernel. */
58 unsigned long initrd_load_addr;
59};
60
61int kexec_file_add_purgatory(struct kimage *image,
62 struct s390_load_data *data);
63int kexec_file_add_initrd(struct kimage *image,
64 struct s390_load_data *data,
65 char *initrd, unsigned long initrd_len);
66int *kexec_file_update_kernel(struct kimage *iamge,
67 struct s390_load_data *data);
68
69extern const struct kexec_file_ops s390_kexec_image_ops;
70
49#endif /*_S390_KEXEC_H */ 71#endif /*_S390_KEXEC_H */
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 35bec1ab84e3..a84e9611c5c7 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -82,7 +82,7 @@ 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 85obj-$(CONFIG_KEXEC_FILE) += machine_kexec_file.o kexec_image.o
86 86
87obj-$(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
88obj-$(CONFIG_PERF_EVENTS) += perf_cpum_cf_events.o perf_regs.o 88obj-$(CONFIG_PERF_EVENTS) += perf_cpum_cf_events.o perf_regs.o
diff --git a/arch/s390/kernel/kexec_image.c b/arch/s390/kernel/kexec_image.c
new file mode 100644
index 000000000000..7f5021e6c242
--- /dev/null
+++ b/arch/s390/kernel/kexec_image.c
@@ -0,0 +1,78 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Image loader 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/errno.h>
11#include <linux/kernel.h>
12#include <linux/kexec.h>
13#include <asm/setup.h>
14
15static int kexec_file_add_image_kernel(struct kimage *image,
16 struct s390_load_data *data,
17 char *kernel, unsigned long kernel_len)
18{
19 struct kexec_buf buf;
20 int ret;
21
22 buf.image = image;
23
24 buf.buffer = kernel + STARTUP_NORMAL_OFFSET;
25 buf.bufsz = kernel_len - STARTUP_NORMAL_OFFSET;
26
27 buf.mem = STARTUP_NORMAL_OFFSET;
28 buf.memsz = buf.bufsz;
29
30 ret = kexec_add_buffer(&buf);
31
32 data->kernel_buf = kernel;
33 data->memsz += buf.memsz + STARTUP_NORMAL_OFFSET;
34
35 return ret;
36}
37
38static void *s390_image_load(struct kimage *image,
39 char *kernel, unsigned long kernel_len,
40 char *initrd, unsigned long initrd_len,
41 char *cmdline, unsigned long cmdline_len)
42{
43 struct s390_load_data data = {0};
44 int ret;
45
46 /* We don't support crash kernels yet. */
47 if (image->type == KEXEC_TYPE_CRASH)
48 return ERR_PTR(-ENOTSUPP);
49
50 ret = kexec_file_add_image_kernel(image, &data, kernel, kernel_len);
51 if (ret)
52 return ERR_PTR(ret);
53
54 if (initrd) {
55 ret = kexec_file_add_initrd(image, &data, initrd, initrd_len);
56 if (ret)
57 return ERR_PTR(ret);
58 }
59
60 ret = kexec_file_add_purgatory(image, &data);
61 if (ret)
62 return ERR_PTR(ret);
63
64 return kexec_file_update_kernel(image, &data);
65}
66
67static int s390_image_probe(const char *buf, unsigned long len)
68{
69 /* Can't reliably tell if an image is valid. Therefore give the
70 * user whatever he wants.
71 */
72 return 0;
73}
74
75const struct kexec_file_ops s390_kexec_image_ops = {
76 .probe = s390_image_probe,
77 .load = s390_image_load,
78};
diff --git a/arch/s390/kernel/machine_kexec_file.c b/arch/s390/kernel/machine_kexec_file.c
index d9b4f9d23e9f..2a2ceece77b0 100644
--- a/arch/s390/kernel/machine_kexec_file.c
+++ b/arch/s390/kernel/machine_kexec_file.c
@@ -12,9 +12,84 @@
12#include <asm/setup.h> 12#include <asm/setup.h>
13 13
14const struct kexec_file_ops * const kexec_file_loaders[] = { 14const struct kexec_file_ops * const kexec_file_loaders[] = {
15 &s390_kexec_image_ops,
15 NULL, 16 NULL,
16}; 17};
17 18
19int *kexec_file_update_kernel(struct kimage *image,
20 struct s390_load_data *data)
21{
22 unsigned long *loc;
23
24 if (image->cmdline_buf_len >= ARCH_COMMAND_LINE_SIZE)
25 return ERR_PTR(-EINVAL);
26
27 if (image->cmdline_buf_len)
28 memcpy(data->kernel_buf + COMMAND_LINE_OFFSET,
29 image->cmdline_buf, image->cmdline_buf_len);
30
31 if (image->initrd_buf) {
32 loc = (unsigned long *)(data->kernel_buf + INITRD_START_OFFSET);
33 *loc = data->initrd_load_addr;
34
35 loc = (unsigned long *)(data->kernel_buf + INITRD_SIZE_OFFSET);
36 *loc = image->initrd_buf_len;
37 }
38
39 return NULL;
40}
41
42static int kexec_file_update_purgatory(struct kimage *image)
43{
44 u64 entry, type;
45 int ret;
46
47 entry = STARTUP_NORMAL_OFFSET;
48 ret = kexec_purgatory_get_set_symbol(image, "kernel_entry", &entry,
49 sizeof(entry), false);
50 return ret;
51}
52
53int kexec_file_add_purgatory(struct kimage *image, struct s390_load_data *data)
54{
55 struct kexec_buf buf;
56 int ret;
57
58 buf.image = image;
59
60 data->memsz = ALIGN(data->memsz, PAGE_SIZE);
61 buf.mem = data->memsz;
62
63 ret = kexec_load_purgatory(image, &buf);
64 if (ret)
65 return ret;
66
67 ret = kexec_file_update_purgatory(image);
68 return ret;
69}
70
71int kexec_file_add_initrd(struct kimage *image, struct s390_load_data *data,
72 char *initrd, unsigned long initrd_len)
73{
74 struct kexec_buf buf;
75 int ret;
76
77 buf.image = image;
78
79 buf.buffer = initrd;
80 buf.bufsz = initrd_len;
81
82 data->memsz = ALIGN(data->memsz, PAGE_SIZE);
83 buf.mem = data->memsz;
84 buf.memsz = buf.bufsz;
85
86 data->initrd_load_addr = buf.mem;
87 data->memsz += buf.memsz;
88
89 ret = kexec_add_buffer(&buf);
90 return ret;
91}
92
18/* 93/*
19 * The kernel is loaded to a fixed location. Turn off kexec_locate_mem_hole 94 * The kernel is loaded to a fixed location. Turn off kexec_locate_mem_hole
20 * and provide kbuf->mem by hand. 95 * and provide kbuf->mem by hand.