summaryrefslogtreecommitdiff
path: root/arch/s390/purgatory/head.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/purgatory/head.S')
-rw-r--r--arch/s390/purgatory/head.S96
1 files changed, 96 insertions, 0 deletions
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 <prudo@linux.vnet.ibm.com>
+ */
+
+#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: