Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1de3447a authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Martin Schwidefsky
Browse files

[S390] 31 bit entry.S update.



Make the code in the 31 bit entry.S code as similar as possible to the
64 bit version in entry64.S. That makes it easier to add new code to
the first level interrupt handler that affects both 31 and 64 bit kernels.

Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent ce322ccd
Loading
Loading
Loading
Loading
+109 −103
Original line number Original line Diff line number Diff line
@@ -9,7 +9,6 @@
 *		 Heiko Carstens <heiko.carstens@de.ibm.com>
 *		 Heiko Carstens <heiko.carstens@de.ibm.com>
 */
 */


#include <linux/sys.h>
#include <linux/linkage.h>
#include <linux/linkage.h>
#include <linux/init.h>
#include <linux/init.h>
#include <asm/cache.h>
#include <asm/cache.h>
@@ -110,31 +109,36 @@ STACK_SIZE = 1 << STACK_SHIFT
1:	stm	%r10,%r11,\lc_sum
1:	stm	%r10,%r11,\lc_sum
	.endm
	.endm


	.macro	SAVE_ALL_BASE savearea
	.macro	SAVE_ALL_SVC psworg,savearea
	stm	%r12,%r15,\savearea
	stm	%r12,%r15,\savearea
	l	%r13,__LC_SVC_NEW_PSW+4	# load &system_call to %r13
	l	%r13,__LC_SVC_NEW_PSW+4	# load &system_call to %r13
	l	%r15,__LC_KERNEL_STACK	# problem state -> load ksp
	s	%r15,BASED(.Lc_spsize)	# make room for registers & psw
	.endm
	.endm


	.macro	SAVE_ALL_SVC psworg,savearea
	.macro	SAVE_ALL_BASE savearea
	la	%r12,\psworg
	stm	%r12,%r15,\savearea
	l	%r15,__LC_KERNEL_STACK	# problem state -> load ksp
	l	%r13,__LC_SVC_NEW_PSW+4	# load &system_call to %r13
	.endm
	.endm


	.macro	SAVE_ALL_SYNC psworg,savearea
	.macro	SAVE_ALL_PGM psworg,savearea
	la	%r12,\psworg
	tm	\psworg+1,0x01		# test problem state bit
	tm	\psworg+1,0x01		# test problem state bit
	bz	BASED(2f)		# skip stack setup save
	l	%r15,__LC_KERNEL_STACK	# problem state -> load ksp
#ifdef CONFIG_CHECK_STACK
#ifdef CONFIG_CHECK_STACK
	b	BASED(3f)
	bnz	BASED(1f)
2:	tml	%r15,STACK_SIZE - CONFIG_STACK_GUARD
	tml	%r15,STACK_SIZE - CONFIG_STACK_GUARD
	bz	BASED(stack_overflow)
	bnz	BASED(2f)
3:
	la	%r12,\psworg
	b	BASED(stack_overflow)
#else
	bz	BASED(2f)
#endif
#endif
2:
1:	l	%r15,__LC_KERNEL_STACK	# problem state -> load ksp
2:	s	%r15,BASED(.Lc_spsize)	# make room for registers & psw
	.endm
	.endm


	.macro	SAVE_ALL_ASYNC psworg,savearea
	.macro	SAVE_ALL_ASYNC psworg,savearea
	stm	%r12,%r15,\savearea
	l	%r13,__LC_SVC_NEW_PSW+4	# load &system_call to %r13
	la	%r12,\psworg
	la	%r12,\psworg
	tm	\psworg+1,0x01		# test problem state bit
	tm	\psworg+1,0x01		# test problem state bit
	bnz	BASED(1f)		# from user -> load async stack
	bnz	BASED(1f)		# from user -> load async stack
@@ -149,27 +153,23 @@ STACK_SIZE = 1 << STACK_SHIFT
0:	l	%r14,__LC_ASYNC_STACK	# are we already on the async stack ?
0:	l	%r14,__LC_ASYNC_STACK	# are we already on the async stack ?
	slr	%r14,%r15
	slr	%r14,%r15
	sra	%r14,STACK_SHIFT
	sra	%r14,STACK_SHIFT
	be	BASED(2f)
