Skip to contentSkip to conversation

s390: improved machine check handling.

PATCH New Martin Schwidefsky 1 participant 1 message Jun 23, 2005 s390

lore
Share & tools
lore
#0 lore raw

PATCH 1/3 s390: improved machine check handling.

[patch 1/3] s390: improved machine check handling.

From: Heiko Carstens <[email protected]>

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.

diffstat:

 arch/s390/kernel/entry.S       |  102 +++++++++++--
 arch/s390/kernel/entry64.S     |   97 +++++++++++-
 arch/s390/kernel/process.c     |   46 +----
 arch/s390/kernel/setup.c       |   13 +
 arch/s390/kernel/smp.c         |   13 +
 drivers/s390/s390mach.c        |  321 ++++++++++++++++++++++++++++++++++++-----
 drivers/s390/s390mach.h        |   35 +++-
 include/asm-s390/lowcore.h     |    7 
 include/asm-s390/processor.h   |   52 ++----
 include/asm-s390/ptrace.h      |    2 
 include/asm-s390/system.h      |   21 +-
 include/asm-s390/thread_info.h |    2 
 12 files changed, 576 insertions(+), 135 deletions(-)
arch/s390/kernel/entry64.S +88 -9
diff -urpN linux-2.6/arch/s390/kernel/entry64.S linux-2.6-patched/arch/s390/kernel/entry64.S
@@ -7,6 +7,7 @@
  *    Author(s): Martin Schwidefsky ([email protected]),
  *               Hartmut Penner ([email protected]),
  *               Denis Joseph Barrow ([email protected],[email protected]),
+ *		 Heiko Carstens <[email protected]>
  */
 
 #include <linux/sys.h>
@@ -52,9 +53,9 @@ SP_SIZE      =  STACK_FRAME_OVERHEAD + _
 STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
 STACK_SIZE  = 1 << STACK_SHIFT
 
-_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
+_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING | \
 		 _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
-_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
+_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
 
 #define BASED(name) name-system_call(%r13)
 
@@ -114,7 +115,11 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_
 	jz	stack_overflow
 3:
 #endif
-2:	aghi    %r15,-SP_SIZE		# make room for registers & psw
+2:
+	.endm
+
+	.macro	CREATE_STACK_FRAME psworg,savearea
+	aghi    %r15,-SP_SIZE		# make room for registers & psw
 	mvc     SP_PSW(16,%r15),0(%r12)	# move user PSW to stack
 	la	%r12,\psworg
 	stg	%r2,SP_ORIG_R2(%r15)	# store original content of gpr 2
@@ -152,6 +157,13 @@ __switch_to:
         je      __switch_to_noper            # we got away without bashing TLB's
         lctlg   %c9,%c11,__THREAD_per(%r3)	# Nope we didn't
 __switch_to_noper:
+	lg	%r4,__THREAD_info(%r2)              # get thread_info of prev
+	tm	__TI_flags+7(%r4),_TIF_MCCK_PENDING # machine check pending?
+	jz	__switch_to_no_mcck
+	ni	__TI_flags+7(%r4),255-_TIF_MCCK_PENDING # clear flag in prev
+	lg	%r4,__THREAD_info(%r3)		    # get thread_info of next
+	oi	__TI_flags+7(%r4),_TIF_MCCK_PENDING # set it in next
+__switch_to_no_mcck:
         stmg    %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task
 	stg	%r15,__THREAD_ksp(%r2)	# store kernel stack to prev->tss.ksp
 	lg	%r15,__THREAD_ksp(%r3)	# load kernel stack from next->tss.ksp
@@ -176,6 +188,7 @@ system_call:
 sysc_saveall:
 	SAVE_ALL_BASE __LC_SAVE_AREA
         SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
+        CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
 	llgh    %r7,__LC_SVC_INT_CODE # get svc number from lowcore
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 sysc_vtime:
@@ -232,6 +245,8 @@ sysc_work_loop:
 # One of the work bits is on. Find out which one.
 #
 sysc_work:
+	tm	__TI_flags+7(%r9),_TIF_MCCK_PENDING
+	jo	sysc_mcck_pending
 	tm	__TI_flags+7(%r9),_TIF_NEED_RESCHED
 	jo	sysc_reschedule
 	tm	__TI_flags+7(%r9),_TIF_SIGPENDING
@@ -250,6 +265,13 @@ sysc_reschedule:        
         jg      schedule            # return point is sysc_return
 
 #
+# _TIF_MCCK_PENDING is set, call handler
+#
+sysc_mcck_pending:
+	larl	%r14,sysc_work_loop
+	jg	s390_handle_mcck    # TIF bit will be cleared by handler
+
+#
 # _TIF_SIGPENDING is set, call do_signal
 #
 sysc_sigpending:     
