[S390] cleanup sysc_work and io_work code
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Mon, 17 May 2010 08:00:01 +0000 (10:00 +0200)
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>
Mon, 17 May 2010 08:00:15 +0000 (10:00 +0200)
Cleanup the #ifdef mess at io_work in entry[64].S and streamline the
TIF work code of the system call and io exit path.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/kernel/entry.S
arch/s390/kernel/entry64.S

index 6af7045280a8945009471209766bbd3f0c289b09..ffebfb64b913c7054087e80d6f6570c51a621cb8 100644 (file)
@@ -301,31 +301,29 @@ sysc_restore_trace_psw:
 #endif
 
 #
-# recheck if there is more work to do
-#
-sysc_work_loop:
-       tm      __TI_flags+3(%r9),_TIF_WORK_SVC
-       bz      BASED(sysc_restore)     # there is no work to do
-#
-# One of the work bits is on. Find out which one.
+# There is work to do, but first we need to check if we return to userspace.
 #
 sysc_work:
        tm      SP_PSW+1(%r15),0x01     # returning to user ?
        bno     BASED(sysc_restore)
+
+#
+# One of the work bits is on. Find out which one.
+#
+sysc_work_loop:
        tm      __TI_flags+3(%r9),_TIF_MCCK_PENDING
        bo      BASED(sysc_mcck_pending)
        tm      __TI_flags+3(%r9),_TIF_NEED_RESCHED
        bo      BASED(sysc_reschedule)
        tm      __TI_flags+3(%r9),_TIF_SIGPENDING
-       bnz     BASED(sysc_sigpending)
+       b     BASED(sysc_sigpending)
        tm      __TI_flags+3(%r9),_TIF_NOTIFY_RESUME
-       bnz     BASED(sysc_notify_resume)
+       b     BASED(sysc_notify_resume)
        tm      __TI_flags+3(%r9),_TIF_RESTART_SVC
        bo      BASED(sysc_restart)
        tm      __TI_flags+3(%r9),_TIF_SINGLE_STEP
        bo      BASED(sysc_singlestep)
-       b       BASED(sysc_restore)
-sysc_work_done:
+       b       BASED(sysc_return)      # beware of critical section cleanup
 
 #
 # _TIF_NEED_RESCHED is set, call schedule
@@ -386,7 +384,7 @@ sysc_singlestep:
        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_return) # load adr. of system return
+       la      %r14,BASED(sysc_work_loop)      # load adr. of system return
        br      %r1                     # branch to do_single_step
 
 #
@@ -636,30 +634,36 @@ io_restore_trace_psw:
 #endif
 
 #
-# switch to kernel stack, then check the TIF bits
+# There is work todo, find out in which context we have been interrupted:
+# 1) if we return to user space we can do all _TIF_WORK_INT work
+# 2) if we return to kernel code and preemptive scheduling is enabled check
+#    the preemption counter and if it is zero call preempt_schedule_irq
+# Before any work can be done, a switch to the kernel stack is required.
 #
 io_work:
        tm      SP_PSW+1(%r15),0x01     # returning to user ?
-#ifndef CONFIG_PREEMPT
-       bno     BASED(io_restore)       # no-> skip resched & signal
-#else
-       bnz     BASED(io_work_user)     # no -> check for preemptive scheduling
+       bo      BASED(io_work_user)     # yes -> do resched & signal
+#ifdef CONFIG_PREEMPT
        # check for preemptive scheduling
        icm     %r0,15,__TI_precount(%r9)
        bnz     BASED(io_restore)       # preemption disabled
+       # 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:
-       tm      __TI_flags+3(%r9),_TIF_NEED_RESCHED
-       bno     BASED(io_restore)
        l       %r1,BASED(.Lpreempt_schedule_irq)
        la      %r14,BASED(io_resume_loop)
-       br      %r1                     # call schedule
+       tm      __TI_flags+3(%r9),_TIF_NEED_RESCHED
+       bor     %r1                     # call preempt_schedule_irq
 #endif
+       b       BASED(io_restore)
 
+#
+# Need to do work before returning to userspace, switch to kernel stack
+#
 io_work_user:
        l       %r1,__LC_KERNEL_STACK
        s       %r1,BASED(.Lc_spsize)
