xref: /openbmc/linux/arch/s390/kernel/entry.S (revision 78c99ba1)
1/*
2 *  arch/s390/kernel/entry.S
3 *    S390 low-level entry points.
4 *
5 *    Copyright (C) IBM Corp. 1999,2006
6 *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
7 *		 Hartmut Penner (hp@de.ibm.com),
8 *		 Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
9 *		 Heiko Carstens <heiko.carstens@de.ibm.com>
10 */
11
12#include <linux/sys.h>
13#include <linux/linkage.h>
14#include <linux/init.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/asm-offsets.h>
21#include <asm/unistd.h>
22#include <asm/page.h>
23
24/*
25 * Stack layout for the system_call stack entry.
26 * The first few entries are identical to the user_regs_struct.
27 */
28SP_PTREGS    =	STACK_FRAME_OVERHEAD
29SP_ARGS      =	STACK_FRAME_OVERHEAD + __PT_ARGS
30SP_PSW	     =	STACK_FRAME_OVERHEAD + __PT_PSW
31SP_R0	     =	STACK_FRAME_OVERHEAD + __PT_GPRS
32SP_R1	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 4
33SP_R2	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 8
34SP_R3	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 12
35SP_R4	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 16
36SP_R5	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 20
37SP_R6	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 24
38SP_R7	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 28
39SP_R8	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 32
40SP_R9	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 36
41SP_R10	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 40
42SP_R11	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 44
43SP_R12	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 48
44SP_R13	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 52
45SP_R14	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 56
46SP_R15	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 60
47SP_ORIG_R2   =	STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2
48SP_ILC	     =	STACK_FRAME_OVERHEAD + __PT_ILC
49SP_SVCNR     =	STACK_FRAME_OVERHEAD + __PT_SVCNR
50SP_SIZE      =	STACK_FRAME_OVERHEAD + __PT_SIZE
51
52_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
53		 _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
54_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
55		 _TIF_MCCK_PENDING)
56
57STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
58STACK_SIZE  = 1 << STACK_SHIFT
59
60#define BASED(name) name-system_call(%r13)
61
62#ifdef CONFIG_TRACE_IRQFLAGS
63	.macro	TRACE_IRQS_ON
64	basr	%r2,%r0
65	l	%r1,BASED(.Ltrace_irq_on_caller)
66	basr	%r14,%r1
67	.endm
68
69	.macro	TRACE_IRQS_OFF
70	basr	%r2,%r0
71	l	%r1,BASED(.Ltrace_irq_off_caller)
72	basr	%r14,%r1
73	.endm
74
75	.macro	TRACE_IRQS_CHECK
76	basr	%r2,%r0
77	tm	SP_PSW(%r15),0x03	# irqs enabled?
78	jz	0f
79	l	%r1,BASED(.Ltrace_irq_on_caller)
80	basr	%r14,%r1
81	j	1f
820:	l	%r1,BASED(.Ltrace_irq_off_caller)
83	basr	%r14,%r1
841:
85	.endm
86#else
87#define TRACE_IRQS_ON
88#define TRACE_IRQS_OFF
89#define TRACE_IRQS_CHECK
90#endif
91
92#ifdef CONFIG_LOCKDEP
93	.macro	LOCKDEP_SYS_EXIT
94	tm	SP_PSW+1(%r15),0x01	# returning to user ?
95	jz	0f
96	l	%r1,BASED(.Llockdep_sys_exit)
97	basr	%r14,%r1
980:
99	.endm
100#else
101#define LOCKDEP_SYS_EXIT
102#endif
103
104/*
105 * Register usage in interrupt handlers:
106 *    R9  - pointer to current task structure
107 *    R13 - pointer to literal pool
108 *    R14 - return register for function calls
109 *    R15 - kernel stack pointer
110 */
111
112	.macro	UPDATE_VTIME lc_from,lc_to,lc_sum
113	lm	%r10,%r11,\lc_from
114	sl	%r10,\lc_to
115	sl	%r11,\lc_to+4
116	bc	3,BASED(0f)
117	sl	%r10,BASED(.Lc_1)
1180:	al	%r10,\lc_sum
119	al	%r11,\lc_sum+4
120	bc	12,BASED(1f)
121	al	%r10,BASED(.Lc_1)
1221:	stm	%r10,%r11,\lc_sum
123	.endm
124
125	.macro	SAVE_ALL_BASE savearea
126	stm	%r12,%r15,\savearea
127	l	%r13,__LC_SVC_NEW_PSW+4	# load &system_call to %r13
128	.endm
129
130	.macro	SAVE_ALL_SVC psworg,savearea
131	la	%r12,\psworg
132	l	%r15,__LC_KERNEL_STACK	# problem state -> load ksp
133	.endm
134
135	.macro	SAVE_ALL_SYNC psworg,savearea
136	la	%r12,\psworg
137	tm	\psworg+1,0x01		# test problem state bit
138	bz	BASED(2f)		# skip stack setup save
139	l	%r15,__LC_KERNEL_STACK	# problem state -> load ksp
140#ifdef CONFIG_CHECK_STACK
141	b	BASED(3f)
1422:	tml	%r15,STACK_SIZE - CONFIG_STACK_GUARD
143	bz	BASED(stack_overflow)
1443:
145#endif
1462:
147	.endm
148
149	.macro	SAVE_ALL_ASYNC psworg,savearea
150	la	%r12,\psworg
151	tm	\psworg+1,0x01		# test problem state bit
152	bnz	BASED(1f)		# from user -> load async stack
153	clc	\psworg+4(4),BASED(.Lcritical_end)
154	bhe	BASED(0f)
155	clc	\psworg+4(4),BASED(.Lcritical_start)
156	bl	BASED(0f)
157	l	%r14,BASED(.Lcleanup_critical)
158	basr	%r14,%r14
159	tm	1(%r12),0x01		# retest problem state after cleanup
160	bnz	BASED(1f)
1610:	l	%r14,__LC_ASYNC_STACK	# are we already on the async stack ?
162	slr	%r14,%r15
163	sra	%r14,STACK_SHIFT
164	be	BASED(2f)
1651:	l	%r15,__LC_ASYNC_STACK
166#ifdef CONFIG_CHECK_STACK
167	b	BASED(3f)
1682:	tml	%r15,STACK_SIZE - CONFIG_STACK_GUARD
169	bz	BASED(stack_overflow)
1703:
171#endif
1722:
173	.endm
174
175	.macro	CREATE_STACK_FRAME psworg,savearea
176	s	%r15,BASED(.Lc_spsize)	# make room for registers & psw
177	mvc	SP_PSW(8,%r15),0(%r12)	# move user PSW to stack
178	st	%r2,SP_ORIG_R2(%r15)	# store original content of gpr 2
179	icm	%r12,3,__LC_SVC_ILC
180	stm	%r0,%r11,SP_R0(%r15)	# store gprs %r0-%r11 to kernel stack
181	st	%r12,SP_SVCNR(%r15)
182	mvc	SP_R12(16,%r15),\savearea # move %r12-%r15 to stack
183	la	%r12,0
184	st	%r12,__SF_BACKCHAIN(%r15)	# clear back chain
185	.endm
186
187	.macro	RESTORE_ALL psworg,sync
188	mvc	\psworg(8),SP_PSW(%r15) # move user PSW to lowcore
189	.if !\sync
190	ni	\psworg+1,0xfd		# clear wait state bit
191	.endif
192	lm	%r0,%r15,SP_R0(%r15)	# load gprs 0-15 of user
193	stpt	__LC_EXIT_TIMER
194	lpsw	\psworg			# back to caller
195	.endm
196
197/*
198 * Scheduler resume function, called by switch_to
199 *  gpr2 = (task_struct *) prev
200 *  gpr3 = (task_struct *) next
201 * Returns:
202 *  gpr2 = prev
203 */
204	.globl	__switch_to
205__switch_to:
206	basr	%r1,0
207__switch_to_base:
208	tm	__THREAD_per(%r3),0xe8		# new process is using per ?
209	bz	__switch_to_noper-__switch_to_base(%r1)	# if not we're fine
210	stctl	%c9,%c11,__SF_EMPTY(%r15)	# We are using per stuff
211	clc	__THREAD_per(12,%r3),__SF_EMPTY(%r15)
212	be	__switch_to_noper-__switch_to_base(%r1)	# we got away w/o bashing TLB's
213	lctl	%c9,%c11,__THREAD_per(%r3)	# Nope we didn't
214__switch_to_noper:
215	l	%r4,__THREAD_info(%r2)		# get thread_info of prev
216	tm	__TI_flags+3(%r4),_TIF_MCCK_PENDING # machine check pending?
217	bz	__switch_to_no_mcck-__switch_to_base(%r1)
218	ni	__TI_flags+3(%r4),255-_TIF_MCCK_PENDING # clear flag in prev
219	l	%r4,__THREAD_info(%r3)		# get thread_info of next
220	oi	__TI_flags+3(%r4),_TIF_MCCK_PENDING # set it in next
221__switch_to_no_mcck:
222	stm	%r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task
223	st	%r15,__THREAD_ksp(%r2)	# store kernel stack to prev->tss.ksp
224	l	%r15,__THREAD_ksp(%r3)	# load kernel stack from next->tss.ksp
225	lm	%r6,%r15,__SF_GPRS(%r15)# load __switch_to registers of next task
226	st	%r3,__LC_CURRENT	# __LC_CURRENT = current task struct
227	lctl	%c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4
228	l	%r3,__THREAD_info(%r3)	# load thread_info from task struct
229	st	%r3,__LC_THREAD_INFO
230	ahi	%r3,STACK_SIZE
231	st	%r3,__LC_KERNEL_STACK	# __LC_KERNEL_STACK = new kernel stack
232	br	%r14
233
234__critical_start:
235/*
236 * SVC interrupt handler routine. System calls are synchronous events and
237 * are executed with interrupts enabled.
238 */
239
240	.globl	system_call
241system_call:
242	stpt	__LC_SYNC_ENTER_TIMER
243sysc_saveall:
244	SAVE_ALL_BASE __LC_SAVE_AREA
245	SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
246	CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
247	lh	%r7,0x8a	  # get svc number from lowcore
248sysc_vtime:
249	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
250sysc_stime:
251	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
252sysc_update:
253	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
254sysc_do_svc:
255	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
256	ltr	%r7,%r7			# test for svc 0
257	bnz	BASED(sysc_nr_ok)	# svc number > 0
258	# svc 0: system call number in %r1
259	cl	%r1,BASED(.Lnr_syscalls)
260	bnl	BASED(sysc_nr_ok)
261	lr	%r7,%r1 	  # copy svc number to %r7
262sysc_nr_ok:
263	mvc	SP_ARGS(4,%r15),SP_R7(%r15)
264sysc_do_restart:
265	sth	%r7,SP_SVCNR(%r15)
266	sll	%r7,2		  # svc number *4
267	l	%r8,BASED(.Lsysc_table)
268	tm	__TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
269	l	%r8,0(%r7,%r8)	  # get system call addr.
270	bnz	BASED(sysc_tracesys)
271	basr	%r14,%r8	  # call sys_xxxx
272	st	%r2,SP_R2(%r15)   # store return value (change R2 on stack)
273
274sysc_return:
275	tm	__TI_flags+3(%r9),_TIF_WORK_SVC
276	bnz	BASED(sysc_work)  # there is work to do (signals etc.)
277sysc_restore:
278#ifdef CONFIG_TRACE_IRQFLAGS
279	la	%r1,BASED(sysc_restore_trace_psw)
280	lpsw	0(%r1)
281sysc_restore_trace:
282	TRACE_IRQS_CHECK
283	LOCKDEP_SYS_EXIT
284#endif
285sysc_leave:
286	RESTORE_ALL __LC_RETURN_PSW,1
287sysc_done:
288
289#ifdef CONFIG_TRACE_IRQFLAGS
290	.align	8
291	.globl	sysc_restore_trace_psw
292sysc_restore_trace_psw:
293	.long	0, sysc_restore_trace + 0x80000000
294#endif
295
296#
297# recheck if there is more work to do
298#
299sysc_work_loop:
300	tm	__TI_flags+3(%r9),_TIF_WORK_SVC
301	bz	BASED(sysc_restore)	# there is no work to do
302#
303# One of the work bits is on. Find out which one.
304#
305sysc_work:
306	tm	SP_PSW+1(%r15),0x01	# returning to user ?
307	bno	BASED(sysc_restore)
308	tm	__TI_flags+3(%r9),_TIF_MCCK_PENDING
309	bo	BASED(sysc_mcck_pending)
310	tm	__TI_flags+3(%r9),_TIF_NEED_RESCHED
311	bo	BASED(sysc_reschedule)
312	tm	__TI_flags+3(%r9),_TIF_SIGPENDING
313	bnz	BASED(sysc_sigpending)
314	tm	__TI_flags+3(%r9),_TIF_NOTIFY_RESUME
315	bnz	BASED(sysc_notify_resume)
316	tm	__TI_flags+3(%r9),_TIF_RESTART_SVC
317	bo	BASED(sysc_restart)
318	tm	__TI_flags+3(%r9),_TIF_SINGLE_STEP
319	bo	BASED(sysc_singlestep)
320	b	BASED(sysc_restore)
321sysc_work_done:
322
323#
324# _TIF_NEED_RESCHED is set, call schedule
325#
326sysc_reschedule:
327	l	%r1,BASED(.Lschedule)
328	la	%r14,BASED(sysc_work_loop)
329	br	%r1			# call scheduler
330
331#
332# _TIF_MCCK_PENDING is set, call handler
333#
334sysc_mcck_pending:
335	l	%r1,BASED(.Ls390_handle_mcck)
336	la	%r14,BASED(sysc_work_loop)
337	br	%r1			# TIF bit will be cleared by handler
338
339#
340# _TIF_SIGPENDING is set, call do_signal
341#
342sysc_sigpending:
343	ni	__TI_flags+3(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
344	la	%r2,SP_PTREGS(%r15)	# load pt_regs
345	l	%r1,BASED(.Ldo_signal)
346	basr	%r14,%r1		# call do_signal
347	tm	__TI_flags+3(%r9),_TIF_RESTART_SVC
348	bo	BASED(sysc_restart)
349	tm	__TI_flags+3(%r9),_TIF_SINGLE_STEP
350	bo	BASED(sysc_singlestep)
351	b	BASED(sysc_work_loop)
352
353#
354# _TIF_NOTIFY_RESUME is set, call do_notify_resume
355#
356sysc_notify_resume:
357	la	%r2,SP_PTREGS(%r15)	# load pt_regs
358	l	%r1,BASED(.Ldo_notify_resume)
359	la	%r14,BASED(sysc_work_loop)
360	br	%r1			# call do_notify_resume
361
362
363#
364# _TIF_RESTART_SVC is set, set up registers and restart svc
365#
366sysc_restart:
367	ni	__TI_flags+3(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
368	l	%r7,SP_R2(%r15) 	# load new svc number
369	mvc	SP_R2(4,%r15),SP_ORIG_R2(%r15) # restore first argument
370	lm	%r2,%r6,SP_R2(%r15)	# load svc arguments
371	b	BASED(sysc_do_restart)	# restart svc
372
373#
374# _TIF_SINGLE_STEP is set, call do_single_step
375#
376sysc_singlestep:
377	ni	__TI_flags+3(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
378	mvi	SP_SVCNR(%r15),0xff	# set trap indication to pgm check
379	mvi	SP_SVCNR+1(%r15),0xff
380	la	%r2,SP_PTREGS(%r15)	# address of register-save area
381	l	%r1,BASED(.Lhandle_per)	# load adr. of per handler
382	la	%r14,BASED(sysc_return)	# load adr. of system return
383	br	%r1			# branch to do_single_step
384
385#
386# call tracehook_report_syscall_entry/tracehook_report_syscall_exit before
387# and after the system call
388#
389sysc_tracesys:
390	l	%r1,BASED(.Ltrace_entry)
391	la	%r2,SP_PTREGS(%r15)	# load pt_regs
392	la	%r3,0
393	srl	%r7,2
394	st	%r7,SP_R2(%r15)
395	basr	%r14,%r1
396	cl	%r2,BASED(.Lnr_syscalls)
397	bnl	BASED(sysc_tracenogo)
398	l	%r8,BASED(.Lsysc_table)
399	lr	%r7,%r2
400	sll	%r7,2			# svc number *4
401	l	%r8,0(%r7,%r8)
402sysc_tracego:
403	lm	%r3,%r6,SP_R3(%r15)
404	l	%r2,SP_ORIG_R2(%r15)
405	basr	%r14,%r8		# call sys_xxx
406	st	%r2,SP_R2(%r15)		# store return value
407sysc_tracenogo:
408	tm	__TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
409	bz	BASED(sysc_return)
410	l	%r1,BASED(.Ltrace_exit)
411	la	%r2,SP_PTREGS(%r15)	# load pt_regs
412	la	%r14,BASED(sysc_return)
413	br	%r1
414
415#
416# a new process exits the kernel with ret_from_fork
417#
418	.globl	ret_from_fork
419ret_from_fork:
420	l	%r13,__LC_SVC_NEW_PSW+4
421	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
422	tm	SP_PSW+1(%r15),0x01	# forking a kernel thread ?
423	bo	BASED(0f)
424	st	%r15,SP_R15(%r15)	# store stack pointer for new kthread
4250:	l	%r1,BASED(.Lschedtail)
426	basr	%r14,%r1
427	TRACE_IRQS_ON
428	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
429	b	BASED(sysc_tracenogo)
430
431#
432# kernel_execve function needs to deal with pt_regs that is not
433# at the usual place
434#
435	.globl	kernel_execve
436kernel_execve:
437	stm	%r12,%r15,48(%r15)
438	lr	%r14,%r15
439	l	%r13,__LC_SVC_NEW_PSW+4
440	s	%r15,BASED(.Lc_spsize)
441	st	%r14,__SF_BACKCHAIN(%r15)
442	la	%r12,SP_PTREGS(%r15)
443	xc	0(__PT_SIZE,%r12),0(%r12)
444	l	%r1,BASED(.Ldo_execve)
445	lr	%r5,%r12
446	basr	%r14,%r1
447	ltr	%r2,%r2
448	be	BASED(0f)
449	a	%r15,BASED(.Lc_spsize)
450	lm	%r12,%r15,48(%r15)
451	br	%r14
452	# execve succeeded.
4530:	stnsm	__SF_EMPTY(%r15),0xfc	# disable interrupts
454	l	%r15,__LC_KERNEL_STACK	# load ksp
455	s	%r15,BASED(.Lc_spsize)	# make room for registers & psw
456	l	%r9,__LC_THREAD_INFO
457	mvc	SP_PTREGS(__PT_SIZE,%r15),0(%r12)	# copy pt_regs
458	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
459	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
460	l	%r1,BASED(.Lexecve_tail)
461	basr	%r14,%r1
462	b	BASED(sysc_return)
463
464/*
465 * Program check handler routine
466 */
467
468	.globl	pgm_check_handler
469pgm_check_handler:
470/*
471 * First we need to check for a special case:
472 * Single stepping an instruction that disables the PER event mask will
473 * cause a PER event AFTER the mask has been set. Example: SVC or LPSW.
474 * For a single stepped SVC the program check handler gets control after
475 * the SVC new PSW has been loaded. But we want to execute the SVC first and
476 * then handle the PER event. Therefore we update the SVC old PSW to point
477 * to the pgm_check_handler and branch to the SVC handler after we checked
478 * if we have to load the kernel stack register.
479 * For every other possible cause for PER event without the PER mask set
480 * we just ignore the PER event (FIXME: is there anything we have to do
481 * for LPSW?).
482 */
483	stpt	__LC_SYNC_ENTER_TIMER
484	SAVE_ALL_BASE __LC_SAVE_AREA
485	tm	__LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
486	bnz	BASED(pgm_per)		# got per exception -> special case
487	SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA
488	CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
489	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
490	bz	BASED(pgm_no_vtime)
491	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
492	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
493	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
494pgm_no_vtime:
495	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
496	TRACE_IRQS_OFF
497	l	%r3,__LC_PGM_ILC	# load program interruption code
498	la	%r8,0x7f
499	nr	%r8,%r3
500pgm_do_call:
501	l	%r7,BASED(.Ljump_table)
502	sll	%r8,2
503	l	%r7,0(%r8,%r7)		# load address of handler routine
504	la	%r2,SP_PTREGS(%r15)	# address of register-save area
505	la	%r14,BASED(sysc_return)
506	br	%r7			# branch to interrupt-handler
507
508#
509# handle per exception
510#
511pgm_per:
512	tm	__LC_PGM_OLD_PSW,0x40	# test if per event recording is on
513	bnz	BASED(pgm_per_std)	# ok, normal per event from user space
514# ok its one of the special cases, now we need to find out which one
515	clc	__LC_PGM_OLD_PSW(8),__LC_SVC_NEW_PSW
516	be	BASED(pgm_svcper)
517# no interesting special case, ignore PER event
518	lm	%r12,%r15,__LC_SAVE_AREA
519	lpsw	0x28
520
521#
522# Normal per exception
523#
524pgm_per_std:
525	SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA
526	CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
527	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
528	bz	BASED(pgm_no_vtime2)
529	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
530	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
531	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
532pgm_no_vtime2:
533	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
534	TRACE_IRQS_OFF
535	l	%r1,__TI_task(%r9)
536	mvc	__THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID
537	mvc	__THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS
538	mvc	__THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
539	oi	__TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
540	tm	SP_PSW+1(%r15),0x01	# kernel per event ?
541	bz	BASED(kernel_per)
542	l	%r3,__LC_PGM_ILC	# load program interruption code
543	la	%r8,0x7f
544	nr	%r8,%r3 		# clear per-event-bit and ilc
545	be	BASED(sysc_return)	# only per or per+check ?
546	b	BASED(pgm_do_call)
547
548#
549# it was a single stepped SVC that is causing all the trouble
550#
551pgm_svcper:
552	SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
553	CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
554	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
555	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
556	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
557	lh	%r7,0x8a		# get svc number from lowcore
558	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
559	TRACE_IRQS_OFF
560	l	%r1,__TI_task(%r9)
561	mvc	__THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID
562	mvc	__THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS
563	mvc	__THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
564	oi	__TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
565	TRACE_IRQS_ON
566	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
567	b	BASED(sysc_do_svc)
568
569#
570# per was called from kernel, must be kprobes
571#
572kernel_per:
573	mvi	SP_SVCNR(%r15),0xff	# set trap indication to pgm check
574	mvi	SP_SVCNR+1(%r15),0xff
575	la	%r2,SP_PTREGS(%r15)	# address of register-save area
576	l	%r1,BASED(.Lhandle_per)	# load adr. of per handler
577	la	%r14,BASED(sysc_restore)# load adr. of system return
578	br	%r1			# branch to do_single_step
579
580/*
581 * IO interrupt handler routine
582 */
583
584	.globl io_int_handler
585io_int_handler:
586	stck	__LC_INT_CLOCK
587	stpt	__LC_ASYNC_ENTER_TIMER
588	SAVE_ALL_BASE __LC_SAVE_AREA+16
589	SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+16
590	CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+16
591	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
592	bz	BASED(io_no_vtime)
593	UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
594	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
595	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
596io_no_vtime:
597	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
598	TRACE_IRQS_OFF
599	l	%r1,BASED(.Ldo_IRQ)	# load address of do_IRQ
600	la	%r2,SP_PTREGS(%r15)	# address of register-save area
601	basr	%r14,%r1		# branch to standard irq handler
602io_return:
603	tm	__TI_flags+3(%r9),_TIF_WORK_INT
604	bnz	BASED(io_work)		# there is work to do (signals etc.)
605io_restore:
606#ifdef CONFIG_TRACE_IRQFLAGS
607	la	%r1,BASED(io_restore_trace_psw)
608	lpsw	0(%r1)
609io_restore_trace:
610	TRACE_IRQS_CHECK
611	LOCKDEP_SYS_EXIT
612#endif
613io_leave:
614	RESTORE_ALL __LC_RETURN_PSW,0
615io_done:
616
617#ifdef CONFIG_TRACE_IRQFLAGS
618	.align	8
619	.globl	io_restore_trace_psw
620io_restore_trace_psw:
621	.long	0, io_restore_trace + 0x80000000
622#endif
623
624#
625# switch to kernel stack, then check the TIF bits
626#
627io_work:
628	tm	SP_PSW+1(%r15),0x01	# returning to user ?
629#ifndef CONFIG_PREEMPT
630	bno	BASED(io_restore)	# no-> skip resched & signal
631#else
632	bnz	BASED(io_work_user)	# no -> check for preemptive scheduling
633	# check for preemptive scheduling
634	icm	%r0,15,__TI_precount(%r9)
635	bnz	BASED(io_restore)	# preemption disabled
636	l	%r1,SP_R15(%r15)
637	s	%r1,BASED(.Lc_spsize)
638	mvc	SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
639	xc	__SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
640	lr	%r15,%r1
641io_resume_loop:
642	tm	__TI_flags+3(%r9),_TIF_NEED_RESCHED
643	bno	BASED(io_restore)
644	l	%r1,BASED(.Lpreempt_schedule_irq)
645	la	%r14,BASED(io_resume_loop)
646	br	%r1			# call schedule
647#endif
648
649io_work_user:
650	l	%r1,__LC_KERNEL_STACK
651	s	%r1,BASED(.Lc_spsize)
652	mvc	SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
653	xc	__SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
654	lr	%r15,%r1
655#
656# One of the work bits is on. Find out which one.
657# Checked are: _TIF_SIGPENDING, _TIF_NEED_RESCHED
658#		and _TIF_MCCK_PENDING
659#
660io_work_loop:
661	tm	__TI_flags+3(%r9),_TIF_MCCK_PENDING
662	bo	BASED(io_mcck_pending)
663	tm	__TI_flags+3(%r9),_TIF_NEED_RESCHED
664	bo	BASED(io_reschedule)
665	tm	__TI_flags+3(%r9),_TIF_SIGPENDING
666	bnz	BASED(io_sigpending)
667	tm	__TI_flags+3(%r9),_TIF_NOTIFY_RESUME
668	bnz	BASED(io_notify_resume)
669	b	BASED(io_restore)
670io_work_done:
671
672#
673# _TIF_MCCK_PENDING is set, call handler
674#
675io_mcck_pending:
676	l	%r1,BASED(.Ls390_handle_mcck)
677	basr	%r14,%r1		# TIF bit will be cleared by handler
678	b	BASED(io_work_loop)
679
680#
681# _TIF_NEED_RESCHED is set, call schedule
682#
683io_reschedule:
684	TRACE_IRQS_ON
685	l	%r1,BASED(.Lschedule)
686	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
687	basr	%r14,%r1		# call scheduler
688	stnsm	__SF_EMPTY(%r15),0xfc	# disable I/O and ext. interrupts
689	TRACE_IRQS_OFF
690	tm	__TI_flags+3(%r9),_TIF_WORK_INT
691	bz	BASED(io_restore)	# there is no work to do
692	b	BASED(io_work_loop)
693
694#
695# _TIF_SIGPENDING is set, call do_signal
696#
697io_sigpending:
698	TRACE_IRQS_ON
699	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
700	la	%r2,SP_PTREGS(%r15)	# load pt_regs
701	l	%r1,BASED(.Ldo_signal)
702	basr	%r14,%r1		# call do_signal
703	stnsm	__SF_EMPTY(%r15),0xfc	# disable I/O and ext. interrupts
704	TRACE_IRQS_OFF
705	b	BASED(io_work_loop)
706
707#
708# _TIF_SIGPENDING is set, call do_signal
709#
710io_notify_resume:
711	TRACE_IRQS_ON
712	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
713	la	%r2,SP_PTREGS(%r15)	# load pt_regs
714	l	%r1,BASED(.Ldo_notify_resume)
715	basr	%r14,%r1		# call do_signal
716	stnsm	__SF_EMPTY(%r15),0xfc	# disable I/O and ext. interrupts
717	TRACE_IRQS_OFF
718	b	BASED(io_work_loop)
719
720/*
721 * External interrupt handler routine
722 */
723
724	.globl	ext_int_handler
725ext_int_handler:
726	stck	__LC_INT_CLOCK
727	stpt	__LC_ASYNC_ENTER_TIMER
728	SAVE_ALL_BASE __LC_SAVE_AREA+16
729	SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16
730	CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16
731	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
732	bz	BASED(ext_no_vtime)
733	UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
734	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
735	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
736ext_no_vtime:
737	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
738	TRACE_IRQS_OFF
739	la	%r2,SP_PTREGS(%r15)	# address of register-save area
740	lh	%r3,__LC_EXT_INT_CODE	# get interruption code
741	l	%r1,BASED(.Ldo_extint)
742	basr	%r14,%r1
743	b	BASED(io_return)
744
745__critical_end:
746
747/*
748 * Machine check handler routines
749 */
750
751	.globl mcck_int_handler
752mcck_int_handler:
753	stck	__LC_INT_CLOCK
754	spt	__LC_CPU_TIMER_SAVE_AREA	# revalidate cpu timer
755	lm	%r0,%r15,__LC_GPREGS_SAVE_AREA	# revalidate gprs
756	SAVE_ALL_BASE __LC_SAVE_AREA+32
757	la	%r12,__LC_MCK_OLD_PSW
758	tm	__LC_MCCK_CODE,0x80	# system damage?
759	bo	BASED(mcck_int_main)	# yes -> rest of mcck code invalid
760	mvc	__LC_SAVE_AREA+52(8),__LC_ASYNC_ENTER_TIMER
761	mvc	__LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA
762	tm	__LC_MCCK_CODE+5,0x02	# stored cpu timer value valid?
763	bo	BASED(1f)
764	la	%r14,__LC_SYNC_ENTER_TIMER
765	clc	0(8,%r14),__LC_ASYNC_ENTER_TIMER
766	bl	BASED(0f)
767	la	%r14,__LC_ASYNC_ENTER_TIMER
7680:	clc	0(8,%r14),__LC_EXIT_TIMER
769	bl	BASED(0f)
770	la	%r14,__LC_EXIT_TIMER
7710:	clc	0(8,%r14),__LC_LAST_UPDATE_TIMER
772	bl	BASED(0f)
773	la	%r14,__LC_LAST_UPDATE_TIMER
7740:	spt	0(%r14)
775	mvc	__LC_ASYNC_ENTER_TIMER(8),0(%r14)
7761:	tm	__LC_MCCK_CODE+2,0x09	# mwp + ia of old psw valid?
777	bno	BASED(mcck_int_main)	# no -> skip cleanup critical
778	tm	__LC_MCK_OLD_PSW+1,0x01	# test problem state bit
779	bnz	BASED(mcck_int_main)	# from user -> load async stack
780	clc	__LC_MCK_OLD_PSW+4(4),BASED(.Lcritical_end)
781	bhe	BASED(mcck_int_main)
782	clc	__LC_MCK_OLD_PSW+4(4),BASED(.Lcritical_start)
783	bl	BASED(mcck_int_main)
784	l	%r14,BASED(.Lcleanup_critical)
785	basr	%r14,%r14
786mcck_int_main:
787	l	%r14,__LC_PANIC_STACK	# are we already on the panic stack?
788	slr	%r14,%r15
789	sra	%r14,PAGE_SHIFT
790	be	BASED(0f)
791	l	%r15,__LC_PANIC_STACK	# load panic stack
7920:	CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+32
793	tm	__LC_MCCK_CODE+2,0x08	# mwp of old psw valid?
794	bno	BASED(mcck_no_vtime)	# no -> skip cleanup critical
795	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
796	bz	BASED(mcck_no_vtime)
797	UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
798	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
799	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
800mcck_no_vtime:
801	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
802	la	%r2,SP_PTREGS(%r15)	# load pt_regs
803	l	%r1,BASED(.Ls390_mcck)
804	basr	%r14,%r1		# call machine check handler
805	tm	SP_PSW+1(%r15),0x01	# returning to user ?
806	bno	BASED(mcck_return)
807	l	%r1,__LC_KERNEL_STACK	# switch to kernel stack
808	s	%r1,BASED(.Lc_spsize)
809	mvc	SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
810	xc	__SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
811	lr	%r15,%r1
812	stosm	__SF_EMPTY(%r15),0x04	# turn dat on
813	tm	__TI_flags+3(%r9),_TIF_MCCK_PENDING
814	bno	BASED(mcck_return)
815	TRACE_IRQS_OFF
816	l	%r1,BASED(.Ls390_handle_mcck)
817	basr	%r14,%r1		# call machine check handler
818	TRACE_IRQS_ON
819mcck_return:
820	mvc	__LC_RETURN_MCCK_PSW(8),SP_PSW(%r15) # move return PSW
821	ni	__LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit
822	mvc	__LC_ASYNC_ENTER_TIMER(8),__LC_SAVE_AREA+52
823	tm	__LC_RETURN_MCCK_PSW+1,0x01 # returning to user ?
824	bno	BASED(0f)
825	lm	%r0,%r15,SP_R0(%r15)	# load gprs 0-15
826	stpt	__LC_EXIT_TIMER
827	lpsw	__LC_RETURN_MCCK_PSW	# back to caller
8280:	lm	%r0,%r15,SP_R0(%r15)	# load gprs 0-15
829	lpsw	__LC_RETURN_MCCK_PSW	# back to caller
830
831	RESTORE_ALL __LC_RETURN_MCCK_PSW,0
832
833/*
834 * Restart interruption handler, kick starter for additional CPUs
835 */
836#ifdef CONFIG_SMP
837	__CPUINIT
838	.globl restart_int_handler
839restart_int_handler:
840	basr	%r1,0
841restart_base:
842	spt	restart_vtime-restart_base(%r1)
843	stck	__LC_LAST_UPDATE_CLOCK
844	mvc	__LC_LAST_UPDATE_TIMER(8),restart_vtime-restart_base(%r1)
845	mvc	__LC_EXIT_TIMER(8),restart_vtime-restart_base(%r1)
846	l	%r15,__LC_SAVE_AREA+60	# load ksp
847	lctl	%c0,%c15,__LC_CREGS_SAVE_AREA # get new ctl regs
848	lam	%a0,%a15,__LC_AREGS_SAVE_AREA
849	lm	%r6,%r15,__SF_GPRS(%r15) # load registers from clone
850	l	%r1,__LC_THREAD_INFO
851	mvc	__LC_USER_TIMER(8),__TI_user_timer(%r1)
852	mvc	__LC_SYSTEM_TIMER(8),__TI_system_timer(%r1)
853	xc	__LC_STEAL_TIMER(8),__LC_STEAL_TIMER
854	stosm	__SF_EMPTY(%r15),0x04	# now we can turn dat on
855	basr	%r14,0
856	l	%r14,restart_addr-.(%r14)
857	br	%r14			# branch to start_secondary
858restart_addr:
859	.long	start_secondary
860	.align	8
861restart_vtime:
862	.long	0x7fffffff,0xffffffff
863	.previous
864#else
865/*
866 * If we do not run with SMP enabled, let the new CPU crash ...
867 */
868	.globl restart_int_handler
869restart_int_handler:
870	basr	%r1,0
871restart_base:
872	lpsw	restart_crash-restart_base(%r1)
873	.align	8
874restart_crash:
875	.long	0x000a0000,0x00000000
876restart_go:
877#endif
878
879#ifdef CONFIG_CHECK_STACK
880/*
881 * The synchronous or the asynchronous stack overflowed. We are dead.
882 * No need to properly save the registers, we are going to panic anyway.
883 * Setup a pt_regs so that show_trace can provide a good call trace.
884 */
885stack_overflow:
886	l	%r15,__LC_PANIC_STACK	# change to panic stack
887	sl	%r15,BASED(.Lc_spsize)
888	mvc	SP_PSW(8,%r15),0(%r12)	# move user PSW to stack
889	stm	%r0,%r11,SP_R0(%r15)	# store gprs %r0-%r11 to kernel stack
890	la	%r1,__LC_SAVE_AREA
891	ch	%r12,BASED(.L0x020)	# old psw addr == __LC_SVC_OLD_PSW ?
892	be	BASED(0f)
893	ch	%r12,BASED(.L0x028)	# old psw addr == __LC_PGM_OLD_PSW ?
894	be	BASED(0f)
895	la	%r1,__LC_SAVE_AREA+16
8960:	mvc	SP_R12(16,%r15),0(%r1)	# move %r12-%r15 to stack
897	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear back chain
898	l	%r1,BASED(1f)		# branch to kernel_stack_overflow
899	la	%r2,SP_PTREGS(%r15)	# load pt_regs
900	br	%r1
9011:	.long	kernel_stack_overflow
902#endif
903
904cleanup_table_system_call:
905	.long	system_call + 0x80000000, sysc_do_svc + 0x80000000
906cleanup_table_sysc_return:
907	.long	sysc_return + 0x80000000, sysc_leave + 0x80000000
908cleanup_table_sysc_leave:
909	.long	sysc_leave + 0x80000000, sysc_done + 0x80000000
910cleanup_table_sysc_work_loop:
911	.long	sysc_work_loop + 0x80000000, sysc_work_done + 0x80000000
912cleanup_table_io_return:
913	.long	io_return + 0x80000000, io_leave + 0x80000000
914cleanup_table_io_leave:
915	.long	io_leave + 0x80000000, io_done + 0x80000000
916cleanup_table_io_work_loop:
917	.long	io_work_loop + 0x80000000, io_work_done + 0x80000000
918
919cleanup_critical:
920	clc	4(4,%r12),BASED(cleanup_table_system_call)
921	bl	BASED(0f)
922	clc	4(4,%r12),BASED(cleanup_table_system_call+4)
923	bl	BASED(cleanup_system_call)
9240:
925	clc	4(4,%r12),BASED(cleanup_table_sysc_return)
926	bl	BASED(0f)
927	clc	4(4,%r12),BASED(cleanup_table_sysc_return+4)
928	bl	BASED(cleanup_sysc_return)
9290:
930	clc	4(4,%r12),BASED(cleanup_table_sysc_leave)
931	bl	BASED(0f)
932	clc	4(4,%r12),BASED(cleanup_table_sysc_leave+4)
933	bl	BASED(cleanup_sysc_leave)
9340:
935	clc	4(4,%r12),BASED(cleanup_table_sysc_work_loop)
936	bl	BASED(0f)
937	clc	4(4,%r12),BASED(cleanup_table_sysc_work_loop+4)
938	bl	BASED(cleanup_sysc_return)
9390:
940	clc	4(4,%r12),BASED(cleanup_table_io_return)
941	bl	BASED(0f)
942	clc	4(4,%r12),BASED(cleanup_table_io_return+4)
943	bl	BASED(cleanup_io_return)
9440:
945	clc	4(4,%r12),BASED(cleanup_table_io_leave)
946	bl	BASED(0f)
947	clc	4(4,%r12),BASED(cleanup_table_io_leave+4)
948	bl	BASED(cleanup_io_leave)
9490:
950	clc	4(4,%r12),BASED(cleanup_table_io_work_loop)
951	bl	BASED(0f)
952	clc	4(4,%r12),BASED(cleanup_table_io_work_loop+4)
953	bl	BASED(cleanup_io_return)
9540:
955	br	%r14
956
957cleanup_system_call:
958	mvc	__LC_RETURN_PSW(8),0(%r12)
959	c	%r12,BASED(.Lmck_old_psw)
960	be	BASED(0f)
961	la	%r12,__LC_SAVE_AREA+16
962	b	BASED(1f)
9630:	la	%r12,__LC_SAVE_AREA+32
9641:
965	clc	__LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+4)
966	bh	BASED(0f)
967	mvc	__LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER
9680:	clc	__LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+8)
969	bhe	BASED(cleanup_vtime)
970	clc	__LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn)
971	bh	BASED(0f)
972	mvc	__LC_SAVE_AREA(16),0(%r12)
9730:	st	%r13,4(%r12)
974	st	%r12,__LC_SAVE_AREA+48	# argh
975	SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
976	CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
977	l	%r12,__LC_SAVE_AREA+48	# argh
978	st	%r15,12(%r12)
979	lh	%r7,0x8a
980cleanup_vtime:
981	clc	__LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+12)
982	bhe	BASED(cleanup_stime)
983	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
984cleanup_stime:
985	clc	__LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+16)
986	bh	BASED(cleanup_update)
987	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
988cleanup_update:
989	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
990	mvc	__LC_RETURN_PSW+4(4),BASED(cleanup_table_system_call+4)
991	la	%r12,__LC_RETURN_PSW
992	br	%r14
993cleanup_system_call_insn:
994	.long	sysc_saveall + 0x80000000
995	.long	system_call + 0x80000000
996	.long	sysc_vtime + 0x80000000
997	.long	sysc_stime + 0x80000000
998	.long	sysc_update + 0x80000000
999
1000cleanup_sysc_return:
1001	mvc	__LC_RETURN_PSW(4),0(%r12)
1002	mvc	__LC_RETURN_PSW+4(4),BASED(cleanup_table_sysc_return)
1003	la	%r12,__LC_RETURN_PSW
1004	br	%r14
1005
1006cleanup_sysc_leave:
1007	clc	4(4,%r12),BASED(cleanup_sysc_leave_insn)
1008	be	BASED(2f)
1009	mvc	__LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
1010	clc	4(4,%r12),BASED(cleanup_sysc_leave_insn+4)
1011	be	BASED(2f)
1012	mvc	__LC_RETURN_PSW(8),SP_PSW(%r15)
1013	c	%r12,BASED(.Lmck_old_psw)
1014	bne	BASED(0f)
1015	mvc	__LC_SAVE_AREA+32(16),SP_R12(%r15)
1016	b	BASED(1f)
10170:	mvc	__LC_SAVE_AREA+16(16),SP_R12(%r15)
10181:	lm	%r0,%r11,SP_R0(%r15)
1019	l	%r15,SP_R15(%r15)
10202:	la	%r12,__LC_RETURN_PSW
1021	br	%r14
1022cleanup_sysc_leave_insn:
1023	.long	sysc_done - 4 + 0x80000000
1024	.long	sysc_done - 8 + 0x80000000
1025
1026cleanup_io_return:
1027	mvc	__LC_RETURN_PSW(4),0(%r12)
1028	mvc	__LC_RETURN_PSW+4(4),BASED(cleanup_table_io_work_loop)
1029	la	%r12,__LC_RETURN_PSW
1030	br	%r14
1031
1032cleanup_io_leave:
1033	clc	4(4,%r12),BASED(cleanup_io_leave_insn)
1034	be	BASED(2f)
1035	mvc	__LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
1036	clc	4(4,%r12),BASED(cleanup_io_leave_insn+4)
1037	be	BASED(2f)
1038	mvc	__LC_RETURN_PSW(8),SP_PSW(%r15)
1039	c	%r12,BASED(.Lmck_old_psw)
1040	bne	BASED(0f)
1041	mvc	__LC_SAVE_AREA+32(16),SP_R12(%r15)
1042	b	BASED(1f)
10430:	mvc	__LC_SAVE_AREA+16(16),SP_R12(%r15)
10441:	lm	%r0,%r11,SP_R0(%r15)
1045	l	%r15,SP_R15(%r15)
10462:	la	%r12,__LC_RETURN_PSW
1047	br	%r14
1048cleanup_io_leave_insn:
1049	.long	io_done - 4 + 0x80000000
1050	.long	io_done - 8 + 0x80000000
1051
1052/*
1053 * Integer constants
1054 */
1055		.align	4
1056.Lc_spsize:	.long	SP_SIZE
1057.Lc_overhead:	.long	STACK_FRAME_OVERHEAD
1058.Lnr_syscalls:	.long	NR_syscalls
1059.L0x018:	.short	0x018
1060.L0x020:	.short	0x020
1061.L0x028:	.short	0x028
1062.L0x030:	.short	0x030
1063.L0x038:	.short	0x038
1064.Lc_1:		.long	1
1065
1066/*
1067 * Symbol constants
1068 */
1069.Ls390_mcck:	.long	s390_do_machine_check
1070.Ls390_handle_mcck:
1071		.long	s390_handle_mcck
1072.Lmck_old_psw:	.long	__LC_MCK_OLD_PSW
1073.Ldo_IRQ:	.long	do_IRQ
1074.Ldo_extint:	.long	do_extint
1075.Ldo_signal:	.long	do_signal
1076.Ldo_notify_resume:
1077		.long	do_notify_resume
1078.Lhandle_per:	.long	do_single_step
1079.Ldo_execve:	.long	do_execve
1080.Lexecve_tail:	.long	execve_tail
1081.Ljump_table:	.long	pgm_check_table
1082.Lschedule:	.long	schedule
1083#ifdef CONFIG_PREEMPT
1084.Lpreempt_schedule_irq:
1085		.long	preempt_schedule_irq
1086#endif
1087.Ltrace_entry:	.long	do_syscall_trace_enter
1088.Ltrace_exit:	.long	do_syscall_trace_exit
1089.Lschedtail:	.long	schedule_tail
1090.Lsysc_table:	.long	sys_call_table
1091#ifdef CONFIG_TRACE_IRQFLAGS
1092.Ltrace_irq_on_caller:
1093		.long	trace_hardirqs_on_caller
1094.Ltrace_irq_off_caller:
1095		.long	trace_hardirqs_off_caller
1096#endif
1097#ifdef CONFIG_LOCKDEP
1098.Llockdep_sys_exit:
1099		.long	lockdep_sys_exit
1100#endif
1101.Lcritical_start:
1102		.long	__critical_start + 0x80000000
1103.Lcritical_end:
1104		.long	__critical_end + 0x80000000
1105.Lcleanup_critical:
1106		.long	cleanup_critical
1107
1108		.section .rodata, "a"
1109#define SYSCALL(esa,esame,emu)	.long esa
1110sys_call_table:
1111#include "syscalls.S"
1112#undef SYSCALL
1113