diff options
Diffstat (limited to 'arch/s390/kernel/entry64.S')
-rw-r--r-- | arch/s390/kernel/entry64.S | 139 |
1 files changed, 80 insertions, 59 deletions
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 412a7b8783d7..4e1c292fa7e3 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
@@ -2,7 +2,7 @@ | |||
2 | * arch/s390/kernel/entry64.S | 2 | * arch/s390/kernel/entry64.S |
3 | * S390 low-level entry points. | 3 | * S390 low-level entry points. |
4 | * | 4 | * |
5 | * Copyright (C) IBM Corp. 1999,2010 | 5 | * Copyright (C) IBM Corp. 1999,2012 |
6 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), | 6 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), |
7 | * Hartmut Penner (hp@de.ibm.com), | 7 | * Hartmut Penner (hp@de.ibm.com), |
8 | * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), | 8 | * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), |
@@ -489,7 +489,6 @@ io_restore: | |||
489 | lg %r14,__LC_VDSO_PER_CPU | 489 | lg %r14,__LC_VDSO_PER_CPU |
490 | lmg %r0,%r10,__PT_R0(%r11) | 490 | lmg %r0,%r10,__PT_R0(%r11) |
491 | mvc __LC_RETURN_PSW(16),__PT_PSW(%r11) | 491 | mvc __LC_RETURN_PSW(16),__PT_PSW(%r11) |
492 | ni __LC_RETURN_PSW+1,0xfd # clear wait state bit | ||
493 | stpt __LC_EXIT_TIMER | 492 | stpt __LC_EXIT_TIMER |
494 | mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER | 493 | mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER |
495 | lmg %r11,%r15,__PT_R11(%r11) | 494 | lmg %r11,%r15,__PT_R11(%r11) |
@@ -625,12 +624,30 @@ ext_skip: | |||
625 | TRACE_IRQS_OFF | 624 | TRACE_IRQS_OFF |
626 | lghi %r1,4096 | 625 | lghi %r1,4096 |
627 | lgr %r2,%r11 # pass pointer to pt_regs | 626 | lgr %r2,%r11 # pass pointer to pt_regs |
628 | llgf %r3,__LC_CPU_ADDRESS # get cpu address + interruption code | 627 | llgf %r3,__LC_EXT_CPU_ADDR # get cpu address + interruption code |
629 | llgf %r4,__LC_EXT_PARAMS # get external parameter | 628 | llgf %r4,__LC_EXT_PARAMS # get external parameter |
630 | lg %r5,__LC_EXT_PARAMS2-4096(%r1) # get 64 bit external parameter | 629 | lg %r5,__LC_EXT_PARAMS2-4096(%r1) # get 64 bit external parameter |
631 | brasl %r14,do_extint | 630 | brasl %r14,do_extint |
632 | j io_return | 631 | j io_return |
633 | 632 | ||
633 | /* | ||
634 | * Load idle PSW. The second "half" of this function is in cleanup_idle. | ||
635 | */ | ||
636 | ENTRY(psw_idle) | ||
637 | stg %r4,__SF_EMPTY(%r15) | ||
638 | larl %r1,psw_idle_lpsw+4 | ||
639 | stg %r1,__SF_EMPTY+8(%r15) | ||
640 | larl %r1,.Lvtimer_max | ||
641 | stck __IDLE_ENTER(%r2) | ||
642 | ltr %r5,%r5 | ||
643 | stpt __VQ_IDLE_ENTER(%r3) | ||
644 | jz psw_idle_lpsw | ||
645 | spt 0(%r1) | ||
646 | psw_idle_lpsw: | ||
647 | lpswe __SF_EMPTY(%r15) | ||
648 | br %r14 | ||
649 | psw_idle_end: | ||
650 | |||
634 | __critical_end: | 651 | __critical_end: |
635 | 652 | ||
636 | /* | 653 | /* |
@@ -696,7 +713,6 @@ mcck_return: | |||
696 | lg %r14,__LC_VDSO_PER_CPU | 713 | lg %r14,__LC_VDSO_PER_CPU |
697 | lmg %r0,%r10,__PT_R0(%r11) | 714 | lmg %r0,%r10,__PT_R0(%r11) |
698 | mvc __LC_RETURN_MCCK_PSW(16),__PT_PSW(%r11) # move return PSW | 715 | mvc __LC_RETURN_MCCK_PSW(16),__PT_PSW(%r11) # move return PSW |
699 | ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit | ||
700 | tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ? | 716 | tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ? |
701 | jno 0f | 717 | jno 0f |
702 | stpt __LC_EXIT_TIMER | 718 | stpt __LC_EXIT_TIMER |
@@ -713,68 +729,30 @@ mcck_panic: | |||
713 | 0: aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) | 729 | 0: aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) |
714 | j mcck_skip | 730 | j mcck_skip |
715 | 731 | ||
716 | /* | ||
717 | * Restart interruption handler, kick starter for additional CPUs | ||
718 | */ | ||
719 | #ifdef CONFIG_SMP | ||
720 | __CPUINIT | ||
721 | ENTRY(restart_int_handler) | ||
722 | basr %r1,0 | ||
723 | restart_base: | ||
724 | spt restart_vtime-restart_base(%r1) | ||
725 | stck __LC_LAST_UPDATE_CLOCK | ||
726 | mvc __LC_LAST_UPDATE_TIMER(8),restart_vtime-restart_base(%r1) | ||
727 | mvc __LC_EXIT_TIMER(8),restart_vtime-restart_base(%r1) | ||
728 | lghi %r10,__LC_GPREGS_SAVE_AREA | ||
729 | lg %r15,120(%r10) # load ksp | ||
730 | lghi %r10,__LC_CREGS_SAVE_AREA | ||
731 | lctlg %c0,%c15,0(%r10) # get new ctl regs | ||
732 | lghi %r10,__LC_AREGS_SAVE_AREA | ||
733 | lam %a0,%a15,0(%r10) | ||
734 | lmg %r6,%r15,__SF_GPRS(%r15)# load registers from clone | ||
735 | lg %r1,__LC_THREAD_INFO | ||
736 | mvc __LC_USER_TIMER(8),__TI_user_timer(%r1) | ||
737 | mvc __LC_SYSTEM_TIMER(8),__TI_system_timer(%r1) | ||
738 | xc __LC_STEAL_TIMER(8),__LC_STEAL_TIMER | ||
739 | ssm __LC_PGM_NEW_PSW # turn dat on, keep irqs off | ||
740 | brasl %r14,start_secondary | ||
741 | .align 8 | ||
742 | restart_vtime: | ||
743 | .long 0x7fffffff,0xffffffff | ||
744 | .previous | ||
745 | #else | ||
746 | /* | ||
747 | * If we do not run with SMP enabled, let the new CPU crash ... | ||
748 | */ | ||
749 | ENTRY(restart_int_handler) | ||
750 | basr %r1,0 | ||
751 | restart_base: | ||
752 | lpswe restart_crash-restart_base(%r1) | ||
753 | .align 8 | ||
754 | restart_crash: | ||
755 | .long 0x000a0000,0x00000000,0x00000000,0x00000000 | ||
756 | restart_go: | ||
757 | #endif | ||
758 | |||
759 | # | 732 | # |
760 | # PSW restart interrupt handler | 733 | # PSW restart interrupt handler |
761 | # | 734 | # |
762 | ENTRY(psw_restart_int_handler) | 735 | ENTRY(restart_int_handler) |
763 | stg %r15,__LC_SAVE_AREA_RESTART | 736 | stg %r15,__LC_SAVE_AREA_RESTART |
764 | larl %r15,restart_stack # load restart stack | 737 | lg %r15,__LC_RESTART_STACK |
765 | lg %r15,0(%r15) | ||
766 | aghi %r15,-__PT_SIZE # create pt_regs on stack | 738 | aghi %r15,-__PT_SIZE # create pt_regs on stack |
739 | xc 0(__PT_SIZE,%r15),0(%r15) | ||
767 | stmg %r0,%r14,__PT_R0(%r15) | 740 | stmg %r0,%r14,__PT_R0(%r15) |
768 | mvc __PT_R15(8,%r15),__LC_SAVE_AREA_RESTART | 741 | mvc __PT_R15(8,%r15),__LC_SAVE_AREA_RESTART |
769 | mvc __PT_PSW(16,%r15),__LC_RST_OLD_PSW # store restart old psw | 742 | mvc __PT_PSW(16,%r15),__LC_RST_OLD_PSW # store restart old psw |
770 | aghi %r15,-STACK_FRAME_OVERHEAD | 743 | aghi %r15,-STACK_FRAME_OVERHEAD # create stack frame on stack |
771 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) | 744 | xc 0(STACK_FRAME_OVERHEAD,%r15),0(%r15) |
772 | brasl %r14,do_restart | 745 | lmg %r1,%r3,__LC_RESTART_FN # load fn, parm & source cpu |
773 | larl %r14,restart_psw_crash # load disabled wait PSW if | 746 | ltgr %r3,%r3 # test source cpu address |
774 | lpswe 0(%r14) # do_restart returns | 747 | jm 1f # negative -> skip source stop |
775 | .align 8 | 748 | 0: sigp %r4,%r3,1 # sigp sense to source cpu |
776 | restart_psw_crash: | 749 | brc 10,0b # wait for status stored |
777 | .quad 0x0002000080000000,0x0000000000000000 + restart_psw_crash | 750 | 1: basr %r14,%r1 # call function |
751 | stap __SF_EMPTY(%r15) # store cpu address | ||
752 | llgh %r3,__SF_EMPTY(%r15) | ||
753 | 2: sigp %r4,%r3,5 # sigp stop to current cpu | ||
754 | brc 2,2b | ||
755 | 3: j 3b | ||
778 | 756 | ||
779 | .section .kprobes.text, "ax" | 757 | .section .kprobes.text, "ax" |
780 | 758 | ||
@@ -808,6 +786,8 @@ cleanup_table: | |||
808 | .quad io_tif | 786 | .quad io_tif |
809 | .quad io_restore | 787 | .quad io_restore |
810 | .quad io_done | 788 | .quad io_done |
789 | .quad psw_idle | ||
790 | .quad psw_idle_end | ||
811 | 791 | ||
812 | cleanup_critical: | 792 | cleanup_critical: |
813 | clg %r9,BASED(cleanup_table) # system_call | 793 | clg %r9,BASED(cleanup_table) # system_call |
@@ -826,6 +806,10 @@ cleanup_critical: | |||
826 | jl cleanup_io_tif | 806 | jl cleanup_io_tif |
827 | clg %r9,BASED(cleanup_table+56) # io_done | 807 | clg %r9,BASED(cleanup_table+56) # io_done |
828 | jl cleanup_io_restore | 808 | jl cleanup_io_restore |
809 | clg %r9,BASED(cleanup_table+64) # psw_idle | ||
810 | jl 0f | ||
811 | clg %r9,BASED(cleanup_table+72) # psw_idle_end | ||
812 | jl cleanup_idle | ||
829 | 0: br %r14 | 813 | 0: br %r14 |
830 | 814 | ||
831 | 815 | ||
@@ -915,7 +899,6 @@ cleanup_io_restore: | |||
915 | je 0f | 899 | je 0f |
916 | lg %r9,24(%r11) # get saved r11 pointer to pt_regs | 900 | lg %r9,24(%r11) # get saved r11 pointer to pt_regs |
917 | mvc __LC_RETURN_PSW(16),__PT_PSW(%r9) | 901 | mvc __LC_RETURN_PSW(16),__PT_PSW(%r9) |
918 | ni __LC_RETURN_PSW+1,0xfd # clear wait state bit | ||
919 | mvc 0(64,%r11),__PT_R8(%r9) | 902 | mvc 0(64,%r11),__PT_R8(%r9) |
920 | lmg %r0,%r7,__PT_R0(%r9) | 903 | lmg %r0,%r7,__PT_R0(%r9) |
921 | 0: lmg %r8,%r9,__LC_RETURN_PSW | 904 | 0: lmg %r8,%r9,__LC_RETURN_PSW |
@@ -923,6 +906,42 @@ cleanup_io_restore: | |||
923 | cleanup_io_restore_insn: | 906 | cleanup_io_restore_insn: |
924 | .quad io_done - 4 | 907 | .quad io_done - 4 |
925 | 908 | ||
909 | cleanup_idle: | ||
910 | # copy interrupt clock & cpu timer | ||
911 | mvc __IDLE_EXIT(8,%r2),__LC_INT_CLOCK | ||
912 | mvc __VQ_IDLE_EXIT(8,%r3),__LC_ASYNC_ENTER_TIMER | ||
913 | cghi %r11,__LC_SAVE_AREA_ASYNC | ||
914 | je 0f | ||
915 | mvc __IDLE_EXIT(8,%r2),__LC_MCCK_CLOCK | ||
916 | mvc __VQ_IDLE_EXIT(8,%r3),__LC_MCCK_ENTER_TIMER | ||
917 | 0: # check if stck & stpt have been executed | ||
918 | clg %r9,BASED(cleanup_idle_insn) | ||
919 | jhe 1f | ||
920 | mvc __IDLE_ENTER(8,%r2),__IDLE_EXIT(%r2) | ||
921 | mvc __VQ_IDLE_ENTER(8,%r3),__VQ_IDLE_EXIT(%r3) | ||
922 | j 2f | ||
923 | 1: # check if the cpu timer has been reprogrammed | ||
924 | ltr %r5,%r5 | ||
925 | jz 2f | ||
926 | spt __VQ_IDLE_ENTER(%r3) | ||
927 | 2: # account system time going idle | ||
928 | lg %r9,__LC_STEAL_TIMER | ||
929 | alg %r9,__IDLE_ENTER(%r2) | ||
930 | slg %r9,__LC_LAST_UPDATE_CLOCK | ||
931 | stg %r9,__LC_STEAL_TIMER | ||
932 | mvc __LC_LAST_UPDATE_CLOCK(8),__IDLE_EXIT(%r2) | ||
933 | lg %r9,__LC_SYSTEM_TIMER | ||
934 | alg %r9,__LC_LAST_UPDATE_TIMER | ||
935 | slg %r9,__VQ_IDLE_ENTER(%r3) | ||
936 | stg %r9,__LC_SYSTEM_TIMER | ||
937 | mvc __LC_LAST_UPDATE_TIMER(8),__VQ_IDLE_EXIT(%r3) | ||
938 | # prepare return psw | ||
939 | nihh %r8,0xfffd # clear wait state bit | ||
940 | lg %r9,48(%r11) # return from psw_idle | ||
941 | br %r14 | ||
942 | cleanup_idle_insn: | ||
943 | .quad psw_idle_lpsw | ||
944 | |||
926 | /* | 945 | /* |
927 | * Integer constants | 946 | * Integer constants |
928 | */ | 947 | */ |
@@ -931,6 +950,8 @@ cleanup_io_restore_insn: | |||
931 | .quad __critical_start | 950 | .quad __critical_start |
932 | .Lcritical_length: | 951 | .Lcritical_length: |
933 | .quad __critical_end - __critical_start | 952 | .quad __critical_end - __critical_start |
953 | .Lvtimer_max: | ||
954 | .quad 0x7fffffffffffffff | ||
934 | 955 | ||
935 | 956 | ||
936 | #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) | 957 | #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) |