]> Zhao Yanbai Git Server - minix.git/commitdiff
SMP - BSP halts APs before shutting down
authorTomas Hruby <tom@minix3.org>
Wed, 15 Sep 2010 14:10:54 +0000 (14:10 +0000)
committerTomas Hruby <tom@minix3.org>
Wed, 15 Sep 2010 14:10:54 +0000 (14:10 +0000)
kernel/arch/i386/apic.c
kernel/arch/i386/apic.h
kernel/arch/i386/apic_asm.S
kernel/arch/i386/arch_smp.c
kernel/arch/i386/include/arch_smp.h
kernel/main.c
kernel/smp.c
kernel/smp.h

index a55a389d0b7eaac46544385d28e16f9153dd7933..8da7187bd355fd2aa5e38e0b0ef366a5ba304508 100644 (file)
@@ -398,10 +398,6 @@ PUBLIC void apic_ipi_sched_handler(void)
 {
 }
 
-PUBLIC void apic_ipi_halt_handler(void)
-{
-}
-
 PUBLIC unsigned int apicid(void)
 {
        return lapic_read(LAPIC_ID);
index 03f28c2e37a8f7ff300d96622d8e751d1f77157d..2530865686cb84fadd41154c984c164caa5ba276 100644 (file)
@@ -167,7 +167,6 @@ _PROTOTYPE(void apic_ipi_sched_intr, (void));
 _PROTOTYPE(void apic_ipi_halt_intr, (void));
 
 _PROTOTYPE(void apic_ipi_sched_handler, (void));
-_PROTOTYPE(void apic_ipi_halt_handler, (void));
 
 #define APIC_IPI_DEST                  0
 #define APIC_IPI_SELF                  1
index 1988dd194f4daff034499d1fa96a6d48cabf5f6c..21f3817d7a9f617ef08e3cfb1a20f5054d88373e 100644 (file)
@@ -73,7 +73,7 @@ ENTRY(apic_ipi_sched_intr)
        lapic_intr(_C_LABEL(apic_ipi_sched_handler))
 
 ENTRY(apic_ipi_halt_intr)
-       lapic_intr(_C_LABEL(apic_ipi_halt_handler))
+       lapic_intr(_C_LABEL(smp_ipi_halt_handler))
 
 #endif /* CONFIG_SMP */
 
index 26c19b79e41ebd16b250f9b706a6adb0940acc71..6a3c8fa96781f574ff06bf6def8f02122dcee1a0 100644 (file)
@@ -37,6 +37,7 @@ extern u32_t busclock[CONFIG_MAX_CPUS];
 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];
@@ -170,30 +171,30 @@ PUBLIC void smp_halt_cpu (void)
        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();
 
@@ -342,3 +343,13 @@ uniproc_fallback:
        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(;;);
+}
index 4885c0f06115708013c4be090396f3a894370fca..3a013a98297c8fa1f3c7f10d7af3104cedd70c3a 100644 (file)
@@ -23,6 +23,8 @@
 
 extern unsigned char cpuid2apicid[CONFIG_MAX_CPUS];
 
+#define barrier()      do { mfence(); } while(0)
+
 #endif
 
 #endif /* __SMP_X86_H__ */
index e24e0748afb1720267897b8731585f22071a9918..8b3de25096a06c52fadf08e4e8617f48eefcf6fa 100644 (file)
@@ -374,7 +374,7 @@ PUBLIC void minix_shutdown(timer_t *tp)
    * monitor again
    */
   if (ncpus > 1)
-         NOT_IMPLEMENTED;
+         smp_shutdown_aps();
 #endif
   arch_stop_local_timer();
   hw_intr_disable_all();
index 3f6e9b5ec6a46ec3a3a8778cea22617072cb953c..2415e4add0f9a87352166bd3e624b4a9c7b66874 100644 (file)
@@ -11,7 +11,7 @@ static volatile unsigned ap_cpus_booted;
 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();
@@ -21,7 +21,14 @@ void wait_for_APs_to_finish_booting(void)
        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();
+}
+
index 01e00c0f76d0cc5e02e286512b1ca2456c9a19f2..e9fba1f842b80564fd1cc0579e4663909f4ee099 100644 (file)
@@ -53,6 +53,8 @@ SPINLOCK_DECLARE(boot_lock)
        
 _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__ */