Skip to content

Commit

Permalink
ARM: 7405/1: kexec: call platform_cpu_kill on the killer rather than …
Browse files Browse the repository at this point in the history
…the victim

When performing a kexec on an SMP system, the secondary cores are stopped
by calling machine_shutdown(), which in turn issues IPIs to offline the
other CPUs. Unfortunately, this isn't enough to reboot the cores into
a new kernel (since they are just executing a cpu_relax loop somewhere
in memory) so we make use of platform_cpu_kill, part of the CPU hotplug
implementation, to place the cores somewhere safe. This function expects
to be called on the killing CPU for each core that it takes out.

This patch moves the platform_cpu_kill callback out of the IPI handler
and into smp_send_stop, therefore ensuring that it executes on the
killing CPU rather than on the victim, matching what the hotplug code
requires.

Cc: stable@vger.kernel.org
Reported-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
  • Loading branch information
Will Deacon authored and Russell King committed Apr 28, 2012
1 parent 6a1c531 commit 6fa99b7
Showing 1 changed file with 17 additions and 11 deletions.
28 changes: 17 additions & 11 deletions arch/arm/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -510,10 +510,6 @@ static void ipi_cpu_stop(unsigned int cpu)
local_fiq_disable();
local_irq_disable();

#ifdef CONFIG_HOTPLUG_CPU
platform_cpu_kill(cpu);
#endif

while (1)
cpu_relax();
}
Expand Down Expand Up @@ -576,17 +572,25 @@ void smp_send_reschedule(int cpu)
smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE);
}

#ifdef CONFIG_HOTPLUG_CPU
static void smp_kill_cpus(cpumask_t *mask)
{
unsigned int cpu;
for_each_cpu(cpu, mask)
platform_cpu_kill(cpu);
}
#else
static void smp_kill_cpus(cpumask_t *mask) { }
#endif

void smp_send_stop(void)
{
unsigned long timeout;
struct cpumask mask;

if (num_online_cpus() > 1) {
struct cpumask mask;
cpumask_copy(&mask, cpu_online_mask);
cpumask_clear_cpu(smp_processor_id(), &mask);

smp_cross_call(&mask, IPI_CPU_STOP);
}
cpumask_copy(&mask, cpu_online_mask);
cpumask_clear_cpu(smp_processor_id(), &mask);
smp_cross_call(&mask, IPI_CPU_STOP);

/* Wait up to one second for other CPUs to stop */
timeout = USEC_PER_SEC;
Expand All @@ -595,6 +599,8 @@ void smp_send_stop(void)

if (num_online_cpus() > 1)
pr_warning("SMP: failed to stop secondary CPUs\n");

smp_kill_cpus(&mask);
}

/*
Expand Down

0 comments on commit 6fa99b7

Please sign in to comment.