[S390] s390-kvm: leave sie context on work. Removes preemption requirement
[safe/jmp/linux-2.6] / arch / s390 / kernel / entry64.S
index e15c80e..fee1017 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/sys.h>
 #include <linux/linkage.h>
+#include <linux/init.h>
 #include <asm/cache.h>
 #include <asm/lowcore.h>
 #include <asm/errno.h>
@@ -51,9 +52,9 @@ SP_SIZE      =        STACK_FRAME_OVERHEAD + __PT_SIZE
 STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
 STACK_SIZE  = 1 << STACK_SHIFT
 
-_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
+_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
                 _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
-_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
+_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
                 _TIF_MCCK_PENDING)
 
 #define BASED(name) name-system_call(%r13)
@@ -270,8 +271,6 @@ sysc_noemu:
        stg     %r2,SP_R2(%r15) # store return value (change R2 on stack)
 
 sysc_return:
-       tm      SP_PSW+1(%r15),0x01     # returning to user ?
-       jno     sysc_restore
        tm      __TI_flags+7(%r9),_TIF_WORK_SVC
        jnz     sysc_work       # there is work to do (signals etc.)
 sysc_restore:
@@ -303,11 +302,13 @@ sysc_work_loop:
 # One of the work bits is on. Find out which one.
 #
 sysc_work:
+       tm      SP_PSW+1(%r15),0x01     # returning to user ?
+       jno     sysc_restore
        tm      __TI_flags+7(%r9),_TIF_MCCK_PENDING
        jo      sysc_mcck_pending
        tm      __TI_flags+7(%r9),_TIF_NEED_RESCHED
        jo      sysc_reschedule
-       tm      __TI_flags+7(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)
+       tm      __TI_flags+7(%r9),_TIF_SIGPENDING
        jnz     sysc_sigpending
        tm      __TI_flags+7(%r9),_TIF_RESTART_SVC
        jo      sysc_restart
@@ -331,7 +332,7 @@ sysc_mcck_pending:
        jg      s390_handle_mcck        # TIF bit will be cleared by handler
 
 #
-# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
+# _TIF_SIGPENDING is set, call do_signal
 #
 sysc_sigpending:
        ni      __TI_flags+7(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
@@ -474,6 +475,7 @@ pgm_check_handler:
 pgm_no_vtime:
 #endif
        lg      %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
+       mvc     SP_ARGS(8,%r15),__LC_LAST_BREAK
        TRACE_IRQS_OFF
        lgf     %r3,__LC_PGM_ILC        # load program interruption code
        lghi    %r8,0x7f
@@ -583,12 +585,6 @@ io_no_vtime:
        la      %r2,SP_PTREGS(%r15)     # address of register-save area
        brasl   %r14,do_IRQ             # call standard irq handler
 io_return:
-       tm      SP_PSW+1(%r15),0x01     # returning to user ?
-#ifdef CONFIG_PREEMPT
-       jno     io_preempt              # no -> check for preemptive scheduling
-#else
-       jno     io_restore              # no-> skip resched & signal
-#endif
        tm      __TI_flags+7(%r9),_TIF_WORK_INT
        jnz     io_work                 # there is work to do (signals etc.)
 io_restore:
@@ -610,10 +606,41 @@ io_restore_trace_psw:
        .quad   0, io_restore_trace
 #endif
 
-#ifdef CONFIG_PREEMPT
-io_preempt:
+#
+# There is work todo, we need to check if we return to userspace, then
+# check, if we are in SIE, if yes leave it
+#
+io_work:
+       tm      SP_PSW+1(%r15),0x01     # returning to user ?
+#ifndef CONFIG_PREEMPT
+#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
+       jnz     io_work_user            # yes -> no need to check for SIE
+       la      %r1, BASED(sie_opcode)  # we return to kernel here
+       lg      %r2, SP_PSW+8(%r15)
+       clc     0(2,%r1), 0(%r2)        # is current instruction = SIE?
+       jne     io_restore              # no-> return to kernel
+       lg      %r1, SP_PSW+8(%r15)     # yes-> add 4 bytes to leave SIE
+       aghi    %r1, 4
+       stg     %r1, SP_PSW+8(%r15)
+       j       io_restore              # return to kernel
+#else
+       jno     io_restore              # no-> skip resched & signal
+#endif
+#else
+       jnz     io_work_user            # yes -> do resched & signal
+#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
+       la      %r1, BASED(sie_opcode)
+       lg      %r2, SP_PSW+8(%r15)
+       clc     0(2,%r1), 0(%r2)        # is current instruction = SIE?
+       jne     0f                      # no -> leave PSW alone
+       lg      %r1, SP_PSW+8(%r15)     # yes-> add 4 bytes to leave SIE
+       aghi    %r1, 4
+       stg     %r1, SP_PSW+8(%r15)
+0:
+#endif
+       # check for preemptive scheduling
        icm     %r0,15,__TI_precount(%r9)
-       jnz     io_restore
+       jnz     io_restore              # preemption is disabled
        # switch to kernel stack
        lg      %r1,SP_R15(%r15)
        aghi    %r1,-SP_SIZE
@@ -623,21 +650,11 @@ io_preempt:
 io_resume_loop:
        tm      __TI_flags+7(%r9),_TIF_NEED_RESCHED
        jno     io_restore
-       larl    %r1,.Lc_pactive
-       mvc     __TI_precount(4,%r9),0(%r1)
-       TRACE_IRQS_ON
-       stosm   __SF_EMPTY(%r15),0x03   # reenable interrupts
-       brasl   %r14,schedule           # call schedule
-       stnsm   __SF_EMPTY(%r15),0xfc   # disable I/O and ext. interrupts
-       TRACE_IRQS_OFF
-       xc      __TI_precount(4,%r9),__TI_precount(%r9)
-       j       io_resume_loop
+       larl    %r14,io_resume_loop
+       jg      preempt_schedule_irq
 #endif
 
-#
-# switch to kernel stack, then check TIF bits
-#
-io_work:
+io_work_user:
        lg      %r1,__LC_KERNEL_STACK
        aghi    %r1,-SP_SIZE
        mvc     SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
@@ -653,11 +670,16 @@ io_work_loop:
        jo      io_mcck_pending
        tm      __TI_flags+7(%r9),_TIF_NEED_RESCHED
        jo      io_reschedule
-       tm      __TI_flags+7(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)
+       tm      __TI_flags+7(%r9),_TIF_SIGPENDING
        jnz     io_sigpending
        j       io_restore
 io_work_done:
 
+#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
+sie_opcode:
+       .long 0xb2140000
+#endif
+
 #
 # _TIF_MCCK_PENDING is set, call handler
 #
@@ -679,7 +701,7 @@ io_reschedule:
        j       io_work_loop
 
 #
-# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
+# _TIF_SIGPENDING or is set, call do_signal
 #
 io_sigpending:
        TRACE_IRQS_ON
@@ -808,9 +830,7 @@ mcck_return:
  * Restart interruption handler, kick starter for additional CPUs
  */
 #ifdef CONFIG_SMP
-#ifndef CONFIG_HOTPLUG_CPU
-       .section .init.text,"ax"
-#endif
+       __CPUINIT
        .globl restart_int_handler
 restart_int_handler:
        lg      %r15,__LC_SAVE_AREA+120 # load ksp
@@ -821,9 +841,7 @@ restart_int_handler:
        lmg     %r6,%r15,__SF_GPRS(%r15) # load registers from clone
        stosm   __SF_EMPTY(%r15),0x04   # now we can turn dat on
        jg      start_secondary
-#ifndef CONFIG_HOTPLUG_CPU
        .previous
-#endif
 #else
 /*
  * If we do not run with SMP enabled, let the new CPU crash ...
@@ -857,6 +875,7 @@ stack_overflow:
        je      0f
        la      %r1,__LC_SAVE_AREA+32
 0:     mvc     SP_R12(32,%r15),0(%r1)  # move %r12-%r15 to stack
+       mvc     SP_ARGS(8,%r15),__LC_LAST_BREAK
        xc      __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) # clear back chain
        la      %r2,SP_PTREGS(%r15)     # load pt_regs
        jg      kernel_stack_overflow
@@ -1029,7 +1048,6 @@ cleanup_io_leave_insn:
  */
                .align  4
 .Lconst:
-.Lc_pactive:   .long   PREEMPT_ACTIVE
 .Lnr_syscalls: .long   NR_syscalls
 .L0x0130:      .short  0x130
 .L0x0140:      .short  0x140