diff options
Diffstat (limited to 'arch/s390/kernel/entry64.S')
-rw-r--r-- | arch/s390/kernel/entry64.S | 57 |
1 files changed, 42 insertions, 15 deletions
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 5a4a7bcd2bba..fee10177dbfc 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
@@ -271,8 +271,6 @@ sysc_noemu: | |||
271 | stg %r2,SP_R2(%r15) # store return value (change R2 on stack) | 271 | stg %r2,SP_R2(%r15) # store return value (change R2 on stack) |
272 | 272 | ||
273 | sysc_return: | 273 | sysc_return: |
274 | tm SP_PSW+1(%r15),0x01 # returning to user ? | ||
275 | jno sysc_restore | ||
276 | tm __TI_flags+7(%r9),_TIF_WORK_SVC | 274 | tm __TI_flags+7(%r9),_TIF_WORK_SVC |
277 | jnz sysc_work # there is work to do (signals etc.) | 275 | jnz sysc_work # there is work to do (signals etc.) |
278 | sysc_restore: | 276 | sysc_restore: |
@@ -304,6 +302,8 @@ sysc_work_loop: | |||
304 | # One of the work bits is on. Find out which one. | 302 | # One of the work bits is on. Find out which one. |
305 | # | 303 | # |
306 | sysc_work: | 304 | sysc_work: |
305 | tm SP_PSW+1(%r15),0x01 # returning to user ? | ||
306 | jno sysc_restore | ||
307 | tm __TI_flags+7(%r9),_TIF_MCCK_PENDING | 307 | tm __TI_flags+7(%r9),_TIF_MCCK_PENDING |
308 | jo sysc_mcck_pending | 308 | jo sysc_mcck_pending |
309 | tm __TI_flags+7(%r9),_TIF_NEED_RESCHED | 309 | tm __TI_flags+7(%r9),_TIF_NEED_RESCHED |
@@ -585,12 +585,6 @@ io_no_vtime: | |||
585 | la %r2,SP_PTREGS(%r15) # address of register-save area | 585 | la %r2,SP_PTREGS(%r15) # address of register-save area |
586 | brasl %r14,do_IRQ # call standard irq handler | 586 | brasl %r14,do_IRQ # call standard irq handler |
587 | io_return: | 587 | io_return: |
588 | tm SP_PSW+1(%r15),0x01 # returning to user ? | ||
589 | #ifdef CONFIG_PREEMPT | ||
590 | jno io_preempt # no -> check for preemptive scheduling | ||
591 | #else | ||
592 | jno io_restore # no-> skip resched & signal | ||
593 | #endif | ||
594 | tm __TI_flags+7(%r9),_TIF_WORK_INT | 588 | tm __TI_flags+7(%r9),_TIF_WORK_INT |
595 | jnz io_work # there is work to do (signals etc.) | 589 | jnz io_work # there is work to do (signals etc.) |
596 | io_restore: | 590 | io_restore: |
@@ -612,10 +606,41 @@ io_restore_trace_psw: | |||
612 | .quad 0, io_restore_trace | 606 | .quad 0, io_restore_trace |
613 | #endif | 607 | #endif |
614 | 608 | ||
615 | #ifdef CONFIG_PREEMPT | 609 | # |
616 | io_preempt: | 610 | # There is work todo, we need to check if we return to userspace, then |
611 | # check, if we are in SIE, if yes leave it | ||
612 | # | ||
613 | io_work: | ||
614 | tm SP_PSW+1(%r15),0x01 # returning to user ? | ||
615 | #ifndef CONFIG_PREEMPT | ||
616 | #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) | ||
617 | jnz io_work_user # yes -> no need to check for SIE | ||
618 | la %r1, BASED(sie_opcode) # we return to kernel here | ||
619 | lg %r2, SP_PSW+8(%r15) | ||
620 | clc 0(2,%r1), 0(%r2) # is current instruction = SIE? | ||
621 | jne io_restore # no-> return to kernel | ||
622 | lg %r1, SP_PSW+8(%r15) # yes-> add 4 bytes to leave SIE | ||
623 | aghi %r1, 4 | ||
624 | stg %r1, SP_PSW+8(%r15) | ||
625 | j io_restore # return to kernel | ||
626 | #else | ||
627 | jno io_restore # no-> skip resched & signal | ||
628 | #endif | ||
629 | #else | ||
630 | jnz io_work_user # yes -> do resched & signal | ||
631 | #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) | ||
632 | la %r1, BASED(sie_opcode) | ||
633 | lg %r2, SP_PSW+8(%r15) | ||
634 | clc 0(2,%r1), 0(%r2) # is current instruction = SIE? | ||
635 | jne 0f # no -> leave PSW alone | ||
636 | lg %r1, SP_PSW+8(%r15) # yes-> add 4 bytes to leave SIE | ||
637 | aghi %r1, 4 | ||
638 | stg %r1, SP_PSW+8(%r15) | ||
639 | 0: | ||
640 | #endif | ||
641 | # check for preemptive scheduling | ||
617 | icm %r0,15,__TI_precount(%r9) | 642 | icm %r0,15,__TI_precount(%r9) |
618 | jnz io_restore | 643 | jnz io_restore # preemption is disabled |
619 | # switch to kernel stack | 644 | # switch to kernel stack |
620 | lg %r1,SP_R15(%r15) | 645 | lg %r1,SP_R15(%r15) |
621 | aghi %r1,-SP_SIZE | 646 | aghi %r1,-SP_SIZE |
@@ -629,10 +654,7 @@ io_resume_loop: | |||
629 | jg preempt_schedule_irq | 654 | jg preempt_schedule_irq |
630 | #endif | 655 | #endif |
631 | 656 | ||
632 | # | 657 | io_work_user: |
633 | # switch to kernel stack, then check TIF bits | ||
634 | # | ||
635 | io_work: | ||
636 | lg %r1,__LC_KERNEL_STACK | 658 | lg %r1,__LC_KERNEL_STACK |
637 | aghi %r1,-SP_SIZE | 659 | aghi %r1,-SP_SIZE |
638 | mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) | 660 | mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) |
@@ -653,6 +675,11 @@ io_work_loop: | |||
653 | j io_restore | 675 | j io_restore |
654 | io_work_done: | 676 | io_work_done: |
655 | 677 | ||
678 | #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) | ||
679 | sie_opcode: | ||
680 | .long 0xb2140000 | ||
681 | #endif | ||
682 | |||
656 | # | 683 | # |
657 | # _TIF_MCCK_PENDING is set, call handler | 684 | # _TIF_MCCK_PENDING is set, call handler |
658 | # | 685 | # |