diff options
-rw-r--r-- | arch/x86/machine/cpu.c | 11 | ||||
-rw-r--r-- | arch/x86/machine/cpu.h | 2 |
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); |