diff options
author | Michael Holzheu <holzheu@linux.vnet.ibm.com> | 2012-05-21 05:30:30 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2012-05-23 11:06:51 -0400 |
commit | fa7c0043425624ed65b94a6fabe750c7b0af8719 (patch) | |
tree | 8e21c28d65b56a0bd22af1b9a196083233341b3c /arch/s390/kernel | |
parent | a9fbf1a53836d4105f95df947ac00e22311dff33 (diff) |
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>
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r-- | arch/s390/kernel/base.S | 12 | ||||
-rw-r--r-- | arch/s390/kernel/ipl.c | 1 | ||||
-rw-r--r-- | arch/s390/kernel/machine_kexec.c | 3 |
3 files changed, 15 insertions, 1 deletions
diff --git a/arch/s390/kernel/base.S b/arch/s390/kernel/base.S index 3aa4d00aaf50..c880ff72db44 100644 --- a/arch/s390/kernel/base.S +++ b/arch/s390/kernel/base.S | |||
@@ -88,6 +88,9 @@ ENTRY(diag308_reset) | |||
88 | stctg %c0,%c15,0(%r4) | 88 | stctg %c0,%c15,0(%r4) |
89 | larl %r4,.Lfpctl # Floating point control register | 89 | larl %r4,.Lfpctl # Floating point control register |
90 | stfpc 0(%r4) | 90 | stfpc 0(%r4) |
91 | larl %r4,.Lcontinue_psw # Save PSW flags | ||
92 | epsw %r2,%r3 | ||
93 | stm %r2,%r3,0(%r4) | ||
91 | larl %r4,.Lrestart_psw # Setup restart PSW at absolute 0 | 94 | larl %r4,.Lrestart_psw # Setup restart PSW at absolute 0 |
92 | lghi %r3,0 | 95 | lghi %r3,0 |
93 | lg %r4,0(%r4) # Save PSW | 96 | lg %r4,0(%r4) # Save PSW |
@@ -103,11 +106,20 @@ ENTRY(diag308_reset) | |||
103 | lctlg %c0,%c15,0(%r4) | 106 | lctlg %c0,%c15,0(%r4) |
104 | larl %r4,.Lfpctl # Restore floating point ctl register | 107 | larl %r4,.Lfpctl # Restore floating point ctl register |
105 | lfpc 0(%r4) | 108 | lfpc 0(%r4) |
109 | larl %r4,.Lcontinue_psw # Restore PSW flags | ||
110 | lpswe 0(%r4) | ||
111 | .Lcontinue: | ||
106 | br %r14 | 112 | br %r14 |
107 | .align 16 | 113 | .align 16 |
108 | .Lrestart_psw: | 114 | .Lrestart_psw: |
109 | .long 0x00080000,0x80000000 + .Lrestart_part2 | 115 | .long 0x00080000,0x80000000 + .Lrestart_part2 |
110 | 116 | ||
117 | .section .data..nosave,"aw",@progbits | ||
118 | .align 8 | ||
119 | .Lcontinue_psw: | ||
120 | .quad 0,.Lcontinue | ||
121 | .previous | ||
122 | |||
111 | .section .bss | 123 | .section .bss |
112 | .align 8 | 124 | .align 8 |
113 | .Lctlregs: | 125 | .Lctlregs: |
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 8342e65a140d..dcfdcb3ea163 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c | |||
@@ -1750,6 +1750,7 @@ static struct kobj_attribute on_restart_attr = | |||
1750 | 1750 | ||
1751 | static void __do_restart(void *ignore) | 1751 | static void __do_restart(void *ignore) |
1752 | { | 1752 | { |
1753 | __arch_local_irq_stosm(0x04); /* enable DAT */ | ||
1753 | smp_send_stop(); | 1754 | smp_send_stop(); |
1754 | #ifdef CONFIG_CRASH_DUMP | 1755 | #ifdef CONFIG_CRASH_DUMP |
1755 | crash_kexec(NULL); | 1756 | crash_kexec(NULL); |
diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c index 03d2027d656a..cdacf8f91b2d 100644 --- a/arch/s390/kernel/machine_kexec.c +++ b/arch/s390/kernel/machine_kexec.c | |||
@@ -80,8 +80,8 @@ static void __do_machine_kdump(void *image) | |||
80 | #ifdef CONFIG_CRASH_DUMP | 80 | #ifdef CONFIG_CRASH_DUMP |
81 | int (*start_kdump)(int) = (void *)((struct kimage *) image)->start; | 81 | int (*start_kdump)(int) = (void *)((struct kimage *) image)->start; |
82 | 82 | ||
83 | __load_psw_mask(PSW_MASK_BASE | PSW_DEFAULT_KEY | PSW_MASK_EA | PSW_MASK_BA); | ||
84 | setup_regs(); | 83 | setup_regs(); |
84 | __load_psw_mask(PSW_MASK_BASE | PSW_DEFAULT_KEY | PSW_MASK_EA | PSW_MASK_BA); | ||
85 | start_kdump(1); | 85 | start_kdump(1); |
86 | #endif | 86 | #endif |
87 | } | 87 | } |
@@ -214,6 +214,7 @@ static void __machine_kexec(void *data) | |||
214 | { | 214 | { |
215 | struct kimage *image = data; | 215 | struct kimage *image = data; |
216 | 216 | ||
217 | __arch_local_irq_stosm(0x04); /* enable DAT */ | ||
217 | pfault_fini(); | 218 | pfault_fini(); |
218 | tracing_off(); | 219 | tracing_off(); |
219 | debug_locks_off(); | 220 | debug_locks_off(); |