diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/s390/include/asm/processor.h | 28 | ||||
-rw-r--r-- | arch/s390/kernel/nmi.c | 5 | ||||
-rw-r--r-- | arch/s390/lib/test_unwind.c | 6 |
3 files changed, 31 insertions, 8 deletions
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index dc17896a001a..0b625373a255 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h @@ -332,14 +332,36 @@ static inline unsigned long __extract_psw(void) return (((unsigned long) reg1) << 32) | ((unsigned long) reg2); } -static inline void local_mcck_enable(void) +static inline unsigned long __local_mcck_save(void) { - __load_psw_mask(__extract_psw() | PSW_MASK_MCHECK); + unsigned long mask = __extract_psw(); + + __load_psw_mask(mask & ~PSW_MASK_MCHECK); + return mask & PSW_MASK_MCHECK; +} + +#define local_mcck_save(mflags) \ +do { \ + typecheck(unsigned long, mflags); \ + mflags = __local_mcck_save(); \ +} while (0) + +static inline void local_mcck_restore(unsigned long mflags) +{ + unsigned long mask = __extract_psw(); + + mask &= ~PSW_MASK_MCHECK; + __load_psw_mask(mask | mflags); } static inline void local_mcck_disable(void) { - __load_psw_mask(__extract_psw() & ~PSW_MASK_MCHECK); + __local_mcck_save(); +} + +static inline void local_mcck_enable(void) +{ + __load_psw_mask(__extract_psw() | PSW_MASK_MCHECK); } /* diff --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c index 0daf0f1cdfc9..60bcb451a4eb 100644 --- a/arch/s390/kernel/nmi.c +++ b/arch/s390/kernel/nmi.c @@ -159,16 +159,17 @@ NOKPROBE_SYMBOL(s390_handle_damage); void s390_handle_mcck(void) { struct mcck_struct mcck; + unsigned long mflags; /* * Disable machine checks and get the current state of accumulated * machine checks. Afterwards delete the old state and enable machine * checks again. */ - local_mcck_disable(); + local_mcck_save(mflags); mcck = *this_cpu_ptr(&cpu_mcck); memset(this_cpu_ptr(&cpu_mcck), 0, sizeof(mcck)); - local_mcck_enable(); + local_mcck_restore(mflags); if (mcck.channel_report) crw_handle_channel_report(); diff --git a/arch/s390/lib/test_unwind.c b/arch/s390/lib/test_unwind.c index 7231bf97b93a..2848e3fb2ff5 100644 --- a/arch/s390/lib/test_unwind.c +++ b/arch/s390/lib/test_unwind.c @@ -350,15 +350,15 @@ static noinline int unwindme_func3(struct unwindme *u) /* This function must appear in the backtrace. */ static noinline int unwindme_func2(struct unwindme *u) { - unsigned long flags; + unsigned long flags, mflags; int rc; if (u->flags & UWM_SWITCH_STACK) { local_irq_save(flags); - local_mcck_disable(); + local_mcck_save(mflags); rc = call_on_stack(1, S390_lowcore.nodat_stack, int, unwindme_func3, struct unwindme *, u); - local_mcck_enable(); + local_mcck_restore(mflags); local_irq_restore(flags); return rc; } else { |