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

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

/*
 * Stack layout for the system_call stack entry.
 * The first few entries are identical to the user_regs_struct.
 */
H
Heiko Carstens 已提交
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
SP_PTREGS    =	STACK_FRAME_OVERHEAD
SP_ARGS      =	STACK_FRAME_OVERHEAD + __PT_ARGS
SP_PSW	     =	STACK_FRAME_OVERHEAD + __PT_PSW
SP_R0	     =	STACK_FRAME_OVERHEAD + __PT_GPRS
SP_R1	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 8
SP_R2	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 16
SP_R3	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 24
SP_R4	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 32
SP_R5	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 40
SP_R6	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 48
SP_R7	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 56
SP_R8	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 64
SP_R9	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 72
SP_R10	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 80
SP_R11	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 88
SP_R12	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 96
SP_R13	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 104
SP_R14	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 112
SP_R15	     =	STACK_FRAME_OVERHEAD + __PT_GPRS + 120
SP_ORIG_R2   =	STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2
SP_ILC	     =	STACK_FRAME_OVERHEAD + __PT_ILC
47
SP_SVCNR      =	STACK_FRAME_OVERHEAD + __PT_SVCNR
H
Heiko Carstens 已提交
48
SP_SIZE      =	STACK_FRAME_OVERHEAD + __PT_SIZE
L
Linus Torvalds 已提交
49 50 51 52

STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
STACK_SIZE  = 1 << STACK_SHIFT

M
Martin Schwidefsky 已提交
53
_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
M
Martin Schwidefsky 已提交
54
		 _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_PER_TRAP )
M
Martin Schwidefsky 已提交
55
_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
56
		 _TIF_MCCK_PENDING)
57
_TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
58
		_TIF_SECCOMP>>8 | _TIF_SYSCALL_TRACEPOINT>>8)
59
_TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
L
Linus Torvalds 已提交
60 61 62

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

63 64 65 66 67 68 69 70
	.macro SPP newpp
#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
	tm	__LC_MACHINE_FLAGS+6,0x20	# MACHINE_FLAG_SPP
	jz	.+8
	.insn	s,0xb2800000,\newpp
#endif
	.endm

71 72
	.macro	HANDLE_SIE_INTERCEPT
#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
73
	tm	__TI_flags+6(%r12),_TIF_SIE>>8
74
	jz	0f
75 76 77 78 79 80
	SPP	__LC_CMF_HPP			# set host id
	clc	SP_PSW+8(8,%r15),BASED(.Lsie_loop)
	jl	0f
	clc	SP_PSW+8(8,%r15),BASED(.Lsie_done)
	jhe	0f
	mvc	SP_PSW+8(8,%r15),BASED(.Lsie_loop)
81
0:
82 83 84
#endif
	.endm

85 86
#ifdef CONFIG_TRACE_IRQFLAGS
	.macro	TRACE_IRQS_ON
87 88
	basr	%r2,%r0
	brasl	%r14,trace_hardirqs_on_caller
89 90 91
	.endm

	.macro	TRACE_IRQS_OFF
92 93
	basr	%r2,%r0
	brasl	%r14,trace_hardirqs_off_caller
94 95 96 97
	.endm
#else
#define TRACE_IRQS_ON
#define TRACE_IRQS_OFF
98 99 100 101 102 103 104 105 106 107
#endif

#ifdef CONFIG_LOCKDEP
	.macro	LOCKDEP_SYS_EXIT
	tm	SP_PSW+1(%r15),0x01	# returning to user ?
	jz	0f
	brasl	%r14,lockdep_sys_exit
0:
	.endm
#else
108
#define LOCKDEP_SYS_EXIT
109 110
#endif

H
Heiko Carstens 已提交
111
	.macro	UPDATE_VTIME lc_from,lc_to,lc_sum
L
Linus Torvalds 已提交
112 113 114 115 116 117 118 119 120 121 122 123 124 125
	lg	%r10,\lc_from
	slg	%r10,\lc_to
	alg	%r10,\lc_sum
	stg	%r10,\lc_sum
	.endm

/*
 * Register usage in interrupt handlers:
 *    R9  - pointer to current task structure
 *    R13 - pointer to literal pool
 *    R14 - return register for function calls
 *    R15 - kernel stack pointer
 */

126
	.macro	SAVE_ALL_SVC psworg,savearea
127
	stmg	%r11,%r15,\savearea
128
	lg	%r15,__LC_KERNEL_STACK	# problem state -> load ksp
129 130
	aghi	%r15,-SP_SIZE		# make room for registers & psw
	lg	%r11,__LC_LAST_BREAK
131 132
	.endm

133 134
	.macro	SAVE_ALL_PGM psworg,savearea
	stmg	%r11,%r15,\savearea
L
Linus Torvalds 已提交
135
	tm	\psworg+1,0x01		# test problem state bit
136
#ifdef CONFIG_CHECK_STACK
137 138 139 140 141 142 143
	jnz	1f
	tml	%r15,STACK_SIZE - CONFIG_STACK_GUARD
	jnz	2f
	la	%r12,\psworg
	j	stack_overflow
#else
	jz	2f
144
#endif
145 146 147 148
1:	lg	%r15,__LC_KERNEL_STACK	# problem state -> load ksp
2:	aghi	%r15,-SP_SIZE		# make room for registers & psw
	larl	%r13,system_call
	lg	%r11,__LC_LAST_BREAK
149 150 151
	.endm

	.macro	SAVE_ALL_ASYNC psworg,savearea
152 153 154
	stmg	%r11,%r15,\savearea
	larl	%r13,system_call
	lg	%r11,__LC_LAST_BREAK
155
	la	%r12,\psworg
L
Linus Torvalds 已提交
156 157 158 159 160 161 162
	tm	\psworg+1,0x01		# test problem state bit
	jnz	1f			# from user -> load kernel stack
	clc	\psworg+8(8),BASED(.Lcritical_end)
	jhe	0f
	clc	\psworg+8(8),BASED(.Lcritical_start)
	jl	0f
	brasl	%r14,cleanup_critical
163
	tm	1(%r12),0x01		# retest problem state after cleanup
L
Linus Torvalds 已提交
164 165 166 167 168
	jnz	1f
0:	lg	%r14,__LC_ASYNC_STACK	# are we already on the async. stack ?
	slgr	%r14,%r15
	srag	%r14,%r14,STACK_SHIFT
#ifdef CONFIG_CHECK_STACK
169 170 171 172 173 174
	jnz	1f
	tml	%r15,STACK_SIZE - CONFIG_STACK_GUARD
	jnz	2f
	j	stack_overflow
#else
	jz	2f
L
Linus Torvalds 已提交
175
#endif
176 177
1:	lg	%r15,__LC_ASYNC_STACK	# load async stack
2:	aghi	%r15,-SP_SIZE		# make room for registers & psw
178 179
	.endm

180 181
	.macro	CREATE_STACK_FRAME savearea
	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
L
Linus Torvalds 已提交
182
	stg	%r2,SP_ORIG_R2(%r15)	# store original content of gpr 2
