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