@@ -668,7 +672,7 @@ io_work_user:
        lr      %r15,%r1
 #
 # One of the work bits is on. Find out which one.
-# Checked are: _TIF_SIGPENDING, _TIF_NEED_RESCHED
+# Checked are: _TIF_SIGPENDING, _TIF_NOTIFY_RESUME, _TIF_NEED_RESCHED
 #              and _TIF_MCCK_PENDING
 #
 io_work_loop:
@@ -677,11 +681,10 @@ io_work_loop:
        tm      __TI_flags+3(%r9),_TIF_NEED_RESCHED
        bo      BASED(io_reschedule)
        tm      __TI_flags+3(%r9),_TIF_SIGPENDING
-       bnz     BASED(io_sigpending)
+       b     BASED(io_sigpending)
        tm      __TI_flags+3(%r9),_TIF_NOTIFY_RESUME
-       bnz     BASED(io_notify_resume)
-       b       BASED(io_restore)
-io_work_done:
+       bo      BASED(io_notify_resume)
+       b       BASED(io_return)        # beware of critical section cleanup
 
 #
 # _TIF_MCCK_PENDING is set, call handler
@@ -701,8 +704,6 @@ io_reschedule:
        basr    %r14,%r1                # call scheduler
        stnsm   __SF_EMPTY(%r15),0xfc   # disable I/O and ext. interrupts
        TRACE_IRQS_OFF
-       tm      __TI_flags+3(%r9),_TIF_WORK_INT
-       bz      BASED(io_restore)       # there is no work to do
        b       BASED(io_work_loop)
 
 #
@@ -921,14 +922,10 @@ cleanup_table_sysc_return:
        .long   sysc_return + 0x80000000, sysc_leave + 0x80000000
 cleanup_table_sysc_leave:
        .long   sysc_leave + 0x80000000, sysc_done + 0x80000000
-cleanup_table_sysc_work_loop:
-       .long   sysc_work_loop + 0x80000000, sysc_work_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_io_work_loop:
-       .long   io_work_loop + 0x80000000, io_work_done + 0x80000000
 
 cleanup_critical:
        clc     4(4,%r12),BASED(cleanup_table_system_call)
@@ -945,11 +942,6 @@ cleanup_critical:
        bl      BASED(0f)
        clc     4(4,%r12),BASED(cleanup_table_sysc_leave+4)
        bl      BASED(cleanup_sysc_leave)
-0:
-       clc     4(4,%r12),BASED(cleanup_table_sysc_work_loop)
-       bl      BASED(0f)
-       clc     4(4,%r12),BASED(cleanup_table_sysc_work_loop+4)
-       bl      BASED(cleanup_sysc_return)
 0:
        clc     4(4,%r12),BASED(cleanup_table_io_return)
        bl      BASED(0f)
@@ -960,11 +952,6 @@ cleanup_critical:
        bl      BASED(0f)
        clc     4(4,%r12),BASED(cleanup_table_io_leave+4)
        bl      BASED(cleanup_io_leave)
-0:
-       clc     4(4,%r12),BASED(cleanup_table_io_work_loop)
-       bl      BASED(0f)
-       clc     4(4,%r12),BASED(cleanup_table_io_work_loop+4)
-       bl      BASED(cleanup_io_work_loop)
 0:
        br      %r14
 
@@ -1043,12 +1030,6 @@ cleanup_io_return:
        la      %r12,__LC_RETURN_PSW
        br      %r14
 
-cleanup_io_work_loop:
-       mvc     __LC_RETURN_PSW(4),0(%r12)
-       mvc     __LC_RETURN_PSW+4(4),BASED(cleanup_table_io_work_loop)
-       la      %r12,__LC_RETURN_PSW
-       br      %r14
-
 cleanup_io_leave:
        clc     4(4,%r12),BASED(cleanup_io_leave_insn)
        be      BASED(2f)
index 52106d53271c3c2b99bede6ffd68f7e0958ab59c..ca02b10a2c329fcaad562738c3efa099943800bd 100644 (file)
@@ -291,38 +291,36 @@ sysc_restore_trace_psw:
 #endif
 
 #
