entry.S 25.9 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3
/*
 *    S390 low-level entry points.
 *
4
 *    Copyright IBM Corp. 1999, 2012
L
Linus Torvalds 已提交
5
 *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
H
Heiko Carstens 已提交
6 7
 *		 Hartmut Penner (hp@de.ibm.com),
 *		 Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
8
 *		 Heiko Carstens <heiko.carstens@de.ibm.com>
L
Linus Torvalds 已提交
9 10
 */

11
#include <linux/init.h>
12
#include <linux/linkage.h>
L
Linus Torvalds 已提交
13 14 15 16
#include <asm/cache.h>
#include <asm/errno.h>
#include <asm/ptrace.h>
#include <asm/thread_info.h>
17
#include <asm/asm-offsets.h>
L
Linus Torvalds 已提交
18 19
#include <asm/unistd.h>
#include <asm/page.h>
20
#include <asm/sigp.h>
21
#include <asm/irq.h>
L
Linus Torvalds 已提交
22

23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
__PT_R0      =	__PT_GPRS
__PT_R1      =	__PT_GPRS + 4
__PT_R2      =	__PT_GPRS + 8
__PT_R3      =	__PT_GPRS + 12
__PT_R4      =	__PT_GPRS + 16
__PT_R5      =	__PT_GPRS + 20
__PT_R6      =	__PT_GPRS + 24
__PT_R7      =	__PT_GPRS + 28
__PT_R8      =	__PT_GPRS + 32
__PT_R9      =	__PT_GPRS + 36
__PT_R10     =	__PT_GPRS + 40
__PT_R11     =	__PT_GPRS + 44
__PT_R12     =	__PT_GPRS + 48
__PT_R13     =	__PT_GPRS + 524
__PT_R14     =	__PT_GPRS + 56
__PT_R15     =	__PT_GPRS + 60
L
Linus Torvalds 已提交
39

M
Martin Schwidefsky 已提交
40
_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
41
		 _TIF_MCCK_PENDING | _TIF_PER_TRAP | _TIF_ASCE)
M
Martin Schwidefsky 已提交
42
_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
43
		 _TIF_MCCK_PENDING | _TIF_ASCE)
44 45
_TIF_TRACE    = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \
		 _TIF_SYSCALL_TRACEPOINT)
46
_TIF_TRANSFER = (_TIF_MCCK_PENDING | _TIF_TLB_WAIT)
L
Linus Torvalds 已提交
47 48 49

STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
STACK_SIZE  = 1 << STACK_SHIFT
50
STACK_INIT  = STACK_SIZE - STACK_FRAME_OVERHEAD - __PT_SIZE
L
Linus Torvalds 已提交
51 52 53

#define BASED(name) name-system_call(%r13)

54
	.macro	TRACE_IRQS_ON
55
#ifdef CONFIG_TRACE_IRQFLAGS
56
	basr	%r2,%r0
57 58 59
	l	%r1,BASED(.Lhardirqs_on)
	basr	%r14,%r1		# call trace_hardirqs_on_caller
#endif
60 61 62
	.endm

	.macro	TRACE_IRQS_OFF
63
#ifdef CONFIG_TRACE_IRQFLAGS
64
	basr	%r2,%r0
65 66
	l	%r1,BASED(.Lhardirqs_off)
	basr	%r14,%r1		# call trace_hardirqs_off_caller
67
#endif
68
	.endm
69 70

	.macro	LOCKDEP_SYS_EXIT
71 72 73
#ifdef CONFIG_LOCKDEP
	tm	__PT_PSW+1(%r11),0x01	# returning to user ?
	jz	.+10
74
	l	%r1,BASED(.Llockdep_sys_exit)
75
	basr	%r14,%r1		# call lockdep_sys_exit
76
#endif
77 78
	.endm

79
	.macro	CHECK_STACK stacksize,savearea
80
#ifdef CONFIG_CHECK_STACK
81 82 83
	tml	%r15,\stacksize - CONFIG_STACK_GUARD
	la	%r14,\savearea
	jz	stack_overflow
84 85 86
#endif
	.endm

87 88 89 90 91 92 93 94 95 96 97 98
	.macro	SWITCH_ASYNC savearea,stack,shift
	tmh	%r8,0x0001		# interrupting from user ?
	jnz	1f
	lr	%r14,%r9
	sl	%r14,BASED(.Lcritical_start)
	cl	%r14,BASED(.Lcritical_length)
	jhe	0f
	la	%r11,\savearea		# inside critical section, do cleanup
	bras	%r14,cleanup_critical
	tmh	%r8,0x0001		# retest problem state after cleanup
	jnz	1f
0:	l	%r14,\stack		# are we already on the target stack?
L
Linus Torvalds 已提交
99
	slr	%r14,%r15
100 101 102
	sra	%r14,\shift
	jnz	1f
	CHECK_STACK 1<<\shift,\savearea
103
	ahi	%r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
104 105
	j	2f
1:	l	%r15,\stack		# load target stack
106
2:	la	%r11,STACK_FRAME_OVERHEAD(%r15)
107 108
	.endm

109 110
	.macro	ADD64 high,low,timer
	al	\high,\timer
M
Martin Schwidefsky 已提交
111
	al	\low,4+\timer
112 113
	brc	12,.+8
	ahi	\high,1
L
Linus Torvalds 已提交
114 115
	.endm

116 117
	.macro	SUB64 high,low,timer
	sl	\high,\timer
M
Martin Schwidefsky 已提交
118
	sl	\low,4+\timer
119 120 121 122 123 124 125 126 127 128 129 130 131 132
	brc	3,.+8
	ahi	\high,-1
	.endm

	.macro	UPDATE_VTIME high,low,enter_timer
	lm	\high,\low,__LC_EXIT_TIMER
	SUB64	\high,\low,\enter_timer
	ADD64	\high,\low,__LC_USER_TIMER
	stm	\high,\low,__LC_USER_TIMER
	lm	\high,\low,__LC_LAST_UPDATE_TIMER
	SUB64	\high,\low,__LC_EXIT_TIMER
	ADD64	\high,\low,__LC_SYSTEM_TIMER
	stm	\high,\low,__LC_SYSTEM_TIMER
	mvc	__LC_LAST_UPDATE_TIMER(8),\enter_timer
L
Linus Torvalds 已提交
133 134
	.endm

135
	.macro REENABLE_IRQS
136 137 138
	st	%r8,__LC_RETURN_PSW
	ni	__LC_RETURN_PSW,0xbf
	ssm	__LC_RETURN_PSW
139 140
	.endm

141 142
	.section .kprobes.text, "ax"

