]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - arch/s390/kernel/entry.S
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / arch / s390 / kernel / entry.S
index 1ecc337fb679045e968ef1915ea009c4777786de..648f64239a9d169d0f9f983d59a667f14fafea9d 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>
@@ -49,7 +48,7 @@ SP_SVCNR     =        STACK_FRAME_OVERHEAD + __PT_SVCNR
 SP_SIZE      = STACK_FRAME_OVERHEAD + __PT_SIZE
 
 _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
-                _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
+                _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_PER_TRAP )
 _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
                 _TIF_MCCK_PENDING)
 _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
@@ -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
@@ -188,6 +188,8 @@ STACK_SIZE  = 1 << STACK_SHIFT
        ssm     __SF_EMPTY(%r15)
        .endm
 
+       .section .kprobes.text, "ax"
+
 /*
  * Scheduler resume function, called by switch_to
  *  gpr2 = (task_struct *) prev
@@ -198,31 +200,21 @@ STACK_SIZE  = 1 << STACK_SHIFT
        .globl  __switch_to
 __switch_to:
        basr    %r1,0
-__switch_to_base:
-       tm      __THREAD_per(%r3),0xe8          # new process is using per ?
-       bz      __switch_to_noper-__switch_to_base(%r1) # if not we're fine
-       stctl   %c9,%c11,__SF_EMPTY(%r15)       # We are using per stuff
-       clc     __THREAD_per(12,%r3),__SF_EMPTY(%r15)
-       be      __switch_to_noper-__switch_to_base(%r1) # we got away w/o bashing TLB's
-       lctl    %c9,%c11,__THREAD_per(%r3)      # Nope we didn't
-__switch_to_noper:
-       l       %r4,__THREAD_info(%r2)          # get thread_info of prev
+0:     l       %r4,__THREAD_info(%r2)          # get thread_info of prev
+       l       %r5,__THREAD_info(%r3)          # get thread_info of next
        tm      __TI_flags+3(%r4),_TIF_MCCK_PENDING # machine check pending?
-       bz      __switch_to_no_mcck-__switch_to_base(%r1)
-       ni      __TI_flags+3(%r4),255-_TIF_MCCK_PENDING # clear flag in prev
-       l       %r4,__THREAD_info(%r3)          # get thread_info of next
-       oi      __TI_flags+3(%r4),_TIF_MCCK_PENDING # set it in next
-__switch_to_no_mcck:
-       stm     %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task
-       st      %r15,__THREAD_ksp(%r2)  # store kernel stack to prev->tss.ksp
-       l       %r15,__THREAD_ksp(%r3)  # load kernel stack from next->tss.ksp
-       lm      %r6,%r15,__SF_GPRS(%r15)# load __switch_to registers of next task
-       st      %r3,__LC_CURRENT        # __LC_CURRENT = current task struct
-       lctl    %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4
-       l       %r3,__THREAD_info(%r3)  # load thread_info from task struct
-       st      %r3,__LC_THREAD_INFO
-       ahi     %r3,STACK_SIZE
-       st      %r3,__LC_KERNEL_STACK   # __LC_KERNEL_STACK = new kernel stack
+       bz      1f-0b(%r1)
+       ni      __TI_flags+3(%r4),255-_TIF_MCCK_PENDING # clear flag in prev
+       oi      __TI_flags+3(%r5),_TIF_MCCK_PENDING     # set it in next
+1:     stm     %r6,%r15,__SF_GPRS(%r15)        # store gprs of prev task
+       st      %r15,__THREAD_ksp(%r2)          # store kernel stack of prev
+       l       %r15,__THREAD_ksp(%r3)          # load kernel stack of next
+       lctl    %c4,%c4,__TASK_pid(%r3)         # load pid to control reg. 4
+       lm      %r6,%r15,__SF_GPRS(%r15)        # load gprs of next task
+       st      %r3,__LC_CURRENT                # store task struct of next
+       st      %r5,__LC_THREAD_INFO            # store thread info of next
+       ahi     %r5,STACK_SIZE                  # end of kernel stack of next
+       st      %r5,__LC_KERNEL_STACK           # store end of kernel stack
        br      %r14
 
 __critical_start:
@@ -235,10 +227,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:
@@ -246,20 +239,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)
@@ -267,7 +260,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
@@ -284,17 +277,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_PER_TRAP
        bo      BASED(sysc_singlestep)
        b       BASED(sysc_return)      # beware of critical section cleanup
 
@@ -318,13 +311,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_PER_TRAP # clear TIF_PER_TRAP
        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_PER_TRAP
        bo      BASED(sysc_singlestep)
        b       BASED(sysc_return)
 
@@ -342,23 +335,23 @@ 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
+# _TIF_PER_TRAP is set, call do_per_trap
 #
 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_PER_TRAP # clear TIF_PER_TRAP
+       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
-       br      %r1                     # branch to do_single_step
+       br      %r1                     # branch to do_per_trap
 
 #
 # call tracehook_report_syscall_entry/tracehook_report_syscall_exit before
@@ -368,15 +361,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)
@@ -384,7 +377,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
@@ -397,7 +390,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
@@ -432,8 +425,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)
@@ -463,26 +456,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)
 
@@ -503,33 +497,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
+       mvc     __THREAD_per_cause(2,%r1),__LC_PER_CAUSE
+       mvc     __THREAD_per_address(4,%r1),__LC_PER_ADDRESS
+       mvc     __THREAD_per_paid(1,%r1),__LC_PER_PAID
+       oi      __TI_flags+3(%r12),_TIF_PER_TRAP # set TIF_PER_TRAP
        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)
 
@@ -537,18 +532,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)
-       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
+       l       %r8,__TI_task(%r12)
+       mvc     __THREAD_per_cause(2,%r8),__LC_PER_CAUSE
+       mvc     __THREAD_per_address(4,%r8),__LC_PER_ADDRESS
+       mvc     __THREAD_per_paid(1,%r8),__LC_PER_PAID
+       oi      __TI_flags+3(%r12),_TIF_PER_TRAP # set TIF_PER_TRAP
        stosm   __SF_EMPTY(%r15),0x03   # reenable interrupts
        lm      %r2,%r6,SP_R2(%r15)     # load svc arguments
        b       BASED(sysc_do_svc)
@@ -558,8 +554,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
@@ -573,9 +568,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
@@ -583,7 +579,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
@@ -591,7 +586,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
@@ -609,9 +604,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)
@@ -645,13 +640,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
 
@@ -711,16 +706,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
@@ -775,7 +770,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 ?
@@ -784,7 +782,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
@@ -796,7 +793,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)
@@ -861,6 +858,8 @@ restart_crash:
 restart_go:
 #endif
 
+       .section .kprobes.text, "ax"
+
 #ifdef CONFIG_CHECK_STACK
 /*
  * The synchronous or the asynchronous stack overflowed. We are dead.
@@ -943,12 +942,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)
@@ -1046,7 +1046,7 @@ cleanup_io_restore_insn:
 .Ldo_signal:   .long   do_signal
 .Ldo_notify_resume:
                .long   do_notify_resume
-.Lhandle_per:  .long   do_single_step
+.Lhandle_per:  .long   do_per_trap
 .Ldo_execve:   .long   do_execve
 .Lexecve_tail: .long   execve_tail
 .Ljump_table:  .long   pgm_check_table