-# recheck if there is more work to do
-#
-sysc_work_loop:
-       tm      __TI_flags+7(%r9),_TIF_WORK_SVC
-       jz      sysc_restore      # there is no work to do
-#
-# One of the work bits is on. Find out which one.
+# There is work to do, but first we need to check if we return to userspace.
 #
 sysc_work:
        tm      SP_PSW+1(%r15),0x01     # returning to user ?
        jno     sysc_restore
+
+#
+# One of the work bits is on. Find out which one.
+#
+sysc_work_loop:
        tm      __TI_flags+7(%r9),_TIF_MCCK_PENDING
        jo      sysc_mcck_pending
        tm      __TI_flags+7(%r9),_TIF_NEED_RESCHED
        jo      sysc_reschedule
        tm      __TI_flags+7(%r9),_TIF_SIGPENDING
-       jnz     sysc_sigpending
+       j     sysc_sigpending
        tm      __TI_flags+7(%r9),_TIF_NOTIFY_RESUME
-       jnz     sysc_notify_resume
+       j     sysc_notify_resume
        tm      __TI_flags+7(%r9),_TIF_RESTART_SVC
        jo      sysc_restart
        tm      __TI_flags+7(%r9),_TIF_SINGLE_STEP
        jo      sysc_singlestep
-       j       sysc_restore
-sysc_work_done:
+       j       sysc_return             # beware of critical section cleanup
 
 #
 # _TIF_NEED_RESCHED is set, call schedule
 #
 sysc_reschedule:
        larl    %r14,sysc_work_loop
-       jg      schedule        # return point is sysc_return
+       jg      schedule                # return point is sysc_work_loop
 
 #
 # _TIF_MCCK_PENDING is set, call handler
@@ -369,7 +367,7 @@ sysc_singlestep:
        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_return        # load adr. of system return
+       larl    %r14,sysc_work_loop     # load adr. of system return
        jg      do_single_step          # branch to do_sigtrap
 
 #
@@ -605,37 +603,27 @@ io_restore_trace_psw:
 #endif
 
 #
-# There is work todo, we need to check if we return to userspace, then
-# check, if we are in SIE, if yes leave it
+# 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.
 #
 io_work:
        tm      SP_PSW+1(%r15),0x01     # returning to user ?
-#ifndef CONFIG_PREEMPT
-#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
-       jnz     io_work_user            # yes -> no need to check for SIE
-       la      %r1, BASED(sie_opcode)  # we return to kernel here
-       lg      %r2, SP_PSW+8(%r15)
-       clc     0(2,%r1), 0(%r2)        # is current instruction = SIE?
-       jne     io_restore              # no-> return to kernel
-       lg      %r1, SP_PSW+8(%r15)     # yes-> add 4 bytes to leave SIE
-       aghi    %r1, 4
-       stg     %r1, SP_PSW+8(%r15)
-       j       io_restore              # return to kernel
-#else
-       jno     io_restore              # no-> skip resched & signal
-#endif
-#else
-       jnz     io_work_user            # yes -> do resched & signal
+       jo      io_work_user            # yes -> do resched & signal
 #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
-       la      %r1, BASED(sie_opcode)
-       lg      %r2, SP_PSW+8(%r15)
-       clc     0(2,%r1), 0(%r2)        # is current instruction = SIE?
+       lg      %r2,SP_PSW+8(%r15)      # check if current instruction is SIE
+       lh      %r1,0(%r2)
+       chi     %r1,-19948              # signed 16 bit compare with 0xb214
        jne     0f                      # no -> leave PSW alone
-       lg      %r1, SP_PSW+8(%r15)     # yes-> add 4 bytes to leave SIE
-       aghi    %r1, 4
-       stg     %r1, SP_PSW+8(%r15)
+       aghi    %r2,4                   # yes-> add 4 bytes to leave SIE
+       stg     %r2,SP_PSW+8(%r15)
 0:
 #endif
+#ifdef CONFIG_PREEMPT
        # check for preemptive scheduling
        icm     %r0,15,__TI_precount(%r9)
        jnz     io_restore              # preemption is disabled
@@ -646,21 +634,25 @@ io_work:
        xc      __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain
        lgr     %r15,%r1
 io_resume_loop:
-       tm      __TI_flags+7(%r9),_TIF_NEED_RESCHED
-       jno     io_restore
        larl    %r14,io_resume_loop
-       jg      preempt_schedule_irq
+       tm      __TI_flags+7(%r12),_TIF_NEED_RESCHED
+       jgo     preempt_schedule_irq
 #endif
+       j       io_restore
 
+#
+# Need to do work before returning to userspace, switch to kernel stack
+#
 io_work_user:
        lg      %r1,__LC_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
+
 #
 # One of the work bits is on. Find out which one.
-# Checked are: _TIF_SIGPENDING, _TIF_RESTORE_SIGPENDING, _TIF_NEED_RESCHED
+# Checked are: _TIF_SIGPENDING, _TIF_NOTIFY_RESUME, _TIF_NEED_RESCHED
 #             and _TIF_MCCK_PENDING
 #
 io_work_loop:
@@ -669,16 +661,10 @@ io_work_loop:
        tm      __TI_flags+7(%r9),_TIF_NEED_RESCHED
        jo      io_reschedule
        tm      __TI_flags+7(%r9),_TIF_SIGPENDING
-       jnz     io_sigpending
+       j     io_sigpending
        tm      __TI_flags+7(%r9),_TIF_NOTIFY_RESUME
-       jnz     io_notify_resume
-       j       io_restore
-io_work_done:
-
-#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
-sie_opcode:
-       .long 0xb2140000
-#endif
+       jo      io_notify_resume
+       j       io_return               # beware of critical section cleanup
 
 #
 # _TIF_MCCK_PENDING is set, call handler
@@ -696,8 +682,6 @@ io_reschedule:
        brasl   %r14,schedule           # call scheduler
        stnsm   __SF_EMPTY(%r15),0xfc   # disable I/O and ext. interrupts
        TRACE_IRQS_OFF
-       tm      __TI_flags+7(%r9),_TIF_WORK_INT
-       jz      io_restore              # there is no work to do
        j       io_work_loop
 
 #
@@ -903,14 +887,10 @@ cleanup_table_sysc_return:
        .quad   sysc_return, sysc_leave
 cleanup_table_sysc_leave:
        .quad   sysc_leave, sysc_done
-cleanup_table_sysc_work_loop:
-       .quad   sysc_work_loop, sysc_work_done
 cleanup_table_io_return:
        .quad   io_return, io_leave
 cleanup_table_io_leave:
        .quad   io_leave, io_done
-cleanup_table_io_work_loop:
-       .quad   io_work_loop, io_work_done
 
 cleanup_critical:
        clc     8(8,%r12),BASED(cleanup_table_system_call)
@@ -927,11 +907,6 @@ cleanup_critical:
        jl      0f
        clc     8(8,%r12),BASED(cleanup_table_sysc_leave+8)
        jl      cleanup_sysc_leave
-0:
-       clc     8(8,%r12),BASED(cleanup_table_sysc_work_loop)
-       jl      0f
-       clc     8(8,%r12),BASED(cleanup_table_sysc_work_loop+8)
-       jl      cleanup_sysc_return
 0:
        clc     8(8,%r12),BASED(cleanup_table_io_return)
        jl      0f
@@ -942,11 +917,6 @@ cleanup_critical:
        jl      0f
        clc     8(8,%r12),BASED(cleanup_table_io_leave+8)
        jl      cleanup_io_leave
-0:
-       clc     8(8,%r12),BASED(cleanup_table_io_work_loop)
-       jl      0f
-       clc     8(8,%r12),BASED(cleanup_table_io_work_loop+8)
-       jl      cleanup_io_work_loop
 0:
        br      %r14
 
@@ -1025,12 +995,6 @@ cleanup_io_return:
        la      %r12,__LC_RETURN_PSW
        br      %r14
 
-cleanup_io_work_loop:
-       mvc     __LC_RETURN_PSW(8),0(%r12)
-       mvc     __LC_RETURN_PSW+8(8),BASED(cleanup_table_io_work_loop)
-       la      %r12,__LC_RETURN_PSW
-       br      %r14
-
 cleanup_io_leave:
        clc     8(8,%r12),BASED(cleanup_io_leave_insn)
        je      3f