L
Linus Torvalds 已提交
143 144 145 146 147 148 149
/*
 * Scheduler resume function, called by switch_to
 *  gpr2 = (task_struct *) prev
 *  gpr3 = (task_struct *) next
 * Returns:
 *  gpr2 = prev
 */
150
ENTRY(__switch_to)
151 152
	stm	%r6,%r15,__SF_GPRS(%r15)	# store gprs of prev task
	st	%r15,__THREAD_ksp(%r2)		# store kernel stack of prev
153
	l	%r4,__THREAD_info(%r2)		# get thread_info of prev
M
Martin Schwidefsky 已提交
154
	l	%r5,__THREAD_info(%r3)		# get thread_info of next
155
	lr	%r15,%r5
156
	ahi	%r15,STACK_INIT			# end of kernel stack of next
157 158 159 160 161 162
	st	%r3,__LC_CURRENT		# store task struct of next
	st	%r5,__LC_THREAD_INFO		# store thread info of next
	st	%r15,__LC_KERNEL_STACK		# store end of kernel stack
	lctl	%c4,%c4,__TASK_pid(%r3)		# load pid to control reg. 4
	mvc	__LC_CURRENT_PID(4,%r0),__TASK_pid(%r3)	# store pid of next
	l	%r15,__THREAD_ksp(%r3)		# load kernel stack of next
163 164
	lhi	%r6,_TIF_TRANSFER		# transfer TIF bits
	n	%r6,__TI_flags(%r4)		# isolate TIF bits
165
	jz	0f
166 167 168
	o	%r6,__TI_flags(%r5)		# set TIF bits of next
	st	%r6,__TI_flags(%r5)
	ni	__TI_flags+3(%r4),255-_TIF_TRANSFER # clear TIF bits of prev
169
0:	lm	%r6,%r15,__SF_GPRS(%r15)	# load gprs of next task
L
Linus Torvalds 已提交
170 171 172 173 174 175 176 177
	br	%r14

__critical_start:
/*
 * SVC interrupt handler routine. System calls are synchronous events and
 * are executed with interrupts enabled.
 */

178
ENTRY(system_call)
M
Martin Schwidefsky 已提交
179
	stpt	__LC_SYNC_ENTER_TIMER
180 181 182 183 184 185 186
sysc_stm:
	stm	%r8,%r15,__LC_SAVE_AREA_SYNC
	l	%r12,__LC_THREAD_INFO
	l	%r13,__LC_SVC_NEW_PSW+4
sysc_per:
	l	%r15,__LC_KERNEL_STACK
	la	%r11,STACK_FRAME_OVERHEAD(%r15)	# pointer to pt_regs
L
Linus Torvalds 已提交
187
sysc_vtime:
188 189 190 191
	UPDATE_VTIME %r8,%r9,__LC_SYNC_ENTER_TIMER
	stm	%r0,%r7,__PT_R0(%r11)
	mvc	__PT_R8(32,%r11),__LC_SAVE_AREA_SYNC
	mvc	__PT_PSW(8,%r11),__LC_SVC_OLD_PSW
M
Martin Schwidefsky 已提交
192
	mvc	__PT_INT_CODE(4,%r11),__LC_SVC_ILC
L
Linus Torvalds 已提交
193
sysc_do_svc:
194
	oi	__TI_flags+3(%r12),_TIF_SYSCALL
195
	l	%r10,__TI_sysc_table(%r12)	# 31 bit system call table
M
Martin Schwidefsky 已提交
196
	lh	%r8,__PT_INT_CODE+2(%r11)
197 198
	sla	%r8,2				# shift and test for svc0
	jnz	sysc_nr_ok
L
Linus Torvalds 已提交
199 200
	# svc 0: system call number in %r1
	cl	%r1,BASED(.Lnr_syscalls)
201
	jnl	sysc_nr_ok
M
Martin Schwidefsky 已提交
202
	sth	%r1,__PT_INT_CODE+2(%r11)
203 204
	lr	%r8,%r1
	sla	%r8,2
L
Linus Torvalds 已提交
205
sysc_nr_ok:
206 207 208 209
	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
	st	%r2,__PT_ORIG_GPR2(%r11)
	st	%r7,STACK_FRAME_OVERHEAD(%r15)
	l	%r9,0(%r8,%r10)			# get system call addr.
210
	tm	__TI_flags+2(%r12),_TIF_TRACE >> 8
211 212 213
	jnz	sysc_tracesys
	basr	%r14,%r9			# call sys_xxxx
	st	%r2,__PT_R2(%r11)		# store return value
L
Linus Torvalds 已提交
214 215

sysc_return:
216 217
	LOCKDEP_SYS_EXIT
sysc_tif:
218 219
	tm	__PT_PSW+1(%r11),0x01		# returning to user ?
	jno	sysc_restore
220
	tm	__TI_flags+3(%r12),_TIF_WORK_SVC
221
	jnz	sysc_work			# check for work
222
	ni	__TI_flags+3(%r12),255-_TIF_SYSCALL
223
sysc_restore:
224 225 226 227
	mvc	__LC_RETURN_PSW(8),__PT_PSW(%r11)
	stpt	__LC_EXIT_TIMER
	lm	%r0,%r15,__PT_R0(%r11)
	lpsw	__LC_RETURN_PSW
228 229
sysc_done:

230 231 232
#
# One of the work bits is on. Find out which one.
#
233
sysc_work:
234
	tm	__TI_flags+3(%r12),_TIF_MCCK_PENDING
235
	jo	sysc_mcck_pending
236
	tm	__TI_flags+3(%r12),_TIF_NEED_RESCHED
237
	jo	sysc_reschedule
238 239
	tm	__TI_flags+3(%r12),_TIF_PER_TRAP
	jo	sysc_singlestep
240
	tm	__TI_flags+3(%r12),_TIF_SIGPENDING
241
	jo	sysc_sigpending
242
	tm	__TI_flags+3(%r12),_TIF_NOTIFY_RESUME
243
	jo	sysc_notify_resume
244 245
	tm	__TI_flags+3(%r12),_TIF_ASCE
	jo	sysc_uaccess
246
	j	sysc_return		# beware of critical section cleanup
L
Linus Torvalds 已提交
247 248 249

#
# _TIF_NEED_RESCHED is set, call schedule
H
Heiko Carstens 已提交
250 251 252
#
sysc_reschedule:
	l	%r1,BASED(.Lschedule)
253
	la	%r14,BASED(sysc_return)
254
	br	%r1			# call schedule
L
Linus Torvalds 已提交
255

256 257 258 259
#
# _TIF_MCCK_PENDING is set, call handler
#
sysc_mcck_pending:
260
	l	%r1,BASED(.Lhandle_mcck)
261
	la	%r14,BASED(sysc_return)
