aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/entry64.S
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2005-09-03 18:57:56 -0400
committerLinus Torvalds <torvalds@evo.osdl.org>2005-09-05 03:06:25 -0400
commitae6aa2ea8973e200cb3d0564a64a1b441d233428 (patch)
tree2bd12e22134b4f087c2179af0a304ca6dd9ca585 /arch/s390/kernel/entry64.S
parent4c139862b8831261d57de02716b92f82e5fb463b (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>
Diffstat (limited to 'arch/s390/kernel/entry64.S')
-rw-r--r--arch/s390/kernel/entry64.S113
1 files changed, 86 insertions, 27 deletions
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.)
235sysc_leave: 235sysc_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.)
614io_leave: 612io_leave:
615 RESTORE_ALL 0 613 RESTORE_ALL __LC_RETURN_PSW,0
614io_done:
616 615
617#ifdef CONFIG_PREEMPT 616#ifdef CONFIG_PREEMPT
618io_preempt: 617io_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:
718mcck_int_handler: 719mcck_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
7330: 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
740mcck_no_vtime:
741#endif 735#endif
7420: 7360: 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
7580: CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+64 7510: 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
760mcck_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
773mcck_return: 776mcck_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
834cleanup_table_sysc_work_loop: 837cleanup_table_sysc_work_loop:
835 .quad sysc_work_loop, sysc_reschedule 838 .quad sysc_work_loop, sysc_reschedule
839cleanup_table_io_leave:
840 .quad io_leave, io_done
841cleanup_table_io_work_loop:
842 .quad io_work_loop, io_mcck_pending
836 843
837cleanup_critical: 844cleanup_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
8570: 8640:
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
8690:
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
8740:
858 br %r14 875 br %r14
859 876
860cleanup_system_call: 877cleanup_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
8830: la %r12,__LC_SAVE_AREA+64
8841:
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)
8720: stg %r13,__LC_SAVE_AREA+40 8950: 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
878cleanup_vtime: 903cleanup_vtime:
@@ -909,17 +934,21 @@ cleanup_sysc_return:
909 934
910cleanup_sysc_leave: 935cleanup_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
9480: mvc __LC_SAVE_AREA+32(32),SP_R12(%r15)
9491: lmg %r0,%r11,SP_R0(%r15)
921 lg %r15,SP_R15(%r15) 950 lg %r15,SP_R15(%r15)
9220: la %r12,__LC_RETURN_PSW 9512: la %r12,__LC_RETURN_PSW
923 br %r14 952 br %r14
924cleanup_sysc_leave_insn: 953cleanup_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
959cleanup_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
965cleanup_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
9780: mvc __LC_SAVE_AREA+32(32),SP_R12(%r15)
9791: lmg %r0,%r11,SP_R0(%r15)
980 lg %r15,SP_R15(%r15)
9812: la %r12,__LC_RETURN_PSW
982 br %r14
983cleanup_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 */