提交 9acf73b7 编写于 作者: H Heiko Carstens 提交者: Martin Schwidefsky

s390/smp: lost IPIs on cpu hotplug

IPIs might be lost when a cpu gets brought offline:

When stop_machine executes its state machine there is a race window
for the state STOPMACHINE_DISABLE_IRQ where the to be brought offline
cpu might already have irqs disabled but a different cpu still may
have irqs enabled.
If the enabled cpu receives an interrupt and as a result sends an IPI
to the to be offlined cpu in its bottom halve context, the IPI won't
be noticed before the cpu is offline.

In fact the race window is much larger since there is no guarantee
when an IPI will be received.

To fix this check for enqueued but not yet received IPIs in the
cpu_disable() path and call the respective handlers before the cpu
is marked offline.
Reported-by: NJuergen Doelle <juergen.doelle@de.ibm.com>
Signed-off-by: NHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: NMartin Schwidefsky <schwidefsky@de.ibm.com>
上级 576ebd74
...@@ -428,34 +428,27 @@ void smp_stop_cpu(void) ...@@ -428,34 +428,27 @@ void smp_stop_cpu(void)
* This is the main routine where commands issued by other * This is the main routine where commands issued by other
* cpus are handled. * cpus are handled.
*/ */
static void do_ext_call_interrupt(struct ext_code ext_code, static void smp_handle_ext_call(void)
unsigned int param32, unsigned long param64)
{ {
unsigned long bits; unsigned long bits;
int cpu;
cpu = smp_processor_id();
if (ext_code.code == 0x1202)
inc_irq_stat(IRQEXT_EXC);
else
inc_irq_stat(IRQEXT_EMS);
/*
* handle bit signal external calls
*/
bits = xchg(&pcpu_devices[cpu].ec_mask, 0);
/* handle bit signal external calls */
bits = xchg(&pcpu_devices[smp_processor_id()].ec_mask, 0);
if (test_bit(ec_stop_cpu, &bits)) if (test_bit(ec_stop_cpu, &bits))
smp_stop_cpu(); smp_stop_cpu();
if (test_bit(ec_schedule, &bits)) if (test_bit(ec_schedule, &bits))
scheduler_ipi(); scheduler_ipi();
if (test_bit(ec_call_function, &bits)) if (test_bit(ec_call_function, &bits))
generic_smp_call_function_interrupt(); generic_smp_call_function_interrupt();
if (test_bit(ec_call_function_single, &bits)) if (test_bit(ec_call_function_single, &bits))
generic_smp_call_function_single_interrupt(); generic_smp_call_function_single_interrupt();
}
static void do_ext_call_interrupt(struct ext_code ext_code,
unsigned int param32, unsigned long param64)
{
inc_irq_stat(ext_code.code == 0x1202 ? IRQEXT_EXC : IRQEXT_EMS);
smp_handle_ext_call();
} }
void arch_send_call_function_ipi_mask(const struct cpumask *mask) void arch_send_call_function_ipi_mask(const struct cpumask *mask)
...@@ -760,6 +753,8 @@ int __cpu_disable(void) ...@@ -760,6 +753,8 @@ int __cpu_disable(void)
{ {
unsigned long cregs[16]; unsigned long cregs[16];
/* Handle possible pending IPIs */
smp_handle_ext_call();
set_cpu_online(smp_processor_id(), false); set_cpu_online(smp_processor_id(), false);
/* Disable pseudo page faults on this cpu. */ /* Disable pseudo page faults on this cpu. */
pfault_fini(); pfault_fini();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册