aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/entry.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/entry.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/entry.S')
-rw-r--r--arch/s390/kernel/entry.S116
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.)
237sysc_leave: 237sysc_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.)
573io_leave: 571io_leave:
574 RESTORE_ALL 0 572 RESTORE_ALL __LC_RETURN_PSW,0
573io_done:
575 574
576#ifdef CONFIG_PREEMPT 575#ifdef CONFIG_PREEMPT
577io_preempt: 576io_preempt:
@@ -621,7 +620,7 @@ io_work_loop:
621# 620#
622io_mcck_pending: 621io_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
682mcck_int_handler: 683mcck_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
6960: 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
703mcck_no_vtime:
704#endif 698#endif
7050: 6990: 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
7220: CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+32 7150: 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
724mcck_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
739mcck_return: 742mcck_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
804cleanup_table_sysc_work_loop: 807cleanup_table_sysc_work_loop:
805 .long sysc_work_loop + 0x80000000, sysc_reschedule + 0x80000000 808 .long sysc_work_loop + 0x80000000, sysc_reschedule + 0x80000000
809cleanup_table_io_leave:
810 .long io_leave + 0x80000000, io_done + 0x80000000
811cleanup_table_io_work_loop:
812 .long io_work_loop + 0x80000000, io_mcck_pending + 0x80000000
806 813
807cleanup_critical: 814cleanup_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)
8270: 8340:
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)
8390:
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)
8440:
828 br %r14 845 br %r14
829 846
830cleanup_system_call: 847cleanup_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)
8530: la %r12,__LC_SAVE_AREA+32
8541:
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)
8420: st %r13,__LC_SAVE_AREA+20 8650: 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
848cleanup_vtime: 873cleanup_vtime:
@@ -879,17 +904,21 @@ cleanup_sysc_return:
879 904
880cleanup_sysc_leave: 905cleanup_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)
9180: mvc __LC_SAVE_AREA+16(16),SP_R12(%r15)
9191: lm %r0,%r11,SP_R0(%r15)
891 l %r15,SP_R15(%r15) 920 l %r15,SP_R15(%r15)
8920: la %r12,__LC_RETURN_PSW 9212: la %r12,__LC_RETURN_PSW
893 br %r14 922 br %r14
894cleanup_sysc_leave_insn: 923cleanup_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
929cleanup_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
935cleanup_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)
9480: mvc __LC_SAVE_AREA+16(16),SP_R12(%r15)
9491: lm %r0,%r11,SP_R0(%r15)
950 l %r15,SP_R15(%r15)
9512: la %r12,__LC_RETURN_PSW
952 br %r14
953cleanup_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