License cleanup: add SPDX GPL-2.0 license identifier to files with no license
[linux-block.git] / arch / s390 / kernel / swsusp.S
CommitLineData
b2441318 1/* SPDX-License-Identifier: GPL-2.0 */
155af2f9
HJP
2/*
3 * S390 64-bit swsusp implementation
4 *
5 * Copyright IBM Corp. 2009
6 *
7 * Author(s): Hans-Joachim Picht <hans@linux.vnet.ibm.com>
8 * Michael Holzheu <holzheu@linux.vnet.ibm.com>
9 */
10
144d634a 11#include <linux/linkage.h>
155af2f9
HJP
12#include <asm/page.h>
13#include <asm/ptrace.h>
1aaf179d 14#include <asm/thread_info.h>
155af2f9 15#include <asm/asm-offsets.h>
eb546195 16#include <asm/sigp.h>
155af2f9
HJP
17
18/*
19 * Save register context in absolute 0 lowcore and call swsusp_save() to
20 * create in-memory kernel image. The context is saved in the designated
21 * "store status" memory locations (see POP).
22 * We return from this function twice. The first time during the suspend to
23 * disk process. The second time via the swsusp_arch_resume() function
24 * (see below) in the resume process.
25 * This function runs with disabled interrupts.
26 */
27 .section .text
144d634a 28ENTRY(swsusp_arch_suspend)
155af2f9
HJP
29 stmg %r6,%r15,__SF_GPRS(%r15)
30 lgr %r1,%r15
31 aghi %r15,-STACK_FRAME_OVERHEAD
32 stg %r1,__SF_BACKCHAIN(%r15)
33
88d64253
MS
34 /* Store FPU registers */
35 brasl %r14,save_fpu_regs
36
155af2f9
HJP
37 /* Deactivate DAT */
38 stnsm __SF_EMPTY(%r15),0xfb
39
155af2f9
HJP
40 /* Store prefix register on stack */
41 stpx __SF_EMPTY(%r15)
42
91c15a95
MH
43 /* Save prefix register contents for lowcore copy */
44 llgf %r10,__SF_EMPTY(%r15)
155af2f9
HJP
45
46 /* Get pointer to save area */
5f954c34 47 lghi %r1,0x1000
155af2f9 48
1aaf179d 49 /* Save CPU address */
7e180bd8 50 stap __LC_EXT_CPU_ADDR(%r0)
1aaf179d 51
155af2f9
HJP
52 /* Store registers */
53 mvc 0x318(4,%r1),__SF_EMPTY(%r15) /* move prefix to lowcore */
155af2f9
HJP
54 stam %a0,%a15,0x340(%r1) /* store access registers */
55 stctg %c0,%c15,0x380(%r1) /* store control registers */
56 stmg %r0,%r15,0x280(%r1) /* store general registers */
57
58 stpt 0x328(%r1) /* store timer */
623c08e4 59 stck __SF_EMPTY(%r15) /* store clock */
155af2f9
HJP
60 stckc 0x330(%r1) /* store clock comparator */
61
623c08e4
MS
62 /* Update cputime accounting before going to sleep */
63 lg %r0,__LC_LAST_UPDATE_TIMER
64 slg %r0,0x328(%r1)
65 alg %r0,__LC_SYSTEM_TIMER
66 stg %r0,__LC_SYSTEM_TIMER
67 mvc __LC_LAST_UPDATE_TIMER(8),0x328(%r1)
68 lg %r0,__LC_LAST_UPDATE_CLOCK
69 slg %r0,__SF_EMPTY(%r15)
70 alg %r0,__LC_STEAL_TIMER
71 stg %r0,__LC_STEAL_TIMER
72 mvc __LC_LAST_UPDATE_CLOCK(8),__SF_EMPTY(%r15)
73
155af2f9
HJP
74 /* Activate DAT */
75 stosm __SF_EMPTY(%r15),0x04
76
77 /* Set prefix page to zero */
78 xc __SF_EMPTY(4,%r15),__SF_EMPTY(%r15)
79 spx __SF_EMPTY(%r15)
80
91c15a95
MH
81 /* Save absolute zero pages */
82 larl %r2,suspend_zero_pages
83 lg %r2,0(%r2)
84 lghi %r4,0
85 lghi %r3,2*PAGE_SIZE
86 lghi %r5,2*PAGE_SIZE
871: mvcle %r2,%r4,0
88 jo 1b
89
90 /* Copy lowcore to absolute zero lowcore */
5f954c34 91 lghi %r2,0
91c15a95 92 lgr %r4,%r10
5f954c34
HC
93 lghi %r3,2*PAGE_SIZE
94 lghi %r5,2*PAGE_SIZE
951: mvcle %r2,%r4,0
96 jo 1b
155af2f9
HJP
97
98 /* Save image */
99 brasl %r14,swsusp_save
100
155af2f9
HJP
101 /* Restore prefix register and return */
102 lghi %r1,0x1000
103 spx 0x318(%r1)
104 lmg %r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15)
105 lghi %r2,0
106 br %r14
107
108/*
109 * Restore saved memory image to correct place and restore register context.
110 * Then we return to the function that called swsusp_arch_suspend().
111 * swsusp_arch_resume() runs with disabled interrupts.
112 */
144d634a 113ENTRY(swsusp_arch_resume)
155af2f9
HJP
114 stmg %r6,%r15,__SF_GPRS(%r15)
115 lgr %r1,%r15
116 aghi %r15,-STACK_FRAME_OVERHEAD
117 stg %r1,__SF_BACKCHAIN(%r15)
118
846955c8
HC
119 /* Make all free pages stable */
120 lghi %r2,1
121 brasl %r14,arch_set_page_states
1aaf179d 122
155af2f9
HJP
123 /* Deactivate DAT */
124 stnsm __SF_EMPTY(%r15),0xfb
125
155af2f9
HJP
126 /* Set prefix page to zero */
127 xc __SF_EMPTY(4,%r15),__SF_EMPTY(%r15)
128 spx __SF_EMPTY(%r15)
129
130 /* Restore saved image */
131 larl %r1,restore_pblist
132 lg %r1,0(%r1)
133 ltgr %r1,%r1
134 jz 2f
1350:
136 lg %r2,8(%r1)
137 lg %r4,0(%r1)
85055dd8 138 iske %r0,%r4
155af2f9
HJP
139 lghi %r3,PAGE_SIZE
140 lghi %r5,PAGE_SIZE
1411:
142 mvcle %r2,%r4,0
143 jo 1b
85055dd8
MS
144 lg %r2,8(%r1)
145 sske %r0,%r2
155af2f9
HJP
146 lg %r1,16(%r1)
147 ltgr %r1,%r1
148 jnz 0b
1492:
150 ptlb /* flush tlb */
151
2583d1ef
HC
152 /* Reset System */
153 larl %r1,restart_entry
1aaf179d 154 larl %r2,.Lrestart_diag308_psw
2583d1ef
HC
155 og %r1,0(%r2)
156 stg %r1,0(%r0)
1aaf179d 157 larl %r1,.Lnew_pgm_check_psw
2583d1ef
HC
158 epsw %r2,%r3
159 stm %r2,%r3,0(%r1)
160 mvc __LC_PGM_NEW_PSW(16,%r0),0(%r1)
161 lghi %r0,0
162 diag %r0,%r0,0x308
163restart_entry:
164 lhi %r1,1
eb546195 165 sigp %r1,%r0,SIGP_SET_ARCHITECTURE
2583d1ef 166 sam64
1833c9f6
HC
167#ifdef CONFIG_SMP
168 larl %r1,smp_cpu_mt_shift
169 icm %r1,15,0(%r1)
170 jz smt_done
171 llgfr %r1,%r1
172smt_loop:
173 sigp %r1,%r0,SIGP_SET_MULTI_THREADING
174 brc 8,smt_done /* accepted */
175 brc 2,smt_loop /* busy, try again */
176smt_done:
177#endif
1aaf179d 178 larl %r1,.Lnew_pgm_check_psw
2583d1ef
HC
179 lpswe 0(%r1)
180pgm_check_entry:
2583d1ef 181
1aaf179d
MH
182 /* Switch to original suspend CPU */
183 larl %r1,.Lresume_cpu /* Resume CPU address: r2 */
184 stap 0(%r1)
185 llgh %r2,0(%r1)
7e180bd8 186 llgh %r1,__LC_EXT_CPU_ADDR(%r0) /* Suspend CPU address: r1 */
1aaf179d
MH
187 cgr %r1,%r2
188 je restore_registers /* r1 = r2 -> nothing to do */
189 larl %r4,.Lrestart_suspend_psw /* Set new restart PSW */
abd1ecf2 190 mvc __LC_RST_NEW_PSW(16,%r0),0(%r4)
1aaf179d 1913:
eb546195 192 sigp %r9,%r1,SIGP_INITIAL_CPU_RESET /* sigp initial cpu reset */
8b646bd7
MS
193 brc 8,4f /* accepted */
194 brc 2,3b /* busy, try again */
1aaf179d
MH
195
196 /* Suspend CPU not available -> panic */
197 larl %r15,init_thread_union
3a890380 198 ahi %r15,1<<(PAGE_SHIFT+THREAD_SIZE_ORDER)
1aaf179d 199 larl %r2,.Lpanic_string
d5ab7a34 200 larl %r3,sclp_early_printk
1aaf179d
MH
201 lghi %r1,0
202 sam31
eb546195 203 sigp %r1,%r0,SIGP_SET_ARCHITECTURE
1aaf179d
MH
204 basr %r14,%r3
205 larl %r3,.Ldisabled_wait_31
206 lpsw 0(%r3)
2074:
208 /* Switch to suspend CPU */
eb546195 209 sigp %r9,%r1,SIGP_RESTART /* sigp restart to suspend CPU */
1aaf179d
MH
210 brc 2,4b /* busy, try again */
2115:
eb546195 212 sigp %r9,%r2,SIGP_STOP /* sigp stop to current resume CPU */
f8501ba7 213 brc 2,5b /* busy, try again */
1aaf179d
MH
2146: j 6b
215
216restart_suspend:
217 larl %r1,.Lresume_cpu
218 llgh %r2,0(%r1)
2197:
eb546195 220 sigp %r9,%r2,SIGP_SENSE /* sigp sense, wait for resume CPU */
b3dcf3de 221 brc 8,7b /* accepted, status 0, still running */
1aaf179d
MH
222 brc 2,7b /* busy, try again */
223 tmll %r9,0x40 /* Test if resume CPU is stopped */
224 jz 7b
225
226restore_registers:
155af2f9 227 /* Restore registers */
623c08e4 228 lghi %r13,0x1000 /* %r1 = pointer to save area */
155af2f9 229
623c08e4
MS
230 /* Ignore time spent in suspended state. */
231 llgf %r1,0x318(%r13)
232 stck __LC_LAST_UPDATE_CLOCK(%r1)
155af2f9
HJP
233 spt 0x328(%r13) /* reprogram timer */
234 //sckc 0x330(%r13) /* set clock comparator */
235
236 lctlg %c0,%c15,0x380(%r13) /* load control registers */
237 lam %a0,%a15,0x340(%r13) /* load access registers */
238
155af2f9
HJP
239 /* Load old stack */
240 lg %r15,0x2f8(%r13)
241
91c15a95
MH
242 /* Save prefix register */
243 mvc __SF_EMPTY(4,%r15),0x318(%r13)
244
245 /* Restore absolute zero pages */
246 lghi %r2,0
247 larl %r4,suspend_zero_pages
248 lg %r4,0(%r4)
249 lghi %r3,2*PAGE_SIZE
250 lghi %r5,2*PAGE_SIZE
2511: mvcle %r2,%r4,0
252 jo 1b
253
155af2f9 254 /* Restore prefix register */
91c15a95 255 spx __SF_EMPTY(%r15)
155af2f9 256
155af2f9
HJP
257 /* Activate DAT */
258 stosm __SF_EMPTY(%r15),0x04
259
846955c8
HC
260 /* Make all free pages unstable */
261 lghi %r2,0
262 brasl %r14,arch_set_page_states
263
77e844b9
SO
264 /* Call arch specific early resume code */
265 brasl %r14,s390_early_resume
889ee955 266
155af2f9
HJP
267 /* Return 0 */
268 lmg %r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15)
269 lghi %r2,0
270 br %r14
2583d1ef 271
07b3bb1e 272 .section .data..nosave,"aw",@progbits
2583d1ef 273 .align 8
1aaf179d
MH
274.Ldisabled_wait_31:
275 .long 0x000a0000,0x00000000
276.Lpanic_string:
02407baa 277 .asciz "Resume not possible because suspend CPU is no longer available\n"
1aaf179d
MH
278 .align 8
279.Lrestart_diag308_psw:
2583d1ef 280 .long 0x00080000,0x80000000
1aaf179d
MH
281.Lrestart_suspend_psw:
282 .quad 0x0000000180000000,restart_suspend
283.Lnew_pgm_check_psw:
2583d1ef 284 .quad 0,pgm_check_entry
1aaf179d
MH
285.Lresume_cpu:
286 .byte 0,0