[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: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
Martin Schwidefsky 2011-01-05 12:47:57 +01:00 committed by Martin Schwidefsky
parent ce322ccd53
commit 1de3447a41

View file

@ -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_SVC psworg,savearea
stm %r12,%r15,\savearea
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
.macro SAVE_ALL_BASE savearea .macro SAVE_ALL_BASE 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
.endm .endm
.macro SAVE_ALL_SVC psworg,savearea .macro SAVE_ALL_PGM psworg,savearea
la %r12,\psworg
l %r15,__LC_KERNEL_STACK # problem state -> load ksp
.endm
.macro SAVE_ALL_SYNC 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)