Hi everybody
resending the series as there was no reaction, yet. Furthermore i was told
that Andrew and the x86 list should also be CCed, so welcome.
No changes made to the patches since first time i sent them. The patches
apply to the current master (v4.16-rc1).
Thanks
Philipp
---
this series adds the kexec_file_load system call to s390. Before the system
call is added there are some preparations/clean ups to common
kexec_file_load. In detail this series contains:
Patch #1&2: Minor cleanups/fixes.
Patch #3-9: Clean up the purgatory load/relocation code. Especially remove
the mis-use of the purgatory_info->sechdrs->sh_offset field, currently
holding a pointer into either kexec_purgatory (ro) or purgatory_buf (rw)
depending on the section. With these patches the section address will be
calculated verbosely and sh_offset will contain the offset of the section
in the stripped purgatory binary (purgatory_buf).
Patch #10: Allows architectures to set the purgaory load address. This
patch is important for s390 as the kernel and purgatory have to be loaded
to fixed addresses. In current code this is impossible as the purgatory
load is opaque to the architecture.
Patch #11: Moves x86 purgatories sha implementation to common lib/
directory.
Patches #12-17 finally adds the kexec_file_load system call to s390.
Please note that I had to touch arch code for x86 and power a little. In
theory this should not change the behavior but I don't have a way to test
it. Cross-compiling with defconfig(*) works fine for both.
Thanks
Philipp
(*) On x86 with the orc unwinder turned off. objtool SEGFAULTs on s390...
Philipp Rudo (17):
kexec_file: Silence compile warnings
kexec_file: Remove checks in kexec_purgatory_load
kexec_file: Make purgatory_info->ehdr const
kexec_file: Search symbols in read-only kexec_purgatory
kexec_file: Use read-only sections in arch_kexec_apply_relocations*
kexec_file: Split up __kexec_load_puragory
kexec_file: Simplify kexec_purgatory_setup_sechdrs 1
kexec_file: Simplify kexec_purgatory_setup_sechdrs 2
kexec_file: Remove mis-use of sh_offset field
kexec_file: Allow archs to set purgatory load address
kexec_file: Move purgatories sha256 to common code
s390/kexec_file: Prepare setup.h for kexec_file_load
s390/kexec_file: Add purgatory
s390/kexec_file: Add kexec_file_load system call
s390/kexec_file: Add image loader
s390/kexec_file: Add crash support to image loader
s390/kexec_file: Add ELF loader
arch/powerpc/kernel/kexec_elf_64.c | 9 +-
arch/s390/Kbuild | 1 +
arch/s390/Kconfig | 4 +
arch/s390/include/asm/kexec.h | 23 ++
arch/s390/include/asm/purgatory.h | 17 ++
arch/s390/include/asm/setup.h | 40 ++-
arch/s390/kernel/Makefile | 1 +
arch/s390/kernel/asm-offsets.c | 5 +
arch/s390/kernel/compat_wrapper.c | 1 +
arch/s390/kernel/kexec_elf.c | 149 ++++++++++
arch/s390/kernel/kexec_image.c | 78 +++++
arch/s390/kernel/machine_kexec_file.c | 291 +++++++++++++++++++
arch/s390/kernel/syscalls/syscall.tbl | 1 +
arch/s390/purgatory/Makefile | 37 +++
arch/s390/purgatory/head.S | 279 ++++++++++++++++++
arch/s390/purgatory/purgatory.c | 42 +++
arch/x86/kernel/kexec-bzimage64.c | 8 +-
arch/x86/kernel/machine_kexec_64.c | 66 ++---
arch/x86/purgatory/Makefile | 3 +
arch/x86/purgatory/purgatory.c | 2 +-
include/linux/kexec.h | 38 +--
{arch/x86/purgatory => include/linux}/sha256.h | 10 +-
kernel/kexec_file.c | 375 ++++++++++++-------------
{arch/x86/purgatory => lib}/sha256.c | 4 +-
24 files changed, 1200 insertions(+), 284 deletions(-)
create mode 100644 arch/s390/include/asm/purgatory.h
create mode 100644 arch/s390/kernel/kexec_elf.c
create mode 100644 arch/s390/kernel/kexec_image.c
create mode 100644 arch/s390/kernel/machine_kexec_file.c
create mode 100644 arch/s390/purgatory/Makefile
create mode 100644 arch/s390/purgatory/head.S
create mode 100644 arch/s390/purgatory/purgatory.c
rename {arch/x86/purgatory => include/linux}/sha256.h (63%)
rename {arch/x86/purgatory => lib}/sha256.c (99%)
--
2.13.5
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 <[email protected]>
Reviewed-by: Martin Schwidefsky <[email protected]>
---
arch/s390/include/asm/kexec.h | 22 ++++++++++
arch/s390/kernel/Makefile | 2 +-
arch/s390/kernel/kexec_image.c | 80 +++++++++++++++++++++++++++++++++++
arch/s390/kernel/machine_kexec_file.c | 73 ++++++++++++++++++++++++++++++++
4 files changed, 176 insertions(+), 1 deletion(-)
create mode 100644 arch/s390/kernel/kexec_image.c
diff --git a/arch/s390/include/asm/kexec.h b/arch/s390/include/asm/kexec.h
index 1d708a419326..532f5e4f198f 100644
--- a/arch/s390/include/asm/kexec.h
+++ b/arch/s390/include/asm/kexec.h
@@ -46,4 +46,26 @@
static inline void crash_setup_regs(struct pt_regs *newregs,
struct pt_regs *oldregs) { }
+struct kimage;
+struct s390_load_data {
+ /* Pointer to the kernel buffer. Used to register cmdline etc.. */
+ void *kernel_buf;
+
+ /* Total size of loaded segments in memory. Used as an offset. */
+ size_t memsz;
+
+ /* Load address of initrd. Used to register INITRD_START in kernel. */
+ unsigned long initrd_load_addr;
+};
+
+int kexec_file_add_purgatory(struct kimage *image,
+ struct s390_load_data *data);
+int kexec_file_add_initrd(struct kimage *image,
+ struct s390_load_data *data,
+ char *initrd, unsigned long initrd_len);
+void kexec_file_update_kernel(struct kimage *iamge,
+ struct s390_load_data *data);
+
+extern const struct kexec_file_ops s390_kexec_image_ops;
+
#endif /*_S390_KEXEC_H */
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 496d4711c186..58a590709cc3 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -60,7 +60,7 @@ obj-y += debug.o irq.o ipl.o dis.o diag.o vdso.o als.o
obj-y += sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o
obj-y += runtime_instr.o cache.o fpu.o dumpstack.o guarded_storage.o sthyi.o
obj-y += entry.o reipl.o relocate_kernel.o kdebugfs.o alternative.o
-obj-y += machine_kexec_file.o
+obj-y += machine_kexec_file.o kexec_image.o
extra-y += head.o head64.o vmlinux.lds
diff --git a/arch/s390/kernel/kexec_image.c b/arch/s390/kernel/kexec_image.c
new file mode 100644
index 000000000000..83cf5a9be3a4
--- /dev/null
+++ b/arch/s390/kernel/kexec_image.c
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Image loader for kexec_file_load system call.
+ *
+ * Copyright IBM Corp. 2018
+ *
+ * Author(s): Philipp Rudo <[email protected]>
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/kexec.h>
+#include <asm/setup.h>
+
+static int kexec_file_add_image_kernel(struct kimage *image,
+ struct s390_load_data *data,
+ char *kernel, unsigned long kernel_len)
+{
+ struct kexec_buf buf;
+ int ret;
+
+ buf.image = image;
+
+ buf.buffer = kernel + STARTUP_NORMAL_OFFSET;
+ buf.bufsz = kernel_len - STARTUP_NORMAL_OFFSET;
+
+ buf.mem = STARTUP_NORMAL_OFFSET;
+ buf.memsz = buf.bufsz;
+
+ ret = kexec_add_buffer(&buf);
+
+ data->kernel_buf = kernel;
+ data->memsz += buf.memsz + STARTUP_NORMAL_OFFSET;
+
+ return ret;
+}
+
+static void *s390_image_load(struct kimage *image,
+ char *kernel, unsigned long kernel_len,
+ char *initrd, unsigned long initrd_len,
+ char *cmdline, unsigned long cmdline_len)
+{
+ struct s390_load_data data = {0};
+ int ret;
+
+ /* We don't support crash kernels yet. */
+ if (image->type == KEXEC_TYPE_CRASH)
+ return ERR_PTR(-ENOTSUPP);
+
+ ret = kexec_file_add_image_kernel(image, &data, kernel, kernel_len);
+ if (ret)
+ return ERR_PTR(ret);
+
+ if (initrd) {
+ ret = kexec_file_add_initrd(image, &data, initrd, initrd_len);
+ if (ret)
+ return ERR_PTR(ret);
+ }
+
+ ret = kexec_file_add_purgatory(image, &data);
+ if (ret)
+ return ERR_PTR(ret);
+
+ kexec_file_update_kernel(image, &data);
+
+ return NULL;
+}
+
+static int s390_image_probe(const char *buf, unsigned long len)
+{
+ /* Can't reliably tell if an image is valid. Therefore give the
+ * user whatever he wants.
+ */
+ return 0;
+}
+
+const struct kexec_file_ops s390_kexec_image_ops = {
+ .probe = s390_image_probe,
+ .load = s390_image_load,
+};
diff --git a/arch/s390/kernel/machine_kexec_file.c b/arch/s390/kernel/machine_kexec_file.c
index e6928cbed524..052640220361 100644
--- a/arch/s390/kernel/machine_kexec_file.c
+++ b/arch/s390/kernel/machine_kexec_file.c
@@ -12,9 +12,82 @@
#include <asm/setup.h>
const struct kexec_file_ops * const kexec_file_loaders[] = {
+ &s390_kexec_image_ops,
NULL,
};
+void kexec_file_update_kernel(struct kimage *image,
+ struct s390_load_data *data)
+{
+ unsigned long *loc;
+
+ /* Callers guarantee cmdline to be \0-terminated and
+ * cmdline_len < ARCH_COMMAND_LINE_SIZE.
+ */
+ if (image->cmdline_buf_len)
+ memcpy(data->kernel_buf + COMMAND_LINE_OFFSET,
+ image->cmdline_buf, image->cmdline_buf_len);
+
+ if (image->initrd_buf) {
+ loc = (unsigned long *)(data->kernel_buf + INITRD_START_OFFSET);
+ *loc = data->initrd_load_addr;
+
+ loc = (unsigned long *)(data->kernel_buf + INITRD_SIZE_OFFSET);
+ *loc = image->initrd_buf_len;
+ }
+}
+
+static int kexec_file_update_purgatory(struct kimage *image)
+{
+ u64 entry, type;
+ int ret;
+
+ entry = STARTUP_NORMAL_OFFSET;
+ ret = kexec_purgatory_get_set_symbol(image, "kernel_entry", &entry,
+ sizeof(entry), false);
+ return ret;
+}
+
+int kexec_file_add_purgatory(struct kimage *image, struct s390_load_data *data)
+{
+ struct kexec_buf buf;
+ int ret;
+
+ buf.image = image;
+
+ data->memsz = ALIGN(data->memsz, PAGE_SIZE);
+ buf.mem = data->memsz;
+
+ ret = kexec_load_purgatory(image, &buf);
+ if (ret)
+ return ret;
+
+ ret = kexec_file_update_purgatory(image);
+ return ret;
+}
+
+int kexec_file_add_initrd(struct kimage *image, struct s390_load_data *data,
+ char *initrd, unsigned long initrd_len)
+{
+ struct kexec_buf buf;
+ int ret;
+
+ buf.image = image;
+
+ buf.buffer = initrd;
+ buf.bufsz = initrd_len;
+
+ data->memsz = ALIGN(data->memsz, PAGE_SIZE);
+ buf.mem = data->memsz;
+ buf.memsz = buf.bufsz;
+
+ data->initrd_load_addr = buf.mem;
+ data->memsz += buf.memsz;
+
+ ret = kexec_add_buffer(&buf);
+ return ret;
+}
+
/*
* The kernel is loaded to a fixed location. Turn off kexec_locate_mem_hole
* and provide kbuf->mem by hand.
--
2.13.5
The code to verify the new kernels sha digest are applicable for all
architectures. Move it to common code.
Signed-off-by: Philipp Rudo <[email protected]>
---
arch/x86/purgatory/Makefile | 3 +++
arch/x86/purgatory/purgatory.c | 2 +-
{arch/x86/purgatory => include/linux}/sha256.h | 10 +++++++++-
{arch/x86/purgatory => lib}/sha256.c | 4 ++--
4 files changed, 15 insertions(+), 4 deletions(-)
rename {arch/x86/purgatory => include/linux}/sha256.h (63%)
rename {arch/x86/purgatory => lib}/sha256.c (99%)
diff --git a/arch/x86/purgatory/Makefile b/arch/x86/purgatory/Makefile
index 2f15a2ac4209..414eed6b5065 100644
--- a/arch/x86/purgatory/Makefile
+++ b/arch/x86/purgatory/Makefile
@@ -6,6 +6,9 @@ purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o string
targets += $(purgatory-y)
PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
+$(obj)/sha256.o: $(srctree)/lib/sha256.c
+ $(call if_changed_rule,cc_o_c)
+
LDFLAGS_purgatory.ro := -e purgatory_start -r --no-undefined -nostdlib -z nodefaultlib
targets += purgatory.ro
diff --git a/arch/x86/purgatory/purgatory.c b/arch/x86/purgatory/purgatory.c
index 470edad96bb9..025c34ac0d84 100644
--- a/arch/x86/purgatory/purgatory.c
+++ b/arch/x86/purgatory/purgatory.c
@@ -11,9 +11,9 @@
*/
#include <linux/bug.h>
+#include <linux/sha256.h>
#include <asm/purgatory.h>
-#include "sha256.h"
#include "../boot/string.h"
unsigned long purgatory_backup_dest __section(.kexec-purgatory);
diff --git a/arch/x86/purgatory/sha256.h b/include/linux/sha256.h
similarity index 63%
rename from arch/x86/purgatory/sha256.h
rename to include/linux/sha256.h
index 2867d9825a57..43a20ac33688 100644
--- a/arch/x86/purgatory/sha256.h
+++ b/include/linux/sha256.h
@@ -13,9 +13,17 @@
#include <linux/types.h>
#include <crypto/sha.h>
+/* Stand-alone implementation of the SHA256 algorithm. It is designed to
+ * have as little dependencies as possible so it can be used in the
+ * kexec_file purgatory. In other cases you should use the implementation in
+ * crypto/.
+ *
+ * For details see lib/sha256.c
+ */
+
extern int sha256_init(struct sha256_state *sctx);
extern int sha256_update(struct sha256_state *sctx, const u8 *input,
- unsigned int length);
+ unsigned int length);
extern int sha256_final(struct sha256_state *sctx, u8 *hash);
#endif /* SHA256_H */
diff --git a/arch/x86/purgatory/sha256.c b/lib/sha256.c
similarity index 99%
rename from arch/x86/purgatory/sha256.c
rename to lib/sha256.c
index 548ca675a14a..4400c832e2aa 100644
--- a/arch/x86/purgatory/sha256.c
+++ b/lib/sha256.c
@@ -16,9 +16,9 @@
*/
#include <linux/bitops.h>
+#include <linux/sha256.h>
+#include <linux/string.h>
#include <asm/byteorder.h>
-#include "sha256.h"
-#include "../boot/string.h"
static inline u32 Ch(u32 x, u32 y, u32 z)
{
--
2.13.5
Before the purgatory is loaded several checks are done whether the ELF file
in kexec_purgatory is valid or not. These checks are incomplete. For
example they don't check for the total size of the sections defined in the
section header table or if the entry point actually points into the
purgatory.
On the other hand the purgatory, although an ELF file on its own, is part
of the kernel. Thus not trusting the purgatory means not trusting the
kernel build itself.
So remove all validity checks on the purgatory and just trust the kernel
build.
Signed-off-by: Philipp Rudo <[email protected]>
---
kernel/kexec_file.c | 14 --------------
1 file changed, 14 deletions(-)
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index e5bcd94c1efb..0f044457b40c 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -880,22 +880,8 @@ int kexec_load_purgatory(struct kimage *image, unsigned long min,
if (kexec_purgatory_size <= 0)
return -EINVAL;
- if (kexec_purgatory_size < sizeof(Elf_Ehdr))
- return -ENOEXEC;
-
pi->ehdr = (Elf_Ehdr *)kexec_purgatory;
- if (memcmp(pi->ehdr->e_ident, ELFMAG, SELFMAG) != 0
- || pi->ehdr->e_type != ET_REL
- || !elf_check_arch(pi->ehdr)
- || pi->ehdr->e_shentsize != sizeof(Elf_Shdr))
- return -ENOEXEC;
-
- if (pi->ehdr->e_shoff >= kexec_purgatory_size
- || (pi->ehdr->e_shnum * sizeof(Elf_Shdr) >
- kexec_purgatory_size - pi->ehdr->e_shoff))
- return -ENOEXEC;
-
ret = __kexec_load_purgatory(image, min, max, top_down);
if (ret)
return ret;
--
2.13.5
The main loop currently uses quite a lot of variables to update the section
headers. Some of them are unnecessary. So clean them up a little.
Signed-off-by: Philipp Rudo <[email protected]>
---
kernel/kexec_file.c | 34 ++++++++++++----------------------
1 file changed, 12 insertions(+), 22 deletions(-)
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index bb31a3b627c2..746b91e46e34 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -724,12 +724,8 @@ static int kexec_purgatory_setup_kbuf(struct purgatory_info *pi,
static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
struct kexec_buf *kbuf)
{
- unsigned long curr_load_addr;
- unsigned long load_addr;
unsigned long bss_addr;
unsigned long offset;
- unsigned char *buf_addr;
- unsigned char *src;
Elf_Shdr *sechdrs;
int i;
@@ -762,20 +758,18 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
sechdrs[i].sh_offset;
}
- /* Load SHF_ALLOC sections */
- buf_addr = kbuf->buffer;
- load_addr = curr_load_addr = kbuf->mem;
- bss_addr = load_addr + kbuf->bufsz;
+ offset = 0;
+ bss_addr = kbuf->mem + kbuf->bufsz;
kbuf->image->start = pi->ehdr->e_entry;
for (i = 0; i < pi->ehdr->e_shnum; i++) {
unsigned long align;
+ void *src, *dst;
if (!(sechdrs[i].sh_flags & SHF_ALLOC))
continue;
align = sechdrs[i].sh_addralign;
-
if (sechdrs[i].sh_type == SHT_NOBITS) {
bss_addr = ALIGN(bss_addr, align);
sechdrs[i].sh_addr = bss_addr;
@@ -783,31 +777,27 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
continue;
}
- curr_load_addr = ALIGN(curr_load_addr, align);
- offset = curr_load_addr - load_addr;
- /* We already modifed ->sh_offset to keep src addr */
- src = (char *)sechdrs[i].sh_offset;
- memcpy(buf_addr + offset, src, sechdrs[i].sh_size);
-
+ offset = ALIGN(offset, align);
if (sechdrs[i].sh_flags & SHF_EXECINSTR &&
pi->ehdr->e_entry >= sechdrs[i].sh_addr &&
pi->ehdr->e_entry < (sechdrs[i].sh_addr
+ sechdrs[i].sh_size)) {
kbuf->image->start -= sechdrs[i].sh_addr;
- kbuf->image->start += curr_load_addr
+ kbuf->image->start += kbuf->mem + offset;
}
- /* Store load address and source address of section */
- sechdrs[i].sh_addr = curr_load_addr;
+ src = (void *)sechdrs[i].sh_offset;
+ dst = pi->purgatory_buf + offset;
+ memcpy(dst, src, sechdrs[i].sh_size);
+
+ sechdrs[i].sh_addr = kbuf->mem + offset;
/*
* This section got copied to temporary buffer. Update
* ->sh_offset accordingly.
*/
- sechdrs[i].sh_offset = (unsigned long)(buf_addr + offset);
-
- /* Advance to the next address */
- curr_load_addr += sechdrs[i].sh_size;
+ sechdrs[i].sh_offset = (unsigned long)dst;
+ offset += sechdrs[i].sh_size;
}
return 0;
--
2.13.5
To update the entry point there is an extra loop over all section headers
although this can be done in the main loop. So move it there and eliminate
the extra loop and variable to store the 'entry section index'.
Also, in the main loop, move the usual case, i.e. non-bss section, out of
the extra if-block.
Signed-off-by: Philipp Rudo <[email protected]>
Reviewed-by: Martin Schwidefsky <[email protected]>
---
kernel/kexec_file.c | 76 +++++++++++++++++++++--------------------------------
1 file changed, 30 insertions(+), 46 deletions(-)
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index d1c3ec8dc6b1..bb31a3b627c2 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -731,7 +731,6 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
unsigned char *buf_addr;
unsigned char *src;
Elf_Shdr *sechdrs;
- int entry_sidx = -1;
int i;
sechdrs = vzalloc(pi->ehdr->e_shnum * sizeof(Elf_Shdr));
@@ -763,32 +762,11 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
sechdrs[i].sh_offset;
}
- /*
- * Identify entry point section and make entry relative to section
- * start.
- */
- kbuf->image->start = pi->ehdr->e_entry;
- for (i = 0; i < pi->ehdr->e_shnum; i++) {
- if (!(sechdrs[i].sh_flags & SHF_ALLOC))
- continue;
-
- if (!(sechdrs[i].sh_flags & SHF_EXECINSTR))
- continue;
-
- /* Make entry section relative */
- if (sechdrs[i].sh_addr <= pi->ehdr->e_entry &&
- ((sechdrs[i].sh_addr + sechdrs[i].sh_size) >
- pi->ehdr->e_entry)) {
- entry_sidx = i;
- kbuf->image->start -= sechdrs[i].sh_addr;
- break;
- }
- }
-
/* Load SHF_ALLOC sections */
buf_addr = kbuf->buffer;
load_addr = curr_load_addr = kbuf->mem;
bss_addr = load_addr + kbuf->bufsz;
+ kbuf->image->start = pi->ehdr->e_entry;
for (i = 0; i < pi->ehdr->e_shnum; i++) {
unsigned long align;
@@ -797,34 +775,40 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
continue;
align = sechdrs[i].sh_addralign;
- if (sechdrs[i].sh_type != SHT_NOBITS) {
- curr_load_addr = ALIGN(curr_load_addr, align);
- offset = curr_load_addr - load_addr;
- /* We already modifed ->sh_offset to keep src addr */
- src = (char *) sechdrs[i].sh_offset;
- memcpy(buf_addr + offset, src, sechdrs[i].sh_size);
-
- /* Store load address and source address of section */
- sechdrs[i].sh_addr = curr_load_addr;
-
- /*
- * This section got copied to temporary buffer. Update
- * ->sh_offset accordingly.
- */
- sechdrs[i].sh_offset = (unsigned long)(buf_addr + offset);
-
- /* Advance to the next address */
- curr_load_addr += sechdrs[i].sh_size;
- } else {
+
+ if (sechdrs[i].sh_type == SHT_NOBITS) {
bss_addr = ALIGN(bss_addr, align);
sechdrs[i].sh_addr = bss_addr;
bss_addr += sechdrs[i].sh_size;
+ continue;
+ }
+
+ curr_load_addr = ALIGN(curr_load_addr, align);
+ offset = curr_load_addr - load_addr;
+ /* We already modifed ->sh_offset to keep src addr */
+ src = (char *)sechdrs[i].sh_offset;
+ memcpy(buf_addr + offset, src, sechdrs[i].sh_size);
+
+ if (sechdrs[i].sh_flags & SHF_EXECINSTR &&
+ pi->ehdr->e_entry >= sechdrs[i].sh_addr &&
+ pi->ehdr->e_entry < (sechdrs[i].sh_addr
+ + sechdrs[i].sh_size)) {
+ kbuf->image->start -= sechdrs[i].sh_addr;
+ kbuf->image->start += curr_load_addr
}
- }
- /* Update entry point based on load address of text section */
- if (entry_sidx >= 0)
- kbuf->image->start += sechdrs[entry_sidx].sh_addr;
+ /* Store load address and source address of section */
+ sechdrs[i].sh_addr = curr_load_addr;
+
+ /*
+ * This section got copied to temporary buffer. Update
+ * ->sh_offset accordingly.
+ */
+ sechdrs[i].sh_offset = (unsigned long)(buf_addr + offset);
+
+ /* Advance to the next address */
+ curr_load_addr += sechdrs[i].sh_size;
+ }
return 0;
}
--
2.13.5
When inspecting __kexec_load_purgatory you find that it has two tasks
1) setting up the kexec_buffer for the new kernel and,
2) setting up pi->sechdrs for the final load address.
The two tasks are independent of each other. To improve readability split
up __kexec_load_purgatory into two functions, one for each task, and call
them directly from kexec_load_purgatory.
Signed-off-by: Philipp Rudo <[email protected]>
---
kernel/kexec_file.c | 200 +++++++++++++++++++++++++++-------------------------
1 file changed, 103 insertions(+), 97 deletions(-)
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 80c7f658afc0..d1c3ec8dc6b1 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -649,39 +649,97 @@ static int kexec_calculate_store_digests(struct kimage *image)
return ret;
}
-/* Actually load purgatory. Lot of code taken from kexec-tools */
-static int __kexec_load_purgatory(struct kimage *image, unsigned long min,
- unsigned long max, int top_down)
+/*
+ * kexec_purgatory_setup_kbuf - prepare buffer to load purgatory.
+ * @pi: Purgatory to be loaded.
+ * @kbuf: Buffer to setup.
+ *
+ * Allocates the memory needed for the buffer. Caller is responsible to free
+ * the memory after use.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+static int kexec_purgatory_setup_kbuf(struct purgatory_info *pi,
+ struct kexec_buf *kbuf)
{
- struct purgatory_info *pi = &image->purgatory_info;
- unsigned long align, bss_align, bss_sz, bss_pad;
- unsigned long entry, load_addr, curr_load_addr, bss_addr, offset;
- unsigned char *buf_addr, *src;
- int i, ret = 0, entry_sidx = -1;
- const Elf_Shdr *sechdrs_c;
- Elf_Shdr *sechdrs = NULL;
- struct kexec_buf kbuf = { .image = image, .bufsz = 0, .buf_align = 1,
- .buf_min = min, .buf_max = max,
- .top_down = top_down };
+ const Elf_Shdr *sechdrs;
+ unsigned long bss_align;
+ unsigned long bss_sz;
+ unsigned long align;
+ int i, ret;
- /*
- * sechdrs_c points to section headers in purgatory and are read
- * only. No modifications allowed.
- */
- sechdrs_c = (void *)pi->ehdr + pi->ehdr->e_shoff;
+ sechdrs = (void *)pi->ehdr + pi->ehdr->e_shoff;
+ bss_align = 1;
+ bss_sz = 0;
+
+ for (i = 0; i < pi->ehdr->e_shnum; i++) {
+ if (!(sechdrs[i].sh_flags & SHF_ALLOC))
+ continue;
+
+ align = sechdrs[i].sh_addralign;
+ if (sechdrs[i].sh_type != SHT_NOBITS) {
+ if (kbuf->buf_align < align)
+ kbuf->buf_align = align;
+ kbuf->bufsz = ALIGN(kbuf->bufsz, align);
+ kbuf->bufsz += sechdrs[i].sh_size;
+ } else {
+ if (bss_align < align)
+ bss_align = align;
+ bss_sz = ALIGN(bss_sz, align);
+ bss_sz += sechdrs[i].sh_size;
+ }
+ }
+ kbuf->bufsz = ALIGN(kbuf->bufsz, bss_align);
+ kbuf->memsz = kbuf->bufsz + bss_sz;
+ if (kbuf->buf_align < bss_align)
+ kbuf->buf_align = bss_align;
+
+ kbuf->buffer = vzalloc(kbuf->bufsz);
+ if (!kbuf->buffer)
+ return -ENOMEM;
+ pi->purgatory_buf = kbuf->buffer;
+
+ ret = kexec_add_buffer(kbuf);
+ if (ret)
+ goto out;
+ pi->purgatory_load_addr = kbuf->mem;
+
+ return 0;
+out:
+ vfree(pi->purgatory_buf);
+ pi->purgatory_buf = NULL;
+ return ret;
+}
+
+/*
+ * kexec_purgatory_setup_sechdrs - prepares the pi->sechdrs buffer.
+ * @pi: Purgatory to be loaded.
+ * @kbuf: Buffer prepared to store purgatory.
+ *
+ * Allocates the memory needed for the buffer. Caller is responsible to free
+ * the memory after use.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
+ struct kexec_buf *kbuf)
+{
+ unsigned long curr_load_addr;
+ unsigned long load_addr;
+ unsigned long bss_addr;
+ unsigned long offset;
+ unsigned char *buf_addr;
+ unsigned char *src;
+ Elf_Shdr *sechdrs;
+ int entry_sidx = -1;
+ int i;
- /*
- * We can not modify sechdrs_c[] and its fields. It is read only.
- * Copy it over to a local copy where one can store some temporary
- * data and free it at the end. We need to modify ->sh_addr and
- * ->sh_offset fields to keep track of permanent and temporary
- * locations of sections.
- */
sechdrs = vzalloc(pi->ehdr->e_shnum * sizeof(Elf_Shdr));
if (!sechdrs)
return -ENOMEM;
-
- memcpy(sechdrs, sechdrs_c, pi->ehdr->e_shnum * sizeof(Elf_Shdr));
+ memcpy(sechdrs, (void *)pi->ehdr + pi->ehdr->e_shoff,
+ pi->ehdr->e_shnum * sizeof(Elf_Shdr));
+ pi->sechdrs = sechdrs;
/*
* We seem to have multiple copies of sections. First copy is which
@@ -709,7 +767,7 @@ static int __kexec_load_purgatory(struct kimage *image, unsigned long min,
* Identify entry point section and make entry relative to section
* start.
*/
- entry = pi->ehdr->e_entry;
+ kbuf->image->start = pi->ehdr->e_entry;
for (i = 0; i < pi->ehdr->e_shnum; i++) {
if (!(sechdrs[i].sh_flags & SHF_ALLOC))
continue;
@@ -722,63 +780,19 @@ static int __kexec_load_purgatory(struct kimage *image, unsigned long min,
((sechdrs[i].sh_addr + sechdrs[i].sh_size) >
pi->ehdr->e_entry)) {
entry_sidx = i;
- entry -= sechdrs[i].sh_addr;
+ kbuf->image->start -= sechdrs[i].sh_addr;
break;
}
}
- /* Determine how much memory is needed to load relocatable object. */
- bss_align = 1;
- bss_sz = 0;
-
- for (i = 0; i < pi->ehdr->e_shnum; i++) {
- if (!(sechdrs[i].sh_flags & SHF_ALLOC))
- continue;
-
- align = sechdrs[i].sh_addralign;
- if (sechdrs[i].sh_type != SHT_NOBITS) {
- if (kbuf.buf_align < align)
- kbuf.buf_align = align;
- kbuf.bufsz = ALIGN(kbuf.bufsz, align);
- kbuf.bufsz += sechdrs[i].sh_size;
- } else {
- /* bss section */
- if (bss_align < align)
- bss_align = align;
- bss_sz = ALIGN(bss_sz, align);
- bss_sz += sechdrs[i].sh_size;
- }
- }
-
- /* Determine the bss padding required to align bss properly */
- bss_pad = 0;
- if (kbuf.bufsz & (bss_align - 1))
- bss_pad = bss_align - (kbuf.bufsz & (bss_align - 1));
-
- kbuf.memsz = kbuf.bufsz + bss_pad + bss_sz;
-
- /* Allocate buffer for purgatory */
- kbuf.buffer = vzalloc(kbuf.bufsz);
- if (!kbuf.buffer) {
- ret = -ENOMEM;
- goto out;
- }
-
- if (kbuf.buf_align < bss_align)
- kbuf.buf_align = bss_align;
-
- /* Add buffer to segment list */
- ret = kexec_add_buffer(&kbuf);
- if (ret)
- goto out;
- pi->purgatory_load_addr = kbuf.mem;
-
/* Load SHF_ALLOC sections */
- buf_addr = kbuf.buffer;
- load_addr = curr_load_addr = pi->purgatory_load_addr;
- bss_addr = load_addr + kbuf.bufsz + bss_pad;
+ buf_addr = kbuf->buffer;
+ load_addr = curr_load_addr = kbuf->mem;
+ bss_addr = load_addr + kbuf->bufsz;
for (i = 0; i < pi->ehdr->e_shnum; i++) {
+ unsigned long align;
+
if (!(sechdrs[i].sh_flags & SHF_ALLOC))
continue;
@@ -810,24 +824,9 @@ static int __kexec_load_purgatory(struct kimage *image, unsigned long min,
/* Update entry point based on load address of text section */
if (entry_sidx >= 0)
- entry += sechdrs[entry_sidx].sh_addr;
-
- /* Make kernel jump to purgatory after shutdown */
- image->start = entry;
-
- /* Used later to get/set symbol values */
- pi->sechdrs = sechdrs;
+ kbuf->image->start += sechdrs[entry_sidx].sh_addr;
- /*
- * Used later to identify which section is purgatory and skip it
- * from checksumming.
- */
- pi->purgatory_buf = kbuf.buffer;
- return ret;
-out:
- vfree(sechdrs);
- vfree(kbuf.buffer);
- return ret;
+ return 0;
}
static int kexec_apply_relocations(struct kimage *image)
@@ -897,16 +896,23 @@ int kexec_load_purgatory(struct kimage *image, unsigned long min,
{
struct purgatory_info *pi = &image->purgatory_info;
int ret;
+ struct kexec_buf kbuf = { .image = image, .bufsz = 0, .buf_align = 1,
+ .buf_min = min, .buf_max = max,
+ .top_down = top_down };
if (kexec_purgatory_size <= 0)
return -EINVAL;
pi->ehdr = (const Elf_Ehdr *)kexec_purgatory;
- ret = __kexec_load_purgatory(image, min, max, top_down);
+ ret = kexec_purgatory_setup_kbuf(pi, &kbuf);
if (ret)
return ret;
+ ret = kexec_purgatory_setup_sechdrs(pi, &kbuf);
+ if (ret)
+ goto out_free_kbuf;
+
ret = kexec_apply_relocations(image);
if (ret)
goto out;
@@ -916,7 +922,7 @@ int kexec_load_purgatory(struct kimage *image, unsigned long min,
out:
vfree(pi->sechdrs);
pi->sechdrs = NULL;
-
+out_free_kbuf:
vfree(pi->purgatory_buf);
pi->purgatory_buf = NULL;
return ret;
--
2.13.5
When building the kernel with CONFIG_KEXEC_FILE enabled gcc prints a
compile warning multiple times.
In file included from <path>/linux/init/initramfs.c:526:0:
<path>/include/linux/kexec.h:120:9: warning: ‘struct kimage’ declared inside parameter list [enabled by default]
unsigned long cmdline_len);
^
This is because the typedefs for kexec_file_load uses struct kimage before
it is declared. Fix this by simply forward declaring struct kimage.
Signed-off-by: Philipp Rudo <[email protected]>
---
include/linux/kexec.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index f16f6ceb3875..7bae5e87bf0d 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -114,6 +114,8 @@ struct purgatory_info {
unsigned long purgatory_load_addr;
};
+struct kimage;
+
typedef int (kexec_probe_t)(const char *kernel_buf, unsigned long kernel_size);
typedef void *(kexec_load_t)(struct kimage *image, char *kernel_buf,
unsigned long kernel_len, char *initrd,
--
2.13.5
When the relocations are applied to the purgatory only the section the
relocations are applied to is writable. The other sections, i.e. the symtab
and .rel/.rela, are in read-only kexec_purgatory. Highlight this by marking
the corresponding variables as 'const'.
While at it also change the signatures of arch_kexec_apply_relocations* to
take section pointers instead of just the index of the relocation section.
This removes the second lookup and sanity check of the sections in arch
code.
Signed-off-by: Philipp Rudo <[email protected]>
---
arch/x86/kernel/machine_kexec_64.c | 56 ++++++++++++---------------------
include/linux/kexec.h | 12 +++++---
kernel/kexec_file.c | 63 +++++++++++++++++++++++++-------------
3 files changed, 70 insertions(+), 61 deletions(-)
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index 1f790cf9d38f..6be04e4d4a7e 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -422,52 +422,36 @@ int arch_kexec_kernel_verify_sig(struct kimage *image, void *kernel,
/*
* Apply purgatory relocations.
*
- * ehdr: Pointer to elf headers
- * sechdrs: Pointer to section headers.
- * relsec: section index of SHT_RELA section.
+ * @pi: Purgatory to be relocated.
+ * @section: Section relocations applying to.
+ * @relsec: Section containing RELAs.
+ * @symtabsec: Corresponding symtab.
*
* TODO: Some of the code belongs to generic code. Move that in kexec.c.
*/
-int arch_kexec_apply_relocations_add(const Elf64_Ehdr *ehdr,
- Elf64_Shdr *sechdrs, unsigned int relsec)
+int arch_kexec_apply_relocations_add(struct purgatory_info *pi,
+ Elf_Shdr *section, const Elf_Shdr *relsec,
+ const Elf_Shdr *symtabsec)
{
unsigned int i;
Elf64_Rela *rel;
Elf64_Sym *sym;
void *location;
- Elf64_Shdr *section, *symtabsec;
unsigned long address, sec_base, value;
const char *strtab, *name, *shstrtab;
+ const Elf_Shdr *sechdrs;
- /*
- * ->sh_offset has been modified to keep the pointer to section
- * contents in memory
- */
- rel = (void *)sechdrs[relsec].sh_offset;
-
- /* Section to which relocations apply */
- section = &sechdrs[sechdrs[relsec].sh_info];
-
- pr_debug("Applying relocate section %u to %u\n", relsec,
- sechdrs[relsec].sh_info);
-
- /* Associated symbol table */
- symtabsec = &sechdrs[sechdrs[relsec].sh_link];
-
- /* String table */
- if (symtabsec->sh_link >= ehdr->e_shnum) {
- /* Invalid strtab section number */
- pr_err("Invalid string table section index %d\n",
- symtabsec->sh_link);
- return -ENOEXEC;
- }
+ /* String & section header string table */
+ sechdrs = (void *)pi->ehdr + pi->ehdr->e_shoff;
+ strtab = (char *)pi->ehdr + sechdrs[symtabsec->sh_link].sh_offset;
+ shstrtab = (char *)pi->ehdr + sechdrs[pi->ehdr->e_shstrndx].sh_offset;
- strtab = (char *)sechdrs[symtabsec->sh_link].sh_offset;
+ rel = (void *)pi->ehdr + relsec->sh_offset;
- /* section header string table */
- shstrtab = (char *)sechdrs[ehdr->e_shstrndx].sh_offset;
+ pr_debug("Applying relocate section %s to %u\n",
+ shstrtab + relsec->sh_name, relsec->sh_info);
- for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+ for (i = 0; i < relsec->sh_size / sizeof(*rel); i++) {
/*
* rel[i].r_offset contains byte offset from beginning
@@ -490,8 +474,8 @@ int arch_kexec_apply_relocations_add(const Elf64_Ehdr *ehdr,
* to apply. ELF64_R_SYM() and ELF64_R_TYPE() macros get
* these respectively.
*/
- sym = (Elf64_Sym *)symtabsec->sh_offset +
- ELF64_R_SYM(rel[i].r_info);
+ sym = (void *)pi->ehdr + symtabsec->sh_offset;
+ sym += ELF64_R_SYM(rel[i].r_info);
if (sym->st_name)
name = strtab + sym->st_name;
@@ -514,12 +498,12 @@ int arch_kexec_apply_relocations_add(const Elf64_Ehdr *ehdr,
if (sym->st_shndx == SHN_ABS)
sec_base = 0;
- else if (sym->st_shndx >= ehdr->e_shnum) {
+ else if (sym->st_shndx >= pi->ehdr->e_shnum) {
pr_err("Invalid section %d for symbol %s\n",
sym->st_shndx, name);
return -ENOEXEC;
} else
- sec_base = sechdrs[sym->st_shndx].sh_addr;
+ sec_base = pi->sechdrs[sym->st_shndx].sh_addr;
value = sym->st_value;
value += sec_base;
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index 10842eece180..f15446be0e25 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -290,10 +290,14 @@ void * __weak arch_kexec_kernel_image_load(struct kimage *image);
int __weak arch_kimage_file_post_load_cleanup(struct kimage *image);
int __weak arch_kexec_kernel_verify_sig(struct kimage *image, void *buf,
unsigned long buf_len);
-int __weak arch_kexec_apply_relocations_add(const Elf_Ehdr *ehdr,
- Elf_Shdr *sechdrs, unsigned int relsec);
-int __weak arch_kexec_apply_relocations(const Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
- unsigned int relsec);
+int __weak arch_kexec_apply_relocations_add(struct purgatory_info *pi,
+ Elf_Shdr *section,
+ const Elf_Shdr *relsec,
+ const Elf_Shdr *symtab);
+int __weak arch_kexec_apply_relocations(struct purgatory_info *pi,
+ Elf_Shdr *section,
+ const Elf_Shdr *relsec,
+ const Elf_Shdr *symtab);
void arch_kexec_protect_crashkres(void);
void arch_kexec_unprotect_crashkres(void);
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 2072b288ec53..80c7f658afc0 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -53,19 +53,35 @@ int __weak arch_kexec_kernel_verify_sig(struct kimage *image, void *buf,
}
#endif
-/* Apply relocations of type RELA */
+/*
+ * arch_kexec_apply_relocations_add - apply relocations of type RELA
+ * @pi: Purgatory to be relocated.
+ * @section: Section relocations applying to.
+ * @relsec: Section containing RELAs.
+ * @symtab: Corresponding symtab.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
int __weak
-arch_kexec_apply_relocations_add(const Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
- unsigned int relsec)
+arch_kexec_apply_relocations_add(struct purgatory_info *pi, Elf_Shdr *section,
+ const Elf_Shdr *relsec, const Elf_Shdr *symtab)
{
pr_err("RELA relocation unsupported.\n");
return -ENOEXEC;
}
-/* Apply relocations of type REL */
+/*
+ * arch_kexec_apply_relocations - apply relocations of type REL
+ * @pi: Purgatory to be relocated.
+ * @section: Section relocations applying to.
+ * @relsec: Section containing RELs.
+ * @symtab: Corresponding symtab.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
int __weak
-arch_kexec_apply_relocations(const Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
- unsigned int relsec)
+arch_kexec_apply_relocations(struct purgatory_info *pi, Elf_Shdr *section,
+ const Elf_Shdr *relsec, const Elf_Shdr *symtab)
{
pr_err("REL relocation unsupported.\n");
return -ENOEXEC;
@@ -818,14 +834,19 @@ static int kexec_apply_relocations(struct kimage *image)
{
int i, ret;
struct purgatory_info *pi = &image->purgatory_info;
- Elf_Shdr *sechdrs = pi->sechdrs;
+ const Elf_Shdr *sechdrs;
+
+ sechdrs = (void *)pi->ehdr + pi->ehdr->e_shoff;
- /* Apply relocations */
for (i = 0; i < pi->ehdr->e_shnum; i++) {
- Elf_Shdr *section, *symtab;
+ const Elf_Shdr *relsec;
+ const Elf_Shdr *symtab;
+ Elf_Shdr *section;
+
+ relsec = sechdrs + i;
- if (sechdrs[i].sh_type != SHT_RELA &&
- sechdrs[i].sh_type != SHT_REL)
+ if (relsec->sh_type != SHT_RELA &&
+ relsec->sh_type != SHT_REL)
continue;
/*
@@ -834,12 +855,12 @@ static int kexec_apply_relocations(struct kimage *image)
* symbol table. And ->sh_info contains section header
* index of section to which relocations apply.
*/
- if (sechdrs[i].sh_info >= pi->ehdr->e_shnum ||
- sechdrs[i].sh_link >= pi->ehdr->e_shnum)
+ if (relsec->sh_info >= pi->ehdr->e_shnum ||
+ relsec->sh_link >= pi->ehdr->e_shnum)
return -ENOEXEC;
- section = &sechdrs[sechdrs[i].sh_info];
- symtab = &sechdrs[sechdrs[i].sh_link];
+ section = pi->sechdrs + relsec->sh_info;
+ symtab = sechdrs + relsec->sh_link;
if (!(section->sh_flags & SHF_ALLOC))
continue;
@@ -856,12 +877,12 @@ static int kexec_apply_relocations(struct kimage *image)
* Respective architecture needs to provide support for applying
* relocations of type SHT_RELA/SHT_REL.
*/
- if (sechdrs[i].sh_type == SHT_RELA)
- ret = arch_kexec_apply_relocations_add(pi->ehdr,
- sechdrs, i);
- else if (sechdrs[i].sh_type == SHT_REL)
- ret = arch_kexec_apply_relocations(pi->ehdr,
- sechdrs, i);
+ if (relsec->sh_type == SHT_RELA)
+ ret = arch_kexec_apply_relocations_add(pi, section,
+ relsec, symtab);
+ else if (relsec->sh_type == SHT_REL)
+ ret = arch_kexec_apply_relocations(pi, section,
+ relsec, symtab);
if (ret)
return ret;
}
--
2.13.5
The stripped purgatory does not contain a symtab. So when looking for
symbols this is done in read-only kexec_purgatory. Highlight this by
marking the corresponding variables as 'const'.
Signed-off-by: Philipp Rudo <[email protected]>
---
kernel/kexec_file.c | 38 ++++++++++++++++++++++----------------
1 file changed, 22 insertions(+), 16 deletions(-)
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 06fc9fdd2474..2072b288ec53 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -901,20 +901,27 @@ int kexec_load_purgatory(struct kimage *image, unsigned long min,
return ret;
}
-static Elf_Sym *kexec_purgatory_find_symbol(struct purgatory_info *pi,
- const char *name)
+/*
+ * kexec_purgatory_find_symbol - find a symbol in the purgatory
+ * @pi: Purgatory to search in.
+ * @name: Name of the symbol.
+ *
+ * Return: pointer to symbol in read-only symtab on success, NULL on error.
+ */
+static const Elf_Sym *kexec_purgatory_find_symbol(struct purgatory_info *pi,
+ const char *name)
{
+ const Elf_Shdr *sechdrs;
const Elf_Ehdr *ehdr;
- Elf_Sym *syms;
- Elf_Shdr *sechdrs;
- int i, k;
+ const Elf_Sym *syms;
const char *strtab;
+ int i, k;
- if (!pi->sechdrs || !pi->ehdr)
+ if (!pi->ehdr)
return NULL;
- sechdrs = pi->sechdrs;
ehdr = pi->ehdr;
+ sechdrs = (void *)ehdr + ehdr->e_shoff;
for (i = 0; i < ehdr->e_shnum; i++) {
if (sechdrs[i].sh_type != SHT_SYMTAB)
@@ -923,8 +930,8 @@ static Elf_Sym *kexec_purgatory_find_symbol(struct purgatory_info *pi,
if (sechdrs[i].sh_link >= ehdr->e_shnum)
/* Invalid strtab section number */
continue;
- strtab = (char *)sechdrs[sechdrs[i].sh_link].sh_offset;
- syms = (Elf_Sym *)sechdrs[i].sh_offset;
+ strtab = (void *)ehdr + sechdrs[sechdrs[i].sh_link].sh_offset;
+ syms = (void *)ehdr + sechdrs[i].sh_offset;
/* Go through symbols for a match */
for (k = 0; k < sechdrs[i].sh_size/sizeof(Elf_Sym); k++) {
@@ -952,7 +959,7 @@ static Elf_Sym *kexec_purgatory_find_symbol(struct purgatory_info *pi,
void *kexec_purgatory_get_symbol_addr(struct kimage *image, const char *name)
{
struct purgatory_info *pi = &image->purgatory_info;
- Elf_Sym *sym;
+ const Elf_Sym *sym;
Elf_Shdr *sechdr;
sym = kexec_purgatory_find_symbol(pi, name);
@@ -975,9 +982,9 @@ void *kexec_purgatory_get_symbol_addr(struct kimage *image, const char *name)
int kexec_purgatory_get_set_symbol(struct kimage *image, const char *name,
void *buf, unsigned int size, bool get_value)
{
- Elf_Sym *sym;
- Elf_Shdr *sechdrs;
struct purgatory_info *pi = &image->purgatory_info;
+ const Elf_Sym *sym;
+ Elf_Shdr *sec;
char *sym_buf;
sym = kexec_purgatory_find_symbol(pi, name);
@@ -990,16 +997,15 @@ int kexec_purgatory_get_set_symbol(struct kimage *image, const char *name,
return -EINVAL;
}
- sechdrs = pi->sechdrs;
+ sec = pi->sechdrs + sym->st_shndx;
- if (sechdrs[sym->st_shndx].sh_type == SHT_NOBITS) {
+ if (sec->sh_type == SHT_NOBITS) {
pr_err("symbol %s is in a bss section. Cannot %s\n", name,
get_value ? "get" : "set");
return -EINVAL;
}
- sym_buf = (unsigned char *)sechdrs[sym->st_shndx].sh_offset +
- sym->st_value;
+ sym_buf = (char *)sec->sh_offset + sym->st_value;
if (get_value)
memcpy((void *)buf, sym_buf, size);
--
2.13.5
The kexec_purgatory buffer is read-only. Thus all pointers into
kexec_purgatory are read-only, too. Point this out by explicitly marking
purgatory_info->ehdr as 'const' and update the comments in purgatory_info.
Signed-off-by: Philipp Rudo <[email protected]>
---
include/linux/kexec.h | 17 +++++++++++------
kernel/kexec_file.c | 4 ++--
2 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index 7bae5e87bf0d..10842eece180 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -99,14 +99,19 @@ struct compat_kexec_segment {
#ifdef CONFIG_KEXEC_FILE
struct purgatory_info {
- /* Pointer to elf header of read only purgatory */
- Elf_Ehdr *ehdr;
-
- /* Pointer to purgatory sechdrs which are modifiable */
+ /*
+ * Pointer to elf header at the beginning of kexec_purgatory.
+ * Note: kexec_purgatory is read only
+ */
+ const Elf_Ehdr *ehdr;
+ /*
+ * Temporary, modifiable buffer for sechdrs used for relocation.
+ * This memory can be freed post image load.
+ */
Elf_Shdr *sechdrs;
/*
- * Temporary buffer location where purgatory is loaded and relocated
- * This memory can be freed post image load
+ * Temporary, modifiable buffer for stripped purgatory used for
+ * relocation. This memory can be freed post image load.
*/
void *purgatory_buf;
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 0f044457b40c..06fc9fdd2474 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -880,7 +880,7 @@ int kexec_load_purgatory(struct kimage *image, unsigned long min,
if (kexec_purgatory_size <= 0)
return -EINVAL;
- pi->ehdr = (Elf_Ehdr *)kexec_purgatory;
+ pi->ehdr = (const Elf_Ehdr *)kexec_purgatory;
ret = __kexec_load_purgatory(image, min, max, top_down);
if (ret)
@@ -904,9 +904,9 @@ int kexec_load_purgatory(struct kimage *image, unsigned long min,
static Elf_Sym *kexec_purgatory_find_symbol(struct purgatory_info *pi,
const char *name)
{
+ const Elf_Ehdr *ehdr;
Elf_Sym *syms;
Elf_Shdr *sechdrs;
- Elf_Ehdr *ehdr;
int i, k;
const char *strtab;
--
2.13.5
The current code uses the sh_offset field in purgatory_info->sechdrs to
store a pointer to the current load address of the section. Depending
whether the section will be loaded or not this is either a pointer into
purgatory_info->purgatory_buf or kexec_purgatory. This is not only a
violation of the ELF standard but also makes the code very hard to
understand as you cannot tell if the memory you are using is read-only or
not.
Remove this mis-use and store the offset of the section in
pugaroty_info->purgatory_buf in sh_offset.
Signed-off-by: Philipp Rudo <[email protected]>
---
arch/x86/kernel/machine_kexec_64.c | 10 ++++++----
kernel/kexec_file.c | 33 +++------------------------------
2 files changed, 9 insertions(+), 34 deletions(-)
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index 6be04e4d4a7e..cf233e878d28 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -457,13 +457,15 @@ int arch_kexec_apply_relocations_add(struct purgatory_info *pi,
* rel[i].r_offset contains byte offset from beginning
* of section to the storage unit affected.
*
- * This is location to update (->sh_offset). This is temporary
- * buffer where section is currently loaded. This will finally
- * be loaded to a different address later, pointed to by
+ * This is location to update. This is temporary buffer
+ * where section is currently loaded. This will finally be
+ * loaded to a different address later, pointed to by
* ->sh_addr. kexec takes care of moving it
* (kexec_load_segment()).
*/
- location = (void *)(section->sh_offset + rel[i].r_offset);
+ location = pi->purgatory_buf;
+ location += section->sh_offset;
+ location += rel[i].r_offset;
/* Final address of the location */
address = section->sh_addr + rel[i].r_offset;
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 746b91e46e34..25b44d1a664a 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -736,28 +736,6 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
pi->ehdr->e_shnum * sizeof(Elf_Shdr));
pi->sechdrs = sechdrs;
- /*
- * We seem to have multiple copies of sections. First copy is which
- * is embedded in kernel in read only section. Some of these sections
- * will be copied to a temporary buffer and relocated. And these
- * sections will finally be copied to their final destination at
- * segment load time.
- *
- * Use ->sh_offset to reflect section address in memory. It will
- * point to original read only copy if section is not allocatable.
- * Otherwise it will point to temporary copy which will be relocated.
- *
- * Use ->sh_addr to contain final address of the section where it
- * will go during execution time.
- */
- for (i = 0; i < pi->ehdr->e_shnum; i++) {
- if (sechdrs[i].sh_type == SHT_NOBITS)
- continue;
-
- sechdrs[i].sh_offset = (unsigned long)pi->ehdr +
- sechdrs[i].sh_offset;
- }
-
offset = 0;
bss_addr = kbuf->mem + kbuf->bufsz;
kbuf->image->start = pi->ehdr->e_entry;
@@ -786,17 +764,12 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
kbuf->image->start += kbuf->mem + offset;
}
- src = (void *)sechdrs[i].sh_offset;
+ src = (void *)pi->ehdr + sechdrs[i].sh_offset;
dst = pi->purgatory_buf + offset;
memcpy(dst, src, sechdrs[i].sh_size);
sechdrs[i].sh_addr = kbuf->mem + offset;
-
- /*
- * This section got copied to temporary buffer. Update
- * ->sh_offset accordingly.
- */
- sechdrs[i].sh_offset = (unsigned long)dst;
+ sechdrs[i].sh_offset = offset;
offset += sechdrs[i].sh_size;
}
@@ -1006,7 +979,7 @@ int kexec_purgatory_get_set_symbol(struct kimage *image, const char *name,
return -EINVAL;
}
- sym_buf = (char *)sec->sh_offset + sym->st_value;
+ sym_buf = (char *)pi->purgatory_buf + sec->sh_offset + sym->st_value;
if (get_value)
memcpy((void *)buf, sym_buf, size);
--
2.13.5
The common code expects the architecture to have a purgatory that runs
between the two kernels. Add it now. For simplicity first skip crash
support.
Signed-off-by: Philipp Rudo <[email protected]>
---
arch/s390/Kbuild | 1 +
arch/s390/include/asm/purgatory.h | 17 +++++++
arch/s390/kernel/asm-offsets.c | 5 ++
arch/s390/purgatory/Makefile | 37 +++++++++++++++
arch/s390/purgatory/head.S | 96 +++++++++++++++++++++++++++++++++++++++
arch/s390/purgatory/purgatory.c | 38 ++++++++++++++++
6 files changed, 194 insertions(+)
create mode 100644 arch/s390/include/asm/purgatory.h
create mode 100644 arch/s390/purgatory/Makefile
create mode 100644 arch/s390/purgatory/head.S
create mode 100644 arch/s390/purgatory/purgatory.c
diff --git a/arch/s390/Kbuild b/arch/s390/Kbuild
index 9fdff3fe1a42..091f14bc9af0 100644
--- a/arch/s390/Kbuild
+++ b/arch/s390/Kbuild
@@ -8,3 +8,4 @@ obj-$(CONFIG_APPLDATA_BASE) += appldata/
obj-y += net/
obj-$(CONFIG_PCI) += pci/
obj-$(CONFIG_NUMA) += numa/
+obj-y += purgatory/
diff --git a/arch/s390/include/asm/purgatory.h b/arch/s390/include/asm/purgatory.h
new file mode 100644
index 000000000000..e297bcfc476f
--- /dev/null
+++ b/arch/s390/include/asm/purgatory.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright IBM Corp. 2018
+ *
+ * Author(s): Philipp Rudo <[email protected]>
+ */
+
+#ifndef _S390_PURGATORY_H_
+#define _S390_PURGATORY_H_
+#ifndef __ASSEMBLY__
+
+#include <linux/purgatory.h>
+
+int verify_sha256_digest(void);
+
+#endif /* __ASSEMBLY__ */
+#endif /* _S390_PURGATORY_H_ */
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
index 587b195b588d..a22b478de567 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -10,6 +10,7 @@
#include <linux/kbuild.h>
#include <linux/kvm_host.h>
#include <linux/sched.h>
+#include <linux/purgatory.h>
#include <asm/idle.h>
#include <asm/vdso.h>
#include <asm/pgtable.h>
@@ -203,5 +204,9 @@ int main(void)
OFFSET(__GMAP_ASCE, gmap, asce);
OFFSET(__SIE_PROG0C, kvm_s390_sie_block, prog0c);
OFFSET(__SIE_PROG20, kvm_s390_sie_block, prog20);
+ /* kexec_sha_region */
+ OFFSET(__KEXEC_SHA_REGION_START, kexec_sha_region, start);
+ OFFSET(__KEXEC_SHA_REGION_LEN, kexec_sha_region, len);
+ DEFINE(__KEXEC_SHA_REGION_SIZE, sizeof(struct kexec_sha_region));
return 0;
}
diff --git a/arch/s390/purgatory/Makefile b/arch/s390/purgatory/Makefile
new file mode 100644
index 000000000000..c4b405d9c713
--- /dev/null
+++ b/arch/s390/purgatory/Makefile
@@ -0,0 +1,37 @@
+# SPDX-License-Identifier: GPL-2.0
+
+OBJECT_FILES_NON_STANDARD := y
+
+purgatory-y := head.o purgatory.o string.o sha256.o mem.o
+
+targets += $(purgatory-y) purgatory.ro kexec-purgatory.c
+PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
+
+$(obj)/sha256.o: $(srctree)/lib/sha256.c
+ $(call if_changed_rule,cc_o_c)
+
+$(obj)/mem.o: $(srctree)/arch/s390/lib/mem.S
+ $(call if_changed_rule,as_o_S)
+
+$(obj)/string.o: $(srctree)/arch/s390/lib/string.c
+ $(call if_changed_rule,cc_o_c)
+
+LDFLAGS_purgatory.ro := -e purgatory_start -r --no-undefined -nostdlib
+LDFLAGS_purgatory.ro += -z nodefaultlib
+KBUILD_CFLAGS := -fno-strict-aliasing -Wall -Wstrict-prototypes
+KBUILD_CFLAGS += -Wno-pointer-sign -Wno-sign-compare
+KBUILD_CFLAGS += -fno-zero-initialized-in-bss -fno-builtin -ffreestanding
+KBUILD_CFLAGS += -c -MD -Os -m64
+KBUILD_CFLAGS += $(call cc-option,-fno-PIE)
+
+$(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
+ $(call if_changed,ld)
+
+CMD_BIN2C = $(objtree)/scripts/basic/bin2c
+quiet_cmd_bin2c = BIN2C $@
+ cmd_bin2c = $(CMD_BIN2C) kexec_purgatory < $< > $@
+
+$(obj)/kexec-purgatory.c: $(obj)/purgatory.ro FORCE
+ $(call if_changed,bin2c)
+
+obj-y += kexec-purgatory.o
diff --git a/arch/s390/purgatory/head.S b/arch/s390/purgatory/head.S
new file mode 100644
index 000000000000..8735409d0280
--- /dev/null
+++ b/arch/s390/purgatory/head.S
@@ -0,0 +1,96 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Purgatory setup code
+ *
+ * Copyright IBM Corp. 2018
+ *
+ * Author(s): Philipp Rudo <[email protected]>
+ */
+
+#include <linux/linkage.h>
+#include <asm/asm-offsets.h>
+#include <asm/page.h>
+#include <asm/sigp.h>
+
+/* The purgatory is the code running between two kernels. It's main purpose
+ * is to verify that the next kernel was not corrupted after load and to
+ * start it.
+ */
+
+.macro START_NEXT_KERNEL base
+ lg %r4,kernel_entry-\base(%r13)
+ lg %r5,load_psw_mask-\base(%r13)
+ ogr %r4,%r5
+ stg %r4,0(%r0)
+
+ xgr %r0,%r0
+ diag %r0,%r0,0x308
+.endm
+
+.text
+.align PAGE_SIZE
+ENTRY(purgatory_start)
+ /* The purgatory might be called after a diag308 so better set
+ * architecture and addressing mode.
+ */
+ lhi %r1,1
+ sigp %r1,%r0,SIGP_SET_ARCHITECTURE
+ sam64
+
+ larl %r5,gprregs
+ stmg %r6,%r15,0(%r5)
+
+ basr %r13,0
+.base_crash:
+
+ /* Setup stack */
+ larl %r15,purgatory_end
+ aghi %r15,-160
+
+.do_checksum_verification:
+ brasl %r14,verify_sha256_digest
+
+ cghi %r2,0 /* checksum match */
+ jne .disabled_wait
+
+ /* start normal kernel */
+ START_NEXT_KERNEL .base_crash
+
+.disabled_wait:
+ lpswe disabled_wait_psw-.base_crash(%r13)
+
+
+load_psw_mask:
+ .long 0x00080000,0x80000000
+
+ .align 8
+disabled_wait_psw:
+ .quad 0x0002000180000000
+ .quad 0x0000000000000000 + .do_checksum_verification
+
+gprregs:
+ .rept 10
+ .quad 0
+ .endr
+
+purgatory_sha256_digest:
+ .global purgatory_sha256_digest
+ .rept 32 /* SHA256_DIGEST_SIZE */
+ .byte 0
+ .endr
+
+purgatory_sha_regions:
+ .global purgatory_sha_regions
+ .rept 16 * __KEXEC_SHA_REGION_SIZE /* KEXEC_SEGMENTS_MAX */
+ .byte 0
+ .endr
+
+kernel_entry:
+ .global kernel_entry
+ .quad 0
+
+ .align PAGE_SIZE
+stack:
+ .skip PAGE_SIZE
+ .align PAGE_SIZE
+purgatory_end:
diff --git a/arch/s390/purgatory/purgatory.c b/arch/s390/purgatory/purgatory.c
new file mode 100644
index 000000000000..fec67b58b8be
--- /dev/null
+++ b/arch/s390/purgatory/purgatory.c
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Purgatory code running between two kernels.
+ *
+ * Copyright IBM Corp. 2018
+ *
+ * Author(s): Philipp Rudo <[email protected]>
+ */
+
+#include <linux/kexec.h>
+#include <linux/sha256.h>
+#include <linux/string.h>
+#include <asm/purgatory.h>
+
+struct kexec_sha_region purgatory_sha_regions[KEXEC_SEGMENT_MAX];
+u8 purgatory_sha256_digest[SHA256_DIGEST_SIZE];
+
+u64 kernel_entry;
+
+int verify_sha256_digest(void)
+{
+ struct kexec_sha_region *ptr, *end;
+ u8 digest[SHA256_DIGEST_SIZE];
+ struct sha256_state sctx;
+
+ sha256_init(&sctx);
+ end = purgatory_sha_regions + ARRAY_SIZE(purgatory_sha_regions);
+
+ for (ptr = purgatory_sha_regions; ptr < end; ptr++)
+ sha256_update(&sctx, (uint8_t *)(ptr->start), ptr->len);
+
+ sha256_final(&sctx, digest);
+
+ if (memcmp(digest, purgatory_sha256_digest, sizeof(digest)))
+ return 1;
+
+ return 0;
+}
--
2.13.5
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 <[email protected]>
---
arch/s390/Kconfig | 4 +
arch/s390/kernel/Makefile | 1 +
arch/s390/kernel/compat_wrapper.c | 1 +
arch/s390/kernel/machine_kexec_file.c | 174 ++++++++++++++++++++++++++++++++++
arch/s390/kernel/syscalls/syscall.tbl | 1 +
5 files changed, 181 insertions(+)
create mode 100644 arch/s390/kernel/machine_kexec_file.c
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 0105ce28e246..baffd88109a5 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -51,6 +51,10 @@ config KEXEC
def_bool y
select KEXEC_CORE
+config KEXEC_FILE
+ def_bool y
+ select KEXEC_CORE
+
config AUDIT_ARCH
def_bool y
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 909bce65cb2b..496d4711c186 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -60,6 +60,7 @@ obj-y += debug.o irq.o ipl.o dis.o diag.o vdso.o als.o
obj-y += sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o
obj-y += runtime_instr.o cache.o fpu.o dumpstack.o guarded_storage.o sthyi.o
obj-y += entry.o reipl.o relocate_kernel.o kdebugfs.o alternative.o
+obj-y += machine_kexec_file.o
extra-y += head.o head64.o vmlinux.lds
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,
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)
diff --git a/arch/s390/kernel/machine_kexec_file.c b/arch/s390/kernel/machine_kexec_file.c
new file mode 100644
index 000000000000..e6928cbed524
--- /dev/null
+++ b/arch/s390/kernel/machine_kexec_file.c
@@ -0,0 +1,174 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * s390 code for kexec_file_load system call
+ *
+ * Copyright IBM Corp. 2018
+ *
+ * Author(s): Philipp Rudo <[email protected]>
+ */
+
+#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)
+{
+ struct kexec_file_ops *fops;
+ int i, ret;
+
+ /* 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;
+
+ for (i = 0; i < ARRAY_SIZE(kexec_file_loaders); i++) {
+ fops = kexec_file_loaders[i];
+ if (!fops || !fops->probe)
+ continue;
+
+ ret = fops->probe(buf, buf_len);
+ if (!ret) {
+ image->fops = fops;
+ return ret;
+ }
+ }
+
+ return -ENOEXEC;
+}
+
+void *arch_kexec_kernel_image_load(struct kimage *image)
+{
+ if (!image->fops || !image->fops->load)
+ return ERR_PTR(-ENOEXEC);
+
+ if (image->cmdline_buf_len >= ARCH_COMMAND_LINE_SIZE)
+ return ERR_PTR(-EINVAL);
+
+ return image->fops->load(image, image->kernel_buf,
+ image->kernel_buf_len, image->initrd_buf,
+ image->initrd_buf_len, image->cmdline_buf,
+ image->cmdline_buf_len);
+}
+
+int arch_kimage_file_post_load_cleanup(struct kimage *image)
+{
+ if (!image->fops || !image->fops->cleanup)
+ return 0;
+
+ return image->fops->cleanup(image->image_loader_data);
+}
+
+#ifdef CONFIG_KEXEC_VERIFY_SIG
+int arch_kexec_kernel_verify_sig(struct kimage *image, void *kernel,
+ unsigned long kernel_len)
+{
+ if (!image->fops || !image->fops->verify_sig)
+ return -EKEYREJECTED;
+
+ return image->fops->verify_sig(kernel, kernel_len);
+}
+#endif /* CONFIG_KEXEC_VERIFY_SIG */
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 @@
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
--
2.13.5
Add support to load a crash kernel to the image loader. This requires
extending the purgatory.
Signed-off-by: Philipp Rudo <[email protected]>
Reviewed-by: Martin Schwidefsky <[email protected]>
---
arch/s390/kernel/kexec_image.c | 6 +-
arch/s390/kernel/machine_kexec_file.c | 45 ++++++++-
arch/s390/purgatory/head.S | 185 +++++++++++++++++++++++++++++++++-
arch/s390/purgatory/purgatory.c | 4 +
4 files changed, 234 insertions(+), 6 deletions(-)
diff --git a/arch/s390/kernel/kexec_image.c b/arch/s390/kernel/kexec_image.c
index 83cf5a9be3a4..60e03f7048b9 100644
--- a/arch/s390/kernel/kexec_image.c
+++ b/arch/s390/kernel/kexec_image.c
@@ -25,6 +25,8 @@ static int kexec_file_add_image_kernel(struct kimage *image,
buf.bufsz = kernel_len - STARTUP_NORMAL_OFFSET;
buf.mem = STARTUP_NORMAL_OFFSET;
+ if (image->type == KEXEC_TYPE_CRASH)
+ buf.mem += crashk_res.start;
buf.memsz = buf.bufsz;
ret = kexec_add_buffer(&buf);
@@ -43,10 +45,6 @@ static void *s390_image_load(struct kimage *image,
struct s390_load_data data = {0};
int ret;
- /* We don't support crash kernels yet. */
- if (image->type == KEXEC_TYPE_CRASH)
- return ERR_PTR(-ENOTSUPP);
-
ret = kexec_file_add_image_kernel(image, &data, kernel, kernel_len);
if (ret)
return ERR_PTR(ret);
diff --git a/arch/s390/kernel/machine_kexec_file.c b/arch/s390/kernel/machine_kexec_file.c
index 052640220361..050ceab746ec 100644
--- a/arch/s390/kernel/machine_kexec_file.c
+++ b/arch/s390/kernel/machine_kexec_file.c
@@ -28,6 +28,14 @@ void kexec_file_update_kernel(struct kimage *image,
memcpy(data->kernel_buf + COMMAND_LINE_OFFSET,
image->cmdline_buf, image->cmdline_buf_len);
+ if (image->type == KEXEC_TYPE_CRASH) {
+ loc = (unsigned long *)(data->kernel_buf + OLDMEM_BASE_OFFSET);
+ *loc = crashk_res.start;
+
+ loc = (unsigned long *)(data->kernel_buf + OLDMEM_SIZE_OFFSET);
+ *loc = crashk_res.end - crashk_res.start + 1;
+ }
+
if (image->initrd_buf) {
loc = (unsigned long *)(data->kernel_buf + INITRD_START_OFFSET);
*loc = data->initrd_load_addr;
@@ -42,9 +50,40 @@ static int kexec_file_update_purgatory(struct kimage *image)
u64 entry, type;
int ret;
- entry = STARTUP_NORMAL_OFFSET;
+ if (image->type == KEXEC_TYPE_CRASH) {
+ entry = STARTUP_KDUMP_OFFSET;
+ type = KEXEC_TYPE_CRASH;
+ } else {
+ entry = STARTUP_NORMAL_OFFSET;
+ type = KEXEC_TYPE_DEFAULT;
+ }
+
ret = kexec_purgatory_get_set_symbol(image, "kernel_entry", &entry,
sizeof(entry), false);
+ if (ret)
+ return ret;
+
+ ret = kexec_purgatory_get_set_symbol(image, "kernel_type", &type,
+ sizeof(type), false);
+ if (ret)
+ return ret;
+
+ if (image->type == KEXEC_TYPE_CRASH) {
+ u64 crash_size;
+
+ ret = kexec_purgatory_get_set_symbol(image, "crash_start",
+ &crashk_res.start,
+ sizeof(crashk_res.start),
+ false);
+ if (ret)
+ return ret;
+
+ crash_size = crashk_res.end - crashk_res.start + 1;
+ ret = kexec_purgatory_get_set_symbol(image, "crash_size",
+ &crash_size,
+ sizeof(crash_size),
+ false);
+ }
return ret;
}
@@ -57,6 +96,8 @@ int kexec_file_add_purgatory(struct kimage *image, struct s390_load_data *data)
data->memsz = ALIGN(data->memsz, PAGE_SIZE);
buf.mem = data->memsz;
+ if (image->type == KEXEC_TYPE_CRASH)
+ buf.mem += crashk_res.start;
ret = kexec_load_purgatory(image, &buf);
if (ret)
@@ -79,6 +120,8 @@ int kexec_file_add_initrd(struct kimage *image, struct s390_load_data *data,
data->memsz = ALIGN(data->memsz, PAGE_SIZE);
buf.mem = data->memsz;
+ if (image->type == KEXEC_TYPE_CRASH)
+ buf.mem += crashk_res.start;
buf.memsz = buf.bufsz;
data->initrd_load_addr = buf.mem;
diff --git a/arch/s390/purgatory/head.S b/arch/s390/purgatory/head.S
index 8735409d0280..6bfb13aa3f42 100644
--- a/arch/s390/purgatory/head.S
+++ b/arch/s390/purgatory/head.S
@@ -15,8 +15,52 @@
/* The purgatory is the code running between two kernels. It's main purpose
* is to verify that the next kernel was not corrupted after load and to
* start it.
+ *
+ * If the next kernel is a crash kernel there are some peculiarities to
+ * consider:
+ *
+ * First the purgatory is called twice. Once only to verify the
+ * sha digest. So if the crash kernel got corrupted the old kernel can try
+ * to trigger a stand-alone dumper. And once to actually load the crash kernel.
+ *
+ * Second the purgatory also has to swap the crash memory region with its
+ * destination at address 0. As the purgatory is part of crash memory this
+ * requires some finesse. The tactic here is that the purgatory first copies
+ * itself to the end of the destination and then swaps the rest of the
+ * memory running from there.
*/
+#define bufsz purgatory_end-stack
+
+.macro MEMCPY dst,src,len
+ lgr %r0,\dst
+ lgr %r1,\len
+ lgr %r2,\src
+ lgr %r3,\len
+
+20: mvcle %r0,%r2,0
+ jo 20b
+.endm
+
+.macro MEMSWAP dst,src,buf,len
+10: cghi \len,bufsz
+ jh 11f
+ lgr %r4,\len
+ j 12f
+11: lghi %r4,bufsz
+
+12: MEMCPY \buf,\dst,%r4
+ MEMCPY \dst,\src,%r4
+ MEMCPY \src,\buf,%r4
+
+ agr \dst,%r4
+ agr \src,%r4
+ sgr \len,%r4
+
+ cghi \len,0
+ jh 10b
+.endm
+
.macro START_NEXT_KERNEL base
lg %r4,kernel_entry-\base(%r13)
lg %r5,load_psw_mask-\base(%r13)
@@ -47,18 +91,144 @@ ENTRY(purgatory_start)
larl %r15,purgatory_end
aghi %r15,-160
+ /* If the next kernel is KEXEC_TYPE_CRASH the purgatory is called
+ * directly with a flag passed in %r2 whether the purgatory shall do
+ * checksum verification only (%r2 = 0 -> verification only).
+ *
+ * Check now and preserve over C function call by storing in
+ * %r10 whith
+ * 1 -> checksum verification only
+ * 0 -> load new kernel
+ */
+ lghi %r10,0
+ lg %r11,kernel_type-.base_crash(%r13)
+ cghi %r11,1 /* KEXEC_TYPE_CRASH */
+ jne .do_checksum_verification
+ cghi %r2,0 /* checksum verification only */
+ jne .do_checksum_verification
+ lghi %r10,1
+
.do_checksum_verification:
brasl %r14,verify_sha256_digest
+ cghi %r10,1 /* checksum verification only */
+ je .return_old_kernel
cghi %r2,0 /* checksum match */
jne .disabled_wait
+ /* If the next kernel is a crash kernel the purgatory has to swap
+ * the mem regions first.
+ */
+ cghi %r11,1 /* KEXEC_TYPE_CRASH */
+ je .start_crash_kernel
+
/* start normal kernel */
START_NEXT_KERNEL .base_crash
+.return_old_kernel:
+ lmg %r6,%r15,gprregs-.base_crash(%r13)
+ br %r14
+
.disabled_wait:
lpswe disabled_wait_psw-.base_crash(%r13)
+.start_crash_kernel:
+ /* Location of purgatory_start in crash memory */
+ lgr %r8,%r13
+ aghi %r8,-(.base_crash-purgatory_start)
+
+ /* Destination for this code i.e. end of memory to be swapped. */
+ lg %r9,crash_size-.base_crash(%r13)
+ aghi %r9,-(purgatory_end-purgatory_start)
+
+ /* Destination in crash memory, i.e. same as r9 but in crash memory. */
+ lg %r10,crash_start-.base_crash(%r13)
+ agr %r10,%r9
+
+ /* Buffer location (in crash memory) and size. As the purgatory is
+ * behind the point of no return it can re-use the stack as buffer.
+ */
+ lghi %r11,bufsz
+ larl %r12,stack
+
+ MEMCPY %r12,%r9,%r11 /* dst -> (crash) buf */
+ MEMCPY %r9,%r8,%r11 /* self -> dst */
+
+ /* Jump to new location. */
+ lgr %r7,%r9
+ aghi %r7,.jump_to_dst-purgatory_start
+ br %r7
+
+.jump_to_dst:
+ basr %r13,0
+.base_dst:
+
+ /* clear buffer */
+ MEMCPY %r12,%r10,%r11 /* (crash) buf -> (crash) dst */
+
+ /* Load new buffer location after jump */
+ larl %r7,stack
+ aghi %r10,stack-purgatory_start
+ MEMCPY %r10,%r7,%r11 /* (new) buf -> (crash) buf */
+
+ /* Now the code is set up to run from its designated location. Start
+ * swapping the rest of crash memory now.
+ *
+ * The registers will be used as follow:
+ *
+ * %r0-%r4 reserved for macros defined above
+ * %r5-%r6 tmp registers
+ * %r7 pointer to current struct sha region
+ * %r8 index to iterate over all sha regions
+ * %r9 pointer in crash memory
+ * %r10 pointer in old kernel
+ * %r11 total size (still) to be moved
+ * %r12 pointer to buffer
+ */
+ lgr %r12,%r7
+ lgr %r11,%r9
+ lghi %r10,0
+ lg %r9,crash_start-.base_dst(%r13)
+ lghi %r8,16 /* KEXEC_SEGMENTS_MAX */
+ larl %r7,purgatory_sha_regions
+
+ j .loop_first
+
+ /* Loop over all purgatory_sha_regions. */
+.loop_next:
+ aghi %r8,-1
+ cghi %r8,0
+ je .loop_out
+
+ aghi %r7,__KEXEC_SHA_REGION_SIZE
+
+.loop_first:
+ lg %r5,__KEXEC_SHA_REGION_START(%r7)
+ cghi %r5,0
+ je .loop_next
+
+ /* Copy [end last sha region, start current sha region) */
+ /* Note: kexec_sha_region->start points in crash memory */
+ sgr %r5,%r9
+ MEMCPY %r9,%r10,%r5
+
+ agr %r9,%r5
+ agr %r10,%r5
+ sgr %r11,%r5
+
+ /* Swap sha region */
+ lg %r6,__KEXEC_SHA_REGION_LEN(%r7)
+ MEMSWAP %r9,%r10,%r12,%r6
+ sg %r11,__KEXEC_SHA_REGION_LEN(%r7)
+ j .loop_next
+
+.loop_out:
+ /* Copy rest of crash memory */
+ MEMCPY %r9,%r10,%r11
+
+ /* start crash kernel */
+ START_NEXT_KERNEL .base_dst
+
load_psw_mask:
.long 0x00080000,0x80000000
@@ -89,8 +259,21 @@ kernel_entry:
.global kernel_entry
.quad 0
+kernel_type:
+ .global kernel_type
+ .quad 0
+
+crash_start:
+ .global crash_start
+ .quad 0
+
+crash_size:
+ .global crash_size
+ .quad 0
+
.align PAGE_SIZE
stack:
- .skip PAGE_SIZE
+ /* The buffer to move this code must be as big as the code. */
+ .skip stack-purgatory_start
.align PAGE_SIZE
purgatory_end:
diff --git a/arch/s390/purgatory/purgatory.c b/arch/s390/purgatory/purgatory.c
index fec67b58b8be..67ded81e0430 100644
--- a/arch/s390/purgatory/purgatory.c
+++ b/arch/s390/purgatory/purgatory.c
@@ -16,6 +16,10 @@ struct kexec_sha_region purgatory_sha_regions[KEXEC_SEGMENT_MAX];
u8 purgatory_sha256_digest[SHA256_DIGEST_SIZE];
u64 kernel_entry;
+u64 kernel_type;
+
+u64 crash_start;
+u64 crash_size;
int verify_sha256_digest(void)
{
--
2.13.5
Add an ELF loader for kexec_file. The main task here is to do proper sanity
checks on the ELF file. Basically all other functionality was already
implemented for the image loader.
Signed-off-by: Philipp Rudo <[email protected]>
---
arch/s390/include/asm/kexec.h | 1 +
arch/s390/kernel/Makefile | 2 +-
arch/s390/kernel/kexec_elf.c | 149 ++++++++++++++++++++++++++++++++++
arch/s390/kernel/machine_kexec_file.c | 1 +
4 files changed, 152 insertions(+), 1 deletion(-)
create mode 100644 arch/s390/kernel/kexec_elf.c
diff --git a/arch/s390/include/asm/kexec.h b/arch/s390/include/asm/kexec.h
index 532f5e4f198f..e450b82e2716 100644
--- a/arch/s390/include/asm/kexec.h
+++ b/arch/s390/include/asm/kexec.h
@@ -67,5 +67,6 @@ void kexec_file_update_kernel(struct kimage *iamge,
struct s390_load_data *data);
extern const struct kexec_file_ops s390_kexec_image_ops;
+extern const struct kexec_file_ops s390_kexec_elf_ops;
#endif /*_S390_KEXEC_H */
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 58a590709cc3..66d7b432c2a8 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -60,7 +60,7 @@ obj-y += debug.o irq.o ipl.o dis.o diag.o vdso.o als.o
obj-y += sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o
obj-y += runtime_instr.o cache.o fpu.o dumpstack.o guarded_storage.o sthyi.o
obj-y += entry.o reipl.o relocate_kernel.o kdebugfs.o alternative.o
-obj-y += machine_kexec_file.o kexec_image.o
+obj-y += machine_kexec_file.o kexec_image.o kexec_elf.o
extra-y += head.o head64.o vmlinux.lds
diff --git a/arch/s390/kernel/kexec_elf.c b/arch/s390/kernel/kexec_elf.c
new file mode 100644
index 000000000000..919ab2f1256f
--- /dev/null
+++ b/arch/s390/kernel/kexec_elf.c
@@ -0,0 +1,149 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * ELF loader for kexec_file_load system call.
+ *
+ * Copyright IBM Corp. 2018
+ *
+ * Author(s): Philipp Rudo <[email protected]>
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/kexec.h>
+#include <asm/setup.h>
+
+static int kexec_file_add_elf_kernel(struct kimage *image,
+ struct s390_load_data *data,
+ char *kernel, unsigned long kernel_len)
+{
+ struct kexec_buf buf;
+ const Elf_Ehdr *ehdr;
+ const Elf_Phdr *phdr;
+ int i, ret;
+
+ ehdr = (Elf_Ehdr *)kernel;
+ buf.image = image;
+
+ phdr = (void *)ehdr + ehdr->e_phoff;
+ for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
+ if (phdr->p_type != PT_LOAD)
+ continue;
+
+ buf.buffer = kernel + phdr->p_offset;
+ buf.bufsz = phdr->p_filesz;
+
+ buf.mem = ALIGN(phdr->p_paddr, phdr->p_align);
+ buf.memsz = phdr->p_memsz;
+
+ if (phdr->p_paddr == 0) {
+ data->kernel_buf = buf.buffer;
+ data->memsz += STARTUP_NORMAL_OFFSET;
+
+ buf.buffer += STARTUP_NORMAL_OFFSET;
+ buf.bufsz -= STARTUP_NORMAL_OFFSET;
+
+ buf.mem += STARTUP_NORMAL_OFFSET;
+ buf.memsz -= STARTUP_NORMAL_OFFSET;
+ }
+
+ if (image->type == KEXEC_TYPE_CRASH)
+ buf.mem += crashk_res.start;
+
+ ret = kexec_add_buffer(&buf);
+ if (ret)
+ return ret;
+
+ data->memsz += buf.memsz;
+ }
+
+ return 0;
+}
+
+static void *s390_elf_load(struct kimage *image,
+ char *kernel, unsigned long kernel_len,
+ char *initrd, unsigned long initrd_len,
+ char *cmdline, unsigned long cmdline_len)
+{
+ struct s390_load_data data = {0};
+ const Elf_Ehdr *ehdr;
+ const Elf_Phdr *phdr;
+ size_t size;
+ int i, ret;
+
+ /* image->fobs->probe already checked for valid ELF magic number. */
+ ehdr = (Elf_Ehdr *)kernel;
+
+ if (ehdr->e_type != ET_EXEC ||
+ ehdr->e_ident[EI_CLASS] != ELFCLASS64 ||
+ !elf_check_arch(ehdr))
+ return ERR_PTR(-EINVAL);
+
+ if (!ehdr->e_phnum || ehdr->e_phentsize != sizeof(Elf_Phdr))
+ return ERR_PTR(-EINVAL);
+
+ size = ehdr->e_ehsize + ehdr->e_phoff;
+ size += ehdr->e_phentsize * ehdr->e_phnum;
+ if (size > kernel_len)
+ return ERR_PTR(-EINVAL);
+
+ phdr = (void *)ehdr + ehdr->e_phoff;
+ size = ALIGN(size, phdr->p_align);
+ for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
+ if (phdr->p_type == PT_INTERP)
+ return ERR_PTR(-EINVAL);
+
+ if (phdr->p_offset > kernel_len)
+ return ERR_PTR(-EINVAL);
+
+ size += ALIGN(phdr->p_filesz, phdr->p_align);
+ }
+
+ if (size > kernel_len)
+ return ERR_PTR(-EINVAL);
+
+ ret = kexec_file_add_elf_kernel(image, &data, kernel, kernel_len);
+ if (ret)
+ return ERR_PTR(ret);
+
+ if (!data.memsz)
+ return ERR_PTR(-EINVAL);
+
+ if (initrd) {
+ ret = kexec_file_add_initrd(image, &data, initrd, initrd_len);
+ if (ret)
+ return ERR_PTR(ret);
+ }
+
+ ret = kexec_file_add_purgatory(image, &data);
+ if (ret)
+ return ERR_PTR(ret);
+
+ kexec_file_update_kernel(image, &data);
+
+ return NULL;
+}
+
+static int s390_elf_probe(const char *buf, unsigned long len)
+{
+ const Elf_Ehdr *ehdr;
+
+ if (len < sizeof(Elf_Ehdr))
+ return -ENOEXEC;
+
+ ehdr = (Elf_Ehdr *)buf;
+
+ /* Only check the ELF magic number here and do proper validity check
+ * in the loader. Any check here that fails would send the erroneous
+ * ELF file to the image loader that does not care what it gets.
+ * (Most likely) causing behavior not intended by the user.
+ */
+ if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0)
+ return -ENOEXEC;
+
+ return 0;
+}
+
+const struct kexec_file_ops s390_kexec_elf_ops = {
+ .probe = s390_elf_probe,
+ .load = s390_elf_load,
+};
diff --git a/arch/s390/kernel/machine_kexec_file.c b/arch/s390/kernel/machine_kexec_file.c
index 050ceab746ec..8938e0eca4b0 100644
--- a/arch/s390/kernel/machine_kexec_file.c
+++ b/arch/s390/kernel/machine_kexec_file.c
@@ -12,6 +12,7 @@
#include <asm/setup.h>
const struct kexec_file_ops * const kexec_file_loaders[] = {
+ &s390_kexec_elf_ops,
&s390_kexec_image_ops,
NULL,
};
--
2.13.5
kexec_file_load needs to prepare the new kernels before they are loaded.
For that it has to know the offsets in head.S, e.g. to register the new
command line. Unfortunately there are no macros right now defining those
offsets. Define them now.
Signed-off-by: Philipp Rudo <[email protected]>
---
arch/s390/include/asm/setup.h | 40 +++++++++++++++++++++++++++-------------
1 file changed, 27 insertions(+), 13 deletions(-)
diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h
index 2eb0c8a7b664..75b354e774eb 100644
--- a/arch/s390/include/asm/setup.h
+++ b/arch/s390/include/asm/setup.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* S390 version
- * Copyright IBM Corp. 1999, 2010
+ * Copyright IBM Corp. 1999, 2017
*/
#ifndef _ASM_S390_SETUP_H
#define _ASM_S390_SETUP_H
@@ -38,17 +38,31 @@
#define LPP_MAGIC _BITUL(31)
#define LPP_PID_MASK _AC(0xffffffff, UL)
+/* Offsets to entry points in kernel/head.S */
+
+#define STARTUP_NORMAL_OFFSET 0x10000
+#define STARTUP_KDUMP_OFFSET 0x10010
+
+/* Offsets to parameters in kernel/head.S */
+
+#define IPL_DEVICE_OFFSET 0x10400
+#define INITRD_START_OFFSET 0x10408
+#define INITRD_SIZE_OFFSET 0x10410
+#define OLDMEM_BASE_OFFSET 0x10418
+#define OLDMEM_SIZE_OFFSET 0x10420
+#define COMMAND_LINE_OFFSET 0x10480
+
#ifndef __ASSEMBLY__
#include <asm/lowcore.h>
#include <asm/types.h>
-#define IPL_DEVICE (*(unsigned long *) (0x10400))
-#define INITRD_START (*(unsigned long *) (0x10408))
-#define INITRD_SIZE (*(unsigned long *) (0x10410))
-#define OLDMEM_BASE (*(unsigned long *) (0x10418))
-#define OLDMEM_SIZE (*(unsigned long *) (0x10420))
-#define COMMAND_LINE ((char *) (0x10480))
+#define IPL_DEVICE (*(unsigned long *) (IPL_DEVICE_OFFSET))
+#define INITRD_START (*(unsigned long *) (INITRD_START_OFFSET))
+#define INITRD_SIZE (*(unsigned long *) (INITRD_SIZE_OFFSET))
+#define OLDMEM_BASE (*(unsigned long *) (OLDMEM_BASE_OFFSET))
+#define OLDMEM_SIZE (*(unsigned long *) (OLDMEM_SIZE_OFFSET))
+#define COMMAND_LINE ((char *) (COMMAND_LINE_OFFSET))
extern int memory_end_set;
extern unsigned long memory_end;
@@ -123,12 +137,12 @@ extern void (*_machine_power_off)(void);
#else /* __ASSEMBLY__ */
-#define IPL_DEVICE 0x10400
-#define INITRD_START 0x10408
-#define INITRD_SIZE 0x10410
-#define OLDMEM_BASE 0x10418
-#define OLDMEM_SIZE 0x10420
-#define COMMAND_LINE 0x10480
+#define IPL_DEVICE (IPL_DEVICE_OFFSET)
+#define INITRD_START (INITRD_START_OFFSET)
+#define INITRD_SIZE (INITRD_SIZE_OFFSET)
+#define OLDMEM_BASE (OLDMEM_BASE_OFFSET)
+#define OLDMEM_SIZE (OLDMEM_SIZE_OFFSET)
+#define COMMAND_LINE (COMMAND_LINE_OFFSET)
#endif /* __ASSEMBLY__ */
#endif /* _ASM_S390_SETUP_H */
--
2.13.5
For s390 new kernels are loaded to fixed addresses in memory before they
are booted. With the current code this is a problem as it assumes the
kernel will be loaded to an 'arbitrary' address. In particular,
kexec_locate_mem_hole searches for a large enough memory region and sets
the load address (kexec_bufer->mem) to it.
Luckily there is a simple workaround for this problem. By returning 1 in
arch_kexec_walk_mem, kexec_locate_mem_hole is turned off. This allows the
architecture to set kbuf->mem by hand. While the trick works fine for the
kernel it does not for the purgatory as here the architectures don't have
access to its kexec_buffer.
Give architectures access to the purgatories kexec_buffer by changing
kexec_load_purgatory to take a pointer to it. With this change
architectures have access to the buffer and can edit it as they need.
A nice side effect of this change is that we can get rid of the
purgatory_info->purgatory_load_address field. As now the information stored
there can directly be accessed from kbuf->mem.
Signed-off-by: Philipp Rudo <[email protected]>
Reviewed-by: Martin Schwidefsky <[email protected]>
---
arch/powerpc/kernel/kexec_elf_64.c | 9 +++++----
arch/x86/kernel/kexec-bzimage64.c | 8 ++++----
include/linux/kexec.h | 7 +------
kernel/kexec_file.c | 29 ++++++++++++++++-------------
4 files changed, 26 insertions(+), 27 deletions(-)
diff --git a/arch/powerpc/kernel/kexec_elf_64.c b/arch/powerpc/kernel/kexec_elf_64.c
index 9a42309b091a..82448c03502d 100644
--- a/arch/powerpc/kernel/kexec_elf_64.c
+++ b/arch/powerpc/kernel/kexec_elf_64.c
@@ -572,7 +572,7 @@ static void *elf64_load(struct kimage *image, char *kernel_buf,
{
int ret;
unsigned int fdt_size;
- unsigned long kernel_load_addr, purgatory_load_addr;
+ unsigned long kernel_load_addr;
unsigned long initrd_load_addr = 0, fdt_load_addr;
void *fdt;
const void *slave_code;
@@ -580,6 +580,8 @@ static void *elf64_load(struct kimage *image, char *kernel_buf,
struct elf_info elf_info;
struct kexec_buf kbuf = { .image = image, .buf_min = 0,
.buf_max = ppc64_rma_size };
+ struct kexec_buf pbuf = { .image = image, .buf_min = 0,
+ .buf_max = ppc64_rma_size, .top_down = true };
ret = build_elf_exec_info(kernel_buf, kernel_len, &ehdr, &elf_info);
if (ret)
@@ -591,14 +593,13 @@ static void *elf64_load(struct kimage *image, char *kernel_buf,
pr_debug("Loaded the kernel at 0x%lx\n", kernel_load_addr);
- ret = kexec_load_purgatory(image, 0, ppc64_rma_size, true,
- &purgatory_load_addr);
+ ret = kexec_load_purgatory(image, &pbuf);
if (ret) {
pr_err("Loading purgatory failed.\n");
goto out;
}
- pr_debug("Loaded purgatory at 0x%lx\n", purgatory_load_addr);
+ pr_debug("Loaded purgatory at 0x%lx\n", pbuf.mem);
if (initrd != NULL) {
kbuf.buffer = initrd;
diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c
index fb095ba0c02f..df183585928f 100644
--- a/arch/x86/kernel/kexec-bzimage64.c
+++ b/arch/x86/kernel/kexec-bzimage64.c
@@ -334,7 +334,6 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
unsigned long setup_header_size, params_cmdline_sz;
struct boot_params *params;
unsigned long bootparam_load_addr, kernel_load_addr, initrd_load_addr;
- unsigned long purgatory_load_addr;
struct bzimage64_data *ldata;
struct kexec_entry64_regs regs64;
void *stack;
@@ -342,6 +341,8 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
unsigned int efi_map_offset, efi_map_sz, efi_setup_data_offset;
struct kexec_buf kbuf = { .image = image, .buf_max = ULONG_MAX,
.top_down = true };
+ struct kexec_buf pbuf = { .image = image, .buf_min = MIN_PURGATORY_ADDR,
+ .buf_max = ULONG_MAX, .top_down = true };
header = (struct setup_header *)(kernel + setup_hdr_offset);
setup_sects = header->setup_sects;
@@ -379,14 +380,13 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
* Load purgatory. For 64bit entry point, purgatory code can be
* anywhere.
*/
- ret = kexec_load_purgatory(image, MIN_PURGATORY_ADDR, ULONG_MAX, 1,
- &purgatory_load_addr);
+ ret = kexec_load_purgatory(image, &pbuf);
if (ret) {
pr_err("Loading purgatory failed\n");
return ERR_PTR(ret);
}
- pr_debug("Loaded purgatory at 0x%lx\n", purgatory_load_addr);
+ pr_debug("Loaded purgatory at 0x%lx\n", pbuf.mem);
/*
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index f15446be0e25..1cd9c5f49859 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -114,9 +114,6 @@ struct purgatory_info {
* relocation. This memory can be freed post image load.
*/
void *purgatory_buf;
-
- /* Address where purgatory is finally loaded and is executed from */
- unsigned long purgatory_load_addr;
};
struct kimage;
@@ -237,9 +234,7 @@ extern asmlinkage long sys_kexec_load(unsigned long entry,
extern int kernel_kexec(void);
extern struct page *kimage_alloc_control_pages(struct kimage *image,
unsigned int order);
-extern int kexec_load_purgatory(struct kimage *image, unsigned long min,
- unsigned long max, int top_down,
- unsigned long *load_addr);
+extern int kexec_load_purgatory(struct kimage *image, struct kexec_buf *kbuf);
extern int kexec_purgatory_get_set_symbol(struct kimage *image,
const char *name, void *buf,
unsigned int size, bool get_value);
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 25b44d1a664a..d69d1bf9e7a2 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -669,8 +669,8 @@ static int kexec_purgatory_setup_kbuf(struct purgatory_info *pi,
int i, ret;
sechdrs = (void *)pi->ehdr + pi->ehdr->e_shoff;
- bss_align = 1;
- bss_sz = 0;
+ kbuf->buf_align = bss_align = 1;
+ kbuf->bufsz = bss_sz = 0;
for (i = 0; i < pi->ehdr->e_shnum; i++) {
if (!(sechdrs[i].sh_flags & SHF_ALLOC))
@@ -702,7 +702,6 @@ static int kexec_purgatory_setup_kbuf(struct purgatory_info *pi,
ret = kexec_add_buffer(kbuf);
if (ret)
goto out;
- pi->purgatory_load_addr = kbuf->mem;
return 0;
out:
@@ -836,27 +835,32 @@ static int kexec_apply_relocations(struct kimage *image)
return 0;
}
-/* Load relocatable purgatory object and relocate it appropriately */
-int kexec_load_purgatory(struct kimage *image, unsigned long min,
- unsigned long max, int top_down,
- unsigned long *load_addr)
+/*
+ * kexec_load_purgatory - Load and relocate the purgatory object.
+ * @image: Image to add the purgatory to.
+ * @kbuf: Memory parameters to use.
+ *
+ * Allocates the memory needed for image->purgatory_info.sechdrs and
+ * image->purgatory_info.purgatory_buf/kbuf->buffer. Caller is responsible
+ * to free the memory after use.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+int kexec_load_purgatory(struct kimage *image, struct kexec_buf *kbuf)
{
struct purgatory_info *pi = &image->purgatory_info;
int ret;
- struct kexec_buf kbuf = { .image = image, .bufsz = 0, .buf_align = 1,
- .buf_min = min, .buf_max = max,
- .top_down = top_down };
if (kexec_purgatory_size <= 0)
return -EINVAL;
pi->ehdr = (const Elf_Ehdr *)kexec_purgatory;
- ret = kexec_purgatory_setup_kbuf(pi, &kbuf);
+ ret = kexec_purgatory_setup_kbuf(pi, kbuf);
if (ret)
return ret;
- ret = kexec_purgatory_setup_sechdrs(pi, &kbuf);
+ ret = kexec_purgatory_setup_sechdrs(pi, kbuf);
if (ret)
goto out_free_kbuf;
@@ -864,7 +868,6 @@ int kexec_load_purgatory(struct kimage *image, unsigned long min,
if (ret)
goto out;
- *load_addr = pi->purgatory_load_addr;
return 0;
out:
vfree(pi->sechdrs);
--
2.13.5
On Mon, Feb 12, 2018 at 11:07 AM, Philipp Rudo <[email protected]> wrote:
> 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 <[email protected]>
<snip>
> --- /dev/null
> +++ b/arch/s390/kernel/machine_kexec_file.c
> @@ -0,0 +1,174 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
I know this may sound weird but in .c files this should be instead:
// SPDX-License-Identifier: GPL-2.0
See Documentation/process/license-rules.rst for why.
--
Cordially
Philippe Ombredanne
Hi Philipp,
I added AKASHI in cc, he posted arm64 kexec_file series previously.
I would like to read both series especially the general part, but
maybe at the end of this month because of a holiday..
From the patch log the cleanup looks nice, but still need read the
details.
On 02/12/18 at 11:07am, Philipp Rudo wrote:
> Hi everybody
>
> resending the series as there was no reaction, yet. Furthermore i was told
> that Andrew and the x86 list should also be CCed, so welcome.
>
> No changes made to the patches since first time i sent them. The patches
> apply to the current master (v4.16-rc1).
>
> Thanks
> Philipp
>
> ---
>
> this series adds the kexec_file_load system call to s390. Before the system
> call is added there are some preparations/clean ups to common
> kexec_file_load. In detail this series contains:
>
> Patch #1&2: Minor cleanups/fixes.
>
> Patch #3-9: Clean up the purgatory load/relocation code. Especially remove
> the mis-use of the purgatory_info->sechdrs->sh_offset field, currently
> holding a pointer into either kexec_purgatory (ro) or purgatory_buf (rw)
> depending on the section. With these patches the section address will be
> calculated verbosely and sh_offset will contain the offset of the section
> in the stripped purgatory binary (purgatory_buf).
>
> Patch #10: Allows architectures to set the purgaory load address. This
> patch is important for s390 as the kernel and purgatory have to be loaded
> to fixed addresses. In current code this is impossible as the purgatory
> load is opaque to the architecture.
>
> Patch #11: Moves x86 purgatories sha implementation to common lib/
> directory.
>
> Patches #12-17 finally adds the kexec_file_load system call to s390.
>
> Please note that I had to touch arch code for x86 and power a little. In
> theory this should not change the behavior but I don't have a way to test
> it. Cross-compiling with defconfig(*) works fine for both.
>
> Thanks
> Philipp
>
> (*) On x86 with the orc unwinder turned off. objtool SEGFAULTs on s390...
>
> Philipp Rudo (17):
> kexec_file: Silence compile warnings
> kexec_file: Remove checks in kexec_purgatory_load
> kexec_file: Make purgatory_info->ehdr const
> kexec_file: Search symbols in read-only kexec_purgatory
> kexec_file: Use read-only sections in arch_kexec_apply_relocations*
> kexec_file: Split up __kexec_load_puragory
> kexec_file: Simplify kexec_purgatory_setup_sechdrs 1
> kexec_file: Simplify kexec_purgatory_setup_sechdrs 2
> kexec_file: Remove mis-use of sh_offset field
> kexec_file: Allow archs to set purgatory load address
> kexec_file: Move purgatories sha256 to common code
> s390/kexec_file: Prepare setup.h for kexec_file_load
> s390/kexec_file: Add purgatory
> s390/kexec_file: Add kexec_file_load system call
> s390/kexec_file: Add image loader
> s390/kexec_file: Add crash support to image loader
> s390/kexec_file: Add ELF loader
>
> arch/powerpc/kernel/kexec_elf_64.c | 9 +-
> arch/s390/Kbuild | 1 +
> arch/s390/Kconfig | 4 +
> arch/s390/include/asm/kexec.h | 23 ++
> arch/s390/include/asm/purgatory.h | 17 ++
> arch/s390/include/asm/setup.h | 40 ++-
> arch/s390/kernel/Makefile | 1 +
> arch/s390/kernel/asm-offsets.c | 5 +
> arch/s390/kernel/compat_wrapper.c | 1 +
> arch/s390/kernel/kexec_elf.c | 149 ++++++++++
> arch/s390/kernel/kexec_image.c | 78 +++++
> arch/s390/kernel/machine_kexec_file.c | 291 +++++++++++++++++++
> arch/s390/kernel/syscalls/syscall.tbl | 1 +
> arch/s390/purgatory/Makefile | 37 +++
> arch/s390/purgatory/head.S | 279 ++++++++++++++++++
> arch/s390/purgatory/purgatory.c | 42 +++
> arch/x86/kernel/kexec-bzimage64.c | 8 +-
> arch/x86/kernel/machine_kexec_64.c | 66 ++---
> arch/x86/purgatory/Makefile | 3 +
> arch/x86/purgatory/purgatory.c | 2 +-
> include/linux/kexec.h | 38 +--
> {arch/x86/purgatory => include/linux}/sha256.h | 10 +-
> kernel/kexec_file.c | 375 ++++++++++++-------------
> {arch/x86/purgatory => lib}/sha256.c | 4 +-
> 24 files changed, 1200 insertions(+), 284 deletions(-)
> create mode 100644 arch/s390/include/asm/purgatory.h
> create mode 100644 arch/s390/kernel/kexec_elf.c
> create mode 100644 arch/s390/kernel/kexec_image.c
> create mode 100644 arch/s390/kernel/machine_kexec_file.c
> create mode 100644 arch/s390/purgatory/Makefile
> create mode 100644 arch/s390/purgatory/head.S
> create mode 100644 arch/s390/purgatory/purgatory.c
> rename {arch/x86/purgatory => include/linux}/sha256.h (63%)
> rename {arch/x86/purgatory => lib}/sha256.c (99%)
>
> --
> 2.13.5
>
>
> _______________________________________________
> kexec mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/kexec
Thanks
Dave
Hi Dave,
I just browsed AKASHI's patches (v7). The way I see it the common code changes
are on different areas of kexec_file and shouldn't get in conflict. Only in the
arch code (s390 and arm64) some function calls might need an update. But I have
to take a closer look on the patches first.
@AKASHI: Welcome to the list. While browsing I couldn't find any
arch_apply_relocation function for arm64. These require the biggest changes in
my patch set. Did I just miss it or does arm64 work differently?
@Dave: Happy holiday
Thanks
Philipp
On Wed, 14 Feb 2018 15:35:43 +0800
Dave Young <[email protected]> wrote:
> Hi Philipp,
>
> I added AKASHI in cc, he posted arm64 kexec_file series previously.
> I would like to read both series especially the general part, but
> maybe at the end of this month because of a holiday..
>
> From the patch log the cleanup looks nice, but still need read the
> details.
>
> On 02/12/18 at 11:07am, Philipp Rudo wrote:
> > Hi everybody
> >
> > resending the series as there was no reaction, yet. Furthermore i was told
> > that Andrew and the x86 list should also be CCed, so welcome.
> >
> > No changes made to the patches since first time i sent them. The patches
> > apply to the current master (v4.16-rc1).
> >
> > Thanks
> > Philipp
> >
> > ---
> >
> > this series adds the kexec_file_load system call to s390. Before the system
> > call is added there are some preparations/clean ups to common
> > kexec_file_load. In detail this series contains:
> >
> > Patch #1&2: Minor cleanups/fixes.
> >
> > Patch #3-9: Clean up the purgatory load/relocation code. Especially remove
> > the mis-use of the purgatory_info->sechdrs->sh_offset field, currently
> > holding a pointer into either kexec_purgatory (ro) or purgatory_buf (rw)
> > depending on the section. With these patches the section address will be
> > calculated verbosely and sh_offset will contain the offset of the section
> > in the stripped purgatory binary (purgatory_buf).
> >
> > Patch #10: Allows architectures to set the purgaory load address. This
> > patch is important for s390 as the kernel and purgatory have to be loaded
> > to fixed addresses. In current code this is impossible as the purgatory
> > load is opaque to the architecture.
> >
> > Patch #11: Moves x86 purgatories sha implementation to common lib/
> > directory.
> >
> > Patches #12-17 finally adds the kexec_file_load system call to s390.
> >
> > Please note that I had to touch arch code for x86 and power a little. In
> > theory this should not change the behavior but I don't have a way to test
> > it. Cross-compiling with defconfig(*) works fine for both.
> >
> > Thanks
> > Philipp
> >
> > (*) On x86 with the orc unwinder turned off. objtool SEGFAULTs on s390...
> >
> > Philipp Rudo (17):
> > kexec_file: Silence compile warnings
> > kexec_file: Remove checks in kexec_purgatory_load
> > kexec_file: Make purgatory_info->ehdr const
> > kexec_file: Search symbols in read-only kexec_purgatory
> > kexec_file: Use read-only sections in arch_kexec_apply_relocations*
> > kexec_file: Split up __kexec_load_puragory
> > kexec_file: Simplify kexec_purgatory_setup_sechdrs 1
> > kexec_file: Simplify kexec_purgatory_setup_sechdrs 2
> > kexec_file: Remove mis-use of sh_offset field
> > kexec_file: Allow archs to set purgatory load address
> > kexec_file: Move purgatories sha256 to common code
> > s390/kexec_file: Prepare setup.h for kexec_file_load
> > s390/kexec_file: Add purgatory
> > s390/kexec_file: Add kexec_file_load system call
> > s390/kexec_file: Add image loader
> > s390/kexec_file: Add crash support to image loader
> > s390/kexec_file: Add ELF loader
> >
> > arch/powerpc/kernel/kexec_elf_64.c | 9 +-
> > arch/s390/Kbuild | 1 +
> > arch/s390/Kconfig | 4 +
> > arch/s390/include/asm/kexec.h | 23 ++
> > arch/s390/include/asm/purgatory.h | 17 ++
> > arch/s390/include/asm/setup.h | 40 ++-
> > arch/s390/kernel/Makefile | 1 +
> > arch/s390/kernel/asm-offsets.c | 5 +
> > arch/s390/kernel/compat_wrapper.c | 1 +
> > arch/s390/kernel/kexec_elf.c | 149 ++++++++++
> > arch/s390/kernel/kexec_image.c | 78 +++++
> > arch/s390/kernel/machine_kexec_file.c | 291 +++++++++++++++++++
> > arch/s390/kernel/syscalls/syscall.tbl | 1 +
> > arch/s390/purgatory/Makefile | 37 +++
> > arch/s390/purgatory/head.S | 279 ++++++++++++++++++
> > arch/s390/purgatory/purgatory.c | 42 +++
> > arch/x86/kernel/kexec-bzimage64.c | 8 +-
> > arch/x86/kernel/machine_kexec_64.c | 66 ++---
> > arch/x86/purgatory/Makefile | 3 +
> > arch/x86/purgatory/purgatory.c | 2 +-
> > include/linux/kexec.h | 38 +--
> > {arch/x86/purgatory => include/linux}/sha256.h | 10 +-
> > kernel/kexec_file.c | 375 ++++++++++++-------------
> > {arch/x86/purgatory => lib}/sha256.c | 4 +-
> > 24 files changed, 1200 insertions(+), 284 deletions(-)
> > create mode 100644 arch/s390/include/asm/purgatory.h
> > create mode 100644 arch/s390/kernel/kexec_elf.c
> > create mode 100644 arch/s390/kernel/kexec_image.c
> > create mode 100644 arch/s390/kernel/machine_kexec_file.c
> > create mode 100644 arch/s390/purgatory/Makefile
> > create mode 100644 arch/s390/purgatory/head.S
> > create mode 100644 arch/s390/purgatory/purgatory.c
> > rename {arch/x86/purgatory => include/linux}/sha256.h (63%)
> > rename {arch/x86/purgatory => lib}/sha256.c (99%)
> >
> > --
> > 2.13.5
> >
> >
> > _______________________________________________
> > kexec mailing list
> > [email protected]
> > http://lists.infradead.org/mailman/listinfo/kexec
>
> Thanks
> Dave
>
Hi,
On Wed, Feb 14, 2018 at 10:54:49AM +0100, Philipp Rudo wrote:
> Hi Dave,
>
> I just browsed AKASHI's patches (v7). The way I see it the common code changes
> are on different areas of kexec_file and shouldn't get in conflict. Only in the
> arch code (s390 and arm64) some function calls might need an update. But I have
> to take a closer look on the patches first.
Yes, I mainly focus on re-factoring elf-core-header related code.
> @AKASHI: Welcome to the list. While browsing I couldn't find any
> arch_apply_relocation function for arm64. These require the biggest changes in
> my patch set. Did I just miss it or does arm64 work differently?
Well, after some discussions with arm64 key developers, we decided not to
utilize digest hash values in purgatory as they may not be very valuable, and
this resulted in a simple purgatory, which requires no re-linking/relocations.
In my next version coming soon, as our purgatory was so simple, we will
completely drop a purgatory from kexec_file_load code.
(we will still maintain a purgatory for legacy kexec_load as kexec-tools
has it now.)
Thanks,
-Takahiro AKASHI
> @Dave: Happy holiday
>
> Thanks
> Philipp
>
> On Wed, 14 Feb 2018 15:35:43 +0800
> Dave Young <[email protected]> wrote:
>
> > Hi Philipp,
> >
> > I added AKASHI in cc, he posted arm64 kexec_file series previously.
> > I would like to read both series especially the general part, but
> > maybe at the end of this month because of a holiday..
> >
> > From the patch log the cleanup looks nice, but still need read the
> > details.
> >
> > On 02/12/18 at 11:07am, Philipp Rudo wrote:
> > > Hi everybody
> > >
> > > resending the series as there was no reaction, yet. Furthermore i was told
> > > that Andrew and the x86 list should also be CCed, so welcome.
> > >
> > > No changes made to the patches since first time i sent them. The patches
> > > apply to the current master (v4.16-rc1).
> > >
> > > Thanks
> > > Philipp
> > >
> > > ---
> > >
> > > this series adds the kexec_file_load system call to s390. Before the system
> > > call is added there are some preparations/clean ups to common
> > > kexec_file_load. In detail this series contains:
> > >
> > > Patch #1&2: Minor cleanups/fixes.
> > >
> > > Patch #3-9: Clean up the purgatory load/relocation code. Especially remove
> > > the mis-use of the purgatory_info->sechdrs->sh_offset field, currently
> > > holding a pointer into either kexec_purgatory (ro) or purgatory_buf (rw)
> > > depending on the section. With these patches the section address will be
> > > calculated verbosely and sh_offset will contain the offset of the section
> > > in the stripped purgatory binary (purgatory_buf).
> > >
> > > Patch #10: Allows architectures to set the purgaory load address. This
> > > patch is important for s390 as the kernel and purgatory have to be loaded
> > > to fixed addresses. In current code this is impossible as the purgatory
> > > load is opaque to the architecture.
> > >
> > > Patch #11: Moves x86 purgatories sha implementation to common lib/
> > > directory.
> > >
> > > Patches #12-17 finally adds the kexec_file_load system call to s390.
> > >
> > > Please note that I had to touch arch code for x86 and power a little. In
> > > theory this should not change the behavior but I don't have a way to test
> > > it. Cross-compiling with defconfig(*) works fine for both.
> > >
> > > Thanks
> > > Philipp
> > >
> > > (*) On x86 with the orc unwinder turned off. objtool SEGFAULTs on s390...
> > >
> > > Philipp Rudo (17):
> > > kexec_file: Silence compile warnings
> > > kexec_file: Remove checks in kexec_purgatory_load
> > > kexec_file: Make purgatory_info->ehdr const
> > > kexec_file: Search symbols in read-only kexec_purgatory
> > > kexec_file: Use read-only sections in arch_kexec_apply_relocations*
> > > kexec_file: Split up __kexec_load_puragory
> > > kexec_file: Simplify kexec_purgatory_setup_sechdrs 1
> > > kexec_file: Simplify kexec_purgatory_setup_sechdrs 2
> > > kexec_file: Remove mis-use of sh_offset field
> > > kexec_file: Allow archs to set purgatory load address
> > > kexec_file: Move purgatories sha256 to common code
> > > s390/kexec_file: Prepare setup.h for kexec_file_load
> > > s390/kexec_file: Add purgatory
> > > s390/kexec_file: Add kexec_file_load system call
> > > s390/kexec_file: Add image loader
> > > s390/kexec_file: Add crash support to image loader
> > > s390/kexec_file: Add ELF loader
> > >
> > > arch/powerpc/kernel/kexec_elf_64.c | 9 +-
> > > arch/s390/Kbuild | 1 +
> > > arch/s390/Kconfig | 4 +
> > > arch/s390/include/asm/kexec.h | 23 ++
> > > arch/s390/include/asm/purgatory.h | 17 ++
> > > arch/s390/include/asm/setup.h | 40 ++-
> > > arch/s390/kernel/Makefile | 1 +
> > > arch/s390/kernel/asm-offsets.c | 5 +
> > > arch/s390/kernel/compat_wrapper.c | 1 +
> > > arch/s390/kernel/kexec_elf.c | 149 ++++++++++
> > > arch/s390/kernel/kexec_image.c | 78 +++++
> > > arch/s390/kernel/machine_kexec_file.c | 291 +++++++++++++++++++
> > > arch/s390/kernel/syscalls/syscall.tbl | 1 +
> > > arch/s390/purgatory/Makefile | 37 +++
> > > arch/s390/purgatory/head.S | 279 ++++++++++++++++++
> > > arch/s390/purgatory/purgatory.c | 42 +++
> > > arch/x86/kernel/kexec-bzimage64.c | 8 +-
> > > arch/x86/kernel/machine_kexec_64.c | 66 ++---
> > > arch/x86/purgatory/Makefile | 3 +
> > > arch/x86/purgatory/purgatory.c | 2 +-
> > > include/linux/kexec.h | 38 +--
> > > {arch/x86/purgatory => include/linux}/sha256.h | 10 +-
> > > kernel/kexec_file.c | 375 ++++++++++++-------------
> > > {arch/x86/purgatory => lib}/sha256.c | 4 +-
> > > 24 files changed, 1200 insertions(+), 284 deletions(-)
> > > create mode 100644 arch/s390/include/asm/purgatory.h
> > > create mode 100644 arch/s390/kernel/kexec_elf.c
> > > create mode 100644 arch/s390/kernel/kexec_image.c
> > > create mode 100644 arch/s390/kernel/machine_kexec_file.c
> > > create mode 100644 arch/s390/purgatory/Makefile
> > > create mode 100644 arch/s390/purgatory/head.S
> > > create mode 100644 arch/s390/purgatory/purgatory.c
> > > rename {arch/x86/purgatory => include/linux}/sha256.h (63%)
> > > rename {arch/x86/purgatory => lib}/sha256.c (99%)
> > >
> > > --
> > > 2.13.5
> > >
> > >
> > > _______________________________________________
> > > kexec mailing list
> > > [email protected]
> > > http://lists.infradead.org/mailman/listinfo/kexec
> >
> > Thanks
> > Dave
> >
>
On 02/14/18 at 10:54am, Philipp Rudo wrote:
> Hi Dave,
>
> I just browsed AKASHI's patches (v7). The way I see it the common code changes
> are on different areas of kexec_file and shouldn't get in conflict. Only in the
> arch code (s390 and arm64) some function calls might need an update. But I have
> to take a closer look on the patches first.
I'm tring both in local branch with both series (V8 from AKASHI and this series),
but there are indeed some conflicts, may because AKASHI factored out some arch
code from ppc/x86 to common code.
>
> @AKASHI: Welcome to the list. While browsing I couldn't find any
> arch_apply_relocation function for arm64. These require the biggest changes in
> my patch set. Did I just miss it or does arm64 work differently?
>
> @Dave: Happy holiday
Thank you!
>
> Thanks
> Philipp
>
> On Wed, 14 Feb 2018 15:35:43 +0800
> Dave Young <[email protected]> wrote:
>
> > Hi Philipp,
> >
> > I added AKASHI in cc, he posted arm64 kexec_file series previously.
> > I would like to read both series especially the general part, but
> > maybe at the end of this month because of a holiday..
> >
> > From the patch log the cleanup looks nice, but still need read the
> > details.
> >
> > On 02/12/18 at 11:07am, Philipp Rudo wrote:
> > > Hi everybody
> > >
> > > resending the series as there was no reaction, yet. Furthermore i was told
> > > that Andrew and the x86 list should also be CCed, so welcome.
> > >
> > > No changes made to the patches since first time i sent them. The patches
> > > apply to the current master (v4.16-rc1).
> > >
> > > Thanks
> > > Philipp
> > >
> > > ---
> > >
> > > this series adds the kexec_file_load system call to s390. Before the system
> > > call is added there are some preparations/clean ups to common
> > > kexec_file_load. In detail this series contains:
> > >
> > > Patch #1&2: Minor cleanups/fixes.
> > >
> > > Patch #3-9: Clean up the purgatory load/relocation code. Especially remove
> > > the mis-use of the purgatory_info->sechdrs->sh_offset field, currently
> > > holding a pointer into either kexec_purgatory (ro) or purgatory_buf (rw)
> > > depending on the section. With these patches the section address will be
> > > calculated verbosely and sh_offset will contain the offset of the section
> > > in the stripped purgatory binary (purgatory_buf).
> > >
> > > Patch #10: Allows architectures to set the purgaory load address. This
> > > patch is important for s390 as the kernel and purgatory have to be loaded
> > > to fixed addresses. In current code this is impossible as the purgatory
> > > load is opaque to the architecture.
> > >
> > > Patch #11: Moves x86 purgatories sha implementation to common lib/
> > > directory.
> > >
> > > Patches #12-17 finally adds the kexec_file_load system call to s390.
> > >
> > > Please note that I had to touch arch code for x86 and power a little. In
> > > theory this should not change the behavior but I don't have a way to test
> > > it. Cross-compiling with defconfig(*) works fine for both.
> > >
> > > Thanks
> > > Philipp
> > >
> > > (*) On x86 with the orc unwinder turned off. objtool SEGFAULTs on s390...
> > >
> > > Philipp Rudo (17):
> > > kexec_file: Silence compile warnings
> > > kexec_file: Remove checks in kexec_purgatory_load
> > > kexec_file: Make purgatory_info->ehdr const
> > > kexec_file: Search symbols in read-only kexec_purgatory
> > > kexec_file: Use read-only sections in arch_kexec_apply_relocations*
> > > kexec_file: Split up __kexec_load_puragory
> > > kexec_file: Simplify kexec_purgatory_setup_sechdrs 1
> > > kexec_file: Simplify kexec_purgatory_setup_sechdrs 2
> > > kexec_file: Remove mis-use of sh_offset field
> > > kexec_file: Allow archs to set purgatory load address
> > > kexec_file: Move purgatories sha256 to common code
> > > s390/kexec_file: Prepare setup.h for kexec_file_load
> > > s390/kexec_file: Add purgatory
> > > s390/kexec_file: Add kexec_file_load system call
> > > s390/kexec_file: Add image loader
> > > s390/kexec_file: Add crash support to image loader
> > > s390/kexec_file: Add ELF loader
> > >
> > > arch/powerpc/kernel/kexec_elf_64.c | 9 +-
> > > arch/s390/Kbuild | 1 +
> > > arch/s390/Kconfig | 4 +
> > > arch/s390/include/asm/kexec.h | 23 ++
> > > arch/s390/include/asm/purgatory.h | 17 ++
> > > arch/s390/include/asm/setup.h | 40 ++-
> > > arch/s390/kernel/Makefile | 1 +
> > > arch/s390/kernel/asm-offsets.c | 5 +
> > > arch/s390/kernel/compat_wrapper.c | 1 +
> > > arch/s390/kernel/kexec_elf.c | 149 ++++++++++
> > > arch/s390/kernel/kexec_image.c | 78 +++++
> > > arch/s390/kernel/machine_kexec_file.c | 291 +++++++++++++++++++
> > > arch/s390/kernel/syscalls/syscall.tbl | 1 +
> > > arch/s390/purgatory/Makefile | 37 +++
> > > arch/s390/purgatory/head.S | 279 ++++++++++++++++++
> > > arch/s390/purgatory/purgatory.c | 42 +++
> > > arch/x86/kernel/kexec-bzimage64.c | 8 +-
> > > arch/x86/kernel/machine_kexec_64.c | 66 ++---
> > > arch/x86/purgatory/Makefile | 3 +
> > > arch/x86/purgatory/purgatory.c | 2 +-
> > > include/linux/kexec.h | 38 +--
> > > {arch/x86/purgatory => include/linux}/sha256.h | 10 +-
> > > kernel/kexec_file.c | 375 ++++++++++++-------------
> > > {arch/x86/purgatory => lib}/sha256.c | 4 +-
> > > 24 files changed, 1200 insertions(+), 284 deletions(-)
> > > create mode 100644 arch/s390/include/asm/purgatory.h
> > > create mode 100644 arch/s390/kernel/kexec_elf.c
> > > create mode 100644 arch/s390/kernel/kexec_image.c
> > > create mode 100644 arch/s390/kernel/machine_kexec_file.c
> > > create mode 100644 arch/s390/purgatory/Makefile
> > > create mode 100644 arch/s390/purgatory/head.S
> > > create mode 100644 arch/s390/purgatory/purgatory.c
> > > rename {arch/x86/purgatory => include/linux}/sha256.h (63%)
> > > rename {arch/x86/purgatory => lib}/sha256.c (99%)
> > >
> > > --
> > > 2.13.5
> > >
> > >
> > > _______________________________________________
> > > kexec mailing list
> > > [email protected]
> > > http://lists.infradead.org/mailman/listinfo/kexec
> >
> > Thanks
> > Dave
> >
>
Hi Dave
On Fri, 23 Feb 2018 16:34:05 +0800
Dave Young <[email protected]> wrote:
> On 02/14/18 at 10:54am, Philipp Rudo wrote:
> > Hi Dave,
> >
> > I just browsed AKASHI's patches (v7). The way I see it the common code changes
> > are on different areas of kexec_file and shouldn't get in conflict. Only in the
> > arch code (s390 and arm64) some function calls might need an update. But I have
> > to take a closer look on the patches first.
>
> I'm tring both in local branch with both series (V8 from AKASHI and this series),
> but there are indeed some conflicts, may because AKASHI factored out some arch
> code from ppc/x86 to common code.
I feared this would happen. I didn't have time to look at AKASHI's v8
yesterday but hope to find some today. How do you think i should handle
conflicts with his patches? I don't think it is wise to include the changes
into my patches as that would make AKASHI's patches a prereq for mine. Is adding
one (multiple?) fixup patches on top of my series ok for you?
Thanks
Philipp
> >
> > @AKASHI: Welcome to the list. While browsing I couldn't find any
> > arch_apply_relocation function for arm64. These require the biggest changes in
> > my patch set. Did I just miss it or does arm64 work differently?
> >
> > @Dave: Happy holiday
>
> Thank you!
>
> >
> > Thanks
> > Philipp
> >
> > On Wed, 14 Feb 2018 15:35:43 +0800
> > Dave Young <[email protected]> wrote:
> >
> > > Hi Philipp,
> > >
> > > I added AKASHI in cc, he posted arm64 kexec_file series previously.
> > > I would like to read both series especially the general part, but
> > > maybe at the end of this month because of a holiday..
> > >
> > > From the patch log the cleanup looks nice, but still need read the
> > > details.
> > >
> > > On 02/12/18 at 11:07am, Philipp Rudo wrote:
> > > > Hi everybody
> > > >
> > > > resending the series as there was no reaction, yet. Furthermore i was told
> > > > that Andrew and the x86 list should also be CCed, so welcome.
> > > >
> > > > No changes made to the patches since first time i sent them. The patches
> > > > apply to the current master (v4.16-rc1).
> > > >
> > > > Thanks
> > > > Philipp
> > > >
> > > > ---
> > > >
> > > > this series adds the kexec_file_load system call to s390. Before the system
> > > > call is added there are some preparations/clean ups to common
> > > > kexec_file_load. In detail this series contains:
> > > >
> > > > Patch #1&2: Minor cleanups/fixes.
> > > >
> > > > Patch #3-9: Clean up the purgatory load/relocation code. Especially remove
> > > > the mis-use of the purgatory_info->sechdrs->sh_offset field, currently
> > > > holding a pointer into either kexec_purgatory (ro) or purgatory_buf (rw)
> > > > depending on the section. With these patches the section address will be
> > > > calculated verbosely and sh_offset will contain the offset of the section
> > > > in the stripped purgatory binary (purgatory_buf).
> > > >
> > > > Patch #10: Allows architectures to set the purgaory load address. This
> > > > patch is important for s390 as the kernel and purgatory have to be loaded
> > > > to fixed addresses. In current code this is impossible as the purgatory
> > > > load is opaque to the architecture.
> > > >
> > > > Patch #11: Moves x86 purgatories sha implementation to common lib/
> > > > directory.
> > > >
> > > > Patches #12-17 finally adds the kexec_file_load system call to s390.
> > > >
> > > > Please note that I had to touch arch code for x86 and power a little. In
> > > > theory this should not change the behavior but I don't have a way to test
> > > > it. Cross-compiling with defconfig(*) works fine for both.
> > > >
> > > > Thanks
> > > > Philipp
> > > >
> > > > (*) On x86 with the orc unwinder turned off. objtool SEGFAULTs on s390...
> > > >
> > > > Philipp Rudo (17):
> > > > kexec_file: Silence compile warnings
> > > > kexec_file: Remove checks in kexec_purgatory_load
> > > > kexec_file: Make purgatory_info->ehdr const
> > > > kexec_file: Search symbols in read-only kexec_purgatory
> > > > kexec_file: Use read-only sections in arch_kexec_apply_relocations*
> > > > kexec_file: Split up __kexec_load_puragory
> > > > kexec_file: Simplify kexec_purgatory_setup_sechdrs 1
> > > > kexec_file: Simplify kexec_purgatory_setup_sechdrs 2
> > > > kexec_file: Remove mis-use of sh_offset field
> > > > kexec_file: Allow archs to set purgatory load address
> > > > kexec_file: Move purgatories sha256 to common code
> > > > s390/kexec_file: Prepare setup.h for kexec_file_load
> > > > s390/kexec_file: Add purgatory
> > > > s390/kexec_file: Add kexec_file_load system call
> > > > s390/kexec_file: Add image loader
> > > > s390/kexec_file: Add crash support to image loader
> > > > s390/kexec_file: Add ELF loader
> > > >
> > > > arch/powerpc/kernel/kexec_elf_64.c | 9 +-
> > > > arch/s390/Kbuild | 1 +
> > > > arch/s390/Kconfig | 4 +
> > > > arch/s390/include/asm/kexec.h | 23 ++
> > > > arch/s390/include/asm/purgatory.h | 17 ++
> > > > arch/s390/include/asm/setup.h | 40 ++-
> > > > arch/s390/kernel/Makefile | 1 +
> > > > arch/s390/kernel/asm-offsets.c | 5 +
> > > > arch/s390/kernel/compat_wrapper.c | 1 +
> > > > arch/s390/kernel/kexec_elf.c | 149 ++++++++++
> > > > arch/s390/kernel/kexec_image.c | 78 +++++
> > > > arch/s390/kernel/machine_kexec_file.c | 291 +++++++++++++++++++
> > > > arch/s390/kernel/syscalls/syscall.tbl | 1 +
> > > > arch/s390/purgatory/Makefile | 37 +++
> > > > arch/s390/purgatory/head.S | 279 ++++++++++++++++++
> > > > arch/s390/purgatory/purgatory.c | 42 +++
> > > > arch/x86/kernel/kexec-bzimage64.c | 8 +-
> > > > arch/x86/kernel/machine_kexec_64.c | 66 ++---
> > > > arch/x86/purgatory/Makefile | 3 +
> > > > arch/x86/purgatory/purgatory.c | 2 +-
> > > > include/linux/kexec.h | 38 +--
> > > > {arch/x86/purgatory => include/linux}/sha256.h | 10 +-
> > > > kernel/kexec_file.c | 375 ++++++++++++-------------
> > > > {arch/x86/purgatory => lib}/sha256.c | 4 +-
> > > > 24 files changed, 1200 insertions(+), 284 deletions(-)
> > > > create mode 100644 arch/s390/include/asm/purgatory.h
> > > > create mode 100644 arch/s390/kernel/kexec_elf.c
> > > > create mode 100644 arch/s390/kernel/kexec_image.c
> > > > create mode 100644 arch/s390/kernel/machine_kexec_file.c
> > > > create mode 100644 arch/s390/purgatory/Makefile
> > > > create mode 100644 arch/s390/purgatory/head.S
> > > > create mode 100644 arch/s390/purgatory/purgatory.c
> > > > rename {arch/x86/purgatory => include/linux}/sha256.h (63%)
> > > > rename {arch/x86/purgatory => lib}/sha256.c (99%)
> > > >
> > > > --
> > > > 2.13.5
> > > >
> > > >
> > > > _______________________________________________
> > > > kexec mailing list
> > > > [email protected]
> > > > http://lists.infradead.org/mailman/listinfo/kexec
> > >
> > > Thanks
> > > Dave
> > >
> >
>
> _______________________________________________
> kexec mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/kexec
>
On 02/23/18 at 11:01am, Philipp Rudo wrote:
> Hi Dave
>
> On Fri, 23 Feb 2018 16:34:05 +0800
> Dave Young <[email protected]> wrote:
>
> > On 02/14/18 at 10:54am, Philipp Rudo wrote:
> > > Hi Dave,
> > >
> > > I just browsed AKASHI's patches (v7). The way I see it the common code changes
> > > are on different areas of kexec_file and shouldn't get in conflict. Only in the
> > > arch code (s390 and arm64) some function calls might need an update. But I have
> > > to take a closer look on the patches first.
> >
> > I'm tring both in local branch with both series (V8 from AKASHI and this series),
> > but there are indeed some conflicts, may because AKASHI factored out some arch
> > code from ppc/x86 to common code.
>
> I feared this would happen. I didn't have time to look at AKASHI's v8
> yesterday but hope to find some today. How do you think i should handle
> conflicts with his patches? I don't think it is wise to include the changes
> into my patches as that would make AKASHI's patches a prereq for mine. Is adding
> one (multiple?) fixup patches on top of my series ok for you?
Arch code need arch maintainer to review, maybe either of you can send
the common part first before the arch code, eg. AKASHI can split the common
cleanup patches and post them as a separate series, after these prep
series are reviewed then other patches can be refreshed based on it.
Seems in AKASHI's series, only patch 2, 3 ,4 ,5 is needed if split out
as a common change series.
What do you think?
>
> Thanks
> Philipp
>
> > >
> > > @AKASHI: Welcome to the list. While browsing I couldn't find any
> > > arch_apply_relocation function for arm64. These require the biggest changes in
> > > my patch set. Did I just miss it or does arm64 work differently?
> > >
> > > @Dave: Happy holiday
> >
> > Thank you!
> >
> > >
> > > Thanks
> > > Philipp
> > >
> > > On Wed, 14 Feb 2018 15:35:43 +0800
> > > Dave Young <[email protected]> wrote:
> > >
> > > > Hi Philipp,
> > > >
> > > > I added AKASHI in cc, he posted arm64 kexec_file series previously.
> > > > I would like to read both series especially the general part, but
> > > > maybe at the end of this month because of a holiday..
> > > >
> > > > From the patch log the cleanup looks nice, but still need read the
> > > > details.
> > > >
> > > > On 02/12/18 at 11:07am, Philipp Rudo wrote:
> > > > > Hi everybody
> > > > >
> > > > > resending the series as there was no reaction, yet. Furthermore i was told
> > > > > that Andrew and the x86 list should also be CCed, so welcome.
> > > > >
> > > > > No changes made to the patches since first time i sent them. The patches
> > > > > apply to the current master (v4.16-rc1).
> > > > >
> > > > > Thanks
> > > > > Philipp
> > > > >
> > > > > ---
> > > > >
> > > > > this series adds the kexec_file_load system call to s390. Before the system
> > > > > call is added there are some preparations/clean ups to common
> > > > > kexec_file_load. In detail this series contains:
> > > > >
> > > > > Patch #1&2: Minor cleanups/fixes.
> > > > >
> > > > > Patch #3-9: Clean up the purgatory load/relocation code. Especially remove
> > > > > the mis-use of the purgatory_info->sechdrs->sh_offset field, currently
> > > > > holding a pointer into either kexec_purgatory (ro) or purgatory_buf (rw)
> > > > > depending on the section. With these patches the section address will be
> > > > > calculated verbosely and sh_offset will contain the offset of the section
> > > > > in the stripped purgatory binary (purgatory_buf).
> > > > >
> > > > > Patch #10: Allows architectures to set the purgaory load address. This
> > > > > patch is important for s390 as the kernel and purgatory have to be loaded
> > > > > to fixed addresses. In current code this is impossible as the purgatory
> > > > > load is opaque to the architecture.
> > > > >
> > > > > Patch #11: Moves x86 purgatories sha implementation to common lib/
> > > > > directory.
> > > > >
> > > > > Patches #12-17 finally adds the kexec_file_load system call to s390.
> > > > >
> > > > > Please note that I had to touch arch code for x86 and power a little. In
> > > > > theory this should not change the behavior but I don't have a way to test
> > > > > it. Cross-compiling with defconfig(*) works fine for both.
> > > > >
> > > > > Thanks
> > > > > Philipp
> > > > >
> > > > > (*) On x86 with the orc unwinder turned off. objtool SEGFAULTs on s390...
> > > > >
> > > > > Philipp Rudo (17):
> > > > > kexec_file: Silence compile warnings
> > > > > kexec_file: Remove checks in kexec_purgatory_load
> > > > > kexec_file: Make purgatory_info->ehdr const
> > > > > kexec_file: Search symbols in read-only kexec_purgatory
> > > > > kexec_file: Use read-only sections in arch_kexec_apply_relocations*
> > > > > kexec_file: Split up __kexec_load_puragory
> > > > > kexec_file: Simplify kexec_purgatory_setup_sechdrs 1
> > > > > kexec_file: Simplify kexec_purgatory_setup_sechdrs 2
> > > > > kexec_file: Remove mis-use of sh_offset field
> > > > > kexec_file: Allow archs to set purgatory load address
> > > > > kexec_file: Move purgatories sha256 to common code
> > > > > s390/kexec_file: Prepare setup.h for kexec_file_load
> > > > > s390/kexec_file: Add purgatory
> > > > > s390/kexec_file: Add kexec_file_load system call
> > > > > s390/kexec_file: Add image loader
> > > > > s390/kexec_file: Add crash support to image loader
> > > > > s390/kexec_file: Add ELF loader
> > > > >
> > > > > arch/powerpc/kernel/kexec_elf_64.c | 9 +-
> > > > > arch/s390/Kbuild | 1 +
> > > > > arch/s390/Kconfig | 4 +
> > > > > arch/s390/include/asm/kexec.h | 23 ++
> > > > > arch/s390/include/asm/purgatory.h | 17 ++
> > > > > arch/s390/include/asm/setup.h | 40 ++-
> > > > > arch/s390/kernel/Makefile | 1 +
> > > > > arch/s390/kernel/asm-offsets.c | 5 +
> > > > > arch/s390/kernel/compat_wrapper.c | 1 +
> > > > > arch/s390/kernel/kexec_elf.c | 149 ++++++++++
> > > > > arch/s390/kernel/kexec_image.c | 78 +++++
> > > > > arch/s390/kernel/machine_kexec_file.c | 291 +++++++++++++++++++
> > > > > arch/s390/kernel/syscalls/syscall.tbl | 1 +
> > > > > arch/s390/purgatory/Makefile | 37 +++
> > > > > arch/s390/purgatory/head.S | 279 ++++++++++++++++++
> > > > > arch/s390/purgatory/purgatory.c | 42 +++
> > > > > arch/x86/kernel/kexec-bzimage64.c | 8 +-
> > > > > arch/x86/kernel/machine_kexec_64.c | 66 ++---
> > > > > arch/x86/purgatory/Makefile | 3 +
> > > > > arch/x86/purgatory/purgatory.c | 2 +-
> > > > > include/linux/kexec.h | 38 +--
> > > > > {arch/x86/purgatory => include/linux}/sha256.h | 10 +-
> > > > > kernel/kexec_file.c | 375 ++++++++++++-------------
> > > > > {arch/x86/purgatory => lib}/sha256.c | 4 +-
> > > > > 24 files changed, 1200 insertions(+), 284 deletions(-)
> > > > > create mode 100644 arch/s390/include/asm/purgatory.h
> > > > > create mode 100644 arch/s390/kernel/kexec_elf.c
> > > > > create mode 100644 arch/s390/kernel/kexec_image.c
> > > > > create mode 100644 arch/s390/kernel/machine_kexec_file.c
> > > > > create mode 100644 arch/s390/purgatory/Makefile
> > > > > create mode 100644 arch/s390/purgatory/head.S
> > > > > create mode 100644 arch/s390/purgatory/purgatory.c
> > > > > rename {arch/x86/purgatory => include/linux}/sha256.h (63%)
> > > > > rename {arch/x86/purgatory => lib}/sha256.c (99%)
> > > > >
> > > > > --
> > > > > 2.13.5
> > > > >
> > > > >
> > > > > _______________________________________________
> > > > > kexec mailing list
> > > > > [email protected]
> > > > > http://lists.infradead.org/mailman/listinfo/kexec
> > > >
> > > > Thanks
> > > > Dave
> > > >
> > >
> >
> > _______________________________________________
> > kexec mailing list
> > [email protected]
> > http://lists.infradead.org/mailman/listinfo/kexec
> >
>
On Sat, Feb 24, 2018 at 09:59:56AM +0800, Dave Young wrote:
> On 02/23/18 at 11:01am, Philipp Rudo wrote:
> > Hi Dave
> >
> > On Fri, 23 Feb 2018 16:34:05 +0800
> > Dave Young <[email protected]> wrote:
> >
> > > On 02/14/18 at 10:54am, Philipp Rudo wrote:
> > > > Hi Dave,
> > > >
> > > > I just browsed AKASHI's patches (v7). The way I see it the common code changes
> > > > are on different areas of kexec_file and shouldn't get in conflict. Only in the
> > > > arch code (s390 and arm64) some function calls might need an update. But I have
> > > > to take a closer look on the patches first.
> > >
> > > I'm tring both in local branch with both series (V8 from AKASHI and this series),
> > > but there are indeed some conflicts, may because AKASHI factored out some arch
> > > code from ppc/x86 to common code.
> >
> > I feared this would happen. I didn't have time to look at AKASHI's v8
> > yesterday but hope to find some today. How do you think i should handle
> > conflicts with his patches? I don't think it is wise to include the changes
> > into my patches as that would make AKASHI's patches a prereq for mine. Is adding
> > one (multiple?) fixup patches on top of my series ok for you?
>
> Arch code need arch maintainer to review, maybe either of you can send
> the common part first before the arch code, eg. AKASHI can split the common
> cleanup patches and post them as a separate series, after these prep
> series are reviewed then other patches can be refreshed based on it.
>
> Seems in AKASHI's series, only patch 2, 3 ,4 ,5 is needed if split out
> as a common change series.
Yeah, all of those are touching kernel/kexec_file.c and in turn
they can conflict if being applied with 390 patches, but none of changes
that I made on kexec_file.c are overlapped with Phillips', I suppose
that merging these two patch sets is rather straightforward.
@Phillips: I hope that your patch#14 and #17 be aligned with my patch#3
as it is factoring out arch_kexec_{image_probe, image_load, verify_sig}()
and arch_kimage_file_post_load_cleanup().
Thanks,
-Takahiro AKASHI
> What do you think?
> >
> > Thanks
> > Philipp
> >
> > > >
> > > > @AKASHI: Welcome to the list. While browsing I couldn't find any
> > > > arch_apply_relocation function for arm64. These require the biggest changes in
> > > > my patch set. Did I just miss it or does arm64 work differently?
> > > >
> > > > @Dave: Happy holiday
> > >
> > > Thank you!
> > >
> > > >
> > > > Thanks
> > > > Philipp
> > > >
> > > > On Wed, 14 Feb 2018 15:35:43 +0800
> > > > Dave Young <[email protected]> wrote:
> > > >
> > > > > Hi Philipp,
> > > > >
> > > > > I added AKASHI in cc, he posted arm64 kexec_file series previously.
> > > > > I would like to read both series especially the general part, but
> > > > > maybe at the end of this month because of a holiday..
> > > > >
> > > > > From the patch log the cleanup looks nice, but still need read the
> > > > > details.
> > > > >
> > > > > On 02/12/18 at 11:07am, Philipp Rudo wrote:
> > > > > > Hi everybody
> > > > > >
> > > > > > resending the series as there was no reaction, yet. Furthermore i was told
> > > > > > that Andrew and the x86 list should also be CCed, so welcome.
> > > > > >
> > > > > > No changes made to the patches since first time i sent them. The patches
> > > > > > apply to the current master (v4.16-rc1).
> > > > > >
> > > > > > Thanks
> > > > > > Philipp
> > > > > >
> > > > > > ---
> > > > > >
> > > > > > this series adds the kexec_file_load system call to s390. Before the system
> > > > > > call is added there are some preparations/clean ups to common
> > > > > > kexec_file_load. In detail this series contains:
> > > > > >
> > > > > > Patch #1&2: Minor cleanups/fixes.
> > > > > >
> > > > > > Patch #3-9: Clean up the purgatory load/relocation code. Especially remove
> > > > > > the mis-use of the purgatory_info->sechdrs->sh_offset field, currently
> > > > > > holding a pointer into either kexec_purgatory (ro) or purgatory_buf (rw)
> > > > > > depending on the section. With these patches the section address will be
> > > > > > calculated verbosely and sh_offset will contain the offset of the section
> > > > > > in the stripped purgatory binary (purgatory_buf).
> > > > > >
> > > > > > Patch #10: Allows architectures to set the purgaory load address. This
> > > > > > patch is important for s390 as the kernel and purgatory have to be loaded
> > > > > > to fixed addresses. In current code this is impossible as the purgatory
> > > > > > load is opaque to the architecture.
> > > > > >
> > > > > > Patch #11: Moves x86 purgatories sha implementation to common lib/
> > > > > > directory.
> > > > > >
> > > > > > Patches #12-17 finally adds the kexec_file_load system call to s390.
> > > > > >
> > > > > > Please note that I had to touch arch code for x86 and power a little. In
> > > > > > theory this should not change the behavior but I don't have a way to test
> > > > > > it. Cross-compiling with defconfig(*) works fine for both.
> > > > > >
> > > > > > Thanks
> > > > > > Philipp
> > > > > >
> > > > > > (*) On x86 with the orc unwinder turned off. objtool SEGFAULTs on s390...
> > > > > >
> > > > > > Philipp Rudo (17):
> > > > > > kexec_file: Silence compile warnings
> > > > > > kexec_file: Remove checks in kexec_purgatory_load
> > > > > > kexec_file: Make purgatory_info->ehdr const
> > > > > > kexec_file: Search symbols in read-only kexec_purgatory
> > > > > > kexec_file: Use read-only sections in arch_kexec_apply_relocations*
> > > > > > kexec_file: Split up __kexec_load_puragory
> > > > > > kexec_file: Simplify kexec_purgatory_setup_sechdrs 1
> > > > > > kexec_file: Simplify kexec_purgatory_setup_sechdrs 2
> > > > > > kexec_file: Remove mis-use of sh_offset field
> > > > > > kexec_file: Allow archs to set purgatory load address
> > > > > > kexec_file: Move purgatories sha256 to common code
> > > > > > s390/kexec_file: Prepare setup.h for kexec_file_load
> > > > > > s390/kexec_file: Add purgatory
> > > > > > s390/kexec_file: Add kexec_file_load system call
> > > > > > s390/kexec_file: Add image loader
> > > > > > s390/kexec_file: Add crash support to image loader
> > > > > > s390/kexec_file: Add ELF loader
> > > > > >
> > > > > > arch/powerpc/kernel/kexec_elf_64.c | 9 +-
> > > > > > arch/s390/Kbuild | 1 +
> > > > > > arch/s390/Kconfig | 4 +
> > > > > > arch/s390/include/asm/kexec.h | 23 ++
> > > > > > arch/s390/include/asm/purgatory.h | 17 ++
> > > > > > arch/s390/include/asm/setup.h | 40 ++-
> > > > > > arch/s390/kernel/Makefile | 1 +
> > > > > > arch/s390/kernel/asm-offsets.c | 5 +
> > > > > > arch/s390/kernel/compat_wrapper.c | 1 +
> > > > > > arch/s390/kernel/kexec_elf.c | 149 ++++++++++
> > > > > > arch/s390/kernel/kexec_image.c | 78 +++++
> > > > > > arch/s390/kernel/machine_kexec_file.c | 291 +++++++++++++++++++
> > > > > > arch/s390/kernel/syscalls/syscall.tbl | 1 +
> > > > > > arch/s390/purgatory/Makefile | 37 +++
> > > > > > arch/s390/purgatory/head.S | 279 ++++++++++++++++++
> > > > > > arch/s390/purgatory/purgatory.c | 42 +++
> > > > > > arch/x86/kernel/kexec-bzimage64.c | 8 +-
> > > > > > arch/x86/kernel/machine_kexec_64.c | 66 ++---
> > > > > > arch/x86/purgatory/Makefile | 3 +
> > > > > > arch/x86/purgatory/purgatory.c | 2 +-
> > > > > > include/linux/kexec.h | 38 +--
> > > > > > {arch/x86/purgatory => include/linux}/sha256.h | 10 +-
> > > > > > kernel/kexec_file.c | 375 ++++++++++++-------------
> > > > > > {arch/x86/purgatory => lib}/sha256.c | 4 +-
> > > > > > 24 files changed, 1200 insertions(+), 284 deletions(-)
> > > > > > create mode 100644 arch/s390/include/asm/purgatory.h
> > > > > > create mode 100644 arch/s390/kernel/kexec_elf.c
> > > > > > create mode 100644 arch/s390/kernel/kexec_image.c
> > > > > > create mode 100644 arch/s390/kernel/machine_kexec_file.c
> > > > > > create mode 100644 arch/s390/purgatory/Makefile
> > > > > > create mode 100644 arch/s390/purgatory/head.S
> > > > > > create mode 100644 arch/s390/purgatory/purgatory.c
> > > > > > rename {arch/x86/purgatory => include/linux}/sha256.h (63%)
> > > > > > rename {arch/x86/purgatory => lib}/sha256.c (99%)
> > > > > >
> > > > > > --
> > > > > > 2.13.5
> > > > > >
> > > > > >
> > > > > > _______________________________________________
> > > > > > kexec mailing list
> > > > > > [email protected]
> > > > > > http://lists.infradead.org/mailman/listinfo/kexec
> > > > >
> > > > > Thanks
> > > > > Dave
> > > > >
> > > >
> > >
> > > _______________________________________________
> > > kexec mailing list
> > > [email protected]
> > > http://lists.infradead.org/mailman/listinfo/kexec
> > >
> >
Hi Dave
Hi AKASHI
On Mon, 26 Feb 2018 10:21:02 +0900
AKASHI Takahiro <[email protected]> wrote:
> >
> > Arch code need arch maintainer to review, maybe either of you can send
> > the common part first before the arch code, eg. AKASHI can split the common
> > cleanup patches and post them as a separate series, after these prep
> > series are reviewed then other patches can be refreshed based on it.
> >
> > Seems in AKASHI's series, only patch 2, 3 ,4 ,5 is needed if split out
> > as a common change series.
>
> Yeah, all of those are touching kernel/kexec_file.c and in turn
> they can conflict if being applied with 390 patches, but none of changes
> that I made on kexec_file.c are overlapped with Phillips', I suppose
> that merging these two patch sets is rather straightforward.
>
> @Phillips: I hope that your patch#14 and #17 be aligned with my patch#3
> as it is factoring out arch_kexec_{image_probe, image_load, verify_sig}()
> and arch_kimage_file_post_load_cleanup().
Splitting the common code patches from the series is totally fine with me.
On Friday I managed to get my code working with AKASHI's patches. After setting
ARCH_HAS_PURGATORY and cleaning up the kexec_* functions it worked basically out
of the box. However there is one problem with older compilers on s390. Please
see my comment on patch #3 for details.
Thanks
Philipp