This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / arch / s390 / kernel / entry64.S
1 /*
2  *  arch/s390/kernel/entry.S
3  *    S390 low-level entry points.
4  *
5  *  S390 version
6  *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
7  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
8  *               Hartmut Penner (hp@de.ibm.com),
9  *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
10  */
11
12 #include <linux/sys.h>
13 #include <linux/linkage.h>
14 #include <linux/config.h>
15 #include <asm/cache.h>
16 #include <asm/lowcore.h>
17 #include <asm/errno.h>
18 #include <asm/ptrace.h>
19 #include <asm/thread_info.h>
20 #include <asm/offsets.h>
21 #include <asm/unistd.h>
22
23 /*
24  * Stack layout for the system_call stack entry.
25  * The first few entries are identical to the user_regs_struct.
26  */
27 SP_PTREGS    =  STACK_FRAME_OVERHEAD 
28 SP_PSW       =  STACK_FRAME_OVERHEAD + __PT_PSW
29 SP_R0        =  STACK_FRAME_OVERHEAD + __PT_GPRS
30 SP_R1        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 8
31 SP_R2        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 16
32 SP_R3        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 24
33 SP_R4        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 32
34 SP_R5        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 40
35 SP_R6        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 48
36 SP_R7        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 56
37 SP_R8        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 64
38 SP_R9        =  STACK_FRAME_OVERHEAD + __PT_GPRS + 72
39 SP_R10       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 80
40 SP_R11       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 88
41 SP_R12       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 96
42 SP_R13       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 104
43 SP_R14       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 112
44 SP_R15       =  STACK_FRAME_OVERHEAD + __PT_GPRS + 120
45 SP_ORIG_R2   =  STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2
46 SP_ILC       =  STACK_FRAME_OVERHEAD + __PT_ILC
47 SP_TRAP      =  STACK_FRAME_OVERHEAD + __PT_TRAP
48 SP_SIZE      =  STACK_FRAME_OVERHEAD + __PT_SIZE
49
50 _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_RESTART_SVC)
51 _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
52
53 /*
54  * Register usage in interrupt handlers:
55  *    R9  - pointer to current task structure
56  *    R13 - pointer to literal pool
57  *    R14 - return register for function calls
58  *    R15 - kernel stack pointer
59  */
60
61         .macro  SAVE_ALL psworg,savearea,sync
62         stmg    %r13,%r15,\savearea
63         .if     \sync
64         tm      \psworg+1,0x01           # test problem state bit
65         jz      1f                       # skip stack setup save
66         lg      %r15,__LC_KERNEL_STACK   # problem state -> load ksp
67         .else
68         tm      \psworg+1,0x01           # test problem state bit
69         jnz     0f                       # from user -> load kernel stack
70         lg      %r14,__LC_ASYNC_STACK    # are we already on the async. stack ?
71         slgr    %r14,%r15
72         srag    %r14,%r14,14
73         jz      1f
74 0:      lg      %r15,__LC_ASYNC_STACK    # load async stack
75         .endif
76 1:      aghi    %r15,-SP_SIZE            # make room for registers & psw
77         lghi    %r14,\psworg
78         slgr    %r13,%r13
79         icm     %r14,12,__LC_SVC_ILC
80         stmg    %r0,%r12,SP_R0(%r15)     # store gprs 0-13 to kernel stack
81         stg     %r2,SP_ORIG_R2(%r15)     # store original content of gpr 2
82         mvc     SP_R13(24,%r15),\savearea # move r13, r14 and r15 to stack
83         mvc     SP_PSW(16,%r15),\psworg  # move user PSW to stack
84         st      %r14,SP_ILC(%r15)
85         stg     %r13,0(%r15)
86         .endm
87
88         .macro  CLEANUP_SAVE_ALL psworg,savearea,sync
89         lg      %r1,SP_PSW+8(%r15)
90         cli     1(%r1),0xdf
91         jne     2f
92         mvc     \savearea(24),SP_R13(%r15)
93 2:      lg      %r1,\savearea+16
94         .if     \sync
95         tm      \psworg+1,0x01
96         jz      1f
97         lg      %r1,__LC_KERNEL_STACK
98         .else
99         tm      \psworg+1,0x01
100         jnz     0f
101         lg      %r0,__LC_ASYNC_STACK
102         slgr    %r0,%r1
103         srag    %r0,%r0,14
104         jz      1f
105 0:      lg      %r1,__LC_ASYNC_STACK
106         .endif
107 1:      aghi    %r1,-SP_SIZE
108         stg     %r1,SP_R15(%r15)
109         lghi    %r0,\psworg
110         xc      SP_R13(8,%r15),SP_R13(%r15)
111         icm     %r0,12,__LC_SVC_ILC
112         stg     %r0,SP_R14(%r15)
113         mvc     SP_R0(104,%r1),SP_R0(%r15)
114         mvc     SP_ORIG_R2(8,%r1),SP_R2(%r15)
115         mvc     SP_R13(24,%r1),\savearea
116         mvc     SP_PSW(16,%r1),\psworg
117         st      %r0,SP_ILC(%r1)
118         xc      0(8,%r1),0(%r1)
119         .endm
120
121         .macro  RESTORE_ALL              # system exit macro
122         mvc     __LC_RETURN_PSW(16),SP_PSW(%r15) # move user PSW to lowcore
123         ni      __LC_RETURN_PSW+1,0xfd   # clear wait state bit
124         lmg     %r0,%r15,SP_R0(%r15)     # load gprs 0-15 of user
125         lpswe   __LC_RETURN_PSW          # back to caller
126         .endm
127
128         .macro  CLEANUP_RESTORE_ALL
129         lg      %r1,SP_PSW+8(%r15)
130         cli     0(%r1),0xb2
131         jne     0f
132         mvc     SP_PSW(16,%r15),__LC_RETURN_PSW
133         j       1f
134 0:      lg      %r1,SP_R15(%r15)
135         mvc     SP_PSW(16,%r15),SP_PSW(%r1)
136         mvc     SP_R0(128,%r15),SP_R0(%r1)
137 1:
138         .endm
139
140         .macro  GET_THREAD_INFO
141         lg      %r9,__LC_THREAD_INFO     # load pointer to thread_info struct
142         .endm
143
144         .macro  CHECK_CRITICAL
145         tm      SP_PSW+1(%r15),0x01      # test problem state bit
146         jnz     0f                       # from user -> not critical
147         larl    %r1,.Lcritical_start
148         clc     SP_PSW+8(8,%r15),8(%r1)  # compare ip with __critical_end
149         jnl     0f
150         clc     SP_PSW+8(8,%r15),0(%r1)  # compare ip with __critical_start
151         jl      0f
152         brasl   %r14,cleanup_critical
153 0:
154         .endm
155
156 /*
157  * Scheduler resume function, called by switch_to
158  *  gpr2 = (task_struct *) prev
159  *  gpr3 = (task_struct *) next
160  * Returns:
161  *  gpr2 = prev
162  */
163         .globl  __switch_to
164 __switch_to:
165         tm      __THREAD_per+4(%r3),0xe8 # is the new process using per ?
166         jz      __switch_to_noper               # if not we're fine
167         stctg   %c9,%c11,48(%r15)       # We are using per stuff
168         clc     __THREAD_per(24,%r3),48(%r15)
169         je      __switch_to_noper            # we got away without bashing TLB's
170         lctlg   %c9,%c11,__THREAD_per(%r3)      # Nope we didn't
171 __switch_to_noper:
172         stmg    %r6,%r15,48(%r15)       # store __switch_to registers of prev task
173         stg     %r15,__THREAD_ksp(%r2)  # store kernel stack to prev->tss.ksp
174         lg      %r15,__THREAD_ksp(%r3)  # load kernel stack from next->tss.ksp
175         lmg     %r6,%r15,48(%r15)       # load __switch_to registers of next task
176         stg     %r3,__LC_CURRENT        # __LC_CURRENT = current task struct
177         lg      %r3,__THREAD_info(%r3)  # load thread_info from task struct
178         stg     %r3,__LC_THREAD_INFO
179         aghi    %r3,16384
180         stg     %r3,__LC_KERNEL_STACK   # __LC_KERNEL_STACK = new kernel stack
181         br      %r14
182
183 /*
184  * do_softirq calling function. We want to run the softirq functions on the
185  * asynchronous interrupt stack.
186  */
187         .global do_call_softirq
188 do_call_softirq:
189         stnsm   48(%r15),0xfc
190         stmg    %r12,%r15,56(%r15)
191         lgr     %r12,%r15
192         lg      %r0,__LC_ASYNC_STACK
193         slgr    %r0,%r15
194         srag    %r0,%r0,14
195         je      0f
196         lg      %r15,__LC_ASYNC_STACK
197 0:      aghi    %r15,-STACK_FRAME_OVERHEAD
198         stg     %r12,0(%r15)            # store back chain
199         brasl   %r14,do_softirq
200         lmg     %r12,%r15,56(%r12)
201         ssm     48(%r15)
202         br      %r14
203
204 __critical_start:
205 /*
206  * SVC interrupt handler routine. System calls are synchronous events and
207  * are executed with interrupts enabled.
208  */
209
210         .globl  system_call
211 system_call:
212         SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
213         llgh    %r7,__LC_SVC_INT_CODE # get svc number from lowcore
214 sysc_enter:
215         GET_THREAD_INFO           # load pointer to task_struct to R9
216         slag    %r7,%r7,2         # *4 and test for svc 0
217         jnz     sysc_do_restart
218         # svc 0: system call number in %r1
219         lghi    %r0,NR_syscalls
220         clr     %r1,%r0
221         jnl     sysc_do_restart
222         lgfr    %r7,%r1           # clear high word in r1
223         slag    %r7,%r7,2         # svc 0: system call number in %r1
224 sysc_do_restart:
225         larl    %r10,sys_call_table
226 #ifdef CONFIG_S390_SUPPORT
227         tm      SP_PSW+3(%r15),0x01  # are we running in 31 bit mode ?
228         jo      sysc_noemu
229         larl    %r10,sys_call_table_emu  # use 31 bit emulation system calls
230 sysc_noemu:
231 #endif
232         tm      __TI_flags+7(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
233         lgf     %r8,0(%r7,%r10)   # load address of system call routine
234         jnz     sysc_tracesys
235         basr    %r14,%r8          # call sys_xxxx
236         stg     %r2,SP_R2(%r15)   # store return value (change R2 on stack)
237                                   # ATTENTION: check sys_execve_glue before
238                                   # changing anything here !!
239
240 sysc_return:
241         tm      SP_PSW+1(%r15),0x01    # returning to user ?
242         jno     sysc_leave
243         tm      __TI_flags+7(%r9),_TIF_WORK_SVC
244         jnz     sysc_work         # there is work to do (signals etc.)
245 sysc_leave:
246         RESTORE_ALL
247
248 #
249 # recheck if there is more work to do
250 #
251 sysc_work_loop:
252         GET_THREAD_INFO           # load pointer to task_struct to R9
253         tm      __TI_flags+7(%r9),_TIF_WORK_SVC
254         jz      sysc_leave        # there is no work to do
255 #
256 # One of the work bits is on. Find out which one.
257 # Checked are: _TIF_SIGPENDING and _TIF_NEED_RESCHED
258 #
259 sysc_work:
260         tm      __TI_flags+7(%r9),_TIF_NEED_RESCHED
261         jo      sysc_reschedule
262         tm      __TI_flags+7(%r9),_TIF_SIGPENDING
263         jo      sysc_sigpending
264         tm      __TI_flags+7(%r9),_TIF_RESTART_SVC
265         jo      sysc_restart
266         j       sysc_leave
267
268 #
269 # _TIF_NEED_RESCHED is set, call schedule
270 #       
271 sysc_reschedule:        
272         larl    %r14,sysc_work_loop
273         jg      schedule            # return point is sysc_return
274
275 #
276 # _TIF_SIGPENDING is set, call do_signal
277 #
278 sysc_sigpending:     
279         la      %r2,SP_PTREGS(%r15) # load pt_regs
280         sgr     %r3,%r3           # clear *oldset
281         brasl   %r14,do_signal    # call do_signal
282         tm      __TI_flags+7(%r9),_TIF_RESTART_SVC
283         jo      sysc_restart
284         j       sysc_leave        # out of here, do NOT recheck
285
286 #
287 # _TIF_RESTART_SVC is set, set up registers and restart svc
288 #
289 sysc_restart:
290         ni      __TI_flags+7(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
291         lg      %r7,SP_R2(%r15)        # load new svc number
292         slag    %r7,%r7,2              # *4
293         mvc     SP_R2(8,%r15),SP_ORIG_R2(%r15) # restore first argument
294         lmg     %r2,%r6,SP_R2(%r15)    # load svc arguments
295         j       sysc_do_restart        # restart svc
296
297 __critical_end:
298
299 #
300 # call syscall_trace before and after system call
301 # special linkage: %r12 contains the return address for trace_svc
302 #
303 sysc_tracesys:
304         la      %r2,SP_PTREGS(%r15)    # load pt_regs
305         la      %r3,0
306         srl     %r7,2
307         stg     %r7,SP_R2(%r15)
308         brasl   %r14,syscall_trace
309         lghi    %r0,NR_syscalls
310         clg     %r0,SP_R2(%r15)
311         jnh     sysc_tracenogo
312         lg      %r7,SP_R2(%r15)   # strace might have changed the
313         sll     %r7,2             #  system call
314         lgf     %r8,0(%r7,%r10)
315 sysc_tracego:
316         lmg     %r3,%r6,SP_R3(%r15)
317         lg      %r2,SP_ORIG_R2(%r15)
318         basr    %r14,%r8            # call sys_xxx
319         stg     %r2,SP_R2(%r15)     # store return value
320 sysc_tracenogo:
321         tm      __TI_flags+7(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
322         jz      sysc_return
323         la      %r2,SP_PTREGS(%r15)    # load pt_regs
324         la      %r3,1
325         larl    %r14,sysc_return    # return point is sysc_return
326         jg      syscall_trace
327
328 #
329 # a new process exits the kernel with ret_from_fork
330 #
331         .globl  ret_from_fork
332 ret_from_fork:  
333         GET_THREAD_INFO           # load pointer to task_struct to R9
334         brasl   %r14,schedule_tail
335         stosm   24(%r15),0x03     # reenable interrupts
336         j       sysc_return
337
338 #
339 # clone, fork, vfork, exec and sigreturn need glue,
340 # because they all expect pt_regs as parameter,
341 # but are called with different parameter.
342 # return-address is set up above
343 #
344 sys_clone_glue: 
345         la      %r2,SP_PTREGS(%r15)    # load pt_regs
346         jg      sys_clone              # branch to sys_clone
347
348 #ifdef CONFIG_S390_SUPPORT
349 sys32_clone_glue: 
350         la      %r2,SP_PTREGS(%r15)    # load pt_regs
351         jg      sys32_clone            # branch to sys32_clone
352 #endif
353
354 sys_fork_glue:  
355         la      %r2,SP_PTREGS(%r15)    # load pt_regs
356         jg      sys_fork               # branch to sys_fork
357
358 sys_vfork_glue: 
359         la      %r2,SP_PTREGS(%r15)    # load pt_regs
360         jg      sys_vfork              # branch to sys_vfork
361
362 sys_execve_glue:        
363         la      %r2,SP_PTREGS(%r15)   # load pt_regs
364         lgr     %r12,%r14             # save return address
365         brasl   %r14,sys_execve       # call sys_execve
366         ltgr    %r2,%r2               # check if execve failed
367         bnz     0(%r12)               # it did fail -> store result in gpr2
368         b       6(%r12)               # SKIP STG 2,SP_R2(15) in
369                                       # system_call/sysc_tracesys
370 #ifdef CONFIG_S390_SUPPORT
371 sys32_execve_glue:        
372         la      %r2,SP_PTREGS(%r15)   # load pt_regs
373         lgr     %r12,%r14             # save return address
374         brasl   %r14,sys32_execve     # call sys32_execve
375         ltgr    %r2,%r2               # check if execve failed
376         bnz     0(%r12)               # it did fail -> store result in gpr2
377         b       6(%r12)               # SKIP STG 2,SP_R2(15) in
378                                       # system_call/sysc_tracesys
379 #endif
380
381 sys_sigreturn_glue:     
382         la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
383         jg      sys_sigreturn         # branch to sys_sigreturn
384
385 #ifdef CONFIG_S390_SUPPORT
386 sys32_sigreturn_glue:     
387         la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
388         jg      sys32_sigreturn       # branch to sys32_sigreturn
389 #endif
390
391 sys_rt_sigreturn_glue:     
392         la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
393         jg      sys_rt_sigreturn      # branch to sys_sigreturn
394
395 #ifdef CONFIG_S390_SUPPORT
396 sys32_rt_sigreturn_glue:     
397         la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
398         jg      sys32_rt_sigreturn    # branch to sys32_sigreturn
399 #endif
400
401 #
402 # sigsuspend and rt_sigsuspend need pt_regs as an additional
403 # parameter and they have to skip the store of %r2 into the
404 # user register %r2 because the return value was set in 
405 # sigsuspend and rt_sigsuspend already and must not be overwritten!
406 #
407
408 sys_sigsuspend_glue:    
409         lgr     %r5,%r4               # move mask back
410         lgr     %r4,%r3               # move history1 parameter
411         lgr     %r3,%r2               # move history0 parameter
412         la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter
413         la      %r14,6(%r14)          # skip store of return value
414         jg      sys_sigsuspend        # branch to sys_sigsuspend
415
416 #ifdef CONFIG_S390_SUPPORT
417 sys32_sigsuspend_glue:    
418         llgfr   %r4,%r4               # unsigned long                   
419         lgr     %r5,%r4               # move mask back
420         lgfr    %r3,%r3               # int                     
421         lgr     %r4,%r3               # move history1 parameter
422         lgfr    %r2,%r2               # int                     
423         lgr     %r3,%r2               # move history0 parameter
424         la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter
425         la      %r14,6(%r14)          # skip store of return value
426         jg      sys32_sigsuspend      # branch to sys32_sigsuspend
427 #endif
428
429 sys_rt_sigsuspend_glue: 
430         lgr     %r4,%r3               # move sigsetsize parameter
431         lgr     %r3,%r2               # move unewset parameter
432         la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter
433         la      %r14,6(%r14)          # skip store of return value
434         jg      sys_rt_sigsuspend     # branch to sys_rt_sigsuspend
435
436 #ifdef CONFIG_S390_SUPPORT
437 sys32_rt_sigsuspend_glue: 
438         llgfr   %r3,%r3               # size_t                  
439         lgr     %r4,%r3               # move sigsetsize parameter
440         llgtr   %r2,%r2               # sigset_emu31_t *
441         lgr     %r3,%r2               # move unewset parameter
442         la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter
443         la      %r14,6(%r14)          # skip store of return value
444         jg      sys32_rt_sigsuspend   # branch to sys32_rt_sigsuspend
445 #endif
446
447 sys_sigaltstack_glue:
448         la      %r4,SP_PTREGS(%r15)   # load pt_regs as parameter
449         jg      sys_sigaltstack       # branch to sys_sigreturn
450
451 #ifdef CONFIG_S390_SUPPORT
452 sys32_sigaltstack_glue:
453         la      %r4,SP_PTREGS(%r15)   # load pt_regs as parameter
454         jg      sys32_sigaltstack_wrapper # branch to sys_sigreturn
455 #endif
456
457 /*
458  * Program check handler routine
459  */
460
461         .globl  pgm_check_handler
462 pgm_check_handler:
463 /*
464  * First we need to check for a special case:
465  * Single stepping an instruction that disables the PER event mask will
466  * cause a PER event AFTER the mask has been set. Example: SVC or LPSW.
467  * For a single stepped SVC the program check handler gets control after
468  * the SVC new PSW has been loaded. But we want to execute the SVC first and
469  * then handle the PER event. Therefore we update the SVC old PSW to point
470  * to the pgm_check_handler and branch to the SVC handler after we checked
471  * if we have to load the kernel stack register.
472  * For every other possible cause for PER event without the PER mask set
473  * we just ignore the PER event (FIXME: is there anything we have to do
474  * for LPSW?).
475  */
476         tm      __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
477         jnz     pgm_per                  # got per exception -> special case
478         SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1
479         lgf     %r3,__LC_PGM_ILC         # load program interruption code
480         lghi    %r8,0x7f
481         ngr     %r8,%r3
482         sll     %r8,3
483         GET_THREAD_INFO
484         larl    %r1,pgm_check_table
485         lg      %r1,0(%r8,%r1)           # load address of handler routine
486         la      %r2,SP_PTREGS(%r15)      # address of register-save area
487         larl    %r14,sysc_return
488         br      %r1                      # branch to interrupt-handler
489
490 #
491 # handle per exception
492 #
493 pgm_per:
494         tm      __LC_PGM_OLD_PSW,0x40    # test if per event recording is on
495         jnz     pgm_per_std              # ok, normal per event from user space
496 # ok its one of the special cases, now we need to find out which one
497         clc     __LC_PGM_OLD_PSW(16),__LC_SVC_NEW_PSW
498         je      pgm_svcper
499 # no interesting special case, ignore PER event
500         lpswe   __LC_PGM_OLD_PSW
501
502 #
503 # Normal per exception
504 #
505 pgm_per_std:
506         SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1
507         GET_THREAD_INFO
508         lg      %r1,__TI_task(%r9)
509         mvc     __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID
510         mvc     __THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS
511         mvc     __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
512         lghi    %r4,0x7f
513         lgf     %r3,__LC_PGM_ILC         # load program interruption code
514         nr      %r4,%r3                  # clear per-event-bit and ilc
515         je      pgm_per_only             # only per of per+check ?
516         sll     %r4,3
517         larl    %r1,pgm_check_table
518         lg      %r1,0(%r4,%r1)           # load address of handler routine
519         la      %r2,SP_PTREGS(%r15)      # address of register-save area
520         basr    %r14,%r1                 # branch to interrupt-handler
521 pgm_per_only:
522         la      %r2,SP_PTREGS(15)        # address of register-save area
523         larl    %r14,sysc_return         # load adr. of system return
524         jg      do_debugger_trap
525
526 #
527 # it was a single stepped SVC that is causing all the trouble
528 #
529 pgm_svcper:
530         SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
531         llgh    %r7,__LC_SVC_INT_CODE # get svc number from lowcore
532         GET_THREAD_INFO           # load pointer to task_struct to R9
533         lg      %r1,__TI_task(%r9)
534         mvc     __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID
535         mvc     __THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS
536         mvc     __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
537         stosm   48(%r15),0x03     # reenable interrupts
538         slag    %r7,%r7,2         # *4 and test for svc 0
539         jnz     pgm_svcstd
540         # svc 0: system call number in %r1
541         lghi    %r0,NR_syscalls
542         clr     %r1,%r0
543         slag    %r7,%r1,2
544 pgm_svcstd:
545         larl    %r10,sys_call_table
546 #ifdef CONFIG_S390_SUPPORT
547         tm      SP_PSW+3(%r15),0x01  # are we running in 31 bit mode ?
548         jo      pgm_svcper_noemu
549         larl    %r10,sys_call_table_emu # use 31 bit emulation system calls
550 pgm_svcper_noemu:
551 #endif
552         tm      __TI_flags+7(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
553         lgf     %r8,0(%r7,%r10)   # load address of system call routine
554         jnz     pgm_tracesys
555         basr    %r14,%r8          # call sys_xxxx
556         stg     %r2,SP_R2(%r15)   # store return value (change R2 on stack)
557                                   # ATTENTION: check sys_execve_glue before
558                                   # changing anything here !!
559
560 pgm_svcret:
561         tm      __TI_flags+7(%r9),_TIF_SIGPENDING
562         jno     pgm_svcper_nosig
563         la      %r2,SP_PTREGS(%r15) # load pt_regs
564         sgr     %r3,%r3             # clear *oldset
565         brasl   %r14,do_signal
566         
567 pgm_svcper_nosig:
568         lhi     %r0,__LC_PGM_OLD_PSW     # set trap indication back to pgm_chk
569         st      %r0,SP_TRAP(%r15)
570         la      %r2,SP_PTREGS(15) # address of register-save area
571         larl    %r14,sysc_return  # load adr. of system return
572         jg      do_debugger_trap
573 #
574 # call trace before and after sys_call
575 #
576 pgm_tracesys:
577         la      %r2,SP_PTREGS(%r15)    # load pt_regs
578         la      %r3,0
579         srlg    %r7,%r7,2
580         stg     %r7,SP_R2(%r15)
581         brasl   %r14,syscall_trace
582         lghi    %r0,NR_syscalls
583         clg     %r0,SP_R2(%r15)
584         jnh     pgm_svc_nogo
585         lg      %r7,SP_R2(%r15)
586         sllg    %r7,%r7,2           # strace wants to change the syscall
587         lgf     %r8,0(%r7,%r10)
588 pgm_svc_go:
589         lmg     %r3,%r6,SP_R3(%r15)
590         lg      %r2,SP_ORIG_R2(%r15)
591         basr    %r14,%r8            # call sys_xxx
592         stg     %r2,SP_R2(%r15)     # store return value
593 pgm_svc_nogo:
594         tm      __TI_flags+7(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
595         jz      pgm_svcret
596         la      %r2,SP_PTREGS(%r15)    # load pt_regs
597         la      %r3,1
598         larl    %r14,pgm_svcret     # return point is sysc_return
599         jg      syscall_trace
600
601 /*
602  * IO interrupt handler routine
603  */
604         .globl io_int_handler
605 io_int_handler:
606         SAVE_ALL __LC_IO_OLD_PSW,__LC_SAVE_AREA+32,0
607         stck    __LC_INT_CLOCK
608         CHECK_CRITICAL
609         GET_THREAD_INFO                # load pointer to task_struct to R9
610         la      %r2,SP_PTREGS(%r15)    # address of register-save area
611         brasl   %r14,do_IRQ            # call standard irq handler
612
613 io_return:
614         tm      SP_PSW+1(%r15),0x01    # returning to user ?
615 #ifdef CONFIG_PREEMPT
616         jno     io_preempt             # no -> check for preemptive scheduling
617 #else
618         jno     io_leave               # no-> skip resched & signal
619 #endif
620         tm      __TI_flags+7(%r9),_TIF_WORK_INT
621         jnz     io_work                # there is work to do (signals etc.)
622 io_leave:
623         RESTORE_ALL
624
625 #ifdef CONFIG_PREEMPT
626 io_preempt:
627         icm     %r0,15,__TI_precount(%r9)       
628         jnz     io_leave
629         # switch to kernel stack
630         lg      %r1,SP_R15(%r15)
631         aghi    %r1,-SP_SIZE
632         mvc     SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
633         xc      0(8,%r1),0(%r1)        # clear back chain
634         lgr     %r15,%r1
635 io_resume_loop:
636         tm      __TI_flags+7(%r9),_TIF_NEED_RESCHED
637         jno     io_leave
638         larl    %r1,.Lc_pactive
639         mvc     __TI_precount(4,%r9),0(%r1)
640         stosm   48(%r15),0x03          # reenable interrupts
641         brasl   %r14,schedule          # call schedule
642         stnsm   48(%r15),0xfc          # disable I/O and ext. interrupts
643         GET_THREAD_INFO                # load pointer to task_struct to R9
644         xc      __TI_precount(4,%r9),__TI_precount(%r9)
645         j       io_resume_loop
646 #endif
647
648 #
649 # switch to kernel stack, then check TIF bits
650 #
651 io_work:
652         lg      %r1,__LC_KERNEL_STACK
653         aghi    %r1,-SP_SIZE
654         mvc     SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
655         xc      0(8,%r1),0(%r1)        # clear back chain
656         lgr     %r15,%r1
657 #
658 # One of the work bits is on. Find out which one.
659 # Checked are: _TIF_SIGPENDING and _TIF_NEED_RESCHED
660 #
661 io_work_loop:
662         tm      __TI_flags+7(%r9),_TIF_NEED_RESCHED
663         jo      io_reschedule
664         tm      __TI_flags+7(%r9),_TIF_SIGPENDING
665         jo      io_sigpending
666         j       io_leave
667
668 #
669 # _TIF_NEED_RESCHED is set, call schedule
670 #       
671 io_reschedule:        
672         stosm   48(%r15),0x03       # reenable interrupts
673         brasl   %r14,schedule       # call scheduler
674         stnsm   48(%r15),0xfc       # disable I/O and ext. interrupts
675         GET_THREAD_INFO             # load pointer to task_struct to R9
676         tm      __TI_flags+7(%r9),_TIF_WORK_INT
677         jz      io_leave               # there is no work to do
678         j       io_work_loop
679
680 #
681 # _TIF_SIGPENDING is set, call do_signal
682 #
683 io_sigpending:     
684         stosm   48(%r15),0x03       # reenable interrupts
685         la      %r2,SP_PTREGS(%r15) # load pt_regs
686         slgr    %r3,%r3             # clear *oldset
687         brasl   %r14,do_signal      # call do_signal
688         stnsm   48(%r15),0xfc       # disable I/O and ext. interrupts
689         j       sysc_leave          # out of here, do NOT recheck
690
691 /*
692  * External interrupt handler routine
693  */
694         .globl  ext_int_handler
695 ext_int_handler:
696         SAVE_ALL __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32,0
697         CHECK_CRITICAL
698         GET_THREAD_INFO                # load pointer to task_struct to R9
699         stck    __LC_INT_CLOCK
700         la      %r2,SP_PTREGS(%r15)    # address of register-save area
701         llgh    %r3,__LC_EXT_INT_CODE  # get interruption code
702         brasl   %r14,do_extint
703         j       io_return
704
705 /*
706  * Machine check handler routines
707  */
708         .globl mcck_int_handler
709 mcck_int_handler:
710         SAVE_ALL __LC_MCK_OLD_PSW,__LC_SAVE_AREA+64,0
711         brasl   %r14,s390_do_machine_check
712 mcck_return:
713         RESTORE_ALL
714
715 #ifdef CONFIG_SMP
716 /*
717  * Restart interruption handler, kick starter for additional CPUs
718  */
719         .globl restart_int_handler
720 restart_int_handler:
721         lg      %r15,__LC_SAVE_AREA+120 # load ksp
722         lghi    %r10,__LC_CREGS_SAVE_AREA
723         lctlg   %c0,%c15,0(%r10) # get new ctl regs
724         lghi    %r10,__LC_AREGS_SAVE_AREA
725         lam     %a0,%a15,0(%r10)
726         stosm   0(%r15),0x04           # now we can turn dat on
727         lmg     %r6,%r15,48(%r15)      # load registers from clone
728         jg      start_secondary
729 #else
730 /*
731  * If we do not run with SMP enabled, let the new CPU crash ...
732  */
733         .globl restart_int_handler
734 restart_int_handler:
735         basr    %r1,0
736 restart_base:
737         lpswe   restart_crash-restart_base(%r1)
738         .align 8
739 restart_crash:
740         .long  0x000a0000,0x00000000,0x00000000,0x00000000
741 restart_go:
742 #endif
743
744 cleanup_table:
745         .quad   system_call, sysc_enter, cleanup_sysc_enter
746         .quad   sysc_return, sysc_leave, cleanup_sysc_return
747         .quad   sysc_leave, sysc_work_loop, cleanup_sysc_leave
748         .quad   sysc_work_loop, sysc_reschedule, cleanup_sysc_return
749 cleanup_table_entries=(.-cleanup_table) / 24
750
751 cleanup_critical:
752         lghi    %r0,cleanup_table_entries
753         larl    %r1,cleanup_table
754         lg      %r2,SP_PSW+8(%r15)
755 cleanup_loop:
756         clg     %r2,0(%r1)
757         jl      cleanup_cont
758         clg     %r2,8(%r1)
759         jl      cleanup_found
760 cleanup_cont:
761         la      %r1,24(%r1)
762         brct    %r0,cleanup_loop
763         br      %r14
764 cleanup_found:
765         lg      %r1,16(%r1)
766         br      %r1
767
768 cleanup_sysc_enter:
769         CLEANUP_SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
770         llgh    %r0,0x8a
771         stg     %r0,SP_R7(%r15)
772         larl    %r1,sysc_enter
773         stg     %r1,SP_PSW+8(%r15)
774         br      %r14
775
776 cleanup_sysc_return:
777         larl    %r1,sysc_return
778         stg     %r1,SP_PSW+8(%r15)
779         br      %r14
780
781 cleanup_sysc_leave:
782         CLEANUP_RESTORE_ALL
783         br      %r14
784
785 /*
786  * Integer constants
787  */
788                .align 4
789 .Lconst:
790 .Lc_pactive:   .long  PREEMPT_ACTIVE
791 .Lcritical_start:
792                .quad  __critical_start
793 .Lcritical_end:
794                .quad  __critical_end
795
796 #define SYSCALL(esa,esame,emu)  .long esame
797         .globl  sys_call_table
798 sys_call_table:
799 #include "syscalls.S"
800 #undef SYSCALL
801
802 #ifdef CONFIG_S390_SUPPORT
803
804 #define SYSCALL(esa,esame,emu)  .long emu
805         .globl  sys_call_table_emu
806 sys_call_table_emu:
807 #include "syscalls.S"
808 #undef SYSCALL
809 #endif