1:	l	%r15,__LC_ASYNC_STACK
#ifdef CONFIG_CHECK_STACK
#ifdef CONFIG_CHECK_STACK
	b	BASED(3f)
	bnz	BASED(1f)
2:	tml	%r15,STACK_SIZE - CONFIG_STACK_GUARD
	tml	%r15,STACK_SIZE - CONFIG_STACK_GUARD
	bz	BASED(stack_overflow)
	bnz	BASED(2f)
3:
	b	BASED(stack_overflow)
#else
	bz	BASED(2f)
#endif
#endif
2:
1:	l	%r15,__LC_ASYNC_STACK
2:	s	%r15,BASED(.Lc_spsize)	# make room for registers & psw
	.endm
	.endm


	.macro	CREATE_STACK_FRAME psworg,savearea
	.macro	CREATE_STACK_FRAME savearea
	s	%r15,BASED(.Lc_spsize)	# make room for registers & psw
	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
	mvc	SP_PSW(8,%r15),0(%r12)	# move user PSW to stack
	st	%r2,SP_ORIG_R2(%r15)	# store original content of gpr 2
	st	%r2,SP_ORIG_R2(%r15)	# store original content of gpr 2
	icm	%r12,12,__LC_SVC_ILC
	stm	%r0,%r11,SP_R0(%r15)	# store gprs %r0-%r11 to kernel stack
	st	%r12,SP_ILC(%r15)
	mvc	SP_R12(16,%r15),\savearea # move %r12-%r15 to stack
	mvc	SP_R12(16,%r15),\savearea # move %r12-%r15 to stack
	la	%r12,0
	stm	%r0,%r11,SP_R0(%r15)	# store gprs %r0-%r11 to kernel stack
	st	%r12,__SF_BACKCHAIN(%r15)	# clear back chain
	.endm
	.endm


	.macro	RESTORE_ALL psworg,sync
	.macro	RESTORE_ALL psworg,sync
@@ -237,10 +237,11 @@ __critical_start:
system_call:
system_call:
	stpt	__LC_SYNC_ENTER_TIMER
	stpt	__LC_SYNC_ENTER_TIMER
sysc_saveall:
sysc_saveall:
	SAVE_ALL_BASE __LC_SAVE_AREA
	SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
	SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
	CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
	CREATE_STACK_FRAME __LC_SAVE_AREA
	lh	%r7,0x8a	  # get svc number from lowcore
	mvc	SP_PSW(8,%r15),__LC_SVC_OLD_PSW
	mvc	SP_ILC(4,%r15),__LC_SVC_ILC
	l	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
sysc_vtime:
sysc_vtime:
	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
sysc_stime:
sysc_stime:
@@ -248,20 +249,20 @@ sysc_stime:
sysc_update:
sysc_update:
	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
sysc_do_svc:
sysc_do_svc:
	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
	xr	%r7,%r7
	ltr	%r7,%r7			# test for svc 0
	icm	%r7,3,SP_SVCNR(%r15)	# load svc number and test for svc 0
	bnz	BASED(sysc_nr_ok)	# svc number > 0
	bnz	BASED(sysc_nr_ok)	# svc number > 0
	# svc 0: system call number in %r1
	# svc 0: system call number in %r1
	cl	%r1,BASED(.Lnr_syscalls)
	cl	%r1,BASED(.Lnr_syscalls)
	bnl	BASED(sysc_nr_ok)
	bnl	BASED(sysc_nr_ok)
	sth	%r1,SP_SVCNR(%r15)
	lr	%r7,%r1 	  # copy svc number to %r7
	lr	%r7,%r1 	  # copy svc number to %r7
sysc_nr_ok:
sysc_nr_ok:
	sth	%r7,SP_SVCNR(%r15)
	sll	%r7,2		  # svc number *4
	sll	%r7,2		  # svc number *4
	l	%r8,BASED(.Lsysc_table)
	l	%r10,BASED(.Lsysc_table)
	tm	__TI_flags+2(%r9),_TIF_SYSCALL
	tm	__TI_flags+2(%r12),_TIF_SYSCALL
	mvc	SP_ARGS(4,%r15),SP_R7(%r15)
	mvc	SP_ARGS(4,%r15),SP_R7(%r15)
	l	%r8,0(%r7,%r8)	  # get system call addr.
	l	%r8,0(%r7,%r10)	  # get system call addr.
	bnz	BASED(sysc_tracesys)
	bnz	BASED(sysc_tracesys)
	basr	%r14,%r8	  # call sys_xxxx
	basr	%r14,%r8	  # call sys_xxxx
	st	%r2,SP_R2(%r15)   # store return value (change R2 on stack)
	st	%r2,SP_R2(%r15)   # store return value (change R2 on stack)
