s390/ipl: correct kdump reipl block checksum calculation
authorVasily Gorbik <gor@linux.ibm.com>
Wed, 4 Apr 2018 12:42:41 +0000 (14:42 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Tue, 10 Apr 2018 05:39:00 +0000 (07:39 +0200)
s390 kdump reipl implementation relies on os_info kernel structure
residing in old memory being dumped. os_info contains reipl block,
which is used (if valid) by the kdump kernel for reipl parameters.

The problem is that the reipl block and its checksum inside
os_info is updated only when /sys/firmware/reipl/reipl_type is
written. This sets an offset of a reipl block for "reipl_type" and
re-calculates reipl block checksum. Any further alteration of values
under /sys/firmware/reipl/{reipl_type}/ without subsequent write to
/sys/firmware/reipl/reipl_type lead to incorrect os_info reipl block
checksum. In such a case kdump kernel ignores it and reboots using
default logic.

To fix this, os_info reipl block update is moved right before kdump
execution.

Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/include/asm/ipl.h
arch/s390/kernel/ipl.c
arch/s390/kernel/machine_kexec.c

index cbc3e09..ae51357 100644 (file)
@@ -120,6 +120,7 @@ struct ipl_info
 
 extern struct ipl_info ipl_info;
 extern void setup_ipl(void);
+extern void set_os_info_reipl_block(void);
 
 /*
  * DIAG 308 support
index db86c67..75dd085 100644 (file)
@@ -913,11 +913,10 @@ static struct attribute_group reipl_nss_attr_group = {
        .attrs = reipl_nss_attrs,
 };
 
-static void set_reipl_block_actual(struct ipl_parameter_block *reipl_block)
+void set_os_info_reipl_block(void)
 {
-       reipl_block_actual = reipl_block;
        os_info_entry_add(OS_INFO_REIPL_BLOCK, reipl_block_actual,
-                         reipl_block->hdr.len);
+                         reipl_block_actual->hdr.len);
 }
 
 /* reipl type */
@@ -930,18 +929,18 @@ static int reipl_set_type(enum ipl_type type)
        switch(type) {
        case IPL_TYPE_CCW:
                reipl_method = REIPL_METHOD_CCW_DIAG;
-               set_reipl_block_actual(reipl_block_ccw);
+               reipl_block_actual = reipl_block_ccw;
                break;
        case IPL_TYPE_FCP:
                reipl_method = REIPL_METHOD_FCP_DIAG;
-               set_reipl_block_actual(reipl_block_fcp);
+               reipl_block_actual = reipl_block_fcp;
                break;
        case IPL_TYPE_FCP_DUMP:
                reipl_method = REIPL_METHOD_FCP_DUMP;
                break;
        case IPL_TYPE_NSS:
                reipl_method = REIPL_METHOD_NSS_DIAG;
-               set_reipl_block_actual(reipl_block_nss);
+               reipl_block_actual = reipl_block_nss;
                break;
        case IPL_TYPE_UNKNOWN:
                reipl_method = REIPL_METHOD_DEFAULT;
index 9adae2a..b7020e7 100644 (file)
@@ -252,6 +252,7 @@ void machine_shutdown(void)
 
 void machine_crash_shutdown(struct pt_regs *regs)
 {
+       set_os_info_reipl_block();
 }
 
 /*