]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
[S390] 31 bit entry.S update.
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Wed, 5 Jan 2011 11:47:57 +0000 (12:47 +0100)
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>
Wed, 5 Jan 2011 11:47:29 +0000 (12:47 +0100)
Make the code in the 31 bit entry.S code as similar as possible to the
64 bit version in entry64.S. That makes it easier to add new code to
the first level interrupt handler that affects both 31 and 64 bit kernels.

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

index 68d1a02db6be263fadaf6aa9a4ec5111ca3021c8..af8bd3b90a268cdc352280f847f8eee3008a3cb9 100644 (file)
@@ -9,7 +9,6 @@
  *              Heiko Carstens <heiko.carstens@de.ibm.com>
  */
 
-#include <linux/sys.h>
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/cache.h>
@@ -110,31 +109,36 @@ STACK_SIZE  = 1 << STACK_SHIFT
 1:     stm     %r10,%r11,\lc_sum
        .endm
 
-       .macro  SAVE_ALL_BASE savearea
+       .macro  SAVE_ALL_SVC psworg,savearea
        stm     %r12,%r15,\savearea
        l       %r13,__LC_SVC_NEW_PSW+4 # load &system_call to %r13
+       l       %r15,__LC_KERNEL_STACK  # problem state -> load ksp
+       s       %r15,BASED(.Lc_spsize)  # make room for registers & psw
        .endm
 
-       .macro  SAVE_ALL_SVC psworg,savearea
-       la      %r12,\psworg
-       l       %r15,__LC_KERNEL_STACK  # problem state -> load ksp
+       .macro  SAVE_ALL_BASE savearea
+       stm     %r12,%r15,\savearea
+       l       %r13,__LC_SVC_NEW_PSW+4 # load &system_call to %r13
        .endm
 
-       .macro  SAVE_ALL_SYNC psworg,savearea
-       la      %r12,\psworg
+       .macro  SAVE_ALL_PGM psworg,savearea
        tm      \psworg+1,0x01          # test problem state bit
-       bz      BASED(2f)               # skip stack setup save
-       l       %r15,__LC_KERNEL_STACK  # problem state -> load ksp
 #ifdef CONFIG_CHECK_STACK
-       b       BASED(3f)
-2:     tml     %r15,STACK_SIZE - CONFIG_STACK_GUARD
-       bz      BASED(stack_overflow)
-3:
+       bnz     BASED(1f)
+       tml     %r15,STACK_SIZE - CONFIG_STACK_GUARD
+       bnz     BASED(2f)
+       la      %r12,\psworg
+       b       BASED(stack_overflow)
+#else
+       bz      BASED(2f)
 #endif
-2:
+1:     l       %r15,__LC_KERNEL_STACK  # problem state -> load ksp
+2:     s       %r15,BASED(.Lc_spsize)  # make room for registers & psw
        .endm
 
        .macro  SAVE_ALL_ASYNC psworg,savearea
+       stm     %r12,%r15,\savearea
+       l       %r13,__LC_SVC_NEW_PSW+4 # load &system_call to %r13
        la      %r12,\psworg
        tm      \psworg+1,0x01          # test problem state bit
        bnz     BASED(1f)               # from user -> load async stack
@@ -149,27 +153,23 @@ STACK_SIZE  = 1 << STACK_SHIFT
 0:     l       %r14,__LC_ASYNC_STACK   # are we already on the async stack ?
        slr     %r14,%r15
        sra     %r14,STACK_SHIFT
-       be      BASED(2f)
-1:     l       %r15,__LC_ASYNC_STACK
 #ifdef CONFIG_CHECK_STACK
-       b       BASED(3f)
-2:     tml     %r15,STACK_SIZE - CONFIG_STACK_GUARD
-       bz      BASED(stack_overflow)
-3:
+       bnz     BASED(1f)
+       tml     %r15,STACK_SIZE - CONFIG_STACK_GUARD
+       bnz     BASED(2f)
+       b       BASED(stack_overflow)
+#else
+       bz      BASED(2f)
 #endif
-2:
+1:     l       %r15,__LC_ASYNC_STACK
+2:     s       %r15,BASED(.Lc_spsize)  # make room for registers & psw
        .endm
 
