extern int panicking;
static int ap_cpu_ready;
+static int cpu_down;
/* there can be at most 255 local APIC ids, each fits in 8 bits */
PRIVATE unsigned char apicid2cpuid[255];
NOT_IMPLEMENTED;
}
-PUBLIC void smp_shutdown_aps (void)
+PUBLIC void smp_shutdown_aps(void)
{
- u8_t cpu;
+ unsigned cpu;
unsigned aid = apicid();
+ unsigned local_cpu = cpuid;
if (ncpus == 1)
goto exit_shutdown_aps;
+
+ /* we must let the other cpus enter the kernel mode */
+ BKL_UNLOCK();
for (cpu = 0; cpu < ncpus; cpu++) {
- u16_t i;
- if (!cpu_is_ready(cpu))
- continue;
- if ((aid == cpuid2apicid[cpu]) && (aid == bsp_lapic_id))
+ if (cpu == cpuid)
continue;
+ cpu_down = -1;
+ barrier();
apic_send_ipi(APIC_SMP_CPU_HALT_VECTOR, cpu, APIC_IPI_DEST);
- /* TODO wait for the cpu to be down */
+ /* wait for the cpu to be down */
+ while (cpu_down != cpu);
+ printf("CPU %d is down\n", cpu);
+ cpu_clear_flag(cpu, CPU_IS_READY);
}
- /* Sending INIT to a processor makes it to wait in a halt state */
- for (cpu = 0; cpu < ncpus; cpu++) {
- if ((aid == cpuid2apicid[cpu]) && (aid == bsp_lapic_id))
- continue;
- apic_send_init_ipi (cpu, 0);
- }
exit_shutdown_aps:
ioapic_disable_all();
intr_init (INTS_MINIX, 0); /* no auto eoi */
printf("WARNING : SMP initialization failed\n");
}
+
+PUBLIC void arch_smp_halt_cpu(void)
+{
+ /* say that we are down */
+ cpu_down = cpuid;
+ barrier();
+ /* unlock the BKL and don't continue */
+ BKL_UNLOCK();
+ for(;;);
+}
SPINLOCK_DEFINE(big_kernel_lock)
SPINLOCK_DEFINE(boot_lock)
-void wait_for_APs_to_finish_booting(void)
+PUBLIC void wait_for_APs_to_finish_booting(void)
{
/* we must let the other CPUs to run in kernel mode first */
BKL_UNLOCK();
BKL_LOCK();
}
-void ap_boot_finished(unsigned cpu)
+PUBLIC void ap_boot_finished(unsigned cpu)
{
ap_cpus_booted++;
}
+
+PUBLIC void smp_ipi_halt_handler(void)
+{
+ arch_stop_local_timer();
+ arch_smp_halt_cpu();
+}
+
_PROTOTYPE(void wait_for_APs_to_finish_booting, (void));
_PROTOTYPE(void ap_boot_finished, (unsigned cpu));
+_PROTOTYPE(void smp_ipi_halt_handler, (void));
+_PROTOTYPE(void arch_smp_halt_cpu, (void));
#endif /* __ASSEMBLY__ */