[S390] fix io_return critical section cleanup
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Fri, 9 Apr 2010 11:43:00 +0000 (13:43 +0200)
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>
Fri, 9 Apr 2010 11:43:02 +0000 (13:43 +0200)
If a machine check interrupts the io interrupt handler on one of the
instructions between io_return and io_leave the critical section
cleanup code will move the return psw to io_work_loop. By doing that
the switch from the asynchronous interrupt stack to the process stack
is skipped. If e.g. TIF_NEED_RESCHED is set things break because
the scheduler is called with the asynchronous interrupts stack.
Moving the psw back to io_return instead fixes the problem.

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

index 4348f9bc5393f445221c1444b8e9a2ddfaeb486c..6af7045280a8945009471209766bbd3f0c289b09 100644 (file)
@@ -964,7 +964,7 @@ cleanup_critical:
        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_return)
+       bl      BASED(cleanup_io_work_loop)
 0:
        br      %r14
 
@@ -1038,6 +1038,12 @@ cleanup_sysc_leave_insn:
        .long   sysc_done - 8 + 0x80000000
 
 cleanup_io_return:
+       mvc     __LC_RETURN_PSW(4),0(%r12)
+       mvc     __LC_RETURN_PSW+4(4),BASED(cleanup_table_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
index 29fd0f1e6ec41fba888f37d43794871bd2106f6f..52106d53271c3c2b99bede6ffd68f7e0958ab59c 100644 (file)
@@ -946,7 +946,7 @@ cleanup_critical:
        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_return
+       jl      cleanup_io_work_loop
 0:
        br      %r14
 
@@ -1020,6 +1020,12 @@ cleanup_sysc_leave_insn:
        .quad   sysc_done - 16
 
 cleanup_io_return:
+       mvc     __LC_RETURN_PSW(8),0(%r12)
+       mvc     __LC_RETURN_PSW+8(8),BASED(cleanup_table_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