_TIF_MCCK_PENDING)
 _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
                _TIF_SECCOMP>>8 | _TIF_SYSCALL_TRACEPOINT>>8)
+_TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
 
 #define BASED(name) name-system_call(%r13)
 
+       .macro SPP newpp
+#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
+       tm      __LC_MACHINE_FLAGS+6,0x20       # MACHINE_FLAG_SPP
+       jz      .+8
+       .insn   s,0xb2800000,\newpp
+#endif
+       .endm
+
        .macro  HANDLE_SIE_INTERCEPT
 #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
-       lg      %r3,__LC_SIE_HOOK
-       ltgr    %r3,%r3
+       tm      __TI_flags+6(%r12),_TIF_SIE>>8
        jz      0f
-       basr    %r14,%r3
+       SPP     __LC_CMF_HPP                    # set host id
+       clc     SP_PSW+8(8,%r15),BASED(.Lsie_loop)
+       jl      0f
+       clc     SP_PSW+8(8,%r15),BASED(.Lsie_done)
+       jhe     0f
+       mvc     SP_PSW+8(8,%r15),BASED(.Lsie_loop)
 0:
 #endif
        .endm
        xc      SP_ILC(4,%r15),SP_ILC(%r15)
        mvc     SP_PSW(16,%r15),__LC_PGM_OLD_PSW
        lg      %r12,__LC_THREAD_INFO   # load pointer to thread_info struct
+       HANDLE_SIE_INTERCEPT
        tm      SP_PSW+1(%r15),0x01     # interrupting from user ?
        jz      pgm_no_vtime
        UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
        mvc     __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
        LAST_BREAK
 pgm_no_vtime:
-       HANDLE_SIE_INTERCEPT
        stg     %r11,SP_ARGS(%r15)
        lgf     %r3,__LC_PGM_ILC        # load program interruption code
        lg      %r4,__LC_TRANS_EXC_CODE
        CREATE_STACK_FRAME __LC_SAVE_AREA
        mvc     SP_PSW(16,%r15),__LC_PGM_OLD_PSW
        lg      %r12,__LC_THREAD_INFO   # load pointer to thread_info struct
+       HANDLE_SIE_INTERCEPT
        tm      SP_PSW+1(%r15),0x01     # interrupting from user ?
        jz      pgm_no_vtime2
        UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
        mvc     __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
        LAST_BREAK
 pgm_no_vtime2:
-       HANDLE_SIE_INTERCEPT
        lg      %r1,__TI_task(%r12)
        tm      SP_PSW+1(%r15),0x01     # kernel per event ?
        jz      kernel_per
        CREATE_STACK_FRAME __LC_SAVE_AREA+40
        mvc     SP_PSW(16,%r15),0(%r12) # move user PSW to stack
        lg      %r12,__LC_THREAD_INFO   # load pointer to thread_info struct
+       HANDLE_SIE_INTERCEPT
        tm      SP_PSW+1(%r15),0x01     # interrupting from user ?
        jz      io_no_vtime
        UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
        mvc     __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
        LAST_BREAK
 io_no_vtime:
-       HANDLE_SIE_INTERCEPT
        TRACE_IRQS_OFF
        la      %r2,SP_PTREGS(%r15)     # address of register-save area
        brasl   %r14,do_IRQ             # call standard irq handler
        CREATE_STACK_FRAME __LC_SAVE_AREA+40
        mvc     SP_PSW(16,%r15),0(%r12) # move user PSW to stack
        lg      %r12,__LC_THREAD_INFO   # load pointer to thread_info struct
+       HANDLE_SIE_INTERCEPT
        tm      SP_PSW+1(%r15),0x01     # interrupting from user ?
        jz      ext_no_vtime
        UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
        mvc     __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
        LAST_BREAK
 ext_no_vtime:
-       HANDLE_SIE_INTERCEPT
        TRACE_IRQS_OFF
        lghi    %r1,4096
        la      %r2,SP_PTREGS(%r15)     # address of register-save area
        lg      %r12,__LC_THREAD_INFO   # load pointer to thread_info struct
        tm      __LC_MCCK_CODE+2,0x08   # mwp of old psw valid?
        jno     mcck_no_vtime           # no -> no timer update
+       HANDLE_SIE_INTERCEPT
        tm      SP_PSW+1(%r15),0x01     # interrupting from user ?
        jz      mcck_no_vtime
        UPDATE_VTIME __LC_EXIT_TIMER,__LC_MCCK_ENTER_TIMER,__LC_USER_TIMER
        stosm   __SF_EMPTY(%r15),0x04   # turn dat on
        tm      __TI_flags+7(%r12),_TIF_MCCK_PENDING
        jno     mcck_return
-       HANDLE_SIE_INTERCEPT
        TRACE_IRQS_OFF
        brasl   %r14,s390_handle_mcck
        TRACE_IRQS_ON
 .Lcritical_end:
                .quad   __critical_end
 
