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

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

s390/smp: avoid concurrent write to sigp status field



When a sigp instruction is issued it may store a status. This status is
currently stored in a per cpu field of the target cpu.
If multiple cpus issue a sigp instruction with the same target cpu
and a status is stored the result is not necessarily as expected.

Currently this is not an issue:
- on cpu hotplug no sigps, except "restart" and "sense" are sent to the
  target cpu.
- on external call we don't look at the status if it is stored
- on sense running the condition code "status stored" is sufficient to
  tell if a cpu is running or not

Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent fbf3c542
Loading
Loading
Loading
Loading
+7 −6
Original line number Original line Diff line number Diff line
@@ -66,7 +66,6 @@ struct pcpu {
	unsigned long panic_stack;	/* panic stack for the cpu */
	unsigned long panic_stack;	/* panic stack for the cpu */
	unsigned long ec_mask;		/* bit mask for ec_xxx functions */
	unsigned long ec_mask;		/* bit mask for ec_xxx functions */
	int state;			/* physical cpu state */
	int state;			/* physical cpu state */
	u32 status;			/* last status received via sigp */
	u16 address;			/* physical cpu address */
	u16 address;			/* physical cpu address */
};
};


@@ -99,7 +98,7 @@ static inline int __pcpu_sigp_relax(u16 addr, u8 order, u32 parm, u32 *status)
	int cc;
	int cc;


	while (1) {
	while (1) {
		cc = __pcpu_sigp(addr, order, parm, status);
		cc = __pcpu_sigp(addr, order, parm, NULL);
		if (cc != SIGP_CC_BUSY)
		if (cc != SIGP_CC_BUSY)
			return cc;
			return cc;
		cpu_relax();
		cpu_relax();
@@ -111,7 +110,7 @@ static int pcpu_sigp_retry(struct pcpu *pcpu, u8 order, u32 parm)
	int cc, retry;
	int cc, retry;


	for (retry = 0; ; retry++) {
	for (retry = 0; ; retry++) {
		cc = __pcpu_sigp(pcpu->address, order, parm, &pcpu->status);
		cc = __pcpu_sigp(pcpu->address, order, parm, NULL);
		if (cc != SIGP_CC_BUSY)
		if (cc != SIGP_CC_BUSY)
			break;
			break;
		if (retry >= 3)
		if (retry >= 3)
@@ -122,16 +121,18 @@ static int pcpu_sigp_retry(struct pcpu *pcpu, u8 order, u32 parm)


static inline int pcpu_stopped(struct pcpu *pcpu)
static inline int pcpu_stopped(struct pcpu *pcpu)
{
{
	u32 status;

	if (__pcpu_sigp(pcpu->address, SIGP_SENSE,
	if (__pcpu_sigp(pcpu->address, SIGP_SENSE,
			0, &pcpu->status) != SIGP_CC_STATUS_STORED)
			0, &status) != SIGP_CC_STATUS_STORED)
		return 0;
		return 0;
	return !!(pcpu->status & (SIGP_STATUS_CHECK_STOP|SIGP_STATUS_STOPPED));
	return !!(status & (SIGP_STATUS_CHECK_STOP|SIGP_STATUS_STOPPED));
}
}


static inline int pcpu_running(struct pcpu *pcpu)
static inline int pcpu_running(struct pcpu *pcpu)
{
{
	if (__pcpu_sigp(pcpu->address, SIGP_SENSE_RUNNING,
	if (__pcpu_sigp(pcpu->address, SIGP_SENSE_RUNNING,
			0, &pcpu->status) != SIGP_CC_STATUS_STORED)
			0, NULL) != SIGP_CC_STATUS_STORED)
		return 1;
		return 1;
	/* Status stored condition code is equivalent to cpu not running. */
	/* Status stored condition code is equivalent to cpu not running. */
	return 0;
	return 0;