Commit 061da3df authored by Michael Holzheu's avatar Michael Holzheu Committed by Martin Schwidefsky

s390/kernel: Fix smp_call_ipl_cpu() for offline CPUs

If the IPL CPU is offline, currently the pcpu_delegate() function
used by smp_call_ipl_cpu() does not work because pcpu_delegate()
modifies the lowcore of the target CPU. In case of an offline
IPL CPU currently the prefix register is zero but pcpu->lowcore
still points to the old prefix page. Therefore the lowcore changes
done by pcpu_delegate() have no effect.

With this fix pcpu_delegate() now uses memcpy_absolute() and therefore
also prepares the absolute zero lowcore if the target CPU has prefix
register zero.
Signed-off-by: default avatarMichael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 73bf463e
...@@ -297,26 +297,27 @@ static void pcpu_start_fn(struct pcpu *pcpu, void (*func)(void *), void *data) ...@@ -297,26 +297,27 @@ static void pcpu_start_fn(struct pcpu *pcpu, void (*func)(void *), void *data)
static void pcpu_delegate(struct pcpu *pcpu, void (*func)(void *), static void pcpu_delegate(struct pcpu *pcpu, void (*func)(void *),
void *data, unsigned long stack) void *data, unsigned long stack)
{ {
struct _lowcore *lc = pcpu->lowcore; struct _lowcore *lc = lowcore_ptr[pcpu - pcpu_devices];
unsigned short this_cpu; struct {
unsigned long stack;
void *func;
void *data;
unsigned long source;
} restart = { stack, func, data, stap() };
__load_psw_mask(psw_kernel_bits); __load_psw_mask(psw_kernel_bits);
this_cpu = stap(); if (pcpu->address == restart.source)
if (pcpu->address == this_cpu)
func(data); /* should not return */ func(data); /* should not return */
/* Stop target cpu (if func returns this stops the current cpu). */ /* Stop target cpu (if func returns this stops the current cpu). */
pcpu_sigp_retry(pcpu, sigp_stop, 0); pcpu_sigp_retry(pcpu, sigp_stop, 0);
/* Restart func on the target cpu and stop the current cpu. */ /* Restart func on the target cpu and stop the current cpu. */
lc->restart_stack = stack; memcpy_absolute(&lc->restart_stack, &restart, sizeof(restart));
lc->restart_fn = (unsigned long) func;
lc->restart_data = (unsigned long) data;
lc->restart_source = (unsigned long) this_cpu;
asm volatile( asm volatile(
"0: sigp 0,%0,6 # sigp restart to target cpu\n" "0: sigp 0,%0,6 # sigp restart to target cpu\n"
" brc 2,0b # busy, try again\n" " brc 2,0b # busy, try again\n"
"1: sigp 0,%1,5 # sigp stop to current cpu\n" "1: sigp 0,%1,5 # sigp stop to current cpu\n"
" brc 2,1b # busy, try again\n" " brc 2,1b # busy, try again\n"
: : "d" (pcpu->address), "d" (this_cpu) : "0", "1", "cc"); : : "d" (pcpu->address), "d" (restart.source) : "0", "1", "cc");
for (;;) ; for (;;) ;
} }
......
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