Эх сурвалжийг харах

s390/kdump: Use real mode for PSW restart and kexec

Currently the PSW restart handler and kexec are executed in real
mode with DAT=off. For kexec/kdump the function setup_regs() is
called that uses the per-cpu variable "crash_notes". Because
there are situations when the per-cpu implementation uses vmalloc
memory, calling setup_regs() in real mode can cause a program
check interrupt.

To fix that problem this patch changes the following:

* Ensure that diag308_reset() does not change PSW bits to real mode
* Enable DAT in __do_restart() after we switched to an online CPU
* Enable DAT in __machine_kexec() after we switched to the IPL CPU
* Call setup_regs() before we switch to real mode and call purgatory

Reviewed-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Michael Holzheu 13 жил өмнө
parent
commit
fa7c004342

+ 12 - 0
arch/s390/kernel/base.S

@@ -88,6 +88,9 @@ ENTRY(diag308_reset)
 	stctg	%c0,%c15,0(%r4)
 	larl	%r4,.Lfpctl		# Floating point control register
 	stfpc	0(%r4)
+	larl	%r4,.Lcontinue_psw	# Save PSW flags
+	epsw	%r2,%r3
+	stm	%r2,%r3,0(%r4)
 	larl	%r4,.Lrestart_psw	# Setup restart PSW at absolute 0
 	lghi	%r3,0
 	lg	%r4,0(%r4)		# Save PSW
@@ -103,11 +106,20 @@ ENTRY(diag308_reset)
 	lctlg	%c0,%c15,0(%r4)
 	larl	%r4,.Lfpctl		# Restore floating point ctl register
 	lfpc	0(%r4)
+	larl	%r4,.Lcontinue_psw	# Restore PSW flags
+	lpswe	0(%r4)
+.Lcontinue:
 	br	%r14
 .align 16
 .Lrestart_psw:
 	.long	0x00080000,0x80000000 + .Lrestart_part2
 
+	.section .data..nosave,"aw",@progbits
+.align 8
+.Lcontinue_psw:
+	.quad	0,.Lcontinue
+	.previous
+
 	.section .bss
 .align 8
 .Lctlregs:

+ 1 - 0
arch/s390/kernel/ipl.c

@@ -1750,6 +1750,7 @@ static struct kobj_attribute on_restart_attr =
 
 static void __do_restart(void *ignore)
 {
+	__arch_local_irq_stosm(0x04); /* enable DAT */
 	smp_send_stop();
 #ifdef CONFIG_CRASH_DUMP
 	crash_kexec(NULL);

+ 2 - 1
arch/s390/kernel/machine_kexec.c

@@ -80,8 +80,8 @@ static void __do_machine_kdump(void *image)
 #ifdef CONFIG_CRASH_DUMP
 	int (*start_kdump)(int) = (void *)((struct kimage *) image)->start;
 
-	__load_psw_mask(PSW_MASK_BASE | PSW_DEFAULT_KEY | PSW_MASK_EA | PSW_MASK_BA);
 	setup_regs();
+	__load_psw_mask(PSW_MASK_BASE | PSW_DEFAULT_KEY | PSW_MASK_EA | PSW_MASK_BA);
 	start_kdump(1);
 #endif
 }
@@ -214,6 +214,7 @@ static void __machine_kexec(void *data)
 {
 	struct kimage *image = data;
 
+	__arch_local_irq_stosm(0x04); /* enable DAT */
 	pfault_fini();
 	tracing_off();
 	debug_locks_off();