aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Rudo <prudo@linux.vnet.ibm.com>2017-08-28 09:32:36 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2018-04-16 03:10:22 -0400
commit840798a1f52994c172270893bd2ec6013cc92e40 (patch)
tree338936422b71c2f0d6ab52fe7c81537cacdeadf0
parent15ceb8c936d13d940ca9e53996fbd05a26ce96db (diff)
s390/kexec_file: Add purgatory
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 <prudo@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/Kbuild1
-rw-r--r--arch/s390/Kconfig4
-rw-r--r--arch/s390/include/asm/purgatory.h17
-rw-r--r--arch/s390/kernel/asm-offsets.c5
-rw-r--r--arch/s390/purgatory/Makefile37
-rw-r--r--arch/s390/purgatory/head.S96
-rw-r--r--arch/s390/purgatory/purgatory.c38
7 files changed, 198 insertions, 0 deletions
diff --git a/arch/s390/Kbuild b/arch/s390/Kbuild
index 9fdff3fe1a42..e63940bb57cd 100644
--- a/arch/s390/Kbuild
+++ b/arch/s390/Kbuild
@@ -8,3 +8,4 @@ obj-$(CONFIG_APPLDATA_BASE) += appldata/
8obj-y += net/ 8obj-y += net/
9obj-$(CONFIG_PCI) += pci/ 9obj-$(CONFIG_PCI) += pci/
10obj-$(CONFIG_NUMA) += numa/ 10obj-$(CONFIG_NUMA) += numa/
11obj-$(CONFIG_ARCH_HAS_KEXEC_PURGATORY) += purgatory/
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 32a0d5b958bf..5b8d0859b317 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -51,6 +51,10 @@ config KEXEC
51 def_bool y 51 def_bool y
52 select KEXEC_CORE 52 select KEXEC_CORE
53 53
54config ARCH_HAS_KEXEC_PURGATORY
55 def_bool y
56 depends on KEXEC_FILE
57
54config AUDIT_ARCH 58config AUDIT_ARCH
55 def_bool y 59 def_bool y
56 60
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 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright IBM Corp. 2018
4 *
5 * Author(s): Philipp Rudo <prudo@linux.vnet.ibm.com>
6 */
7
8#ifndef _S390_PURGATORY_H_
9#define _S390_PURGATORY_H_
10#ifndef __ASSEMBLY__
11
12#include <linux/purgatory.h>
13
14int verify_sha256_digest(void);
15
16#endif /* __ASSEMBLY__ */
17#endif /* _S390_PURGATORY_H_ */
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
index cfe2c45c5180..eb2a5c0443cd 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -10,6 +10,7 @@
10#include <linux/kbuild.h> 10#include <linux/kbuild.h>
11#include <linux/kvm_host.h> 11#include <linux/kvm_host.h>
12#include <linux/sched.h> 12#include <linux/sched.h>
13#include <linux/purgatory.h>
13#include <asm/idle.h> 14#include <asm/idle.h>
14#include <asm/vdso.h> 15#include <asm/vdso.h>
15#include <asm/pgtable.h> 16#include <asm/pgtable.h>
@@ -204,5 +205,9 @@ int main(void)
204 OFFSET(__GMAP_ASCE, gmap, asce); 205 OFFSET(__GMAP_ASCE, gmap, asce);
205 OFFSET(__SIE_PROG0C, kvm_s390_sie_block, prog0c); 206 OFFSET(__SIE_PROG0C, kvm_s390_sie_block, prog0c);
206 OFFSET(__SIE_PROG20, kvm_s390_sie_block, prog20); 207 OFFSET(__SIE_PROG20, kvm_s390_sie_block, prog20);
208 /* kexec_sha_region */
209 OFFSET(__KEXEC_SHA_REGION_START, kexec_sha_region, start);
210 OFFSET(__KEXEC_SHA_REGION_LEN, kexec_sha_region, len);
211 DEFINE(__KEXEC_SHA_REGION_SIZE, sizeof(struct kexec_sha_region));
207 return 0; 212 return 0;
208} 213}
diff --git a/arch/s390/purgatory/Makefile b/arch/s390/purgatory/Makefile
new file mode 100644
index 000000000000..e9525bc1b4a6
--- /dev/null
+++ b/arch/s390/purgatory/Makefile
@@ -0,0 +1,37 @@
1# SPDX-License-Identifier: GPL-2.0
2
3OBJECT_FILES_NON_STANDARD := y
4
5purgatory-y := head.o purgatory.o string.o sha256.o mem.o
6
7targets += $(purgatory-y) purgatory.ro kexec-purgatory.c
8PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
9
10$(obj)/sha256.o: $(srctree)/lib/sha256.c
11 $(call if_changed_rule,cc_o_c)
12
13$(obj)/mem.o: $(srctree)/arch/s390/lib/mem.S
14 $(call if_changed_rule,as_o_S)
15
16$(obj)/string.o: $(srctree)/arch/s390/lib/string.c
17 $(call if_changed_rule,cc_o_c)
18
19LDFLAGS_purgatory.ro := -e purgatory_start -r --no-undefined -nostdlib
20LDFLAGS_purgatory.ro += -z nodefaultlib
21KBUILD_CFLAGS := -fno-strict-aliasing -Wall -Wstrict-prototypes
22KBUILD_CFLAGS += -Wno-pointer-sign -Wno-sign-compare
23KBUILD_CFLAGS += -fno-zero-initialized-in-bss -fno-builtin -ffreestanding
24KBUILD_CFLAGS += -c -MD -Os -m64
25KBUILD_CFLAGS += $(call cc-option,-fno-PIE)
26
27$(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
28 $(call if_changed,ld)
29
30CMD_BIN2C = $(objtree)/scripts/basic/bin2c
31quiet_cmd_bin2c = BIN2C $@
32 cmd_bin2c = $(CMD_BIN2C) kexec_purgatory < $< > $@
33
34$(obj)/kexec-purgatory.c: $(obj)/purgatory.ro FORCE
35 $(call if_changed,bin2c)
36
37obj-$(CONFIG_ARCH_HAS_KEXEC_PURGATORY) += 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 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Purgatory setup code
4 *
5 * Copyright IBM Corp. 2018
6 *
7 * Author(s): Philipp Rudo <prudo@linux.vnet.ibm.com>
8 */
9
10#include <linux/linkage.h>
11#include <asm/asm-offsets.h>
12#include <asm/page.h>
13#include <asm/sigp.h>
14
15/* The purgatory is the code running between two kernels. It's main purpose
16 * is to verify that the next kernel was not corrupted after load and to
17 * start it.
18 */
19
20.macro START_NEXT_KERNEL base
21 lg %r4,kernel_entry-\base(%r13)
22 lg %r5,load_psw_mask-\base(%r13)
23 ogr %r4,%r5
24 stg %r4,0(%r0)
25
26 xgr %r0,%r0
27 diag %r0,%r0,0x308
28.endm
29
30.text
31.align PAGE_SIZE
32ENTRY(purgatory_start)
33 /* The purgatory might be called after a diag308 so better set
34 * architecture and addressing mode.
35 */
36 lhi %r1,1
37 sigp %r1,%r0,SIGP_SET_ARCHITECTURE
38 sam64
39
40 larl %r5,gprregs
41 stmg %r6,%r15,0(%r5)
42
43 basr %r13,0
44.base_crash:
45
46 /* Setup stack */
47 larl %r15,purgatory_end
48 aghi %r15,-160
49
50.do_checksum_verification:
51 brasl %r14,verify_sha256_digest
52
53 cghi %r2,0 /* checksum match */
54 jne .disabled_wait
55
56 /* start normal kernel */
57 START_NEXT_KERNEL .base_crash
58
59.disabled_wait:
60 lpswe disabled_wait_psw-.base_crash(%r13)
61
62
63load_psw_mask:
64 .long 0x00080000,0x80000000
65
66 .align 8
67disabled_wait_psw:
68 .quad 0x0002000180000000
69 .quad 0x0000000000000000 + .do_checksum_verification
70
71gprregs:
72 .rept 10
73 .quad 0
74 .endr
75
76purgatory_sha256_digest:
77 .global purgatory_sha256_digest
78 .rept 32 /* SHA256_DIGEST_SIZE */
79 .byte 0
80 .endr
81
82purgatory_sha_regions:
83 .global purgatory_sha_regions
84 .rept 16 * __KEXEC_SHA_REGION_SIZE /* KEXEC_SEGMENTS_MAX */
85 .byte 0
86 .endr
87
88kernel_entry:
89 .global kernel_entry
90 .quad 0
91
92 .align PAGE_SIZE
93stack:
94 .skip PAGE_SIZE
95 .align PAGE_SIZE
96purgatory_end:
diff --git a/arch/s390/purgatory/purgatory.c b/arch/s390/purgatory/purgatory.c
new file mode 100644
index 000000000000..52b92f2bf0b9
--- /dev/null
+++ b/arch/s390/purgatory/purgatory.c
@@ -0,0 +1,38 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Purgatory code running between two kernels.
4 *
5 * Copyright IBM Corp. 2018
6 *
7 * Author(s): Philipp Rudo <prudo@linux.vnet.ibm.com>
8 */
9
10#include <linux/kexec.h>
11#include <linux/sha256.h>
12#include <linux/string.h>
13#include <asm/purgatory.h>
14
15struct kexec_sha_region purgatory_sha_regions[KEXEC_SEGMENT_MAX];
16u8 purgatory_sha256_digest[SHA256_DIGEST_SIZE];
17
18u64 kernel_entry;
19
20int verify_sha256_digest(void)
21{
22 struct kexec_sha_region *ptr, *end;
23 u8 digest[SHA256_DIGEST_SIZE];
24 struct sha256_state sctx;
25
26 sha256_init(&sctx);
27 end = purgatory_sha_regions + ARRAY_SIZE(purgatory_sha_regions);
28
29 for (ptr = purgatory_sha_regions; ptr < end; ptr++)
30 sha256_update(&sctx, (uint8_t *)(ptr->start), ptr->len);
31
32 sha256_final(&sctx, digest);
33
34 if (memcmp(digest, purgatory_sha256_digest, sizeof(digest)))
35 return 1;
36
37 return 0;
38}