]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - arch/s390/kernel/swsusp.S
License cleanup: add SPDX GPL-2.0 license identifier to files with no license
[mirror_ubuntu-bionic-kernel.git] / arch / s390 / kernel / swsusp.S
1 /* SPDX-License-Identifier: GPL-2.0 */
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
11 #include <linux/linkage.h>
12 #include <asm/page.h>
13 #include <asm/ptrace.h>
14 #include <asm/thread_info.h>
15 #include <asm/asm-offsets.h>
16 #include <asm/sigp.h>
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
28 ENTRY(swsusp_arch_suspend)
29 stmg %r6,%r15,__SF_GPRS(%r15)
30 lgr %r1,%r15
31 aghi %r15,-STACK_FRAME_OVERHEAD
32 stg %r1,__SF_BACKCHAIN(%r15)
33
34 /* Store FPU registers */
35 brasl %r14,save_fpu_regs
36
37 /* Deactivate DAT */
38 stnsm __SF_EMPTY(%r15),0xfb
39
40 /* Store prefix register on stack */
41 stpx __SF_EMPTY(%r15)
42
43 /* Save prefix register contents for lowcore copy */
44 llgf %r10,__SF_EMPTY(%r15)
45
46 /* Get pointer to save area */
47 lghi %r1,0x1000
48
49 /* Save CPU address */
50 stap __LC_EXT_CPU_ADDR(%r0)
51
52 /* Store registers */
53 mvc 0x318(4,%r1),__SF_EMPTY(%r15) /* move prefix to lowcore */
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 */
59 stck __SF_EMPTY(%r15) /* store clock */
60 stckc 0x330(%r1) /* store clock comparator */
61
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
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
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
87 1: mvcle %r2,%r4,0
88 jo 1b
89
90 /* Copy lowcore to absolute zero lowcore */
91 lghi %r2,0
92 lgr %r4,%r10
93 lghi %r3,2*PAGE_SIZE
94 lghi %r5,2*PAGE_SIZE
95 1: mvcle %r2,%r4,0
96 jo 1b
97
98 /* Save image */
99 brasl %r14,swsusp_save
100
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 */
113 ENTRY(swsusp_arch_resume)
114 stmg %r6,%r15,__SF_GPRS(%r15)
115 lgr %r1,%r15
116 aghi %r15,-STACK_FRAME_OVERHEAD
117 stg %r1,__SF_BACKCHAIN(%r15)
118
119 /* Make all free pages stable */
120 lghi %r2,1
121 brasl %r14,arch_set_page_states
122
123 /* Deactivate DAT */
124 stnsm __SF_EMPTY(%r15),0xfb
125
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
135 0:
136 lg %r2,8(%r1)
137 lg %r4,0(%r1)
138 iske %r0,%r4
139 lghi %r3,PAGE_SIZE
140 lghi %r5,PAGE_SIZE
141 1:
142 mvcle %r2,%r4,0
143 jo 1b
144 lg %r2,8(%r1)
145 sske %r0,%r2
146 lg %r1,16(%r1)
147 ltgr %r1,%r1
148 jnz 0b
149 2:
150 ptlb /* flush tlb */
151
152 /* Reset System */
153 larl %r1,restart_entry
154 larl %r2,.Lrestart_diag308_psw
155 og %r1,0(%r2)
156 stg %r1,0(%r0)
157 larl %r1,.Lnew_pgm_check_psw
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
163 restart_entry:
164 lhi %r1,1
165 sigp %r1,%r0,SIGP_SET_ARCHITECTURE
166 sam64
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
172 smt_loop:
173 sigp %r1,%r0,SIGP_SET_MULTI_THREADING
174 brc 8,smt_done /* accepted */
175 brc 2,smt_loop /* busy, try again */
176 smt_done:
177 #endif
178 larl %r1,.Lnew_pgm_check_psw
179 lpswe 0(%r1)
180 pgm_check_entry:
181
182 /* Switch to original suspend CPU */
183 larl %r1,.Lresume_cpu /* Resume CPU address: r2 */
184 stap 0(%r1)
185 llgh %r2,0(%r1)
186 llgh %r1,__LC_EXT_CPU_ADDR(%r0) /* Suspend CPU address: r1 */
187 cgr %r1,%r2
188 je restore_registers /* r1 = r2 -> nothing to do */
189 larl %r4,.Lrestart_suspend_psw /* Set new restart PSW */
190 mvc __LC_RST_NEW_PSW(16,%r0),0(%r4)
191 3:
192 sigp %r9,%r1,SIGP_INITIAL_CPU_RESET /* sigp initial cpu reset */
193 brc 8,4f /* accepted */
194 brc 2,3b /* busy, try again */
195
196 /* Suspend CPU not available -> panic */
197 larl %r15,init_thread_union
198 ahi %r15,1<<(PAGE_SHIFT+THREAD_SIZE_ORDER)
199 larl %r2,.Lpanic_string
200 larl %r3,sclp_early_printk
201 lghi %r1,0
202 sam31
203 sigp %r1,%r0,SIGP_SET_ARCHITECTURE
204 basr %r14,%r3
205 larl %r3,.Ldisabled_wait_31
206 lpsw 0(%r3)
207 4:
208 /* Switch to suspend CPU */
209 sigp %r9,%r1,SIGP_RESTART /* sigp restart to suspend CPU */
210 brc 2,4b /* busy, try again */
211 5:
212 sigp %r9,%r2,SIGP_STOP /* sigp stop to current resume CPU */
213 brc 2,5b /* busy, try again */
214 6: j 6b
215
216 restart_suspend:
217 larl %r1,.Lresume_cpu
218 llgh %r2,0(%r1)
219 7:
220 sigp %r9,%r2,SIGP_SENSE /* sigp sense, wait for resume CPU */
221 brc 8,7b /* accepted, status 0, still running */
222 brc 2,7b /* busy, try again */
223 tmll %r9,0x40 /* Test if resume CPU is stopped */
224 jz 7b
225
226 restore_registers:
227 /* Restore registers */
228 lghi %r13,0x1000 /* %r1 = pointer to save area */
229
230 /* Ignore time spent in suspended state. */
231 llgf %r1,0x318(%r13)
232 stck __LC_LAST_UPDATE_CLOCK(%r1)
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
239 /* Load old stack */
240 lg %r15,0x2f8(%r13)
241
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
251 1: mvcle %r2,%r4,0
252 jo 1b
253
254 /* Restore prefix register */
255 spx __SF_EMPTY(%r15)
256
257 /* Activate DAT */
258 stosm __SF_EMPTY(%r15),0x04
259
260 /* Make all free pages unstable */
261 lghi %r2,0
262 brasl %r14,arch_set_page_states
263
264 /* Call arch specific early resume code */
265 brasl %r14,s390_early_resume
266
267 /* Return 0 */
268 lmg %r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15)
269 lghi %r2,0
270 br %r14
271
272 .section .data..nosave,"aw",@progbits
273 .align 8
274 .Ldisabled_wait_31:
275 .long 0x000a0000,0x00000000
276 .Lpanic_string:
277 .asciz "Resume not possible because suspend CPU is no longer available\n"
278 .align 8
279 .Lrestart_diag308_psw:
280 .long 0x00080000,0x80000000
281 .Lrestart_suspend_psw:
282 .quad 0x0000000180000000,restart_suspend
283 .Lnew_pgm_check_psw:
284 .quad 0,pgm_check_entry
285 .Lresume_cpu:
286 .byte 0,0