@@ -269,7 +270,7 @@ sysc_nr_ok:
sysc_return:
sysc_return:
	LOCKDEP_SYS_EXIT
	LOCKDEP_SYS_EXIT
sysc_tif:
sysc_tif:
	tm	__TI_flags+3(%r9),_TIF_WORK_SVC
	tm	__TI_flags+3(%r12),_TIF_WORK_SVC
	bnz	BASED(sysc_work)  # there is work to do (signals etc.)
	bnz	BASED(sysc_work)  # there is work to do (signals etc.)
sysc_restore:
sysc_restore:
	RESTORE_ALL __LC_RETURN_PSW,1
	RESTORE_ALL __LC_RETURN_PSW,1
@@ -286,17 +287,17 @@ sysc_work:
# One of the work bits is on. Find out which one.
# One of the work bits is on. Find out which one.
#
#
sysc_work_tif:
sysc_work_tif:
	tm	__TI_flags+3(%r9),_TIF_MCCK_PENDING
	tm	__TI_flags+3(%r12),_TIF_MCCK_PENDING
	bo	BASED(sysc_mcck_pending)
	bo	BASED(sysc_mcck_pending)
	tm	__TI_flags+3(%r9),_TIF_NEED_RESCHED
	tm	__TI_flags+3(%r12),_TIF_NEED_RESCHED
	bo	BASED(sysc_reschedule)
	bo	BASED(sysc_reschedule)
	tm	__TI_flags+3(%r9),_TIF_SIGPENDING
	tm	__TI_flags+3(%r12),_TIF_SIGPENDING
	bo	BASED(sysc_sigpending)
	bo	BASED(sysc_sigpending)
	tm	__TI_flags+3(%r9),_TIF_NOTIFY_RESUME
	tm	__TI_flags+3(%r12),_TIF_NOTIFY_RESUME
	bo	BASED(sysc_notify_resume)
	bo	BASED(sysc_notify_resume)
	tm	__TI_flags+3(%r9),_TIF_RESTART_SVC
	tm	__TI_flags+3(%r12),_TIF_RESTART_SVC
	bo	BASED(sysc_restart)
	bo	BASED(sysc_restart)
	tm	__TI_flags+3(%r9),_TIF_SINGLE_STEP
	tm	__TI_flags+3(%r12),_TIF_SINGLE_STEP
	bo	BASED(sysc_singlestep)
	bo	BASED(sysc_singlestep)
	b	BASED(sysc_return)	# beware of critical section cleanup
	b	BASED(sysc_return)	# beware of critical section cleanup


