Commit d3ec5cae authored by Ivan Vecera's avatar Ivan Vecera Committed by Ingo Molnar

x86: call machine_shutdown and stop all CPUs in native_machine_halt

Impact: really halt all CPUs on halt

Function machine_halt (resp. native_machine_halt) is empty for x86
architectures. When command 'halt -f' is invoked, the message "System
halted." is displayed but this is not really true because all CPUs are
still running.

There are also similar inconsistencies for other arches (some uses
power-off for halt or forever-loop with IRQs enabled/disabled).

IMO there should be used the same approach for all architectures OR
what does the message "System halted" really mean?

This patch fixes it for x86.
Signed-off-by: default avatarIvan Vecera <ivecera@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 3ad4f597
...@@ -193,6 +193,7 @@ extern u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask); ...@@ -193,6 +193,7 @@ extern u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask);
static inline void lapic_shutdown(void) { } static inline void lapic_shutdown(void) { }
#define local_apic_timer_c2_ok 1 #define local_apic_timer_c2_ok 1
static inline void init_apic_mappings(void) { } static inline void init_apic_mappings(void) { }
static inline void disable_local_APIC(void) { }
#endif /* !CONFIG_X86_LOCAL_APIC */ #endif /* !CONFIG_X86_LOCAL_APIC */
......
...@@ -314,6 +314,8 @@ extern void free_init_pages(char *what, unsigned long begin, unsigned long end); ...@@ -314,6 +314,8 @@ extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
void default_idle(void); void default_idle(void);
void stop_this_cpu(void *dummy);
/* /*
* Force strict CPU ordering. * Force strict CPU ordering.
* And yes, this is required on UP too when we're talking * And yes, this is required on UP too when we're talking
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/clockchips.h> #include <linux/clockchips.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/apic.h>
unsigned long idle_halt; unsigned long idle_halt;
EXPORT_SYMBOL(idle_halt); EXPORT_SYMBOL(idle_halt);
...@@ -122,6 +123,21 @@ void default_idle(void) ...@@ -122,6 +123,21 @@ void default_idle(void)
EXPORT_SYMBOL(default_idle); EXPORT_SYMBOL(default_idle);
#endif #endif
void stop_this_cpu(void *dummy)
{
local_irq_disable();
/*
* Remove this CPU:
*/
cpu_clear(smp_processor_id(), cpu_online_map);
disable_local_APIC();
for (;;) {
if (hlt_works(smp_processor_id()))
halt();
}
}
static void do_nothing(void *unused) static void do_nothing(void *unused)
{ {
} }
......
...@@ -461,6 +461,11 @@ static void native_machine_restart(char *__unused) ...@@ -461,6 +461,11 @@ static void native_machine_restart(char *__unused)
static void native_machine_halt(void) static void native_machine_halt(void)
{ {
/* stop other cpus and apics */
machine_shutdown();
/* stop this cpu */
stop_this_cpu(NULL);
} }
static void native_machine_power_off(void) static void native_machine_power_off(void)
......
...@@ -140,19 +140,6 @@ void native_send_call_func_ipi(cpumask_t mask) ...@@ -140,19 +140,6 @@ void native_send_call_func_ipi(cpumask_t mask)
send_IPI_mask(mask, CALL_FUNCTION_VECTOR); send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
} }
static void stop_this_cpu(void *dummy)
{
local_irq_disable();
/*
* Remove this CPU:
*/
cpu_clear(smp_processor_id(), cpu_online_map);
disable_local_APIC();
if (hlt_works(smp_processor_id()))
for (;;) halt();
for (;;);
}
/* /*
* this function calls the 'stop' function on all other CPUs in the system. * this function calls the 'stop' function on all other CPUs in the system.
*/ */
......
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