aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/entry.S
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2007-11-20 05:13:32 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2007-11-20 05:13:45 -0500
commit411788ea7fca01ee803af8225ac35807b4d02050 (patch)
treea9704a068513b438bbe33b219ef9f6c29be01918 /arch/s390/kernel/entry.S
parent7aa8dac7ac68f5c2293e2ecf5ef542aa849f541f (diff)
[S390] Fix irq tracing and lockdep_sys_exit calls.
Current support for TRACE_IRQFLAGS and lockdep_sys_exit is broken. IRQ flag tracing is broken for program checks. Even worse is that the newly introduced calls to lockdep_sys_exit are in the critical section code which is not supposed to call any C functions. In addition the checks if locks are still held are also done when returning to kernel code which is broken as well. Fix all this by disabling interrupts and machine checks at the exit paths and then do the appropriate checks and calls. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel/entry.S')
-rw-r--r--arch/s390/kernel/entry.S109
1 files changed, 76 insertions, 33 deletions
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 139ca153d5cc..764d56177cb5 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -69,13 +69,31 @@ STACK_SIZE = 1 << STACK_SHIFT
69 basr %r14,%r1 69 basr %r14,%r1
70 .endm 70 .endm
71 71
72 .macro LOCKDEP_SYS_EXIT 72 .macro TRACE_IRQS_CHECK
73 l %r1,BASED(.Llockdep_sys_exit) 73 tm SP_PSW(%r15),0x03 # irqs enabled?
74 jz 0f
75 l %r1,BASED(.Ltrace_irq_on)
74 basr %r14,%r1 76 basr %r14,%r1
77 j 1f
780: l %r1,BASED(.Ltrace_irq_off)
79 basr %r14,%r1
801:
75 .endm 81 .endm
76#else 82#else
77#define TRACE_IRQS_ON 83#define TRACE_IRQS_ON
78#define TRACE_IRQS_OFF 84#define TRACE_IRQS_OFF
85#define TRACE_IRQS_CHECK
86#endif
87
88#ifdef CONFIG_LOCKDEP
89 .macro LOCKDEP_SYS_EXIT
90 tm SP_PSW+1(%r15),0x01 # returning to user ?
91 jz 0f
92 l %r1,BASED(.Llockdep_sys_exit)
93 basr %r14,%r1
940:
95 .endm
96#else
79#define LOCKDEP_SYS_EXIT 97#define LOCKDEP_SYS_EXIT
80#endif 98#endif
81 99
@@ -234,8 +252,6 @@ sysc_saveall:
234 lh %r7,0x8a # get svc number from lowcore 252 lh %r7,0x8a # get svc number from lowcore
235#ifdef CONFIG_VIRT_CPU_ACCOUNTING 253#ifdef CONFIG_VIRT_CPU_ACCOUNTING
236sysc_vtime: 254sysc_vtime:
237 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
238 bz BASED(sysc_do_svc)
239 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER 255 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
240sysc_stime: 256sysc_stime:
241 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER 257 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
@@ -263,19 +279,34 @@ sysc_do_restart:
263 279
264sysc_return: 280sysc_return:
265 tm SP_PSW+1(%r15),0x01 # returning to user ? 281 tm SP_PSW+1(%r15),0x01 # returning to user ?
266 bno BASED(sysc_leave) 282 bno BASED(sysc_restore)
267 tm __TI_flags+3(%r9),_TIF_WORK_SVC 283 tm __TI_flags+3(%r9),_TIF_WORK_SVC
268 bnz BASED(sysc_work) # there is work to do (signals etc.) 284 bnz BASED(sysc_work) # there is work to do (signals etc.)
285sysc_restore:
286#ifdef CONFIG_TRACE_IRQFLAGS
287 la %r1,BASED(sysc_restore_trace_psw)
288 lpsw 0(%r1)
289sysc_restore_trace:
290 TRACE_IRQS_CHECK
269 LOCKDEP_SYS_EXIT 291 LOCKDEP_SYS_EXIT
292#endif
270sysc_leave: 293sysc_leave:
271 RESTORE_ALL __LC_RETURN_PSW,1 294 RESTORE_ALL __LC_RETURN_PSW,1
295sysc_done:
296
297#ifdef CONFIG_TRACE_IRQFLAGS
298 .align 8
299 .globl sysc_restore_trace_psw
300sysc_restore_trace_psw:
301 .long 0, sysc_restore_trace + 0x80000000
302#endif
272 303
273# 304#
274# recheck if there is more work to do 305# recheck if there is more work to do
275# 306#
276sysc_work_loop: 307sysc_work_loop:
277 tm __TI_flags+3(%r9),_TIF_WORK_SVC 308 tm __TI_flags+3(%r9),_TIF_WORK_SVC
278 bz BASED(sysc_leave) # there is no work to do 309 bz BASED(sysc_restore) # there is no work to do
279# 310#
280# One of the work bits is on. Find out which one. 311# One of the work bits is on. Find out which one.
281# 312#
@@ -290,8 +321,8 @@ sysc_work:
290 bo BASED(sysc_restart) 321 bo BASED(sysc_restart)
291 tm __TI_flags+3(%r9),_TIF_SINGLE_STEP 322 tm __TI_flags+3(%r9),_TIF_SINGLE_STEP
292 bo BASED(sysc_singlestep) 323 bo BASED(sysc_singlestep)
293 LOCKDEP_SYS_EXIT 324 b BASED(sysc_restore)
294 b BASED(sysc_leave) 325sysc_work_done:
295 326
296# 327#
297# _TIF_NEED_RESCHED is set, call schedule 328# _TIF_NEED_RESCHED is set, call schedule
@@ -458,6 +489,7 @@ pgm_check_handler:
458pgm_no_vtime: 489pgm_no_vtime:
459#endif 490#endif
460 l %r9,__LC_THREAD_INFO # load pointer to thread_info struct 491 l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
492 TRACE_IRQS_OFF
461 l %r3,__LC_PGM_ILC # load program interruption code 493 l %r3,__LC_PGM_ILC # load program interruption code
462 la %r8,0x7f 494 la %r8,0x7f
463 nr %r8,%r3 495 nr %r8,%r3
@@ -497,6 +529,7 @@ pgm_per_std:
497pgm_no_vtime2: 529pgm_no_vtime2:
498#endif 530#endif
499 l %r9,__LC_THREAD_INFO # load pointer to thread_info struct 531 l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
532 TRACE_IRQS_OFF
500 l %r1,__TI_task(%r9) 533 l %r1,__TI_task(%r9)
501 mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID 534 mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID
502 mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS 535 mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS
@@ -517,15 +550,13 @@ pgm_svcper:
517 SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA 550 SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
518 CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA 551 CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
519#ifdef CONFIG_VIRT_CPU_ACCOUNTING 552#ifdef CONFIG_VIRT_CPU_ACCOUNTING
520 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
521 bz BASED(pgm_no_vtime3)
522 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER 553 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
523 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER 554 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
524 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER 555 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
525pgm_no_vtime3:
526#endif 556#endif
527 lh %r7,0x8a # get svc number from lowcore 557 lh %r7,0x8a # get svc number from lowcore
528 l %r9,__LC_THREAD_INFO # load pointer to thread_info struct 558 l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
559 TRACE_IRQS_OFF
529 l %r1,__TI_task(%r9) 560 l %r1,__TI_task(%r9)
530 mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID 561 mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID
531 mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS 562 mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS
@@ -542,7 +573,7 @@ kernel_per:
542 mvi SP_TRAP+1(%r15),0x28 # set trap indication to pgm check 573 mvi SP_TRAP+1(%r15),0x28 # set trap indication to pgm check
543 la %r2,SP_PTREGS(%r15) # address of register-save area 574 la %r2,SP_PTREGS(%r15) # address of register-save area
544 l %r1,BASED(.Lhandle_per) # load adr. of per handler 575 l %r1,BASED(.Lhandle_per) # load adr. of per handler
545 la %r14,BASED(sysc_leave) # load adr. of system return 576 la %r14,BASED(sysc_restore)# load adr. of system return
546 br %r1 # branch to do_single_step 577 br %r1 # branch to do_single_step
547 578
548/* 579/*
@@ -569,26 +600,38 @@ io_no_vtime:
569 l %r1,BASED(.Ldo_IRQ) # load address of do_IRQ 600 l %r1,BASED(.Ldo_IRQ) # load address of do_IRQ
570 la %r2,SP_PTREGS(%r15) # address of register-save area 601 la %r2,SP_PTREGS(%r15) # address of register-save area
571 basr %r14,%r1 # branch to standard irq handler 602 basr %r14,%r1 # branch to standard irq handler
572 TRACE_IRQS_ON
573
574io_return: 603io_return:
575 tm SP_PSW+1(%r15),0x01 # returning to user ? 604 tm SP_PSW+1(%r15),0x01 # returning to user ?
576#ifdef CONFIG_PREEMPT 605#ifdef CONFIG_PREEMPT
577 bno BASED(io_preempt) # no -> check for preemptive scheduling 606 bno BASED(io_preempt) # no -> check for preemptive scheduling
578#else 607#else
579 bno BASED(io_leave) # no-> skip resched & signal 608 bno BASED(io_restore) # no-> skip resched & signal
580#endif 609#endif
581 tm __TI_flags+3(%r9),_TIF_WORK_INT 610 tm __TI_flags+3(%r9),_TIF_WORK_INT
582 bnz BASED(io_work) # there is work to do (signals etc.) 611 bnz BASED(io_work) # there is work to do (signals etc.)
612io_restore:
613#ifdef CONFIG_TRACE_IRQFLAGS
614 la %r1,BASED(io_restore_trace_psw)
615 lpsw 0(%r1)
616io_restore_trace:
617 TRACE_IRQS_CHECK
583 LOCKDEP_SYS_EXIT 618 LOCKDEP_SYS_EXIT
619#endif
584io_leave: 620io_leave:
585 RESTORE_ALL __LC_RETURN_PSW,0 621 RESTORE_ALL __LC_RETURN_PSW,0
586io_done: 622io_done:
587 623
624#ifdef CONFIG_TRACE_IRQFLAGS
625 .align 8
626 .globl io_restore_trace_psw
627io_restore_trace_psw:
628 .long 0, io_restore_trace + 0x80000000
629#endif
630
588#ifdef CONFIG_PREEMPT 631#ifdef CONFIG_PREEMPT
589io_preempt: 632io_preempt:
590 icm %r0,15,__TI_precount(%r9) 633 icm %r0,15,__TI_precount(%r9)
591 bnz BASED(io_leave) 634 bnz BASED(io_restore)
592 l %r1,SP_R15(%r15) 635 l %r1,SP_R15(%r15)
593 s %r1,BASED(.Lc_spsize) 636 s %r1,BASED(.Lc_spsize)
594 mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) 637 mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
@@ -596,12 +639,14 @@ io_preempt:
596 lr %r15,%r1 639 lr %r15,%r1
597io_resume_loop: 640io_resume_loop:
598 tm __TI_flags+3(%r9),_TIF_NEED_RESCHED 641 tm __TI_flags+3(%r9),_TIF_NEED_RESCHED
599 bno BASED(io_leave) 642 bno BASED(io_restore)
600 mvc __TI_precount(4,%r9),BASED(.Lc_pactive) 643 mvc __TI_precount(4,%r9),BASED(.Lc_pactive)
644 TRACE_IRQS_ON
601 stosm __SF_EMPTY(%r15),0x03 # reenable interrupts 645 stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
602 l %r1,BASED(.Lschedule) 646 l %r1,BASED(.Lschedule)
603 basr %r14,%r1 # call schedule 647 basr %r14,%r1 # call schedule
604 stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts 648 stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
649 TRACE_IRQS_OFF
605 xc __TI_precount(4,%r9),__TI_precount(%r9) 650 xc __TI_precount(4,%r9),__TI_precount(%r9)
606 b BASED(io_resume_loop) 651 b BASED(io_resume_loop)
607#endif 652#endif
@@ -627,40 +672,42 @@ io_work_loop:
627 bo BASED(io_reschedule) 672 bo BASED(io_reschedule)
628 tm __TI_flags+3(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK) 673 tm __TI_flags+3(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)
629 bnz BASED(io_sigpending) 674 bnz BASED(io_sigpending)
630 LOCKDEP_SYS_EXIT 675 b BASED(io_restore)
631 b BASED(io_leave) 676io_work_done:
632 677
633# 678#
634# _TIF_MCCK_PENDING is set, call handler 679# _TIF_MCCK_PENDING is set, call handler
635# 680#
636io_mcck_pending: 681io_mcck_pending:
637 TRACE_IRQS_OFF
638 l %r1,BASED(.Ls390_handle_mcck) 682 l %r1,BASED(.Ls390_handle_mcck)
639 basr %r14,%r1 # TIF bit will be cleared by handler 683 basr %r14,%r1 # TIF bit will be cleared by handler
640 TRACE_IRQS_ON
641 b BASED(io_work_loop) 684 b BASED(io_work_loop)
642 685
643# 686#
644# _TIF_NEED_RESCHED is set, call schedule 687# _TIF_NEED_RESCHED is set, call schedule
645# 688#
646io_reschedule: 689io_reschedule:
690 TRACE_IRQS_ON
647 l %r1,BASED(.Lschedule) 691 l %r1,BASED(.Lschedule)
648 stosm __SF_EMPTY(%r15),0x03 # reenable interrupts 692 stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
649 basr %r14,%r1 # call scheduler 693 basr %r14,%r1 # call scheduler
650 stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts 694 stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
695 TRACE_IRQS_OFF
651 tm __TI_flags+3(%r9),_TIF_WORK_INT 696 tm __TI_flags+3(%r9),_TIF_WORK_INT
652 bz BASED(io_leave) # there is no work to do 697 bz BASED(io_restore) # there is no work to do
653 b BASED(io_work_loop) 698 b BASED(io_work_loop)
654 699
655# 700#
656# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal 701# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
657# 702#
658io_sigpending: 703io_sigpending:
704 TRACE_IRQS_ON
659 stosm __SF_EMPTY(%r15),0x03 # reenable interrupts 705 stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
660 la %r2,SP_PTREGS(%r15) # load pt_regs 706 la %r2,SP_PTREGS(%r15) # load pt_regs
661 l %r1,BASED(.Ldo_signal) 707 l %r1,BASED(.Ldo_signal)
662 basr %r14,%r1 # call do_signal 708 basr %r14,%r1 # call do_signal
663 stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts 709 stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
710 TRACE_IRQS_OFF
664 b BASED(io_work_loop) 711 b BASED(io_work_loop)
665 712
666/* 713/*
@@ -688,7 +735,6 @@ ext_no_vtime:
688 lh %r3,__LC_EXT_INT_CODE # get interruption code 735 lh %r3,__LC_EXT_INT_CODE # get interruption code
689 l %r1,BASED(.Ldo_extint) 736 l %r1,BASED(.Ldo_extint)
690 basr %r14,%r1 737 basr %r14,%r1
691 TRACE_IRQS_ON
692 b BASED(io_return) 738 b BASED(io_return)
693 739
694__critical_end: 740__critical_end:
@@ -853,15 +899,15 @@ cleanup_table_system_call:
853cleanup_table_sysc_return: 899cleanup_table_sysc_return:
854 .long sysc_return + 0x80000000, sysc_leave + 0x80000000 900 .long sysc_return + 0x80000000, sysc_leave + 0x80000000
855cleanup_table_sysc_leave: 901cleanup_table_sysc_leave:
856 .long sysc_leave + 0x80000000, sysc_work_loop + 0x80000000 902 .long sysc_leave + 0x80000000, sysc_done + 0x80000000
857cleanup_table_sysc_work_loop: 903cleanup_table_sysc_work_loop:
858 .long sysc_work_loop + 0x80000000, sysc_reschedule + 0x80000000 904 .long sysc_work_loop + 0x80000000, sysc_work_done + 0x80000000
859cleanup_table_io_return: 905cleanup_table_io_return:
860 .long io_return + 0x80000000, io_leave + 0x80000000 906 .long io_return + 0x80000000, io_leave + 0x80000000
861cleanup_table_io_leave: 907cleanup_table_io_leave:
862 .long io_leave + 0x80000000, io_done + 0x80000000 908 .long io_leave + 0x80000000, io_done + 0x80000000
863cleanup_table_io_work_loop: 909cleanup_table_io_work_loop:
864 .long io_work_loop + 0x80000000, io_mcck_pending + 0x80000000 910 .long io_work_loop + 0x80000000, io_work_done + 0x80000000
865 911
866cleanup_critical: 912cleanup_critical:
867 clc 4(4,%r12),BASED(cleanup_table_system_call) 913 clc 4(4,%r12),BASED(cleanup_table_system_call)
@@ -930,8 +976,6 @@ cleanup_system_call:
930cleanup_vtime: 976cleanup_vtime:
931 clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+12) 977 clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+12)
932 bhe BASED(cleanup_stime) 978 bhe BASED(cleanup_stime)
933 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
934 bz BASED(cleanup_novtime)
935 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER 979 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
936cleanup_stime: 980cleanup_stime:
937 clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+16) 981 clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+16)
@@ -939,7 +983,6 @@ cleanup_stime:
939 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER 983 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
940cleanup_update: 984cleanup_update:
941 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER 985 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
942cleanup_novtime:
943#endif 986#endif
944 mvc __LC_RETURN_PSW+4(4),BASED(cleanup_table_system_call+4) 987 mvc __LC_RETURN_PSW+4(4),BASED(cleanup_table_system_call+4)
945 la %r12,__LC_RETURN_PSW 988 la %r12,__LC_RETURN_PSW
@@ -978,10 +1021,10 @@ cleanup_sysc_leave:
9782: la %r12,__LC_RETURN_PSW 10212: la %r12,__LC_RETURN_PSW
979 br %r14 1022 br %r14
980cleanup_sysc_leave_insn: 1023cleanup_sysc_leave_insn:
1024 .long sysc_done - 4 + 0x80000000
981#ifdef CONFIG_VIRT_CPU_ACCOUNTING 1025#ifdef CONFIG_VIRT_CPU_ACCOUNTING
982 .long sysc_leave + 14 + 0x80000000 1026 .long sysc_done - 8 + 0x80000000
983#endif 1027#endif
984 .long sysc_leave + 10 + 0x80000000
985 1028
986cleanup_io_return: 1029cleanup_io_return:
987 mvc __LC_RETURN_PSW(4),0(%r12) 1030 mvc __LC_RETURN_PSW(4),0(%r12)
@@ -1008,10 +1051,10 @@ cleanup_io_leave:
10082: la %r12,__LC_RETURN_PSW 10512: la %r12,__LC_RETURN_PSW
1009 br %r14 1052 br %r14
1010cleanup_io_leave_insn: 1053cleanup_io_leave_insn:
1054 .long io_done - 4 + 0x80000000
1011#ifdef CONFIG_VIRT_CPU_ACCOUNTING 1055#ifdef CONFIG_VIRT_CPU_ACCOUNTING
1012 .long io_leave + 18 + 0x80000000 1056 .long io_done - 8 + 0x80000000
1013#endif 1057#endif
1014 .long io_leave + 14 + 0x80000000
1015 1058
1016/* 1059/*
1017 * Integer constants 1060 * Integer constants