aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/sclp.c
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2017-01-11 09:14:45 +0100
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2017-01-16 07:27:55 +0100
commit742dc5773cf5bbb355e4b4dd61310d5f51556477 (patch)
treec5bcd9921d22571dfd55a333c3746c44dec278a2 /arch/s390/kernel/sclp.c
parents390/topology: make "topology=off" parameter work (diff)
downloadlinux-dev-742dc5773cf5bbb355e4b4dd61310d5f51556477.tar.xz
linux-dev-742dc5773cf5bbb355e4b4dd61310d5f51556477.zip
s390/sclp: make early sclp irq handler more robust
Make the early sclp interrupt handler more robust: - disable all interrupt sub classes except for the service signal subclass - extend ctlreg0 union so it is easily possible to set the service signal subclass mask bit without using a magic number - disable lowcore protection before writing to it - make sure that all write accesses are done before the original content of control register 0 is restored, which could enable lowcore protection Reviewed-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com> 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/sclp.c')
-rw-r--r--arch/s390/kernel/sclp.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/arch/s390/kernel/sclp.c b/arch/s390/kernel/sclp.c
index f08af675f36f..745324349a7b 100644
--- a/arch/s390/kernel/sclp.c
+++ b/arch/s390/kernel/sclp.c
@@ -18,12 +18,16 @@ static bool have_linemode __section(data);
static void _sclp_wait_int(void)
{
- unsigned long cr0, cr0_new, psw_mask, addr;
+ unsigned long psw_mask, addr, flags;
psw_t psw_ext_save, psw_wait;
+ union ctlreg0 cr0, cr0_new;
- __ctl_store(cr0, 0, 0);
- cr0_new = cr0 | 0x200;
- __ctl_load(cr0_new, 0, 0);
+ raw_local_irq_save(flags);
+ __ctl_store(cr0.val, 0, 0);
+ cr0_new.val = cr0.val & ~CR0_IRQ_SUBCLASS_MASK;
+ cr0_new.lap = 0;
+ cr0_new.sssm = 1;
+ __ctl_load(cr0_new.val, 0, 0);
psw_ext_save = S390_lowcore.external_new_psw;
psw_mask = __extract_psw();
@@ -45,8 +49,9 @@ static void _sclp_wait_int(void)
: "cc", "memory");
} while (S390_lowcore.ext_int_code != EXT_IRQ_SERVICE_SIG);
- __ctl_load(cr0, 0, 0);
S390_lowcore.external_new_psw = psw_ext_save;
+ __ctl_load(cr0.val, 0, 0);
+ raw_local_irq_restore(flags);
}
static int _sclp_servc(unsigned int cmd, char *sccb)