aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/swsusp_asm64.S
diff options
context:
space:
mode:
authorMichael Holzheu <michael.holzheu@linux.vnet.ibm.com>2009-09-22 16:58:53 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2009-09-22 16:58:46 -0400
commit1aaf179d043856d80bbb354f9feaf706b9cfbcd3 (patch)
treeb477b19f229869f45fc9f331f308dcdb5e3b01a0 /arch/s390/kernel/swsusp_asm64.S
parent68d1e5f08b13132504752cad54169376739753db (diff)
[S390] hibernate: Do real CPU swap at resume time
Currently, when the physical resume CPU is not equal to the physical suspend CPU, we swap the CPUs logically, by modifying the logical/physical CPU mapping. This has two major drawbacks: First the change is visible from user space (e.g. CPU sysfs files) and second it is hard to ensure that nowhere in the kernel the physical CPU ID is stored before suspend. To fix this, we now really swap the physical CPUs, if the resume CPU is not the pysical suspend CPU. We restart the suspend CPU and stop the resume CPU using SIGP restart and SIGP stop. If the suspend CPU is no longer available, we write a message and load a disabled wait PSW. Signed-off-by: Michael Holzheu <michael.holzheu@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel/swsusp_asm64.S')
-rw-r--r--arch/s390/kernel/swsusp_asm64.S91
1 files changed, 63 insertions, 28 deletions
diff --git a/arch/s390/kernel/swsusp_asm64.S b/arch/s390/kernel/swsusp_asm64.S
index fc056810a017..fe927d0bc20b 100644
--- a/arch/s390/kernel/swsusp_asm64.S
+++ b/arch/s390/kernel/swsusp_asm64.S
@@ -9,6 +9,7 @@
9 9
10#include <asm/page.h> 10#include <asm/page.h>
11#include <asm/ptrace.h> 11#include <asm/ptrace.h>
12#include <asm/thread_info.h>
12#include <asm/asm-offsets.h> 13#include <asm/asm-offsets.h>
13 14
14/* 15/*
@@ -41,6 +42,9 @@ swsusp_arch_suspend:
41 /* Get pointer to save area */ 42 /* Get pointer to save area */
42 lghi %r1,0x1000 43 lghi %r1,0x1000
43 44
45 /* Save CPU address */
46 stap __LC_CPU_ADDRESS(%r1)
47
44 /* Store registers */ 48 /* Store registers */
45 mvc 0x318(4,%r1),__SF_EMPTY(%r15) /* move prefix to lowcore */ 49 mvc 0x318(4,%r1),__SF_EMPTY(%r15) /* move prefix to lowcore */
46 stfpc 0x31c(%r1) /* store fpu control */ 50 stfpc 0x31c(%r1) /* store fpu control */
@@ -105,12 +109,7 @@ swsusp_arch_resume:
105 /* Make all free pages stable */ 109 /* Make all free pages stable */
106 lghi %r2,1 110 lghi %r2,1
107 brasl %r14,arch_set_page_states 111 brasl %r14,arch_set_page_states
108#ifdef CONFIG_SMP 112
109 /* Save boot cpu number */
110 brasl %r14,smp_get_phys_cpu_id
111 larl %r1,saved_cpu_id
112 st %r2,0(%r1)
113#endif
114 /* Deactivate DAT */ 113 /* Deactivate DAT */
115 stnsm __SF_EMPTY(%r15),0xfb 114 stnsm __SF_EMPTY(%r15),0xfb
116 115
@@ -139,12 +138,10 @@ swsusp_arch_resume:
139 138
140 /* Reset System */ 139 /* Reset System */
141 larl %r1,restart_entry 140 larl %r1,restart_entry
142 larl %r2,restart_psw 141 larl %r2,.Lrestart_diag308_psw
143 og %r1,0(%r2) 142 og %r1,0(%r2)
144 stg %r1,0(%r0) 143 stg %r1,0(%r0)
145 larl %r1,saved_pgm_check_psw 144 larl %r1,.Lnew_pgm_check_psw
146 mvc 0(16,%r1),__LC_PGM_NEW_PSW(%r0)
147 larl %r1,new_pgm_check_psw
148 epsw %r2,%r3 145 epsw %r2,%r3
149 stm %r2,%r3,0(%r1) 146 stm %r2,%r3,0(%r1)
150 mvc __LC_PGM_NEW_PSW(16,%r0),0(%r1) 147 mvc __LC_PGM_NEW_PSW(16,%r0),0(%r1)
@@ -154,12 +151,54 @@ restart_entry:
154 lhi %r1,1 151 lhi %r1,1
155 sigp %r1,%r0,0x12 152 sigp %r1,%r0,0x12
156 sam64 153 sam64
157 larl %r1,new_pgm_check_psw 154 larl %r1,.Lnew_pgm_check_psw
158 lpswe 0(%r1) 155 lpswe 0(%r1)
159pgm_check_entry: 156pgm_check_entry:
160 larl %r1,saved_pgm_check_psw
161 mvc __LC_PGM_NEW_PSW(16,%r0),0(%r1)
162 157
158 /* Switch to original suspend CPU */
159 larl %r1,.Lresume_cpu /* Resume CPU address: r2 */
160 stap 0(%r1)
161 llgh %r2,0(%r1)
162 lghi %r3,0x1000
163 llgh %r1,__LC_CPU_ADDRESS(%r3) /* Suspend CPU address: r1 */
164 cgr %r1,%r2
165 je restore_registers /* r1 = r2 -> nothing to do */
166 larl %r4,.Lrestart_suspend_psw /* Set new restart PSW */
167 mvc __LC_RESTART_PSW(16,%r0),0(%r4)
1683:
169 sigp %r9,%r1,__SIGP_INITIAL_CPU_RESET
170 brc 8,4f /* accepted */
171 brc 2,3b /* busy, try again */
172
173 /* Suspend CPU not available -> panic */
174 larl %r15,init_thread_union
175 ahi %r15,1<<(PAGE_SHIFT+THREAD_ORDER)
176 larl %r2,.Lpanic_string
177 larl %r3,_sclp_print_early
178 lghi %r1,0
179 sam31
180 sigp %r1,%r0,0x12
181 basr %r14,%r3
182 larl %r3,.Ldisabled_wait_31
183 lpsw 0(%r3)
1844:
185 /* Switch to suspend CPU */
186 sigp %r9,%r1,__SIGP_RESTART /* start suspend CPU */
187 brc 2,4b /* busy, try again */
1885:
189 sigp %r9,%r2,__SIGP_STOP /* stop resume (current) CPU */
1906: j 6b
191
192restart_suspend:
193 larl %r1,.Lresume_cpu
194 llgh %r2,0(%r1)
1957:
196 sigp %r9,%r2,__SIGP_SENSE /* Wait for resume CPU */
197 brc 2,7b /* busy, try again */
198 tmll %r9,0x40 /* Test if resume CPU is stopped */
199 jz 7b
200
201restore_registers:
163 /* Restore registers */ 202 /* Restore registers */
164 lghi %r13,0x1000 /* %r1 = pointer to save arae */ 203 lghi %r13,0x1000 /* %r1 = pointer to save arae */
165 204
@@ -193,13 +232,6 @@ pgm_check_entry:
193 /* Pointer to save area */ 232 /* Pointer to save area */
194 lghi %r13,0x1000 233 lghi %r13,0x1000
195 234
196#ifdef CONFIG_SMP
197 /* Switch CPUs */
198 larl %r1,saved_cpu_id
199 llgf %r2,0(%r1)
200 llgf %r3,0x318(%r13)
201 brasl %r14,smp_switch_boot_cpu_in_resume
202#endif
203 /* Restore prefix register */ 235 /* Restore prefix register */
204 spx 0x318(%r13) 236 spx 0x318(%r13)
205 237
@@ -217,13 +249,16 @@ pgm_check_entry:
217 249
218 .section .data.nosave,"aw",@progbits 250 .section .data.nosave,"aw",@progbits
219 .align 8 251 .align 8
220restart_psw: 252.Ldisabled_wait_31:
253 .long 0x000a0000,0x00000000
254.Lpanic_string:
255 .asciz "Resume not possible because suspend CPU is no longer available"
256 .align 8
257.Lrestart_diag308_psw:
221 .long 0x00080000,0x80000000 258 .long 0x00080000,0x80000000
222new_pgm_check_psw: 259.Lrestart_suspend_psw:
260 .quad 0x0000000180000000,restart_suspend
261.Lnew_pgm_check_psw:
223 .quad 0,pgm_check_entry 262 .quad 0,pgm_check_entry
224saved_pgm_check_psw: 263.Lresume_cpu:
225 .quad 0,0 264 .byte 0,0
226#ifdef CONFIG_SMP
227saved_cpu_id:
228 .long 0
229#endif