183 184
	mvc	SP_R11(40,%r15),\savearea # move %r11-%r15 to stack
	stmg	%r0,%r10,SP_R0(%r15)	# store gprs %r0-%r10 to kernel stack
H
Heiko Carstens 已提交
185
	.endm
L
Linus Torvalds 已提交
186

187 188
	.macro	RESTORE_ALL psworg,sync
	mvc	\psworg(16),SP_PSW(%r15) # move user PSW to lowcore
L
Linus Torvalds 已提交
189
	.if !\sync
190
	ni	\psworg+1,0xfd		# clear wait state bit
L
Linus Torvalds 已提交
191
	.endif
192 193
	lg	%r14,__LC_VDSO_PER_CPU
	lmg	%r0,%r13,SP_R0(%r15)	# load gprs 0-13 of user
M
Martin Schwidefsky 已提交
194
	stpt	__LC_EXIT_TIMER
195 196
	mvc	__VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER
	lmg	%r14,%r15,SP_R14(%r15)	# load grps 14-15 of user
197
	lpswe	\psworg			# back to caller
L
Linus Torvalds 已提交
198 199
	.endm

200 201 202 203 204 205 206
	.macro	LAST_BREAK
	srag	%r10,%r11,23
	jz	0f
	stg	%r11,__TI_last_break(%r12)
0:
	.endm

207 208 209 210 211 212
	.macro REENABLE_IRQS
	mvc	__SF_EMPTY(1,%r15),SP_PSW(%r15)
	ni	__SF_EMPTY(%r15),0xbf
	ssm	__SF_EMPTY(%r15)
	.endm

213 214
	.section .kprobes.text, "ax"

L
Linus Torvalds 已提交
215 216 217 218 219 220 221
/*
 * Scheduler resume function, called by switch_to
 *  gpr2 = (task_struct *) prev
 *  gpr3 = (task_struct *) next
 * Returns:
 *  gpr2 = prev
 */
H
Heiko Carstens 已提交
222
	.globl	__switch_to
L
Linus Torvalds 已提交
223
__switch_to:
M
Martin Schwidefsky 已提交
224 225
	lg	%r4,__THREAD_info(%r2)		# get thread_info of prev
	lg	%r5,__THREAD_info(%r3)		# get thread_info of next
226
	tm	__TI_flags+7(%r4),_TIF_MCCK_PENDING # machine check pending?
M
Martin Schwidefsky 已提交
227 228 229 230 231 232 233 234 235
	jz	0f
	ni	__TI_flags+7(%r4),255-_TIF_MCCK_PENDING	# clear flag in prev
	oi	__TI_flags+7(%r5),_TIF_MCCK_PENDING	# set it in next
0:	stmg	%r6,%r15,__SF_GPRS(%r15)	# store gprs of prev task
	stg	%r15,__THREAD_ksp(%r2)		# store kernel stack of prev
	lg	%r15,__THREAD_ksp(%r3)		# load kernel stack of next
	lctl	%c4,%c4,__TASK_pid(%r3)		# load pid to control reg. 4
	lmg	%r6,%r15,__SF_GPRS(%r15)	# load gprs of next task
	stg	%r3,__LC_CURRENT		# store task struct of next
236
	mvc	__LC_CURRENT_PID+4(4,%r0),__TASK_pid(%r3) # store pid of next
M
Martin Schwidefsky 已提交
237 238 239
	stg	%r5,__LC_THREAD_INFO		# store thread info of next
	aghi	%r5,STACK_SIZE			# end of kernel stack of next
	stg	%r5,__LC_KERNEL_STACK		# store end of kernel stack
L
Linus Torvalds 已提交
240 241 242 243 244 245 246 247
	br	%r14

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

H
Heiko Carstens 已提交
248
	.globl	system_call
L
Linus Torvalds 已提交
249
system_call:
M
Martin Schwidefsky 已提交
250
	stpt	__LC_SYNC_ENTER_TIMER
L
Linus Torvalds 已提交
251
sysc_saveall:
252
	SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
253 254 255 256
	CREATE_STACK_FRAME __LC_SAVE_AREA
	mvc	SP_PSW(16,%r15),__LC_SVC_OLD_PSW
	mvc	SP_ILC(4,%r15),__LC_SVC_ILC
	lg	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
L
Linus Torvalds 已提交
257 258 259 260 261 262
sysc_vtime:
	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
sysc_stime:
	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
sysc_update:
	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
263
	LAST_BREAK
L
Linus Torvalds 已提交
264
sysc_do_svc:
265 266
	llgh	%r7,SP_SVCNR(%r15)
	slag	%r7,%r7,2	# shift and test for svc 0
L
Linus Torvalds 已提交
267 268
	jnz	sysc_nr_ok
	# svc 0: system call number in %r1
269 270
	llgfr	%r1,%r1		# clear high word in r1
	cghi	%r1,NR_syscalls
L
Linus Torvalds 已提交
271
	jnl	sysc_nr_ok
272 273
	sth	%r1,SP_SVCNR(%r15)
	slag	%r7,%r1,2	# shift and test for svc 0
L
Linus Torvalds 已提交
274
sysc_nr_ok:
H
Heiko Carstens 已提交
275
	larl	%r10,sys_call_table
276
#ifdef CONFIG_COMPAT
277
	tm	__TI_flags+5(%r12),(_TIF_31BIT>>16)  # running in 31 bit mode ?
278
	jno	sysc_noemu
H
Heiko Carstens 已提交
279
	larl	%r10,sys_call_table_emu  # use 31 bit emulation system calls
L
Linus Torvalds 已提交
280 281
sysc_noemu:
#endif
282
	tm	__TI_flags+6(%r12),_TIF_SYSCALL
283
	mvc	SP_ARGS(8,%r15),SP_R7(%r15)
H
Heiko Carstens 已提交
284 285 286 287
	lgf	%r8,0(%r7,%r10) # load address of system call routine
	jnz	sysc_tracesys
	basr	%r14,%r8	# call sys_xxxx
	stg	%r2,SP_R2(%r15) # store return value (change R2 on stack)
L
Linus Torvalds 已提交
288 289

sysc_return:
290 291
	LOCKDEP_SYS_EXIT
sysc_tif:
292
	tm	__TI_flags+7(%r12),_TIF_WORK_SVC
H
Heiko Carstens 已提交
293
	jnz	sysc_work	# there is work to do (signals etc.)
294
sysc_restore:
H
Heiko Carstens 已提交
295
	RESTORE_ALL __LC_RETURN_PSW,1
296 297
sysc_done:

L
Linus Torvalds 已提交
298
#
299
# There is work to do, but first we need to check if we return to userspace.
L
Linus Torvalds 已提交
300 301
#
sysc_work:
302 303
	tm	SP_PSW+1(%r15),0x01	# returning to user ?
	jno	sysc_restore
304 305 306 307

#
# One of the work bits is on. Find out which one.
#
308
sysc_work_tif:
309
	tm	__TI_flags+7(%r12),_TIF_MCCK_PENDING
310
	jo	sysc_mcck_pending
311
	tm	__TI_flags+7(%r12),_TIF_NEED_RESCHED
L
Linus Torvalds 已提交
312
	jo	sysc_reschedule