-       .macro  CREATE_STACK_FRAME psworg,savearea
-       s       %r15,BASED(.Lc_spsize)  # make room for registers & psw
-       mvc     SP_PSW(8,%r15),0(%r12)  # move user PSW to stack
+       .macro  CREATE_STACK_FRAME savearea
+       xc      __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
        st      %r2,SP_ORIG_R2(%r15)    # store original content of gpr 2
-       icm     %r12,12,__LC_SVC_ILC
-       stm     %r0,%r11,SP_R0(%r15)    # store gprs %r0-%r11 to kernel stack
-       st      %r12,SP_ILC(%r15)
        mvc     SP_R12(16,%r15),\savearea # move %r12-%r15 to stack
-       la      %r12,0
-       st      %r12,__SF_BACKCHAIN(%r15)       # clear back chain
+       stm     %r0,%r11,SP_R0(%r15)    # store gprs %r0-%r11 to kernel stack
        .endm
 
        .macro  RESTORE_ALL psworg,sync
@@ -237,10 +237,11 @@ __critical_start:
 system_call:
        stpt    __LC_SYNC_ENTER_TIMER
 sysc_saveall:
-       SAVE_ALL_BASE __LC_SAVE_AREA
        SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
-       CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
-       lh      %r7,0x8a          # get svc number from lowcore
+       CREATE_STACK_FRAME __LC_SAVE_AREA
+       mvc     SP_PSW(8,%r15),__LC_SVC_OLD_PSW
+       mvc     SP_ILC(4,%r15),__LC_SVC_ILC
+       l       %r12,__LC_THREAD_INFO   # load pointer to thread_info struct
 sysc_vtime:
        UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
 sysc_stime:
@@ -248,20 +249,20 @@ sysc_stime:
 sysc_update:
        mvc     __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
 sysc_do_svc:
-       l       %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
-       ltr     %r7,%r7                 # test for svc 0
+       xr      %r7,%r7
+       icm     %r7,3,SP_SVCNR(%r15)    # load svc number and test for svc 0
        bnz     BASED(sysc_nr_ok)       # svc number > 0
        # svc 0: system call number in %r1
        cl      %r1,BASED(.Lnr_syscalls)
        bnl     BASED(sysc_nr_ok)
+       sth     %r1,SP_SVCNR(%r15)
        lr      %r7,%r1           # copy svc number to %r7
 sysc_nr_ok:
-       sth     %r7,SP_SVCNR(%r15)
        sll     %r7,2             # svc number *4
-       l       %r8,BASED(.Lsysc_table)
-       tm      __TI_flags+2(%r9),_TIF_SYSCALL
+       l       %r10,BASED(.Lsysc_table)
+       tm      __TI_flags+2(%r12),_TIF_SYSCALL
        mvc     SP_ARGS(4,%r15),SP_R7(%r15)
-       l       %r8,0(%r7,%r8)    # get system call addr.
+       l       %r8,0(%r7,%r10)   # get system call addr.
        bnz     BASED(sysc_tracesys)
        basr    %r14,%r8          # call sys_xxxx
        st      %r2,SP_R2(%r15)   # store return value (change R2 on stack)
@@ -269,7 +270,7 @@ sysc_nr_ok:
 sysc_return:
        LOCKDEP_SYS_EXIT
 sysc_tif:
-       tm      __TI_flags+3(%r9),_TIF_WORK_SVC
+       tm      __TI_flags+3(%r12),_TIF_WORK_SVC
        bnz     BASED(sysc_work)  # there is work to do (signals etc.)
 sysc_restore:
        RESTORE_ALL __LC_RETURN_PSW,1
@@ -286,17 +287,17 @@ sysc_work:
 # One of the work bits is on. Find out which one.
 #
 sysc_work_tif:
-       tm      __TI_flags+3(%r9),_TIF_MCCK_PENDING
+       tm      __TI_flags+3(%r12),_TIF_MCCK_PENDING
        bo      BASED(sysc_mcck_pending)
-       tm      __TI_flags+3(%r9),_TIF_NEED_RESCHED
+       tm      __TI_flags+3(%r12),_TIF_NEED_RESCHED
        bo      BASED(sysc_reschedule)
-       tm      __TI_flags+3(%r9),_TIF_SIGPENDING
+       tm      __TI_flags+3(%r12),_TIF_SIGPENDING
        bo      BASED(sysc_sigpending)
