diff options
Diffstat (limited to 'arch/s390/kernel/entry.S')
-rw-r--r-- | arch/s390/kernel/entry.S | 116 |
1 files changed, 88 insertions, 28 deletions
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 1a271b16cb5c..cbe7d6a2d02c 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S | |||
@@ -138,14 +138,14 @@ STACK_SIZE = 1 << STACK_SHIFT | |||
138 | st %r12,__SF_BACKCHAIN(%r15) # clear back chain | 138 | st %r12,__SF_BACKCHAIN(%r15) # clear back chain |
139 | .endm | 139 | .endm |
140 | 140 | ||
141 | .macro RESTORE_ALL sync | 141 | .macro RESTORE_ALL psworg,sync |
142 | mvc __LC_RETURN_PSW(8),SP_PSW(%r15) # move user PSW to lowcore | 142 | mvc \psworg(8),SP_PSW(%r15) # move user PSW to lowcore |
143 | .if !\sync | 143 | .if !\sync |
144 | ni __LC_RETURN_PSW+1,0xfd # clear wait state bit | 144 | ni \psworg+1,0xfd # clear wait state bit |
145 | .endif | 145 | .endif |
146 | lm %r0,%r15,SP_R0(%r15) # load gprs 0-15 of user | 146 | lm %r0,%r15,SP_R0(%r15) # load gprs 0-15 of user |
147 | STORE_TIMER __LC_EXIT_TIMER | 147 | STORE_TIMER __LC_EXIT_TIMER |
148 | lpsw __LC_RETURN_PSW # back to caller | 148 | lpsw \psworg # back to caller |
149 | .endm | 149 | .endm |
150 | 150 | ||
151 | /* | 151 | /* |
@@ -235,7 +235,7 @@ sysc_return: | |||
235 | tm __TI_flags+3(%r9),_TIF_WORK_SVC | 235 | tm __TI_flags+3(%r9),_TIF_WORK_SVC |
236 | bnz BASED(sysc_work) # there is work to do (signals etc.) | 236 | bnz BASED(sysc_work) # there is work to do (signals etc.) |
237 | sysc_leave: | 237 | sysc_leave: |
238 | RESTORE_ALL 1 | 238 | RESTORE_ALL __LC_RETURN_PSW,1 |
239 | 239 | ||
240 | # | 240 | # |
241 | # recheck if there is more work to do | 241 | # recheck if there is more work to do |
@@ -312,8 +312,6 @@ sysc_singlestep: | |||
312 | la %r14,BASED(sysc_return) # load adr. of system return | 312 | la %r14,BASED(sysc_return) # load adr. of system return |
313 | br %r1 # branch to do_single_step | 313 | br %r1 # branch to do_single_step |
314 | 314 | ||
315 | __critical_end: | ||
316 | |||
317 | # | 315 | # |
318 | # call trace before and after sys_call | 316 | # call trace before and after sys_call |
319 | # | 317 | # |
@@ -571,7 +569,8 @@ io_return: | |||
571 | tm __TI_flags+3(%r9),_TIF_WORK_INT | 569 | tm __TI_flags+3(%r9),_TIF_WORK_INT |
572 | bnz BASED(io_work) # there is work to do (signals etc.) | 570 | bnz BASED(io_work) # there is work to do (signals etc.) |
573 | io_leave: | 571 | io_leave: |
574 | RESTORE_ALL 0 | 572 | RESTORE_ALL __LC_RETURN_PSW,0 |
573 | io_done: | ||
575 | 574 | ||
576 | #ifdef CONFIG_PREEMPT | 575 | #ifdef CONFIG_PREEMPT |
577 | io_preempt: | 576 | io_preempt: |
@@ -621,7 +620,7 @@ io_work_loop: | |||
621 | # | 620 | # |
622 | io_mcck_pending: | 621 | io_mcck_pending: |
623 | l %r1,BASED(.Ls390_handle_mcck) | 622 | l %r1,BASED(.Ls390_handle_mcck) |
624 | l %r14,BASED(io_work_loop) | 623 | la %r14,BASED(io_work_loop) |
625 | br %r1 # TIF bit will be cleared by handler | 624 | br %r1 # TIF bit will be cleared by handler |
626 | 625 | ||
627 | # | 626 | # |
@@ -674,6 +673,8 @@ ext_no_vtime: | |||
674 | basr %r14,%r1 | 673 | basr %r14,%r1 |
675 | b BASED(io_return) | 674 | b BASED(io_return) |
676 | 675 | ||
676 | __critical_end: | ||
677 | |||
677 | /* | 678 | /* |
678 | * Machine check handler routines | 679 | * Machine check handler routines |
679 | */ | 680 | */ |
@@ -681,6 +682,7 @@ ext_no_vtime: | |||
681 | .globl mcck_int_handler | 682 | .globl mcck_int_handler |
682 | mcck_int_handler: | 683 | mcck_int_handler: |
683 | spt __LC_CPU_TIMER_SAVE_AREA # revalidate cpu timer | 684 | spt __LC_CPU_TIMER_SAVE_AREA # revalidate cpu timer |
685 | mvc __LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA | ||
684 | lm %r0,%r15,__LC_GPREGS_SAVE_AREA # revalidate gprs | 686 | lm %r0,%r15,__LC_GPREGS_SAVE_AREA # revalidate gprs |
685 | SAVE_ALL_BASE __LC_SAVE_AREA+32 | 687 | SAVE_ALL_BASE __LC_SAVE_AREA+32 |
686 | la %r12,__LC_MCK_OLD_PSW | 688 | la %r12,__LC_MCK_OLD_PSW |
@@ -693,17 +695,8 @@ mcck_int_handler: | |||
693 | mvc __LC_ASYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER | 695 | mvc __LC_ASYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER |
694 | mvc __LC_SYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER | 696 | mvc __LC_SYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER |
695 | mvc __LC_EXIT_TIMER(8),__LC_LAST_UPDATE_TIMER | 697 | mvc __LC_EXIT_TIMER(8),__LC_LAST_UPDATE_TIMER |
696 | 0: tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid? | ||
697 | bno BASED(mcck_no_vtime) # no -> skip cleanup critical | ||
698 | tm __LC_MCK_OLD_PSW+1,0x01 # interrupting from user ? | ||
699 | bz BASED(mcck_no_vtime) | ||
700 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER | ||
701 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | ||
702 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER | ||
703 | mcck_no_vtime: | ||
704 | #endif | 698 | #endif |
705 | 0: | 699 | 0: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? |
706 | tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? | ||
707 | bno BASED(mcck_int_main) # no -> skip cleanup critical | 700 | bno BASED(mcck_int_main) # no -> skip cleanup critical |
708 | tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit | 701 | tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit |
709 | bnz BASED(mcck_int_main) # from user -> load async stack | 702 | bnz BASED(mcck_int_main) # from user -> load async stack |
@@ -720,6 +713,16 @@ mcck_int_main: | |||
720 | be BASED(0f) | 713 | be BASED(0f) |
721 | l %r15,__LC_PANIC_STACK # load panic stack | 714 | l %r15,__LC_PANIC_STACK # load panic stack |
722 | 0: CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+32 | 715 | 0: CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+32 |
716 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
717 | tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid? | ||
718 | bno BASED(mcck_no_vtime) # no -> skip cleanup critical | ||
719 | tm __LC_MCK_OLD_PSW+1,0x01 # interrupting from user ? | ||
720 | bz BASED(mcck_no_vtime) | ||
721 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER | ||
722 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | ||
723 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER | ||
724 | mcck_no_vtime: | ||
725 | #endif | ||
723 | l %r9,__LC_THREAD_INFO # load pointer to thread_info struct | 726 | l %r9,__LC_THREAD_INFO # load pointer to thread_info struct |
724 | la %r2,SP_PTREGS(%r15) # load pt_regs | 727 | la %r2,SP_PTREGS(%r15) # load pt_regs |
725 | l %r1,BASED(.Ls390_mcck) | 728 | l %r1,BASED(.Ls390_mcck) |
@@ -737,7 +740,7 @@ mcck_int_main: | |||
737 | l %r1,BASED(.Ls390_handle_mcck) | 740 | l %r1,BASED(.Ls390_handle_mcck) |
738 | basr %r14,%r1 # call machine check handler | 741 | basr %r14,%r1 # call machine check handler |
739 | mcck_return: | 742 | mcck_return: |
740 | RESTORE_ALL 0 | 743 | RESTORE_ALL __LC_RETURN_MCCK_PSW,0 |
741 | 744 | ||
742 | #ifdef CONFIG_SMP | 745 | #ifdef CONFIG_SMP |
743 | /* | 746 | /* |
@@ -803,6 +806,10 @@ cleanup_table_sysc_leave: | |||
803 | .long sysc_leave + 0x80000000, sysc_work_loop + 0x80000000 | 806 | .long sysc_leave + 0x80000000, sysc_work_loop + 0x80000000 |
804 | cleanup_table_sysc_work_loop: | 807 | cleanup_table_sysc_work_loop: |
805 | .long sysc_work_loop + 0x80000000, sysc_reschedule + 0x80000000 | 808 | .long sysc_work_loop + 0x80000000, sysc_reschedule + 0x80000000 |
809 | cleanup_table_io_leave: | ||
810 | .long io_leave + 0x80000000, io_done + 0x80000000 | ||
811 | cleanup_table_io_work_loop: | ||
812 | .long io_work_loop + 0x80000000, io_mcck_pending + 0x80000000 | ||
806 | 813 | ||
807 | cleanup_critical: | 814 | cleanup_critical: |
808 | clc 4(4,%r12),BASED(cleanup_table_system_call) | 815 | clc 4(4,%r12),BASED(cleanup_table_system_call) |
@@ -825,10 +832,26 @@ cleanup_critical: | |||
825 | clc 4(4,%r12),BASED(cleanup_table_sysc_work_loop+4) | 832 | clc 4(4,%r12),BASED(cleanup_table_sysc_work_loop+4) |
826 | bl BASED(cleanup_sysc_return) | 833 | bl BASED(cleanup_sysc_return) |
827 | 0: | 834 | 0: |
835 | clc 4(4,%r12),BASED(cleanup_table_io_leave) | ||
836 | bl BASED(0f) | ||
837 | clc 4(4,%r12),BASED(cleanup_table_io_leave+4) | ||
838 | bl BASED(cleanup_io_leave) | ||
839 | 0: | ||
840 | clc 4(4,%r12),BASED(cleanup_table_io_work_loop) | ||
841 | bl BASED(0f) | ||
842 | clc 4(4,%r12),BASED(cleanup_table_io_work_loop+4) | ||
843 | bl BASED(cleanup_io_return) | ||
844 | 0: | ||
828 | br %r14 | 845 | br %r14 |
829 | 846 | ||
830 | cleanup_system_call: | 847 | cleanup_system_call: |
831 | mvc __LC_RETURN_PSW(8),0(%r12) | 848 | mvc __LC_RETURN_PSW(8),0(%r12) |
849 | c %r12,BASED(.Lmck_old_psw) | ||
850 | be BASED(0f) | ||
851 | la %r12,__LC_SAVE_AREA+16 | ||
852 | b BASED(1f) | ||
853 | 0: la %r12,__LC_SAVE_AREA+32 | ||
854 | 1: | ||
832 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 855 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
833 | clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+4) | 856 | clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+4) |
834 | bh BASED(0f) | 857 | bh BASED(0f) |
@@ -838,11 +861,13 @@ cleanup_system_call: | |||
838 | #endif | 861 | #endif |
839 | clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn) | 862 | clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn) |
840 | bh BASED(0f) | 863 | bh BASED(0f) |
841 | mvc __LC_SAVE_AREA(16),__LC_SAVE_AREA+16 | 864 | mvc __LC_SAVE_AREA(16),0(%r12) |
842 | 0: st %r13,__LC_SAVE_AREA+20 | 865 | 0: st %r13,4(%r12) |
866 | st %r12,__LC_SAVE_AREA+48 # argh | ||
843 | SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 | 867 | SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 |
844 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 868 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA |
845 | st %r15,__LC_SAVE_AREA+28 | 869 | l %r12,__LC_SAVE_AREA+48 # argh |
870 | st %r15,12(%r12) | ||
846 | lh %r7,0x8a | 871 | lh %r7,0x8a |
847 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 872 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
848 | cleanup_vtime: | 873 | cleanup_vtime: |
@@ -879,17 +904,21 @@ cleanup_sysc_return: | |||
879 | 904 | ||
880 | cleanup_sysc_leave: | 905 | cleanup_sysc_leave: |
881 | clc 4(4,%r12),BASED(cleanup_sysc_leave_insn) | 906 | clc 4(4,%r12),BASED(cleanup_sysc_leave_insn) |
882 | be BASED(0f) | 907 | be BASED(2f) |
883 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 908 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
884 | mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER | 909 | mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER |
885 | clc 4(4,%r12),BASED(cleanup_sysc_leave_insn+4) | 910 | clc 4(4,%r12),BASED(cleanup_sysc_leave_insn+4) |
886 | be BASED(0f) | 911 | be BASED(2f) |
887 | #endif | 912 | #endif |
888 | mvc __LC_RETURN_PSW(8),SP_PSW(%r15) | 913 | mvc __LC_RETURN_PSW(8),SP_PSW(%r15) |
889 | mvc __LC_SAVE_AREA+16(16),SP_R12(%r15) | 914 | c %r12,BASED(.Lmck_old_psw) |
890 | lm %r0,%r11,SP_R0(%r15) | 915 | bne BASED(0f) |
916 | mvc __LC_SAVE_AREA+32(16),SP_R12(%r15) | ||
917 | b BASED(1f) | ||
918 | 0: mvc __LC_SAVE_AREA+16(16),SP_R12(%r15) | ||
919 | 1: lm %r0,%r11,SP_R0(%r15) | ||
891 | l %r15,SP_R15(%r15) | 920 | l %r15,SP_R15(%r15) |
892 | 0: la %r12,__LC_RETURN_PSW | 921 | 2: la %r12,__LC_RETURN_PSW |
893 | br %r14 | 922 | br %r14 |
894 | cleanup_sysc_leave_insn: | 923 | cleanup_sysc_leave_insn: |
895 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 924 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
@@ -897,6 +926,36 @@ cleanup_sysc_leave_insn: | |||
897 | #endif | 926 | #endif |
898 | .long sysc_leave + 10 + 0x80000000 | 927 | .long sysc_leave + 10 + 0x80000000 |
899 | 928 | ||
929 | cleanup_io_return: | ||
930 | mvc __LC_RETURN_PSW(4),0(%r12) | ||
931 | mvc __LC_RETURN_PSW+4(4),BASED(cleanup_table_io_work_loop) | ||
932 | la %r12,__LC_RETURN_PSW | ||
933 | br %r14 | ||
934 | |||
935 | cleanup_io_leave: | ||
936 | clc 4(4,%r12),BASED(cleanup_io_leave_insn) | ||
937 | be BASED(2f) | ||
938 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
939 | mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER | ||
940 | clc 4(4,%r12),BASED(cleanup_io_leave_insn+4) | ||
941 | be BASED(2f) | ||
942 | #endif | ||
943 | mvc __LC_RETURN_PSW(8),SP_PSW(%r15) | ||
944 | c %r12,BASED(.Lmck_old_psw) | ||
945 | bne BASED(0f) | ||
946 | mvc __LC_SAVE_AREA+32(16),SP_R12(%r15) | ||
947 | b BASED(1f) | ||
948 | 0: mvc __LC_SAVE_AREA+16(16),SP_R12(%r15) | ||
949 | 1: lm %r0,%r11,SP_R0(%r15) | ||
950 | l %r15,SP_R15(%r15) | ||
951 | 2: la %r12,__LC_RETURN_PSW | ||
952 | br %r14 | ||
953 | cleanup_io_leave_insn: | ||
954 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
955 | .long io_leave + 18 + 0x80000000 | ||
956 | #endif | ||
957 | .long io_leave + 14 + 0x80000000 | ||
958 | |||
900 | /* | 959 | /* |
901 | * Integer constants | 960 | * Integer constants |
902 | */ | 961 | */ |
@@ -918,6 +977,7 @@ cleanup_sysc_leave_insn: | |||
918 | .Ls390_mcck: .long s390_do_machine_check | 977 | .Ls390_mcck: .long s390_do_machine_check |
919 | .Ls390_handle_mcck: | 978 | .Ls390_handle_mcck: |
920 | .long s390_handle_mcck | 979 | .long s390_handle_mcck |
980 | .Lmck_old_psw: .long __LC_MCK_OLD_PSW | ||
921 | .Ldo_IRQ: .long do_IRQ | 981 | .Ldo_IRQ: .long do_IRQ |
922 | .Ldo_extint: .long do_extint | 982 | .Ldo_extint: .long do_extint |
923 | .Ldo_signal: .long do_signal | 983 | .Ldo_signal: .long do_signal |