summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/x86/machine/cpu.c11
-rw-r--r--arch/x86/machine/cpu.h2
2 files changed, 9 insertions, 4 deletions
diff --git a/arch/x86/machine/cpu.c b/arch/x86/machine/cpu.c
index 1c306a60..1bbdc419 100644
--- a/arch/x86/machine/cpu.c
+++ b/arch/x86/machine/cpu.c
@@ -578,6 +578,8 @@ cpu_halt_broadcast(void)
unsigned long nr_halts;
unsigned int nr_cpus;
+ assert(!cpu_intr_enabled());
+
nr_cpus = cpu_count();
if (nr_cpus == 1)
@@ -585,10 +587,11 @@ cpu_halt_broadcast(void)
nr_halts = atomic_cas(&cpu_nr_halts, 0, nr_cpus - 1);
- /* Another CPU has started a halt, wait for the IPI */
- if (nr_halts != 0)
- for (;;)
- cpu_idle();
+ /* Another CPU has started a halt, emulate the IPI handler */
+ if (nr_halts != 0) {
+ atomic_add(&cpu_nr_halts, -1);
+ cpu_halt();
+ }
lapic_ipi_broadcast(TRAP_CPU_HALT);
diff --git a/arch/x86/machine/cpu.h b/arch/x86/machine/cpu.h
index d1a8b68e..bd5c2b8f 100644
--- a/arch/x86/machine/cpu.h
+++ b/arch/x86/machine/cpu.h
@@ -422,6 +422,8 @@ cpu_halt(void)
/*
* Halt all other processors.
+ *
+ * Interrupts must be disabled when calling this function.
*/
void cpu_halt_broadcast(void);