Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 742dc577 authored by Heiko Carstens's avatar Heiko Carstens Committed by Martin Schwidefsky
Browse files

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: default avatarPeter Oberparleiter <oberpar@linux.vnet.ibm.com>
Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 68cc795d
Loading
Loading
Loading
Loading
+3 −1
Original line number Original line Diff line number Diff line
@@ -62,7 +62,9 @@ union ctlreg0 {
		unsigned long	   : 4;
		unsigned long	   : 4;
		unsigned long afp  : 1; /* AFP-register control */
		unsigned long afp  : 1; /* AFP-register control */
		unsigned long vx   : 1; /* Vector enablement 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;
	};
	};
};
};


+10 −5
Original line number Original line Diff line number Diff line
@@ -18,12 +18,16 @@ static bool have_linemode __section(data);


static void _sclp_wait_int(void)
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;
	psw_t psw_ext_save, psw_wait;
	union ctlreg0 cr0, cr0_new;


	__ctl_store(cr0, 0, 0);
	raw_local_irq_save(flags);
	cr0_new = cr0 | 0x200;
	__ctl_store(cr0.val, 0, 0);
	__ctl_load(cr0_new, 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_ext_save = S390_lowcore.external_new_psw;
	psw_mask = __extract_psw();
	psw_mask = __extract_psw();
@@ -45,8 +49,9 @@ static void _sclp_wait_int(void)
			: "cc", "memory");
			: "cc", "memory");
	} while (S390_lowcore.ext_int_code != EXT_IRQ_SERVICE_SIG);
	} while (S390_lowcore.ext_int_code != EXT_IRQ_SERVICE_SIG);


	__ctl_load(cr0, 0, 0);
	S390_lowcore.external_new_psw = psw_ext_save;
	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)
static int _sclp_servc(unsigned int cmd, char *sccb)