@@ -474,6 +496,7 @@ pgm_check_handler:
         tm      __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
         jnz     pgm_per                  # got per exception -> special case
 	SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1
+	CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
 	jz	pgm_no_vtime
@@ -512,6 +535,7 @@ pgm_per:
 #
 pgm_per_std:
 	SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1
+	CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
 	jz	pgm_no_vtime2
@@ -537,6 +561,7 @@ pgm_no_vtime2:
 #
 pgm_svcper:
 	SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
+	CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
 	jz	pgm_no_vtime3
@@ -564,6 +589,7 @@ io_int_handler:
 	stck	__LC_INT_CLOCK
 	SAVE_ALL_BASE __LC_SAVE_AREA+32
         SAVE_ALL __LC_IO_OLD_PSW,__LC_SAVE_AREA+32,0
+	CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+32
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
 	jz	io_no_vtime
@@ -621,9 +647,11 @@ io_work:
 	lgr	%r15,%r1
 #
 # One of the work bits is on. Find out which one.
-# Checked are: _TIF_SIGPENDING and _TIF_NEED_RESCHED
+# Checked are: _TIF_SIGPENDING, _TIF_NEED_RESCHED and _TIF_MCCK_PENDING
 #
 io_work_loop:
+	tm	__TI_flags+7(%r9),_TIF_MCCK_PENDING
+	jo	io_mcck_pending
 	tm	__TI_flags+7(%r9),_TIF_NEED_RESCHED
 	jo	io_reschedule
 	tm	__TI_flags+7(%r9),_TIF_SIGPENDING
@@ -631,6 +659,13 @@ io_work_loop:
 	j	io_leave
 
 #
+# _TIF_MCCK_PENDING is set, call handler
+#
+io_mcck_pending:
+	larl	%r14,io_work_loop
+	jg	s390_handle_mcck	# TIF bit will be cleared by handler
+
+#
 # _TIF_NEED_RESCHED is set, call schedule
 #	
 io_reschedule:        
@@ -661,6 +696,7 @@ ext_int_handler:
 	stck	__LC_INT_CLOCK
 	SAVE_ALL_BASE __LC_SAVE_AREA+32
         SAVE_ALL __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32,0
+	CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
 	jz	ext_no_vtime
@@ -680,18 +716,60 @@ ext_no_vtime:
  */
         .globl mcck_int_handler
 mcck_int_handler:
-	STORE_TIMER __LC_ASYNC_ENTER_TIMER
+	la	%r1,4095		# revalidate r1
+	spt	__LC_CPU_TIMER_SAVE_AREA-4095(%r1)	# revalidate cpu timer
+  	lmg     %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs
 	SAVE_ALL_BASE __LC_SAVE_AREA+64
-        SAVE_ALL __LC_MCK_OLD_PSW,__LC_SAVE_AREA+64,0
+	la	%r12,__LC_MCK_OLD_PSW
+	tm	__LC_MCCK_CODE,0x80     # system damage?
+	jo	mcck_int_main		# yes -> rest of mcck code invalid
+	tm	__LC_MCCK_CODE+5,0x02   # stored cpu timer value valid?
+	jo	0f
+	spt	__LC_LAST_UPDATE_TIMER
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
-	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
+	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
+	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
+	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_EXIT_TIMER
+0:	tm	__LC_MCCK_CODE+2,0x08	# mwp of old psw valid?
+	jno	mcck_no_vtime		# no -> no timer update
+	tm      __LC_MCK_OLD_PSW+1,0x01 # interrupting from user ?
 	jz	mcck_no_vtime
 	UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
 	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
 	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
 mcck_no_vtime:
 #endif
-	brasl   %r14,s390_do_machine_check
+0:
+	tm	__LC_MCCK_CODE+2,0x09   # mwp + ia of old psw valid?
+	jno	mcck_int_main		# no -> skip cleanup critical
+	tm      __LC_MCK_OLD_PSW+1,0x01 # test problem state bit
+	jnz	mcck_int_main		# from user -> load kernel stack
+	clc	__LC_MCK_OLD_PSW+8(8),BASED(.Lcritical_end)
+	jhe	mcck_int_main
+	clc     __LC_MCK_OLD_PSW+8(8),BASED(.Lcritical_start)
+	jl	mcck_int_main
+	brasl   %r14,cleanup_critical
+mcck_int_main:
+	lg      %r14,__LC_PANIC_STACK   # are we already on the panic stack?
+	slgr	%r14,%r15
+	srag	%r14,%r14,PAGE_SHIFT
+	jz	0f
+	lg      %r15,__LC_PANIC_STACK   # load panic stack
+0:	CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+64
+	lg	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs
+	brasl	%r14,s390_do_machine_check
+	tm	SP_PSW+1(%r15),0x01     # returning to user ?
+	jno	mcck_return
+	lg	%r1,__LC_KERNEL_STACK	# switch to kernel stack
+	aghi	%r1,-SP_SIZE
+	mvc	SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
+	xc	__SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain
+	lgr	%r15,%r1
+	stosm	__SF_EMPTY(%r15),0x04	# turn dat on
+	tm	__TI_flags+7(%r9),_TIF_MCCK_PENDING
+	jno	mcck_return
+	brasl	%r14,s390_handle_mcck
 mcck_return:
         RESTORE_ALL 0
 