262 263
	br	%r1			# TIF bit will be cleared by handler

264 265 266 267 268 269 270 271
#
# _TIF_ASCE is set, load user space asce
#
sysc_uaccess:
	ni	__TI_flags+3(%r12),255-_TIF_ASCE
	lctl	%c1,%c1,__LC_USER_ASCE	# load primary asce
	j	sysc_return

L
Linus Torvalds 已提交
272
#
273
# _TIF_SIGPENDING is set, call do_signal
L
Linus Torvalds 已提交
274
#
H
Heiko Carstens 已提交
275
sysc_sigpending:
276
	lr	%r2,%r11		# pass pointer to pt_regs
H
Heiko Carstens 已提交
277 278
	l	%r1,BASED(.Ldo_signal)
	basr	%r14,%r1		# call do_signal
279
	tm	__TI_flags+3(%r12),_TIF_SYSCALL
280 281
	jno	sysc_return
	lm	%r2,%r7,__PT_R2(%r11)	# load svc arguments
282
	l	%r10,__TI_sysc_table(%r12)	# 31 bit system call table
283
	xr	%r8,%r8			# svc 0 returns -ENOSYS
M
Martin Schwidefsky 已提交
284
	clc	__PT_INT_CODE+2(2,%r11),BASED(.Lnr_syscalls+2)
285
	jnl	sysc_nr_ok		# invalid svc number -> do svc 0
M
Martin Schwidefsky 已提交
286
	lh	%r8,__PT_INT_CODE+2(%r11)	# load new svc number
287 288
	sla	%r8,2
	j	sysc_nr_ok		# restart svc
L
Linus Torvalds 已提交
289

M
Martin Schwidefsky 已提交
290 291 292 293
#
# _TIF_NOTIFY_RESUME is set, call do_notify_resume
#
sysc_notify_resume:
294
	lr	%r2,%r11		# pass pointer to pt_regs
M
Martin Schwidefsky 已提交
295
	l	%r1,BASED(.Ldo_notify_resume)
296
	la	%r14,BASED(sysc_return)
M
Martin Schwidefsky 已提交
297 298
	br	%r1			# call do_notify_resume

L
Linus Torvalds 已提交
299
#
M
Martin Schwidefsky 已提交
300
# _TIF_PER_TRAP is set, call do_per_trap
L
Linus Torvalds 已提交
301 302
#
sysc_singlestep:
303
	ni	__TI_flags+3(%r12),255-_TIF_PER_TRAP
304 305 306 307
	lr	%r2,%r11		# pass pointer to pt_regs
	l	%r1,BASED(.Ldo_per_trap)
	la	%r14,BASED(sysc_return)
	br	%r1			# call do_per_trap
L
Linus Torvalds 已提交
308 309

#
M
Martin Schwidefsky 已提交
310 311
# call tracehook_report_syscall_entry/tracehook_report_syscall_exit before
# and after the system call
L
Linus Torvalds 已提交
312 313
#
sysc_tracesys:
314 315
	l	%r1,BASED(.Ltrace_enter)
	lr	%r2,%r11		# pass pointer to pt_regs
L
Linus Torvalds 已提交
316
	la	%r3,0
317
	xr	%r0,%r0
M
Martin Schwidefsky 已提交
318
	icm	%r0,3,__PT_INT_CODE+2(%r11)
319 320
	st	%r0,__PT_R2(%r11)
	basr	%r14,%r1		# call do_syscall_trace_enter
M
Martin Schwidefsky 已提交
321
	cl	%r2,BASED(.Lnr_syscalls)
322 323 324 325
	jnl	sysc_tracenogo
	lr	%r8,%r2
	sll	%r8,2
	l	%r9,0(%r8,%r10)
L
Linus Torvalds 已提交
326
sysc_tracego:
327 328 329 330 331
	lm	%r3,%r7,__PT_R3(%r11)
	st	%r7,STACK_FRAME_OVERHEAD(%r15)
	l	%r2,__PT_ORIG_GPR2(%r11)
	basr	%r14,%r9		# call sys_xxx
	st	%r2,__PT_R2(%r11)	# store return value
L
Linus Torvalds 已提交
332
sysc_tracenogo:
333
	tm	__TI_flags+2(%r12),_TIF_TRACE >> 8
334
	jz	sysc_return
M
Martin Schwidefsky 已提交
335
	l	%r1,BASED(.Ltrace_exit)
336
	lr	%r2,%r11		# pass pointer to pt_regs
L
Linus Torvalds 已提交
337
	la	%r14,BASED(sysc_return)
338
	br	%r1			# call do_syscall_trace_exit
L
Linus Torvalds 已提交
339 340 341 342

#
# a new process exits the kernel with ret_from_fork
#
343
ENTRY(ret_from_fork)
344 345
	la	%r11,STACK_FRAME_OVERHEAD(%r15)
	l	%r12,__LC_THREAD_INFO
L
Linus Torvalds 已提交
346
	l	%r13,__LC_SVC_NEW_PSW+4
347 348 349 350
	l	%r1,BASED(.Lschedule_tail)
	basr	%r14,%r1		# call schedule_tail
	TRACE_IRQS_ON
	ssm	__LC_SVC_NEW_PSW	# reenable interrupts
351 352 353 354
	tm	__PT_PSW+1(%r11),0x01	# forking a kernel thread ?
	jne	sysc_tracenogo
	# it's a kernel thread
	lm	%r9,%r10,__PT_R9(%r11)	# load gprs
355 356 357
ENTRY(kernel_thread_starter)
	la	%r2,0(%r10)
	basr	%r14,%r9
358
	j	sysc_tracenogo
L
Linus Torvalds 已提交
359 360 361 362 363

/*
 * Program check handler routine
 */

364
ENTRY(pgm_check_handler)
M
Martin Schwidefsky 已提交
365
	stpt	__LC_SYNC_ENTER_TIMER
366 367 368 369 370 371 372 373 374 375 376
	stm	%r8,%r15,__LC_SAVE_AREA_SYNC
	l	%r12,__LC_THREAD_INFO
	l	%r13,__LC_SVC_NEW_PSW+4
	lm	%r8,%r9,__LC_PGM_OLD_PSW
	tmh	%r8,0x0001		# test problem state bit
	jnz	1f			# -> fault in user space
	tmh	%r8,0x4000		# PER bit set in old PSW ?
	jnz	0f			# -> enabled, can't be a double fault
	tm	__LC_PGM_ILC+3,0x80	# check for per exception
	jnz	pgm_svcper		# -> single stepped svc
0:	CHECK_STACK STACK_SIZE,__LC_SAVE_AREA_SYNC
377
	ahi	%r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