-       tm      __TI_flags+3(%r9),_TIF_NOTIFY_RESUME
+       tm      __TI_flags+3(%r12),_TIF_NOTIFY_RESUME
        bo      BASED(sysc_notify_resume)
-       tm      __TI_flags+3(%r9),_TIF_RESTART_SVC
+       tm      __TI_flags+3(%r12),_TIF_RESTART_SVC
        bo      BASED(sysc_restart)
-       tm      __TI_flags+3(%r9),_TIF_SINGLE_STEP
+       tm      __TI_flags+3(%r12),_TIF_SINGLE_STEP
        bo      BASED(sysc_singlestep)
        b       BASED(sysc_return)      # beware of critical section cleanup
 
@@ -320,13 +321,13 @@ sysc_mcck_pending:
 # _TIF_SIGPENDING is set, call do_signal
 #
 sysc_sigpending:
-       ni      __TI_flags+3(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
+       ni      __TI_flags+3(%r12),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
        la      %r2,SP_PTREGS(%r15)     # load pt_regs
        l       %r1,BASED(.Ldo_signal)
        basr    %r14,%r1                # call do_signal
-       tm      __TI_flags+3(%r9),_TIF_RESTART_SVC
+       tm      __TI_flags+3(%r12),_TIF_RESTART_SVC
        bo      BASED(sysc_restart)
-       tm      __TI_flags+3(%r9),_TIF_SINGLE_STEP
+       tm      __TI_flags+3(%r12),_TIF_SINGLE_STEP
        bo      BASED(sysc_singlestep)
        b       BASED(sysc_return)
 
@@ -344,19 +345,19 @@ sysc_notify_resume:
 # _TIF_RESTART_SVC is set, set up registers and restart svc
 #
 sysc_restart:
-       ni      __TI_flags+3(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
+       ni      __TI_flags+3(%r12),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
        l       %r7,SP_R2(%r15)         # load new svc number
        mvc     SP_R2(4,%r15),SP_ORIG_R2(%r15) # restore first argument
        lm      %r2,%r6,SP_R2(%r15)     # load svc arguments
+       sth     %r7,SP_SVCNR(%r15)
        b       BASED(sysc_nr_ok)       # restart svc
 
 #
 # _TIF_SINGLE_STEP is set, call do_single_step
 #
 sysc_singlestep:
-       ni      __TI_flags+3(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
-       mvi     SP_SVCNR(%r15),0xff     # set trap indication to pgm check
-       mvi     SP_SVCNR+1(%r15),0xff
+       ni      __TI_flags+3(%r12),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
        l       %r1,BASED(.Lhandle_per) # load adr. of per handler
        la      %r14,BASED(sysc_return) # load adr. of system return
@@ -370,15 +371,15 @@ sysc_tracesys:
        l       %r1,BASED(.Ltrace_entry)
        la      %r2,SP_PTREGS(%r15)     # load pt_regs
        la      %r3,0
-       srl     %r7,2
-       st      %r7,SP_R2(%r15)
+       xr      %r0,%r0
+       icm     %r0,3,SP_SVCNR(%r15)
+       st      %r0,SP_R2(%r15)
        basr    %r14,%r1
        cl      %r2,BASED(.Lnr_syscalls)
        bnl     BASED(sysc_tracenogo)
-       l       %r8,BASED(.Lsysc_table)
        lr      %r7,%r2
        sll     %r7,2                   # svc number *4
-       l       %r8,0(%r7,%r8)
+       l       %r8,0(%r7,%r10)
 sysc_tracego:
        lm      %r3,%r6,SP_R3(%r15)
        mvc     SP_ARGS(4,%r15),SP_R7(%r15)
@@ -386,7 +387,7 @@ sysc_tracego:
        basr    %r14,%r8                # call sys_xxx
        st      %r2,SP_R2(%r15)         # store return value
 sysc_tracenogo:
-       tm      __TI_flags+2(%r9),_TIF_SYSCALL
+       tm      __TI_flags+2(%r12),_TIF_SYSCALL
        bz      BASED(sysc_return)
        l       %r1,BASED(.Ltrace_exit)
        la      %r2,SP_PTREGS(%r15)     # load pt_regs
@@ -399,7 +400,7 @@ sysc_tracenogo:
        .globl  ret_from_fork
 ret_from_fork:
        l       %r13,__LC_SVC_NEW_PSW+4
-       l       %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
+       l       %r12,__LC_THREAD_INFO   # load pointer to thread_info struct
        tm      SP_PSW+1(%r15),0x01     # forking a kernel thread ?
        bo      BASED(0f)
        st      %r15,SP_R15(%r15)       # store stack pointer for new kthread
@@ -434,8 +435,8 @@ kernel_execve:
 0:     stnsm   __SF_EMPTY(%r15),0xfc   # disable interrupts
        l       %r15,__LC_KERNEL_STACK  # load ksp
        s       %r15,BASED(.Lc_spsize)  # make room for registers & psw
-       l       %r9,__LC_THREAD_INFO
        mvc     SP_PTREGS(__PT_SIZE,%r15),0(%r12)       # copy pt_regs
+       l       %r12,__LC_THREAD_INFO
        xc      __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
        stosm   __SF_EMPTY(%r15),0x03   # reenable interrupts
        l       %r1,BASED(.Lexecve_tail)
@@ -465,26 +466,27 @@ pgm_check_handler:
        SAVE_ALL_BASE __LC_SAVE_AREA
        tm      __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
        bnz     BASED(pgm_per)          # got per exception -> special case
-       SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA
-       CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
+       SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA
+       CREATE_STACK_FRAME __LC_SAVE_AREA
+       xc      SP_ILC(4,%r15),SP_ILC(%r15)
+       mvc     SP_PSW(8,%r15),__LC_PGM_OLD_PSW
+       l       %r12,__LC_THREAD_INFO   # load pointer to thread_info struct
        tm      SP_PSW+1(%r15),0x01     # interrupting from user ?
        bz      BASED(pgm_no_vtime)
        UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
        UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
        mvc     __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
 pgm_no_vtime:
-       l       %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
        l       %r3,__LC_PGM_ILC        # load program interruption code
        l       %r4,__LC_TRANS_EXC_CODE
        REENABLE_IRQS
        la      %r8,0x7f
        nr      %r8,%r3
-pgm_do_call:
-       l       %r7,BASED(.Ljump_table)
        sll     %r8,2
-       l       %r7,0(%r8,%r7)          # load address of handler routine
+       l       %r1,BASED(.Ljump_table)
+       l       %r1,0(%r8,%r1)          # load address of handler routine
        la      %r2,SP_PTREGS(%r15)     # address of register-save area
-       basr    %r14,%r7                # branch to interrupt-handler
+       basr    %r14,%r1                # branch to interrupt-handler
 pgm_exit:
        b       BASED(sysc_return)
 
@@ -505,33 +507,34 @@ pgm_per:
 # Normal per exception
 #
 pgm_per_std:
-       SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA
-       CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
+       SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA
+       CREATE_STACK_FRAME __LC_SAVE_AREA
+       mvc     SP_PSW(8,%r15),__LC_PGM_OLD_PSW
+       l       %r12,__LC_THREAD_INFO   # load pointer to thread_info struct
        tm      SP_PSW+1(%r15),0x01     # interrupting from user ?
        bz      BASED(pgm_no_vtime2)
        UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
        UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
        mvc     __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
 pgm_no_vtime2:
-       l       %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
-       l       %r1,__TI_task(%r9)
+       l       %r1,__TI_task(%r12)
        tm      SP_PSW+1(%r15),0x01     # kernel per event ?
        bz      BASED(kernel_per)
        mvc     __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID
        mvc     __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS
        mvc     __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
-       oi      __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
+       oi      __TI_flags+3(%r12),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
        l       %r3,__LC_PGM_ILC        # load program interruption code
        l       %r4,__LC_TRANS_EXC_CODE
        REENABLE_IRQS
        la      %r8,0x7f
        nr      %r8,%r3                 # clear per-event-bit and ilc
        be      BASED(pgm_exit2)        # only per or per+check ?
-       l       %r7,BASED(.Ljump_table)
        sll     %r8,2
-       l       %r7,0(%r8,%r7)          # load address of handler routine
+       l       %r1,BASED(.Ljump_table)
+       l       %r1,0(%r8,%r1)          # load address of handler routine
        la      %r2,SP_PTREGS(%r15)     # address of register-save area
-       basr    %r14,%r7                # branch to interrupt-handler
+       basr    %r14,%r1                # branch to interrupt-handler
 pgm_exit2:
        b       BASED(sysc_return)
 
@@ -539,18 +542,19 @@ pgm_exit2:
 # it was a single stepped SVC that is causing all the trouble
 #
 pgm_svcper:
-       SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
-       CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
+       SAVE_ALL_PGM __LC_SVC_OLD_PSW,__LC_SAVE_AREA
+       CREATE_STACK_FRAME __LC_SAVE_AREA
+       mvc     SP_PSW(8,%r15),__LC_SVC_OLD_PSW
+       mvc     SP_ILC(4,%r15),__LC_SVC_ILC
+       l       %r12,__LC_THREAD_INFO   # load pointer to thread_info struct
        UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
        UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
        mvc     __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
-       lh      %r7,0x8a                # get svc number from lowcore
-       l       %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
-       l       %r8,__TI_task(%r9)
+       l       %r8,__TI_task(%r12)
        mvc     __THREAD_per+__PER_atmid(2,%r8),__LC_PER_ATMID
        mvc     __THREAD_per+__PER_address(4,%r8),__LC_PER_ADDRESS
        mvc     __THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID
-       oi      __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
+       oi      __TI_flags+3(%r12),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
        stosm   __SF_EMPTY(%r15),0x03   # reenable interrupts
        lm      %r2,%r6,SP_R2(%r15)     # load svc arguments
        b       BASED(sysc_do_svc)
@@ -560,8 +564,7 @@ pgm_svcper:
 #
 kernel_per:
        REENABLE_IRQS
-       mvi     SP_SVCNR(%r15),0xff     # set trap indication to pgm check
-       mvi     SP_SVCNR+1(%r15),0xff
+       xc      SP_SVCNR(2,%r15),SP_SVCNR(%r15)
        la      %r2,SP_PTREGS(%r15)     # address of register-save area
        l       %r1,BASED(.Lhandle_per) # load adr. of per handler
        basr    %r14,%r1                # branch to do_single_step
@@ -575,9 +578,10 @@ kernel_per:
 io_int_handler:
        stck    __LC_INT_CLOCK
        stpt    __LC_ASYNC_ENTER_TIMER
-       SAVE_ALL_BASE __LC_SAVE_AREA+16
        SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+16
-       CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+16
+       CREATE_STACK_FRAME __LC_SAVE_AREA+16
+       mvc     SP_PSW(8,%r15),0(%r12)  # move user PSW to stack
+       l       %r12,__LC_THREAD_INFO   # load pointer to thread_info struct
        tm      SP_PSW+1(%r15),0x01     # interrupting from user ?
        bz      BASED(io_no_vtime)
        UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
@@ -585,7 +589,6 @@ io_int_handler:
        mvc     __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
 io_no_vtime:
        TRACE_IRQS_OFF
-       l       %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
        l       %r1,BASED(.Ldo_IRQ)     # load address of do_IRQ
        la      %r2,SP_PTREGS(%r15)     # address of register-save area
        basr    %r14,%r1                # branch to standard irq handler
@@ -593,7 +596,7 @@ io_return:
        LOCKDEP_SYS_EXIT
        TRACE_IRQS_ON
 io_tif:
-       tm      __TI_flags+3(%r9),_TIF_WORK_INT
+       tm      __TI_flags+3(%r12),_TIF_WORK_INT
        bnz     BASED(io_work)          # there is work to do (signals etc.)
 io_restore:
        RESTORE_ALL __LC_RETURN_PSW,0
@@ -611,9 +614,9 @@ io_work:
        bo      BASED(io_work_user)     # yes -> do resched & signal
 #ifdef CONFIG_PREEMPT
        # check for preemptive scheduling
-       icm     %r0,15,__TI_precount(%r9)
+       icm     %r0,15,__TI_precount(%r12)
        bnz     BASED(io_restore)       # preemption disabled
-       tm      __TI_flags+3(%r9),_TIF_NEED_RESCHED
+       tm      __TI_flags+3(%r12),_TIF_NEED_RESCHED
        bno     BASED(io_restore)
        # switch to kernel stack
        l       %r1,SP_R15(%r15)
@@ -647,13 +650,13 @@ io_work_user:
 #              and _TIF_MCCK_PENDING
 #
 io_work_tif:
-       tm      __TI_flags+3(%r9),_TIF_MCCK_PENDING
+       tm      __TI_flags+3(%r12),_TIF_MCCK_PENDING
        bo      BASED(io_mcck_pending)
-       tm      __TI_flags+3(%r9),_TIF_NEED_RESCHED
+       tm      __TI_flags+3(%r12),_TIF_NEED_RESCHED
        bo      BASED(io_reschedule)
-       tm      __TI_flags+3(%r9),_TIF_SIGPENDING
+       tm      __TI_flags+3(%r12),_TIF_SIGPENDING
        bo      BASED(io_sigpending)
-       tm      __TI_flags+3(%r9),_TIF_NOTIFY_RESUME
+       tm      __TI_flags+3(%r12),_TIF_NOTIFY_RESUME
        bo      BASED(io_notify_resume)
        b       BASED(io_return)        # beware of critical section cleanup
 
@@ -713,16 +716,16 @@ io_notify_resume:
 ext_int_handler:
        stck    __LC_INT_CLOCK
        stpt    __LC_ASYNC_ENTER_TIMER
-       SAVE_ALL_BASE __LC_SAVE_AREA+16
        SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16
-       CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16
+       CREATE_STACK_FRAME __LC_SAVE_AREA+16
+       mvc     SP_PSW(8,%r15),0(%r12)  # move user PSW to stack
+       l       %r12,__LC_THREAD_INFO   # load pointer to thread_info struct
        tm      SP_PSW+1(%r15),0x01     # interrupting from user ?
        bz      BASED(ext_no_vtime)
        UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
        UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
        mvc     __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
 ext_no_vtime:
-       l       %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
        TRACE_IRQS_OFF
        la      %r2,SP_PTREGS(%r15)     # address of register-save area
        l       %r3,__LC_CPU_ADDRESS    # get cpu address + interruption code
@@ -777,7 +780,10 @@ mcck_int_main:
        sra     %r14,PAGE_SHIFT
        be      BASED(0f)
        l       %r15,__LC_PANIC_STACK   # load panic stack
-0:     CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+32
+0:     s       %r15,BASED(.Lc_spsize)  # make room for registers & psw
+       CREATE_STACK_FRAME __LC_SAVE_AREA+32
+       mvc     SP_PSW(8,%r15),0(%r12)
+       l       %r12,__LC_THREAD_INFO   # load pointer to thread_info struct
        tm      __LC_MCCK_CODE+2,0x08   # mwp of old psw valid?
        bno     BASED(mcck_no_vtime)    # no -> skip cleanup critical
        tm      SP_PSW+1(%r15),0x01     # interrupting from user ?
@@ -786,7 +792,6 @@ mcck_int_main:
        UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
        mvc     __LC_LAST_UPDATE_TIMER(8),__LC_MCCK_ENTER_TIMER
 mcck_no_vtime:
-       l       %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
        la      %r2,SP_PTREGS(%r15)     # load pt_regs
        l       %r1,BASED(.Ls390_mcck)
        basr    %r14,%r1                # call machine check handler
@@ -798,7 +803,7 @@ mcck_no_vtime:
        xc      __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
        lr      %r15,%r1
        stosm   __SF_EMPTY(%r15),0x04   # turn dat on
-       tm      __TI_flags+3(%r9),_TIF_MCCK_PENDING
+       tm      __TI_flags+3(%r12),_TIF_MCCK_PENDING
        bno     BASED(mcck_return)
        TRACE_IRQS_OFF
        l       %r1,BASED(.Ls390_handle_mcck)
@@ -947,12 +952,13 @@ cleanup_system_call:
        bh      BASED(0f)
        mvc     __LC_SAVE_AREA(16),0(%r12)
 0:     st      %r13,4(%r12)
-       st      %r12,__LC_SAVE_AREA+48  # argh
-       SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
-       CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
-       l       %r12,__LC_SAVE_AREA+48  # argh
+       l       %r15,__LC_KERNEL_STACK  # problem state -> load ksp
+       s       %r15,BASED(.Lc_spsize)  # make room for registers & psw
        st      %r15,12(%r12)
-       lh      %r7,0x8a
+       CREATE_STACK_FRAME __LC_SAVE_AREA
+       mvc     SP_PSW(8,%r15),__LC_SVC_OLD_PSW
+       mvc     SP_ILC(4,%r15),__LC_SVC_ILC
+       mvc     0(4,%r12),__LC_THREAD_INFO
 cleanup_vtime:
        clc     __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+12)
        bhe     BASED(cleanup_stime)