]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
s390/kdump: Use real mode for PSW restart and kexec
authorMichael Holzheu <holzheu@linux.vnet.ibm.com>
Mon, 21 May 2012 09:30:30 +0000 (11:30 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Wed, 23 May 2012 15:06:51 +0000 (17:06 +0200)
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>
arch/s390/kernel/base.S
arch/s390/kernel/ipl.c
arch/s390/kernel/machine_kexec.c

index 3aa4d00aaf50ec0af3d4581facf40c1cffeef171..c880ff72db44a0247f57c48450a230f682843ec1 100644 (file)
@@ -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:
index 8342e65a140daf7bb3fc9f589fbcd1f8d417f322..dcfdcb3ea1637e9a93dbca03e625ed3c1971f18b 100644 (file)
@@ -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);
index 03d2027d656a13b8c3f4607aa830e822a9aa51e3..cdacf8f91b2d11b7cb3acd683f7a8db830c6fb05 100644 (file)
@@ -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();