@@ -775,7 +853,7 @@ cleanup_critical:
 	clc	8(8,%r12),BASED(cleanup_table_sysc_work_loop)
 	jl	0f
 	clc	8(8,%r12),BASED(cleanup_table_sysc_work_loop+8)
-	jl	cleanup_sysc_leave
+	jl	cleanup_sysc_return
 0:
 	br	%r14
 
@@ -793,6 +871,7 @@ cleanup_system_call:
 	mvc	__LC_SAVE_AREA(32),__LC_SAVE_AREA+32
 0:	stg	%r13,__LC_SAVE_AREA+40
 	SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
+	CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
 	stg	%r15,__LC_SAVE_AREA+56
 	llgh	%r7,__LC_SVC_INT_CODE
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
arch/s390/kernel/entry.S +93 -9

222 lines not on this page · raw message

arch/s390/kernel/process.c +12 -34

63 lines not on this page · raw message

arch/s390/kernel/setup.c +10 -3
diff -urpN linux-2.6/arch/s390/kernel/setup.c linux-2.6-patched/arch/s390/kernel/setup.c
@@ -414,7 +414,8 @@ setup_lowcore(void)
 	lc->program_new_psw.mask = PSW_KERNEL_BITS;
 	lc->program_new_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long)pgm_check_handler;
-	lc->mcck_new_psw.mask = PSW_KERNEL_BITS;
+	lc->mcck_new_psw.mask =
+		PSW_KERNEL_BITS & ~PSW_MASK_MCHECK & ~PSW_MASK_DAT;
 	lc->mcck_new_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long) mcck_int_handler;
 	lc->io_new_psw.mask = PSW_KERNEL_BITS;
@@ -424,12 +425,18 @@ setup_lowcore(void)
 	lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE;
 	lc->async_stack = (unsigned long)
 		__alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE;
-#ifdef CONFIG_CHECK_STACK
 	lc->panic_stack = (unsigned long)
 		__alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0) + PAGE_SIZE;
-#endif
 	lc->current_task = (unsigned long) init_thread_union.thread_info.task;
 	lc->thread_info = (unsigned long) &init_thread_union;
+#ifndef CONFIG_ARCH_S390X
+	if (MACHINE_HAS_IEEE) {
+		lc->extended_save_area_addr = (__u32)
+			__alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0);
+		/* enable extended save area */
+		ctl_set_bit(14, 29);
+	}
+#endif
 #ifdef CONFIG_ARCH_S390X
 	if (MACHINE_HAS_DIAG44)
 		lc->diag44_opcode = 0x83000044;
arch/s390/kernel/smp.c +12 -1
diff -urpN linux-2.6/arch/s390/kernel/smp.c linux-2.6-patched/arch/s390/kernel/smp.c
@@ -771,13 +771,24 @@ void __init smp_prepare_cpus(unsigned in
 
 		*(lowcore_ptr[i]) = S390_lowcore;
 		lowcore_ptr[i]->async_stack = stack + (ASYNC_SIZE);
-#ifdef CONFIG_CHECK_STACK
 		stack = __get_free_pages(GFP_KERNEL,0);
 		if (stack == 0ULL)
 			panic("smp_boot_cpus failed to allocate memory\n");
 		lowcore_ptr[i]->panic_stack = stack + (PAGE_SIZE);
+#ifndef __s390x__
+		if (MACHINE_HAS_IEEE) {
+			lowcore_ptr[i]->extended_save_area_addr =
+				(__u32) __get_free_pages(GFP_KERNEL,0);
+			if (lowcore_ptr[i]->extended_save_area_addr == 0)
+				panic("smp_boot_cpus failed to "
+				      "allocate memory\n");
+		}
 #endif
 	}