378 379 380
	j	2f
1:	UPDATE_VTIME %r14,%r15,__LC_SYNC_ENTER_TIMER
	l	%r15,__LC_KERNEL_STACK
381
2:	la	%r11,STACK_FRAME_OVERHEAD(%r15)
382 383 384
	stm	%r0,%r7,__PT_R0(%r11)
	mvc	__PT_R8(32,%r11),__LC_SAVE_AREA_SYNC
	stm	%r8,%r9,__PT_PSW(%r11)
M
Martin Schwidefsky 已提交
385 386
	mvc	__PT_INT_CODE(4,%r11),__LC_PGM_ILC
	mvc	__PT_INT_PARM_LONG(4,%r11),__LC_TRANS_EXC_CODE
387 388
	tm	__LC_PGM_ILC+3,0x80	# check for per exception
	jz	0f
389
	l	%r1,__TI_task(%r12)
390 391 392
	tmh	%r8,0x0001		# kernel per event ?
	jz	pgm_kprobe
	oi	__TI_flags+3(%r12),_TIF_PER_TRAP
M
Martin Schwidefsky 已提交
393
	mvc	__THREAD_per_address(4,%r1),__LC_PER_ADDRESS
394
	mvc	__THREAD_per_cause(2,%r1),__LC_PER_CAUSE
M
Martin Schwidefsky 已提交
395
	mvc	__THREAD_per_paid(1,%r1),__LC_PER_PAID
M
Martin Schwidefsky 已提交
396
0:	REENABLE_IRQS
397
	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
398
	l	%r1,BASED(.Ljump_table)
399
	la	%r10,0x7f
M
Martin Schwidefsky 已提交
400
	n	%r10,__PT_INT_CODE(%r11)
401 402 403 404
	je	sysc_return
	sll	%r10,2
	l	%r1,0(%r10,%r1)		# load address of handler routine
	lr	%r2,%r11		# pass pointer to pt_regs
405
	basr	%r14,%r1		# branch to interrupt-handler
406
	j	sysc_return
L
Linus Torvalds 已提交
407 408

#
409
# PER event in supervisor state, must be kprobes
L
Linus Torvalds 已提交
410
#
411 412 413 414 415 416 417
pgm_kprobe:
	REENABLE_IRQS
	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
	l	%r1,BASED(.Ldo_per_trap)
	lr	%r2,%r11		# pass pointer to pt_regs
	basr	%r14,%r1		# call do_per_trap
	j	sysc_return
L
Linus Torvalds 已提交
418

M
Michael Grundy 已提交
419
#
420
# single stepped system call
M
Michael Grundy 已提交
421
#
422 423 424 425 426
pgm_svcper:
	oi	__TI_flags+3(%r12),_TIF_PER_TRAP
	mvc	__LC_RETURN_PSW(4),__LC_SVC_NEW_PSW
	mvc	__LC_RETURN_PSW+4(4),BASED(.Lsysc_per)
	lpsw	__LC_RETURN_PSW		# branch to sysc_per and enable irqs
M
Michael Grundy 已提交
427

L
Linus Torvalds 已提交
428 429 430 431
/*
 * IO interrupt handler routine
 */

432
ENTRY(io_int_handler)
L
Linus Torvalds 已提交
433
	stck	__LC_INT_CLOCK
434
	stpt	__LC_ASYNC_ENTER_TIMER
435 436 437 438 439 440 441 442 443 444 445 446
	stm	%r8,%r15,__LC_SAVE_AREA_ASYNC
	l	%r12,__LC_THREAD_INFO
	l	%r13,__LC_SVC_NEW_PSW+4
	lm	%r8,%r9,__LC_IO_OLD_PSW
	tmh	%r8,0x0001		# interrupting from user ?
	jz	io_skip
	UPDATE_VTIME %r14,%r15,__LC_ASYNC_ENTER_TIMER
io_skip:
	SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT
	stm	%r0,%r7,__PT_R0(%r11)
	mvc	__PT_R8(32,%r11),__LC_SAVE_AREA_ASYNC
	stm	%r8,%r9,__PT_PSW(%r11)
447
	mvc	__PT_INT_CODE(12,%r11),__LC_SUBCHANNEL_ID
448
	TRACE_IRQS_OFF
449
	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
450
io_loop:
451 452
	l	%r1,BASED(.Ldo_IRQ)
	lr	%r2,%r11		# pass pointer to pt_regs
453 454 455 456 457
	lhi	%r3,IO_INTERRUPT
	tm	__PT_INT_CODE+8(%r11),0x80	# adapter interrupt ?
	jz	io_call
	lhi	%r3,THIN_INTERRUPT
io_call:
458
	basr	%r14,%r1		# call do_IRQ
459 460 461 462 463 464
	tm	__LC_MACHINE_FLAGS+2,0x10	# MACHINE_FLAG_LPAR
	jz	io_return
	tpi	0
	jz	io_return
	mvc	__PT_INT_CODE(12,%r11),__LC_SUBCHANNEL_ID
	j	io_loop
L
Linus Torvalds 已提交
465
io_return:
466 467 468
	LOCKDEP_SYS_EXIT
	TRACE_IRQS_ON
io_tif:
469
	tm	__TI_flags+3(%r12),_TIF_WORK_INT
470
	jnz	io_work			# there is work to do (signals etc.)
471
io_restore:
472 473 474 475
	mvc	__LC_RETURN_PSW(8),__PT_PSW(%r11)
	stpt	__LC_EXIT_TIMER
	lm	%r0,%r15,__PT_R0(%r11)
	lpsw	__LC_RETURN_PSW
476
io_done:
L
Linus Torvalds 已提交
477

478
#
479 480 481 482 483
# There is work todo, find out in which context we have been interrupted:
# 1) if we return to user space we can do all _TIF_WORK_INT work
# 2) if we return to kernel code and preemptive scheduling is enabled check
#    the preemption counter and if it is zero call preempt_schedule_irq
# Before any work can be done, a switch to the kernel stack is required.
484 485
#
io_work:
486 487
	tm	__PT_PSW+1(%r11),0x01	# returning to user ?
	jo	io_work_user		# yes -> do resched & signal
488
#ifdef CONFIG_PREEMPT
489
	# check for preemptive scheduling
490
	icm	%r0,15,__TI_precount(%r12)
491
	jnz	io_restore		# preemption disabled
492
	tm	__TI_flags+3(%r12),_TIF_NEED_RESCHED
493
	jno	io_restore
494
	# switch to kernel stack
495 496 497 498 499
	l	%r1,__PT_R15(%r11)
	ahi	%r1,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
	mvc	STACK_FRAME_OVERHEAD(__PT_SIZE,%r1),0(%r11)
	xc	__SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1)
	la	%r11,STACK_FRAME_OVERHEAD(%r1)
