arm64: Fix deadlock scenario with smp_send_stop()
If one process calls sys_reboot and that process then stops other
CPUs while those CPUs are within a spin_lock() region we can
potentially encounter a deadlock scenario like below.
CPU 0                   CPU 1
-----                   -----
                        spin_lock(my_lock)
smp_send_stop()
 <send IPI>             handle_IPI()
                         disable_preemption/irqs
                          while(1);
 <PREEMPT>
spin_lock(my_lock) <--- Waits forever
We shouldn't attempt to run any other tasks after we send a stop
IPI to a CPU so disable preemption so that this task runs to
completion. We use local_irq_disable() here for cross-arch
consistency with x86.
Based-on-work-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Arun KS <getarunks@gmail.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
			
			
This commit is contained in:
		
							parent
							
								
									90f51a09ef
								
							
						
					
					
						commit
						b9acc49ee9
					
				| @ -135,6 +135,7 @@ void machine_shutdown(void) | ||||
|  */ | ||||
| void machine_halt(void) | ||||
| { | ||||
| 	local_irq_disable(); | ||||
| 	smp_send_stop(); | ||||
| 	while (1); | ||||
| } | ||||
| @ -147,6 +148,7 @@ void machine_halt(void) | ||||
|  */ | ||||
| void machine_power_off(void) | ||||
| { | ||||
| 	local_irq_disable(); | ||||
| 	smp_send_stop(); | ||||
| 	if (pm_power_off) | ||||
| 		pm_power_off(); | ||||
| @ -165,10 +167,9 @@ void machine_power_off(void) | ||||
|  */ | ||||
| void machine_restart(char *cmd) | ||||
| { | ||||
| 	smp_send_stop(); | ||||
| 
 | ||||
| 	/* Disable interrupts first */ | ||||
| 	local_irq_disable(); | ||||
| 	smp_send_stop(); | ||||
| 
 | ||||
| 	/* Now call the architecture specific reboot code. */ | ||||
| 	if (arm_pm_restart) | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user