aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--arch/s390/kernel/entry.S102
-rw-r--r--arch/s390/kernel/entry64.S97
-rw-r--r--arch/s390/kernel/process.c46
-rw-r--r--arch/s390/kernel/setup.c13
-rw-r--r--arch/s390/kernel/smp.c13
-rw-r--r--drivers/s390/s390mach.c321
-rw-r--r--drivers/s390/s390mach.h35
-rw-r--r--include/asm-s390/lowcore.h7
-rw-r--r--include/asm-s390/processor.h52
-rw-r--r--include/asm-s390/ptrace.h2
-rw-r--r--include/asm-s390/system.h21
-rw-r--r--include/asm-s390/thread_info.h2
12 files changed, 576 insertions, 135 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
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 51527ab8c8f9..57ca75d0ad7f 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.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>
@@ -52,9 +53,9 @@ SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE
52STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER 53STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
53STACK_SIZE = 1 << STACK_SHIFT 54STACK_SIZE = 1 << STACK_SHIFT
54 55
55_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ 56_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING | \
56 _TIF_RESTART_SVC | _TIF_SINGLE_STEP ) 57 _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
57_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED) 58_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
58 59
59#define BASED(name) name-system_call(%r13) 60#define BASED(name) name-system_call(%r13)
60 61
@@ -114,7 +115,11 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
114 jz stack_overflow 115 jz stack_overflow
1153: 1163:
116#endif 117#endif
1172: aghi %r15,-SP_SIZE # make room for registers & psw 1182:
119 .endm
120
121 .macro CREATE_STACK_FRAME psworg,savearea
122 aghi %r15,-SP_SIZE # make room for registers & psw
118 mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack 123 mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack
119 la %r12,\psworg 124 la %r12,\psworg
120 stg %r2,SP_ORIG_R2(%r15) # store original content of gpr 2 125 stg %r2,SP_ORIG_R2(%r15) # store original content of gpr 2
@@ -152,6 +157,13 @@ __switch_to:
152 je __switch_to_noper # we got away without bashing TLB's 157 je __switch_to_noper # we got away without bashing TLB's
153 lctlg %c9,%c11,__THREAD_per(%r3) # Nope we didn't 158 lctlg %c9,%c11,__THREAD_per(%r3) # Nope we didn't
154__switch_to_noper: 159__switch_to_noper:
160 lg %r4,__THREAD_info(%r2) # get thread_info of prev
161 tm __TI_flags+7(%r4),_TIF_MCCK_PENDING # machine check pending?
162 jz __switch_to_no_mcck
163 ni __TI_flags+7(%r4),255-_TIF_MCCK_PENDING # clear flag in prev
164 lg %r4,__THREAD_info(%r3) # get thread_info of next
165 oi __TI_flags+7(%r4),_TIF_MCCK_PENDING # set it in next
166__switch_to_no_mcck:
155 stmg %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task 167 stmg %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task
156 stg %r15,__THREAD_ksp(%r2) # store kernel stack to prev->tss.ksp 168 stg %r15,__THREAD_ksp(%r2) # store kernel stack to prev->tss.ksp
157 lg %r15,__THREAD_ksp(%r3) # load kernel stack from next->tss.ksp 169 lg %r15,__THREAD_ksp(%r3) # load kernel stack from next->tss.ksp
@@ -176,6 +188,7 @@ system_call:
176sysc_saveall: 188sysc_saveall:
177 SAVE_ALL_BASE __LC_SAVE_AREA 189 SAVE_ALL_BASE __LC_SAVE_AREA
178 SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 190 SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
191 CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
179 llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore 192 llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore
180#ifdef CONFIG_VIRT_CPU_ACCOUNTING 193#ifdef CONFIG_VIRT_CPU_ACCOUNTING
181sysc_vtime: 194sysc_vtime:
@@ -232,6 +245,8 @@ sysc_work_loop:
232# One of the work bits is on. Find out which one. 245# One of the work bits is on. Find out which one.
233# 246#
234sysc_work: 247sysc_work:
248 tm __TI_flags+7(%r9),_TIF_MCCK_PENDING
249 jo sysc_mcck_pending
235 tm __TI_flags+7(%r9),_TIF_NEED_RESCHED 250 tm __TI_flags+7(%r9),_TIF_NEED_RESCHED
236 jo sysc_reschedule 251 jo sysc_reschedule
237 tm __TI_flags+7(%r9),_TIF_SIGPENDING 252 tm __TI_flags+7(%r9),_TIF_SIGPENDING
@@ -250,6 +265,13 @@ sysc_reschedule:
250 jg schedule # return point is sysc_return 265 jg schedule # return point is sysc_return
251 266
252# 267#
268# _TIF_MCCK_PENDING is set, call handler
269#
270sysc_mcck_pending:
271 larl %r14,sysc_work_loop
272 jg s390_handle_mcck # TIF bit will be cleared by handler
273
274#
253# _TIF_SIGPENDING is set, call do_signal 275# _TIF_SIGPENDING is set, call do_signal
254# 276#
255sysc_sigpending: 277sysc_sigpending:
@@ -474,6 +496,7 @@ pgm_check_handler:
474 tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception 496 tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
475 jnz pgm_per # got per exception -> special case 497 jnz pgm_per # got per exception -> special case
476 SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 498 SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1
499 CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
477#ifdef CONFIG_VIRT_CPU_ACCOUNTING 500#ifdef CONFIG_VIRT_CPU_ACCOUNTING
478 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 501 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
479 jz pgm_no_vtime 502 jz pgm_no_vtime
@@ -512,6 +535,7 @@ pgm_per:
512# 535#
513pgm_per_std: 536pgm_per_std:
514 SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 537 SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1
538 CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
515#ifdef CONFIG_VIRT_CPU_ACCOUNTING 539#ifdef CONFIG_VIRT_CPU_ACCOUNTING
516 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 540 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
517 jz pgm_no_vtime2 541 jz pgm_no_vtime2
@@ -537,6 +561,7 @@ pgm_no_vtime2:
537# 561#
538pgm_svcper: 562pgm_svcper:
539 SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 563 SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
564 CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
540#ifdef CONFIG_VIRT_CPU_ACCOUNTING 565#ifdef CONFIG_VIRT_CPU_ACCOUNTING
541 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 566 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
542 jz pgm_no_vtime3 567 jz pgm_no_vtime3
@@ -564,6 +589,7 @@ io_int_handler:
564 stck __LC_INT_CLOCK 589 stck __LC_INT_CLOCK
565 SAVE_ALL_BASE __LC_SAVE_AREA+32 590 SAVE_ALL_BASE __LC_SAVE_AREA+32
566 SAVE_ALL __LC_IO_OLD_PSW,__LC_SAVE_AREA+32,0 591 SAVE_ALL __LC_IO_OLD_PSW,__LC_SAVE_AREA+32,0
592 CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+32
567#ifdef CONFIG_VIRT_CPU_ACCOUNTING 593#ifdef CONFIG_VIRT_CPU_ACCOUNTING
568 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 594 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
569 jz io_no_vtime 595 jz io_no_vtime
@@ -621,9 +647,11 @@ io_work:
621 lgr %r15,%r1 647 lgr %r15,%r1
622# 648#
623# One of the work bits is on. Find out which one. 649# One of the work bits is on. Find out which one.
624# Checked are: _TIF_SIGPENDING and _TIF_NEED_RESCHED 650# Checked are: _TIF_SIGPENDING, _TIF_NEED_RESCHED and _TIF_MCCK_PENDING
625# 651#
626io_work_loop: 652io_work_loop:
653 tm __TI_flags+7(%r9),_TIF_MCCK_PENDING
654 jo io_mcck_pending
627 tm __TI_flags+7(%r9),_TIF_NEED_RESCHED 655 tm __TI_flags+7(%r9),_TIF_NEED_RESCHED
628 jo io_reschedule 656 jo io_reschedule
629 tm __TI_flags+7(%r9),_TIF_SIGPENDING 657 tm __TI_flags+7(%r9),_TIF_SIGPENDING
@@ -631,6 +659,13 @@ io_work_loop:
631 j io_leave 659 j io_leave
632 660
633# 661#
662# _TIF_MCCK_PENDING is set, call handler
663#
664io_mcck_pending:
665 larl %r14,io_work_loop
666 jg s390_handle_mcck # TIF bit will be cleared by handler
667
668#
634# _TIF_NEED_RESCHED is set, call schedule 669# _TIF_NEED_RESCHED is set, call schedule
635# 670#
636io_reschedule: 671io_reschedule:
@@ -661,6 +696,7 @@ ext_int_handler:
661 stck __LC_INT_CLOCK 696 stck __LC_INT_CLOCK
662 SAVE_ALL_BASE __LC_SAVE_AREA+32 697 SAVE_ALL_BASE __LC_SAVE_AREA+32
663 SAVE_ALL __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32,0 698 SAVE_ALL __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32,0
699 CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32
664#ifdef CONFIG_VIRT_CPU_ACCOUNTING 700#ifdef CONFIG_VIRT_CPU_ACCOUNTING
665 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 701 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
666 jz ext_no_vtime 702 jz ext_no_vtime
@@ -680,18 +716,60 @@ ext_no_vtime:
680 */ 716 */
681 .globl mcck_int_handler 717 .globl mcck_int_handler
682mcck_int_handler: 718mcck_int_handler:
683 STORE_TIMER __LC_ASYNC_ENTER_TIMER 719 la %r1,4095 # revalidate r1
720 spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer
721 lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs
684 SAVE_ALL_BASE __LC_SAVE_AREA+64 722 SAVE_ALL_BASE __LC_SAVE_AREA+64
685 SAVE_ALL __LC_MCK_OLD_PSW,__LC_SAVE_AREA+64,0 723 la %r12,__LC_MCK_OLD_PSW
724 tm __LC_MCCK_CODE,0x80 # system damage?
725 jo mcck_int_main # yes -> rest of mcck code invalid
726 tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid?
727 jo 0f
728 spt __LC_LAST_UPDATE_TIMER
686#ifdef CONFIG_VIRT_CPU_ACCOUNTING 729#ifdef CONFIG_VIRT_CPU_ACCOUNTING
687 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 730 mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
731 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
732 mvc __LC_LAST_UPDATE_TIMER(8),__LC_EXIT_TIMER
7330: tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid?
734 jno mcck_no_vtime # no -> no timer update
735 tm __LC_MCK_OLD_PSW+1,0x01 # interrupting from user ?
688 jz mcck_no_vtime 736 jz mcck_no_vtime
689 UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER 737 UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
690 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER 738 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
691 mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER 739 mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
692mcck_no_vtime: 740mcck_no_vtime:
693#endif 741#endif
694 brasl %r14,s390_do_machine_check 7420:
743 tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid?
744 jno mcck_int_main # no -> skip cleanup critical
745 tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit
746 jnz mcck_int_main # from user -> load kernel stack
747 clc __LC_MCK_OLD_PSW+8(8),BASED(.Lcritical_end)
748 jhe mcck_int_main
749 clc __LC_MCK_OLD_PSW+8(8),BASED(.Lcritical_start)
750 jl mcck_int_main
751 brasl %r14,cleanup_critical
752mcck_int_main:
753 lg %r14,__LC_PANIC_STACK # are we already on the panic stack?
754 slgr %r14,%r15
755 srag %r14,%r14,PAGE_SHIFT
756 jz 0f
757 lg %r15,__LC_PANIC_STACK # load panic stack
7580: CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+64
759 lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
760 la %r2,SP_PTREGS(%r15) # load pt_regs
761 brasl %r14,s390_do_machine_check
762 tm SP_PSW+1(%r15),0x01 # returning to user ?
763 jno mcck_return
764 lg %r1,__LC_KERNEL_STACK # switch to kernel stack
765 aghi %r1,-SP_SIZE
766 mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
767 xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain
768 lgr %r15,%r1
769 stosm __SF_EMPTY(%r15),0x04 # turn dat on
770 tm __TI_flags+7(%r9),_TIF_MCCK_PENDING
771 jno mcck_return
772 brasl %r14,s390_handle_mcck
695mcck_return: 773mcck_return:
696 RESTORE_ALL 0 774 RESTORE_ALL 0
697 775
@@ -775,7 +853,7 @@ cleanup_critical:
775 clc 8(8,%r12),BASED(cleanup_table_sysc_work_loop) 853 clc 8(8,%r12),BASED(cleanup_table_sysc_work_loop)
776 jl 0f 854 jl 0f
777 clc 8(8,%r12),BASED(cleanup_table_sysc_work_loop+8) 855 clc 8(8,%r12),BASED(cleanup_table_sysc_work_loop+8)
778 jl cleanup_sysc_leave 856 jl cleanup_sysc_return
7790: 8570:
780 br %r14 858 br %r14
781 859
@@ -793,6 +871,7 @@ cleanup_system_call:
793 mvc __LC_SAVE_AREA(32),__LC_SAVE_AREA+32 871 mvc __LC_SAVE_AREA(32),__LC_SAVE_AREA+32
7940: stg %r13,__LC_SAVE_AREA+40 8720: stg %r13,__LC_SAVE_AREA+40
795 SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 873 SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
874 CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
796 stg %r15,__LC_SAVE_AREA+56 875 stg %r15,__LC_SAVE_AREA+56
797 llgh %r7,__LC_SVC_INT_CODE 876 llgh %r7,__LC_SVC_INT_CODE
798#ifdef CONFIG_VIRT_CPU_ACCOUNTING 877#ifdef CONFIG_VIRT_CPU_ACCOUNTING
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 7aea25d6e300..9f3dff6c0b72 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -91,13 +91,12 @@ void do_monitor_call(struct pt_regs *regs, long interruption_code)
91 (void *)(long) smp_processor_id()); 91 (void *)(long) smp_processor_id());
92} 92}
93 93
94extern void s390_handle_mcck(void);
94/* 95/*
95 * The idle loop on a S390... 96 * The idle loop on a S390...
96 */ 97 */
97void default_idle(void) 98void default_idle(void)
98{ 99{
99 psw_t wait_psw;
100 unsigned long reg;
101 int cpu, rc; 100 int cpu, rc;
102 101
103 local_irq_disable(); 102 local_irq_disable();
@@ -125,38 +124,17 @@ void default_idle(void)
125 cpu_die(); 124 cpu_die();
126#endif 125#endif
127 126
128 /* 127 local_mcck_disable();
129 * Wait for external, I/O or machine check interrupt and 128 if (test_thread_flag(TIF_MCCK_PENDING)) {
130 * switch off machine check bit after the wait has ended. 129 local_mcck_enable();
131 */ 130 local_irq_enable();
132 wait_psw.mask = PSW_KERNEL_BITS | PSW_MASK_MCHECK | PSW_MASK_WAIT | 131 s390_handle_mcck();
133 PSW_MASK_IO | PSW_MASK_EXT; 132 return;
134#ifndef CONFIG_ARCH_S390X 133 }
135 asm volatile ( 134
136 " basr %0,0\n" 135 /* Wait for external, I/O or machine check interrupt. */
137 "0: la %0,1f-0b(%0)\n" 136 __load_psw_mask(PSW_KERNEL_BITS | PSW_MASK_WAIT |
138 " st %0,4(%1)\n" 137 PSW_MASK_IO | PSW_MASK_EXT);
139 " oi 4(%1),0x80\n"
140 " lpsw 0(%1)\n"
141 "1: la %0,2f-1b(%0)\n"
142 " st %0,4(%1)\n"
143 " oi 4(%1),0x80\n"
144 " ni 1(%1),0xf9\n"
145 " lpsw 0(%1)\n"
146 "2:"
147 : "=&a" (reg) : "a" (&wait_psw) : "memory", "cc" );
148#else /* CONFIG_ARCH_S390X */
149 asm volatile (
150 " larl %0,0f\n"
151 " stg %0,8(%1)\n"
152 " lpswe 0(%1)\n"
153 "0: larl %0,1f\n"
154 " stg %0,8(%1)\n"
155 " ni 1(%1),0xf9\n"
156 " lpswe 0(%1)\n"
157 "1:"
158 : "=&a" (reg) : "a" (&wait_psw) : "memory", "cc" );
159#endif /* CONFIG_ARCH_S390X */
160} 138}
161 139
162void cpu_idle(void) 140void cpu_idle(void)
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index df83215beac3..eb7be0ad7175 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -414,7 +414,8 @@ setup_lowcore(void)
414 lc->program_new_psw.mask = PSW_KERNEL_BITS; 414 lc->program_new_psw.mask = PSW_KERNEL_BITS;
415 lc->program_new_psw.addr = 415 lc->program_new_psw.addr =
416 PSW_ADDR_AMODE | (unsigned long)pgm_check_handler; 416 PSW_ADDR_AMODE | (unsigned long)pgm_check_handler;
417 lc->mcck_new_psw.mask = PSW_KERNEL_BITS; 417 lc->mcck_new_psw.mask =
418 PSW_KERNEL_BITS & ~PSW_MASK_MCHECK & ~PSW_MASK_DAT;
418 lc->mcck_new_psw.addr = 419 lc->mcck_new_psw.addr =
419 PSW_ADDR_AMODE | (unsigned long) mcck_int_handler; 420 PSW_ADDR_AMODE | (unsigned long) mcck_int_handler;
420 lc->io_new_psw.mask = PSW_KERNEL_BITS; 421 lc->io_new_psw.mask = PSW_KERNEL_BITS;
@@ -424,12 +425,18 @@ setup_lowcore(void)
424 lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE; 425 lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE;
425 lc->async_stack = (unsigned long) 426 lc->async_stack = (unsigned long)
426 __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE; 427 __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE;
427#ifdef CONFIG_CHECK_STACK
428 lc->panic_stack = (unsigned long) 428 lc->panic_stack = (unsigned long)
429 __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0) + PAGE_SIZE; 429 __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0) + PAGE_SIZE;
430#endif
431 lc->current_task = (unsigned long) init_thread_union.thread_info.task; 430 lc->current_task = (unsigned long) init_thread_union.thread_info.task;
432 lc->thread_info = (unsigned long) &init_thread_union; 431 lc->thread_info = (unsigned long) &init_thread_union;
432#ifndef CONFIG_ARCH_S390X
433 if (MACHINE_HAS_IEEE) {
434 lc->extended_save_area_addr = (__u32)
435 __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0);
436 /* enable extended save area */
437 ctl_set_bit(14, 29);
438 }
439#endif
433#ifdef CONFIG_ARCH_S390X 440#ifdef CONFIG_ARCH_S390X
434 if (MACHINE_HAS_DIAG44) 441 if (MACHINE_HAS_DIAG44)
435 lc->diag44_opcode = 0x83000044; 442 lc->diag44_opcode = 0x83000044;
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 93c71fef99dc..50c335067cfe 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -773,13 +773,24 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
773 773
774 *(lowcore_ptr[i]) = S390_lowcore; 774 *(lowcore_ptr[i]) = S390_lowcore;
775 lowcore_ptr[i]->async_stack = stack + (ASYNC_SIZE); 775 lowcore_ptr[i]->async_stack = stack + (ASYNC_SIZE);
776#ifdef CONFIG_CHECK_STACK
777 stack = __get_free_pages(GFP_KERNEL,0); 776 stack = __get_free_pages(GFP_KERNEL,0);
778 if (stack == 0ULL) 777 if (stack == 0ULL)
779 panic("smp_boot_cpus failed to allocate memory\n"); 778 panic("smp_boot_cpus failed to allocate memory\n");
780 lowcore_ptr[i]->panic_stack = stack + (PAGE_SIZE); 779 lowcore_ptr[i]->panic_stack = stack + (PAGE_SIZE);
780#ifndef __s390x__
781 if (MACHINE_HAS_IEEE) {
782 lowcore_ptr[i]->extended_save_area_addr =
783 (__u32) __get_free_pages(GFP_KERNEL,0);
784 if (lowcore_ptr[i]->extended_save_area_addr == 0)
785 panic("smp_boot_cpus failed to "
786 "allocate memory\n");
787 }
781#endif 788#endif
782 } 789 }
790#ifndef __s390x__
791 if (MACHINE_HAS_IEEE)
792 ctl_set_bit(14, 29); /* enable extended save area */
793#endif
783 set_prefix((u32)(unsigned long) lowcore_ptr[smp_processor_id()]); 794 set_prefix((u32)(unsigned long) lowcore_ptr[smp_processor_id()]);
784 795
785 for_each_cpu(cpu) 796 for_each_cpu(cpu)
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c
index ffa996c8a908..5bb255e02acc 100644
--- a/drivers/s390/s390mach.c
+++ b/drivers/s390/s390mach.c
@@ -31,14 +31,14 @@ extern void css_reiterate_subchannels(void);
31extern struct workqueue_struct *slow_path_wq; 31extern struct workqueue_struct *slow_path_wq;
32extern struct work_struct slow_path_work; 32extern struct work_struct slow_path_work;
33 33
34static void 34static NORET_TYPE void
35s390_handle_damage(char *msg) 35s390_handle_damage(char *msg)
36{ 36{
37 printk(KERN_EMERG "%s\n", msg);
38#ifdef CONFIG_SMP 37#ifdef CONFIG_SMP
39 smp_send_stop(); 38 smp_send_stop();
40#endif 39#endif
41 disabled_wait((unsigned long) __builtin_return_address(0)); 40 disabled_wait((unsigned long) __builtin_return_address(0));
41 for(;;);
42} 42}
43 43
44/* 44/*
@@ -122,40 +122,39 @@ repeat:
122 return 0; 122 return 0;
123} 123}
124 124
125struct mcck_struct {
126 int kill_task;
127 int channel_report;
128 int warning;
129 unsigned long long mcck_code;
130};
131
132static DEFINE_PER_CPU(struct mcck_struct, cpu_mcck);
133
125/* 134/*
126 * machine check handler. 135 * Main machine check handler function. Will be called with interrupts enabled
136 * or disabled and machine checks enabled or disabled.
127 */ 137 */
128void 138void
129s390_do_machine_check(void) 139s390_handle_mcck(void)
130{ 140{
131 struct mci *mci; 141 unsigned long flags;
132 142 struct mcck_struct mcck;
133 mci = (struct mci *) &S390_lowcore.mcck_interruption_code;
134 143
135 if (mci->sd) /* system damage */ 144 /*
136 s390_handle_damage("received system damage machine check\n"); 145 * Disable machine checks and get the current state of accumulated
146 * machine checks. Afterwards delete the old state and enable machine
147 * checks again.
148 */
149 local_irq_save(flags);
150 local_mcck_disable();
151 mcck = __get_cpu_var(cpu_mcck);
152 memset(&__get_cpu_var(cpu_mcck), 0, sizeof(struct mcck_struct));
153 clear_thread_flag(TIF_MCCK_PENDING);
154 local_mcck_enable();
155 local_irq_restore(flags);
137 156
138 if (mci->pd) /* instruction processing damage */ 157 if (mcck.channel_report)
139 s390_handle_damage("received instruction processing "
140 "damage machine check\n");
141
142 if (mci->se) /* storage error uncorrected */
143 s390_handle_damage("received storage error uncorrected "
144 "machine check\n");
145
146 if (mci->sc) /* storage error corrected */
147 printk(KERN_WARNING
148 "received storage error corrected machine check\n");
149
150 if (mci->ke) /* storage key-error uncorrected */
151 s390_handle_damage("received storage key-error uncorrected "
152 "machine check\n");
153
154 if (mci->ds && mci->fa) /* storage degradation */
155 s390_handle_damage("received storage degradation machine "
156 "check\n");
157
158 if (mci->cp) /* channel report word pending */
159 up(&m_sem); 158 up(&m_sem);
160 159
161#ifdef CONFIG_MACHCHK_WARNING 160#ifdef CONFIG_MACHCHK_WARNING
@@ -168,7 +167,7 @@ s390_do_machine_check(void)
168 * On VM we only get one interrupt per virtally presented machinecheck. 167 * On VM we only get one interrupt per virtally presented machinecheck.
169 * Though one suffices, we may get one interrupt per (virtual) processor. 168 * Though one suffices, we may get one interrupt per (virtual) processor.
170 */ 169 */
171 if (mci->w) { /* WARNING pending ? */ 170 if (mcck.warning) { /* WARNING pending ? */
172 static int mchchk_wng_posted = 0; 171 static int mchchk_wng_posted = 0;
173 /* 172 /*
174 * Use single machine clear, as we cannot handle smp right now 173 * Use single machine clear, as we cannot handle smp right now
@@ -178,6 +177,261 @@ s390_do_machine_check(void)
178 kill_proc(1, SIGPWR, 1); 177 kill_proc(1, SIGPWR, 1);
179 } 178 }
180#endif 179#endif
180
181 if (mcck.kill_task) {
182 local_irq_enable();
183 printk(KERN_EMERG "mcck: Terminating task because of machine "
184 "malfunction (code 0x%016llx).\n", mcck.mcck_code);
185 printk(KERN_EMERG "mcck: task: %s, pid: %d.\n",
186 current->comm, current->pid);
187 do_exit(SIGSEGV);
188 }
189}
190
191/*
192 * returns 0 if all registers could be validated
193 * returns 1 otherwise
194 */
195static int
196s390_revalidate_registers(struct mci *mci)
197{
198 int kill_task;
199 u64 tmpclock;
200 u64 zero;
201 void *fpt_save_area, *fpt_creg_save_area;
202
203 kill_task = 0;
204 zero = 0;
205 /* General purpose registers */
206 if (!mci->gr)
207 /*
208 * General purpose registers couldn't be restored and have
209 * unknown contents. Process needs to be terminated.
210 */
211 kill_task = 1;
212
213 /* Revalidate floating point registers */
214 if (!mci->fp)
215 /*
216 * Floating point registers can't be restored and
217 * therefore the process needs to be terminated.
218 */
219 kill_task = 1;
220
221#ifndef __s390x__
222 asm volatile("ld 0,0(%0)\n"
223 "ld 2,8(%0)\n"
224 "ld 4,16(%0)\n"
225 "ld 6,24(%0)"
226 : : "a" (&S390_lowcore.floating_pt_save_area));
227#endif
228
229 if (MACHINE_HAS_IEEE) {
230#ifdef __s390x__
231 fpt_save_area = &S390_lowcore.floating_pt_save_area;
232 fpt_creg_save_area = &S390_lowcore.fpt_creg_save_area;
233#else
234 fpt_save_area = (void *) S390_lowcore.extended_save_area_addr;
235 fpt_creg_save_area = fpt_save_area+128;
236#endif
237 /* Floating point control register */
238 if (!mci->fc) {
239 /*
240 * Floating point control register can't be restored.
241 * Task will be terminated.
242 */
243 asm volatile ("lfpc 0(%0)" : : "a" (&zero));
244 kill_task = 1;
245
246 }
247 else
248 asm volatile (
249 "lfpc 0(%0)"
250 : : "a" (fpt_creg_save_area));
251
252 asm volatile("ld 0,0(%0)\n"
253 "ld 1,8(%0)\n"
254 "ld 2,16(%0)\n"
255 "ld 3,24(%0)\n"
256 "ld 4,32(%0)\n"
257 "ld 5,40(%0)\n"
258 "ld 6,48(%0)\n"
259 "ld 7,56(%0)\n"
260 "ld 8,64(%0)\n"
261 "ld 9,72(%0)\n"
262 "ld 10,80(%0)\n"
263 "ld 11,88(%0)\n"
264 "ld 12,96(%0)\n"
265 "ld 13,104(%0)\n"
266 "ld 14,112(%0)\n"
267 "ld 15,120(%0)\n"
268 : : "a" (fpt_save_area));
269 }
270
271 /* Revalidate access registers */
272 asm volatile("lam 0,15,0(%0)"
273 : : "a" (&S390_lowcore.access_regs_save_area));
274 if (!mci->ar)
275 /*
276 * Access registers have unknown contents.
277 * Terminating task.
278 */
279 kill_task = 1;
280
281 /* Revalidate control registers */
282 if (!mci->cr)
283 /*
284 * Control registers have unknown contents.
285 * Can't recover and therefore stopping machine.
286 */
287 s390_handle_damage("invalid control registers.");
288 else
289#ifdef __s390x__
290 asm volatile("lctlg 0,15,0(%0)"
291 : : "a" (&S390_lowcore.cregs_save_area));
292#else
293 asm volatile("lctl 0,15,0(%0)"
294 : : "a" (&S390_lowcore.cregs_save_area));
295#endif
296
297 /*
298 * We don't even try to revalidate the TOD register, since we simply
299 * can't write something sensible into that register.
300 */
301
302#ifdef __s390x__
303 /*
304 * See if we can revalidate the TOD programmable register with its
305 * old contents (should be zero) otherwise set it to zero.
306 */
307 if (!mci->pr)
308 asm volatile("sr 0,0\n"
309 "sckpf"
310 : : : "0", "cc");
311 else
312 asm volatile(
313 "l 0,0(%0)\n"
314 "sckpf"
315 : : "a" (&S390_lowcore.tod_progreg_save_area) : "0", "cc");
316#endif
317
318 /* Revalidate clock comparator register */
319 asm volatile ("stck 0(%1)\n"
320 "sckc 0(%1)"
321 : "=m" (tmpclock) : "a" (&(tmpclock)) : "cc", "memory");
322
323 /* Check if old PSW is valid */
324 if (!mci->wp)
325 /*
326 * Can't tell if we come from user or kernel mode
327 * -> stopping machine.
328 */
329 s390_handle_damage("old psw invalid.");
330
331 if (!mci->ms || !mci->pm || !mci->ia)
332 kill_task = 1;
333
334 return kill_task;
335}
336
337/*
338 * machine check handler.
339 */
340void
341s390_do_machine_check(struct pt_regs *regs)
342{
343 struct mci *mci;
344 struct mcck_struct *mcck;
345 int umode;
346
347 mci = (struct mci *) &S390_lowcore.mcck_interruption_code;
348 mcck = &__get_cpu_var(cpu_mcck);
349 umode = user_mode(regs);
350
351 if (mci->sd)
352 /* System damage -> stopping machine */
353 s390_handle_damage("received system damage machine check.");
354
355 if (mci->pd) {
356 if (mci->b) {
357 /* Processing backup -> verify if we can survive this */
358 u64 z_mcic, o_mcic, t_mcic;
359#ifdef __s390x__
360 z_mcic = (1ULL<<63 | 1ULL<<59 | 1ULL<<29);
361 o_mcic = (1ULL<<43 | 1ULL<<42 | 1ULL<<41 | 1ULL<<40 |
362 1ULL<<36 | 1ULL<<35 | 1ULL<<34 | 1ULL<<32 |
363 1ULL<<30 | 1ULL<<21 | 1ULL<<20 | 1ULL<<17 |
364 1ULL<<16);
365#else
366 z_mcic = (1ULL<<63 | 1ULL<<59 | 1ULL<<57 | 1ULL<<50 |
367 1ULL<<29);
368 o_mcic = (1ULL<<43 | 1ULL<<42 | 1ULL<<41 | 1ULL<<40 |
369 1ULL<<36 | 1ULL<<35 | 1ULL<<34 | 1ULL<<32 |
370 1ULL<<30 | 1ULL<<20 | 1ULL<<17 | 1ULL<<16);
371#endif
372 t_mcic = *(u64 *)mci;
373
374 if (((t_mcic & z_mcic) != 0) ||
375 ((t_mcic & o_mcic) != o_mcic)) {
376 s390_handle_damage("processing backup machine "
377 "check with damage.");
378 }
379 if (!umode)
380 s390_handle_damage("processing backup machine "
381 "check in kernel mode.");
382 mcck->kill_task = 1;
383 mcck->mcck_code = *(unsigned long long *) mci;
384 }
385 else {
386 /* Processing damage -> stopping machine */
387 s390_handle_damage("received instruction processing "
388 "damage machine check.");
389 }
390 }
391 if (s390_revalidate_registers(mci)) {
392 if (umode) {
393 /*
394 * Couldn't restore all register contents while in
395 * user mode -> mark task for termination.
396 */
397 mcck->kill_task = 1;
398 mcck->mcck_code = *(unsigned long long *) mci;
399 set_thread_flag(TIF_MCCK_PENDING);
400 }
401 else
402 /*
403 * Couldn't restore all register contents while in
404 * kernel mode -> stopping machine.
405 */
406 s390_handle_damage("unable to revalidate registers.");
407 }
408
409 if (mci->se)
410 /* Storage error uncorrected */
411 s390_handle_damage("received storage error uncorrected "
412 "machine check.");
413
414 if (mci->ke)
415 /* Storage key-error uncorrected */
416 s390_handle_damage("received storage key-error uncorrected "
417 "machine check.");
418
419 if (mci->ds && mci->fa)
420 /* Storage degradation */
421 s390_handle_damage("received storage degradation machine "
422 "check.");
423
424 if (mci->cp) {
425 /* Channel report word pending */
426 mcck->channel_report = 1;
427 set_thread_flag(TIF_MCCK_PENDING);
428 }
429
430 if (mci->w) {
431 /* Warning pending */
432 mcck->warning = 1;
433 set_thread_flag(TIF_MCCK_PENDING);
434 }
181} 435}
182 436
183/* 437/*
@@ -189,9 +443,8 @@ static int
189machine_check_init(void) 443machine_check_init(void)
190{ 444{
191 init_MUTEX_LOCKED(&m_sem); 445 init_MUTEX_LOCKED(&m_sem);
192 ctl_clear_bit(14, 25); /* disable damage MCH */ 446 ctl_clear_bit(14, 25); /* disable external damage MCH */
193 ctl_set_bit(14, 26); /* enable degradation MCH */ 447 ctl_set_bit(14, 27); /* enable system recovery MCH */
194 ctl_set_bit(14, 27); /* enable system recovery MCH */
195#ifdef CONFIG_MACHCHK_WARNING 448#ifdef CONFIG_MACHCHK_WARNING
196 ctl_set_bit(14, 24); /* enable warning MCH */ 449 ctl_set_bit(14, 24); /* enable warning MCH */
197#endif 450#endif
diff --git a/drivers/s390/s390mach.h b/drivers/s390/s390mach.h
index 7e26f0f1b0dc..4eaa70179182 100644
--- a/drivers/s390/s390mach.h
+++ b/drivers/s390/s390mach.h
@@ -16,20 +16,45 @@ struct mci {
16 __u32 sd : 1; /* 00 system damage */ 16 __u32 sd : 1; /* 00 system damage */
17 __u32 pd : 1; /* 01 instruction-processing damage */ 17 __u32 pd : 1; /* 01 instruction-processing damage */
18 __u32 sr : 1; /* 02 system recovery */ 18 __u32 sr : 1; /* 02 system recovery */
19 __u32 to_be_defined_1 : 4; /* 03-06 */ 19 __u32 to_be_defined_1 : 1; /* 03 */
20 __u32 cd : 1; /* 04 timing-facility damage */
21 __u32 ed : 1; /* 05 external damage */
22 __u32 to_be_defined_2 : 1; /* 06 */
20 __u32 dg : 1; /* 07 degradation */ 23 __u32 dg : 1; /* 07 degradation */
21 __u32 w : 1; /* 08 warning pending */ 24 __u32 w : 1; /* 08 warning pending */
22 __u32 cp : 1; /* 09 channel-report pending */ 25 __u32 cp : 1; /* 09 channel-report pending */
23 __u32 to_be_defined_2 : 6; /* 10-15 */ 26 __u32 sp : 1; /* 10 service-processor damage */
27 __u32 ck : 1; /* 11 channel-subsystem damage */
28 __u32 to_be_defined_3 : 2; /* 12-13 */
29 __u32 b : 1; /* 14 backed up */
30 __u32 to_be_defined_4 : 1; /* 15 */
24 __u32 se : 1; /* 16 storage error uncorrected */ 31 __u32 se : 1; /* 16 storage error uncorrected */
25 __u32 sc : 1; /* 17 storage error corrected */ 32 __u32 sc : 1; /* 17 storage error corrected */
26 __u32 ke : 1; /* 18 storage-key error uncorrected */ 33 __u32 ke : 1; /* 18 storage-key error uncorrected */
27 __u32 ds : 1; /* 19 storage degradation */ 34 __u32 ds : 1; /* 19 storage degradation */
28 __u32 to_be_defined_3 : 4; /* 20-23 */ 35 __u32 wp : 1; /* 20 psw mwp validity */
36 __u32 ms : 1; /* 21 psw mask and key validity */
37 __u32 pm : 1; /* 22 psw program mask and cc validity */
38 __u32 ia : 1; /* 23 psw instruction address validity */
29 __u32 fa : 1; /* 24 failing storage address validity */ 39 __u32 fa : 1; /* 24 failing storage address validity */
30 __u32 to_be_defined_4 : 7; /* 25-31 */ 40 __u32 to_be_defined_5 : 1; /* 25 */
41 __u32 ec : 1; /* 26 external damage code validity */
42 __u32 fp : 1; /* 27 floating point register validity */
43 __u32 gr : 1; /* 28 general register validity */
44 __u32 cr : 1; /* 29 control register validity */
45 __u32 to_be_defined_6 : 1; /* 30 */
46 __u32 st : 1; /* 31 storage logical validity */
31 __u32 ie : 1; /* 32 indirect storage error */ 47 __u32 ie : 1; /* 32 indirect storage error */
32 __u32 to_be_defined_5 : 31; /* 33-63 */ 48 __u32 ar : 1; /* 33 access register validity */
49 __u32 da : 1; /* 34 delayed access exception */
50 __u32 to_be_defined_7 : 7; /* 35-41 */
51 __u32 pr : 1; /* 42 tod programmable register validity */
52 __u32 fc : 1; /* 43 fp control register validity */
53 __u32 ap : 1; /* 44 ancillary report */
54 __u32 to_be_defined_8 : 1; /* 45 */
55 __u32 ct : 1; /* 46 cpu timer validity */
56 __u32 cc : 1; /* 47 clock comparator validity */
57 __u32 to_be_defined_9 : 16; /* 47-63 */
33}; 58};
34 59
35/* 60/*
diff --git a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h
index df5172fc589d..76b5b19c0ae2 100644
--- a/include/asm-s390/lowcore.h
+++ b/include/asm-s390/lowcore.h
@@ -109,10 +109,14 @@
109 109
110#ifndef __s390x__ 110#ifndef __s390x__
111#define __LC_PFAULT_INTPARM 0x080 111#define __LC_PFAULT_INTPARM 0x080
112#define __LC_CPU_TIMER_SAVE_AREA 0x0D8
112#define __LC_AREGS_SAVE_AREA 0x120 113#define __LC_AREGS_SAVE_AREA 0x120
114#define __LC_GPREGS_SAVE_AREA 0x180
113#define __LC_CREGS_SAVE_AREA 0x1C0 115#define __LC_CREGS_SAVE_AREA 0x1C0
114#else /* __s390x__ */ 116#else /* __s390x__ */
115#define __LC_PFAULT_INTPARM 0x11B8 117#define __LC_PFAULT_INTPARM 0x11B8
118#define __LC_GPREGS_SAVE_AREA 0x1280
119#define __LC_CPU_TIMER_SAVE_AREA 0x1328
116#define __LC_AREGS_SAVE_AREA 0x1340 120#define __LC_AREGS_SAVE_AREA 0x1340
117#define __LC_CREGS_SAVE_AREA 0x1380 121#define __LC_CREGS_SAVE_AREA 0x1380
118#endif /* __s390x__ */ 122#endif /* __s390x__ */
@@ -167,7 +171,8 @@ struct _lowcore
167 __u16 subchannel_nr; /* 0x0ba */ 171 __u16 subchannel_nr; /* 0x0ba */
168 __u32 io_int_parm; /* 0x0bc */ 172 __u32 io_int_parm; /* 0x0bc */
169 __u32 io_int_word; /* 0x0c0 */ 173 __u32 io_int_word; /* 0x0c0 */
170 __u8 pad3[0xD8-0xC4]; /* 0x0c4 */ 174 __u8 pad3[0xD4-0xC4]; /* 0x0c4 */
175 __u32 extended_save_area_addr; /* 0x0d4 */
171 __u32 cpu_timer_save_area[2]; /* 0x0d8 */ 176 __u32 cpu_timer_save_area[2]; /* 0x0d8 */
172 __u32 clock_comp_save_area[2]; /* 0x0e0 */ 177 __u32 clock_comp_save_area[2]; /* 0x0e0 */
173 __u32 mcck_interruption_code[2]; /* 0x0e8 */ 178 __u32 mcck_interruption_code[2]; /* 0x0e8 */
diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h
index fb46e9090b50..8bd14de69e35 100644
--- a/include/asm-s390/processor.h
+++ b/include/asm-s390/processor.h
@@ -207,6 +207,18 @@ unsigned long get_wchan(struct task_struct *p);
207#endif /* __s390x__ */ 207#endif /* __s390x__ */
208 208
209/* 209/*
210 * Set PSW to specified value.
211 */
212static inline void __load_psw(psw_t psw)
213{
214#ifndef __s390x__
215 asm volatile ("lpsw 0(%0)" : : "a" (&psw), "m" (psw) : "cc" );
216#else
217 asm volatile ("lpswe 0(%0)" : : "a" (&psw), "m" (psw) : "cc" );
218#endif
219}
220
221/*
210 * Set PSW mask to specified value, while leaving the 222 * Set PSW mask to specified value, while leaving the
211 * PSW addr pointing to the next instruction. 223 * PSW addr pointing to the next instruction.
212 */ 224 */
@@ -214,8 +226,8 @@ unsigned long get_wchan(struct task_struct *p);
214static inline void __load_psw_mask (unsigned long mask) 226static inline void __load_psw_mask (unsigned long mask)
215{ 227{
216 unsigned long addr; 228 unsigned long addr;
217
218 psw_t psw; 229 psw_t psw;
230
219 psw.mask = mask; 231 psw.mask = mask;
220 232
221#ifndef __s390x__ 233#ifndef __s390x__
@@ -241,30 +253,8 @@ static inline void __load_psw_mask (unsigned long mask)
241 */ 253 */
242static inline void enabled_wait(void) 254static inline void enabled_wait(void)
243{ 255{
244 unsigned long reg; 256 __load_psw_mask(PSW_BASE_BITS | PSW_MASK_IO | PSW_MASK_EXT |
245 psw_t wait_psw; 257 PSW_MASK_MCHECK | PSW_MASK_WAIT | PSW_DEFAULT_KEY);
246
247 wait_psw.mask = PSW_BASE_BITS | PSW_MASK_IO | PSW_MASK_EXT |
248 PSW_MASK_MCHECK | PSW_MASK_WAIT | PSW_DEFAULT_KEY;
249#ifndef __s390x__
250 asm volatile (
251 " basr %0,0\n"
252 "0: la %0,1f-0b(%0)\n"
253 " st %0,4(%1)\n"
254 " oi 4(%1),0x80\n"
255 " lpsw 0(%1)\n"
256 "1:"
257 : "=&a" (reg) : "a" (&wait_psw), "m" (wait_psw)
258 : "memory", "cc" );
259#else /* __s390x__ */
260 asm volatile (
261 " larl %0,0f\n"
262 " stg %0,8(%1)\n"
263 " lpswe 0(%1)\n"
264 "0:"
265 : "=&a" (reg) : "a" (&wait_psw), "m" (wait_psw)
266 : "memory", "cc" );
267#endif /* __s390x__ */
268} 258}
269 259
270/* 260/*
@@ -273,13 +263,11 @@ static inline void enabled_wait(void)
273 263
274static inline void disabled_wait(unsigned long code) 264static inline void disabled_wait(unsigned long code)
275{ 265{
276 char psw_buffer[2*sizeof(psw_t)];
277 unsigned long ctl_buf; 266 unsigned long ctl_buf;
278 psw_t *dw_psw = (psw_t *)(((unsigned long) &psw_buffer+sizeof(psw_t)-1) 267 psw_t dw_psw;
279 & -sizeof(psw_t));
280 268
281 dw_psw->mask = PSW_BASE_BITS | PSW_MASK_WAIT; 269 dw_psw.mask = PSW_BASE_BITS | PSW_MASK_WAIT;
282 dw_psw->addr = code; 270 dw_psw.addr = code;
283 /* 271 /*
284 * Store status and then load disabled wait psw, 272 * Store status and then load disabled wait psw,
285 * the processor is dead afterwards 273 * the processor is dead afterwards
@@ -301,7 +289,7 @@ static inline void disabled_wait(unsigned long code)
301 " oi 0x1c0,0x10\n" /* fake protection bit */ 289 " oi 0x1c0,0x10\n" /* fake protection bit */
302 " lpsw 0(%1)" 290 " lpsw 0(%1)"
303 : "=m" (ctl_buf) 291 : "=m" (ctl_buf)
304 : "a" (dw_psw), "a" (&ctl_buf), "m" (dw_psw) : "cc" ); 292 : "a" (&dw_psw), "a" (&ctl_buf), "m" (dw_psw) : "cc" );
305#else /* __s390x__ */ 293#else /* __s390x__ */
306 asm volatile (" stctg 0,0,0(%2)\n" 294 asm volatile (" stctg 0,0,0(%2)\n"
307 " ni 4(%2),0xef\n" /* switch off protection */ 295 " ni 4(%2),0xef\n" /* switch off protection */
@@ -333,7 +321,7 @@ static inline void disabled_wait(unsigned long code)
333 " oi 0x384(1),0x10\n" /* fake protection bit */ 321 " oi 0x384(1),0x10\n" /* fake protection bit */
334 " lpswe 0(%1)" 322 " lpswe 0(%1)"
335 : "=m" (ctl_buf) 323 : "=m" (ctl_buf)
336 : "a" (dw_psw), "a" (&ctl_buf), 324 : "a" (&dw_psw), "a" (&ctl_buf),
337 "m" (dw_psw) : "cc", "0", "1"); 325 "m" (dw_psw) : "cc", "0", "1");
338#endif /* __s390x__ */ 326#endif /* __s390x__ */
339} 327}
diff --git a/include/asm-s390/ptrace.h b/include/asm-s390/ptrace.h
index 4eff8f2e3bf1..fc7c96edc697 100644
--- a/include/asm-s390/ptrace.h
+++ b/include/asm-s390/ptrace.h
@@ -276,7 +276,7 @@ typedef struct
276#endif /* __s390x__ */ 276#endif /* __s390x__ */
277 277
278#define PSW_KERNEL_BITS (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY | \ 278#define PSW_KERNEL_BITS (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY | \
279 PSW_DEFAULT_KEY) 279 PSW_MASK_MCHECK | PSW_DEFAULT_KEY)
280#define PSW_USER_BITS (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME | \ 280#define PSW_USER_BITS (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME | \
281 PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | \ 281 PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | \
282 PSW_MASK_PSTATE | PSW_DEFAULT_KEY) 282 PSW_MASK_PSTATE | PSW_DEFAULT_KEY)
diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h
index 81514d76edcf..e3cb3ce1d24a 100644
--- a/include/asm-s390/system.h
+++ b/include/asm-s390/system.h
@@ -16,6 +16,7 @@
16#include <asm/types.h> 16#include <asm/types.h>
17#include <asm/ptrace.h> 17#include <asm/ptrace.h>
18#include <asm/setup.h> 18#include <asm/setup.h>
19#include <asm/processor.h>
19 20
20#ifdef __KERNEL__ 21#ifdef __KERNEL__
21 22
@@ -331,9 +332,6 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
331 332
332#ifdef __s390x__ 333#ifdef __s390x__
333 334
334#define __load_psw(psw) \
335 __asm__ __volatile__("lpswe 0(%0)" : : "a" (&psw), "m" (psw) : "cc" );
336
337#define __ctl_load(array, low, high) ({ \ 335#define __ctl_load(array, low, high) ({ \
338 typedef struct { char _[sizeof(array)]; } addrtype; \ 336 typedef struct { char _[sizeof(array)]; } addrtype; \
339 __asm__ __volatile__ ( \ 337 __asm__ __volatile__ ( \
@@ -390,9 +388,6 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
390 388
391#else /* __s390x__ */ 389#else /* __s390x__ */
392 390
393#define __load_psw(psw) \
394 __asm__ __volatile__("lpsw 0(%0)" : : "a" (&psw) : "cc" );
395
396#define __ctl_load(array, low, high) ({ \ 391#define __ctl_load(array, low, high) ({ \
397 typedef struct { char _[sizeof(array)]; } addrtype; \ 392 typedef struct { char _[sizeof(array)]; } addrtype; \
398 __asm__ __volatile__ ( \ 393 __asm__ __volatile__ ( \
@@ -451,6 +446,20 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
451/* For spinlocks etc */ 446/* For spinlocks etc */
452#define local_irq_save(x) ((x) = local_irq_disable()) 447#define local_irq_save(x) ((x) = local_irq_disable())
453 448
449/*
450 * Use to set psw mask except for the first byte which
451 * won't be changed by this function.
452 */
453static inline void
454__set_psw_mask(unsigned long mask)
455{
456 local_save_flags(mask);
457 __load_psw_mask(mask);
458}
459
460#define local_mcck_enable() __set_psw_mask(PSW_KERNEL_BITS)
461#define local_mcck_disable() __set_psw_mask(PSW_KERNEL_BITS & ~PSW_MASK_MCHECK)
462
454#ifdef CONFIG_SMP 463#ifdef CONFIG_SMP
455 464
456extern void smp_ctl_set_bit(int cr, int bit); 465extern void smp_ctl_set_bit(int cr, int bit);
diff --git a/include/asm-s390/thread_info.h b/include/asm-s390/thread_info.h
index fe101d41e849..6c18a3f24316 100644
--- a/include/asm-s390/thread_info.h
+++ b/include/asm-s390/thread_info.h
@@ -96,6 +96,7 @@ static inline struct thread_info *current_thread_info(void)
96#define TIF_RESTART_SVC 4 /* restart svc with new svc number */ 96#define TIF_RESTART_SVC 4 /* restart svc with new svc number */
97#define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */ 97#define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */
98#define TIF_SINGLE_STEP 6 /* deliver sigtrap on return to user */ 98#define TIF_SINGLE_STEP 6 /* deliver sigtrap on return to user */
99#define TIF_MCCK_PENDING 7 /* machine check handling is pending */
99#define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */ 100#define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */
100#define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling 101#define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling
101 TIF_NEED_RESCHED */ 102 TIF_NEED_RESCHED */
@@ -109,6 +110,7 @@ static inline struct thread_info *current_thread_info(void)
109#define _TIF_RESTART_SVC (1<<TIF_RESTART_SVC) 110#define _TIF_RESTART_SVC (1<<TIF_RESTART_SVC)
110#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT) 111#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
111#define _TIF_SINGLE_STEP (1<<TIF_SINGLE_STEP) 112#define _TIF_SINGLE_STEP (1<<TIF_SINGLE_STEP)
113#define _TIF_MCCK_PENDING (1<<TIF_MCCK_PENDING)
112#define _TIF_USEDFPU (1<<TIF_USEDFPU) 114#define _TIF_USEDFPU (1<<TIF_USEDFPU)
113#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) 115#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
114#define _TIF_31BIT (1<<TIF_31BIT) 116#define _TIF_31BIT (1<<TIF_31BIT)