diff options
author | Philipp Rudo <prudo@linux.vnet.ibm.com> | 2017-08-28 09:32:36 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2018-04-16 03:10:22 -0400 |
commit | 840798a1f52994c172270893bd2ec6013cc92e40 (patch) | |
tree | 338936422b71c2f0d6ab52fe7c81537cacdeadf0 | |
parent | 15ceb8c936d13d940ca9e53996fbd05a26ce96db (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/Kbuild | 1 | ||||
-rw-r--r-- | arch/s390/Kconfig | 4 | ||||
-rw-r--r-- | arch/s390/include/asm/purgatory.h | 17 | ||||
-rw-r--r-- | arch/s390/kernel/asm-offsets.c | 5 | ||||
-rw-r--r-- | arch/s390/purgatory/Makefile | 37 | ||||
-rw-r--r-- | arch/s390/purgatory/head.S | 96 | ||||
-rw-r--r-- | arch/s390/purgatory/purgatory.c | 38 |
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/ | |||
8 | obj-y += net/ | 8 | obj-y += net/ |
9 | obj-$(CONFIG_PCI) += pci/ | 9 | obj-$(CONFIG_PCI) += pci/ |
10 | obj-$(CONFIG_NUMA) += numa/ | 10 | obj-$(CONFIG_NUMA) += numa/ |
11 | obj-$(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 | ||
54 | config ARCH_HAS_KEXEC_PURGATORY | ||
55 | def_bool y | ||
56 | depends on KEXEC_FILE | ||
57 | |||
54 | config AUDIT_ARCH | 58 | config 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 | |||
14 | int 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 | |||
3 | OBJECT_FILES_NON_STANDARD := y | ||
4 | |||
5 | purgatory-y := head.o purgatory.o string.o sha256.o mem.o | ||
6 | |||
7 | targets += $(purgatory-y) purgatory.ro kexec-purgatory.c | ||
8 | PURGATORY_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 | |||
19 | LDFLAGS_purgatory.ro := -e purgatory_start -r --no-undefined -nostdlib | ||
20 | LDFLAGS_purgatory.ro += -z nodefaultlib | ||
21 | KBUILD_CFLAGS := -fno-strict-aliasing -Wall -Wstrict-prototypes | ||
22 | KBUILD_CFLAGS += -Wno-pointer-sign -Wno-sign-compare | ||
23 | KBUILD_CFLAGS += -fno-zero-initialized-in-bss -fno-builtin -ffreestanding | ||
24 | KBUILD_CFLAGS += -c -MD -Os -m64 | ||
25 | KBUILD_CFLAGS += $(call cc-option,-fno-PIE) | ||
26 | |||
27 | $(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE | ||
28 | $(call if_changed,ld) | ||
29 | |||
30 | CMD_BIN2C = $(objtree)/scripts/basic/bin2c | ||
31 | quiet_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 | |||
37 | obj-$(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 | ||
32 | ENTRY(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 | |||
63 | load_psw_mask: | ||
64 | .long 0x00080000,0x80000000 | ||
65 | |||
66 | .align 8 | ||
67 | disabled_wait_psw: | ||
68 | .quad 0x0002000180000000 | ||
69 | .quad 0x0000000000000000 + .do_checksum_verification | ||
70 | |||
71 | gprregs: | ||
72 | .rept 10 | ||
73 | .quad 0 | ||
74 | .endr | ||
75 | |||
76 | purgatory_sha256_digest: | ||
77 | .global purgatory_sha256_digest | ||
78 | .rept 32 /* SHA256_DIGEST_SIZE */ | ||
79 | .byte 0 | ||
80 | .endr | ||
81 | |||
82 | purgatory_sha_regions: | ||
83 | .global purgatory_sha_regions | ||
84 | .rept 16 * __KEXEC_SHA_REGION_SIZE /* KEXEC_SEGMENTS_MAX */ | ||
85 | .byte 0 | ||
86 | .endr | ||
87 | |||
88 | kernel_entry: | ||
89 | .global kernel_entry | ||
90 | .quad 0 | ||
91 | |||
92 | .align PAGE_SIZE | ||
93 | stack: | ||
94 | .skip PAGE_SIZE | ||
95 | .align PAGE_SIZE | ||
96 | purgatory_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 | |||
15 | struct kexec_sha_region purgatory_sha_regions[KEXEC_SEGMENT_MAX]; | ||
16 | u8 purgatory_sha256_digest[SHA256_DIGEST_SIZE]; | ||
17 | |||
18 | u64 kernel_entry; | ||
19 | |||
20 | int 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 | } | ||