313
	tm	__TI_flags+7(%r12),_TIF_SIGPENDING
314
	jo	sysc_sigpending
315
	tm	__TI_flags+7(%r12),_TIF_NOTIFY_RESUME
316
	jo	sysc_notify_resume
317
	tm	__TI_flags+7(%r12),_TIF_RESTART_SVC
L
Linus Torvalds 已提交
318
	jo	sysc_restart
M
Martin Schwidefsky 已提交
319
	tm	__TI_flags+7(%r12),_TIF_PER_TRAP
L
Linus Torvalds 已提交
320
	jo	sysc_singlestep
321
	j	sysc_return		# beware of critical section cleanup
L
Linus Torvalds 已提交
322 323 324

#
# _TIF_NEED_RESCHED is set, call schedule
H
Heiko Carstens 已提交
325 326
#
sysc_reschedule:
327 328
	larl	%r14,sysc_return
	jg	schedule		# return point is sysc_return
L
Linus Torvalds 已提交
329

330 331 332 333
#
# _TIF_MCCK_PENDING is set, call handler
#
sysc_mcck_pending:
334
	larl	%r14,sysc_return
H
Heiko Carstens 已提交
335
	jg	s390_handle_mcck	# TIF bit will be cleared by handler
336

L
Linus Torvalds 已提交
337
#
338
# _TIF_SIGPENDING is set, call do_signal
L
Linus Torvalds 已提交
339
#
H
Heiko Carstens 已提交
340
sysc_sigpending:
M
Martin Schwidefsky 已提交
341
	ni	__TI_flags+7(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP
H
Heiko Carstens 已提交
342 343
	la	%r2,SP_PTREGS(%r15)	# load pt_regs
	brasl	%r14,do_signal		# call do_signal
344
	tm	__TI_flags+7(%r12),_TIF_RESTART_SVC
L
Linus Torvalds 已提交
345
	jo	sysc_restart
M
Martin Schwidefsky 已提交
346
	tm	__TI_flags+7(%r12),_TIF_PER_TRAP
L
Linus Torvalds 已提交
347
	jo	sysc_singlestep
348
	j	sysc_return
L
Linus Torvalds 已提交
349

M
Martin Schwidefsky 已提交
350 351 352 353 354
#
# _TIF_NOTIFY_RESUME is set, call do_notify_resume
#
sysc_notify_resume:
	la	%r2,SP_PTREGS(%r15)	# load pt_regs
355
	larl	%r14,sysc_return
M
Martin Schwidefsky 已提交
356 357
	jg	do_notify_resume	# call do_notify_resume

L
Linus Torvalds 已提交
358 359 360 361
#
# _TIF_RESTART_SVC is set, set up registers and restart svc
#
sysc_restart:
362
	ni	__TI_flags+7(%r12),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
H
Heiko Carstens 已提交
363
	lg	%r7,SP_R2(%r15)		# load new svc number
L
Linus Torvalds 已提交
364
	mvc	SP_R2(8,%r15),SP_ORIG_R2(%r15) # restore first argument
H
Heiko Carstens 已提交
365
	lmg	%r2,%r6,SP_R2(%r15)	# load svc arguments
366 367 368
	sth	%r7,SP_SVCNR(%r15)
	slag	%r7,%r7,2
	j	sysc_nr_ok		# restart svc
L
Linus Torvalds 已提交
369 370

#
M
Martin Schwidefsky 已提交
371
# _TIF_PER_TRAP is set, call do_per_trap
L
Linus Torvalds 已提交
372 373
#
sysc_singlestep:
M
Martin Schwidefsky 已提交
374
	ni	__TI_flags+7(%r12),255-_TIF_PER_TRAP	# clear TIF_PER_TRAP
375
	xc	SP_SVCNR(2,%r15),SP_SVCNR(%r15)		# clear svc number
L
Linus Torvalds 已提交
376
	la	%r2,SP_PTREGS(%r15)	# address of register-save area
377
	larl	%r14,sysc_return	# load adr. of system return
M
Martin Schwidefsky 已提交
378
	jg	do_per_trap
L
Linus Torvalds 已提交
379 380

#
M
Martin Schwidefsky 已提交
381 382
# call tracehook_report_syscall_entry/tracehook_report_syscall_exit before
# and after the system call
L
Linus Torvalds 已提交
383 384
#
sysc_tracesys:
H
Heiko Carstens 已提交
385
	la	%r2,SP_PTREGS(%r15)	# load pt_regs
L
Linus Torvalds 已提交
386
	la	%r3,0
387 388
	llgh	%r0,SP_SVCNR(%r15)
	stg	%r0,SP_R2(%r15)
M
Martin Schwidefsky 已提交
389
	brasl	%r14,do_syscall_trace_enter
L
Linus Torvalds 已提交
390
	lghi	%r0,NR_syscalls
M
Martin Schwidefsky 已提交
391
	clgr	%r0,%r2
L
Linus Torvalds 已提交
392
	jnh	sysc_tracenogo
393
	sllg	%r7,%r2,2		# svc number *4
L
Linus Torvalds 已提交
394 395
	lgf	%r8,0(%r7,%r10)
sysc_tracego:
H
Heiko Carstens 已提交
396
	lmg	%r3,%r6,SP_R3(%r15)
397
	mvc	SP_ARGS(8,%r15),SP_R7(%r15)
H
Heiko Carstens 已提交
398 399 400
	lg	%r2,SP_ORIG_R2(%r15)
	basr	%r14,%r8		# call sys_xxx
	stg	%r2,SP_R2(%r15)		# store return value
L
Linus Torvalds 已提交
401
sysc_tracenogo:
402
	tm	__TI_flags+6(%r12),_TIF_SYSCALL
H
Heiko Carstens 已提交
403 404 405
	jz	sysc_return
	la	%r2,SP_PTREGS(%r15)	# load pt_regs
	larl	%r14,sysc_return	# return point is sysc_return
M
Martin Schwidefsky 已提交
406
	jg	do_syscall_trace_exit
L
Linus Torvalds 已提交
407 408 409 410

#
# a new process exits the kernel with ret_from_fork
#
H
Heiko Carstens 已提交
411
	.globl	ret_from_fork
L
Linus Torvalds 已提交
412 413
ret_from_fork:
	lg	%r13,__LC_SVC_NEW_PSW+8
414
	lg	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
L
Linus Torvalds 已提交
415 416 417
	tm	SP_PSW+1(%r15),0x01	# forking a kernel thread ?
	jo	0f
	stg	%r15,SP_R15(%r15)	# store stack pointer for new kthread
H
Heiko Carstens 已提交
418
0:	brasl	%r14,schedule_tail
419
	TRACE_IRQS_ON
H
Heiko Carstens 已提交
420
	stosm	24(%r15),0x03		# reenable interrupts
421
	j	sysc_tracenogo
L
Linus Torvalds 已提交
422 423

#
M
Martin Schwidefsky 已提交
424 425
# kernel_execve function needs to deal with pt_regs that is not
# at the usual place
L
Linus Torvalds 已提交
426
#
M
Martin Schwidefsky 已提交
427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447
	.globl	kernel_execve
kernel_execve:
	stmg	%r12,%r15,96(%r15)
	lgr	%r14,%r15
	aghi	%r15,-SP_SIZE
	stg	%r14,__SF_BACKCHAIN(%r15)
	la	%r12,SP_PTREGS(%r15)
	xc	0(__PT_SIZE,%r12),0(%r12)
	lgr	%r5,%r12
	brasl	%r14,do_execve
	ltgfr	%r2,%r2
	je	0f
	aghi	%r15,SP_SIZE
	lmg	%r12,%r15,96(%r15)
	br	%r14
	# execve succeeded.
0:	stnsm	__SF_EMPTY(%r15),0xfc	# disable interrupts
	lg	%r15,__LC_KERNEL_STACK	# load ksp
	aghi	%r15,-SP_SIZE		# make room for registers & psw
	lg	%r13,__LC_SVC_NEW_PSW+8
	mvc	SP_PTREGS(__PT_SIZE,%r15),0(%r12)	# copy pt_regs
448
	lg	%r12,__LC_THREAD_INFO
M
Martin Schwidefsky 已提交
449 450 451 452
	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
	brasl	%r14,execve_tail
	j	sysc_return
L
Linus Torvalds 已提交
453 454 455 456 457

/*
 * Program check handler routine
 */

H
Heiko Carstens 已提交
458
	.globl	pgm_check_handler
L
Linus Torvalds 已提交
459 460 461 462 463 464 465 466 467 468 469 470 471 472
pgm_check_handler:
/*
 * First we need to check for a special case:
 * Single stepping an instruction that disables the PER event mask will
 * cause a PER event AFTER the mask has been set. Example: SVC or LPSW.
 * For a single stepped SVC the program check handler gets control after
 * the SVC new PSW has been loaded. But we want to execute the SVC first and
 * then handle the PER event. Therefore we update the SVC old PSW to point
 * to the pgm_check_handler and branch to the SVC handler after we checked
 * if we have to load the kernel stack register.
 * For every other possible cause for PER event without the PER mask set
 * we just ignore the PER event (FIXME: is there anything we have to do
 * for LPSW?).
 */
M
Martin Schwidefsky 已提交
473
	stpt	__LC_SYNC_ENTER_TIMER
H
Heiko Carstens 已提交
474 475
	tm	__LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
	jnz	pgm_per 		 # got per exception -> special case
476 477 478 479 480
	SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA
	CREATE_STACK_FRAME __LC_SAVE_AREA
	xc	SP_ILC(4,%r15),SP_ILC(%r15)
	mvc	SP_PSW(16,%r15),__LC_PGM_OLD_PSW
	lg	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
481
	HANDLE_SIE_INTERCEPT
L
Linus Torvalds 已提交
482 483 484 485 486
	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
	jz	pgm_no_vtime
	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
487
	LAST_BREAK
L
Linus Torvalds 已提交
488
pgm_no_vtime:
489
	stg	%r11,SP_ARGS(%r15)
H
Heiko Carstens 已提交
490
	lgf	%r3,__LC_PGM_ILC	# load program interruption code
491 492
	lg	%r4,__LC_TRANS_EXC_CODE
	REENABLE_IRQS
L
Linus Torvalds 已提交
493 494
	lghi	%r8,0x7f
	ngr	%r8,%r3
H
Heiko Carstens 已提交
495 496 497 498
	sll	%r8,3
	larl	%r1,pgm_check_table
	lg	%r1,0(%r8,%r1)		# load address of handler routine
	la	%r2,SP_PTREGS(%r15)	# address of register-save area
499 500 501
	basr	%r14,%r1		# branch to interrupt-handler
pgm_exit:
	j	sysc_return
L
Linus Torvalds 已提交
502 503 504 505 506

#
# handle per exception
#
pgm_per:
H
Heiko Carstens 已提交
507 508
	tm	__LC_PGM_OLD_PSW,0x40	# test if per event recording is on
	jnz	pgm_per_std		# ok, normal per event from user space
L
Linus Torvalds 已提交
509
# ok its one of the special cases, now we need to find out which one
H
Heiko Carstens 已提交
510 511
	clc	__LC_PGM_OLD_PSW(16),__LC_SVC_NEW_PSW
	je	pgm_svcper
L
Linus Torvalds 已提交
512
# no interesting special case, ignore PER event
H
Heiko Carstens 已提交
513
	lpswe	__LC_PGM_OLD_PSW
L
Linus Torvalds 已提交
514 515 516 517 518

#
# Normal per exception
#
pgm_per_std:
519 520 521 522
	SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA
	CREATE_STACK_FRAME __LC_SAVE_AREA
	mvc	SP_PSW(16,%r15),__LC_PGM_OLD_PSW
	lg	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
523
	HANDLE_SIE_INTERCEPT
L
Linus Torvalds 已提交
524 525 526 527 528
	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
	jz	pgm_no_vtime2
	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
529
	LAST_BREAK
L
Linus Torvalds 已提交
530
pgm_no_vtime2:
531
	lg	%r1,__TI_task(%r12)
M
Michael Grundy 已提交
532 533
	tm	SP_PSW+1(%r15),0x01	# kernel per event ?
	jz	kernel_per
M
Martin Schwidefsky 已提交
534 535 536 537
	mvc	__THREAD_per_cause(2,%r1),__LC_PER_CAUSE
	mvc	__THREAD_per_address(8,%r1),__LC_PER_ADDRESS
	mvc	__THREAD_per_paid(1,%r1),__LC_PER_PAID
	oi	__TI_flags+7(%r12),_TIF_PER_TRAP # set TIF_PER_TRAP
H
Heiko Carstens 已提交
538
	lgf	%r3,__LC_PGM_ILC	# load program interruption code
539 540
	lg	%r4,__LC_TRANS_EXC_CODE
	REENABLE_IRQS
L
Linus Torvalds 已提交
541
	lghi	%r8,0x7f
H
Heiko Carstens 已提交
542
	ngr	%r8,%r3			# clear per-event-bit and ilc
543 544 545 546 547 548 549 550
	je	pgm_exit2
	sll	%r8,3
	larl	%r1,pgm_check_table
	lg	%r1,0(%r8,%r1)		# load address of handler routine
	la	%r2,SP_PTREGS(%r15)	# address of register-save area
	basr	%r14,%r1		# branch to interrupt-handler
pgm_exit2:
	j	sysc_return
L
Linus Torvalds 已提交
551 552 553 554 555

#
# it was a single stepped SVC that is causing all the trouble
#
pgm_svcper:
556 557 558 559 560
	SAVE_ALL_PGM __LC_SVC_OLD_PSW,__LC_SAVE_AREA
	CREATE_STACK_FRAME __LC_SAVE_AREA
	mvc	SP_PSW(16,%r15),__LC_SVC_OLD_PSW
	mvc	SP_ILC(4,%r15),__LC_SVC_ILC
	lg	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
L
Linus Torvalds 已提交
561 562 563
	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
564 565
	LAST_BREAK
	lg	%r8,__TI_task(%r12)
M
Martin Schwidefsky 已提交
566 567 568 569
	mvc	__THREAD_per_cause(2,%r8),__LC_PER_CAUSE
	mvc	__THREAD_per_address(8,%r8),__LC_PER_ADDRESS
	mvc	__THREAD_per_paid(1,%r8),__LC_PER_PAID
	oi	__TI_flags+7(%r12),_TIF_PER_TRAP # set TIF_PER_TRAP
L
Linus Torvalds 已提交
570
	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
571
	lmg	%r2,%r6,SP_R2(%r15)	# load svc arguments
L
Linus Torvalds 已提交
572 573
	j	sysc_do_svc

M
Michael Grundy 已提交
574 575 576 577
#
# per was called from kernel, must be kprobes
#
kernel_per:
578
	REENABLE_IRQS
579
	xc	SP_SVCNR(2,%r15),SP_SVCNR(%r15)	# clear svc number
M
Michael Grundy 已提交
580
	la	%r2,SP_PTREGS(%r15)	# address of register-save area
M
Martin Schwidefsky 已提交
581
	brasl	%r14,do_per_trap
582
	j	pgm_exit
M
Michael Grundy 已提交
583

L
Linus Torvalds 已提交
584 585 586
/*
 * IO interrupt handler routine
 */
H
Heiko Carstens 已提交
587
	.globl io_int_handler
L
Linus Torvalds 已提交
588 589
io_int_handler:
	stck	__LC_INT_CLOCK
590
	stpt	__LC_ASYNC_ENTER_TIMER
591 592 593 594
	SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+40
	CREATE_STACK_FRAME __LC_SAVE_AREA+40
	mvc	SP_PSW(16,%r15),0(%r12)	# move user PSW to stack
	lg	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
595
	HANDLE_SIE_INTERCEPT
L
Linus Torvalds 已提交
596 597 598 599 600
	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
	jz	io_no_vtime
	UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
601
	LAST_BREAK
L
Linus Torvalds 已提交
602
io_no_vtime:
603
	TRACE_IRQS_OFF
H
Heiko Carstens 已提交
604 605
	la	%r2,SP_PTREGS(%r15)	# address of register-save area
	brasl	%r14,do_IRQ		# call standard irq handler
L
Linus Torvalds 已提交
606
io_return:
607 608 609
	LOCKDEP_SYS_EXIT
	TRACE_IRQS_ON
io_tif:
610
	tm	__TI_flags+7(%r12),_TIF_WORK_INT
H
Heiko Carstens 已提交
611
	jnz	io_work 		# there is work to do (signals etc.)
612
io_restore:
H
Heiko Carstens 已提交
613
	RESTORE_ALL __LC_RETURN_PSW,0
614
io_done:
L
Linus Torvalds 已提交
615

616
#
617 618 619 620 621 622 623
# 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 kvm is enabled check if we need to
#    modify the psw to leave SIE
# 3) 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.
624 625 626
#
io_work:
	tm	SP_PSW+1(%r15),0x01	# returning to user ?
627 628
	jo	io_work_user		# yes -> do resched & signal
#ifdef CONFIG_PREEMPT
629
	# check for preemptive scheduling
630
	icm	%r0,15,__TI_precount(%r12)
631
	jnz	io_restore		# preemption is disabled
632 633
	tm	__TI_flags+7(%r12),_TIF_NEED_RESCHED
	jno	io_restore
L
Linus Torvalds 已提交
634 635 636 637
	# switch to kernel stack
	lg	%r1,SP_R15(%r15)
	aghi	%r1,-SP_SIZE
	mvc	SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
H
Heiko Carstens 已提交
638
	xc	__SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain
L
Linus Torvalds 已提交
639
	lgr	%r15,%r1
640 641 642 643 644 645
	# TRACE_IRQS_ON already done at io_return, call
	# TRACE_IRQS_OFF to keep things symmetrical
	TRACE_IRQS_OFF
	brasl	%r14,preempt_schedule_irq
	j	io_return
#else
646
	j	io_restore
647
#endif
L
Linus Torvalds 已提交
648

649 650 651
#
# Need to do work before returning to userspace, switch to kernel stack
#
652
io_work_user:
L
Linus Torvalds 已提交
653 654 655
	lg	%r1,__LC_KERNEL_STACK
	aghi	%r1,-SP_SIZE
	mvc	SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
H
Heiko Carstens 已提交
656
	xc	__SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain
L
Linus Torvalds 已提交
657
	lgr	%r15,%r1
658

L
Linus Torvalds 已提交
659 660
#
# One of the work bits is on. Find out which one.
661
# Checked are: _TIF_SIGPENDING, _TIF_NOTIFY_RESUME, _TIF_NEED_RESCHED
662
#	       and _TIF_MCCK_PENDING
L
Linus Torvalds 已提交
663
#
664
io_work_tif:
665
	tm	__TI_flags+7(%r12),_TIF_MCCK_PENDING
666
	jo	io_mcck_pending
667
	tm	__TI_flags+7(%r12),_TIF_NEED_RESCHED
L
Linus Torvalds 已提交
668
	jo	io_reschedule
669
	tm	__TI_flags+7(%r12),_TIF_SIGPENDING
670
	jo	io_sigpending
671
	tm	__TI_flags+7(%r12),_TIF_NOTIFY_RESUME
672 673
	jo	io_notify_resume
	j	io_return		# beware of critical section cleanup
674

675 676 677 678
#
# _TIF_MCCK_PENDING is set, call handler
#
io_mcck_pending:
679
	# TRACE_IRQS_ON already done at io_return
H
Heiko Carstens 已提交
680
	brasl	%r14,s390_handle_mcck	# TIF bit will be cleared by handler
681 682
	TRACE_IRQS_OFF
	j	io_return
683

L
Linus Torvalds 已提交
684 685
#
# _TIF_NEED_RESCHED is set, call schedule
H
Heiko Carstens 已提交
686 687
#
io_reschedule:
688
	# TRACE_IRQS_ON already done at io_return
H
Heiko Carstens 已提交
689 690 691
	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
	brasl	%r14,schedule		# call scheduler
	stnsm	__SF_EMPTY(%r15),0xfc	# disable I/O and ext. interrupts
692
	TRACE_IRQS_OFF
693
	j	io_return
L
Linus Torvalds 已提交
694 695

#
696
# _TIF_SIGPENDING or is set, call do_signal
L
Linus Torvalds 已提交
697
#
H
Heiko Carstens 已提交
698
io_sigpending:
699
	# TRACE_IRQS_ON already done at io_return
H
Heiko Carstens 已提交
700 701
	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
	la	%r2,SP_PTREGS(%r15)	# load pt_regs
L
Linus Torvalds 已提交
702
	brasl	%r14,do_signal		# call do_signal
H
Heiko Carstens 已提交
703
	stnsm	__SF_EMPTY(%r15),0xfc	# disable I/O and ext. interrupts
704
	TRACE_IRQS_OFF
705
	j	io_return
L
Linus Torvalds 已提交
706

M
Martin Schwidefsky 已提交
707 708 709 710
#
# _TIF_NOTIFY_RESUME or is set, call do_notify_resume
#
io_notify_resume:
711
	# TRACE_IRQS_ON already done at io_return
M
Martin Schwidefsky 已提交
712 713 714 715 716
	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
	la	%r2,SP_PTREGS(%r15)	# load pt_regs
	brasl	%r14,do_notify_resume	# call do_notify_resume
	stnsm	__SF_EMPTY(%r15),0xfc	# disable I/O and ext. interrupts
	TRACE_IRQS_OFF
717
	j	io_return
M
Martin Schwidefsky 已提交
718

L
Linus Torvalds 已提交
719 720 721
/*
 * External interrupt handler routine
 */
H
Heiko Carstens 已提交
722
	.globl	ext_int_handler
L
Linus Torvalds 已提交
723 724
ext_int_handler:
	stck	__LC_INT_CLOCK
725
	stpt	__LC_ASYNC_ENTER_TIMER
726 727 728 729
	SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+40
	CREATE_STACK_FRAME __LC_SAVE_AREA+40
	mvc	SP_PSW(16,%r15),0(%r12)	# move user PSW to stack
	lg	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
730
	HANDLE_SIE_INTERCEPT
L
Linus Torvalds 已提交
731 732 733 734 735
	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
	jz	ext_no_vtime
	UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
736
	LAST_BREAK
L
Linus Torvalds 已提交
737
ext_no_vtime:
738
	TRACE_IRQS_OFF
739
	lghi	%r1,4096
H
Heiko Carstens 已提交
740
	la	%r2,SP_PTREGS(%r15)	# address of register-save area
741 742 743
	llgf	%r3,__LC_CPU_ADDRESS	# get cpu address + interruption code
	llgf	%r4,__LC_EXT_PARAMS	# get external parameter
	lg	%r5,__LC_EXT_PARAMS2-4096(%r1)	# get 64 bit external parameter
H
Heiko Carstens 已提交
744
	brasl	%r14,do_extint
L
Linus Torvalds 已提交
745 746
	j	io_return

747 748
__critical_end:

L
Linus Torvalds 已提交
749 750 751
/*
 * Machine check handler routines
 */
H
Heiko Carstens 已提交
752
	.globl mcck_int_handler
L
Linus Torvalds 已提交
753
mcck_int_handler:
754
	stck	__LC_MCCK_CLOCK
755 756
	la	%r1,4095		# revalidate r1
	spt	__LC_CPU_TIMER_SAVE_AREA-4095(%r1)	# revalidate cpu timer
H
Heiko Carstens 已提交
757
	lmg	%r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs
758 759 760
	stmg	%r11,%r15,__LC_SAVE_AREA+80
	larl	%r13,system_call
	lg	%r11,__LC_LAST_BREAK
761
	la	%r12,__LC_MCK_OLD_PSW
H
Heiko Carstens 已提交
762
	tm	__LC_MCCK_CODE,0x80	# system damage?
763
	jo	mcck_int_main		# yes -> rest of mcck code invalid
764
	la	%r14,4095
765
	mvc	__LC_MCCK_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA-4095(%r14)
766 767 768 769 770 771 772 773 774 775 776 777 778
	tm	__LC_MCCK_CODE+5,0x02	# stored cpu timer value valid?
	jo	1f
	la	%r14,__LC_SYNC_ENTER_TIMER
	clc	0(8,%r14),__LC_ASYNC_ENTER_TIMER
	jl	0f
	la	%r14,__LC_ASYNC_ENTER_TIMER
0:	clc	0(8,%r14),__LC_EXIT_TIMER
	jl	0f
	la	%r14,__LC_EXIT_TIMER
0:	clc	0(8,%r14),__LC_LAST_UPDATE_TIMER
	jl	0f
	la	%r14,__LC_LAST_UPDATE_TIMER
0:	spt	0(%r14)
779
	mvc	__LC_MCCK_ENTER_TIMER(8),0(%r14)
M
Martin Schwidefsky 已提交
780
1:	tm	__LC_MCCK_CODE+2,0x09	# mwp + ia of old psw valid?
781
	jno	mcck_int_main		# no -> skip cleanup critical
H
Heiko Carstens 已提交
782
	tm	__LC_MCK_OLD_PSW+1,0x01 # test problem state bit
783 784 785
	jnz	mcck_int_main		# from user -> load kernel stack
	clc	__LC_MCK_OLD_PSW+8(8),BASED(.Lcritical_end)
	jhe	mcck_int_main
H
Heiko Carstens 已提交
786
	clc	__LC_MCK_OLD_PSW+8(8),BASED(.Lcritical_start)
787
	jl	mcck_int_main
H
Heiko Carstens 已提交
788
	brasl	%r14,cleanup_critical
789
mcck_int_main:
H
Heiko Carstens 已提交
790
	lg	%r14,__LC_PANIC_STACK	# are we already on the panic stack?
791 792 793
	slgr	%r14,%r15
	srag	%r14,%r14,PAGE_SHIFT
	jz	0f
H
Heiko Carstens 已提交
794
	lg	%r15,__LC_PANIC_STACK	# load panic stack
795 796 797 798
0:	aghi	%r15,-SP_SIZE		# make room for registers & psw
	CREATE_STACK_FRAME __LC_SAVE_AREA+80
	mvc	SP_PSW(16,%r15),0(%r12)
	lg	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
799 800
	tm	__LC_MCCK_CODE+2,0x08	# mwp of old psw valid?
	jno	mcck_no_vtime		# no -> no timer update
801
	HANDLE_SIE_INTERCEPT
802
	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
803
	jz	mcck_no_vtime
804
	UPDATE_VTIME __LC_EXIT_TIMER,__LC_MCCK_ENTER_TIMER,__LC_USER_TIMER
805
	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
806
	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_MCCK_ENTER_TIMER
807
	LAST_BREAK
808
mcck_no_vtime:
809 810
	la	%r2,SP_PTREGS(%r15)	# load pt_regs
	brasl	%r14,s390_do_machine_check
H
Heiko Carstens 已提交
811
	tm	SP_PSW+1(%r15),0x01	# returning to user ?
812 813 814 815 816 817 818
	jno	mcck_return
	lg	%r1,__LC_KERNEL_STACK	# switch to kernel stack
	aghi	%r1,-SP_SIZE
	mvc	SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
	xc	__SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain
	lgr	%r15,%r1
	stosm	__SF_EMPTY(%r15),0x04	# turn dat on
819
	tm	__TI_flags+7(%r12),_TIF_MCCK_PENDING
820
	jno	mcck_return
821
	TRACE_IRQS_OFF
822
	brasl	%r14,s390_handle_mcck
823
	TRACE_IRQS_ON
L
Linus Torvalds 已提交
824
mcck_return:
825 826 827 828 829 830
	mvc	__LC_RETURN_MCCK_PSW(16),SP_PSW(%r15) # move return PSW
	ni	__LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit
	lmg	%r0,%r15,SP_R0(%r15)	# load gprs 0-15
	tm	__LC_RETURN_MCCK_PSW+1,0x01 # returning to user ?
	jno	0f
	stpt	__LC_EXIT_TIMER
M
Martin Schwidefsky 已提交
831
0:	lpswe	__LC_RETURN_MCCK_PSW	# back to caller
832
mcck_done:
L
Linus Torvalds 已提交
833 834 835 836

/*
 * Restart interruption handler, kick starter for additional CPUs
 */
837
#ifdef CONFIG_SMP
838
	__CPUINIT
H
Heiko Carstens 已提交
839
	.globl restart_int_handler
L
Linus Torvalds 已提交
840
restart_int_handler:
841 842 843 844 845 846
	basr	%r1,0
restart_base:
	spt	restart_vtime-restart_base(%r1)
	stck	__LC_LAST_UPDATE_CLOCK
	mvc	__LC_LAST_UPDATE_TIMER(8),restart_vtime-restart_base(%r1)
	mvc	__LC_EXIT_TIMER(8),restart_vtime-restart_base(%r1)
H
Heiko Carstens 已提交
847 848 849 850 851 852
	lg	%r15,__LC_SAVE_AREA+120 # load ksp
	lghi	%r10,__LC_CREGS_SAVE_AREA
	lctlg	%c0,%c15,0(%r10) # get new ctl regs
	lghi	%r10,__LC_AREGS_SAVE_AREA
	lam	%a0,%a15,0(%r10)
	lmg	%r6,%r15,__SF_GPRS(%r15) # load registers from clone
853 854 855 856
	lg	%r1,__LC_THREAD_INFO
	mvc	__LC_USER_TIMER(8),__TI_user_timer(%r1)
	mvc	__LC_SYSTEM_TIMER(8),__TI_system_timer(%r1)
	xc	__LC_STEAL_TIMER(8),__LC_STEAL_TIMER
H
Heiko Carstens 已提交
857
	stosm	__SF_EMPTY(%r15),0x04	# now we can turn dat on
858
	brasl	%r14,start_secondary
859 860 861
	.align	8
restart_vtime:
	.long	0x7fffffff,0xffffffff
862
	.previous
L
Linus Torvalds 已提交
863 864 865 866
#else
/*
 * If we do not run with SMP enabled, let the new CPU crash ...
 */
H
Heiko Carstens 已提交
867
	.globl restart_int_handler
L
Linus Torvalds 已提交
868
restart_int_handler:
H
Heiko Carstens 已提交
869
	basr	%r1,0
L
Linus Torvalds 已提交
870
restart_base:
H
Heiko Carstens 已提交
871 872
	lpswe	restart_crash-restart_base(%r1)
	.align 8
L
Linus Torvalds 已提交
873
restart_crash:
H
Heiko Carstens 已提交
874
	.long  0x000a0000,0x00000000,0x00000000,0x00000000
L
Linus Torvalds 已提交
875 876 877
restart_go:
#endif

878 879
	.section .kprobes.text, "ax"

L
Linus Torvalds 已提交
880 881 882 883 884 885 886 887
#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:
	lg	%r15,__LC_PANIC_STACK	# change to panic stack
888
	aghi	%r15,-SP_SIZE
L
Linus Torvalds 已提交
889
	mvc	SP_PSW(16,%r15),0(%r12)	# move user PSW to stack
890
	stmg	%r0,%r10,SP_R0(%r15)	# store gprs %r0-%r10 to kernel stack
L
Linus Torvalds 已提交
891 892 893 894 895
	la	%r1,__LC_SAVE_AREA
	chi	%r12,__LC_SVC_OLD_PSW
	je	0f
	chi	%r12,__LC_PGM_OLD_PSW
	je	0f
896 897
	la	%r1,__LC_SAVE_AREA+40
0:	mvc	SP_R11(40,%r15),0(%r1)	# move %r11-%r15 to stack
898
	mvc	SP_ARGS(8,%r15),__LC_LAST_BREAK
H
Heiko Carstens 已提交
899 900
	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) # clear back chain
	la	%r2,SP_PTREGS(%r15)	# load pt_regs
L
Linus Torvalds 已提交
901 902 903 904 905
	jg	kernel_stack_overflow
#endif

cleanup_table_system_call:
	.quad	system_call, sysc_do_svc
906 907 908 909 910 911 912 913
cleanup_table_sysc_tif:
	.quad	sysc_tif, sysc_restore
cleanup_table_sysc_restore:
	.quad	sysc_restore, sysc_done
cleanup_table_io_tif:
	.quad	io_tif, io_restore
cleanup_table_io_restore:
	.quad	io_restore, io_done
L
Linus Torvalds 已提交
914 915 916 917 918 919 920

cleanup_critical:
	clc	8(8,%r12),BASED(cleanup_table_system_call)
	jl	0f
	clc	8(8,%r12),BASED(cleanup_table_system_call+8)
	jl	cleanup_system_call
0:
921
	clc	8(8,%r12),BASED(cleanup_table_sysc_tif)
L
Linus Torvalds 已提交
922
	jl	0f
923 924
	clc	8(8,%r12),BASED(cleanup_table_sysc_tif+8)
	jl	cleanup_sysc_tif
L
Linus Torvalds 已提交
925
0:
926
	clc	8(8,%r12),BASED(cleanup_table_sysc_restore)
L
Linus Torvalds 已提交
927
	jl	0f
928 929
	clc	8(8,%r12),BASED(cleanup_table_sysc_restore+8)
	jl	cleanup_sysc_restore
930
0:
931
	clc	8(8,%r12),BASED(cleanup_table_io_tif)
932
	jl	0f
933 934
	clc	8(8,%r12),BASED(cleanup_table_io_tif+8)
	jl	cleanup_io_tif
935
0:
936
	clc	8(8,%r12),BASED(cleanup_table_io_restore)
937
	jl	0f
938 939
	clc	8(8,%r12),BASED(cleanup_table_io_restore+8)
	jl	cleanup_io_restore
L
Linus Torvalds 已提交
940 941 942 943 944 945 946
0:
	br	%r14

cleanup_system_call:
	mvc	__LC_RETURN_PSW(16),0(%r12)
	clc	__LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+8)
	jh	0f
947 948 949
	mvc	__LC_SYNC_ENTER_TIMER(8),__LC_MCCK_ENTER_TIMER
	cghi	%r12,__LC_MCK_OLD_PSW
	je	0f
L
Linus Torvalds 已提交
950
	mvc	__LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER
951
0:	cghi	%r12,__LC_MCK_OLD_PSW
952
	la	%r12,__LC_SAVE_AREA+80
953
	je	0f
954
	la	%r12,__LC_SAVE_AREA+40