L
Linus Torvalds 已提交
500
	lr	%r15,%r1
501 502 503
	# TRACE_IRQS_ON already done at io_return, call
	# TRACE_IRQS_OFF to keep things symmetrical
	TRACE_IRQS_OFF
504
	l	%r1,BASED(.Lpreempt_irq)
505
	basr	%r14,%r1		# call preempt_schedule_irq
506
	j	io_return
507
#else
508
	j	io_restore
509
#endif
L
Linus Torvalds 已提交
510

511 512 513
#
# Need to do work before returning to userspace, switch to kernel stack
#
514
io_work_user:
L
Linus Torvalds 已提交
515
	l	%r1,__LC_KERNEL_STACK
516 517 518
	mvc	STACK_FRAME_OVERHEAD(__PT_SIZE,%r1),0(%r11)
	xc	__SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1)
	la	%r11,STACK_FRAME_OVERHEAD(%r1)
L
Linus Torvalds 已提交
519
	lr	%r15,%r1
520

L
Linus Torvalds 已提交
521 522
#
# One of the work bits is on. Find out which one.
523
# Checked are: _TIF_SIGPENDING, _TIF_NOTIFY_RESUME, _TIF_NEED_RESCHED
H
Heiko Carstens 已提交
524
#		and _TIF_MCCK_PENDING
L
Linus Torvalds 已提交
525
#
526
io_work_tif:
527
	tm	__TI_flags+3(%r12),_TIF_MCCK_PENDING
528
	jo	io_mcck_pending
529
	tm	__TI_flags+3(%r12),_TIF_NEED_RESCHED
530
	jo	io_reschedule
531
	tm	__TI_flags+3(%r12),_TIF_SIGPENDING
532
	jo	io_sigpending
533
	tm	__TI_flags+3(%r12),_TIF_NOTIFY_RESUME
534
	jo	io_notify_resume
535 536
	tm	__TI_flags+3(%r12),_TIF_ASCE
	jo	io_uaccess
537
	j	io_return		# beware of critical section cleanup
L
Linus Torvalds 已提交
538

539 540 541 542
#
# _TIF_MCCK_PENDING is set, call handler
#
io_mcck_pending:
543
	# TRACE_IRQS_ON already done at io_return
544
	l	%r1,BASED(.Lhandle_mcck)
H
Heiko Carstens 已提交
545
	basr	%r14,%r1		# TIF bit will be cleared by handler
546
	TRACE_IRQS_OFF
547
	j	io_return
548

549 550 551 552 553 554 555 556
#
# _TIF_ASCE is set, load user space asce
#
io_uaccess:
	ni	__TI_flags+3(%r12),255-_TIF_ASCE
	lctl	%c1,%c1,__LC_USER_ASCE	# load primary asce
	j	io_return

L
Linus Torvalds 已提交
557 558
#
# _TIF_NEED_RESCHED is set, call schedule
H
Heiko Carstens 已提交
559 560
#
io_reschedule:
561
	# TRACE_IRQS_ON already done at io_return
H
Heiko Carstens 已提交
562
	l	%r1,BASED(.Lschedule)
563
	ssm	__LC_SVC_NEW_PSW	# reenable interrupts
H
Heiko Carstens 已提交
564
	basr	%r14,%r1		# call scheduler
565
	ssm	__LC_PGM_NEW_PSW	# disable I/O and ext. interrupts
566
	TRACE_IRQS_OFF
567
	j	io_return
L
Linus Torvalds 已提交
568 569

#
570
# _TIF_SIGPENDING is set, call do_signal
L
Linus Torvalds 已提交
571
#
H
Heiko Carstens 已提交
572
io_sigpending:
573
	# TRACE_IRQS_ON already done at io_return
H
Heiko Carstens 已提交
574
	l	%r1,BASED(.Ldo_signal)
575 576
	ssm	__LC_SVC_NEW_PSW	# reenable interrupts
	lr	%r2,%r11		# pass pointer to pt_regs
H
Heiko Carstens 已提交
577
	basr	%r14,%r1		# call do_signal
578
	ssm	__LC_PGM_NEW_PSW	# disable I/O and ext. interrupts
579
	TRACE_IRQS_OFF
580
	j	io_return
L
Linus Torvalds 已提交
581

M
Martin Schwidefsky 已提交
582 583 584 585
#
# _TIF_SIGPENDING is set, call do_signal
#
io_notify_resume:
586
	# TRACE_IRQS_ON already done at io_return
M
Martin Schwidefsky 已提交
587
	l	%r1,BASED(.Ldo_notify_resume)
588 589 590 591
	ssm	__LC_SVC_NEW_PSW	# reenable interrupts
	lr	%r2,%r11		# pass pointer to pt_regs
	basr	%r14,%r1		# call do_notify_resume
	ssm	__LC_PGM_NEW_PSW	# disable I/O and ext. interrupts
M
Martin Schwidefsky 已提交
592
	TRACE_IRQS_OFF
593
	j	io_return
M
Martin Schwidefsky 已提交
594

L
Linus Torvalds 已提交
595 596 597 598
/*
 * External interrupt handler routine
 */

599
ENTRY(ext_int_handler)
L
Linus Torvalds 已提交
600
	stck	__LC_INT_CLOCK
601
	stpt	__LC_ASYNC_ENTER_TIMER
602 603 604 605 606 607 608 609 610 611 612 613
	stm	%r8,%r15,__LC_SAVE_AREA_ASYNC
	l	%r12,__LC_THREAD_INFO
	l	%r13,__LC_SVC_NEW_PSW+4
	lm	%r8,%r9,__LC_EXT_OLD_PSW
	tmh	%r8,0x0001		# interrupting from user ?
	jz	ext_skip
	UPDATE_VTIME %r14,%r15,__LC_ASYNC_ENTER_TIMER
ext_skip:
	SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT
	stm	%r0,%r7,__PT_R0(%r11)
	mvc	__PT_R8(32,%r11),__LC_SAVE_AREA_ASYNC
	stm	%r8,%r9,__PT_PSW(%r11)
614 615
	mvc	__PT_INT_CODE(4,%r11),__LC_EXT_CPU_ADDR
	mvc	__PT_INT_PARM(4,%r11),__LC_EXT_PARAMS
616
	TRACE_IRQS_OFF
617
	l	%r1,BASED(.Ldo_IRQ)
618
	lr	%r2,%r11		# pass pointer to pt_regs
619 620
	lhi	%r3,EXT_INTERRUPT
	basr	%r14,%r1		# call do_IRQ
621
	j	io_return
