From 3b9678472bab86ae654cf2c18d5dd551558045be Mon Sep 17 00:00:00 2001 From: Vasily Gorbik Date: Wed, 4 Apr 2018 14:42:41 +0200 Subject: 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 Signed-off-by: Vasily Gorbik Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/ipl.h | 1 + arch/s390/kernel/ipl.c | 11 +++++------ arch/s390/kernel/machine_kexec.c | 1 + 3 files changed, 7 insertions(+), 6 deletions(-) (limited to 'arch/s390') 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 extern struct ipl_info ipl_info; extern void setup_ipl(void); +extern void set_os_info_reipl_block(void); /* * 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 = { .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; 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) void machine_crash_shutdown(struct pt_regs *regs) { + set_os_info_reipl_block(); } /* -- cgit v1.2.3