From: Heiko Carstens Date: Wed, 11 Jan 2017 08:14:45 +0000 (+0100) Subject: s390/sclp: make early sclp irq handler more robust X-Git-Tag: android-x86-8.1-r1~4095^2~43 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=742dc5773cf5bbb355e4b4dd61310d5f51556477;p=android-x86%2Fkernel.git 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 Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- diff --git a/arch/s390/include/asm/ctl_reg.h b/arch/s390/include/asm/ctl_reg.h index 8e136b88cdf4..cf4c9a106049 100644 --- a/arch/s390/include/asm/ctl_reg.h +++ b/arch/s390/include/asm/ctl_reg.h @@ -62,7 +62,9 @@ union ctlreg0 { unsigned long : 4; unsigned long afp : 1; /* AFP-register control */ unsigned long vx : 1; /* Vector enablement control */ - unsigned long : 17; + unsigned long : 7; + unsigned long sssm : 1; /* Service signal subclass mask */ + unsigned long : 9; }; }; 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)