Commit 0861b5a7 authored by Heiko Carstens's avatar Heiko Carstens Committed by Martin Schwidefsky

s390/smp: fix ipl from cpu with non-zero address

Commit af51160e ("s390/smp: initialize cpu_present_mask in
setup_arch") initializes the cpu_present_mask much earlier than
before. However the cpu detection code relies on the fact that iff
logical cpu 0 is marked present then also the corresponding physical
cpu address within the pcpu_devices array slot is valid.

Since commit 44fd2299 ("[PATCH] Register the boot-cpu in the cpu
maps earlier") this assumption is not true anymore. The patch marks
logical cpu 0 as present in common code without that architecture code
had a chance to setup the logical to physical map.

With that change the cpu detection code assumes that the physical cpu
address of cpu 0 is also 0, which is not necessarily true.
Subsequently the physical cpu address of the ipl cpu will be mapped to
a different logical cpu. If that cpu is brought online later the ipl
cpu will send itself an initial cpu reset sigp signal. This in turn
completely resets the ipl cpu and the system stops working.

A dump of such a system looks like a "store status" has been
forgotten. But actually the kernel itself removed all traces which
would allow to easily tell what went wrong.

To fix this initialize the logical to physical cpu address already in
smp_setup_processor_id(). In addition remove the initialization of the
cpu_present_mask and cpu_online_mask for cpu 0, since that has already
been done. Also add a sanity check, just in case common code will be
changed again...

The problem can be easily reproduced within a z/VM guest:

> chcpu -d 0
> vmcp ipl

Fixes: af51160e ("s390/smp: initialize cpu_present_mask in setup_arch")
Reported-by: default avatarSebastian Ott <sebott@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 d82c0d12
......@@ -909,13 +909,11 @@ void __init smp_prepare_boot_cpu(void)
{
struct pcpu *pcpu = pcpu_devices;
WARN_ON(!cpu_present(0) || !cpu_online(0));
pcpu->state = CPU_STATE_CONFIGURED;
pcpu->address = stap();
pcpu->lowcore = (struct lowcore *)(unsigned long) store_prefix();
S390_lowcore.percpu_offset = __per_cpu_offset[0];
smp_cpu_set_polarization(0, POLARIZATION_UNKNOWN);
set_cpu_present(0, true);
set_cpu_online(0, true);
}
void __init smp_cpus_done(unsigned int max_cpus)
......@@ -924,6 +922,7 @@ void __init smp_cpus_done(unsigned int max_cpus)
void __init smp_setup_processor_id(void)
{
pcpu_devices[0].address = stap();
S390_lowcore.cpu_nr = 0;
S390_lowcore.spinlock_lockval = arch_spin_lockval(0);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment