diff options
Diffstat (limited to 'arch/s390/kernel/entry64.S')
-rw-r--r-- | arch/s390/kernel/entry64.S | 617 |
1 files changed, 297 insertions, 320 deletions
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 52106d53271..178d92536d9 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
@@ -2,7 +2,7 @@ | |||
2 | * arch/s390/kernel/entry64.S | 2 | * arch/s390/kernel/entry64.S |
3 | * S390 low-level entry points. | 3 | * S390 low-level entry points. |
4 | * | 4 | * |
5 | * Copyright (C) IBM Corp. 1999,2006 | 5 | * Copyright (C) IBM Corp. 1999,2010 |
6 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), | 6 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), |
7 | * Hartmut Penner (hp@de.ibm.com), | 7 | * Hartmut Penner (hp@de.ibm.com), |
8 | * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), | 8 | * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), |
@@ -59,30 +59,45 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \ | |||
59 | 59 | ||
60 | #define BASED(name) name-system_call(%r13) | 60 | #define BASED(name) name-system_call(%r13) |
61 | 61 | ||
62 | .macro HANDLE_SIE_INTERCEPT | ||
63 | #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) | ||
64 | lg %r3,__LC_SIE_HOOK | ||
65 | ltgr %r3,%r3 | ||
66 | jz 0f | ||
67 | basr %r14,%r3 | ||
68 | 0: | ||
69 | #endif | ||
70 | .endm | ||
71 | |||
62 | #ifdef CONFIG_TRACE_IRQFLAGS | 72 | #ifdef CONFIG_TRACE_IRQFLAGS |
63 | .macro TRACE_IRQS_ON | 73 | .macro TRACE_IRQS_ON |
64 | basr %r2,%r0 | 74 | basr %r2,%r0 |
65 | brasl %r14,trace_hardirqs_on_caller | 75 | brasl %r14,trace_hardirqs_on_caller |
66 | .endm | 76 | .endm |
67 | 77 | ||
68 | .macro TRACE_IRQS_OFF | 78 | .macro TRACE_IRQS_OFF |
69 | basr %r2,%r0 | 79 | basr %r2,%r0 |
70 | brasl %r14,trace_hardirqs_off_caller | 80 | brasl %r14,trace_hardirqs_off_caller |
71 | .endm | 81 | .endm |
72 | 82 | ||
73 | .macro TRACE_IRQS_CHECK | 83 | .macro TRACE_IRQS_CHECK_ON |
74 | basr %r2,%r0 | ||
75 | tm SP_PSW(%r15),0x03 # irqs enabled? | 84 | tm SP_PSW(%r15),0x03 # irqs enabled? |
76 | jz 0f | 85 | jz 0f |
77 | brasl %r14,trace_hardirqs_on_caller | 86 | TRACE_IRQS_ON |
78 | j 1f | 87 | 0: |
79 | 0: brasl %r14,trace_hardirqs_off_caller | 88 | .endm |
80 | 1: | 89 | |
90 | .macro TRACE_IRQS_CHECK_OFF | ||
91 | tm SP_PSW(%r15),0x03 # irqs enabled? | ||
92 | jz 0f | ||
93 | TRACE_IRQS_OFF | ||
94 | 0: | ||
81 | .endm | 95 | .endm |
82 | #else | 96 | #else |
83 | #define TRACE_IRQS_ON | 97 | #define TRACE_IRQS_ON |
84 | #define TRACE_IRQS_OFF | 98 | #define TRACE_IRQS_OFF |
85 | #define TRACE_IRQS_CHECK | 99 | #define TRACE_IRQS_CHECK_ON |
100 | #define TRACE_IRQS_CHECK_OFF | ||
86 | #endif | 101 | #endif |
87 | 102 | ||
88 | #ifdef CONFIG_LOCKDEP | 103 | #ifdef CONFIG_LOCKDEP |
@@ -111,31 +126,35 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \ | |||
111 | * R15 - kernel stack pointer | 126 | * R15 - kernel stack pointer |
112 | */ | 127 | */ |
113 | 128 | ||
114 | .macro SAVE_ALL_BASE savearea | ||
115 | stmg %r12,%r15,\savearea | ||
116 | larl %r13,system_call | ||
117 | .endm | ||
118 | |||
119 | .macro SAVE_ALL_SVC psworg,savearea | 129 | .macro SAVE_ALL_SVC psworg,savearea |
120 | la %r12,\psworg | 130 | stmg %r11,%r15,\savearea |
121 | lg %r15,__LC_KERNEL_STACK # problem state -> load ksp | 131 | lg %r15,__LC_KERNEL_STACK # problem state -> load ksp |
132 | aghi %r15,-SP_SIZE # make room for registers & psw | ||
133 | lg %r11,__LC_LAST_BREAK | ||
122 | .endm | 134 | .endm |
123 | 135 | ||
124 | .macro SAVE_ALL_SYNC psworg,savearea | 136 | .macro SAVE_ALL_PGM psworg,savearea |
125 | la %r12,\psworg | 137 | stmg %r11,%r15,\savearea |
126 | tm \psworg+1,0x01 # test problem state bit | 138 | tm \psworg+1,0x01 # test problem state bit |
127 | jz 2f # skip stack setup save | ||
128 | lg %r15,__LC_KERNEL_STACK # problem state -> load ksp | ||
129 | #ifdef CONFIG_CHECK_STACK | 139 | #ifdef CONFIG_CHECK_STACK |
130 | j 3f | 140 | jnz 1f |
131 | 2: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD | 141 | tml %r15,STACK_SIZE - CONFIG_STACK_GUARD |
132 | jz stack_overflow | 142 | jnz 2f |
133 | 3: | 143 | la %r12,\psworg |
144 | j stack_overflow | ||
145 | #else | ||
146 | jz 2f | ||
134 | #endif | 147 | #endif |
135 | 2: | 148 | 1: lg %r15,__LC_KERNEL_STACK # problem state -> load ksp |
149 | 2: aghi %r15,-SP_SIZE # make room for registers & psw | ||
150 | larl %r13,system_call | ||
151 | lg %r11,__LC_LAST_BREAK | ||
136 | .endm | 152 | .endm |
137 | 153 | ||
138 | .macro SAVE_ALL_ASYNC psworg,savearea | 154 | .macro SAVE_ALL_ASYNC psworg,savearea |
155 | stmg %r11,%r15,\savearea | ||
156 | larl %r13,system_call | ||
157 | lg %r11,__LC_LAST_BREAK | ||
139 | la %r12,\psworg | 158 | la %r12,\psworg |
140 | tm \psworg+1,0x01 # test problem state bit | 159 | tm \psworg+1,0x01 # test problem state bit |
141 | jnz 1f # from user -> load kernel stack | 160 | jnz 1f # from user -> load kernel stack |
@@ -149,27 +168,23 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \ | |||
149 | 0: lg %r14,__LC_ASYNC_STACK # are we already on the async. stack ? | 168 | 0: lg %r14,__LC_ASYNC_STACK # are we already on the async. stack ? |
150 | slgr %r14,%r15 | 169 | slgr %r14,%r15 |
151 | srag %r14,%r14,STACK_SHIFT | 170 | srag %r14,%r14,STACK_SHIFT |
152 | jz 2f | ||
153 | 1: lg %r15,__LC_ASYNC_STACK # load async stack | ||
154 | #ifdef CONFIG_CHECK_STACK | 171 | #ifdef CONFIG_CHECK_STACK |
155 | j 3f | 172 | jnz 1f |
156 | 2: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD | 173 | tml %r15,STACK_SIZE - CONFIG_STACK_GUARD |
157 | jz stack_overflow | 174 | jnz 2f |
158 | 3: | 175 | j stack_overflow |
176 | #else | ||
177 | jz 2f | ||
159 | #endif | 178 | #endif |
160 | 2: | 179 | 1: lg %r15,__LC_ASYNC_STACK # load async stack |
180 | 2: aghi %r15,-SP_SIZE # make room for registers & psw | ||
161 | .endm | 181 | .endm |
162 | 182 | ||
163 | .macro CREATE_STACK_FRAME psworg,savearea | 183 | .macro CREATE_STACK_FRAME savearea |
164 | aghi %r15,-SP_SIZE # make room for registers & psw | 184 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) |
165 | mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack | ||
166 | stg %r2,SP_ORIG_R2(%r15) # store original content of gpr 2 | 185 | stg %r2,SP_ORIG_R2(%r15) # store original content of gpr 2 |
167 | icm %r12,3,__LC_SVC_ILC | 186 | mvc SP_R11(40,%r15),\savearea # move %r11-%r15 to stack |
168 | stmg %r0,%r11,SP_R0(%r15) # store gprs %r0-%r11 to kernel stack | 187 | stmg %r0,%r10,SP_R0(%r15) # store gprs %r0-%r10 to kernel stack |
169 | st %r12,SP_SVCNR(%r15) | ||
170 | mvc SP_R12(32,%r15),\savearea # move %r12-%r15 to stack | ||
171 | la %r12,0 | ||
172 | stg %r12,__SF_BACKCHAIN(%r15) | ||
173 | .endm | 188 | .endm |
174 | 189 | ||
175 | .macro RESTORE_ALL psworg,sync | 190 | .macro RESTORE_ALL psworg,sync |
@@ -185,6 +200,13 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \ | |||
185 | lpswe \psworg # back to caller | 200 | lpswe \psworg # back to caller |
186 | .endm | 201 | .endm |
187 | 202 | ||
203 | .macro LAST_BREAK | ||
204 | srag %r10,%r11,23 | ||
205 | jz 0f | ||
206 | stg %r11,__TI_last_break(%r12) | ||
207 | 0: | ||
208 | .endm | ||
209 | |||
188 | /* | 210 | /* |
189 | * Scheduler resume function, called by switch_to | 211 | * Scheduler resume function, called by switch_to |
190 | * gpr2 = (task_struct *) prev | 212 | * gpr2 = (task_struct *) prev |
@@ -230,143 +252,129 @@ __critical_start: | |||
230 | system_call: | 252 | system_call: |
231 | stpt __LC_SYNC_ENTER_TIMER | 253 | stpt __LC_SYNC_ENTER_TIMER |
232 | sysc_saveall: | 254 | sysc_saveall: |
233 | SAVE_ALL_BASE __LC_SAVE_AREA | ||
234 | SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 255 | SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA |
235 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 256 | CREATE_STACK_FRAME __LC_SAVE_AREA |
236 | llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore | 257 | mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW |
258 | mvc SP_ILC(4,%r15),__LC_SVC_ILC | ||
259 | stg %r7,SP_ARGS(%r15) | ||
260 | lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct | ||
237 | sysc_vtime: | 261 | sysc_vtime: |
238 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER | 262 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER |
239 | sysc_stime: | 263 | sysc_stime: |
240 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | 264 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER |
241 | sysc_update: | 265 | sysc_update: |
242 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER | 266 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER |
267 | LAST_BREAK | ||
243 | sysc_do_svc: | 268 | sysc_do_svc: |
244 | lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct | 269 | llgh %r7,SP_SVCNR(%r15) |
245 | ltgr %r7,%r7 # test for svc 0 | 270 | slag %r7,%r7,2 # shift and test for svc 0 |
246 | jnz sysc_nr_ok | 271 | jnz sysc_nr_ok |
247 | # svc 0: system call number in %r1 | 272 | # svc 0: system call number in %r1 |
248 | cl %r1,BASED(.Lnr_syscalls) | 273 | llgfr %r1,%r1 # clear high word in r1 |
274 | cghi %r1,NR_syscalls | ||
249 | jnl sysc_nr_ok | 275 | jnl sysc_nr_ok |
250 | lgfr %r7,%r1 # clear high word in r1 | 276 | sth %r1,SP_SVCNR(%r15) |
277 | slag %r7,%r1,2 # shift and test for svc 0 | ||
251 | sysc_nr_ok: | 278 | sysc_nr_ok: |
252 | mvc SP_ARGS(8,%r15),SP_R7(%r15) | ||
253 | sysc_do_restart: | ||
254 | sth %r7,SP_SVCNR(%r15) | ||
255 | sllg %r7,%r7,2 # svc number * 4 | ||
256 | larl %r10,sys_call_table | 279 | larl %r10,sys_call_table |
257 | #ifdef CONFIG_COMPAT | 280 | #ifdef CONFIG_COMPAT |
258 | tm __TI_flags+5(%r9),(_TIF_31BIT>>16) # running in 31 bit mode ? | 281 | tm __TI_flags+5(%r12),(_TIF_31BIT>>16) # running in 31 bit mode ? |
259 | jno sysc_noemu | 282 | jno sysc_noemu |
260 | larl %r10,sys_call_table_emu # use 31 bit emulation system calls | 283 | larl %r10,sys_call_table_emu # use 31 bit emulation system calls |
261 | sysc_noemu: | 284 | sysc_noemu: |
262 | #endif | 285 | #endif |
263 | tm __TI_flags+6(%r9),_TIF_SYSCALL | 286 | tm __TI_flags+6(%r12),_TIF_SYSCALL |
264 | lgf %r8,0(%r7,%r10) # load address of system call routine | 287 | lgf %r8,0(%r7,%r10) # load address of system call routine |
265 | jnz sysc_tracesys | 288 | jnz sysc_tracesys |
266 | basr %r14,%r8 # call sys_xxxx | 289 | basr %r14,%r8 # call sys_xxxx |
267 | stg %r2,SP_R2(%r15) # store return value (change R2 on stack) | 290 | stg %r2,SP_R2(%r15) # store return value (change R2 on stack) |
268 | 291 | ||
269 | sysc_return: | 292 | sysc_return: |
270 | tm __TI_flags+7(%r9),_TIF_WORK_SVC | 293 | LOCKDEP_SYS_EXIT |
294 | sysc_tif: | ||
295 | tm __TI_flags+7(%r12),_TIF_WORK_SVC | ||
271 | jnz sysc_work # there is work to do (signals etc.) | 296 | jnz sysc_work # there is work to do (signals etc.) |
272 | sysc_restore: | 297 | sysc_restore: |
273 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
274 | larl %r1,sysc_restore_trace_psw | ||
275 | lpswe 0(%r1) | ||
276 | sysc_restore_trace: | ||
277 | TRACE_IRQS_CHECK | ||
278 | LOCKDEP_SYS_EXIT | ||
279 | #endif | ||
280 | sysc_leave: | ||
281 | RESTORE_ALL __LC_RETURN_PSW,1 | 298 | RESTORE_ALL __LC_RETURN_PSW,1 |
282 | sysc_done: | 299 | sysc_done: |
283 | 300 | ||
284 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
285 | .section .data,"aw",@progbits | ||
286 | .align 8 | ||
287 | .globl sysc_restore_trace_psw | ||
288 | sysc_restore_trace_psw: | ||
289 | .quad 0, sysc_restore_trace | ||
290 | .previous | ||
291 | #endif | ||
292 | |||
293 | # | ||
294 | # recheck if there is more work to do | ||
295 | # | 301 | # |
296 | sysc_work_loop: | 302 | # There is work to do, but first we need to check if we return to userspace. |
297 | tm __TI_flags+7(%r9),_TIF_WORK_SVC | ||
298 | jz sysc_restore # there is no work to do | ||
299 | # | ||
300 | # One of the work bits is on. Find out which one. | ||
301 | # | 303 | # |
302 | sysc_work: | 304 | sysc_work: |
303 | tm SP_PSW+1(%r15),0x01 # returning to user ? | 305 | tm SP_PSW+1(%r15),0x01 # returning to user ? |
304 | jno sysc_restore | 306 | jno sysc_restore |
305 | tm __TI_flags+7(%r9),_TIF_MCCK_PENDING | 307 | |
308 | # | ||
309 | # One of the work bits is on. Find out which one. | ||
310 | # | ||
311 | sysc_work_tif: | ||
312 | tm __TI_flags+7(%r12),_TIF_MCCK_PENDING | ||
306 | jo sysc_mcck_pending | 313 | jo sysc_mcck_pending |
307 | tm __TI_flags+7(%r9),_TIF_NEED_RESCHED | 314 | tm __TI_flags+7(%r12),_TIF_NEED_RESCHED |
308 | jo sysc_reschedule | 315 | jo sysc_reschedule |
309 | tm __TI_flags+7(%r9),_TIF_SIGPENDING | 316 | tm __TI_flags+7(%r12),_TIF_SIGPENDING |
310 | jnz sysc_sigpending | 317 | jo sysc_sigpending |
311 | tm __TI_flags+7(%r9),_TIF_NOTIFY_RESUME | 318 | tm __TI_flags+7(%r12),_TIF_NOTIFY_RESUME |
312 | jnz sysc_notify_resume | 319 | jo sysc_notify_resume |
313 | tm __TI_flags+7(%r9),_TIF_RESTART_SVC | 320 | tm __TI_flags+7(%r12),_TIF_RESTART_SVC |
314 | jo sysc_restart | 321 | jo sysc_restart |
315 | tm __TI_flags+7(%r9),_TIF_SINGLE_STEP | 322 | tm __TI_flags+7(%r12),_TIF_SINGLE_STEP |
316 | jo sysc_singlestep | 323 | jo sysc_singlestep |
317 | j sysc_restore | 324 | j sysc_return # beware of critical section cleanup |
318 | sysc_work_done: | ||
319 | 325 | ||
320 | # | 326 | # |
321 | # _TIF_NEED_RESCHED is set, call schedule | 327 | # _TIF_NEED_RESCHED is set, call schedule |
322 | # | 328 | # |
323 | sysc_reschedule: | 329 | sysc_reschedule: |
324 | larl %r14,sysc_work_loop | 330 | larl %r14,sysc_return |
325 | jg schedule # return point is sysc_return | 331 | jg schedule # return point is sysc_return |
326 | 332 | ||
327 | # | 333 | # |
328 | # _TIF_MCCK_PENDING is set, call handler | 334 | # _TIF_MCCK_PENDING is set, call handler |
329 | # | 335 | # |
330 | sysc_mcck_pending: | 336 | sysc_mcck_pending: |
331 | larl %r14,sysc_work_loop | 337 | larl %r14,sysc_return |
332 | jg s390_handle_mcck # TIF bit will be cleared by handler | 338 | jg s390_handle_mcck # TIF bit will be cleared by handler |
333 | 339 | ||
334 | # | 340 | # |
335 | # _TIF_SIGPENDING is set, call do_signal | 341 | # _TIF_SIGPENDING is set, call do_signal |
336 | # | 342 | # |
337 | sysc_sigpending: | 343 | sysc_sigpending: |
338 | ni __TI_flags+7(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP | 344 | ni __TI_flags+7(%r12),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP |
339 | la %r2,SP_PTREGS(%r15) # load pt_regs | 345 | la %r2,SP_PTREGS(%r15) # load pt_regs |
340 | brasl %r14,do_signal # call do_signal | 346 | brasl %r14,do_signal # call do_signal |
341 | tm __TI_flags+7(%r9),_TIF_RESTART_SVC | 347 | tm __TI_flags+7(%r12),_TIF_RESTART_SVC |
342 | jo sysc_restart | 348 | jo sysc_restart |
343 | tm __TI_flags+7(%r9),_TIF_SINGLE_STEP | 349 | tm __TI_flags+7(%r12),_TIF_SINGLE_STEP |
344 | jo sysc_singlestep | 350 | jo sysc_singlestep |
345 | j sysc_work_loop | 351 | j sysc_return |
346 | 352 | ||
347 | # | 353 | # |
348 | # _TIF_NOTIFY_RESUME is set, call do_notify_resume | 354 | # _TIF_NOTIFY_RESUME is set, call do_notify_resume |
349 | # | 355 | # |
350 | sysc_notify_resume: | 356 | sysc_notify_resume: |
351 | la %r2,SP_PTREGS(%r15) # load pt_regs | 357 | la %r2,SP_PTREGS(%r15) # load pt_regs |
352 | larl %r14,sysc_work_loop | 358 | larl %r14,sysc_return |
353 | jg do_notify_resume # call do_notify_resume | 359 | jg do_notify_resume # call do_notify_resume |
354 | 360 | ||
355 | # | 361 | # |
356 | # _TIF_RESTART_SVC is set, set up registers and restart svc | 362 | # _TIF_RESTART_SVC is set, set up registers and restart svc |
357 | # | 363 | # |
358 | sysc_restart: | 364 | sysc_restart: |
359 | ni __TI_flags+7(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC | 365 | ni __TI_flags+7(%r12),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC |
360 | lg %r7,SP_R2(%r15) # load new svc number | 366 | lg %r7,SP_R2(%r15) # load new svc number |
361 | mvc SP_R2(8,%r15),SP_ORIG_R2(%r15) # restore first argument | 367 | mvc SP_R2(8,%r15),SP_ORIG_R2(%r15) # restore first argument |
362 | lmg %r2,%r6,SP_R2(%r15) # load svc arguments | 368 | lmg %r2,%r6,SP_R2(%r15) # load svc arguments |
363 | j sysc_do_restart # restart svc | 369 | sth %r7,SP_SVCNR(%r15) |
370 | slag %r7,%r7,2 | ||
371 | j sysc_nr_ok # restart svc | ||
364 | 372 | ||
365 | # | 373 | # |
366 | # _TIF_SINGLE_STEP is set, call do_single_step | 374 | # _TIF_SINGLE_STEP is set, call do_single_step |
367 | # | 375 | # |
368 | sysc_singlestep: | 376 | sysc_singlestep: |
369 | ni __TI_flags+7(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP | 377 | ni __TI_flags+7(%r12),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP |
370 | xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number | 378 | xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number |
371 | la %r2,SP_PTREGS(%r15) # address of register-save area | 379 | la %r2,SP_PTREGS(%r15) # address of register-save area |
372 | larl %r14,sysc_return # load adr. of system return | 380 | larl %r14,sysc_return # load adr. of system return |
@@ -379,8 +387,8 @@ sysc_singlestep: | |||
379 | sysc_tracesys: | 387 | sysc_tracesys: |
380 | la %r2,SP_PTREGS(%r15) # load pt_regs | 388 | la %r2,SP_PTREGS(%r15) # load pt_regs |
381 | la %r3,0 | 389 | la %r3,0 |
382 | srl %r7,2 | 390 | llgh %r0,SP_SVCNR(%r15) |
383 | stg %r7,SP_R2(%r15) | 391 | stg %r0,SP_R2(%r15) |
384 | brasl %r14,do_syscall_trace_enter | 392 | brasl %r14,do_syscall_trace_enter |
385 | lghi %r0,NR_syscalls | 393 | lghi %r0,NR_syscalls |
386 | clgr %r0,%r2 | 394 | clgr %r0,%r2 |
@@ -393,7 +401,7 @@ sysc_tracego: | |||
393 | basr %r14,%r8 # call sys_xxx | 401 | basr %r14,%r8 # call sys_xxx |
394 | stg %r2,SP_R2(%r15) # store return value | 402 | stg %r2,SP_R2(%r15) # store return value |
395 | sysc_tracenogo: | 403 | sysc_tracenogo: |
396 | tm __TI_flags+6(%r9),_TIF_SYSCALL | 404 | tm __TI_flags+6(%r12),_TIF_SYSCALL |
397 | jz sysc_return | 405 | jz sysc_return |
398 | la %r2,SP_PTREGS(%r15) # load pt_regs | 406 | la %r2,SP_PTREGS(%r15) # load pt_regs |
399 | larl %r14,sysc_return # return point is sysc_return | 407 | larl %r14,sysc_return # return point is sysc_return |
@@ -405,7 +413,7 @@ sysc_tracenogo: | |||
405 | .globl ret_from_fork | 413 | .globl ret_from_fork |
406 | ret_from_fork: | 414 | ret_from_fork: |
407 | lg %r13,__LC_SVC_NEW_PSW+8 | 415 | lg %r13,__LC_SVC_NEW_PSW+8 |
408 | lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct | 416 | lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct |
409 | tm SP_PSW+1(%r15),0x01 # forking a kernel thread ? | 417 | tm SP_PSW+1(%r15),0x01 # forking a kernel thread ? |
410 | jo 0f | 418 | jo 0f |
411 | stg %r15,SP_R15(%r15) # store stack pointer for new kthread | 419 | stg %r15,SP_R15(%r15) # store stack pointer for new kthread |
@@ -435,12 +443,14 @@ kernel_execve: | |||
435 | br %r14 | 443 | br %r14 |
436 | # execve succeeded. | 444 | # execve succeeded. |
437 | 0: stnsm __SF_EMPTY(%r15),0xfc # disable interrupts | 445 | 0: stnsm __SF_EMPTY(%r15),0xfc # disable interrupts |
446 | # TRACE_IRQS_OFF | ||
438 | lg %r15,__LC_KERNEL_STACK # load ksp | 447 | lg %r15,__LC_KERNEL_STACK # load ksp |
439 | aghi %r15,-SP_SIZE # make room for registers & psw | 448 | aghi %r15,-SP_SIZE # make room for registers & psw |
440 | lg %r13,__LC_SVC_NEW_PSW+8 | 449 | lg %r13,__LC_SVC_NEW_PSW+8 |
441 | lg %r9,__LC_THREAD_INFO | ||
442 | mvc SP_PTREGS(__PT_SIZE,%r15),0(%r12) # copy pt_regs | 450 | mvc SP_PTREGS(__PT_SIZE,%r15),0(%r12) # copy pt_regs |
451 | lg %r12,__LC_THREAD_INFO | ||
443 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) | 452 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) |
453 | # TRACE_IRQS_ON | ||
444 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts | 454 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts |
445 | brasl %r14,execve_tail | 455 | brasl %r14,execve_tail |
446 | j sysc_return | 456 | j sysc_return |
@@ -465,20 +475,23 @@ pgm_check_handler: | |||
465 | * for LPSW?). | 475 | * for LPSW?). |
466 | */ | 476 | */ |
467 | stpt __LC_SYNC_ENTER_TIMER | 477 | stpt __LC_SYNC_ENTER_TIMER |
468 | SAVE_ALL_BASE __LC_SAVE_AREA | ||
469 | tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception | 478 | tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception |
470 | jnz pgm_per # got per exception -> special case | 479 | jnz pgm_per # got per exception -> special case |
471 | SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA | 480 | SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA |
472 | CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA | 481 | CREATE_STACK_FRAME __LC_SAVE_AREA |
482 | xc SP_ILC(4,%r15),SP_ILC(%r15) | ||
483 | mvc SP_PSW(16,%r15),__LC_PGM_OLD_PSW | ||
484 | lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct | ||
473 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 485 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
474 | jz pgm_no_vtime | 486 | jz pgm_no_vtime |
475 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER | 487 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER |
476 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | 488 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER |
477 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER | 489 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER |
490 | LAST_BREAK | ||
478 | pgm_no_vtime: | 491 | pgm_no_vtime: |
479 | lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct | 492 | HANDLE_SIE_INTERCEPT |
480 | mvc SP_ARGS(8,%r15),__LC_LAST_BREAK | 493 | TRACE_IRQS_CHECK_OFF |
481 | TRACE_IRQS_OFF | 494 | stg %r11,SP_ARGS(%r15) |
482 | lgf %r3,__LC_PGM_ILC # load program interruption code | 495 | lgf %r3,__LC_PGM_ILC # load program interruption code |
483 | lghi %r8,0x7f | 496 | lghi %r8,0x7f |
484 | ngr %r8,%r3 | 497 | ngr %r8,%r3 |
@@ -487,8 +500,10 @@ pgm_do_call: | |||
487 | larl %r1,pgm_check_table | 500 | larl %r1,pgm_check_table |
488 | lg %r1,0(%r8,%r1) # load address of handler routine | 501 | lg %r1,0(%r8,%r1) # load address of handler routine |
489 | la %r2,SP_PTREGS(%r15) # address of register-save area | 502 | la %r2,SP_PTREGS(%r15) # address of register-save area |
490 | larl %r14,sysc_return | 503 | basr %r14,%r1 # branch to interrupt-handler |
491 | br %r1 # branch to interrupt-handler | 504 | pgm_exit: |
505 | TRACE_IRQS_CHECK_ON | ||
506 | j sysc_return | ||
492 | 507 | ||
493 | # | 508 | # |
494 | # handle per exception | 509 | # handle per exception |
@@ -500,55 +515,60 @@ pgm_per: | |||
500 | clc __LC_PGM_OLD_PSW(16),__LC_SVC_NEW_PSW | 515 | clc __LC_PGM_OLD_PSW(16),__LC_SVC_NEW_PSW |
501 | je pgm_svcper | 516 | je pgm_svcper |
502 | # no interesting special case, ignore PER event | 517 | # no interesting special case, ignore PER event |
503 | lmg %r12,%r15,__LC_SAVE_AREA | ||
504 | lpswe __LC_PGM_OLD_PSW | 518 | lpswe __LC_PGM_OLD_PSW |
505 | 519 | ||
506 | # | 520 | # |
507 | # Normal per exception | 521 | # Normal per exception |
508 | # | 522 | # |
509 | pgm_per_std: | 523 | pgm_per_std: |
510 | SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA | 524 | SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA |
511 | CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA | 525 | CREATE_STACK_FRAME __LC_SAVE_AREA |
526 | mvc SP_PSW(16,%r15),__LC_PGM_OLD_PSW | ||
527 | lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct | ||
512 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 528 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
513 | jz pgm_no_vtime2 | 529 | jz pgm_no_vtime2 |
514 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER | 530 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER |
515 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | 531 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER |
516 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER | 532 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER |
533 | LAST_BREAK | ||
517 | pgm_no_vtime2: | 534 | pgm_no_vtime2: |
518 | lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct | 535 | HANDLE_SIE_INTERCEPT |
519 | TRACE_IRQS_OFF | 536 | TRACE_IRQS_CHECK_OFF |
520 | lg %r1,__TI_task(%r9) | 537 | lg %r1,__TI_task(%r12) |
521 | tm SP_PSW+1(%r15),0x01 # kernel per event ? | 538 | tm SP_PSW+1(%r15),0x01 # kernel per event ? |
522 | jz kernel_per | 539 | jz kernel_per |
523 | mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID | 540 | mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID |
524 | mvc __THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS | 541 | mvc __THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS |
525 | mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID | 542 | mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID |
526 | oi __TI_flags+7(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP | 543 | oi __TI_flags+7(%r12),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP |
527 | lgf %r3,__LC_PGM_ILC # load program interruption code | 544 | lgf %r3,__LC_PGM_ILC # load program interruption code |
528 | lghi %r8,0x7f | 545 | lghi %r8,0x7f |
529 | ngr %r8,%r3 # clear per-event-bit and ilc | 546 | ngr %r8,%r3 # clear per-event-bit and ilc |
530 | je sysc_return | 547 | je pgm_exit |
531 | j pgm_do_call | 548 | j pgm_do_call |
532 | 549 | ||
533 | # | 550 | # |
534 | # it was a single stepped SVC that is causing all the trouble | 551 | # it was a single stepped SVC that is causing all the trouble |
535 | # | 552 | # |
536 | pgm_svcper: | 553 | pgm_svcper: |
537 | SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 554 | SAVE_ALL_PGM __LC_SVC_OLD_PSW,__LC_SAVE_AREA |
538 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 555 | CREATE_STACK_FRAME __LC_SAVE_AREA |
556 | mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW | ||
557 | mvc SP_ILC(4,%r15),__LC_SVC_ILC | ||
558 | lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct | ||
539 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER | 559 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER |
540 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | 560 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER |
541 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER | 561 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER |
542 | llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore | 562 | LAST_BREAK |
543 | lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct | 563 | TRACE_IRQS_OFF |
544 | lg %r8,__TI_task(%r9) | 564 | lg %r8,__TI_task(%r12) |
545 | mvc __THREAD_per+__PER_atmid(2,%r8),__LC_PER_ATMID | 565 | mvc __THREAD_per+__PER_atmid(2,%r8),__LC_PER_ATMID |
546 | mvc __THREAD_per+__PER_address(8,%r8),__LC_PER_ADDRESS | 566 | mvc __THREAD_per+__PER_address(8,%r8),__LC_PER_ADDRESS |
547 | mvc __THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID | 567 | mvc __THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID |
548 | oi __TI_flags+7(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP | 568 | oi __TI_flags+7(%r12),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP |
549 | TRACE_IRQS_ON | 569 | TRACE_IRQS_ON |
550 | lmg %r2,%r6,SP_R2(%r15) # load svc arguments | ||
551 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts | 570 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts |
571 | lmg %r2,%r6,SP_R2(%r15) # load svc arguments | ||
552 | j sysc_do_svc | 572 | j sysc_do_svc |
553 | 573 | ||
554 | # | 574 | # |
@@ -557,8 +577,8 @@ pgm_svcper: | |||
557 | kernel_per: | 577 | kernel_per: |
558 | xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number | 578 | xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number |
559 | la %r2,SP_PTREGS(%r15) # address of register-save area | 579 | la %r2,SP_PTREGS(%r15) # address of register-save area |
560 | larl %r14,sysc_restore # load adr. of system ret, no work | 580 | brasl %r14,do_single_step |
561 | jg do_single_step # branch to do_single_step | 581 | j pgm_exit |
562 | 582 | ||
563 | /* | 583 | /* |
564 | * IO interrupt handler routine | 584 | * IO interrupt handler routine |
@@ -567,162 +587,133 @@ kernel_per: | |||
567 | io_int_handler: | 587 | io_int_handler: |
568 | stck __LC_INT_CLOCK | 588 | stck __LC_INT_CLOCK |
569 | stpt __LC_ASYNC_ENTER_TIMER | 589 | stpt __LC_ASYNC_ENTER_TIMER |
570 | SAVE_ALL_BASE __LC_SAVE_AREA+32 | 590 | SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+40 |
571 | SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+32 | 591 | CREATE_STACK_FRAME __LC_SAVE_AREA+40 |
572 | CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+32 | 592 | mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack |
593 | lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct | ||
573 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 594 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
574 | jz io_no_vtime | 595 | jz io_no_vtime |
575 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER | 596 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER |
576 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | 597 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER |
577 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER | 598 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER |
599 | LAST_BREAK | ||
578 | io_no_vtime: | 600 | io_no_vtime: |
579 | lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct | 601 | HANDLE_SIE_INTERCEPT |
580 | TRACE_IRQS_OFF | 602 | TRACE_IRQS_OFF |
581 | la %r2,SP_PTREGS(%r15) # address of register-save area | 603 | la %r2,SP_PTREGS(%r15) # address of register-save area |
582 | brasl %r14,do_IRQ # call standard irq handler | 604 | brasl %r14,do_IRQ # call standard irq handler |
583 | io_return: | 605 | io_return: |
584 | tm __TI_flags+7(%r9),_TIF_WORK_INT | 606 | LOCKDEP_SYS_EXIT |
607 | TRACE_IRQS_ON | ||
608 | io_tif: | ||
609 | tm __TI_flags+7(%r12),_TIF_WORK_INT | ||
585 | jnz io_work # there is work to do (signals etc.) | 610 | jnz io_work # there is work to do (signals etc.) |
586 | io_restore: | 611 | io_restore: |
587 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
588 | larl %r1,io_restore_trace_psw | ||
589 | lpswe 0(%r1) | ||
590 | io_restore_trace: | ||
591 | TRACE_IRQS_CHECK | ||
592 | LOCKDEP_SYS_EXIT | ||
593 | #endif | ||
594 | io_leave: | ||
595 | RESTORE_ALL __LC_RETURN_PSW,0 | 612 | RESTORE_ALL __LC_RETURN_PSW,0 |
596 | io_done: | 613 | io_done: |
597 | 614 | ||
598 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
599 | .section .data,"aw",@progbits | ||
600 | .align 8 | ||
601 | .globl io_restore_trace_psw | ||
602 | io_restore_trace_psw: | ||
603 | .quad 0, io_restore_trace | ||
604 | .previous | ||
605 | #endif | ||
606 | |||
607 | # | 615 | # |
608 | # There is work todo, we need to check if we return to userspace, then | 616 | # There is work todo, find out in which context we have been interrupted: |
609 | # check, if we are in SIE, if yes leave it | 617 | # 1) if we return to user space we can do all _TIF_WORK_INT work |
618 | # 2) if we return to kernel code and kvm is enabled check if we need to | ||
619 | # modify the psw to leave SIE | ||
620 | # 3) if we return to kernel code and preemptive scheduling is enabled check | ||
621 | # the preemption counter and if it is zero call preempt_schedule_irq | ||
622 | # Before any work can be done, a switch to the kernel stack is required. | ||
610 | # | 623 | # |
611 | io_work: | 624 | io_work: |
612 | tm SP_PSW+1(%r15),0x01 # returning to user ? | 625 | tm SP_PSW+1(%r15),0x01 # returning to user ? |
613 | #ifndef CONFIG_PREEMPT | 626 | jo io_work_user # yes -> do resched & signal |
614 | #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) | 627 | #ifdef CONFIG_PREEMPT |
615 | jnz io_work_user # yes -> no need to check for SIE | ||
616 | la %r1, BASED(sie_opcode) # we return to kernel here | ||
617 | lg %r2, SP_PSW+8(%r15) | ||
618 | clc 0(2,%r1), 0(%r2) # is current instruction = SIE? | ||
619 | jne io_restore # no-> return to kernel | ||
620 | lg %r1, SP_PSW+8(%r15) # yes-> add 4 bytes to leave SIE | ||
621 | aghi %r1, 4 | ||
622 | stg %r1, SP_PSW+8(%r15) | ||
623 | j io_restore # return to kernel | ||
624 | #else | ||
625 | jno io_restore # no-> skip resched & signal | ||
626 | #endif | ||
627 | #else | ||
628 | jnz io_work_user # yes -> do resched & signal | ||
629 | #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) | ||
630 | la %r1, BASED(sie_opcode) | ||
631 | lg %r2, SP_PSW+8(%r15) | ||
632 | clc 0(2,%r1), 0(%r2) # is current instruction = SIE? | ||
633 | jne 0f # no -> leave PSW alone | ||
634 | lg %r1, SP_PSW+8(%r15) # yes-> add 4 bytes to leave SIE | ||
635 | aghi %r1, 4 | ||
636 | stg %r1, SP_PSW+8(%r15) | ||
637 | 0: | ||
638 | #endif | ||
639 | # check for preemptive scheduling | 628 | # check for preemptive scheduling |
640 | icm %r0,15,__TI_precount(%r9) | 629 | icm %r0,15,__TI_precount(%r12) |
641 | jnz io_restore # preemption is disabled | 630 | jnz io_restore # preemption is disabled |
631 | tm __TI_flags+7(%r12),_TIF_NEED_RESCHED | ||
632 | jno io_restore | ||
642 | # switch to kernel stack | 633 | # switch to kernel stack |
643 | lg %r1,SP_R15(%r15) | 634 | lg %r1,SP_R15(%r15) |
644 | aghi %r1,-SP_SIZE | 635 | aghi %r1,-SP_SIZE |
645 | mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) | 636 | mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) |
646 | xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain | 637 | xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain |
647 | lgr %r15,%r1 | 638 | lgr %r15,%r1 |
648 | io_resume_loop: | 639 | # TRACE_IRQS_ON already done at io_return, call |
649 | tm __TI_flags+7(%r9),_TIF_NEED_RESCHED | 640 | # TRACE_IRQS_OFF to keep things symmetrical |
650 | jno io_restore | 641 | TRACE_IRQS_OFF |
651 | larl %r14,io_resume_loop | 642 | brasl %r14,preempt_schedule_irq |
652 | jg preempt_schedule_irq | 643 | j io_return |
644 | #else | ||
645 | j io_restore | ||
653 | #endif | 646 | #endif |
654 | 647 | ||
648 | # | ||
649 | # Need to do work before returning to userspace, switch to kernel stack | ||
650 | # | ||
655 | io_work_user: | 651 | io_work_user: |
656 | lg %r1,__LC_KERNEL_STACK | 652 | lg %r1,__LC_KERNEL_STACK |
657 | aghi %r1,-SP_SIZE | 653 | aghi %r1,-SP_SIZE |
658 | mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) | 654 | mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) |
659 | xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain | 655 | xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain |
660 | lgr %r15,%r1 | 656 | lgr %r15,%r1 |
657 | |||
661 | # | 658 | # |
662 | # One of the work bits is on. Find out which one. | 659 | # One of the work bits is on. Find out which one. |
663 | # Checked are: _TIF_SIGPENDING, _TIF_RESTORE_SIGPENDING, _TIF_NEED_RESCHED | 660 | # Checked are: _TIF_SIGPENDING, _TIF_NOTIFY_RESUME, _TIF_NEED_RESCHED |
664 | # and _TIF_MCCK_PENDING | 661 | # and _TIF_MCCK_PENDING |
665 | # | 662 | # |
666 | io_work_loop: | 663 | io_work_tif: |
667 | tm __TI_flags+7(%r9),_TIF_MCCK_PENDING | 664 | tm __TI_flags+7(%r12),_TIF_MCCK_PENDING |
668 | jo io_mcck_pending | 665 | jo io_mcck_pending |
669 | tm __TI_flags+7(%r9),_TIF_NEED_RESCHED | 666 | tm __TI_flags+7(%r12),_TIF_NEED_RESCHED |
670 | jo io_reschedule | 667 | jo io_reschedule |
671 | tm __TI_flags+7(%r9),_TIF_SIGPENDING | 668 | tm __TI_flags+7(%r12),_TIF_SIGPENDING |
672 | jnz io_sigpending | 669 | jo io_sigpending |
673 | tm __TI_flags+7(%r9),_TIF_NOTIFY_RESUME | 670 | tm __TI_flags+7(%r12),_TIF_NOTIFY_RESUME |
674 | jnz io_notify_resume | 671 | jo io_notify_resume |
675 | j io_restore | 672 | j io_return # beware of critical section cleanup |
676 | io_work_done: | ||
677 | |||
678 | #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) | ||
679 | sie_opcode: | ||
680 | .long 0xb2140000 | ||
681 | #endif | ||
682 | 673 | ||
683 | # | 674 | # |
684 | # _TIF_MCCK_PENDING is set, call handler | 675 | # _TIF_MCCK_PENDING is set, call handler |
685 | # | 676 | # |
686 | io_mcck_pending: | 677 | io_mcck_pending: |
678 | # TRACE_IRQS_ON already done at io_return | ||
687 | brasl %r14,s390_handle_mcck # TIF bit will be cleared by handler | 679 | brasl %r14,s390_handle_mcck # TIF bit will be cleared by handler |
688 | j io_work_loop | 680 | TRACE_IRQS_OFF |
681 | j io_return | ||
689 | 682 | ||
690 | # | 683 | # |
691 | # _TIF_NEED_RESCHED is set, call schedule | 684 | # _TIF_NEED_RESCHED is set, call schedule |
692 | # | 685 | # |
693 | io_reschedule: | 686 | io_reschedule: |
694 | TRACE_IRQS_ON | 687 | # TRACE_IRQS_ON already done at io_return |
695 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts | 688 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts |
696 | brasl %r14,schedule # call scheduler | 689 | brasl %r14,schedule # call scheduler |
697 | stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts | 690 | stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts |
698 | TRACE_IRQS_OFF | 691 | TRACE_IRQS_OFF |
699 | tm __TI_flags+7(%r9),_TIF_WORK_INT | 692 | j io_return |
700 | jz io_restore # there is no work to do | ||
701 | j io_work_loop | ||
702 | 693 | ||
703 | # | 694 | # |
704 | # _TIF_SIGPENDING or is set, call do_signal | 695 | # _TIF_SIGPENDING or is set, call do_signal |
705 | # | 696 | # |
706 | io_sigpending: | 697 | io_sigpending: |
707 | TRACE_IRQS_ON | 698 | # TRACE_IRQS_ON already done at io_return |
708 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts | 699 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts |
709 | la %r2,SP_PTREGS(%r15) # load pt_regs | 700 | la %r2,SP_PTREGS(%r15) # load pt_regs |
710 | brasl %r14,do_signal # call do_signal | 701 | brasl %r14,do_signal # call do_signal |
711 | stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts | 702 | stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts |
712 | TRACE_IRQS_OFF | 703 | TRACE_IRQS_OFF |
713 | j io_work_loop | 704 | j io_return |
714 | 705 | ||
715 | # | 706 | # |
716 | # _TIF_NOTIFY_RESUME or is set, call do_notify_resume | 707 | # _TIF_NOTIFY_RESUME or is set, call do_notify_resume |
717 | # | 708 | # |
718 | io_notify_resume: | 709 | io_notify_resume: |
719 | TRACE_IRQS_ON | 710 | # TRACE_IRQS_ON already done at io_return |
720 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts | 711 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts |
721 | la %r2,SP_PTREGS(%r15) # load pt_regs | 712 | la %r2,SP_PTREGS(%r15) # load pt_regs |
722 | brasl %r14,do_notify_resume # call do_notify_resume | 713 | brasl %r14,do_notify_resume # call do_notify_resume |
723 | stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts | 714 | stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts |
724 | TRACE_IRQS_OFF | 715 | TRACE_IRQS_OFF |
725 | j io_work_loop | 716 | j io_return |
726 | 717 | ||
727 | /* | 718 | /* |
728 | * External interrupt handler routine | 719 | * External interrupt handler routine |
@@ -731,16 +722,18 @@ io_notify_resume: | |||
731 | ext_int_handler: | 722 | ext_int_handler: |
732 | stck __LC_INT_CLOCK | 723 | stck __LC_INT_CLOCK |
733 | stpt __LC_ASYNC_ENTER_TIMER | 724 | stpt __LC_ASYNC_ENTER_TIMER |
734 | SAVE_ALL_BASE __LC_SAVE_AREA+32 | 725 | SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+40 |
735 | SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32 | 726 | CREATE_STACK_FRAME __LC_SAVE_AREA+40 |
736 | CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32 | 727 | mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack |
728 | lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct | ||
737 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 729 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
738 | jz ext_no_vtime | 730 | jz ext_no_vtime |
739 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER | 731 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER |
740 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | 732 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER |
741 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER | 733 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER |
734 | LAST_BREAK | ||
742 | ext_no_vtime: | 735 | ext_no_vtime: |
743 | lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct | 736 | HANDLE_SIE_INTERCEPT |
744 | TRACE_IRQS_OFF | 737 | TRACE_IRQS_OFF |
745 | la %r2,SP_PTREGS(%r15) # address of register-save area | 738 | la %r2,SP_PTREGS(%r15) # address of register-save area |
746 | llgh %r3,__LC_EXT_INT_CODE # get interruption code | 739 | llgh %r3,__LC_EXT_INT_CODE # get interruption code |
@@ -754,17 +747,18 @@ __critical_end: | |||
754 | */ | 747 | */ |
755 | .globl mcck_int_handler | 748 | .globl mcck_int_handler |
756 | mcck_int_handler: | 749 | mcck_int_handler: |
757 | stck __LC_INT_CLOCK | 750 | stck __LC_MCCK_CLOCK |
758 | la %r1,4095 # revalidate r1 | 751 | la %r1,4095 # revalidate r1 |
759 | spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer | 752 | spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer |
760 | lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs | 753 | lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs |
761 | SAVE_ALL_BASE __LC_SAVE_AREA+64 | 754 | stmg %r11,%r15,__LC_SAVE_AREA+80 |
755 | larl %r13,system_call | ||
756 | lg %r11,__LC_LAST_BREAK | ||
762 | la %r12,__LC_MCK_OLD_PSW | 757 | la %r12,__LC_MCK_OLD_PSW |
763 | tm __LC_MCCK_CODE,0x80 # system damage? | 758 | tm __LC_MCCK_CODE,0x80 # system damage? |
764 | jo mcck_int_main # yes -> rest of mcck code invalid | 759 | jo mcck_int_main # yes -> rest of mcck code invalid |
765 | la %r14,4095 | 760 | la %r14,4095 |
766 | mvc __LC_SAVE_AREA+104(8),__LC_ASYNC_ENTER_TIMER | 761 | mvc __LC_MCCK_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA-4095(%r14) |
767 | mvc __LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA-4095(%r14) | ||
768 | tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid? | 762 | tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid? |
769 | jo 1f | 763 | jo 1f |
770 | la %r14,__LC_SYNC_ENTER_TIMER | 764 | la %r14,__LC_SYNC_ENTER_TIMER |
@@ -778,7 +772,7 @@ mcck_int_handler: | |||
778 | jl 0f | 772 | jl 0f |
779 | la %r14,__LC_LAST_UPDATE_TIMER | 773 | la %r14,__LC_LAST_UPDATE_TIMER |
780 | 0: spt 0(%r14) | 774 | 0: spt 0(%r14) |
781 | mvc __LC_ASYNC_ENTER_TIMER(8),0(%r14) | 775 | mvc __LC_MCCK_ENTER_TIMER(8),0(%r14) |
782 | 1: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? | 776 | 1: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? |
783 | jno mcck_int_main # no -> skip cleanup critical | 777 | jno mcck_int_main # no -> skip cleanup critical |
784 | tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit | 778 | tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit |
@@ -794,16 +788,19 @@ mcck_int_main: | |||
794 | srag %r14,%r14,PAGE_SHIFT | 788 | srag %r14,%r14,PAGE_SHIFT |
795 | jz 0f | 789 | jz 0f |
796 | lg %r15,__LC_PANIC_STACK # load panic stack | 790 | lg %r15,__LC_PANIC_STACK # load panic stack |
797 | 0: CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+64 | 791 | 0: aghi %r15,-SP_SIZE # make room for registers & psw |
792 | CREATE_STACK_FRAME __LC_SAVE_AREA+80 | ||
793 | mvc SP_PSW(16,%r15),0(%r12) | ||
794 | lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct | ||
798 | tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid? | 795 | tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid? |
799 | jno mcck_no_vtime # no -> no timer update | 796 | jno mcck_no_vtime # no -> no timer update |
800 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 797 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
801 | jz mcck_no_vtime | 798 | jz mcck_no_vtime |
802 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER | 799 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_MCCK_ENTER_TIMER,__LC_USER_TIMER |
803 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | 800 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER |
804 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER | 801 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_MCCK_ENTER_TIMER |
802 | LAST_BREAK | ||
805 | mcck_no_vtime: | 803 | mcck_no_vtime: |
806 | lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct | ||
807 | la %r2,SP_PTREGS(%r15) # load pt_regs | 804 | la %r2,SP_PTREGS(%r15) # load pt_regs |
808 | brasl %r14,s390_do_machine_check | 805 | brasl %r14,s390_do_machine_check |
809 | tm SP_PSW+1(%r15),0x01 # returning to user ? | 806 | tm SP_PSW+1(%r15),0x01 # returning to user ? |
@@ -814,8 +811,9 @@ mcck_no_vtime: | |||
814 | xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain | 811 | xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain |
815 | lgr %r15,%r1 | 812 | lgr %r15,%r1 |
816 | stosm __SF_EMPTY(%r15),0x04 # turn dat on | 813 | stosm __SF_EMPTY(%r15),0x04 # turn dat on |
817 | tm __TI_flags+7(%r9),_TIF_MCCK_PENDING | 814 | tm __TI_flags+7(%r12),_TIF_MCCK_PENDING |
818 | jno mcck_return | 815 | jno mcck_return |
816 | HANDLE_SIE_INTERCEPT | ||
819 | TRACE_IRQS_OFF | 817 | TRACE_IRQS_OFF |
820 | brasl %r14,s390_handle_mcck | 818 | brasl %r14,s390_handle_mcck |
821 | TRACE_IRQS_ON | 819 | TRACE_IRQS_ON |
@@ -823,11 +821,11 @@ mcck_return: | |||
823 | mvc __LC_RETURN_MCCK_PSW(16),SP_PSW(%r15) # move return PSW | 821 | mvc __LC_RETURN_MCCK_PSW(16),SP_PSW(%r15) # move return PSW |
824 | ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit | 822 | ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit |
825 | lmg %r0,%r15,SP_R0(%r15) # load gprs 0-15 | 823 | lmg %r0,%r15,SP_R0(%r15) # load gprs 0-15 |
826 | mvc __LC_ASYNC_ENTER_TIMER(8),__LC_SAVE_AREA+104 | ||
827 | tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ? | 824 | tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ? |
828 | jno 0f | 825 | jno 0f |
829 | stpt __LC_EXIT_TIMER | 826 | stpt __LC_EXIT_TIMER |
830 | 0: lpswe __LC_RETURN_MCCK_PSW # back to caller | 827 | 0: lpswe __LC_RETURN_MCCK_PSW # back to caller |
828 | mcck_done: | ||
831 | 829 | ||
832 | /* | 830 | /* |
833 | * Restart interruption handler, kick starter for additional CPUs | 831 | * Restart interruption handler, kick starter for additional CPUs |
@@ -883,14 +881,14 @@ stack_overflow: | |||
883 | lg %r15,__LC_PANIC_STACK # change to panic stack | 881 | lg %r15,__LC_PANIC_STACK # change to panic stack |
884 | aghi %r15,-SP_SIZE | 882 | aghi %r15,-SP_SIZE |
885 | mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack | 883 | mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack |
886 | stmg %r0,%r11,SP_R0(%r15) # store gprs %r0-%r11 to kernel stack | 884 | stmg %r0,%r10,SP_R0(%r15) # store gprs %r0-%r10 to kernel stack |
887 | la %r1,__LC_SAVE_AREA | 885 | la %r1,__LC_SAVE_AREA |
888 | chi %r12,__LC_SVC_OLD_PSW | 886 | chi %r12,__LC_SVC_OLD_PSW |
889 | je 0f | 887 | je 0f |
890 | chi %r12,__LC_PGM_OLD_PSW | 888 | chi %r12,__LC_PGM_OLD_PSW |
891 | je 0f | 889 | je 0f |
892 | la %r1,__LC_SAVE_AREA+32 | 890 | la %r1,__LC_SAVE_AREA+40 |
893 | 0: mvc SP_R12(32,%r15),0(%r1) # move %r12-%r15 to stack | 891 | 0: mvc SP_R11(40,%r15),0(%r1) # move %r11-%r15 to stack |
894 | mvc SP_ARGS(8,%r15),__LC_LAST_BREAK | 892 | mvc SP_ARGS(8,%r15),__LC_LAST_BREAK |
895 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) # clear back chain | 893 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) # clear back chain |
896 | la %r2,SP_PTREGS(%r15) # load pt_regs | 894 | la %r2,SP_PTREGS(%r15) # load pt_regs |
@@ -899,18 +897,14 @@ stack_overflow: | |||
899 | 897 | ||
900 | cleanup_table_system_call: | 898 | cleanup_table_system_call: |
901 | .quad system_call, sysc_do_svc | 899 | .quad system_call, sysc_do_svc |
902 | cleanup_table_sysc_return: | 900 | cleanup_table_sysc_tif: |
903 | .quad sysc_return, sysc_leave | 901 | .quad sysc_tif, sysc_restore |
904 | cleanup_table_sysc_leave: | 902 | cleanup_table_sysc_restore: |
905 | .quad sysc_leave, sysc_done | 903 | .quad sysc_restore, sysc_done |
906 | cleanup_table_sysc_work_loop: | 904 | cleanup_table_io_tif: |
907 | .quad sysc_work_loop, sysc_work_done | 905 | .quad io_tif, io_restore |
908 | cleanup_table_io_return: | 906 | cleanup_table_io_restore: |
909 | .quad io_return, io_leave | 907 | .quad io_restore, io_done |
910 | cleanup_table_io_leave: | ||
911 | .quad io_leave, io_done | ||
912 | cleanup_table_io_work_loop: | ||
913 | .quad io_work_loop, io_work_done | ||
914 | 908 | ||
915 | cleanup_critical: | 909 | cleanup_critical: |
916 | clc 8(8,%r12),BASED(cleanup_table_system_call) | 910 | clc 8(8,%r12),BASED(cleanup_table_system_call) |
@@ -918,61 +912,54 @@ cleanup_critical: | |||
918 | clc 8(8,%r12),BASED(cleanup_table_system_call+8) | 912 | clc 8(8,%r12),BASED(cleanup_table_system_call+8) |
919 | jl cleanup_system_call | 913 | jl cleanup_system_call |
920 | 0: | 914 | 0: |
921 | clc 8(8,%r12),BASED(cleanup_table_sysc_return) | 915 | clc 8(8,%r12),BASED(cleanup_table_sysc_tif) |
922 | jl 0f | ||
923 | clc 8(8,%r12),BASED(cleanup_table_sysc_return+8) | ||
924 | jl cleanup_sysc_return | ||
925 | 0: | ||
926 | clc 8(8,%r12),BASED(cleanup_table_sysc_leave) | ||
927 | jl 0f | 916 | jl 0f |
928 | clc 8(8,%r12),BASED(cleanup_table_sysc_leave+8) | 917 | clc 8(8,%r12),BASED(cleanup_table_sysc_tif+8) |
929 | jl cleanup_sysc_leave | 918 | jl cleanup_sysc_tif |
930 | 0: | 919 | 0: |
931 | clc 8(8,%r12),BASED(cleanup_table_sysc_work_loop) | 920 | clc 8(8,%r12),BASED(cleanup_table_sysc_restore) |
932 | jl 0f | 921 | jl 0f |
933 | clc 8(8,%r12),BASED(cleanup_table_sysc_work_loop+8) | 922 | clc 8(8,%r12),BASED(cleanup_table_sysc_restore+8) |
934 | jl cleanup_sysc_return | 923 | jl cleanup_sysc_restore |
935 | 0: | 924 | 0: |
936 | clc 8(8,%r12),BASED(cleanup_table_io_return) | 925 | clc 8(8,%r12),BASED(cleanup_table_io_tif) |
937 | jl 0f | 926 | jl 0f |
938 | clc 8(8,%r12),BASED(cleanup_table_io_return+8) | 927 | clc 8(8,%r12),BASED(cleanup_table_io_tif+8) |
939 | jl cleanup_io_return | 928 | jl cleanup_io_tif |
940 | 0: | 929 | 0: |
941 | clc 8(8,%r12),BASED(cleanup_table_io_leave) | 930 | clc 8(8,%r12),BASED(cleanup_table_io_restore) |
942 | jl 0f | 931 | jl 0f |
943 | clc 8(8,%r12),BASED(cleanup_table_io_leave+8) | 932 | clc 8(8,%r12),BASED(cleanup_table_io_restore+8) |
944 | jl cleanup_io_leave | 933 | jl cleanup_io_restore |
945 | 0: | ||
946 | clc 8(8,%r12),BASED(cleanup_table_io_work_loop) | ||
947 | jl 0f | ||
948 | clc 8(8,%r12),BASED(cleanup_table_io_work_loop+8) | ||
949 | jl cleanup_io_work_loop | ||
950 | 0: | 934 | 0: |
951 | br %r14 | 935 | br %r14 |
952 | 936 | ||
953 | cleanup_system_call: | 937 | cleanup_system_call: |
954 | mvc __LC_RETURN_PSW(16),0(%r12) | 938 | mvc __LC_RETURN_PSW(16),0(%r12) |
955 | cghi %r12,__LC_MCK_OLD_PSW | ||
956 | je 0f | ||
957 | la %r12,__LC_SAVE_AREA+32 | ||
958 | j 1f | ||
959 | 0: la %r12,__LC_SAVE_AREA+64 | ||
960 | 1: | ||
961 | clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+8) | 939 | clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+8) |
962 | jh 0f | 940 | jh 0f |
941 | mvc __LC_SYNC_ENTER_TIMER(8),__LC_MCCK_ENTER_TIMER | ||
942 | cghi %r12,__LC_MCK_OLD_PSW | ||
943 | je 0f | ||
963 | mvc __LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER | 944 | mvc __LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER |
945 | 0: cghi %r12,__LC_MCK_OLD_PSW | ||
946 | la %r12,__LC_SAVE_AREA+80 | ||
947 | je 0f | ||
948 | la %r12,__LC_SAVE_AREA+40 | ||
964 | 0: clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+16) | 949 | 0: clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+16) |
965 | jhe cleanup_vtime | 950 | jhe cleanup_vtime |
966 | clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn) | 951 | clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn) |
967 | jh 0f | 952 | jh 0f |
968 | mvc __LC_SAVE_AREA(32),0(%r12) | 953 | mvc __LC_SAVE_AREA(40),0(%r12) |
969 | 0: stg %r13,8(%r12) | 954 | 0: lg %r15,__LC_KERNEL_STACK # problem state -> load ksp |
970 | stg %r12,__LC_SAVE_AREA+96 # argh | 955 | aghi %r15,-SP_SIZE # make room for registers & psw |
971 | SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 956 | stg %r15,32(%r12) |
972 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 957 | stg %r11,0(%r12) |
973 | lg %r12,__LC_SAVE_AREA+96 # argh | 958 | CREATE_STACK_FRAME __LC_SAVE_AREA |
974 | stg %r15,24(%r12) | 959 | mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW |
975 | llgh %r7,__LC_SVC_INT_CODE | 960 | mvc SP_ILC(4,%r15),__LC_SVC_ILC |
961 | stg %r7,SP_ARGS(%r15) | ||
962 | mvc 8(8,%r12),__LC_THREAD_INFO | ||
976 | cleanup_vtime: | 963 | cleanup_vtime: |
977 | clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+24) | 964 | clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+24) |
978 | jhe cleanup_stime | 965 | jhe cleanup_stime |
@@ -983,7 +970,11 @@ cleanup_stime: | |||
983 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | 970 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER |
984 | cleanup_update: | 971 | cleanup_update: |
985 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER | 972 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER |
986 | mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_system_call+8) | 973 | srag %r12,%r11,23 |
974 | lg %r12,__LC_THREAD_INFO | ||
975 | jz 0f | ||
976 | stg %r11,__TI_last_break(%r12) | ||
977 | 0: mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_system_call+8) | ||
987 | la %r12,__LC_RETURN_PSW | 978 | la %r12,__LC_RETURN_PSW |
988 | br %r14 | 979 | br %r14 |
989 | cleanup_system_call_insn: | 980 | cleanup_system_call_insn: |
@@ -993,61 +984,54 @@ cleanup_system_call_insn: | |||
993 | .quad sysc_stime | 984 | .quad sysc_stime |
994 | .quad sysc_update | 985 | .quad sysc_update |
995 | 986 | ||
996 | cleanup_sysc_return: | 987 | cleanup_sysc_tif: |
997 | mvc __LC_RETURN_PSW(8),0(%r12) | 988 | mvc __LC_RETURN_PSW(8),0(%r12) |
998 | mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_sysc_return) | 989 | mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_sysc_tif) |
999 | la %r12,__LC_RETURN_PSW | 990 | la %r12,__LC_RETURN_PSW |
1000 | br %r14 | 991 | br %r14 |
1001 | 992 | ||
1002 | cleanup_sysc_leave: | 993 | cleanup_sysc_restore: |
1003 | clc 8(8,%r12),BASED(cleanup_sysc_leave_insn) | 994 | clc 8(8,%r12),BASED(cleanup_sysc_restore_insn) |
1004 | je 3f | 995 | je 2f |
1005 | clc 8(8,%r12),BASED(cleanup_sysc_leave_insn+8) | 996 | clc 8(8,%r12),BASED(cleanup_sysc_restore_insn+8) |
1006 | jhe 0f | 997 | jhe 0f |
998 | mvc __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER | ||
999 | cghi %r12,__LC_MCK_OLD_PSW | ||
1000 | je 0f | ||
1007 | mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER | 1001 | mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER |
1008 | 0: mvc __LC_RETURN_PSW(16),SP_PSW(%r15) | 1002 | 0: mvc __LC_RETURN_PSW(16),SP_PSW(%r15) |
1009 | cghi %r12,__LC_MCK_OLD_PSW | 1003 | cghi %r12,__LC_MCK_OLD_PSW |
1010 | jne 1f | 1004 | la %r12,__LC_SAVE_AREA+80 |
1011 | mvc __LC_SAVE_AREA+64(32),SP_R12(%r15) | 1005 | je 1f |
1012 | j 2f | 1006 | la %r12,__LC_SAVE_AREA+40 |
1013 | 1: mvc __LC_SAVE_AREA+32(32),SP_R12(%r15) | 1007 | 1: mvc 0(40,%r12),SP_R11(%r15) |
1014 | 2: lmg %r0,%r11,SP_R0(%r15) | 1008 | lmg %r0,%r10,SP_R0(%r15) |
1015 | lg %r15,SP_R15(%r15) | 1009 | lg %r15,SP_R15(%r15) |
1016 | 3: la %r12,__LC_RETURN_PSW | 1010 | 2: la %r12,__LC_RETURN_PSW |
1017 | br %r14 | 1011 | br %r14 |
1018 | cleanup_sysc_leave_insn: | 1012 | cleanup_sysc_restore_insn: |
1019 | .quad sysc_done - 4 | 1013 | .quad sysc_done - 4 |
1020 | .quad sysc_done - 16 | 1014 | .quad sysc_done - 16 |
1021 | 1015 | ||
1022 | cleanup_io_return: | 1016 | cleanup_io_tif: |
1023 | mvc __LC_RETURN_PSW(8),0(%r12) | ||
1024 | mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_io_return) | ||
1025 | la %r12,__LC_RETURN_PSW | ||
1026 | br %r14 | ||
1027 | |||
1028 | cleanup_io_work_loop: | ||
1029 | mvc __LC_RETURN_PSW(8),0(%r12) | 1017 | mvc __LC_RETURN_PSW(8),0(%r12) |
1030 | mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_io_work_loop) | 1018 | mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_io_tif) |
1031 | la %r12,__LC_RETURN_PSW | 1019 | la %r12,__LC_RETURN_PSW |
1032 | br %r14 | 1020 | br %r14 |
1033 | 1021 | ||
1034 | cleanup_io_leave: | 1022 | cleanup_io_restore: |
1035 | clc 8(8,%r12),BASED(cleanup_io_leave_insn) | 1023 | clc 8(8,%r12),BASED(cleanup_io_restore_insn) |
1036 | je 3f | 1024 | je 1f |
1037 | clc 8(8,%r12),BASED(cleanup_io_leave_insn+8) | 1025 | clc 8(8,%r12),BASED(cleanup_io_restore_insn+8) |
1038 | jhe 0f | 1026 | jhe 0f |
1039 | mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER | 1027 | mvc __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER |
1040 | 0: mvc __LC_RETURN_PSW(16),SP_PSW(%r15) | 1028 | 0: mvc __LC_RETURN_PSW(16),SP_PSW(%r15) |
1041 | cghi %r12,__LC_MCK_OLD_PSW | 1029 | mvc __LC_SAVE_AREA+80(40),SP_R11(%r15) |
1042 | jne 1f | 1030 | lmg %r0,%r10,SP_R0(%r15) |
1043 | mvc __LC_SAVE_AREA+64(32),SP_R12(%r15) | ||
1044 | j 2f | ||
1045 | 1: mvc __LC_SAVE_AREA+32(32),SP_R12(%r15) | ||
1046 | 2: lmg %r0,%r11,SP_R0(%r15) | ||
1047 | lg %r15,SP_R15(%r15) | 1031 | lg %r15,SP_R15(%r15) |
1048 | 3: la %r12,__LC_RETURN_PSW | 1032 | 1: la %r12,__LC_RETURN_PSW |
1049 | br %r14 | 1033 | br %r14 |
1050 | cleanup_io_leave_insn: | 1034 | cleanup_io_restore_insn: |
1051 | .quad io_done - 4 | 1035 | .quad io_done - 4 |
1052 | .quad io_done - 16 | 1036 | .quad io_done - 16 |
1053 | 1037 | ||
@@ -1055,13 +1039,6 @@ cleanup_io_leave_insn: | |||
1055 | * Integer constants | 1039 | * Integer constants |
1056 | */ | 1040 | */ |
1057 | .align 4 | 1041 | .align 4 |
1058 | .Lconst: | ||
1059 | .Lnr_syscalls: .long NR_syscalls | ||
1060 | .L0x0130: .short 0x130 | ||
1061 | .L0x0140: .short 0x140 | ||
1062 | .L0x0150: .short 0x150 | ||
1063 | .L0x0160: .short 0x160 | ||
1064 | .L0x0170: .short 0x170 | ||
1065 | .Lcritical_start: | 1042 | .Lcritical_start: |
1066 | .quad __critical_start | 1043 | .quad __critical_start |
1067 | .Lcritical_end: | 1044 | .Lcritical_end: |