L
Linus Torvalds 已提交
955 956 957 958
0:	clc	__LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+16)
	jhe	cleanup_vtime
	clc	__LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn)
	jh	0f
959 960 961 962 963 964 965 966 967
	mvc	__LC_SAVE_AREA(40),0(%r12)
0:	lg	%r15,__LC_KERNEL_STACK	# problem state -> load ksp
	aghi	%r15,-SP_SIZE		# make room for registers & psw
	stg	%r15,32(%r12)
	stg	%r11,0(%r12)
	CREATE_STACK_FRAME __LC_SAVE_AREA
	mvc	SP_PSW(16,%r15),__LC_SVC_OLD_PSW
	mvc	SP_ILC(4,%r15),__LC_SVC_ILC
	mvc	8(8,%r12),__LC_THREAD_INFO
L
Linus Torvalds 已提交
968 969 970 971 972 973 974 975 976 977
cleanup_vtime:
	clc	__LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+24)
	jhe	cleanup_stime
	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
cleanup_stime:
	clc	__LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+32)
	jh	cleanup_update
	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
cleanup_update:
	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
978 979 980 981 982
	srag	%r12,%r11,23
	lg	%r12,__LC_THREAD_INFO
	jz	0f
	stg	%r11,__TI_last_break(%r12)
