diff options
Diffstat (limited to 'arch/s390/kernel/swsusp_asm64.S')
-rw-r--r-- | arch/s390/kernel/swsusp_asm64.S | 102 |
1 files changed, 91 insertions, 11 deletions
diff --git a/arch/s390/kernel/swsusp_asm64.S b/arch/s390/kernel/swsusp_asm64.S index 7cd6b096f0d1..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 */ |
@@ -102,11 +106,10 @@ swsusp_arch_resume: | |||
102 | aghi %r15,-STACK_FRAME_OVERHEAD | 106 | aghi %r15,-STACK_FRAME_OVERHEAD |
103 | stg %r1,__SF_BACKCHAIN(%r15) | 107 | stg %r1,__SF_BACKCHAIN(%r15) |
104 | 108 | ||
105 | #ifdef CONFIG_SMP | 109 | /* Make all free pages stable */ |
106 | /* Save boot cpu number */ | 110 | lghi %r2,1 |
107 | brasl %r14,smp_get_phys_cpu_id | 111 | brasl %r14,arch_set_page_states |
108 | lgr %r10,%r2 | 112 | |
109 | #endif | ||
110 | /* Deactivate DAT */ | 113 | /* Deactivate DAT */ |
111 | stnsm __SF_EMPTY(%r15),0xfb | 114 | stnsm __SF_EMPTY(%r15),0xfb |
112 | 115 | ||
@@ -133,6 +136,69 @@ swsusp_arch_resume: | |||
133 | 2: | 136 | 2: |
134 | ptlb /* flush tlb */ | 137 | ptlb /* flush tlb */ |
135 | 138 | ||
139 | /* Reset System */ | ||
140 | larl %r1,restart_entry | ||
141 | larl %r2,.Lrestart_diag308_psw | ||
142 | og %r1,0(%r2) | ||
143 | stg %r1,0(%r0) | ||
144 | larl %r1,.Lnew_pgm_check_psw | ||
145 | epsw %r2,%r3 | ||
146 | stm %r2,%r3,0(%r1) | ||
147 | mvc __LC_PGM_NEW_PSW(16,%r0),0(%r1) | ||
148 | lghi %r0,0 | ||
149 | diag %r0,%r0,0x308 | ||
150 | restart_entry: | ||
151 | lhi %r1,1 | ||
152 | sigp %r1,%r0,0x12 | ||
153 | sam64 | ||
154 | larl %r1,.Lnew_pgm_check_psw | ||
155 | lpswe 0(%r1) | ||
156 | pgm_check_entry: | ||
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) | ||
168 | 3: | ||
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) | ||
184 | 4: | ||
185 | /* Switch to suspend CPU */ | ||
186 | sigp %r9,%r1,__SIGP_RESTART /* start suspend CPU */ | ||
187 | brc 2,4b /* busy, try again */ | ||
188 | 5: | ||
189 | sigp %r9,%r2,__SIGP_STOP /* stop resume (current) CPU */ | ||
190 | 6: j 6b | ||
191 | |||
192 | restart_suspend: | ||
193 | larl %r1,.Lresume_cpu | ||
194 | llgh %r2,0(%r1) | ||
195 | 7: | ||
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 | |||
201 | restore_registers: | ||
136 | /* Restore registers */ | 202 | /* Restore registers */ |
137 | lghi %r13,0x1000 /* %r1 = pointer to save arae */ | 203 | lghi %r13,0x1000 /* %r1 = pointer to save arae */ |
138 | 204 | ||
@@ -166,19 +232,33 @@ swsusp_arch_resume: | |||
166 | /* Pointer to save area */ | 232 | /* Pointer to save area */ |
167 | lghi %r13,0x1000 | 233 | lghi %r13,0x1000 |
168 | 234 | ||
169 | #ifdef CONFIG_SMP | ||
170 | /* Switch CPUs */ | ||
171 | lgr %r2,%r10 /* get cpu id */ | ||
172 | llgf %r3,0x318(%r13) | ||
173 | brasl %r14,smp_switch_boot_cpu_in_resume | ||
174 | #endif | ||
175 | /* Restore prefix register */ | 235 | /* Restore prefix register */ |
176 | spx 0x318(%r13) | 236 | spx 0x318(%r13) |
177 | 237 | ||
178 | /* Activate DAT */ | 238 | /* Activate DAT */ |
179 | stosm __SF_EMPTY(%r15),0x04 | 239 | stosm __SF_EMPTY(%r15),0x04 |
180 | 240 | ||
241 | /* Make all free pages unstable */ | ||
242 | lghi %r2,0 | ||
243 | brasl %r14,arch_set_page_states | ||
244 | |||
181 | /* Return 0 */ | 245 | /* Return 0 */ |
182 | lmg %r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15) | 246 | lmg %r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15) |
183 | lghi %r2,0 | 247 | lghi %r2,0 |
184 | br %r14 | 248 | br %r14 |
249 | |||
250 | .section .data.nosave,"aw",@progbits | ||
251 | .align 8 | ||
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: | ||
258 | .long 0x00080000,0x80000000 | ||
259 | .Lrestart_suspend_psw: | ||
260 | .quad 0x0000000180000000,restart_suspend | ||
261 | .Lnew_pgm_check_psw: | ||
262 | .quad 0,pgm_check_entry | ||
263 | .Lresume_cpu: | ||
264 | .byte 0,0 | ||