diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2017-05-02 07:36:00 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2017-05-03 03:08:57 -0400 |
commit | 07a63cbe8bcb6ba72fb989dcab1ec55ec6c36c7e (patch) | |
tree | e7ef1fae73975159ed7886988db715af73e73d49 | |
parent | 89c9fea3c8034cdb2fd745f551cde0b507fd6893 (diff) |
s390/cputime: fix incorrect system time
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.
Cc: stable@vger.kernel.org # 3.3+
Tested-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r-- | arch/s390/kernel/entry.S | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index a5f5d3bb3dbc..e408d9cc5b96 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S | |||
@@ -312,6 +312,7 @@ ENTRY(system_call) | |||
312 | lg %r14,__LC_VDSO_PER_CPU | 312 | lg %r14,__LC_VDSO_PER_CPU |
313 | lmg %r0,%r10,__PT_R0(%r11) | 313 | lmg %r0,%r10,__PT_R0(%r11) |
314 | mvc __LC_RETURN_PSW(16),__PT_PSW(%r11) | 314 | mvc __LC_RETURN_PSW(16),__PT_PSW(%r11) |
315 | .Lsysc_exit_timer: | ||
315 | stpt __LC_EXIT_TIMER | 316 | stpt __LC_EXIT_TIMER |
316 | mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER | 317 | mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER |
317 | lmg %r11,%r15,__PT_R11(%r11) | 318 | lmg %r11,%r15,__PT_R11(%r11) |
@@ -623,6 +624,7 @@ ENTRY(io_int_handler) | |||
623 | lg %r14,__LC_VDSO_PER_CPU | 624 | lg %r14,__LC_VDSO_PER_CPU |
624 | lmg %r0,%r10,__PT_R0(%r11) | 625 | lmg %r0,%r10,__PT_R0(%r11) |
625 | mvc __LC_RETURN_PSW(16),__PT_PSW(%r11) | 626 | mvc __LC_RETURN_PSW(16),__PT_PSW(%r11) |
627 | .Lio_exit_timer: | ||
626 | stpt __LC_EXIT_TIMER | 628 | stpt __LC_EXIT_TIMER |
627 | mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER | 629 | mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER |
628 | lmg %r11,%r15,__PT_R11(%r11) | 630 | lmg %r11,%r15,__PT_R11(%r11) |
@@ -1174,15 +1176,23 @@ cleanup_critical: | |||
1174 | br %r14 | 1176 | br %r14 |
1175 | 1177 | ||
1176 | .Lcleanup_sysc_restore: | 1178 | .Lcleanup_sysc_restore: |
1179 | # check if stpt has been executed | ||
1177 | clg %r9,BASED(.Lcleanup_sysc_restore_insn) | 1180 | clg %r9,BASED(.Lcleanup_sysc_restore_insn) |
1181 | jh 0f | ||
1182 | mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER | ||
1183 | cghi %r11,__LC_SAVE_AREA_ASYNC | ||
1178 | je 0f | 1184 | je 0f |
1185 | mvc __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER | ||
1186 | 0: clg %r9,BASED(.Lcleanup_sysc_restore_insn+8) | ||
1187 | je 1f | ||
1179 | lg %r9,24(%r11) # get saved pointer to pt_regs | 1188 | lg %r9,24(%r11) # get saved pointer to pt_regs |
1180 | mvc __LC_RETURN_PSW(16),__PT_PSW(%r9) | 1189 | mvc __LC_RETURN_PSW(16),__PT_PSW(%r9) |
1181 | mvc 0(64,%r11),__PT_R8(%r9) | 1190 | mvc 0(64,%r11),__PT_R8(%r9) |
1182 | lmg %r0,%r7,__PT_R0(%r9) | 1191 | lmg %r0,%r7,__PT_R0(%r9) |
1183 | 0: lmg %r8,%r9,__LC_RETURN_PSW | 1192 | 1: lmg %r8,%r9,__LC_RETURN_PSW |
1184 | br %r14 | 1193 | br %r14 |
1185 | .Lcleanup_sysc_restore_insn: | 1194 | .Lcleanup_sysc_restore_insn: |
1195 | .quad .Lsysc_exit_timer | ||
1186 | .quad .Lsysc_done - 4 | 1196 | .quad .Lsysc_done - 4 |
1187 | 1197 | ||
1188 | .Lcleanup_io_tif: | 1198 | .Lcleanup_io_tif: |
@@ -1190,15 +1200,20 @@ cleanup_critical: | |||
1190 | br %r14 | 1200 | br %r14 |
1191 | 1201 | ||
1192 | .Lcleanup_io_restore: | 1202 | .Lcleanup_io_restore: |
1203 | # check if stpt has been executed | ||
1193 | clg %r9,BASED(.Lcleanup_io_restore_insn) | 1204 | clg %r9,BASED(.Lcleanup_io_restore_insn) |
1194 | je 0f | 1205 | jh 0f |
1206 | mvc __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER | ||
1207 | 0: clg %r9,BASED(.Lcleanup_io_restore_insn+8) | ||
1208 | je 1f | ||
1195 | lg %r9,24(%r11) # get saved r11 pointer to pt_regs | 1209 | lg %r9,24(%r11) # get saved r11 pointer to pt_regs |
1196 | mvc __LC_RETURN_PSW(16),__PT_PSW(%r9) | 1210 | mvc __LC_RETURN_PSW(16),__PT_PSW(%r9) |
1197 | mvc 0(64,%r11),__PT_R8(%r9) | 1211 | mvc 0(64,%r11),__PT_R8(%r9) |
1198 | lmg %r0,%r7,__PT_R0(%r9) | 1212 | lmg %r0,%r7,__PT_R0(%r9) |
1199 | 0: lmg %r8,%r9,__LC_RETURN_PSW | 1213 | 1: lmg %r8,%r9,__LC_RETURN_PSW |
1200 | br %r14 | 1214 | br %r14 |
1201 | .Lcleanup_io_restore_insn: | 1215 | .Lcleanup_io_restore_insn: |
1216 | .quad .Lio_exit_timer | ||
1202 | .quad .Lio_done - 4 | 1217 | .quad .Lio_done - 4 |
1203 | 1218 | ||
1204 | .Lcleanup_idle: | 1219 | .Lcleanup_idle: |