aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/entry64.S
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2006-06-29 08:58:05 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2006-06-29 08:58:05 -0400
commit63b122466484e44d09af12bba33b34019757a3c2 (patch)
treed35ecad386c69ddb930adcce352d0d0a8d5d95da /arch/s390/kernel/entry64.S
parent9faf06547efe11ccb51678c6805037c7377b85ee (diff)
[S390] virtual cpu accounting vs. machine checks.
If a machine checks interrupts the external or the i/o interrupt handler before they have completed the cpu time calculations, the accounting goes wrong. After the cpu returned from the machine check handler to the interrupted interrupt handler, a negative cpu time delta can occur. If the accumulated cpu time in lowcore is small enough this value can get negative as well. The next jiffy interrupt will pick up that negative value, shift it by 12 and add the now huge positive value to the cpu time of the process. To solve this the machine check handler is modified not to change any of the timestamps in the lowcore if the machine check interrupted kernel context. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel/entry64.S')
-rw-r--r--arch/s390/kernel/entry64.S78
1 files changed, 57 insertions, 21 deletions
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 2ac095bc0e25..21e601d56139 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -87,13 +87,22 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
87 larl %r13,system_call 87 larl %r13,system_call
88 .endm 88 .endm
89 89
90 .macro SAVE_ALL psworg,savearea,sync 90 .macro SAVE_ALL_SYNC psworg,savearea
91 la %r12,\psworg 91 la %r12,\psworg
92 .if \sync
93 tm \psworg+1,0x01 # test problem state bit 92 tm \psworg+1,0x01 # test problem state bit
94 jz 2f # skip stack setup save 93 jz 2f # skip stack setup save
95 lg %r15,__LC_KERNEL_STACK # problem state -> load ksp 94 lg %r15,__LC_KERNEL_STACK # problem state -> load ksp
96 .else 95#ifdef CONFIG_CHECK_STACK
96 j 3f
972: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD
98 jz stack_overflow
993:
100#endif
1012:
102 .endm
103
104 .macro SAVE_ALL_ASYNC psworg,savearea
105 la %r12,\psworg
97 tm \psworg+1,0x01 # test problem state bit 106 tm \psworg+1,0x01 # test problem state bit
98 jnz 1f # from user -> load kernel stack 107 jnz 1f # from user -> load kernel stack
99 clc \psworg+8(8),BASED(.Lcritical_end) 108 clc \psworg+8(8),BASED(.Lcritical_end)
@@ -108,7 +117,6 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
108 srag %r14,%r14,STACK_SHIFT 117 srag %r14,%r14,STACK_SHIFT
109 jz 2f 118 jz 2f
1101: lg %r15,__LC_ASYNC_STACK # load async stack 1191: lg %r15,__LC_ASYNC_STACK # load async stack
111 .endif
112#ifdef CONFIG_CHECK_STACK 120#ifdef CONFIG_CHECK_STACK
113 j 3f 121 j 3f
1142: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD 1222: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD
@@ -187,7 +195,7 @@ system_call:
187 STORE_TIMER __LC_SYNC_ENTER_TIMER 195 STORE_TIMER __LC_SYNC_ENTER_TIMER
188sysc_saveall: 196sysc_saveall:
189 SAVE_ALL_BASE __LC_SAVE_AREA 197 SAVE_ALL_BASE __LC_SAVE_AREA
190 SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 198 SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
191 CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA 199 CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
192 llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore 200 llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore
193#ifdef CONFIG_VIRT_CPU_ACCOUNTING 201#ifdef CONFIG_VIRT_CPU_ACCOUNTING
@@ -446,7 +454,7 @@ pgm_check_handler:
446 SAVE_ALL_BASE __LC_SAVE_AREA 454 SAVE_ALL_BASE __LC_SAVE_AREA
447 tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception 455 tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
448 jnz pgm_per # got per exception -> special case 456 jnz pgm_per # got per exception -> special case
449 SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 457 SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA
450 CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA 458 CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
451#ifdef CONFIG_VIRT_CPU_ACCOUNTING 459#ifdef CONFIG_VIRT_CPU_ACCOUNTING
452 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 460 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
@@ -485,7 +493,7 @@ pgm_per:
485# Normal per exception 493# Normal per exception
486# 494#
487pgm_per_std: 495pgm_per_std:
488 SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 496 SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA
489 CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA 497 CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
490#ifdef CONFIG_VIRT_CPU_ACCOUNTING 498#ifdef CONFIG_VIRT_CPU_ACCOUNTING
491 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 499 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
@@ -511,7 +519,7 @@ pgm_no_vtime2:
511# it was a single stepped SVC that is causing all the trouble 519# it was a single stepped SVC that is causing all the trouble
512# 520#
513pgm_svcper: 521pgm_svcper:
514 SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 522 SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
515 CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA 523 CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
516#ifdef CONFIG_VIRT_CPU_ACCOUNTING 524#ifdef CONFIG_VIRT_CPU_ACCOUNTING
517 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 525 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
@@ -539,7 +547,7 @@ io_int_handler:
539 STORE_TIMER __LC_ASYNC_ENTER_TIMER 547 STORE_TIMER __LC_ASYNC_ENTER_TIMER
540 stck __LC_INT_CLOCK 548 stck __LC_INT_CLOCK
541 SAVE_ALL_BASE __LC_SAVE_AREA+32 549 SAVE_ALL_BASE __LC_SAVE_AREA+32
542 SAVE_ALL __LC_IO_OLD_PSW,__LC_SAVE_AREA+32,0 550 SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+32
543 CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+32 551 CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+32
544#ifdef CONFIG_VIRT_CPU_ACCOUNTING 552#ifdef CONFIG_VIRT_CPU_ACCOUNTING
545 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 553 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
@@ -647,7 +655,7 @@ ext_int_handler:
647 STORE_TIMER __LC_ASYNC_ENTER_TIMER 655 STORE_TIMER __LC_ASYNC_ENTER_TIMER
648 stck __LC_INT_CLOCK 656 stck __LC_INT_CLOCK
649 SAVE_ALL_BASE __LC_SAVE_AREA+32 657 SAVE_ALL_BASE __LC_SAVE_AREA+32
650 SAVE_ALL __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32,0 658 SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32
651 CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32 659 CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32
652#ifdef CONFIG_VIRT_CPU_ACCOUNTING 660#ifdef CONFIG_VIRT_CPU_ACCOUNTING
653 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 661 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
@@ -672,21 +680,32 @@ __critical_end:
672mcck_int_handler: 680mcck_int_handler:
673 la %r1,4095 # revalidate r1 681 la %r1,4095 # revalidate r1
674 spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer 682 spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer
675 mvc __LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA-4095(%r1)
676 lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs 683 lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs
677 SAVE_ALL_BASE __LC_SAVE_AREA+64 684 SAVE_ALL_BASE __LC_SAVE_AREA+64
678 la %r12,__LC_MCK_OLD_PSW 685 la %r12,__LC_MCK_OLD_PSW
679 tm __LC_MCCK_CODE,0x80 # system damage? 686 tm __LC_MCCK_CODE,0x80 # system damage?
680 jo mcck_int_main # yes -> rest of mcck code invalid 687 jo mcck_int_main # yes -> rest of mcck code invalid
681 tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid?
682 jo 0f
683 spt __LC_LAST_UPDATE_TIMER
684#ifdef CONFIG_VIRT_CPU_ACCOUNTING 688#ifdef CONFIG_VIRT_CPU_ACCOUNTING
685 mvc __LC_ASYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER 689 la %r14,4095
686 mvc __LC_SYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER 690 mvc __LC_SAVE_AREA+104(8),__LC_ASYNC_ENTER_TIMER
687 mvc __LC_EXIT_TIMER(8),__LC_LAST_UPDATE_TIMER 691 mvc __LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA-4095(%r14)
692 tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid?
693 jo 1f
694 la %r14,__LC_SYNC_ENTER_TIMER
695 clc 0(8,%r14),__LC_ASYNC_ENTER_TIMER
696 jl 0f
697 la %r14,__LC_ASYNC_ENTER_TIMER
6980: clc 0(8,%r14),__LC_EXIT_TIMER
699 jl 0f
700 la %r14,__LC_EXIT_TIMER
7010: clc 0(8,%r14),__LC_LAST_UPDATE_TIMER
702 jl 0f
703 la %r14,__LC_LAST_UPDATE_TIMER
7040: spt 0(%r14)
705 mvc __LC_ASYNC_ENTER_TIMER(8),0(%r14)
7061:
688#endif 707#endif
6890: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? 708 tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid?
690 jno mcck_int_main # no -> skip cleanup critical 709 jno mcck_int_main # no -> skip cleanup critical
691 tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit 710 tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit
692 jnz mcck_int_main # from user -> load kernel stack 711 jnz mcck_int_main # from user -> load kernel stack
@@ -705,7 +724,7 @@ mcck_int_main:
705#ifdef CONFIG_VIRT_CPU_ACCOUNTING 724#ifdef CONFIG_VIRT_CPU_ACCOUNTING
706 tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid? 725 tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid?
707 jno mcck_no_vtime # no -> no timer update 726 jno mcck_no_vtime # no -> no timer update
708 tm __LC_MCK_OLD_PSW+1,0x01 # interrupting from user ? 727 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
709 jz mcck_no_vtime 728 jz mcck_no_vtime
710 UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER 729 UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
711 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER 730 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
@@ -727,7 +746,17 @@ mcck_no_vtime:
727 jno mcck_return 746 jno mcck_return
728 brasl %r14,s390_handle_mcck 747 brasl %r14,s390_handle_mcck
729mcck_return: 748mcck_return:
730 RESTORE_ALL __LC_RETURN_MCCK_PSW,0 749 mvc __LC_RETURN_MCCK_PSW(16),SP_PSW(%r15) # move return PSW
750 ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit
751 lmg %r0,%r15,SP_R0(%r15) # load gprs 0-15
752#ifdef CONFIG_VIRT_CPU_ACCOUNTING
753 mvc __LC_ASYNC_ENTER_TIMER(8),__LC_SAVE_AREA+104
754 tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ?
755 jno 0f
756 stpt __LC_EXIT_TIMER
7570:
758#endif
759 lpswe __LC_RETURN_MCCK_PSW # back to caller
731 760
732#ifdef CONFIG_SMP 761#ifdef CONFIG_SMP
733/* 762/*
@@ -789,6 +818,8 @@ cleanup_table_sysc_leave:
789 .quad sysc_leave, sysc_work_loop 818 .quad sysc_leave, sysc_work_loop
790cleanup_table_sysc_work_loop: 819cleanup_table_sysc_work_loop:
791 .quad sysc_work_loop, sysc_reschedule 820 .quad sysc_work_loop, sysc_reschedule
821cleanup_table_io_return:
822 .quad io_return, io_leave
792cleanup_table_io_leave: 823cleanup_table_io_leave:
793 .quad io_leave, io_done 824 .quad io_leave, io_done
794cleanup_table_io_work_loop: 825cleanup_table_io_work_loop:
@@ -815,6 +846,11 @@ cleanup_critical:
815 clc 8(8,%r12),BASED(cleanup_table_sysc_work_loop+8) 846 clc 8(8,%r12),BASED(cleanup_table_sysc_work_loop+8)
816 jl cleanup_sysc_return 847 jl cleanup_sysc_return
8170: 8480:
849 clc 8(8,%r12),BASED(cleanup_table_io_return)
850 jl 0f
851 clc 8(8,%r12),BASED(cleanup_table_io_return+8)
852 jl cleanup_io_return
8530:
818 clc 8(8,%r12),BASED(cleanup_table_io_leave) 854 clc 8(8,%r12),BASED(cleanup_table_io_leave)
819 jl 0f 855 jl 0f
820 clc 8(8,%r12),BASED(cleanup_table_io_leave+8) 856 clc 8(8,%r12),BASED(cleanup_table_io_leave+8)
@@ -847,7 +883,7 @@ cleanup_system_call:
847 mvc __LC_SAVE_AREA(32),0(%r12) 883 mvc __LC_SAVE_AREA(32),0(%r12)
8480: stg %r13,8(%r12) 8840: stg %r13,8(%r12)
849 stg %r12,__LC_SAVE_AREA+96 # argh 885 stg %r12,__LC_SAVE_AREA+96 # argh
850 SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 886 SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
851 CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA 887 CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
852 lg %r12,__LC_SAVE_AREA+96 # argh 888 lg %r12,__LC_SAVE_AREA+96 # argh
853 stg %r15,24(%r12) 889 stg %r15,24(%r12)