basr %r14,%r1
.endm
- .macro TRACE_IRQS_CHECK
- basr %r2,%r0
+ .macro TRACE_IRQS_CHECK_ON
tm SP_PSW(%r15),0x03 # irqs enabled?
- jz 0f
- l %r1,BASED(.Ltrace_irq_on_caller)
- basr %r14,%r1
- j 1f
-0: l %r1,BASED(.Ltrace_irq_off_caller)
- basr %r14,%r1
-1:
+ bz BASED(0f)
+ TRACE_IRQS_ON
+0:
+ .endm
+
+ .macro TRACE_IRQS_CHECK_OFF
+ tm SP_PSW(%r15),0x03 # irqs enabled?
+ bz BASED(0f)
+ TRACE_IRQS_OFF
+0:
.endm
#else
#define TRACE_IRQS_ON
#define TRACE_IRQS_OFF
-#define TRACE_IRQS_CHECK
+#define TRACE_IRQS_CHECK_ON
+#define TRACE_IRQS_CHECK_OFF
#endif
#ifdef CONFIG_LOCKDEP
st %r2,SP_R2(%r15) # store return value (change R2 on stack)
sysc_return:
+ LOCKDEP_SYS_EXIT
+sysc_tif:
tm __TI_flags+3(%r9),_TIF_WORK_SVC
bnz BASED(sysc_work) # there is work to do (signals etc.)
sysc_restore:
-#ifdef CONFIG_TRACE_IRQFLAGS
- la %r1,BASED(sysc_restore_trace_psw_addr)
- l %r1,0(%r1)
- lpsw 0(%r1)
-sysc_restore_trace:
- TRACE_IRQS_CHECK
- LOCKDEP_SYS_EXIT
-#endif
-sysc_leave:
RESTORE_ALL __LC_RETURN_PSW,1
sysc_done:
-#ifdef CONFIG_TRACE_IRQFLAGS
-sysc_restore_trace_psw_addr:
- .long sysc_restore_trace_psw
-
- .section .data,"aw",@progbits
- .align 8
- .globl sysc_restore_trace_psw
-sysc_restore_trace_psw:
- .long 0, sysc_restore_trace + 0x80000000
- .previous
-#endif
-
#
# There is work to do, but first we need to check if we return to userspace.
#
#
# One of the work bits is on. Find out which one.
#
-sysc_work_loop:
+sysc_work_tif:
tm __TI_flags+3(%r9),_TIF_MCCK_PENDING
bo BASED(sysc_mcck_pending)
tm __TI_flags+3(%r9),_TIF_NEED_RESCHED
#
sysc_reschedule:
l %r1,BASED(.Lschedule)
- la %r14,BASED(sysc_work_loop)
+ la %r14,BASED(sysc_return)
br %r1 # call scheduler
#
#
sysc_mcck_pending:
l %r1,BASED(.Ls390_handle_mcck)
- la %r14,BASED(sysc_work_loop)
+ la %r14,BASED(sysc_return)
br %r1 # TIF bit will be cleared by handler
#
bo BASED(sysc_restart)
tm __TI_flags+3(%r9),_TIF_SINGLE_STEP
bo BASED(sysc_singlestep)
- b BASED(sysc_work_loop)
+ b BASED(sysc_return)
#
# _TIF_NOTIFY_RESUME is set, call do_notify_resume
sysc_notify_resume:
la %r2,SP_PTREGS(%r15) # load pt_regs
l %r1,BASED(.Ldo_notify_resume)
- la %r14,BASED(sysc_work_loop)
+ la %r14,BASED(sysc_return)
br %r1 # call do_notify_resume
mvi SP_SVCNR+1(%r15),0xff
la %r2,SP_PTREGS(%r15) # address of register-save area
l %r1,BASED(.Lhandle_per) # load adr. of per handler
- la %r14,BASED(sysc_work_loop) # load adr. of system return
+ la %r14,BASED(sysc_return) # load adr. of system return
br %r1 # branch to do_single_step
#
br %r14
# execve succeeded.
0: stnsm __SF_EMPTY(%r15),0xfc # disable interrupts
+ TRACE_IRQS_OFF
l %r15,__LC_KERNEL_STACK # load ksp
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
xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
+ TRACE_IRQS_ON
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
l %r1,BASED(.Lexecve_tail)
basr %r14,%r1
UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
pgm_no_vtime:
+ TRACE_IRQS_CHECK_OFF
l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
- TRACE_IRQS_OFF
l %r3,__LC_PGM_ILC # load program interruption code
la %r8,0x7f
nr %r8,%r3
sll %r8,2
l %r7,0(%r8,%r7) # load address of handler routine
la %r2,SP_PTREGS(%r15) # address of register-save area
- la %r14,BASED(sysc_return)
- br %r7 # branch to interrupt-handler
+ basr %r14,%r7 # branch to interrupt-handler
+pgm_exit:
+ TRACE_IRQS_CHECK_ON
+ b BASED(sysc_return)
#
# handle per exception
UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
pgm_no_vtime2:
+ TRACE_IRQS_CHECK_OFF
l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
- TRACE_IRQS_OFF
l %r1,__TI_task(%r9)
+ tm SP_PSW+1(%r15),0x01 # kernel per event ?
+ bz BASED(kernel_per)
mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID
mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS
mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
oi __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
- tm SP_PSW+1(%r15),0x01 # kernel per event ?
- bz BASED(kernel_per)
l %r3,__LC_PGM_ILC # load program interruption code
la %r8,0x7f
nr %r8,%r3 # clear per-event-bit and ilc
- be BASED(sysc_return) # only per or per+check ?
+ be BASED(pgm_exit) # only per or per+check ?
b BASED(pgm_do_call)
#
mvc __THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID
oi __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
TRACE_IRQS_ON
- lm %r2,%r6,SP_R2(%r15) # load svc arguments
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
+ lm %r2,%r6,SP_R2(%r15) # load svc arguments
b BASED(sysc_do_svc)
#
mvi SP_SVCNR+1(%r15),0xff
la %r2,SP_PTREGS(%r15) # address of register-save area
l %r1,BASED(.Lhandle_per) # load adr. of per handler
- la %r14,BASED(sysc_restore)# load adr. of system return
- br %r1 # branch to do_single_step
+ basr %r14,%r1 # branch to do_single_step
+ b BASED(pgm_exit)
/*
* IO interrupt handler routine
UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
io_no_vtime:
- l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
TRACE_IRQS_OFF
+ l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
l %r1,BASED(.Ldo_IRQ) # load address of do_IRQ
la %r2,SP_PTREGS(%r15) # address of register-save area
basr %r14,%r1 # branch to standard irq handler
io_return:
+ LOCKDEP_SYS_EXIT
+ TRACE_IRQS_ON
+io_tif:
tm __TI_flags+3(%r9),_TIF_WORK_INT
bnz BASED(io_work) # there is work to do (signals etc.)
io_restore:
-#ifdef CONFIG_TRACE_IRQFLAGS
- la %r1,BASED(io_restore_trace_psw_addr)
- l %r1,0(%r1)
- lpsw 0(%r1)
-io_restore_trace:
- TRACE_IRQS_CHECK
- LOCKDEP_SYS_EXIT
-#endif
-io_leave:
RESTORE_ALL __LC_RETURN_PSW,0
io_done:
-#ifdef CONFIG_TRACE_IRQFLAGS
-io_restore_trace_psw_addr:
- .long io_restore_trace_psw
-
- .section .data,"aw",@progbits
- .align 8
- .globl io_restore_trace_psw
-io_restore_trace_psw:
- .long 0, io_restore_trace + 0x80000000
- .previous
-#endif
-
#
# 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
# check for preemptive scheduling
icm %r0,15,__TI_precount(%r9)
bnz BASED(io_restore) # preemption disabled
+ tm __TI_flags+3(%r9),_TIF_NEED_RESCHED
+ bno BASED(io_restore)
# switch to kernel stack
l %r1,SP_R15(%r15)
s %r1,BASED(.Lc_spsize)
mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
lr %r15,%r1
-io_resume_loop:
+ # TRACE_IRQS_ON already done at io_return, call
+ # TRACE_IRQS_OFF to keep things symmetrical
+ TRACE_IRQS_OFF
l %r1,BASED(.Lpreempt_schedule_irq)
- la %r14,BASED(io_resume_loop)
- tm __TI_flags+3(%r9),_TIF_NEED_RESCHED
- bor %r1 # call preempt_schedule_irq
-#endif
+ basr %r14,%r1 # call preempt_schedule_irq
+ b BASED(io_return)
+#else
b BASED(io_restore)
+#endif
#
# Need to do work before returning to userspace, switch to kernel stack
mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
lr %r15,%r1
+
#
# One of the work bits is on. Find out which one.
# Checked are: _TIF_SIGPENDING, _TIF_NOTIFY_RESUME, _TIF_NEED_RESCHED
# and _TIF_MCCK_PENDING
#
-io_work_loop:
+io_work_tif:
tm __TI_flags+3(%r9),_TIF_MCCK_PENDING
bo BASED(io_mcck_pending)
tm __TI_flags+3(%r9),_TIF_NEED_RESCHED
# _TIF_MCCK_PENDING is set, call handler
#
io_mcck_pending:
+ # TRACE_IRQS_ON already done at io_return
l %r1,BASED(.Ls390_handle_mcck)
basr %r14,%r1 # TIF bit will be cleared by handler
- b BASED(io_work_loop)
+ TRACE_IRQS_OFF
+ b BASED(io_return)
#
# _TIF_NEED_RESCHED is set, call schedule
#
io_reschedule:
- TRACE_IRQS_ON
+ # TRACE_IRQS_ON already done at io_return
l %r1,BASED(.Lschedule)
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
basr %r14,%r1 # call scheduler
stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
TRACE_IRQS_OFF
- b BASED(io_work_loop)
+ b BASED(io_return)
#
# _TIF_SIGPENDING is set, call do_signal
#
io_sigpending:
- TRACE_IRQS_ON
+ # TRACE_IRQS_ON already done at io_return
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
la %r2,SP_PTREGS(%r15) # load pt_regs
l %r1,BASED(.Ldo_signal)
basr %r14,%r1 # call do_signal
stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
TRACE_IRQS_OFF
- b BASED(io_work_loop)
+ b BASED(io_return)
#
# _TIF_SIGPENDING is set, call do_signal
#
io_notify_resume:
- TRACE_IRQS_ON
+ # TRACE_IRQS_ON already done at io_return
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
la %r2,SP_PTREGS(%r15) # load pt_regs
l %r1,BASED(.Ldo_notify_resume)
basr %r14,%r1 # call do_signal
stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
TRACE_IRQS_OFF
- b BASED(io_work_loop)
+ b BASED(io_return)
/*
* External interrupt handler routine
cleanup_table_system_call:
.long system_call + 0x80000000, sysc_do_svc + 0x80000000
-cleanup_table_sysc_return:
- .long sysc_return + 0x80000000, sysc_leave + 0x80000000
-cleanup_table_sysc_leave:
- .long sysc_leave + 0x80000000, sysc_done + 0x80000000
-cleanup_table_io_return:
- .long io_return + 0x80000000, io_leave + 0x80000000
-cleanup_table_io_leave:
- .long io_leave + 0x80000000, io_done + 0x80000000
+cleanup_table_sysc_tif:
+ .long sysc_tif + 0x80000000, sysc_restore + 0x80000000
+cleanup_table_sysc_restore:
+ .long sysc_restore + 0x80000000, sysc_done + 0x80000000
+cleanup_table_io_tif:
+ .long io_tif + 0x80000000, io_restore + 0x80000000
+cleanup_table_io_restore:
+ .long io_restore + 0x80000000, io_done + 0x80000000
cleanup_critical:
clc 4(4,%r12),BASED(cleanup_table_system_call)
clc 4(4,%r12),BASED(cleanup_table_system_call+4)
bl BASED(cleanup_system_call)
0:
- clc 4(4,%r12),BASED(cleanup_table_sysc_return)
+ clc 4(4,%r12),BASED(cleanup_table_sysc_tif)
bl BASED(0f)
- clc 4(4,%r12),BASED(cleanup_table_sysc_return+4)
- bl BASED(cleanup_sysc_return)
+ clc 4(4,%r12),BASED(cleanup_table_sysc_tif+4)
+ bl BASED(cleanup_sysc_tif)
0:
- clc 4(4,%r12),BASED(cleanup_table_sysc_leave)
+ clc 4(4,%r12),BASED(cleanup_table_sysc_restore)
bl BASED(0f)
- clc 4(4,%r12),BASED(cleanup_table_sysc_leave+4)
- bl BASED(cleanup_sysc_leave)
+ clc 4(4,%r12),BASED(cleanup_table_sysc_restore+4)
+ bl BASED(cleanup_sysc_restore)
0:
- clc 4(4,%r12),BASED(cleanup_table_io_return)
+ clc 4(4,%r12),BASED(cleanup_table_io_tif)
bl BASED(0f)
- clc 4(4,%r12),BASED(cleanup_table_io_return+4)
- bl BASED(cleanup_io_return)
+ clc 4(4,%r12),BASED(cleanup_table_io_tif+4)
+ bl BASED(cleanup_io_tif)
0:
- clc 4(4,%r12),BASED(cleanup_table_io_leave)
+ clc 4(4,%r12),BASED(cleanup_table_io_restore)
bl BASED(0f)
- clc 4(4,%r12),BASED(cleanup_table_io_leave+4)
- bl BASED(cleanup_io_leave)
+ clc 4(4,%r12),BASED(cleanup_table_io_restore+4)
+ bl BASED(cleanup_io_restore)
0:
br %r14
.long sysc_stime + 0x80000000
.long sysc_update + 0x80000000
-cleanup_sysc_return:
+cleanup_sysc_tif:
mvc __LC_RETURN_PSW(4),0(%r12)
- mvc __LC_RETURN_PSW+4(4),BASED(cleanup_table_sysc_return)
+ mvc __LC_RETURN_PSW+4(4),BASED(cleanup_table_sysc_tif)
la %r12,__LC_RETURN_PSW
br %r14
-cleanup_sysc_leave:
- clc 4(4,%r12),BASED(cleanup_sysc_leave_insn)
+cleanup_sysc_restore:
+ clc 4(4,%r12),BASED(cleanup_sysc_restore_insn)
be BASED(2f)
mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
- clc 4(4,%r12),BASED(cleanup_sysc_leave_insn+4)
+ clc 4(4,%r12),BASED(cleanup_sysc_restore_insn+4)
be BASED(2f)
mvc __LC_RETURN_PSW(8),SP_PSW(%r15)
c %r12,BASED(.Lmck_old_psw)
l %r15,SP_R15(%r15)
2: la %r12,__LC_RETURN_PSW
br %r14
-cleanup_sysc_leave_insn:
+cleanup_sysc_restore_insn:
.long sysc_done - 4 + 0x80000000
.long sysc_done - 8 + 0x80000000
-cleanup_io_return:
+cleanup_io_tif:
mvc __LC_RETURN_PSW(4),0(%r12)
- mvc __LC_RETURN_PSW+4(4),BASED(cleanup_table_io_return)
+ mvc __LC_RETURN_PSW+4(4),BASED(cleanup_table_io_tif)
la %r12,__LC_RETURN_PSW
br %r14
-cleanup_io_leave:
- clc 4(4,%r12),BASED(cleanup_io_leave_insn)
+cleanup_io_restore:
+ clc 4(4,%r12),BASED(cleanup_io_restore_insn)
be BASED(2f)
mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
- clc 4(4,%r12),BASED(cleanup_io_leave_insn+4)
+ clc 4(4,%r12),BASED(cleanup_io_restore_insn+4)
be BASED(2f)
mvc __LC_RETURN_PSW(8),SP_PSW(%r15)
c %r12,BASED(.Lmck_old_psw)
l %r15,SP_R15(%r15)
2: la %r12,__LC_RETURN_PSW
br %r14
-cleanup_io_leave_insn:
+cleanup_io_restore_insn:
.long io_done - 4 + 0x80000000
.long io_done - 8 + 0x80000000
#ifdef CONFIG_TRACE_IRQFLAGS
.macro TRACE_IRQS_ON
- basr %r2,%r0
- brasl %r14,trace_hardirqs_on_caller
+ basr %r2,%r0
+ brasl %r14,trace_hardirqs_on_caller
.endm
.macro TRACE_IRQS_OFF
- basr %r2,%r0
- brasl %r14,trace_hardirqs_off_caller
+ basr %r2,%r0
+ brasl %r14,trace_hardirqs_off_caller
.endm
- .macro TRACE_IRQS_CHECK
- basr %r2,%r0
+ .macro TRACE_IRQS_CHECK_ON
tm SP_PSW(%r15),0x03 # irqs enabled?
jz 0f
- brasl %r14,trace_hardirqs_on_caller
- j 1f
-0: brasl %r14,trace_hardirqs_off_caller
-1:
+ TRACE_IRQS_ON
+0:
+ .endm
+
+ .macro TRACE_IRQS_CHECK_OFF
+ tm SP_PSW(%r15),0x03 # irqs enabled?
+ jz 0f
+ TRACE_IRQS_OFF
+0:
.endm
#else
#define TRACE_IRQS_ON
#define TRACE_IRQS_OFF
-#define TRACE_IRQS_CHECK
+#define TRACE_IRQS_CHECK_ON
+#define TRACE_IRQS_CHECK_OFF
#endif
#ifdef CONFIG_LOCKDEP
stg %r2,SP_R2(%r15) # store return value (change R2 on stack)
sysc_return:
+ LOCKDEP_SYS_EXIT
+sysc_tif:
tm __TI_flags+7(%r9),_TIF_WORK_SVC
jnz sysc_work # there is work to do (signals etc.)
sysc_restore:
-#ifdef CONFIG_TRACE_IRQFLAGS
- larl %r1,sysc_restore_trace_psw
- lpswe 0(%r1)
-sysc_restore_trace:
- TRACE_IRQS_CHECK
- LOCKDEP_SYS_EXIT
-#endif
-sysc_leave:
RESTORE_ALL __LC_RETURN_PSW,1
sysc_done:
-#ifdef CONFIG_TRACE_IRQFLAGS
- .section .data,"aw",@progbits
- .align 8
- .globl sysc_restore_trace_psw
-sysc_restore_trace_psw:
- .quad 0, sysc_restore_trace
- .previous
-#endif
-
#
# There is work to do, but first we need to check if we return to userspace.
#
#
# One of the work bits is on. Find out which one.
#
-sysc_work_loop:
+sysc_work_tif:
tm __TI_flags+7(%r9),_TIF_MCCK_PENDING
jo sysc_mcck_pending
tm __TI_flags+7(%r9),_TIF_NEED_RESCHED
# _TIF_NEED_RESCHED is set, call schedule
#
sysc_reschedule:
- larl %r14,sysc_work_loop
- jg schedule # return point is sysc_work_loop
+ larl %r14,sysc_return
+ jg schedule # return point is sysc_return
#
# _TIF_MCCK_PENDING is set, call handler
#
sysc_mcck_pending:
- larl %r14,sysc_work_loop
+ larl %r14,sysc_return
jg s390_handle_mcck # TIF bit will be cleared by handler
#
jo sysc_restart
tm __TI_flags+7(%r9),_TIF_SINGLE_STEP
jo sysc_singlestep
- j sysc_work_loop
+ j sysc_return
#
# _TIF_NOTIFY_RESUME is set, call do_notify_resume
#
sysc_notify_resume:
la %r2,SP_PTREGS(%r15) # load pt_regs
- larl %r14,sysc_work_loop
+ larl %r14,sysc_return
jg do_notify_resume # call do_notify_resume
#
ni __TI_flags+7(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number
la %r2,SP_PTREGS(%r15) # address of register-save area
- larl %r14,sysc_work_loop # load adr. of system return
+ larl %r14,sysc_return # load adr. of system return
jg do_single_step # branch to do_sigtrap
#
br %r14
# execve succeeded.
0: stnsm __SF_EMPTY(%r15),0xfc # disable interrupts
+# TRACE_IRQS_OFF
lg %r15,__LC_KERNEL_STACK # load ksp
aghi %r15,-SP_SIZE # make room for registers & psw
lg %r13,__LC_SVC_NEW_PSW+8
lg %r9,__LC_THREAD_INFO
mvc SP_PTREGS(__PT_SIZE,%r15),0(%r12) # copy pt_regs
xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
+# TRACE_IRQS_ON
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
brasl %r14,execve_tail
j sysc_return
UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
pgm_no_vtime:
+ TRACE_IRQS_CHECK_OFF
lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
mvc SP_ARGS(8,%r15),__LC_LAST_BREAK
- TRACE_IRQS_OFF
lgf %r3,__LC_PGM_ILC # load program interruption code
lghi %r8,0x7f
ngr %r8,%r3
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
- larl %r14,sysc_return
- br %r1 # branch to interrupt-handler
+ basr %r14,%r1 # branch to interrupt-handler
+pgm_exit:
+ TRACE_IRQS_CHECK_ON
+ j sysc_return
#
# handle per exception
UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
pgm_no_vtime2:
+ TRACE_IRQS_CHECK_OFF
lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
- TRACE_IRQS_OFF
lg %r1,__TI_task(%r9)
tm SP_PSW+1(%r15),0x01 # kernel per event ?
jz kernel_per
lgf %r3,__LC_PGM_ILC # load program interruption code
lghi %r8,0x7f
ngr %r8,%r3 # clear per-event-bit and ilc
- je sysc_return
+ je pgm_exit
j pgm_do_call
#
mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore
lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
+ TRACE_IRQS_OFF
lg %r8,__TI_task(%r9)
mvc __THREAD_per+__PER_atmid(2,%r8),__LC_PER_ATMID
mvc __THREAD_per+__PER_address(8,%r8),__LC_PER_ADDRESS
mvc __THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID
oi __TI_flags+7(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
TRACE_IRQS_ON
- lmg %r2,%r6,SP_R2(%r15) # load svc arguments
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
+ lmg %r2,%r6,SP_R2(%r15) # load svc arguments
j sysc_do_svc
#
kernel_per:
xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number
la %r2,SP_PTREGS(%r15) # address of register-save area
- larl %r14,sysc_restore # load adr. of system ret, no work
- jg do_single_step # branch to do_single_step
+ brasl %r14,do_single_step
+ j pgm_exit
/*
* IO interrupt handler routine
la %r2,SP_PTREGS(%r15) # address of register-save area
brasl %r14,do_IRQ # call standard irq handler
io_return:
+ LOCKDEP_SYS_EXIT
+ TRACE_IRQS_ON
+io_tif:
tm __TI_flags+7(%r9),_TIF_WORK_INT
jnz io_work # there is work to do (signals etc.)
io_restore:
-#ifdef CONFIG_TRACE_IRQFLAGS
- larl %r1,io_restore_trace_psw
- lpswe 0(%r1)
-io_restore_trace:
- TRACE_IRQS_CHECK
- LOCKDEP_SYS_EXIT
-#endif
-io_leave:
RESTORE_ALL __LC_RETURN_PSW,0
io_done:
-#ifdef CONFIG_TRACE_IRQFLAGS
- .section .data,"aw",@progbits
- .align 8
- .globl io_restore_trace_psw
-io_restore_trace_psw:
- .quad 0, io_restore_trace
- .previous
-#endif
-
#
# 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
# check for preemptive scheduling
icm %r0,15,__TI_precount(%r9)
jnz io_restore # preemption is disabled
+ tm __TI_flags+7(%r12),_TIF_NEED_RESCHED
+ jno io_restore
# switch to kernel stack
lg %r1,SP_R15(%r15)
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
-io_resume_loop:
- larl %r14,io_resume_loop
- tm __TI_flags+7(%r12),_TIF_NEED_RESCHED
- jgo preempt_schedule_irq
-#endif
+ # 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
j io_restore
+#endif
#
# Need to do work before returning to userspace, switch to kernel stack
# Checked are: _TIF_SIGPENDING, _TIF_NOTIFY_RESUME, _TIF_NEED_RESCHED
# and _TIF_MCCK_PENDING
#
-io_work_loop:
+io_work_tif:
tm __TI_flags+7(%r9),_TIF_MCCK_PENDING
jo io_mcck_pending
tm __TI_flags+7(%r9),_TIF_NEED_RESCHED
# _TIF_MCCK_PENDING is set, call handler
#
io_mcck_pending:
+ # TRACE_IRQS_ON already done at io_return
brasl %r14,s390_handle_mcck # TIF bit will be cleared by handler
- j io_work_loop
+ TRACE_IRQS_OFF
+ j io_return
#
# _TIF_NEED_RESCHED is set, call schedule
#
io_reschedule:
- TRACE_IRQS_ON
+ # TRACE_IRQS_ON already done at io_return
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
brasl %r14,schedule # call scheduler
stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
TRACE_IRQS_OFF
- j io_work_loop
+ j io_return
#
# _TIF_SIGPENDING or is set, call do_signal
#
io_sigpending:
- TRACE_IRQS_ON
+ # TRACE_IRQS_ON already done at io_return
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
la %r2,SP_PTREGS(%r15) # load pt_regs
brasl %r14,do_signal # call do_signal
stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
TRACE_IRQS_OFF
- j io_work_loop
+ j io_return
#
# _TIF_NOTIFY_RESUME or is set, call do_notify_resume
#
io_notify_resume:
- TRACE_IRQS_ON
+ # TRACE_IRQS_ON already done at io_return
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
- j io_work_loop
+ j io_return
/*
* External interrupt handler routine
cleanup_table_system_call:
.quad system_call, sysc_do_svc
-cleanup_table_sysc_return:
- .quad sysc_return, sysc_leave
-cleanup_table_sysc_leave:
- .quad sysc_leave, sysc_done
-cleanup_table_io_return:
- .quad io_return, io_leave
-cleanup_table_io_leave:
- .quad io_leave, io_done
+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
cleanup_critical:
clc 8(8,%r12),BASED(cleanup_table_system_call)
clc 8(8,%r12),BASED(cleanup_table_system_call+8)
jl cleanup_system_call
0:
- clc 8(8,%r12),BASED(cleanup_table_sysc_return)
+ clc 8(8,%r12),BASED(cleanup_table_sysc_tif)
jl 0f
- clc 8(8,%r12),BASED(cleanup_table_sysc_return+8)
- jl cleanup_sysc_return
+ clc 8(8,%r12),BASED(cleanup_table_sysc_tif+8)
+ jl cleanup_sysc_tif
0:
- clc 8(8,%r12),BASED(cleanup_table_sysc_leave)
+ clc 8(8,%r12),BASED(cleanup_table_sysc_restore)
jl 0f
- clc 8(8,%r12),BASED(cleanup_table_sysc_leave+8)
- jl cleanup_sysc_leave
+ clc 8(8,%r12),BASED(cleanup_table_sysc_restore+8)
+ jl cleanup_sysc_restore
0:
- clc 8(8,%r12),BASED(cleanup_table_io_return)
+ clc 8(8,%r12),BASED(cleanup_table_io_tif)
jl 0f
- clc 8(8,%r12),BASED(cleanup_table_io_return+8)
- jl cleanup_io_return
+ clc 8(8,%r12),BASED(cleanup_table_io_tif+8)
+ jl cleanup_io_tif
0:
- clc 8(8,%r12),BASED(cleanup_table_io_leave)
+ clc 8(8,%r12),BASED(cleanup_table_io_restore)
jl 0f
- clc 8(8,%r12),BASED(cleanup_table_io_leave+8)
- jl cleanup_io_leave
+ clc 8(8,%r12),BASED(cleanup_table_io_restore+8)
+ jl cleanup_io_restore
0:
br %r14
.quad sysc_stime
.quad sysc_update
-cleanup_sysc_return:
+cleanup_sysc_tif:
mvc __LC_RETURN_PSW(8),0(%r12)
- mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_sysc_return)
+ mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_sysc_tif)
la %r12,__LC_RETURN_PSW
br %r14
-cleanup_sysc_leave:
- clc 8(8,%r12),BASED(cleanup_sysc_leave_insn)
+cleanup_sysc_restore:
+ clc 8(8,%r12),BASED(cleanup_sysc_restore_insn)
je 3f
- clc 8(8,%r12),BASED(cleanup_sysc_leave_insn+8)
+ clc 8(8,%r12),BASED(cleanup_sysc_restore_insn+8)
jhe 0f
mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
0: mvc __LC_RETURN_PSW(16),SP_PSW(%r15)
lg %r15,SP_R15(%r15)
3: la %r12,__LC_RETURN_PSW
br %r14
-cleanup_sysc_leave_insn:
+cleanup_sysc_restore_insn:
.quad sysc_done - 4
.quad sysc_done - 16
-cleanup_io_return:
+cleanup_io_tif:
mvc __LC_RETURN_PSW(8),0(%r12)
- mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_io_return)
+ mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_io_tif)
la %r12,__LC_RETURN_PSW
br %r14
-cleanup_io_leave:
- clc 8(8,%r12),BASED(cleanup_io_leave_insn)
+cleanup_io_restore:
+ clc 8(8,%r12),BASED(cleanup_io_restore_insn)
je 3f
- clc 8(8,%r12),BASED(cleanup_io_leave_insn+8)
+ clc 8(8,%r12),BASED(cleanup_io_restore_insn+8)
jhe 0f
mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
0: mvc __LC_RETURN_PSW(16),SP_PSW(%r15)
lg %r15,SP_R15(%r15)
3: la %r12,__LC_RETURN_PSW
br %r14
-cleanup_io_leave_insn:
+cleanup_io_restore_insn:
.quad io_done - 4
.quad io_done - 16