diff options
author | Vasily Gorbik <gor@linux.ibm.com> | 2018-04-04 08:42:41 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2018-04-10 01:39:00 -0400 |
commit | 3b9678472bab86ae654cf2c18d5dd551558045be (patch) | |
tree | a952f6901e8b0bec9f84e60099c502b4e13cf78f | |
parent | 0649685073422af82ab8e7d9119b9991403851a6 (diff) |
s390/ipl: correct kdump reipl block checksum calculation
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>
-rw-r--r-- | arch/s390/include/asm/ipl.h | 1 | ||||
-rw-r--r-- | arch/s390/kernel/ipl.c | 11 | ||||
-rw-r--r-- | arch/s390/kernel/machine_kexec.c | 1 |
3 files changed, 7 insertions, 6 deletions
diff --git a/arch/s390/include/asm/ipl.h b/arch/s390/include/asm/ipl.h index cbc3e0945d7e..ae5135704616 100644 --- a/arch/s390/include/asm/ipl.h +++ b/arch/s390/include/asm/ipl.h | |||
@@ -120,6 +120,7 @@ struct ipl_info | |||
120 | 120 | ||
121 | extern struct ipl_info ipl_info; | 121 | extern struct ipl_info ipl_info; |
122 | extern void setup_ipl(void); | 122 | extern void setup_ipl(void); |
123 | extern void set_os_info_reipl_block(void); | ||
123 | 124 | ||
124 | /* | 125 | /* |
125 | * DIAG 308 support | 126 | * DIAG 308 support |
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index db86c67f48ec..75dd08547c31 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c | |||
@@ -913,11 +913,10 @@ static struct attribute_group reipl_nss_attr_group = { | |||
913 | .attrs = reipl_nss_attrs, | 913 | .attrs = reipl_nss_attrs, |
914 | }; | 914 | }; |
915 | 915 | ||
916 | static void set_reipl_block_actual(struct ipl_parameter_block *reipl_block) | 916 | void set_os_info_reipl_block(void) |
917 | { | 917 | { |
918 | reipl_block_actual = reipl_block; | ||
919 | os_info_entry_add(OS_INFO_REIPL_BLOCK, reipl_block_actual, | 918 | os_info_entry_add(OS_INFO_REIPL_BLOCK, reipl_block_actual, |
920 | reipl_block->hdr.len); | 919 | reipl_block_actual->hdr.len); |
921 | } | 920 | } |
922 | 921 | ||
923 | /* reipl type */ | 922 | /* reipl type */ |
@@ -930,18 +929,18 @@ static int reipl_set_type(enum ipl_type type) | |||
930 | switch(type) { | 929 | switch(type) { |
931 | case IPL_TYPE_CCW: | 930 | case IPL_TYPE_CCW: |
932 | reipl_method = REIPL_METHOD_CCW_DIAG; | 931 | reipl_method = REIPL_METHOD_CCW_DIAG; |
933 | set_reipl_block_actual(reipl_block_ccw); | 932 | reipl_block_actual = reipl_block_ccw; |
934 | break; | 933 | break; |
935 | case IPL_TYPE_FCP: | 934 | case IPL_TYPE_FCP: |
936 | reipl_method = REIPL_METHOD_FCP_DIAG; | 935 | reipl_method = REIPL_METHOD_FCP_DIAG; |
937 | set_reipl_block_actual(reipl_block_fcp); | 936 | reipl_block_actual = reipl_block_fcp; |
938 | break; | 937 | break; |
939 | case IPL_TYPE_FCP_DUMP: | 938 | case IPL_TYPE_FCP_DUMP: |
940 | reipl_method = REIPL_METHOD_FCP_DUMP; | 939 | reipl_method = REIPL_METHOD_FCP_DUMP; |
941 | break; | 940 | break; |
942 | case IPL_TYPE_NSS: | 941 | case IPL_TYPE_NSS: |
943 | reipl_method = REIPL_METHOD_NSS_DIAG; | 942 | reipl_method = REIPL_METHOD_NSS_DIAG; |
944 | set_reipl_block_actual(reipl_block_nss); | 943 | reipl_block_actual = reipl_block_nss; |
945 | break; | 944 | break; |
946 | case IPL_TYPE_UNKNOWN: | 945 | case IPL_TYPE_UNKNOWN: |
947 | reipl_method = REIPL_METHOD_DEFAULT; | 946 | reipl_method = REIPL_METHOD_DEFAULT; |
diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c index 9adae2a1e1a0..b7020e721ae3 100644 --- a/arch/s390/kernel/machine_kexec.c +++ b/arch/s390/kernel/machine_kexec.c | |||
@@ -252,6 +252,7 @@ void machine_shutdown(void) | |||
252 | 252 | ||
253 | void machine_crash_shutdown(struct pt_regs *regs) | 253 | void machine_crash_shutdown(struct pt_regs *regs) |
254 | { | 254 | { |
255 | set_os_info_reipl_block(); | ||
255 | } | 256 | } |
256 | 257 | ||
257 | /* | 258 | /* |