Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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 */

+2 −0
Original line number Diff line number Diff line
@@ -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
+16 −0
Original line number Diff line number Diff line
@@ -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);
@@ -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)
{
}
+5 −0
Original line number Diff line number Diff line
@@ -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)
+0 −13
Original line number Diff line number Diff line
@@ -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.
 */