s390/startup: add initial pgm check handler
authorVasily Gorbik <gor@linux.ibm.com>
Thu, 8 Aug 2019 11:50:02 +0000 (13:50 +0200)
committerVasily Gorbik <gor@linux.ibm.com>
Wed, 21 Aug 2019 10:41:43 +0000 (12:41 +0200)
The startup code is getting more complicated with features like kaslr and
secure boot in place. In a potential unexpected startup code crash case
the system would end up in a pgm check loop at address 0, overwriting
pgm check old psw value and just making debugging more complicated. To
avoid that introduce startup program check handler which is active
immediately after kernel start and until early_pgm_check_handler is set
in kernel/early.c. So it covers kernel relocation phase and transition
to it. This pgm check handler simply saves general/control registers and
psw in the save area which should guarantee that we still have something
to look at when standalone dumper is called without saving registers. And
it does disabled wait with a faulty address in the end.

Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
arch/s390/boot/head.S

index 2087bed6e60f3e8fd72db7a93b2d78e53c068a55..5b79ae7b44f3ff62016f9077e6f6d68b491cbd6c 100644 (file)
@@ -60,8 +60,10 @@ __HEAD
        .long   0x02000690,0x60000050
        .long   0x020006e0,0x20000050
 
-       .org    0x1a0
+       .org    __LC_RST_NEW_PSW                # 0x1a0
        .quad   0,iplstart
+       .org    __LC_PGM_NEW_PSW                # 0x1d0
+       .quad   0x0000000180000000,startup_pgm_check_handler
 
        .org    0x200
 
@@ -351,6 +353,26 @@ ENTRY(startup_kdump)
 
 #include "head_kdump.S"
 
+#
+# This program check is active immediately after kernel start
+# and until early_pgm_check_handler is set in kernel/early.c
+# It simply saves general/control registers and psw in
+# the save area and does disabled wait with a faulty address.
+#
+ENTRY(startup_pgm_check_handler)
+       stmg    %r0,%r15,__LC_SAVE_AREA_SYNC
+       la      %r1,4095
+       stctg   %c0,%c15,__LC_CREGS_SAVE_AREA-4095(%r1)
+       mvc     __LC_GPREGS_SAVE_AREA-4095(128,%r1),__LC_SAVE_AREA_SYNC
+       mvc     __LC_PSW_SAVE_AREA-4095(16,%r1),__LC_PGM_OLD_PSW
+       lg      %r1,__LC_SAVE_AREA_SYNC+8
+       mvc     __LC_RETURN_PSW(16),__LC_PGM_OLD_PSW
+       ni      __LC_RETURN_PSW,0xfc    # remove IO and EX bits
+       ni      __LC_RETURN_PSW+1,0xfb  # remove MCHK bit
+       oi      __LC_RETURN_PSW+1,0x2   # set wait state bit
+       lpswe   __LC_RETURN_PSW         # disabled wait
+ENDPROC(startup_pgm_check_handler)
+
 #
 # params at 10400 (setup.h)
 # Must be keept in sync with struct parmarea in setup.h