L
Linus Torvalds 已提交
622

M
Martin Schwidefsky 已提交
623 624 625 626
/*
 * Load idle PSW. The second "half" of this function is in cleanup_idle.
 */
ENTRY(psw_idle)
627
	st	%r3,__SF_EMPTY(%r15)
M
Martin Schwidefsky 已提交
628 629 630 631
	basr	%r1,0
	la	%r1,psw_idle_lpsw+4-.(%r1)
	st	%r1,__SF_EMPTY+4(%r15)
	oi	__SF_EMPTY+4(%r15),0x80
632 633
	stck	__CLOCK_IDLE_ENTER(%r2)
	stpt	__TIMER_IDLE_ENTER(%r2)
M
Martin Schwidefsky 已提交
634 635 636 637 638
psw_idle_lpsw:
	lpsw	__SF_EMPTY(%r15)
	br	%r14
psw_idle_end:

639 640
__critical_end:

L
Linus Torvalds 已提交
641 642 643 644
/*
 * Machine check handler routines
 */

645
ENTRY(mcck_int_handler)
646
	stck	__LC_MCCK_CLOCK
647 648
	spt	__LC_CPU_TIMER_SAVE_AREA	# revalidate cpu timer
	lm	%r0,%r15,__LC_GPREGS_SAVE_AREA	# revalidate gprs
649 650 651
	l	%r12,__LC_THREAD_INFO
	l	%r13,__LC_SVC_NEW_PSW+4
	lm	%r8,%r9,__LC_MCK_OLD_PSW
H
Heiko Carstens 已提交
652
	tm	__LC_MCCK_CODE,0x80	# system damage?
653 654 655
	jo	mcck_panic		# yes -> rest of mcck code invalid
	la	%r14,__LC_CPU_TIMER_SAVE_AREA
	mvc	__LC_MCCK_ENTER_TIMER(8),0(%r14)
656
	tm	__LC_MCCK_CODE+5,0x02	# stored cpu timer value valid?
657
	jo	3f
658 659
	la	%r14,__LC_SYNC_ENTER_TIMER
	clc	0(8,%r14),__LC_ASYNC_ENTER_TIMER
660
	jl	0f
661 662
	la	%r14,__LC_ASYNC_ENTER_TIMER
0:	clc	0(8,%r14),__LC_EXIT_TIMER
663
	jl	1f
664
	la	%r14,__LC_EXIT_TIMER
665 666
1:	clc	0(8,%r14),__LC_LAST_UPDATE_TIMER
	jl	2f
667
	la	%r14,__LC_LAST_UPDATE_TIMER
668
2:	spt	0(%r14)
669
	mvc	__LC_MCCK_ENTER_TIMER(8),0(%r14)
670 671 672 673 674 675 676
3:	tm	__LC_MCCK_CODE+2,0x09	# mwp + ia of old psw valid?
	jno	mcck_panic		# no -> skip cleanup critical
	tm	%r8,0x0001		# interrupting from user ?
	jz	mcck_skip
	UPDATE_VTIME %r14,%r15,__LC_MCCK_ENTER_TIMER
mcck_skip:
	SWITCH_ASYNC __LC_GPREGS_SAVE_AREA+32,__LC_PANIC_STACK,PAGE_SHIFT
677 678
	stm	%r0,%r7,__PT_R0(%r11)
	mvc	__PT_R8(32,%r11),__LC_GPREGS_SAVE_AREA+32
679 680 681 682 683 684 685
	stm	%r8,%r9,__PT_PSW(%r11)
	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
	l	%r1,BASED(.Ldo_machine_check)
	lr	%r2,%r11		# pass pointer to pt_regs
	basr	%r14,%r1		# call s390_do_machine_check
	tm	__PT_PSW+1(%r11),0x01	# returning to user ?
	jno	mcck_return
H
Heiko Carstens 已提交
686
	l	%r1,__LC_KERNEL_STACK	# switch to kernel stack
687 688 689
	mvc	STACK_FRAME_OVERHEAD(__PT_SIZE,%r1),0(%r11)
	xc	__SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1)
	la	%r11,STACK_FRAME_OVERHEAD(%r15)
690
	lr	%r15,%r1
691
	ssm	__LC_PGM_NEW_PSW	# turn dat on, keep irqs off
692
	tm	__TI_flags+3(%r12),_TIF_MCCK_PENDING
693
	jno	mcck_return
694
	TRACE_IRQS_OFF
695 696
	l	%r1,BASED(.Lhandle_mcck)
	basr	%r14,%r1		# call s390_handle_mcck
697
	TRACE_IRQS_ON
L
Linus Torvalds 已提交
698
mcck_return:
699
	mvc	__LC_RETURN_MCCK_PSW(8),__PT_PSW(%r11) # move return PSW
700
	tm	__LC_RETURN_MCCK_PSW+1,0x01 # returning to user ?
701 702
	jno	0f
	lm	%r0,%r15,__PT_R0(%r11)
703
	stpt	__LC_EXIT_TIMER
704 705 706
	lpsw	__LC_RETURN_MCCK_PSW
0:	lm	%r0,%r15,__PT_R0(%r11)
	lpsw	__LC_RETURN_MCCK_PSW
707

708 709 710 711 712 713
mcck_panic:
	l	%r14,__LC_PANIC_STACK
	slr	%r14,%r15
	sra	%r14,PAGE_SHIFT
	jz	0f
	l	%r15,__LC_PANIC_STACK
714
	j	mcck_skip
715 716
0:	ahi	%r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
	j	mcck_skip
L
Linus Torvalds 已提交
717

718 719 720
#
# PSW restart interrupt handler
#
M
Martin Schwidefsky 已提交
721
ENTRY(restart_int_handler)
722
	st	%r15,__LC_SAVE_AREA_RESTART
M
Martin Schwidefsky 已提交
723
	l	%r15,__LC_RESTART_STACK
724
	ahi	%r15,-__PT_SIZE			# create pt_regs on stack
M
Martin Schwidefsky 已提交
725
	xc	0(__PT_SIZE,%r15),0(%r15)
726 727 728
	stm	%r0,%r14,__PT_R0(%r15)
	mvc	__PT_R15(4,%r15),__LC_SAVE_AREA_RESTART
	mvc	__PT_PSW(8,%r15),__LC_RST_OLD_PSW # store restart old psw
M
Martin Schwidefsky 已提交
729 730
	ahi	%r15,-STACK_FRAME_OVERHEAD	# create stack frame on stack
	xc	0(STACK_FRAME_OVERHEAD,%r15),0(%r15)
731 732 733
	l	%r1,__LC_RESTART_FN		# load fn, parm & source cpu
	l	%r2,__LC_RESTART_DATA
	l	%r3,__LC_RESTART_SOURCE
