4.9-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Martin Schwidefsky <schwidef...@de.ibm.com>

commit 07a63cbe8bcb6ba72fb989dcab1ec55ec6c36c7e upstream.

git commit c5328901aa1db134 "[S390] entry[64].S improvements" removed
the update of the exit_timer lowcore field from the critical section
cleanup of the .Lsysc_restore/.Lsysc_done and .Lio_restore/.Lio_done
blocks. If the PSW is updated by the critical section cleanup to point to
user space again, the interrupt entry code will do a vtime calculation
after the cleanup completed with an exit_timer value which has *not* been
updated. Due to this incorrect system time deltas are calculated.

If an interrupt occured with an old PSW between .Lsysc_restore/.Lsysc_done
or .Lio_restore/.Lio_done update __LC_EXIT_TIMER with the system entry
time of the interrupt.

Tested-by: Christian Borntraeger <borntrae...@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidef...@de.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>

---
 arch/s390/kernel/entry.S |   21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -321,6 +321,7 @@ ENTRY(system_call)
        lg      %r14,__LC_VDSO_PER_CPU
        lmg     %r0,%r10,__PT_R0(%r11)
        mvc     __LC_RETURN_PSW(16),__PT_PSW(%r11)
+.Lsysc_exit_timer:
        stpt    __LC_EXIT_TIMER
        mvc     __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER
        lmg     %r11,%r15,__PT_R11(%r11)
@@ -606,6 +607,7 @@ ENTRY(io_int_handler)
        lg      %r14,__LC_VDSO_PER_CPU
        lmg     %r0,%r10,__PT_R0(%r11)
        mvc     __LC_RETURN_PSW(16),__PT_PSW(%r11)
+.Lio_exit_timer:
        stpt    __LC_EXIT_TIMER
        mvc     __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER
        lmg     %r11,%r15,__PT_R11(%r11)
@@ -1135,15 +1137,23 @@ cleanup_critical:
        br      %r14
 
 .Lcleanup_sysc_restore:
+       # check if stpt has been executed
        clg     %r9,BASED(.Lcleanup_sysc_restore_insn)
+       jh      0f
+       mvc     __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
+       cghi    %r11,__LC_SAVE_AREA_ASYNC
        je      0f
+       mvc     __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER
+0:     clg     %r9,BASED(.Lcleanup_sysc_restore_insn+8)
+       je      1f
        lg      %r9,24(%r11)            # get saved pointer to pt_regs
        mvc     __LC_RETURN_PSW(16),__PT_PSW(%r9)
        mvc     0(64,%r11),__PT_R8(%r9)
        lmg     %r0,%r7,__PT_R0(%r9)
-0:     lmg     %r8,%r9,__LC_RETURN_PSW
+1:     lmg     %r8,%r9,__LC_RETURN_PSW
        br      %r14
 .Lcleanup_sysc_restore_insn:
+       .quad   .Lsysc_exit_timer
        .quad   .Lsysc_done - 4
 
 .Lcleanup_io_tif:
@@ -1151,15 +1161,20 @@ cleanup_critical:
        br      %r14
 
 .Lcleanup_io_restore:
+       # check if stpt has been executed
        clg     %r9,BASED(.Lcleanup_io_restore_insn)
-       je      0f
+       jh      0f
+       mvc     __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER
+0:     clg     %r9,BASED(.Lcleanup_io_restore_insn+8)
+       je      1f
        lg      %r9,24(%r11)            # get saved r11 pointer to pt_regs
        mvc     __LC_RETURN_PSW(16),__PT_PSW(%r9)
        mvc     0(64,%r11),__PT_R8(%r9)
        lmg     %r0,%r7,__PT_R0(%r9)
-0:     lmg     %r8,%r9,__LC_RETURN_PSW
+1:     lmg     %r8,%r9,__LC_RETURN_PSW
        br      %r14
 .Lcleanup_io_restore_insn:
+       .quad   .Lio_exit_timer
        .quad   .Lio_done - 4
 
 .Lcleanup_idle:


Reply via email to