@@ -320,13 +321,13 @@ sysc_mcck_pending:
# _TIF_SIGPENDING is set, call do_signal
# _TIF_SIGPENDING is set, call do_signal
#
#
sysc_sigpending:
sysc_sigpending:
	ni	__TI_flags+3(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
	ni	__TI_flags+3(%r12),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
	la	%r2,SP_PTREGS(%r15)	# load pt_regs
	la	%r2,SP_PTREGS(%r15)	# load pt_regs
	l	%r1,BASED(.Ldo_signal)
	l	%r1,BASED(.Ldo_signal)
	basr	%r14,%r1		# call do_signal
	basr	%r14,%r1		# call do_signal
	tm	__TI_flags+3(%r9),_TIF_RESTART_SVC
	tm	__TI_flags+3(%r12),_TIF_RESTART_SVC
	bo	BASED(sysc_restart)
	bo	BASED(sysc_restart)
	tm	__TI_flags+3(%r9),_TIF_SINGLE_STEP
	tm	__TI_flags+3(%r12),_TIF_SINGLE_STEP
	bo	BASED(sysc_singlestep)
	bo	BASED(sysc_singlestep)
	b	BASED(sysc_return)
	b	BASED(sysc_return)


@@ -344,19 +345,19 @@ sysc_notify_resume:
# _TIF_RESTART_SVC is set, set up registers and restart svc
# _TIF_RESTART_SVC is set, set up registers and restart svc
#
#
sysc_restart:
sysc_restart:
	ni	__TI_flags+3(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
	ni	__TI_flags+3(%r12),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
	l	%r7,SP_R2(%r15) 	# load new svc number
	l	%r7,SP_R2(%r15) 	# load new svc number
	mvc	SP_R2(4,%r15),SP_ORIG_R2(%r15) # restore first argument
	mvc	SP_R2(4,%r15),SP_ORIG_R2(%r15) # restore first argument
	lm	%r2,%r6,SP_R2(%r15)	# load svc arguments
	lm	%r2,%r6,SP_R2(%r15)	# load svc arguments
	sth	%r7,SP_SVCNR(%r15)
	b	BASED(sysc_nr_ok)	# restart svc
	b	BASED(sysc_nr_ok)	# restart svc


#
#
# _TIF_SINGLE_STEP is set, call do_single_step
# _TIF_SINGLE_STEP is set, call do_single_step
#
#
sysc_singlestep:
sysc_singlestep:
	ni	__TI_flags+3(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
	ni	__TI_flags+3(%r12),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
	mvi	SP_SVCNR(%r15),0xff	# set trap indication to pgm check
	xc	SP_SVCNR(2,%r15),SP_SVCNR(%r15)		# clear svc number
	mvi	SP_SVCNR+1(%r15),0xff
	la	%r2,SP_PTREGS(%r15)	# address of register-save area
	la	%r2,SP_PTREGS(%r15)	# address of register-save area
	l	%r1,BASED(.Lhandle_per)	# load adr. of per handler
	l	%r1,BASED(.Lhandle_per)	# load adr. of per handler
	la	%r14,BASED(sysc_return)	# load adr. of system return
	la	%r14,BASED(sysc_return)	# load adr. of system return
@@ -370,15 +371,15 @@ sysc_tracesys:
	l	%r1,BASED(.Ltrace_entry)
	l	%r1,BASED(.Ltrace_entry)
	la	%r2,SP_PTREGS(%r15)	# load pt_regs
	la	%r2,SP_PTREGS(%r15)	# load pt_regs
	la	%r3,0
	la	%r3,0
	srl	%r7,2
	xr	%r0,%r0
	st	%r7,SP_R2(%r15)
	icm	%r0,3,SP_SVCNR(%r15)
	st	%r0,SP_R2(%r15)
	basr	%r14,%r1
	basr	%r14,%r1
	cl	%r2,BASED(.Lnr_syscalls)
	cl	%r2,BASED(.Lnr_syscalls)
	bnl	BASED(sysc_tracenogo)
	bnl	BASED(sysc_tracenogo)
	l	%r8,BASED(.Lsysc_table)
	lr	%r7,%r2
	lr	%r7,%r2
	sll	%r7,2			# svc number *4
	sll	%r7,2			# svc number *4
	l	%r8,0(%r7,%r8)
	l	%r8,0(%r7,%r10)
sysc_tracego:
sysc_tracego:
	lm	%r3,%r6,SP_R3(%r15)
	lm	%r3,%r6,SP_R3(%r15)
	mvc	SP_ARGS(4,%r15),SP_R7(%r15)
	mvc	SP_ARGS(4,%r15),SP_R7(%r15)
@@ -386,7 +387,7 @@ sysc_tracego:
	basr	%r14,%r8		# call sys_xxx
	basr	%r14,%r8		# call sys_xxx
	st	%r2,SP_R2(%r15)		# store return value
	st	%r2,SP_R2(%r15)		# store return value
sysc_tracenogo:
sysc_tracenogo:
	tm	__TI_flags+2(%r9),_TIF_SYSCALL
	tm	__TI_flags+2(%r12),_TIF_SYSCALL
	bz	BASED(sysc_return)
	bz	BASED(sysc_return)
	l	%r1,BASED(.Ltrace_exit)
	l	%r1,BASED(.Ltrace_exit)
	la	%r2,SP_PTREGS(%r15)	# load pt_regs
	la	%r2,SP_PTREGS(%r15)	# load pt_regs
@@ -399,7 +400,7 @@ sysc_tracenogo:
	.globl	ret_from_fork
	.globl	ret_from_fork
ret_from_fork:
ret_from_fork:
	l	%r13,__LC_SVC_NEW_PSW+4
	l	%r13,__LC_SVC_NEW_PSW+4
	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
	l	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
	tm	SP_PSW+1(%r15),0x01	# forking a kernel thread ?
	tm	SP_PSW+1(%r15),0x01	# forking a kernel thread ?
	bo	BASED(0f)
	bo	BASED(0f)
	st	%r15,SP_R15(%r15)	# store stack pointer for new kthread
	st	%r15,SP_R15(%r15)	# store stack pointer for new kthread
@@ -434,8 +435,8 @@ kernel_execve:
0:	stnsm	__SF_EMPTY(%r15),0xfc	# disable interrupts
0:	stnsm	__SF_EMPTY(%r15),0xfc	# disable interrupts
	l	%r15,__LC_KERNEL_STACK	# load ksp
	l	%r15,__LC_KERNEL_STACK	# load ksp
	s	%r15,BASED(.Lc_spsize)	# make room for registers & psw
	s	%r15,BASED(.Lc_spsize)	# make room for registers & psw
	l	%r9,__LC_THREAD_INFO
	mvc	SP_PTREGS(__PT_SIZE,%r15),0(%r12)	# copy pt_regs
	mvc	SP_PTREGS(__PT_SIZE,%r15),0(%r12)	# copy pt_regs
	l	%r12,__LC_THREAD_INFO
	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
	l	%r1,BASED(.Lexecve_tail)
	l	%r1,BASED(.Lexecve_tail)
@@ -465,26 +466,27 @@ pgm_check_handler:
	SAVE_ALL_BASE __LC_SAVE_AREA
	SAVE_ALL_BASE __LC_SAVE_AREA
	tm	__LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
	tm	__LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
	bnz	BASED(pgm_per)		# got per exception -> special case
	bnz	BASED(pgm_per)		# got per exception -> special case
	SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA
	SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA
	CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
	CREATE_STACK_FRAME __LC_SAVE_AREA
	xc	SP_ILC(4,%r15),SP_ILC(%r15)
	mvc	SP_PSW(8,%r15),__LC_PGM_OLD_PSW
	l	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
	bz	BASED(pgm_no_vtime)
	bz	BASED(pgm_no_vtime)
	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
pgm_no_vtime:
pgm_no_vtime:
	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
	l	%r3,__LC_PGM_ILC	# load program interruption code
	l	%r3,__LC_PGM_ILC	# load program interruption code
	l	%r4,__LC_TRANS_EXC_CODE
	l	%r4,__LC_TRANS_EXC_CODE
	REENABLE_IRQS
	REENABLE_IRQS
	la	%r8,0x7f
	la	%r8,0x7f
	nr	%r8,%r3
	nr	%r8,%r3
pgm_do_call:
	l	%r7,BASED(.Ljump_table)
	sll	%r8,2
	sll	%r8,2
	l	%r7,0(%r8,%r7)		# load address of handler routine
	l	%r1,BASED(.Ljump_table)
	l	%r1,0(%r8,%r1)		# load address of handler routine
	la	%r2,SP_PTREGS(%r15)	# address of register-save area
	la	%r2,SP_PTREGS(%r15)	# address of register-save area
	basr	%r14,%r7		# branch to interrupt-handler
	basr	%r14,%r1		# branch to interrupt-handler
pgm_exit:
pgm_exit:
	b	BASED(sysc_return)
	b	BASED(sysc_return)


@@ -505,33 +507,34 @@ pgm_per:
# Normal per exception
# Normal per exception
#
#
pgm_per_std:
pgm_per_std:
	SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA
	SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA
	CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
	CREATE_STACK_FRAME __LC_SAVE_AREA
	mvc	SP_PSW(8,%r15),__LC_PGM_OLD_PSW
	l	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
	bz	BASED(pgm_no_vtime2)
	bz	BASED(pgm_no_vtime2)
	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
pgm_no_vtime2:
pgm_no_vtime2:
	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
	l	%r1,__TI_task(%r12)
	l	%r1,__TI_task(%r9)
	tm	SP_PSW+1(%r15),0x01	# kernel per event ?
	tm	SP_PSW+1(%r15),0x01	# kernel per event ?
	bz	BASED(kernel_per)
	bz	BASED(kernel_per)
	mvc	__THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID
	mvc	__THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID
	mvc	__THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS
	mvc	__THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS
	mvc	__THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
	mvc	__THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
	oi	__TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
	oi	__TI_flags+3(%r12),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
	l	%r3,__LC_PGM_ILC	# load program interruption code
	l	%r3,__LC_PGM_ILC	# load program interruption code
	l	%r4,__LC_TRANS_EXC_CODE
	l	%r4,__LC_TRANS_EXC_CODE
	REENABLE_IRQS
	REENABLE_IRQS
	la	%r8,0x7f
	la	%r8,0x7f
	nr	%r8,%r3 		# clear per-event-bit and ilc
	nr	%r8,%r3 		# clear per-event-bit and ilc
	be	BASED(pgm_exit2)	# only per or per+check ?
	be	BASED(pgm_exit2)	# only per or per+check ?
	l	%r7,BASED(.Ljump_table)
	sll	%r8,2
	sll	%r8,2
	l	%r7,0(%r8,%r7)		# load address of handler routine
	l	%r1,BASED(.Ljump_table)
	l	%r1,0(%r8,%r1)		# load address of handler routine
	la	%r2,SP_PTREGS(%r15)	# address of register-save area
	la	%r2,SP_PTREGS(%r15)	# address of register-save area
	basr	%r14,%r7		# branch to interrupt-handler
	basr	%r14,%r1		# branch to interrupt-handler
pgm_exit2:
pgm_exit2:
	b	BASED(sysc_return)
	b	BASED(sysc_return)


@@ -539,18 +542,19 @@ pgm_exit2:
# it was a single stepped SVC that is causing all the trouble
# it was a single stepped SVC that is causing all the trouble
#
#
pgm_svcper:
pgm_svcper:
	SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
	SAVE_ALL_PGM __LC_SVC_OLD_PSW,__LC_SAVE_AREA
	CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
	CREATE_STACK_FRAME __LC_SAVE_AREA
	mvc	SP_PSW(8,%r15),__LC_SVC_OLD_PSW
	mvc	SP_ILC(4,%r15),__LC_SVC_ILC
	l	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
	lh	%r7,0x8a		# get svc number from lowcore
	l	%r8,__TI_task(%r12)
	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
	l	%r8,__TI_task(%r9)
	mvc	__THREAD_per+__PER_atmid(2,%r8),__LC_PER_ATMID
	mvc	__THREAD_per+__PER_atmid(2,%r8),__LC_PER_ATMID
	mvc	__THREAD_per+__PER_address(4,%r8),__LC_PER_ADDRESS
	mvc	__THREAD_per+__PER_address(4,%r8),__LC_PER_ADDRESS
	mvc	__THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID
	mvc	__THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID
	oi	__TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
	oi	__TI_flags+3(%r12),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
	lm	%r2,%r6,SP_R2(%r15)	# load svc arguments
	lm	%r2,%r6,SP_R2(%r15)	# load svc arguments
	b	BASED(sysc_do_svc)
	b	BASED(sysc_do_svc)
@@ -560,8 +564,7 @@ pgm_svcper:
#
#
kernel_per:
kernel_per:
	REENABLE_IRQS
	REENABLE_IRQS
	mvi	SP_SVCNR(%r15),0xff	# set trap indication to pgm check
	xc	SP_SVCNR(2,%r15),SP_SVCNR(%r15)
	mvi	SP_SVCNR+1(%r15),0xff
	la	%r2,SP_PTREGS(%r15)	# address of register-save area
	la	%r2,SP_PTREGS(%r15)	# address of register-save area
	l	%r1,BASED(.Lhandle_per)	# load adr. of per handler
	l	%r1,BASED(.Lhandle_per)	# load adr. of per handler
	basr	%r14,%r1		# branch to do_single_step
	basr	%r14,%r1		# branch to do_single_step
@@ -575,9 +578,10 @@ kernel_per:
io_int_handler:
io_int_handler:
	stck	__LC_INT_CLOCK
	stck	__LC_INT_CLOCK
	stpt	__LC_ASYNC_ENTER_TIMER
	stpt	__LC_ASYNC_ENTER_TIMER
	SAVE_ALL_BASE __LC_SAVE_AREA+16
	SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+16
	SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+16
	CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+16
	CREATE_STACK_FRAME __LC_SAVE_AREA+16
	mvc	SP_PSW(8,%r15),0(%r12)	# move user PSW to stack
	l	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
	bz	BASED(io_no_vtime)
	bz	BASED(io_no_vtime)
	UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
	UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
@@ -585,7 +589,6 @@ io_int_handler:
	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
io_no_vtime:
io_no_vtime:
	TRACE_IRQS_OFF
	TRACE_IRQS_OFF
	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
	l	%r1,BASED(.Ldo_IRQ)	# load address of do_IRQ
	l	%r1,BASED(.Ldo_IRQ)	# load address of do_IRQ
	la	%r2,SP_PTREGS(%r15)	# address of register-save area
	la	%r2,SP_PTREGS(%r15)	# address of register-save area
	basr	%r14,%r1		# branch to standard irq handler
	basr	%r14,%r1		# branch to standard irq handler
@@ -593,7 +596,7 @@ io_return:
	LOCKDEP_SYS_EXIT
	LOCKDEP_SYS_EXIT
	TRACE_IRQS_ON
	TRACE_IRQS_ON
io_tif:
io_tif:
	tm	__TI_flags+3(%r9),_TIF_WORK_INT
	tm	__TI_flags+3(%r12),_TIF_WORK_INT
	bnz	BASED(io_work)		# there is work to do (signals etc.)
	bnz	BASED(io_work)		# there is work to do (signals etc.)
io_restore:
io_restore:
	RESTORE_ALL __LC_RETURN_PSW,0
	RESTORE_ALL __LC_RETURN_PSW,0
@@ -611,9 +614,9 @@ io_work:
	bo	BASED(io_work_user)	# yes -> do resched & signal
	bo	BASED(io_work_user)	# yes -> do resched & signal
#ifdef CONFIG_PREEMPT
#ifdef CONFIG_PREEMPT
	# check for preemptive scheduling
	# check for preemptive scheduling
	icm	%r0,15,__TI_precount(%r9)
	icm	%r0,15,__TI_precount(%r12)
	bnz	BASED(io_restore)	# preemption disabled
	bnz	BASED(io_restore)	# preemption disabled
	tm	__TI_flags+3(%r9),_TIF_NEED_RESCHED
	tm	__TI_flags+3(%r12),_TIF_NEED_RESCHED
	bno	BASED(io_restore)
	bno	BASED(io_restore)
	# switch to kernel stack
	# switch to kernel stack
	l	%r1,SP_R15(%r15)
	l	%r1,SP_R15(%r15)
@@ -647,13 +650,13 @@ io_work_user:
#		and _TIF_MCCK_PENDING
#		and _TIF_MCCK_PENDING
#
#
io_work_tif:
io_work_tif:
	tm	__TI_flags+3(%r9),_TIF_MCCK_PENDING
	tm	__TI_flags+3(%r12),_TIF_MCCK_PENDING
	bo	BASED(io_mcck_pending)
	bo	BASED(io_mcck_pending)
	tm	__TI_flags+3(%r9),_TIF_NEED_RESCHED
	tm	__TI_flags+3(%r12),_TIF_NEED_RESCHED
	bo	BASED(io_reschedule)
	bo	BASED(io_reschedule)
	tm	__TI_flags+3(%r9),_TIF_SIGPENDING
	tm	__TI_flags+3(%r12),_TIF_SIGPENDING
	bo	BASED(io_sigpending)
	bo	BASED(io_sigpending)
	tm	__TI_flags+3(%r9),_TIF_NOTIFY_RESUME
	tm	__TI_flags+3(%r12),_TIF_NOTIFY_RESUME
	bo	BASED(io_notify_resume)
	bo	BASED(io_notify_resume)
	b	BASED(io_return)	# beware of critical section cleanup
	b	BASED(io_return)	# beware of critical section cleanup


@@ -713,16 +716,16 @@ io_notify_resume:
ext_int_handler:
ext_int_handler:
	stck	__LC_INT_CLOCK
	stck	__LC_INT_CLOCK
	stpt	__LC_ASYNC_ENTER_TIMER
	stpt	__LC_ASYNC_ENTER_TIMER
	SAVE_ALL_BASE __LC_SAVE_AREA+16
	SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16
	SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16
	CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16
	CREATE_STACK_FRAME __LC_SAVE_AREA+16
	mvc	SP_PSW(8,%r15),0(%r12)	# move user PSW to stack
	l	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
	bz	BASED(ext_no_vtime)
	bz	BASED(ext_no_vtime)
	UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
	UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
ext_no_vtime:
ext_no_vtime:
	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
	TRACE_IRQS_OFF
	TRACE_IRQS_OFF
	la	%r2,SP_PTREGS(%r15)	# address of register-save area
	la	%r2,SP_PTREGS(%r15)	# address of register-save area
	l	%r3,__LC_CPU_ADDRESS	# get cpu address + interruption code
	l	%r3,__LC_CPU_ADDRESS	# get cpu address + interruption code
@@ -777,7 +780,10 @@ mcck_int_main:
	sra	%r14,PAGE_SHIFT
	sra	%r14,PAGE_SHIFT
	be	BASED(0f)
	be	BASED(0f)
	l	%r15,__LC_PANIC_STACK	# load panic stack
	l	%r15,__LC_PANIC_STACK	# load panic stack
0:	CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+32
0:	s	%r15,BASED(.Lc_spsize)	# make room for registers & psw
	CREATE_STACK_FRAME __LC_SAVE_AREA+32
	mvc	SP_PSW(8,%r15),0(%r12)
	l	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
	tm	__LC_MCCK_CODE+2,0x08	# mwp of old psw valid?
	tm	__LC_MCCK_CODE+2,0x08	# mwp of old psw valid?
	bno	BASED(mcck_no_vtime)	# no -> skip cleanup critical
	bno	BASED(mcck_no_vtime)	# no -> skip cleanup critical
	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
@@ -786,7 +792,6 @@ mcck_int_main:
	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_MCCK_ENTER_TIMER
	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_MCCK_ENTER_TIMER
mcck_no_vtime:
mcck_no_vtime:
	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
	la	%r2,SP_PTREGS(%r15)	# load pt_regs
	la	%r2,SP_PTREGS(%r15)	# load pt_regs
	l	%r1,BASED(.Ls390_mcck)
	l	%r1,BASED(.Ls390_mcck)
	basr	%r14,%r1		# call machine check handler
	basr	%r14,%r1		# call machine check handler
@@ -798,7 +803,7 @@ mcck_no_vtime:
	xc	__SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
	xc	__SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
	lr	%r15,%r1
	lr	%r15,%r1
	stosm	__SF_EMPTY(%r15),0x04	# turn dat on
	stosm	__SF_EMPTY(%r15),0x04	# turn dat on
	tm	__TI_flags+3(%r9),_TIF_MCCK_PENDING
	tm	__TI_flags+3(%r12),_TIF_MCCK_PENDING
	bno	BASED(mcck_return)
	bno	BASED(mcck_return)
	TRACE_IRQS_OFF
	TRACE_IRQS_OFF
	l	%r1,BASED(.Ls390_handle_mcck)
	l	%r1,BASED(.Ls390_handle_mcck)
@@ -947,12 +952,13 @@ cleanup_system_call:
	bh	BASED(0f)
	bh	BASED(0f)
	mvc	__LC_SAVE_AREA(16),0(%r12)
	mvc	__LC_SAVE_AREA(16),0(%r12)
0:	st	%r13,4(%r12)
0:	st	%r13,4(%r12)
	st	%r12,__LC_SAVE_AREA+48	# argh
	l	%r15,__LC_KERNEL_STACK	# problem state -> load ksp
	SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
	s	%r15,BASED(.Lc_spsize)	# make room for registers & psw
	CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
	l	%r12,__LC_SAVE_AREA+48	# argh
	st	%r15,12(%r12)
	st	%r15,12(%r12)
	lh	%r7,0x8a
	CREATE_STACK_FRAME __LC_SAVE_AREA
	mvc	SP_PSW(8,%r15),__LC_SVC_OLD_PSW
	mvc	SP_ILC(4,%r15),__LC_SVC_ILC
	mvc	0(4,%r12),__LC_THREAD_INFO
cleanup_vtime:
cleanup_vtime:
	clc	__LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+12)
	clc	__LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+12)
	bhe	BASED(cleanup_stime)
	bhe	BASED(cleanup_stime)