+#ifndef __s390x__
+	if (MACHINE_HAS_IEEE)
+		ctl_set_bit(14, 29); /* enable extended save area */
+#endif
 	set_prefix((u32)(unsigned long) lowcore_ptr[smp_processor_id()]);
 
 	for_each_cpu(cpu)
drivers/s390/s390mach.c +287 -34

363 lines not on this page · raw message

drivers/s390/s390mach.h +30 -5
diff -urpN linux-2.6/drivers/s390/s390mach.h linux-2.6-patched/drivers/s390/s390mach.h
@@ -16,20 +16,45 @@ struct mci {
 	__u32   sd              :  1; /* 00 system damage */
 	__u32   pd              :  1; /* 01 instruction-processing damage */
 	__u32   sr              :  1; /* 02 system recovery */
-	__u32   to_be_defined_1 :  4; /* 03-06 */
+	__u32   to_be_defined_1 :  1; /* 03 */
+	__u32   cd              :  1; /* 04 timing-facility damage */
+	__u32   ed              :  1; /* 05 external damage */
+	__u32   to_be_defined_2 :  1; /* 06 */
 	__u32   dg              :  1; /* 07 degradation */
 	__u32   w               :  1; /* 08 warning pending */
 	__u32   cp              :  1; /* 09 channel-report pending */
-	__u32   to_be_defined_2 :  6; /* 10-15 */
+	__u32   sp              :  1; /* 10 service-processor damage */
+	__u32   ck              :  1; /* 11 channel-subsystem damage */
+	__u32   to_be_defined_3 :  2; /* 12-13 */
+	__u32   b               :  1; /* 14 backed up */
+	__u32   to_be_defined_4 :  1; /* 15 */
 	__u32   se              :  1; /* 16 storage error uncorrected */
 	__u32   sc              :  1; /* 17 storage error corrected */
 	__u32   ke              :  1; /* 18 storage-key error uncorrected */
 	__u32   ds              :  1; /* 19 storage degradation */
-	__u32	to_be_defined_3 :  4; /* 20-23 */
+	__u32   wp              :  1; /* 20 psw mwp validity */
+	__u32   ms              :  1; /* 21 psw mask and key validity */
+	__u32   pm              :  1; /* 22 psw program mask and cc validity */
+	__u32   ia              :  1; /* 23 psw instruction address validity */
 	__u32   fa              :  1; /* 24 failing storage address validity */
-	__u32   to_be_defined_4 :  7; /* 25-31 */
+	__u32   to_be_defined_5 :  1; /* 25 */
+	__u32   ec              :  1; /* 26 external damage code validity */
+	__u32   fp              :  1; /* 27 floating point register validity */
+	__u32   gr              :  1; /* 28 general register validity */
+	__u32   cr              :  1; /* 29 control register validity */
+	__u32   to_be_defined_6 :  1; /* 30 */
+	__u32   st              :  1; /* 31 storage logical validity */
 	__u32   ie              :  1; /* 32 indirect storage error */
-	__u32	to_be_defined_5 : 31; /* 33-63 */
+	__u32   ar              :  1; /* 33 access register validity */
+	__u32   da              :  1; /* 34 delayed access exception */
+	__u32   to_be_defined_7 :  7; /* 35-41 */
+	__u32   pr              :  1; /* 42 tod programmable register validity */
+	__u32   fc              :  1; /* 43 fp control register validity */
+	__u32   ap              :  1; /* 44 ancillary report */
+	__u32   to_be_defined_8 :  1; /* 45 */
+	__u32   ct              :  1; /* 46 cpu timer validity */
+	__u32   cc              :  1; /* 47 clock comparator validity */
+	__u32	to_be_defined_9 : 16; /* 47-63 */
 };
 
 /*
include/asm-s390/lowcore.h +6 -1
diff -urpN linux-2.6/include/asm-s390/lowcore.h linux-2.6-patched/include/asm-s390/lowcore.h
@@ -109,10 +109,14 @@
 
 #ifndef __s390x__
 #define __LC_PFAULT_INTPARM             0x080
+#define __LC_CPU_TIMER_SAVE_AREA        0x0D8
 #define __LC_AREGS_SAVE_AREA            0x120
+#define __LC_GPREGS_SAVE_AREA           0x180
 #define __LC_CREGS_SAVE_AREA            0x1C0
 #else /* __s390x__ */
 #define __LC_PFAULT_INTPARM             0x11B8
+#define __LC_GPREGS_SAVE_AREA           0x1280
+#define __LC_CPU_TIMER_SAVE_AREA        0x1328
 #define __LC_AREGS_SAVE_AREA            0x1340
 #define __LC_CREGS_SAVE_AREA            0x1380
 #endif /* __s390x__ */
