diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2005-09-03 18:57:56 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@evo.osdl.org> | 2005-09-05 03:06:25 -0400 |
commit | ae6aa2ea8973e200cb3d0564a64a1b441d233428 (patch) | |
tree | 2bd12e22134b4f087c2179af0a304ca6dd9ca585 | |
parent | 4c139862b8831261d57de02716b92f82e5fb463b (diff) |
[PATCH] s390: machine check handler bugs
The new machine check handler still has a few bugs.
1) The system entry time has to be stored in the machine check handler,
2) the machine check return psw may not be stored at the usual place
because it might overwrite the return psw of the interrupted context,
3) the return address for the call to s390_handle_mcck in the i/o interrupt
handler is not correct,
4) the system call cleanup has to take the different save area of the
machine check handler into account,
5) the machine check handler may not call UPDATE_VTIME before
CREATE_STACK_FRAME, and
6) the io leave path needs a critical section cleanup to make sure that the
TIF_MCCK_PENDING bit is really checked before switching back to user space.
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | arch/s390/kernel/entry.S | 116 | ||||
-rw-r--r-- | arch/s390/kernel/entry64.S | 113 | ||||
-rw-r--r-- | drivers/s390/s390mach.c | 2 | ||||
-rw-r--r-- | include/asm-s390/lowcore.h | 8 |
4 files changed, 181 insertions, 58 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 |
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index d9f22915008c..5db5976ff594 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 | /* |
@@ -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 | */ |
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c index 5bb255e02acc..4191fd9d4d11 100644 --- a/drivers/s390/s390mach.c +++ b/drivers/s390/s390mach.c | |||
@@ -240,7 +240,7 @@ s390_revalidate_registers(struct mci *mci) | |||
240 | * Floating point control register can't be restored. | 240 | * Floating point control register can't be restored. |
241 | * Task will be terminated. | 241 | * Task will be terminated. |
242 | */ | 242 | */ |
243 | asm volatile ("lfpc 0(%0)" : : "a" (&zero)); | 243 | asm volatile ("lfpc 0(%0)" : : "a" (&zero), "m" (zero)); |
244 | kill_task = 1; | 244 | kill_task = 1; |
245 | 245 | ||
246 | } | 246 | } |
diff --git a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h index afe6a9f9b0ae..c6f51c9ce3ff 100644 --- a/include/asm-s390/lowcore.h +++ b/include/asm-s390/lowcore.h | |||
@@ -68,6 +68,7 @@ | |||
68 | #define __LC_SYSTEM_TIMER 0x270 | 68 | #define __LC_SYSTEM_TIMER 0x270 |
69 | #define __LC_LAST_UPDATE_CLOCK 0x278 | 69 | #define __LC_LAST_UPDATE_CLOCK 0x278 |
70 | #define __LC_STEAL_CLOCK 0x280 | 70 | #define __LC_STEAL_CLOCK 0x280 |
71 | #define __LC_RETURN_MCCK_PSW 0x288 | ||
71 | #define __LC_KERNEL_STACK 0xC40 | 72 | #define __LC_KERNEL_STACK 0xC40 |
72 | #define __LC_THREAD_INFO 0xC44 | 73 | #define __LC_THREAD_INFO 0xC44 |
73 | #define __LC_ASYNC_STACK 0xC48 | 74 | #define __LC_ASYNC_STACK 0xC48 |
@@ -90,6 +91,7 @@ | |||
90 | #define __LC_SYSTEM_TIMER 0x278 | 91 | #define __LC_SYSTEM_TIMER 0x278 |
91 | #define __LC_LAST_UPDATE_CLOCK 0x280 | 92 | #define __LC_LAST_UPDATE_CLOCK 0x280 |
92 | #define __LC_STEAL_CLOCK 0x288 | 93 | #define __LC_STEAL_CLOCK 0x288 |
94 | #define __LC_RETURN_MCCK_PSW 0x290 | ||
93 | #define __LC_KERNEL_STACK 0xD40 | 95 | #define __LC_KERNEL_STACK 0xD40 |
94 | #define __LC_THREAD_INFO 0xD48 | 96 | #define __LC_THREAD_INFO 0xD48 |
95 | #define __LC_ASYNC_STACK 0xD50 | 97 | #define __LC_ASYNC_STACK 0xD50 |
@@ -196,7 +198,8 @@ struct _lowcore | |||
196 | __u64 system_timer; /* 0x270 */ | 198 | __u64 system_timer; /* 0x270 */ |
197 | __u64 last_update_clock; /* 0x278 */ | 199 | __u64 last_update_clock; /* 0x278 */ |
198 | __u64 steal_clock; /* 0x280 */ | 200 | __u64 steal_clock; /* 0x280 */ |
199 | __u8 pad8[0xc00-0x288]; /* 0x288 */ | 201 | psw_t return_mcck_psw; /* 0x288 */ |
202 | __u8 pad8[0xc00-0x290]; /* 0x290 */ | ||
200 | 203 | ||
201 | /* System info area */ | 204 | /* System info area */ |
202 | __u32 save_area[16]; /* 0xc00 */ | 205 | __u32 save_area[16]; /* 0xc00 */ |
@@ -285,7 +288,8 @@ struct _lowcore | |||
285 | __u64 system_timer; /* 0x278 */ | 288 | __u64 system_timer; /* 0x278 */ |
286 | __u64 last_update_clock; /* 0x280 */ | 289 | __u64 last_update_clock; /* 0x280 */ |
287 | __u64 steal_clock; /* 0x288 */ | 290 | __u64 steal_clock; /* 0x288 */ |
288 | __u8 pad8[0xc00-0x290]; /* 0x290 */ | 291 | psw_t return_mcck_psw; /* 0x290 */ |
292 | __u8 pad8[0xc00-0x2a0]; /* 0x2a0 */ | ||
289 | /* System info area */ | 293 | /* System info area */ |
290 | __u64 save_area[16]; /* 0xc00 */ | 294 | __u64 save_area[16]; /* 0xc00 */ |
291 | __u8 pad9[0xd40-0xc80]; /* 0xc80 */ | 295 | __u8 pad9[0xd40-0xc80]; /* 0xc80 */ |