aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/entry.S
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2005-06-25 17:55:30 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-25 19:24:37 -0400
commit77fa22450de00d535de2cc8be653983560828000 (patch)
tree61644edb2263c3d0db3ea9e9518c6f76a60039e0 /arch/s390/kernel/entry.S
parentf901e5d1e06b3326c100c5d0df43656311befb81 (diff)
[PATCH] s390: improved machine check handling
Improved machine check handling. Kernel is now able to receive machine checks while in kernel mode (system call, interrupt and program check handling). Also register validation is now performed. 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.S102
1 files changed, 93 insertions, 9 deletions
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index c0e09b33febe..5b262b5d869f 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -7,6 +7,7 @@
7 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), 7 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
8 * Hartmut Penner (hp@de.ibm.com), 8 * Hartmut Penner (hp@de.ibm.com),
9 * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), 9 * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
10 * Heiko Carstens <heiko.carstens@de.ibm.com>
10 */ 11 */
11 12
12#include <linux/sys.h> 13#include <linux/sys.h>
@@ -49,9 +50,9 @@ SP_ILC = STACK_FRAME_OVERHEAD + __PT_ILC
49SP_TRAP = STACK_FRAME_OVERHEAD + __PT_TRAP 50SP_TRAP = STACK_FRAME_OVERHEAD + __PT_TRAP
50SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE 51SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE
51 52
52_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ 53_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING | \
53 _TIF_RESTART_SVC | _TIF_SINGLE_STEP ) 54 _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
54_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED) 55_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
55 56
56STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER 57STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
57STACK_SIZE = 1 << STACK_SHIFT 58STACK_SIZE = 1 << STACK_SHIFT
@@ -121,7 +122,11 @@ STACK_SIZE = 1 << STACK_SHIFT
121 bz BASED(stack_overflow) 122 bz BASED(stack_overflow)
1223: 1233:
123#endif 124#endif
1242: s %r15,BASED(.Lc_spsize) # make room for registers & psw 1252:
126 .endm
127
128 .macro CREATE_STACK_FRAME psworg,savearea
129 s %r15,BASED(.Lc_spsize) # make room for registers & psw
125 mvc SP_PSW(8,%r15),0(%r12) # move user PSW to stack 130 mvc SP_PSW(8,%r15),0(%r12) # move user PSW to stack
126 la %r12,\psworg 131 la %r12,\psworg
127 st %r2,SP_ORIG_R2(%r15) # store original content of gpr 2 132 st %r2,SP_ORIG_R2(%r15) # store original content of gpr 2
@@ -161,6 +166,13 @@ __switch_to_base:
161 be __switch_to_noper-__switch_to_base(%r1) # we got away w/o bashing TLB's 166 be __switch_to_noper-__switch_to_base(%r1) # we got away w/o bashing TLB's
162 lctl %c9,%c11,__THREAD_per(%r3) # Nope we didn't 167 lctl %c9,%c11,__THREAD_per(%r3) # Nope we didn't
163__switch_to_noper: 168__switch_to_noper:
169 l %r4,__THREAD_info(%r2) # get thread_info of prev
170 tm __TI_flags+3(%r4),_TIF_MCCK_PENDING # machine check pending?
171 bz __switch_to_no_mcck-__switch_to_base(%r1)
172 ni __TI_flags+3(%r4),255-_TIF_MCCK_PENDING # clear flag in prev
173 l %r4,__THREAD_info(%r3) # get thread_info of next
174 oi __TI_flags+3(%r4),_TIF_MCCK_PENDING # set it in next
175__switch_to_no_mcck:
164 stm %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task 176 stm %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task
165 st %r15,__THREAD_ksp(%r2) # store kernel stack to prev->tss.ksp 177 st %r15,__THREAD_ksp(%r2) # store kernel stack to prev->tss.ksp
166 l %r15,__THREAD_ksp(%r3) # load kernel stack from next->tss.ksp 178 l %r15,__THREAD_ksp(%r3) # load kernel stack from next->tss.ksp
@@ -185,6 +197,7 @@ system_call:
185sysc_saveall: 197sysc_saveall:
186 SAVE_ALL_BASE __LC_SAVE_AREA 198 SAVE_ALL_BASE __LC_SAVE_AREA
187 SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 199 SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
200 CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
188 lh %r7,0x8a # get svc number from lowcore 201 lh %r7,0x8a # get svc number from lowcore
189#ifdef CONFIG_VIRT_CPU_ACCOUNTING 202#ifdef CONFIG_VIRT_CPU_ACCOUNTING
190sysc_vtime: 203sysc_vtime:
@@ -234,6 +247,8 @@ sysc_work_loop:
234# One of the work bits is on. Find out which one. 247# One of the work bits is on. Find out which one.
235# 248#
236sysc_work: 249sysc_work:
250 tm __TI_flags+3(%r9),_TIF_MCCK_PENDING
251 bo BASED(sysc_mcck_pending)
237 tm __TI_flags+3(%r9),_TIF_NEED_RESCHED 252 tm __TI_flags+3(%r9),_TIF_NEED_RESCHED
238 bo BASED(sysc_reschedule) 253 bo BASED(sysc_reschedule)
239 tm __TI_flags+3(%r9),_TIF_SIGPENDING 254 tm __TI_flags+3(%r9),_TIF_SIGPENDING
@@ -253,6 +268,14 @@ sysc_reschedule:
253 br %r1 # call scheduler 268 br %r1 # call scheduler
254 269
255# 270#
271# _TIF_MCCK_PENDING is set, call handler
272#
273sysc_mcck_pending:
274 l %r1,BASED(.Ls390_handle_mcck)
275 la %r14,BASED(sysc_work_loop)
276 br %r1 # TIF bit will be cleared by handler
277
278#
256# _TIF_SIGPENDING is set, call do_signal 279# _TIF_SIGPENDING is set, call do_signal
257# 280#
258sysc_sigpending: 281sysc_sigpending:
@@ -430,6 +453,7 @@ pgm_check_handler:
430 tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception 453 tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
431 bnz BASED(pgm_per) # got per exception -> special case 454 bnz BASED(pgm_per) # got per exception -> special case
432 SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 455 SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1
456 CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
433#ifdef CONFIG_VIRT_CPU_ACCOUNTING 457#ifdef CONFIG_VIRT_CPU_ACCOUNTING
434 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 458 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
435 bz BASED(pgm_no_vtime) 459 bz BASED(pgm_no_vtime)
@@ -468,6 +492,7 @@ pgm_per:
468# 492#
469pgm_per_std: 493pgm_per_std:
470 SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 494 SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1
495 CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
471#ifdef CONFIG_VIRT_CPU_ACCOUNTING 496#ifdef CONFIG_VIRT_CPU_ACCOUNTING
472 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 497 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
473 bz BASED(pgm_no_vtime2) 498 bz BASED(pgm_no_vtime2)
@@ -493,6 +518,7 @@ pgm_no_vtime2:
493# 518#
494pgm_svcper: 519pgm_svcper:
495 SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 520 SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
521 CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
496#ifdef CONFIG_VIRT_CPU_ACCOUNTING 522#ifdef CONFIG_VIRT_CPU_ACCOUNTING
497 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 523 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
498 bz BASED(pgm_no_vtime3) 524 bz BASED(pgm_no_vtime3)
@@ -521,6 +547,7 @@ io_int_handler:
521 stck __LC_INT_CLOCK 547 stck __LC_INT_CLOCK
522 SAVE_ALL_BASE __LC_SAVE_AREA+16 548 SAVE_ALL_BASE __LC_SAVE_AREA+16
523 SAVE_ALL __LC_IO_OLD_PSW,__LC_SAVE_AREA+16,0 549 SAVE_ALL __LC_IO_OLD_PSW,__LC_SAVE_AREA+16,0
550 CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+16
524#ifdef CONFIG_VIRT_CPU_ACCOUNTING 551#ifdef CONFIG_VIRT_CPU_ACCOUNTING
525 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 552 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
526 bz BASED(io_no_vtime) 553 bz BASED(io_no_vtime)
@@ -578,9 +605,11 @@ io_work:
578 lr %r15,%r1 605 lr %r15,%r1
579# 606#
580# One of the work bits is on. Find out which one. 607# One of the work bits is on. Find out which one.
581# Checked are: _TIF_SIGPENDING and _TIF_NEED_RESCHED 608# Checked are: _TIF_SIGPENDING, _TIF_NEED_RESCHED and _TIF_MCCK_PENDING
582# 609#
583io_work_loop: 610io_work_loop:
611 tm __TI_flags+3(%r9),_TIF_MCCK_PENDING
612 bo BASED(io_mcck_pending)
584 tm __TI_flags+3(%r9),_TIF_NEED_RESCHED 613 tm __TI_flags+3(%r9),_TIF_NEED_RESCHED
585 bo BASED(io_reschedule) 614 bo BASED(io_reschedule)
586 tm __TI_flags+3(%r9),_TIF_SIGPENDING 615 tm __TI_flags+3(%r9),_TIF_SIGPENDING
@@ -588,6 +617,14 @@ io_work_loop:
588 b BASED(io_leave) 617 b BASED(io_leave)
589 618
590# 619#
620# _TIF_MCCK_PENDING is set, call handler
621#
622io_mcck_pending:
623 l %r1,BASED(.Ls390_handle_mcck)
624 l %r14,BASED(io_work_loop)
625 br %r1 # TIF bit will be cleared by handler
626
627#
591# _TIF_NEED_RESCHED is set, call schedule 628# _TIF_NEED_RESCHED is set, call schedule
592# 629#
593io_reschedule: 630io_reschedule:
@@ -621,6 +658,7 @@ ext_int_handler:
621 stck __LC_INT_CLOCK 658 stck __LC_INT_CLOCK
622 SAVE_ALL_BASE __LC_SAVE_AREA+16 659 SAVE_ALL_BASE __LC_SAVE_AREA+16
623 SAVE_ALL __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16,0 660 SAVE_ALL __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16,0
661 CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16
624#ifdef CONFIG_VIRT_CPU_ACCOUNTING 662#ifdef CONFIG_VIRT_CPU_ACCOUNTING
625 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 663 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
626 bz BASED(ext_no_vtime) 664 bz BASED(ext_no_vtime)
@@ -642,19 +680,62 @@ ext_no_vtime:
642 680
643 .globl mcck_int_handler 681 .globl mcck_int_handler
644mcck_int_handler: 682mcck_int_handler:
645 STORE_TIMER __LC_ASYNC_ENTER_TIMER 683 spt __LC_CPU_TIMER_SAVE_AREA # revalidate cpu timer
684 lm %r0,%r15,__LC_GPREGS_SAVE_AREA # revalidate gprs
646 SAVE_ALL_BASE __LC_SAVE_AREA+32 685 SAVE_ALL_BASE __LC_SAVE_AREA+32
647 SAVE_ALL __LC_MCK_OLD_PSW,__LC_SAVE_AREA+32,0 686 la %r12,__LC_MCK_OLD_PSW
687 tm __LC_MCCK_CODE,0x80 # system damage?
688 bo BASED(mcck_int_main) # yes -> rest of mcck code invalid
689 tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid?
690 bo BASED(0f)
691 spt __LC_LAST_UPDATE_TIMER # revalidate cpu timer
648#ifdef CONFIG_VIRT_CPU_ACCOUNTING 692#ifdef CONFIG_VIRT_CPU_ACCOUNTING
649 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 693 mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
694 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
695 mvc __LC_LAST_UPDATE_TIMER(8),__LC_EXIT_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 ?
650 bz BASED(mcck_no_vtime) 699 bz BASED(mcck_no_vtime)
651 UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER 700 UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
652 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER 701 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
653 mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER 702 mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
654mcck_no_vtime: 703mcck_no_vtime:
655#endif 704#endif
7050:
706 tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid?
707 bno BASED(mcck_int_main) # no -> skip cleanup critical
708 tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit
709 bnz BASED(mcck_int_main) # from user -> load async stack
710 clc __LC_MCK_OLD_PSW+4(4),BASED(.Lcritical_end)
711 bhe BASED(mcck_int_main)
712 clc __LC_MCK_OLD_PSW+4(4),BASED(.Lcritical_start)
713 bl BASED(mcck_int_main)
714 l %r14,BASED(.Lcleanup_critical)
715 basr %r14,%r14
716mcck_int_main:
717 l %r14,__LC_PANIC_STACK # are we already on the panic stack?
718 slr %r14,%r15
719 sra %r14,PAGE_SHIFT
720 be BASED(0f)
721 l %r15,__LC_PANIC_STACK # load panic stack
7220: CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+32
723 l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
724 la %r2,SP_PTREGS(%r15) # load pt_regs
656 l %r1,BASED(.Ls390_mcck) 725 l %r1,BASED(.Ls390_mcck)
657 basr %r14,%r1 # call machine check handler 726 basr %r14,%r1 # call machine check handler
727 tm SP_PSW+1(%r15),0x01 # returning to user ?
728 bno BASED(mcck_return)
729 l %r1,__LC_KERNEL_STACK # switch to kernel stack
730 s %r1,BASED(.Lc_spsize)
731 mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
732 xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
733 lr %r15,%r1
734 stosm __SF_EMPTY(%r15),0x04 # turn dat on
735 tm __TI_flags+3(%r9),_TIF_MCCK_PENDING
736 bno BASED(mcck_return)
737 l %r1,BASED(.Ls390_handle_mcck)
738 basr %r14,%r1 # call machine check handler
658mcck_return: 739mcck_return:
659 RESTORE_ALL 0 740 RESTORE_ALL 0
660 741
@@ -742,7 +823,7 @@ cleanup_critical:
742 clc 4(4,%r12),BASED(cleanup_table_sysc_work_loop) 823 clc 4(4,%r12),BASED(cleanup_table_sysc_work_loop)
743 bl BASED(0f) 824 bl BASED(0f)
744 clc 4(4,%r12),BASED(cleanup_table_sysc_work_loop+4) 825 clc 4(4,%r12),BASED(cleanup_table_sysc_work_loop+4)
745 bl BASED(cleanup_sysc_leave) 826 bl BASED(cleanup_sysc_return)
7460: 8270:
747 br %r14 828 br %r14
748 829
@@ -760,6 +841,7 @@ cleanup_system_call:
760 mvc __LC_SAVE_AREA(16),__LC_SAVE_AREA+16 841 mvc __LC_SAVE_AREA(16),__LC_SAVE_AREA+16
7610: st %r13,__LC_SAVE_AREA+20 8420: st %r13,__LC_SAVE_AREA+20
762 SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 843 SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
844 CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
763 st %r15,__LC_SAVE_AREA+28 845 st %r15,__LC_SAVE_AREA+28
764 lh %r7,0x8a 846 lh %r7,0x8a
765#ifdef CONFIG_VIRT_CPU_ACCOUNTING 847#ifdef CONFIG_VIRT_CPU_ACCOUNTING
@@ -834,6 +916,8 @@ cleanup_sysc_leave_insn:
834 * Symbol constants 916 * Symbol constants
835 */ 917 */
836.Ls390_mcck: .long s390_do_machine_check 918.Ls390_mcck: .long s390_do_machine_check
919.Ls390_handle_mcck:
920 .long s390_handle_mcck
837.Ldo_IRQ: .long do_IRQ 921.Ldo_IRQ: .long do_IRQ
838.Ldo_extint: .long do_extint 922.Ldo_extint: .long do_extint
839.Ldo_signal: .long do_signal 923.Ldo_signal: .long do_signal