aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/entry.S
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2010-05-17 04:00:03 -0400
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>2010-05-17 04:00:15 -0400
commit6377981faf1a4425b0531e577736ef03df97c8f6 (patch)
treef690c5d357413cb6f26c8463519ad2b1f8800851 /arch/s390/kernel/entry.S
parent6a2df3a87276cdc08fd87070d09ea18d1fb9d622 (diff)
[S390] idle time accounting vs. machine checks
A machine check can interrupt the i/o and external interrupt handler anytime. If the machine check occurs while the interrupt handler is waking up from idle vtime_start_cpu can get executed a second time and the int_clock / async_enter_timer values in the lowcore get clobbered. This can confuse the cpu time accounting. To fix this problem two changes are needed. First the machine check handler has to use its own copies of int_clock and async_enter_timer, named mcck_clock and mcck_enter_timer. Second the nested execution of vtime_start_cpu has to be prevented. This is done in s390_idle_check by checking the wait bit in the program status word. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel/entry.S')
-rw-r--r--arch/s390/kernel/entry.S54
1 files changed, 26 insertions, 28 deletions
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 07d849995da..0e2b16241df 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -742,15 +742,14 @@ __critical_end:
742 742
743 .globl mcck_int_handler 743 .globl mcck_int_handler
744mcck_int_handler: 744mcck_int_handler:
745 stck __LC_INT_CLOCK 745 stck __LC_MCCK_CLOCK
746 spt __LC_CPU_TIMER_SAVE_AREA # revalidate cpu timer 746 spt __LC_CPU_TIMER_SAVE_AREA # revalidate cpu timer
747 lm %r0,%r15,__LC_GPREGS_SAVE_AREA # revalidate gprs 747 lm %r0,%r15,__LC_GPREGS_SAVE_AREA # revalidate gprs
748 SAVE_ALL_BASE __LC_SAVE_AREA+32 748 SAVE_ALL_BASE __LC_SAVE_AREA+32
749 la %r12,__LC_MCK_OLD_PSW 749 la %r12,__LC_MCK_OLD_PSW
750 tm __LC_MCCK_CODE,0x80 # system damage? 750 tm __LC_MCCK_CODE,0x80 # system damage?
751 bo BASED(mcck_int_main) # yes -> rest of mcck code invalid 751 bo BASED(mcck_int_main) # yes -> rest of mcck code invalid
752 mvc __LC_SAVE_AREA+52(8),__LC_ASYNC_ENTER_TIMER 752 mvc __LC_MCCK_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA
753 mvc __LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA
754 tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid? 753 tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid?
755 bo BASED(1f) 754 bo BASED(1f)
756 la %r14,__LC_SYNC_ENTER_TIMER 755 la %r14,__LC_SYNC_ENTER_TIMER
@@ -764,7 +763,7 @@ mcck_int_handler:
764 bl BASED(0f) 763 bl BASED(0f)
765 la %r14,__LC_LAST_UPDATE_TIMER 764 la %r14,__LC_LAST_UPDATE_TIMER
7660: spt 0(%r14) 7650: spt 0(%r14)
767 mvc __LC_ASYNC_ENTER_TIMER(8),0(%r14) 766 mvc __LC_MCCK_ENTER_TIMER(8),0(%r14)
7681: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? 7671: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid?
769 bno BASED(mcck_int_main) # no -> skip cleanup critical 768 bno BASED(mcck_int_main) # no -> skip cleanup critical
770 tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit 769 tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit
@@ -786,9 +785,9 @@ mcck_int_main:
786 bno BASED(mcck_no_vtime) # no -> skip cleanup critical 785 bno BASED(mcck_no_vtime) # no -> skip cleanup critical
787 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 786 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
788 bz BASED(mcck_no_vtime) 787 bz BASED(mcck_no_vtime)
789 UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER 788 UPDATE_VTIME __LC_EXIT_TIMER,__LC_MCCK_ENTER_TIMER,__LC_USER_TIMER
790 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER 789 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
791 mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER 790 mvc __LC_LAST_UPDATE_TIMER(8),__LC_MCCK_ENTER_TIMER
792mcck_no_vtime: 791mcck_no_vtime:
793 l %r9,__LC_THREAD_INFO # load pointer to thread_info struct 792 l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
794 la %r2,SP_PTREGS(%r15) # load pt_regs 793 la %r2,SP_PTREGS(%r15) # load pt_regs
@@ -811,7 +810,6 @@ mcck_no_vtime:
811mcck_return: 810mcck_return:
812 mvc __LC_RETURN_MCCK_PSW(8),SP_PSW(%r15) # move return PSW 811 mvc __LC_RETURN_MCCK_PSW(8),SP_PSW(%r15) # move return PSW
813 ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit 812 ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit
814 mvc __LC_ASYNC_ENTER_TIMER(8),__LC_SAVE_AREA+52
815 tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ? 813 tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ?
816 bno BASED(0f) 814 bno BASED(0f)
817 lm %r0,%r15,SP_R0(%r15) # load gprs 0-15 815 lm %r0,%r15,SP_R0(%r15) # load gprs 0-15
@@ -934,15 +932,16 @@ cleanup_critical:
934 932
935cleanup_system_call: 933cleanup_system_call:
936 mvc __LC_RETURN_PSW(8),0(%r12) 934 mvc __LC_RETURN_PSW(8),0(%r12)
937 c %r12,BASED(.Lmck_old_psw)
938 be BASED(0f)
939 la %r12,__LC_SAVE_AREA+16
940 b BASED(1f)
9410: la %r12,__LC_SAVE_AREA+32
9421:
943 clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+4) 935 clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+4)
944 bh BASED(0f) 936 bh BASED(0f)
937 mvc __LC_SYNC_ENTER_TIMER(8),__LC_MCCK_ENTER_TIMER
938 c %r12,BASED(.Lmck_old_psw)
939 be BASED(0f)
945 mvc __LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER 940 mvc __LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER
9410: c %r12,BASED(.Lmck_old_psw)
942 la %r12,__LC_SAVE_AREA+32
943 be BASED(0f)
944 la %r12,__LC_SAVE_AREA+16
9460: clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+8) 9450: clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+8)
947 bhe BASED(cleanup_vtime) 946 bhe BASED(cleanup_vtime)
948 clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn) 947 clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn)
@@ -984,16 +983,19 @@ cleanup_sysc_tif:
984cleanup_sysc_restore: 983cleanup_sysc_restore:
985 clc 4(4,%r12),BASED(cleanup_sysc_restore_insn) 984 clc 4(4,%r12),BASED(cleanup_sysc_restore_insn)
986 be BASED(2f) 985 be BASED(2f)
986 mvc __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER
987 c %r12,BASED(.Lmck_old_psw)
988 be BASED(0f)
987 mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER 989 mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
988 clc 4(4,%r12),BASED(cleanup_sysc_restore_insn+4) 9900: clc 4(4,%r12),BASED(cleanup_sysc_restore_insn+4)
989 be BASED(2f) 991 be BASED(2f)
990 mvc __LC_RETURN_PSW(8),SP_PSW(%r15) 992 mvc __LC_RETURN_PSW(8),SP_PSW(%r15)
991 c %r12,BASED(.Lmck_old_psw) 993 c %r12,BASED(.Lmck_old_psw)
992 bne BASED(0f) 994 la %r12,__LC_SAVE_AREA+32
993 mvc __LC_SAVE_AREA+32(16),SP_R12(%r15) 995 be BASED(1f)
994 b BASED(1f) 996 la %r12,__LC_SAVE_AREA+16
9950: mvc __LC_SAVE_AREA+16(16),SP_R12(%r15) 9971: mvc 0(16,%r12),SP_R12(%r15)
9961: lm %r0,%r11,SP_R0(%r15) 998 lm %r0,%r11,SP_R0(%r15)
997 l %r15,SP_R15(%r15) 999 l %r15,SP_R15(%r15)
9982: la %r12,__LC_RETURN_PSW 10002: la %r12,__LC_RETURN_PSW
999 br %r14 1001 br %r14
@@ -1009,19 +1011,15 @@ cleanup_io_tif:
1009 1011
1010cleanup_io_restore: 1012cleanup_io_restore:
1011 clc 4(4,%r12),BASED(cleanup_io_restore_insn) 1013 clc 4(4,%r12),BASED(cleanup_io_restore_insn)
1012 be BASED(2f) 1014 be BASED(1f)
1013 mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER 1015 mvc __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER
1014 clc 4(4,%r12),BASED(cleanup_io_restore_insn+4) 1016 clc 4(4,%r12),BASED(cleanup_io_restore_insn+4)
1015 be BASED(2f) 1017 be BASED(1f)
1016 mvc __LC_RETURN_PSW(8),SP_PSW(%r15) 1018 mvc __LC_RETURN_PSW(8),SP_PSW(%r15)
1017 c %r12,BASED(.Lmck_old_psw)
1018 bne BASED(0f)
1019 mvc __LC_SAVE_AREA+32(16),SP_R12(%r15) 1019 mvc __LC_SAVE_AREA+32(16),SP_R12(%r15)
1020 b BASED(1f) 1020 lm %r0,%r11,SP_R0(%r15)
10210: mvc __LC_SAVE_AREA+16(16),SP_R12(%r15)
10221: lm %r0,%r11,SP_R0(%r15)
1023 l %r15,SP_R15(%r15) 1021 l %r15,SP_R15(%r15)
10242: la %r12,__LC_RETURN_PSW 10221: la %r12,__LC_RETURN_PSW
1025 br %r14 1023 br %r14
1026cleanup_io_restore_insn: 1024cleanup_io_restore_insn:
1027 .long io_done - 4 + 0x80000000 1025 .long io_done - 4 + 0x80000000