0:	mvc	__LC_RETURN_PSW+8(8),BASED(cleanup_table_system_call+8)
L
Linus Torvalds 已提交
983 984 985 986
	la	%r12,__LC_RETURN_PSW
	br	%r14
cleanup_system_call_insn:
	.quad	sysc_saveall
H
Heiko Carstens 已提交
987 988 989 990
	.quad	system_call
	.quad	sysc_vtime
	.quad	sysc_stime
	.quad	sysc_update
L
Linus Torvalds 已提交
991

992
cleanup_sysc_tif:
L
Linus Torvalds 已提交
993
	mvc	__LC_RETURN_PSW(8),0(%r12)
994
	mvc	__LC_RETURN_PSW+8(8),BASED(cleanup_table_sysc_tif)
L
Linus Torvalds 已提交
995 996 997
	la	%r12,__LC_RETURN_PSW
	br	%r14

998 999
cleanup_sysc_restore:
	clc	8(8,%r12),BASED(cleanup_sysc_restore_insn)
1000
	je	2f
1001
	clc	8(8,%r12),BASED(cleanup_sysc_restore_insn+8)
1002
	jhe	0f
1003 1004 1005
	mvc	__LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER
	cghi	%r12,__LC_MCK_OLD_PSW
	je	0f
1006 1007
	mvc	__LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
