diff options
Diffstat (limited to 'arch/s390/kernel/entry64.S')
-rw-r--r-- | arch/s390/kernel/entry64.S | 117 |
1 files changed, 88 insertions, 29 deletions
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index d9f22915008c..fb77b72ab262 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
@@ -131,14 +131,14 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING) | |||
131 | stg %r12,__SF_BACKCHAIN(%r15) | 131 | stg %r12,__SF_BACKCHAIN(%r15) |
132 | .endm | 132 | .endm |
133 | 133 | ||
134 | .macro RESTORE_ALL sync | 134 | .macro RESTORE_ALL psworg,sync |
135 | mvc __LC_RETURN_PSW(16),SP_PSW(%r15) # move user PSW to lowcore | 135 | mvc \psworg(16),SP_PSW(%r15) # move user PSW to lowcore |
136 | .if !\sync | 136 | .if !\sync |
137 | ni __LC_RETURN_PSW+1,0xfd # clear wait state bit | 137 | ni \psworg+1,0xfd # clear wait state bit |
138 | .endif | 138 | .endif |
139 | lmg %r0,%r15,SP_R0(%r15) # load gprs 0-15 of user | 139 | lmg %r0,%r15,SP_R0(%r15) # load gprs 0-15 of user |
140 | STORE_TIMER __LC_EXIT_TIMER | 140 | STORE_TIMER __LC_EXIT_TIMER |
141 | lpswe __LC_RETURN_PSW # back to caller | 141 | lpswe \psworg # back to caller |
142 | .endm | 142 | .endm |
143 | 143 | ||
144 | /* | 144 | /* |
@@ -214,8 +214,8 @@ sysc_nr_ok: | |||
214 | sysc_do_restart: | 214 | sysc_do_restart: |
215 | larl %r10,sys_call_table | 215 | larl %r10,sys_call_table |
216 | #ifdef CONFIG_S390_SUPPORT | 216 | #ifdef CONFIG_S390_SUPPORT |
217 | tm SP_PSW+3(%r15),0x01 # are we running in 31 bit mode ? | 217 | tm __TI_flags+5(%r9),(_TIF_31BIT>>16) # running in 31 bit mode ? |
218 | jo sysc_noemu | 218 | jno sysc_noemu |
219 | larl %r10,sys_call_table_emu # use 31 bit emulation system calls | 219 | larl %r10,sys_call_table_emu # use 31 bit emulation system calls |
220 | sysc_noemu: | 220 | sysc_noemu: |
221 | #endif | 221 | #endif |
@@ -233,7 +233,7 @@ sysc_return: | |||
233 | tm __TI_flags+7(%r9),_TIF_WORK_SVC | 233 | tm __TI_flags+7(%r9),_TIF_WORK_SVC |
234 | jnz sysc_work # there is work to do (signals etc.) | 234 | jnz sysc_work # there is work to do (signals etc.) |
235 | sysc_leave: | 235 | sysc_leave: |
236 | RESTORE_ALL 1 | 236 | RESTORE_ALL __LC_RETURN_PSW,1 |
237 | 237 | ||
238 | # | 238 | # |
239 | # recheck if there is more work to do | 239 | # recheck if there is more work to do |
@@ -308,8 +308,6 @@ sysc_singlestep: | |||
308 | jg do_single_step # branch to do_sigtrap | 308 | jg do_single_step # branch to do_sigtrap |
309 | 309 | ||
310 | 310 | ||
311 | __critical_end: | ||
312 | |||
313 | # | 311 | # |
314 | # call syscall_trace before and after system call | 312 | # call syscall_trace before and after system call |
315 | # special linkage: %r12 contains the return address for trace_svc | 313 | # special linkage: %r12 contains the return address for trace_svc |
@@ -612,7 +610,8 @@ io_return: | |||
612 | tm __TI_flags+7(%r9),_TIF_WORK_INT | 610 | tm __TI_flags+7(%r9),_TIF_WORK_INT |
613 | jnz io_work # there is work to do (signals etc.) | 611 | jnz io_work # there is work to do (signals etc.) |
614 | io_leave: | 612 | io_leave: |
615 | RESTORE_ALL 0 | 613 | RESTORE_ALL __LC_RETURN_PSW,0 |
614 | io_done: | ||
616 | 615 | ||
617 | #ifdef CONFIG_PREEMPT | 616 | #ifdef CONFIG_PREEMPT |
618 | io_preempt: | 617 | io_preempt: |
@@ -711,6 +710,8 @@ ext_no_vtime: | |||
711 | brasl %r14,do_extint | 710 | brasl %r14,do_extint |
712 | j io_return | 711 | j io_return |
713 | 712 | ||
713 | __critical_end: | ||
714 | |||
714 | /* | 715 | /* |
715 | * Machine check handler routines | 716 | * Machine check handler routines |
716 | */ | 717 | */ |
@@ -718,6 +719,7 @@ ext_no_vtime: | |||
718 | mcck_int_handler: | 719 | mcck_int_handler: |
719 | la %r1,4095 # revalidate r1 | 720 | la %r1,4095 # revalidate r1 |
720 | spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer | 721 | spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer |
722 | mvc __LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA-4095(%r1) | ||
721 | lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs | 723 | lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs |
722 | SAVE_ALL_BASE __LC_SAVE_AREA+64 | 724 | SAVE_ALL_BASE __LC_SAVE_AREA+64 |
723 | la %r12,__LC_MCK_OLD_PSW | 725 | la %r12,__LC_MCK_OLD_PSW |
@@ -730,17 +732,8 @@ mcck_int_handler: | |||
730 | mvc __LC_ASYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER | 732 | mvc __LC_ASYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER |
731 | mvc __LC_SYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER | 733 | mvc __LC_SYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER |
732 | mvc __LC_EXIT_TIMER(8),__LC_LAST_UPDATE_TIMER | 734 | mvc __LC_EXIT_TIMER(8),__LC_LAST_UPDATE_TIMER |
733 | 0: tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid? | ||
734 | jno mcck_no_vtime # no -> no timer update | ||
735 | tm __LC_MCK_OLD_PSW+1,0x01 # interrupting from user ? | ||
736 | jz mcck_no_vtime | ||
737 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER | ||
738 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | ||
739 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER | ||
740 | mcck_no_vtime: | ||
741 | #endif | 735 | #endif |
742 | 0: | 736 | 0: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? |
743 | tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? | ||
744 | jno mcck_int_main # no -> skip cleanup critical | 737 | jno mcck_int_main # no -> skip cleanup critical |
745 | tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit | 738 | tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit |
746 | jnz mcck_int_main # from user -> load kernel stack | 739 | jnz mcck_int_main # from user -> load kernel stack |
@@ -756,6 +749,16 @@ mcck_int_main: | |||
756 | jz 0f | 749 | jz 0f |
757 | lg %r15,__LC_PANIC_STACK # load panic stack | 750 | lg %r15,__LC_PANIC_STACK # load panic stack |
758 | 0: CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+64 | 751 | 0: CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+64 |
752 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
753 | tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid? | ||
754 | jno mcck_no_vtime # no -> no timer update | ||
755 | tm __LC_MCK_OLD_PSW+1,0x01 # interrupting from user ? | ||
756 | jz mcck_no_vtime | ||
757 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER | ||
758 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | ||
759 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER | ||
760 | mcck_no_vtime: | ||
761 | #endif | ||
759 | lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct | 762 | lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct |
760 | la %r2,SP_PTREGS(%r15) # load pt_regs | 763 | la %r2,SP_PTREGS(%r15) # load pt_regs |
761 | brasl %r14,s390_do_machine_check | 764 | brasl %r14,s390_do_machine_check |
@@ -771,7 +774,7 @@ mcck_int_main: | |||
771 | jno mcck_return | 774 | jno mcck_return |
772 | brasl %r14,s390_handle_mcck | 775 | brasl %r14,s390_handle_mcck |
773 | mcck_return: | 776 | mcck_return: |
774 | RESTORE_ALL 0 | 777 | RESTORE_ALL __LC_RETURN_MCCK_PSW,0 |
775 | 778 | ||
776 | #ifdef CONFIG_SMP | 779 | #ifdef CONFIG_SMP |
777 | /* | 780 | /* |
@@ -833,6 +836,10 @@ cleanup_table_sysc_leave: | |||
833 | .quad sysc_leave, sysc_work_loop | 836 | .quad sysc_leave, sysc_work_loop |
834 | cleanup_table_sysc_work_loop: | 837 | cleanup_table_sysc_work_loop: |
835 | .quad sysc_work_loop, sysc_reschedule | 838 | .quad sysc_work_loop, sysc_reschedule |
839 | cleanup_table_io_leave: | ||
840 | .quad io_leave, io_done | ||
841 | cleanup_table_io_work_loop: | ||
842 | .quad io_work_loop, io_mcck_pending | ||
836 | 843 | ||
837 | cleanup_critical: | 844 | cleanup_critical: |
838 | clc 8(8,%r12),BASED(cleanup_table_system_call) | 845 | clc 8(8,%r12),BASED(cleanup_table_system_call) |
@@ -855,10 +862,26 @@ cleanup_critical: | |||
855 | clc 8(8,%r12),BASED(cleanup_table_sysc_work_loop+8) | 862 | clc 8(8,%r12),BASED(cleanup_table_sysc_work_loop+8) |
856 | jl cleanup_sysc_return | 863 | jl cleanup_sysc_return |
857 | 0: | 864 | 0: |
865 | clc 8(8,%r12),BASED(cleanup_table_io_leave) | ||
866 | jl 0f | ||
867 | clc 8(8,%r12),BASED(cleanup_table_io_leave+8) | ||
868 | jl cleanup_io_leave | ||
869 | 0: | ||
870 | clc 8(8,%r12),BASED(cleanup_table_io_work_loop) | ||
871 | jl 0f | ||
872 | clc 8(8,%r12),BASED(cleanup_table_io_work_loop+8) | ||
873 | jl cleanup_io_return | ||
874 | 0: | ||
858 | br %r14 | 875 | br %r14 |
859 | 876 | ||
860 | cleanup_system_call: | 877 | cleanup_system_call: |
861 | mvc __LC_RETURN_PSW(16),0(%r12) | 878 | mvc __LC_RETURN_PSW(16),0(%r12) |
879 | cghi %r12,__LC_MCK_OLD_PSW | ||
880 | je 0f | ||
881 | la %r12,__LC_SAVE_AREA+32 | ||
882 | j 1f | ||
883 | 0: la %r12,__LC_SAVE_AREA+64 | ||
884 | 1: | ||
862 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 885 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
863 | clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+8) | 886 | clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+8) |
864 | jh 0f | 887 | jh 0f |
@@ -868,11 +891,13 @@ cleanup_system_call: | |||
868 | #endif | 891 | #endif |
869 | clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn) | 892 | clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn) |
870 | jh 0f | 893 | jh 0f |
871 | mvc __LC_SAVE_AREA(32),__LC_SAVE_AREA+32 | 894 | mvc __LC_SAVE_AREA(32),0(%r12) |
872 | 0: stg %r13,__LC_SAVE_AREA+40 | 895 | 0: stg %r13,8(%r12) |
896 | stg %r12,__LC_SAVE_AREA+96 # argh | ||
873 | SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 | 897 | SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 |
874 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 898 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA |
875 | stg %r15,__LC_SAVE_AREA+56 | 899 | lg %r12,__LC_SAVE_AREA+96 # argh |
900 | stg %r15,24(%r12) | ||
876 | llgh %r7,__LC_SVC_INT_CODE | 901 | llgh %r7,__LC_SVC_INT_CODE |
877 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 902 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
878 | cleanup_vtime: | 903 | cleanup_vtime: |
@@ -909,17 +934,21 @@ cleanup_sysc_return: | |||
909 | 934 | ||
910 | cleanup_sysc_leave: | 935 | cleanup_sysc_leave: |
911 | clc 8(8,%r12),BASED(cleanup_sysc_leave_insn) | 936 | clc 8(8,%r12),BASED(cleanup_sysc_leave_insn) |
912 | je 0f | 937 | je 2f |
913 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 938 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
914 | mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER | 939 | mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER |
915 | clc 8(8,%r12),BASED(cleanup_sysc_leave_insn+8) | 940 | clc 8(8,%r12),BASED(cleanup_sysc_leave_insn+8) |
916 | je 0f | 941 | je 2f |
917 | #endif | 942 | #endif |
918 | mvc __LC_RETURN_PSW(16),SP_PSW(%r15) | 943 | mvc __LC_RETURN_PSW(16),SP_PSW(%r15) |
919 | mvc __LC_SAVE_AREA+32(32),SP_R12(%r15) | 944 | cghi %r12,__LC_MCK_OLD_PSW |
920 | lmg %r0,%r11,SP_R0(%r15) | 945 | jne 0f |
946 | mvc __LC_SAVE_AREA+64(32),SP_R12(%r15) | ||
947 | j 1f | ||
948 | 0: mvc __LC_SAVE_AREA+32(32),SP_R12(%r15) | ||
949 | 1: lmg %r0,%r11,SP_R0(%r15) | ||
921 | lg %r15,SP_R15(%r15) | 950 | lg %r15,SP_R15(%r15) |
922 | 0: la %r12,__LC_RETURN_PSW | 951 | 2: la %r12,__LC_RETURN_PSW |
923 | br %r14 | 952 | br %r14 |
924 | cleanup_sysc_leave_insn: | 953 | cleanup_sysc_leave_insn: |
925 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 954 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
@@ -927,6 +956,36 @@ cleanup_sysc_leave_insn: | |||
927 | #endif | 956 | #endif |
928 | .quad sysc_leave + 12 | 957 | .quad sysc_leave + 12 |
929 | 958 | ||
959 | cleanup_io_return: | ||
960 | mvc __LC_RETURN_PSW(8),0(%r12) | ||
961 | mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_io_work_loop) | ||
962 | la %r12,__LC_RETURN_PSW | ||
963 | br %r14 | ||
964 | |||
965 | cleanup_io_leave: | ||
966 | clc 8(8,%r12),BASED(cleanup_io_leave_insn) | ||
967 | je 2f | ||
968 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
969 | mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER | ||
970 | clc 8(8,%r12),BASED(cleanup_io_leave_insn+8) | ||
971 | je 2f | ||
972 | #endif | ||
973 | mvc __LC_RETURN_PSW(16),SP_PSW(%r15) | ||
974 | cghi %r12,__LC_MCK_OLD_PSW | ||
975 | jne 0f | ||
976 | mvc __LC_SAVE_AREA+64(32),SP_R12(%r15) | ||
977 | j 1f | ||
978 | 0: mvc __LC_SAVE_AREA+32(32),SP_R12(%r15) | ||
979 | 1: lmg %r0,%r11,SP_R0(%r15) | ||
980 | lg %r15,SP_R15(%r15) | ||
981 | 2: la %r12,__LC_RETURN_PSW | ||
982 | br %r14 | ||
983 | cleanup_io_leave_insn: | ||
984 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
985 | .quad io_leave + 20 | ||
986 | #endif | ||
987 | .quad io_leave + 16 | ||
988 | |||
930 | /* | 989 | /* |
931 | * Integer constants | 990 | * Integer constants |
932 | */ | 991 | */ |