+#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
+/*
+ * sie64a calling convention:
+ * %r2 pointer to sie control block
+ * %r3 guest register save area
+ */
+       .globl  sie64a
+sie64a:
+       stmg    %r6,%r14,__SF_GPRS(%r15)        # save kernel registers
+       stg     %r2,__SF_EMPTY(%r15)            # save control block pointer
+       stg     %r3,__SF_EMPTY+8(%r15)          # save guest register save area
+       lmg     %r0,%r13,0(%r3)                 # load guest gprs 0-13
+       lg      %r14,__LC_THREAD_INFO           # pointer thread_info struct
+       oi      __TI_flags+6(%r14),_TIF_SIE>>8
+sie_loop:
+       lg      %r14,__LC_THREAD_INFO           # pointer thread_info struct
+       tm      __TI_flags+7(%r14),_TIF_EXIT_SIE
+       jnz     sie_exit
+       lg      %r14,__SF_EMPTY(%r15)           # get control block pointer
+       SPP     __SF_EMPTY(%r15)                # set guest id
+       sie     0(%r14)
+sie_done:
+       SPP     __LC_CMF_HPP                    # set host id
+       lg      %r14,__LC_THREAD_INFO           # pointer thread_info struct
+sie_exit:
+       ni      __TI_flags+6(%r14),255-(_TIF_SIE>>8)
+       lg      %r14,__SF_EMPTY+8(%r15)         # load guest register save area
+       stmg    %r0,%r13,0(%r14)                # save guest gprs 0-13
+       lmg     %r6,%r14,__SF_GPRS(%r15)        # restore kernel registers
+       lghi    %r2,0
+       br      %r14
+sie_fault:
+       lg      %r14,__LC_THREAD_INFO           # pointer thread_info struct
+       ni      __TI_flags+6(%r14),255-(_TIF_SIE>>8)
+       lg      %r14,__SF_EMPTY+8(%r15)         # load guest register save area
+       stmg    %r0,%r13,0(%r14)                # save guest gprs 0-13
+       lmg     %r6,%r14,__SF_GPRS(%r15)        # restore kernel registers
+       lghi    %r2,-EFAULT
+       br      %r14
+
+       .align  8
+.Lsie_loop:
+       .quad   sie_loop
+.Lsie_done:
+       .quad   sie_done
+
+       .section __ex_table,"a"
+       .quad   sie_loop,sie_fault
+       .previous
+#endif
+
                .section .rodata, "a"
 #define SYSCALL(esa,esame,emu) .long esame
        .globl  sys_call_table
 
+++ /dev/null
-/*
- * sie64a.S - low level sie call
- *
- * Copyright IBM Corp. 2008,2010
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License (version 2 only)
- * as published by the Free Software Foundation.
- *
- *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
- *              Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
- */
-
-#include <linux/errno.h>
-#include <asm/asm-offsets.h>
-#include <asm/setup.h>
-#include <asm/asm-offsets.h>
-#include <asm/ptrace.h>
-#include <asm/thread_info.h>
-
-_TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
-
-/*
- * offsets into stackframe
- * SP_ = offsets into stack sie64 is called with
- * SPI_ = offsets into irq stack
- */
-SP_GREGS = __SF_EMPTY
-SP_HOOK  = __SF_EMPTY+8
-SP_GPP  = __SF_EMPTY+16
-SPI_PSW  = STACK_FRAME_OVERHEAD + __PT_PSW
-
-
-       .macro SPP newpp
-       tm      __LC_MACHINE_FLAGS+6,0x20       # MACHINE_FLAG_SPP
-       jz      0f
-       .insn   s,0xb2800000,\newpp
-0:
-       .endm
-
-sie_irq_handler:
-       SPP     __LC_CMF_HPP                    # set host id
-       larl    %r2,sie_inst
-       clg     %r2,SPI_PSW+8(0,%r15)           # intercepted sie
-       jne     1f
-       xc      __LC_SIE_HOOK(8),__LC_SIE_HOOK
-       lg      %r2,__LC_THREAD_INFO            # pointer thread_info struct
-       tm      __TI_flags+7(%r2),_TIF_EXIT_SIE
-       jz      0f
-       larl    %r2,sie_exit                    # work pending, leave sie
-       stg     %r2,SPI_PSW+8(0,%r15)
-       br      %r14
-0:     larl    %r2,sie_reenter                 # re-enter with guest id
-       stg     %r2,SPI_PSW+8(0,%r15)
-1:     br      %r14
-
-/*
- * sie64a calling convention:
- * %r2 pointer to sie control block
- * %r3 guest register save area
- */
-       .globl  sie64a
-sie64a:
-       stg     %r3,SP_GREGS(%r15)              # save guest register save area
-       stmg    %r6,%r14,__SF_GPRS(%r15)        # save registers on entry
-       lgr     %r14,%r2                        # pointer to sie control block
-       larl    %r5,sie_irq_handler
-       stg     %r2,SP_GPP(%r15)
-       stg     %r5,SP_HOOK(%r15)               # save hook target
-       lmg     %r0,%r13,0(%r3)                 # load guest gprs 0-13
-sie_reenter:
-       mvc     __LC_SIE_HOOK(8),SP_HOOK(%r15)
-       SPP     SP_GPP(%r15)                    # set guest id
-sie_inst:
-       sie     0(%r14)
-       xc      __LC_SIE_HOOK(8),__LC_SIE_HOOK
-       SPP     __LC_CMF_HPP                    # set host id
-sie_exit:
-       lg      %r14,SP_GREGS(%r15)
-       stmg    %r0,%r13,0(%r14)                # save guest gprs 0-13
-       lghi    %r2,0
-       lmg     %r6,%r14,__SF_GPRS(%r15)
-       br      %r14
-
-sie_err:
-       xc      __LC_SIE_HOOK(8),__LC_SIE_HOOK
-       SPP     __LC_CMF_HPP                    # set host id
-       lg      %r14,SP_GREGS(%r15)
-       stmg    %r0,%r13,0(%r14)                # save guest gprs 0-13
-       lghi    %r2,-EFAULT
-       lmg     %r6,%r14,__SF_GPRS(%r15)
-       br      %r14
-
-       .section __ex_table,"a"
-       .quad   sie_inst,sie_err
-       .quad   sie_exit,sie_err
-       .quad   sie_reenter,sie_err
-       .previous