Skip to contentSkip to conversation

ARM: Stop secondary cpus in machine_halt()

PATCH New Olof Johansson 2 participants 7 messages Jul 1, 2010 – Jul 26, 2010 Arm (32-bit)

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 ARM: Stop secondary cpus in machine_halt()

ARM doesn't spin down secondary cpus on halt, which results in interrupts being delivered even after the "System halted" message, etc.

Change that to use smp_send_stop() to halt them. Also, change the smp_send_stop() on ARM to not do a stack dump when stopping.

---
 arch/arm/kernel/process.c |    6 ++++++
 arch/arm/kernel/smp.c     |   10 ++++++----
 2 files changed, 12 insertions(+), 4 deletions(-)
arch/arm/kernel/process.c +6 -0
index acf5e6f..203fc1b 100644
@@ -191,6 +191,12 @@ __setup("reboot=", reboot_setup);
 
 void machine_halt(void)
 {
+#ifdef CONFIG_SMP
+	smp_send_stop();
+#endif
+	printk(KERN_EMERG "System halted, OK to turn off power\n");
+	local_irq_disable();
+	while (1) ;
 }
 
 
arch/arm/kernel/smp.c +6 -4
index b8c3d0f..5496dea 100644
@@ -467,10 +467,12 @@ static DEFINE_SPINLOCK(stop_lock);
  */
 static void ipi_cpu_stop(unsigned int cpu)
 {
-	spin_lock(&stop_lock);
-	printk(KERN_CRIT "CPU%u: stopping\n", cpu);
-	dump_stack();
-	spin_unlock(&stop_lock);
+	if (system_state != SYSTEM_HALT) {
+		spin_lock(&stop_lock);
+		printk(KERN_CRIT "CPU%u: stopping\n", cpu);
+		dump_stack();
+		spin_unlock(&stop_lock);
+	}
 
 	set_cpu_online(cpu, false);
 
Signature · 1 line
1.5.6.5
#1 lore raw

PATCH 1/1 ARM: Stop secondary cpus in machine_halt()

Quoted 5 lines · Olof Johansson

ARM doesn't spin down secondary cpus on halt, which results in interrupts being delivered even after the "System halted" message, etc.

Change that to use smp_send_stop() to halt them. Also, change the smp_send_stop() on ARM to not do a stack dump when stopping.

Actually, we want stack dumps - sometimes. For instance, when we panic() or similar.

#2 lore raw

PATCH 1/1 ARM: Stop secondary cpus in machine_halt()

Quoted 9 lines · Russell King - ARM Linux
Quoted 5 lines · Olof Johansson

ARM doesn't spin down secondary cpus on halt, which results in interrupts being delivered even after the "System halted" message, etc.

Change that to use smp_send_stop() to halt them. Also, change the smp_send_stop() on ARM to not do a stack dump when stopping.

Actually, we want stack dumps - sometimes. For instance, when we panic() or similar.

Do we really want the stack dumps of all cpus at panic time? They won't be printed precisely since the IPI takes a while to make it over.

As the size of SMP systems grow, it'll also become too spammy.

Anyway, the patch only changes behaviour when the system_state is SYSTEM_HALT, i.e. during shutdown so all other panics will still dump stacks from all cpus.

-Olof

#3 lore raw

PATCH v2 1/1 ARM: Stop secondary cpus in machine_halt()

In reply to Olof Johansson

ARM doesn't spin down secondary cpus on halt, which resulted interrupts being delivered even after the "System halted" message, etc.

Change that to use smp_send_stop() to halt them.

Also, change the smp_send_stop() on ARM to not do a stack dump when stopping the cpus during halt (but still print during other stops, i.e. panic).

---
 arch/arm/kernel/process.c |    6 ++++++
 arch/arm/kernel/smp.c     |   10 ++++++----
 2 files changed, 12 insertions(+), 4 deletions(-)
arch/arm/kernel/process.c +6 -0
index acf5e6f..203fc1b 100644
@@ -191,6 +191,12 @@ __setup("reboot=", reboot_setup);
 
 void machine_halt(void)
 {
+#ifdef CONFIG_SMP
+	smp_send_stop();
+#endif
+	printk(KERN_EMERG "System halted, OK to turn off power\n");
+	local_irq_disable();
+	while (1) ;
 }
 
 
arch/arm/kernel/smp.c +6 -4
index b8c3d0f..5496dea 100644
@@ -467,10 +467,12 @@ static DEFINE_SPINLOCK(stop_lock);
  */
 static void ipi_cpu_stop(unsigned int cpu)
 {
-	spin_lock(&stop_lock);
-	printk(KERN_CRIT "CPU%u: stopping\n", cpu);
-	dump_stack();
-	spin_unlock(&stop_lock);
+	if (system_state != SYSTEM_HALT) {
+		spin_lock(&stop_lock);
+		printk(KERN_CRIT "CPU%u: stopping\n", cpu);
+		dump_stack();
+		spin_unlock(&stop_lock);
+	}
 
 	set_cpu_online(cpu, false);
 
Signature · 1 line
1.5.6.5
#4 lore raw

PATCH v2 1/1 ARM: Stop secondary cpus in machine_halt()

Quoted 8 lines · Olof Johansson

ARM doesn't spin down secondary cpus on halt, which resulted interrupts being delivered even after the "System halted" message, etc.

Change that to use smp_send_stop() to halt them.

Also, change the smp_send_stop() on ARM to not do a stack dump when stopping the cpus during halt (but still print during other stops, i.e. panic).

Hmm... what about kexec on a SMP system, or we try to reboot a SMP system?

The x86 code suggests that we put smp_send_stop() inside machine_shutdown() (and move that function into arch/arm/kernel/process.c) and call it from machine_halt() and machine_reboot().

This will cover the kexec and reboot cases too.

So, something like this:

arch/arm/kernel/machine_kexec.c +0 -4
index 598ca61..4acce99 100644
@@ -37,10 +37,6 @@ void machine_kexec_cleanup(struct kimage *image)
 {
 }
 
-void machine_shutdown(void)
-{
-}
-
 void machine_crash_shutdown(struct pt_regs *regs)
 {
 }
arch/arm/kernel/process.c +11 -1
index a4a9cc8..ceb2aa4 100644
@@ -189,19 +189,29 @@ int __init reboot_setup(char *str)
 
 __setup("reboot=", reboot_setup);
 
-void machine_halt(void)
+void machine_shutdown(void)
 {
+#ifdef CONFIG_SMP
+	smp_send_stop();
+#endif
 }
 
+void machine_halt(void)
+{
+	machine_shutdown();
+	while (1);
+}
 
 void machine_power_off(void)
 {
+	machine_shutdown();
 	if (pm_power_off)
 		pm_power_off();
 }
 
 void machine_restart(char *cmd)
 {
+	machine_shutdown();
 	arm_pm_restart(reboot_mode, cmd);
 }
 
arch/arm/kernel/smp.c +7 -4
index b8c3d0f..11f631b 100644
@@ -467,10 +467,13 @@ static DEFINE_SPINLOCK(stop_lock);
  */
 static void ipi_cpu_stop(unsigned int cpu)
 {
-	spin_lock(&stop_lock);
-	printk(KERN_CRIT "CPU%u: stopping\n", cpu);
-	dump_stack();
-	spin_unlock(&stop_lock);
+	if (system_state == SYSTEM_BOOTING ||
+	    system_state == SYSTEM_RUNNING) {
+		spin_lock(&stop_lock);
+		printk(KERN_CRIT "CPU%u: stopping\n", cpu);
+		dump_stack();
+		spin_unlock(&stop_lock);
+	}
 
 	set_cpu_online(cpu, false);
 
#5 lore raw

PATCH v2 1/1 ARM: Stop secondary cpus in machine_halt()

Quoted 8 lines · Russell King - ARM Linux

Hmm... what about kexec on a SMP system, or we try to reboot a SMP system?

The x86 code suggests that we put smp_send_stop() inside machine_shutdown() (and move that function into arch/arm/kernel/process.c) and call it from machine_halt() and machine_reboot().

This will cover the kexec and reboot cases too.

As no one's commented on this, I'm going to apply it later today for the next merge window - it seems to be the right way to solve this problem, and makes us reflect what x86 does.

Quoted 79 lines

So, something like this:

arch/arm/kernel/machine_kexec.c +0 -4
index 598ca61..4acce99 100644
@@ -37,10 +37,6 @@ void machine_kexec_cleanup(struct kimage *image)
 {
 }
 
-void machine_shutdown(void)
-{
-}
-
 void machine_crash_shutdown(struct pt_regs *regs)
 {
 }
arch/arm/kernel/process.c +11 -1
index a4a9cc8..ceb2aa4 100644
@@ -189,19 +189,29 @@ int __init reboot_setup(char *str)
 
 __setup("reboot=", reboot_setup);
 
-void machine_halt(void)
+void machine_shutdown(void)
 {
+#ifdef CONFIG_SMP
+	smp_send_stop();
+#endif
 }
 
+void machine_halt(void)
+{
+	machine_shutdown();
+	while (1);
+}
 
 void machine_power_off(void)
 {
+	machine_shutdown();
 	if (pm_power_off)
 		pm_power_off();
 }
 
 void machine_restart(char *cmd)
 {
+	machine_shutdown();
 	arm_pm_restart(reboot_mode, cmd);
 }
 
arch/arm/kernel/smp.c +7 -4
index b8c3d0f..11f631b 100644
@@ -467,10 +467,13 @@ static DEFINE_SPINLOCK(stop_lock);
  */
 static void ipi_cpu_stop(unsigned int cpu)
 {
-	spin_lock(&stop_lock);
-	printk(KERN_CRIT "CPU%u: stopping\n", cpu);
-	dump_stack();
-	spin_unlock(&stop_lock);
+	if (system_state == SYSTEM_BOOTING ||
+	    system_state == SYSTEM_RUNNING) {
+		spin_lock(&stop_lock);
+		printk(KERN_CRIT "CPU%u: stopping\n", cpu);
+		dump_stack();
+		spin_unlock(&stop_lock);
+	}
 
 	set_cpu_online(cpu, false);
 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

#6 lore raw

PATCH v2 1/1 ARM: Stop secondary cpus in machine_halt()

Quoted 8 lines · Russell King - ARM Linux
Quoted 7 lines · Russell King - ARM Linux

Hmm... what about kexec on a SMP system, or we try to reboot a SMP system?

The x86 code suggests that we put smp_send_stop() inside machine_shutdown() (and move that function into arch/arm/kernel/process.c) and call it from machine_halt() and machine_reboot().

Quoted 5 lines
Quoted 1 line

This will cover the kexec and reboot cases too.

As no one's commented on this, I'm going to apply it later today for the next merge window - it seems to be the right way to solve this problem, and makes us reflect what x86 does.

Yeah, looks good to me.

-Olof