M
Martin Schwidefsky 已提交
734 735
	ltr	%r3,%r3				# test source cpu address
	jm	1f				# negative -> skip source stop
736
0:	sigp	%r4,%r3,SIGP_SENSE		# sigp sense to source cpu
M
Martin Schwidefsky 已提交
737 738 739 740
	brc	10,0b				# wait for status stored
1:	basr	%r14,%r1			# call function
	stap	__SF_EMPTY(%r15)		# store cpu address
	lh	%r3,__SF_EMPTY(%r15)
741
2:	sigp	%r4,%r3,SIGP_STOP		# sigp stop to current cpu
M
Martin Schwidefsky 已提交
742 743
	brc	2,2b
3:	j	3b
744

745 746
	.section .kprobes.text, "ax"

L
Linus Torvalds 已提交
747 748 749 750 751 752 753 754
#ifdef CONFIG_CHECK_STACK
/*
 * The synchronous or the asynchronous stack overflowed. We are dead.
 * No need to properly save the registers, we are going to panic anyway.
 * Setup a pt_regs so that show_trace can provide a good call trace.
 */
stack_overflow:
	l	%r15,__LC_PANIC_STACK	# change to panic stack
755 756 757
	la	%r11,STACK_FRAME_OVERHEAD(%r15)
	stm	%r0,%r7,__PT_R0(%r11)
	stm	%r8,%r9,__PT_PSW(%r11)
758 759 760 761 762
	mvc	__PT_R8(32,%r11),0(%r14)
	l	%r1,BASED(1f)
	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
	lr	%r2,%r11		# pass pointer to pt_regs
	br	%r1			# branch to kernel_stack_overflow
H
Heiko Carstens 已提交
763
1:	.long	kernel_stack_overflow
L
Linus Torvalds 已提交
764 765
#endif

766 767 768 769 770 771 772 773 774
cleanup_table:
	.long	system_call + 0x80000000
	.long	sysc_do_svc + 0x80000000
	.long	sysc_tif + 0x80000000
	.long	sysc_restore + 0x80000000
	.long	sysc_done + 0x80000000
	.long	io_tif + 0x80000000
	.long	io_restore + 0x80000000
	.long	io_done + 0x80000000
M
Martin Schwidefsky 已提交
775 776
	.long	psw_idle + 0x80000000
	.long	psw_idle_end + 0x80000000
L
Linus Torvalds 已提交
777 778

cleanup_critical:
779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794
	cl	%r9,BASED(cleanup_table)	# system_call
	jl	0f
	cl	%r9,BASED(cleanup_table+4)	# sysc_do_svc
	jl	cleanup_system_call
	cl	%r9,BASED(cleanup_table+8)	# sysc_tif
	jl	0f
	cl	%r9,BASED(cleanup_table+12)	# sysc_restore
	jl	cleanup_sysc_tif
	cl	%r9,BASED(cleanup_table+16)	# sysc_done
	jl	cleanup_sysc_restore
	cl	%r9,BASED(cleanup_table+20)	# io_tif
	jl	0f
	cl	%r9,BASED(cleanup_table+24)	# io_restore
	jl	cleanup_io_tif
	cl	%r9,BASED(cleanup_table+28)	# io_done
	jl	cleanup_io_restore
M
Martin Schwidefsky 已提交
795 796 797 798
	cl	%r9,BASED(cleanup_table+32)	# psw_idle
	jl	0f
	cl	%r9,BASED(cleanup_table+36)	# psw_idle_end
	jl	cleanup_idle
799
0:	br	%r14
L
Linus Torvalds 已提交
800 801

cleanup_system_call:
802 803 804
	# check if stpt has been executed
	cl	%r9,BASED(cleanup_system_call_insn)
	jh	0f
L
Linus Torvalds 已提交
805
	mvc	__LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER
806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834
	chi	%r11,__LC_SAVE_AREA_ASYNC
	je	0f
	mvc	__LC_SYNC_ENTER_TIMER(8),__LC_MCCK_ENTER_TIMER
0:	# check if stm has been executed
	cl	%r9,BASED(cleanup_system_call_insn+4)
	jh	0f
	mvc	__LC_SAVE_AREA_SYNC(32),0(%r11)
0:	# set up saved registers r12, and r13
	st	%r12,16(%r11)		# r12 thread-info pointer
	st	%r13,20(%r11)		# r13 literal-pool pointer
	# check if the user time calculation has been done
	cl	%r9,BASED(cleanup_system_call_insn+8)
	jh	0f
	l	%r10,__LC_EXIT_TIMER
	l	%r15,__LC_EXIT_TIMER+4
	SUB64	%r10,%r15,__LC_SYNC_ENTER_TIMER
	ADD64	%r10,%r15,__LC_USER_TIMER
	st	%r10,__LC_USER_TIMER
	st	%r15,__LC_USER_TIMER+4
0:	# check if the system time calculation has been done
	cl	%r9,BASED(cleanup_system_call_insn+12)
	jh	0f
	l	%r10,__LC_LAST_UPDATE_TIMER
	l	%r15,__LC_LAST_UPDATE_TIMER+4
	SUB64	%r10,%r15,__LC_EXIT_TIMER
	ADD64	%r10,%r15,__LC_SYSTEM_TIMER
	st	%r10,__LC_SYSTEM_TIMER
	st	%r15,__LC_SYSTEM_TIMER+4
0:	# update accounting time stamp
L
Linus Torvalds 已提交
835
	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
836 837
	# set up saved register 11
	l	%r15,__LC_KERNEL_STACK
838 839
	la	%r9,STACK_FRAME_OVERHEAD(%r15)
	st	%r9,12(%r11)		# r11 pt_regs pointer
840
	# fill pt_regs
841 842 843 844
	mvc	__PT_R8(32,%r9),__LC_SAVE_AREA_SYNC
	stm	%r0,%r7,__PT_R0(%r9)
	mvc	__PT_PSW(8,%r9),__LC_SVC_OLD_PSW
	mvc	__PT_INT_CODE(4,%r9),__LC_SVC_ILC
845 846 847 848
	# setup saved register 15
	st	%r15,28(%r11)		# r15 stack pointer
	# set new psw address and exit
	l	%r9,BASED(cleanup_table+4)	# sysc_do_svc + 0x80000000
L
Linus Torvalds 已提交
849 850
	br	%r14
cleanup_system_call_insn:
H
Heiko Carstens 已提交
851
	.long	system_call + 0x80000000
852 853 854
	.long	sysc_stm + 0x80000000
	.long	sysc_vtime + 0x80000000 + 36
	.long	sysc_vtime + 0x80000000 + 76
L
Linus Torvalds 已提交
855

856
cleanup_sysc_tif:
857
	l	%r9,BASED(cleanup_table+8)	# sysc_tif + 0x80000000
L
Linus Torvalds 已提交
858 859
	br	%r14

860
cleanup_sysc_restore:
861 862 863 864 865 866 867
	cl	%r9,BASED(cleanup_sysc_restore_insn)
	jhe	0f
	l	%r9,12(%r11)		# get saved pointer to pt_regs
	mvc	__LC_RETURN_PSW(8),__PT_PSW(%r9)
	mvc	0(32,%r11),__PT_R8(%r9)
	lm	%r0,%r7,__PT_R0(%r9)
0:	lm	%r8,%r9,__LC_RETURN_PSW
L
Linus Torvalds 已提交
868
	br	%r14
869
cleanup_sysc_restore_insn:
870
	.long	sysc_done - 4 + 0x80000000
L
Linus Torvalds 已提交
871

872
cleanup_io_tif:
873
	l	%r9,BASED(cleanup_table+20)	# io_tif + 0x80000000
874 875
	br	%r14

876
cleanup_io_restore:
877 878 879 880 881 882 883
	cl	%r9,BASED(cleanup_io_restore_insn)
	jhe	0f
	l	%r9,12(%r11)		# get saved r11 pointer to pt_regs
	mvc	__LC_RETURN_PSW(8),__PT_PSW(%r9)
	mvc	0(32,%r11),__PT_R8(%r9)
	lm	%r0,%r7,__PT_R0(%r9)
0:	lm	%r8,%r9,__LC_RETURN_PSW
884
	br	%r14
885
cleanup_io_restore_insn:
886
	.long	io_done - 4 + 0x80000000
887

M
Martin Schwidefsky 已提交
888 889
cleanup_idle:
	# copy interrupt clock & cpu timer
890 891
	mvc	__CLOCK_IDLE_EXIT(8,%r2),__LC_INT_CLOCK
	mvc	__TIMER_IDLE_EXIT(8,%r2),__LC_ASYNC_ENTER_TIMER
M
Martin Schwidefsky 已提交
892 893
	chi	%r11,__LC_SAVE_AREA_ASYNC
	je	0f
894 895
	mvc	__CLOCK_IDLE_EXIT(8,%r2),__LC_MCCK_CLOCK
	mvc	__TIMER_IDLE_EXIT(8,%r2),__LC_MCCK_ENTER_TIMER
M
Martin Schwidefsky 已提交
896 897 898
0:	# check if stck has been executed
	cl	%r9,BASED(cleanup_idle_insn)
	jhe	1f
899 900 901
	mvc	__CLOCK_IDLE_ENTER(8,%r2),__CLOCK_IDLE_EXIT(%r2)
	mvc	__TIMER_IDLE_ENTER(8,%r2),__TIMER_IDLE_EXIT(%r3)
1:	# account system time going idle
M
Martin Schwidefsky 已提交
902
	lm	%r9,%r10,__LC_STEAL_TIMER
903
	ADD64	%r9,%r10,__CLOCK_IDLE_ENTER(%r2)
M
Martin Schwidefsky 已提交
904 905
	SUB64	%r9,%r10,__LC_LAST_UPDATE_CLOCK
	stm	%r9,%r10,__LC_STEAL_TIMER
906
	mvc	__LC_LAST_UPDATE_CLOCK(8),__CLOCK_IDLE_EXIT(%r2)
M
Martin Schwidefsky 已提交
907 908
	lm	%r9,%r10,__LC_SYSTEM_TIMER
	ADD64	%r9,%r10,__LC_LAST_UPDATE_TIMER
909
	SUB64	%r9,%r10,__TIMER_IDLE_ENTER(%r2)
M
Martin Schwidefsky 已提交
910
	stm	%r9,%r10,__LC_SYSTEM_TIMER
911
	mvc	__LC_LAST_UPDATE_TIMER(8),__TIMER_IDLE_EXIT(%r2)
M
Martin Schwidefsky 已提交
912
	# prepare return psw
913
	n	%r8,BASED(cleanup_idle_wait)	# clear irq & wait state bits
M
Martin Schwidefsky 已提交
914 915 916 917 918
	l	%r9,24(%r11)			# return from psw_idle
	br	%r14
cleanup_idle_insn:
	.long	psw_idle_lpsw + 0x80000000
cleanup_idle_wait:
919
	.long	0xfcfdffff
M
Martin Schwidefsky 已提交
920

L
Linus Torvalds 已提交
921 922 923
/*
 * Integer constants
 */
924
	.align	4
M
Martin Schwidefsky 已提交
925 926 927 928
.Lnr_syscalls:
	.long	NR_syscalls
.Lvtimer_max:
	.quad	0x7fffffffffffffff
L
Linus Torvalds 已提交
929 930 931 932

/*
 * Symbol constants
 */
933 934 935 936 937 938 939 940
.Ldo_machine_check:	.long	s390_do_machine_check
.Lhandle_mcck:		.long	s390_handle_mcck
.Ldo_IRQ:		.long	do_IRQ
.Ldo_signal:		.long	do_signal
.Ldo_notify_resume:	.long	do_notify_resume
.Ldo_per_trap:		.long	do_per_trap
.Ljump_table:		.long	pgm_check_table
.Lschedule:		.long	schedule
941
#ifdef CONFIG_PREEMPT
942
.Lpreempt_irq:		.long	preempt_schedule_irq
943
#endif
944 945 946 947
.Ltrace_enter:		.long	do_syscall_trace_enter
.Ltrace_exit:		.long	do_syscall_trace_exit
.Lschedule_tail:	.long	schedule_tail
.Lsysc_per:		.long	sysc_per + 0x80000000
948
#ifdef CONFIG_TRACE_IRQFLAGS
949 950
.Lhardirqs_on:		.long	trace_hardirqs_on_caller
.Lhardirqs_off:		.long	trace_hardirqs_off_caller
H
Heiko Carstens 已提交
951 952
#endif
#ifdef CONFIG_LOCKDEP
953
.Llockdep_sys_exit:	.long	lockdep_sys_exit
954
#endif
955 956
.Lcritical_start:	.long	__critical_start + 0x80000000
.Lcritical_length:	.long	__critical_end - __critical_start
L
Linus Torvalds 已提交
957

H
Heiko Carstens 已提交
958
		.section .rodata, "a"
L
Linus Torvalds 已提交
959
#define SYSCALL(esa,esame,emu)	.long esa
960
	.globl	sys_call_table
L
Linus Torvalds 已提交
961 962 963
sys_call_table:
#include "syscalls.S"
#undef SYSCALL