0:	mvc	__LC_RETURN_PSW(16),SP_PSW(%r15)
1008
	cghi	%r12,__LC_MCK_OLD_PSW
1009
	la	%r12,__LC_SAVE_AREA+80
1010
	je	1f
1011 1012 1013
	la	%r12,__LC_SAVE_AREA+40
1:	mvc	0(40,%r12),SP_R11(%r15)
	lmg	%r0,%r10,SP_R0(%r15)
L
Linus Torvalds 已提交
1014
	lg	%r15,SP_R15(%r15)
1015
2:	la	%r12,__LC_RETURN_PSW
L
Linus Torvalds 已提交
1016
	br	%r14
1017
cleanup_sysc_restore_insn:
1018
	.quad	sysc_done - 4
1019
	.quad	sysc_done - 16
L
Linus Torvalds 已提交
1020

1021
cleanup_io_tif:
1022
	mvc	__LC_RETURN_PSW(8),0(%r12)
1023
	mvc	__LC_RETURN_PSW+8(8),BASED(cleanup_table_io_tif)
1024 1025 1026
	la	%r12,__LC_RETURN_PSW
	br	%r14

1027 1028
cleanup_io_restore:
	clc	8(8,%r12),BASED(cleanup_io_restore_insn)
1029
	je	1f
1030
	clc	8(8,%r12),BASED(cleanup_io_restore_insn+8)
1031
	jhe	0f
1032
	mvc	__LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER
1033
0:	mvc	__LC_RETURN_PSW(16),SP_PSW(%r15)
1034 1035
	mvc	__LC_SAVE_AREA+80(40),SP_R11(%r15)
	lmg	%r0,%r10,SP_R0(%r15)
1036
	lg	%r15,SP_R15(%r15)
1037
1:	la	%r12,__LC_RETURN_PSW
1038
	br	%r14
1039
cleanup_io_restore_insn:
1040
	.quad	io_done - 4
1041
	.quad	io_done - 16
1042

L
Linus Torvalds 已提交
1043 1044 1045
/*
 * Integer constants
 */
H
Heiko Carstens 已提交
1046
		.align	4
L
Linus Torvalds 已提交
1047
.Lcritical_start:
H
Heiko Carstens 已提交
1048
		.quad	__critical_start
L
Linus Torvalds 已提交
1049
.Lcritical_end:
H
Heiko Carstens 已提交
1050
		.quad	__critical_end
L
Linus Torvalds 已提交
1051

1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102
#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
/*
 * sie64a calling convention:
 * %r2 pointer to sie control block
 * %r3 guest register save area
 */
	.globl	sie64a
sie64a:
	stmg	%r6,%r14,__SF_GPRS(%r15)	# save kernel registers
	stg	%r2,__SF_EMPTY(%r15)		# save control block pointer
	stg	%r3,__SF_EMPTY+8(%r15)		# save guest register save area
	lmg	%r0,%r13,0(%r3)			# load guest gprs 0-13
	lg	%r14,__LC_THREAD_INFO		# pointer thread_info struct
	oi	__TI_flags+6(%r14),_TIF_SIE>>8
sie_loop:
	lg	%r14,__LC_THREAD_INFO		# pointer thread_info struct
	tm	__TI_flags+7(%r14),_TIF_EXIT_SIE
	jnz	sie_exit
	lg	%r14,__SF_EMPTY(%r15)		# get control block pointer
	SPP	__SF_EMPTY(%r15)		# set guest id
	sie	0(%r14)
sie_done:
	SPP	__LC_CMF_HPP			# set host id
	lg	%r14,__LC_THREAD_INFO		# pointer thread_info struct
sie_exit:
	ni	__TI_flags+6(%r14),255-(_TIF_SIE>>8)
	lg	%r14,__SF_EMPTY+8(%r15)		# load guest register save area
	stmg	%r0,%r13,0(%r14)		# save guest gprs 0-13
	lmg	%r6,%r14,__SF_GPRS(%r15)	# restore kernel registers
	lghi	%r2,0
	br	%r14
sie_fault:
	lg	%r14,__LC_THREAD_INFO		# pointer thread_info struct
	ni	__TI_flags+6(%r14),255-(_TIF_SIE>>8)
	lg	%r14,__SF_EMPTY+8(%r15)		# load guest register save area
	stmg	%r0,%r13,0(%r14)		# save guest gprs 0-13
	lmg	%r6,%r14,__SF_GPRS(%r15)	# restore kernel registers
	lghi	%r2,-EFAULT
	br	%r14

	.align	8
.Lsie_loop:
	.quad	sie_loop
.Lsie_done:
	.quad	sie_done

	.section __ex_table,"a"
	.quad	sie_loop,sie_fault
	.previous
#endif

H
Heiko Carstens 已提交
1103
		.section .rodata, "a"
L
Linus Torvalds 已提交
1104
#define SYSCALL(esa,esame,emu)	.long esame
1105
	.globl	sys_call_table
L
Linus Torvalds 已提交
1106 1107 1108 1109
sys_call_table:
#include "syscalls.S"
#undef SYSCALL

1110
#ifdef CONFIG_COMPAT
L
Linus Torvalds 已提交
1111 1112 1113 1114 1115 1116

#define SYSCALL(esa,esame,emu)	.long emu
sys_call_table_emu:
#include "syscalls.S"
#undef SYSCALL
#endif