[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 4348f9b..6af7045 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
 
@@ -1039,6 +1039,12 @@ cleanup_sysc_leave_insn:
 
 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
        br      %r14
index 29fd0f1..52106d5 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
 
@@ -1021,6 +1021,12 @@ cleanup_sysc_leave_insn:
 
 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
        br      %r14