Skip to content

Commit

Permalink
x86: call machine_shutdown and stop all CPUs in native_machine_halt
Browse files Browse the repository at this point in the history
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: Ivan Vecera <ivecera@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
  • Loading branch information
Ivan Vecera authored and Ingo Molnar committed Nov 11, 2008
1 parent 3ad4f59 commit d3ec5ca
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 13 deletions.
1 change: 1 addition & 0 deletions arch/x86/include/asm/apic.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ extern u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask);
static inline void lapic_shutdown(void) { }
#define local_apic_timer_c2_ok 1
static inline void init_apic_mappings(void) { }
static inline void disable_local_APIC(void) { }

#endif /* !CONFIG_X86_LOCAL_APIC */

Expand Down
2 changes: 2 additions & 0 deletions arch/x86/include/asm/system.h
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,8 @@ extern void free_init_pages(char *what, unsigned long begin, unsigned long end);

void default_idle(void);

void stop_this_cpu(void *dummy);

/*
* Force strict CPU ordering.
* And yes, this is required on UP too when we're talking
Expand Down
16 changes: 16 additions & 0 deletions arch/x86/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <linux/pm.h>
#include <linux/clockchips.h>
#include <asm/system.h>
#include <asm/apic.h>

unsigned long idle_halt;
EXPORT_SYMBOL(idle_halt);
Expand Down Expand Up @@ -122,6 +123,21 @@ void default_idle(void)
EXPORT_SYMBOL(default_idle);
#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)
{
}
Expand Down
5 changes: 5 additions & 0 deletions arch/x86/kernel/reboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,11 @@ static void native_machine_restart(char *__unused)

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)
Expand Down
13 changes: 0 additions & 13 deletions arch/x86/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,19 +140,6 @@ void native_send_call_func_ipi(cpumask_t mask)
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.
*/
Expand Down

0 comments on commit d3ec5ca

Please sign in to comment.