aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/entry.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/entry.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/entry.S')
-rw-r--r--arch/s390/kernel/entry.S79
1 files changed, 59 insertions, 20 deletions
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index b2448487854c..74d80c3bba80 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -93,13 +93,22 @@ STACK_SIZE = 1 << STACK_SHIFT
93 l %r13,__LC_SVC_NEW_PSW+4 # load &system_call to %r13 93 l %r13,__LC_SVC_NEW_PSW+4 # load &system_call to %r13
94 .endm 94 .endm
95 95
96 .macro SAVE_ALL psworg,savearea,sync 96 .macro SAVE_ALL_SYNC psworg,savearea
97 la %r12,\psworg 97 la %r12,\psworg
98 .if \sync
99 tm \psworg+1,0x01 # test problem state bit 98 tm \psworg+1,0x01 # test problem state bit
100 bz BASED(2f) # skip stack setup save 99 bz BASED(2f) # skip stack setup save
101 l %r15,__LC_KERNEL_STACK # problem state -> load ksp 100 l %r15,__LC_KERNEL_STACK # problem state -> load ksp
102 .else 101#ifdef CONFIG_CHECK_STACK
102 b BASED(3f)
1032: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD
104 bz BASED(stack_overflow)
1053:
106#endif
1072:
108 .endm
109
110 .macro SAVE_ALL_ASYNC psworg,savearea
111 la %r12,\psworg
103 tm \psworg+1,0x01 # test problem state bit 112 tm \psworg+1,0x01 # test problem state bit
104 bnz BASED(1f) # from user -> load async stack 113 bnz BASED(1f) # from user -> load async stack
105 clc \psworg+4(4),BASED(.Lcritical_end) 114 clc \psworg+4(4),BASED(.Lcritical_end)
@@ -115,7 +124,6 @@ STACK_SIZE = 1 << STACK_SHIFT
115 sra %r14,STACK_SHIFT 124 sra %r14,STACK_SHIFT
116 be BASED(2f) 125 be BASED(2f)
1171: l %r15,__LC_ASYNC_STACK 1261: l %r15,__LC_ASYNC_STACK
118 .endif
119#ifdef CONFIG_CHECK_STACK 127#ifdef CONFIG_CHECK_STACK
120 b BASED(3f) 128 b BASED(3f)
1212: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD 1292: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD
@@ -196,7 +204,7 @@ system_call:
196 STORE_TIMER __LC_SYNC_ENTER_TIMER 204 STORE_TIMER __LC_SYNC_ENTER_TIMER
197sysc_saveall: 205sysc_saveall:
198 SAVE_ALL_BASE __LC_SAVE_AREA 206 SAVE_ALL_BASE __LC_SAVE_AREA
199 SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 207 SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
200 CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA 208 CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
201 lh %r7,0x8a # get svc number from lowcore 209 lh %r7,0x8a # get svc number from lowcore
202#ifdef CONFIG_VIRT_CPU_ACCOUNTING 210#ifdef CONFIG_VIRT_CPU_ACCOUNTING
@@ -425,7 +433,7 @@ pgm_check_handler:
425 SAVE_ALL_BASE __LC_SAVE_AREA 433 SAVE_ALL_BASE __LC_SAVE_AREA
426 tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception 434 tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
427 bnz BASED(pgm_per) # got per exception -> special case 435 bnz BASED(pgm_per) # got per exception -> special case
428 SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 436 SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA
429 CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA 437 CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
430#ifdef CONFIG_VIRT_CPU_ACCOUNTING 438#ifdef CONFIG_VIRT_CPU_ACCOUNTING
431 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 439 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
@@ -464,7 +472,7 @@ pgm_per:
464# Normal per exception 472# Normal per exception
465# 473#
466pgm_per_std: 474pgm_per_std:
467 SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 475 SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA
468 CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA 476 CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
469#ifdef CONFIG_VIRT_CPU_ACCOUNTING 477#ifdef CONFIG_VIRT_CPU_ACCOUNTING
470 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 478 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
@@ -490,7 +498,7 @@ pgm_no_vtime2:
490# it was a single stepped SVC that is causing all the trouble 498# it was a single stepped SVC that is causing all the trouble
491# 499#
492pgm_svcper: 500pgm_svcper:
493 SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 501 SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
494 CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA 502 CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
495#ifdef CONFIG_VIRT_CPU_ACCOUNTING 503#ifdef CONFIG_VIRT_CPU_ACCOUNTING
496 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 504 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
@@ -519,7 +527,7 @@ io_int_handler:
519 STORE_TIMER __LC_ASYNC_ENTER_TIMER 527 STORE_TIMER __LC_ASYNC_ENTER_TIMER
520 stck __LC_INT_CLOCK 528 stck __LC_INT_CLOCK
521 SAVE_ALL_BASE __LC_SAVE_AREA+16 529 SAVE_ALL_BASE __LC_SAVE_AREA+16
522 SAVE_ALL __LC_IO_OLD_PSW,__LC_SAVE_AREA+16,0 530 SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+16
523 CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+16 531 CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+16
524#ifdef CONFIG_VIRT_CPU_ACCOUNTING 532#ifdef CONFIG_VIRT_CPU_ACCOUNTING
525 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 533 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
@@ -631,7 +639,7 @@ ext_int_handler:
631 STORE_TIMER __LC_ASYNC_ENTER_TIMER 639 STORE_TIMER __LC_ASYNC_ENTER_TIMER
632 stck __LC_INT_CLOCK 640 stck __LC_INT_CLOCK
633 SAVE_ALL_BASE __LC_SAVE_AREA+16 641 SAVE_ALL_BASE __LC_SAVE_AREA+16
634 SAVE_ALL __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16,0 642 SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16
635 CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16 643 CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16
636#ifdef CONFIG_VIRT_CPU_ACCOUNTING 644#ifdef CONFIG_VIRT_CPU_ACCOUNTING
637 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 645 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
@@ -657,21 +665,31 @@ __critical_end:
657 .globl mcck_int_handler 665 .globl mcck_int_handler
658mcck_int_handler: 666mcck_int_handler:
659 spt __LC_CPU_TIMER_SAVE_AREA # revalidate cpu timer 667 spt __LC_CPU_TIMER_SAVE_AREA # revalidate cpu timer
660 mvc __LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA
661 lm %r0,%r15,__LC_GPREGS_SAVE_AREA # revalidate gprs 668 lm %r0,%r15,__LC_GPREGS_SAVE_AREA # revalidate gprs
662 SAVE_ALL_BASE __LC_SAVE_AREA+32 669 SAVE_ALL_BASE __LC_SAVE_AREA+32
663 la %r12,__LC_MCK_OLD_PSW 670 la %r12,__LC_MCK_OLD_PSW
664 tm __LC_MCCK_CODE,0x80 # system damage? 671 tm __LC_MCCK_CODE,0x80 # system damage?
665 bo BASED(mcck_int_main) # yes -> rest of mcck code invalid 672 bo BASED(mcck_int_main) # yes -> rest of mcck code invalid
666 tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid?
667 bo BASED(0f)
668 spt __LC_LAST_UPDATE_TIMER # revalidate cpu timer
669#ifdef CONFIG_VIRT_CPU_ACCOUNTING 673#ifdef CONFIG_VIRT_CPU_ACCOUNTING
670 mvc __LC_ASYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER 674 mvc __LC_SAVE_AREA+52(8),__LC_ASYNC_ENTER_TIMER
671 mvc __LC_SYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER 675 mvc __LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA
672 mvc __LC_EXIT_TIMER(8),__LC_LAST_UPDATE_TIMER 676 tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid?
677 bo BASED(1f)
678 la %r14,__LC_SYNC_ENTER_TIMER
679 clc 0(8,%r14),__LC_ASYNC_ENTER_TIMER
680 bl BASED(0f)
681 la %r14,__LC_ASYNC_ENTER_TIMER
6820: clc 0(8,%r14),__LC_EXIT_TIMER
683 bl BASED(0f)
684 la %r14,__LC_EXIT_TIMER
6850: clc 0(8,%r14),__LC_LAST_UPDATE_TIMER
686 bl BASED(0f)
687 la %r14,__LC_LAST_UPDATE_TIMER
6880: spt 0(%r14)
689 mvc __LC_ASYNC_ENTER_TIMER(8),0(%r14)
6901:
673#endif 691#endif
6740: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? 692 tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid?
675 bno BASED(mcck_int_main) # no -> skip cleanup critical 693 bno BASED(mcck_int_main) # no -> skip cleanup critical
676 tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit 694 tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit
677 bnz BASED(mcck_int_main) # from user -> load async stack 695 bnz BASED(mcck_int_main) # from user -> load async stack
@@ -691,7 +709,7 @@ mcck_int_main:
691#ifdef CONFIG_VIRT_CPU_ACCOUNTING 709#ifdef CONFIG_VIRT_CPU_ACCOUNTING
692 tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid? 710 tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid?
693 bno BASED(mcck_no_vtime) # no -> skip cleanup critical 711 bno BASED(mcck_no_vtime) # no -> skip cleanup critical
694 tm __LC_MCK_OLD_PSW+1,0x01 # interrupting from user ? 712 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
695 bz BASED(mcck_no_vtime) 713 bz BASED(mcck_no_vtime)
696 UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER 714 UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
697 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER 715 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
@@ -715,6 +733,20 @@ mcck_no_vtime:
715 l %r1,BASED(.Ls390_handle_mcck) 733 l %r1,BASED(.Ls390_handle_mcck)
716 basr %r14,%r1 # call machine check handler 734 basr %r14,%r1 # call machine check handler
717mcck_return: 735mcck_return:
736 mvc __LC_RETURN_MCCK_PSW(8),SP_PSW(%r15) # move return PSW
737 ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit
738#ifdef CONFIG_VIRT_CPU_ACCOUNTING
739 mvc __LC_ASYNC_ENTER_TIMER(8),__LC_SAVE_AREA+52
740 tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ?
741 bno BASED(0f)
742 lm %r0,%r15,SP_R0(%r15) # load gprs 0-15
743 stpt __LC_EXIT_TIMER
744 lpsw __LC_RETURN_MCCK_PSW # back to caller
7450:
746#endif
747 lm %r0,%r15,SP_R0(%r15) # load gprs 0-15
748 lpsw __LC_RETURN_MCCK_PSW # back to caller
749
718 RESTORE_ALL __LC_RETURN_MCCK_PSW,0 750 RESTORE_ALL __LC_RETURN_MCCK_PSW,0
719 751
720#ifdef CONFIG_SMP 752#ifdef CONFIG_SMP
@@ -781,6 +813,8 @@ cleanup_table_sysc_leave:
781 .long sysc_leave + 0x80000000, sysc_work_loop + 0x80000000 813 .long sysc_leave + 0x80000000, sysc_work_loop + 0x80000000
782cleanup_table_sysc_work_loop: 814cleanup_table_sysc_work_loop:
783 .long sysc_work_loop + 0x80000000, sysc_reschedule + 0x80000000 815 .long sysc_work_loop + 0x80000000, sysc_reschedule + 0x80000000
816cleanup_table_io_return:
817 .long io_return + 0x80000000, io_leave + 0x80000000
784cleanup_table_io_leave: 818cleanup_table_io_leave:
785 .long io_leave + 0x80000000, io_done + 0x80000000 819 .long io_leave + 0x80000000, io_done + 0x80000000
786cleanup_table_io_work_loop: 820cleanup_table_io_work_loop:
@@ -807,6 +841,11 @@ cleanup_critical:
807 clc 4(4,%r12),BASED(cleanup_table_sysc_work_loop+4) 841 clc 4(4,%r12),BASED(cleanup_table_sysc_work_loop+4)
808 bl BASED(cleanup_sysc_return) 842 bl BASED(cleanup_sysc_return)
8090: 8430:
844 clc 4(4,%r12),BASED(cleanup_table_io_return)
845 bl BASED(0f)
846 clc 4(4,%r12),BASED(cleanup_table_io_return+4)
847 bl BASED(cleanup_io_return)
8480:
810 clc 4(4,%r12),BASED(cleanup_table_io_leave) 849 clc 4(4,%r12),BASED(cleanup_table_io_leave)
811 bl BASED(0f) 850 bl BASED(0f)
812 clc 4(4,%r12),BASED(cleanup_table_io_leave+4) 851 clc 4(4,%r12),BASED(cleanup_table_io_leave+4)
@@ -839,7 +878,7 @@ cleanup_system_call:
839 mvc __LC_SAVE_AREA(16),0(%r12) 878 mvc __LC_SAVE_AREA(16),0(%r12)
8400: st %r13,4(%r12) 8790: st %r13,4(%r12)
841 st %r12,__LC_SAVE_AREA+48 # argh 880 st %r12,__LC_SAVE_AREA+48 # argh
842 SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 881 SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
843 CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA 882 CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
844 l %r12,__LC_SAVE_AREA+48 # argh 883 l %r12,__LC_SAVE_AREA+48 # argh
845 st %r15,12(%r12) 884 st %r15,12(%r12)