@@ -167,7 +171,8 @@ struct _lowcore
 	__u16        subchannel_nr;            /* 0x0ba */
 	__u32        io_int_parm;              /* 0x0bc */
 	__u32        io_int_word;              /* 0x0c0 */
-        __u8         pad3[0xD8-0xC4];          /* 0x0c4 */
+        __u8         pad3[0xD4-0xC4];          /* 0x0c4 */
+	__u32        extended_save_area_addr;  /* 0x0d4 */
 	__u32        cpu_timer_save_area[2];   /* 0x0d8 */
 	__u32        clock_comp_save_area[2];  /* 0x0e0 */
 	__u32        mcck_interruption_code[2]; /* 0x0e8 */
include/asm-s390/processor.h +20 -32

91 lines not on this page · raw message

include/asm-s390/ptrace.h +1 -1
diff -urpN linux-2.6/include/asm-s390/ptrace.h linux-2.6-patched/include/asm-s390/ptrace.h
@@ -276,7 +276,7 @@ typedef struct 
 #endif /* __s390x__ */
 
 #define PSW_KERNEL_BITS	(PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY | \
-			 PSW_DEFAULT_KEY)
+			 PSW_MASK_MCHECK | PSW_DEFAULT_KEY)
 #define PSW_USER_BITS	(PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME | \
 			 PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | \
 			 PSW_MASK_PSTATE | PSW_DEFAULT_KEY)
include/asm-s390/system.h +15 -6
diff -urpN linux-2.6/include/asm-s390/system.h linux-2.6-patched/include/asm-s390/system.h
@@ -16,6 +16,7 @@
 #include <asm/types.h>
 #include <asm/ptrace.h>
 #include <asm/setup.h>
+#include <asm/processor.h>
 
 #ifdef __KERNEL__
 
@@ -331,9 +332,6 @@ __cmpxchg(volatile void *ptr, unsigned l
 
 #ifdef __s390x__
 
-#define __load_psw(psw) \
-        __asm__ __volatile__("lpswe 0(%0)" : : "a" (&psw), "m" (psw) : "cc" );
-
 #define __ctl_load(array, low, high) ({ \
 	typedef struct { char _[sizeof(array)]; } addrtype; \
 	__asm__ __volatile__ ( \
@@ -390,9 +388,6 @@ __cmpxchg(volatile void *ptr, unsigned l
 
 #else /* __s390x__ */
 
-#define __load_psw(psw) \
-	__asm__ __volatile__("lpsw 0(%0)" : : "a" (&psw) : "cc" );
-
 #define __ctl_load(array, low, high) ({ \
 	typedef struct { char _[sizeof(array)]; } addrtype; \
 	__asm__ __volatile__ ( \
@@ -451,6 +446,20 @@ __cmpxchg(volatile void *ptr, unsigned l
 /* For spinlocks etc */
 #define local_irq_save(x)	((x) = local_irq_disable())
 
+/*
+ * Use to set psw mask except for the first byte which
+ * won't be changed by this function.
+ */
+static inline void
+__set_psw_mask(unsigned long mask)
+{
+	local_save_flags(mask);
+	__load_psw_mask(mask);
+}
+
+#define local_mcck_enable()  __set_psw_mask(PSW_KERNEL_BITS)
+#define local_mcck_disable() __set_psw_mask(PSW_KERNEL_BITS & ~PSW_MASK_MCHECK)
+
 #ifdef CONFIG_SMP
 
 extern void smp_ctl_set_bit(int cr, int bit);
include/asm-s390/thread_info.h +2 -0
diff -urpN linux-2.6/include/asm-s390/thread_info.h linux-2.6-patched/include/asm-s390/thread_info.h
@@ -96,6 +96,7 @@ static inline struct thread_info *curren
 #define TIF_RESTART_SVC		4	/* restart svc with new svc number */
 #define TIF_SYSCALL_AUDIT	5	/* syscall auditing active */
 #define TIF_SINGLE_STEP		6	/* deliver sigtrap on return to user */
+#define TIF_MCCK_PENDING	7	/* machine check handling is pending */
 #define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
 #define TIF_POLLING_NRFLAG	17	/* true if poll_idle() is polling 
 					   TIF_NEED_RESCHED */
@@ -109,6 +110,7 @@ static inline struct thread_info *curren
 #define _TIF_RESTART_SVC	(1<<TIF_RESTART_SVC)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SINGLE_STEP	(1<<TIF_SINGLE_STEP)
+#define _TIF_MCCK_PENDING	(1<<TIF_MCCK_PENDING)
 #define _TIF_USEDFPU		(1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_31BIT		(1<<TIF_31BIT)