]> Zhao Yanbai Git Server - minix.git/commitdiff
SMP - APs are fully enabled
authorTomas Hruby <tom@minix3.org>
Wed, 15 Sep 2010 14:10:30 +0000 (14:10 +0000)
committerTomas Hruby <tom@minix3.org>
Wed, 15 Sep 2010 14:10:30 +0000 (14:10 +0000)
- apic_send_ipi() to send inter-processor interrupts (IPIs)

- APIC IPI schedule and halt handlers to signal x-cpu that a cpu shold
  reschedule or halt

- various little changes to let APs run

- no processes are scheduled at the APs and therefore they are idle
  except being interrupted by a timer time to time

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/exception.c
kernel/arch/i386/include/arch_smp.h
kernel/smp.c
kernel/smp.h

index fc6a313ef80647c0181d9427749a42451d5d425a..a55a389d0b7eaac46544385d28e16f9153dd7933 100644 (file)
@@ -294,6 +294,11 @@ PUBLIC void ioapic_eoi(int irq)
                irq_8259_eoi(irq);
 }
  
+PUBLIC void ioapic_set_id(u32_t addr, unsigned int id)
+{
+       ioapic_write(addr, IOAPIC_ID, id << 24);
+}
+
 PUBLIC int ioapic_enable_all(void)
 {
        i8259_disable();
@@ -389,14 +394,17 @@ PUBLIC void ioapic_mask_irq(unsigned irq)
                irq_8259_mask(irq);
 }
 
-PUBLIC unsigned int apicid(void)
+PUBLIC void apic_ipi_sched_handler(void)
 {
-       return lapic_read(LAPIC_ID);
 }
 
-PUBLIC void ioapic_set_id(u32_t addr, unsigned int id)
+PUBLIC void apic_ipi_halt_handler(void)
 {
-       ioapic_write(addr, IOAPIC_ID, id << 24);
+}
+
+PUBLIC unsigned int apicid(void)
+{
+       return lapic_read(LAPIC_ID);
 }
 
 PRIVATE int calib_clk_handler(irq_hook_t * UNUSED(hook))
@@ -793,10 +801,8 @@ PRIVATE struct gate_table_s gate_table_common[] = {
 
 #ifdef CONFIG_SMP
 PRIVATE struct gate_table_s gate_table_smp[] = {
-       { smp_ipi_sched, SMP_SCHED_PROC, INTR_PRIVILEGE },
-       { smp_ipi_dequeue, SMP_DEQUEUE_PROC, INTR_PRIVILEGE },
-       { smp_ipi_reboot,SMP_CPU_REBOOT, INTR_PRIVILEGE },
-       { smp_ipi_stop,  SMP_CPU_HALT, INTR_PRIVILEGE },
+       { apic_ipi_sched_intr, APIC_SMP_SCHED_PROC_VECTOR, INTR_PRIVILEGE },
+       { apic_ipi_halt_intr,  APIC_SMP_CPU_HALT_VECTOR, INTR_PRIVILEGE },
        { NULL, 0, 0}
 };
 #endif
@@ -909,6 +915,45 @@ PUBLIC int detect_ioapics(void)
 
 #ifdef CONFIG_SMP
 
+PUBLIC void apic_send_ipi(unsigned vector, unsigned cpu, int type)
+{
+       u32_t icr1, icr2;
+
+       if (ncpus == 1)
+               /* no need of sending an IPI */
+               return;
+
+       while (lapic_read_icr1() & APIC_ICR_DELIVERY_PENDING) 
+               arch_pause();
+
+       icr1 = lapic_read_icr1() & 0xFFF0F800;
+       icr2 = lapic_read_icr2() & 0xFFFFFF;
+
+       switch (type) {
+               case APIC_IPI_DEST:
+                       if (!cpu_is_ready(cpu))
+                               return;
+                       lapic_write_icr2(icr2 | (cpuid2apicid[cpu] << 24));
+                       lapic_write_icr1(icr1 | APIC_ICR_DEST_FIELD | vector);
+                       break;
+               case APIC_IPI_SELF:
+                       lapic_write_icr2(icr2);
+                       lapic_write_icr1(icr1 | APIC_ICR_DEST_SELF | vector);
+                       break;
+               case APIC_IPI_TO_ALL_BUT_SELF:
+                       lapic_write_icr2(icr2);
+                       lapic_write_icr1(icr1 | APIC_ICR_DEST_ALL_BUT_SELF | vector);
+                       break;
+               case APIC_IPI_TO_ALL:
+                       lapic_write_icr2(icr2);
+                       lapic_write_icr1(icr1 | APIC_ICR_DEST_ALL | vector);
+                       break;
+               default:
+                       printf("WARNING : unknown send ipi type request\n");
+       }
+
+}
+
 PUBLIC int apic_send_startup_ipi(unsigned cpu, phys_bytes trampoline)
 {
        int timeout;
@@ -919,6 +964,8 @@ PUBLIC int apic_send_startup_ipi(unsigned cpu, phys_bytes trampoline)
 
        for (i = 0; i < 2; i++) {
                u32_t val;
+               
+               /* clear err status */
                lapic_errstatus();
 
                /* set target pe */
@@ -938,8 +985,8 @@ PUBLIC int apic_send_startup_ipi(unsigned cpu, phys_bytes trampoline)
                lapic_microsec_sleep (200);
                errstatus = 0;
 
-               while ((lapic_read(LAPIC_ICR1) & APIC_ICR_DELIVERY_PENDING) && !errstatus)
-               {
+               while ((lapic_read(LAPIC_ICR1) & APIC_ICR_DELIVERY_PENDING) &&
+                               !errstatus) {
                        errstatus = lapic_errstatus();
                        timeout--;
                        if (!timeout) break;
index ca7f6a9c381bff8f4b4f45489d398e9122c9d9a5..03f28c2e37a8f7ff300d96622d8e751d1f77157d 100644 (file)
@@ -88,6 +88,8 @@
 #define IOAPIC_REDIR_TABLE             0x10
 
 #define APIC_TIMER_INT_VECTOR          0xf0
+#define APIC_SMP_SCHED_PROC_VECTOR     0xf1
+#define APIC_SMP_CPU_HALT_VECTOR       0xf2
 #define APIC_ERROR_INT_VECTOR          0xfe
 #define APIC_SPURIOUS_INT_VECTOR       0xff
 
@@ -157,12 +159,31 @@ _PROTOTYPE(void ioapic_unset_irq, (unsigned irq));
  /* signal the end of interrupt handler to apic */
 _PROTOTYPE(void ioapic_eoi, (int irq));
 
-_PROTOTYPE(void lapic_disable, (void));
-_PROTOTYPE(void ioapic_disable_all, (void));
-_PROTOTYPE(void ioapic_reset_pic, (void));
-
 _PROTOTYPE(void dump_apic_irq_state, (void));
 
+_PROTOTYPE(void apic_send_ipi, (unsigned vector, unsigned cpu, int type));
+
+_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
+#define APIC_IPI_TO_ALL                        2
+#define APIC_IPI_TO_ALL_BUT_SELF       3
+
+#define apic_send_ipi_single(vector,cpu) \
+       apic_send_ipi(vector, cpu, APIC_IPI_DEST);
+#define apic_send_ipi_self(vector) \
+       apic_send_ipi(vector, 0, APIC_IPI_SELF)
+#define apic_send_ipi_all(vector) \
+       apic_send_ipi (vector, 0, APIC_IPI_TO_ALL)
+#define apic_send_ipi_allbutself(vector) \
+       apic_send_ipi (vector, 0, APIC_IPI_TO_ALL_BUT_SELF);
+
+
 #include <minix/cpufeature.h>
 
 #define cpu_feature_apic_on_chip() _cpufeature(_CPUF_I386_APIC_ON_CHIP)
index 34c651baf4941f6e056c4f97faf1f3152442f6eb..1988dd194f4daff034499d1fa96a6d48cabf5f6c 100644 (file)
@@ -68,26 +68,12 @@ ENTRY(lapic_timer_int_handler)
        lapic_intr(_C_LABEL(timer_int_handler))
 
 #ifdef CONFIG_SMP
-#include "arch_smp.h"
 
-/* FIXME dummy stubs */
-ENTRY(smp_ipi_sched)
-1:     jmp 1b
+ENTRY(apic_ipi_sched_intr)
+       lapic_intr(_C_LABEL(apic_ipi_sched_handler))
 
-ENTRY(smp_ipi_dequeue)
-1:     jmp 1b
-
-ENTRY(smp_ipi_stop)
-1:     jmp 1b
-
-ENTRY(smp_ipi_reboot)
-1:     jmp 1b
-
-ENTRY(smp_ipi_err_int)
-1:     jmp 1b
-
-ENTRY(smp_ipi_spv_int)
-1:     jmp 1b
+ENTRY(apic_ipi_halt_intr)
+       lapic_intr(_C_LABEL(apic_ipi_halt_handler))
 
 #endif /* CONFIG_SMP */
 
index e45d0439aa8b0ca7689acf834db96ffe6528d987..26c19b79e41ebd16b250f9b706a6adb0940acc71 100644 (file)
@@ -126,13 +126,10 @@ PRIVATE void smp_start_aps(void)
         * using the processor's apic id values.
         */
        for (cpu = 0; cpu < ncpus; cpu++) {
-               printf("Booting cpu %d\n", cpu);
                ap_cpu_ready = -1;
                /* Don't send INIT/SIPI to boot cpu.  */
                if((apicid() == cpuid2apicid[cpu]) && 
                                (apicid() == bsp_lapic_id)) {
-                       cpu_set_flag(cpu, CPU_IS_READY);
-                       printf("Skiping bsp\n");
                        continue;
                }
 
@@ -150,7 +147,6 @@ PRIVATE void smp_start_aps(void)
 
                while (lapic_read(LAPIC_TIMER_CCR)) {
                        if (ap_cpu_ready == cpu) {
-                               printf("CPU %d is up\n", cpu);
                                cpu_set_flag(cpu, CPU_IS_READY);
                                break;
                        }
@@ -176,14 +172,42 @@ PUBLIC void smp_halt_cpu (void)
 
 PUBLIC void smp_shutdown_aps (void)
 {
-       NOT_IMPLEMENTED;
+       u8_t cpu;
+       unsigned aid = apicid();
+       
+       if (ncpus == 1)
+               goto exit_shutdown_aps;
+
+       for (cpu = 0; cpu < ncpus; cpu++) {
+               u16_t i;
+               if (!cpu_is_ready(cpu))
+                       continue;
+               if ((aid == cpuid2apicid[cpu]) && (aid == bsp_lapic_id))
+                       continue;
+               apic_send_ipi(APIC_SMP_CPU_HALT_VECTOR, cpu, APIC_IPI_DEST);
+               /* TODO wait for the cpu to be down */
+       }
+
+       /* 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();
+
+       lapic_disable();
+
+       ncpus = 1; /* hopefully !!! */
+       lapic_addr = lapic_eoi_addr = 0;
+       return;
 }
 
 PRIVATE void ap_finish_booting(void)
 {
        unsigned cpu = cpuid;
 
-       printf("CPU %d says hello world!\n", cpu);
        /* inform the world of our presence. */
        ap_cpu_ready = cpu;
 
@@ -222,12 +246,6 @@ PRIVATE void ap_finish_booting(void)
        ap_boot_finished(cpu);
        spinlock_unlock(&boot_lock);
 
-       /* finish processor initialisation. */
-       lapic_enable(cpu);
-
-       BKL_UNLOCK();
-       for(;;);
-
        switch_to_user();
        NOT_REACHABLE;
 }
index 5c9094e5bde1d26b0382779af73ab3ed6e6dd4d5..86eb541011aa54ab29f79d0f55944c86096c2baf 100644 (file)
@@ -69,8 +69,9 @@ PRIVATE void pagefault( struct proc *pr,
                /* Page fault we can't / don't want to
                 * handle.
                 */
-               printf("pagefault for process %d ('%s'), pc = 0x%x, addr = 0x%x, flags = 0x%x, is_nested %d\n",
-                       pr->p_endpoint, pr->p_name, pr->p_reg.pc,
+               printf("pagefault for process %d ('%s') on CPU %d, "
+                       "pc = 0x%x, addr = 0x%x, flags = 0x%x, is_nested %d\n",
+                       pr->p_endpoint, pr->p_name, cpuid, pr->p_reg.pc,
                        pagefaultcr2, frame->errcode, is_nested);
                proc_stacktrace(pr);
                printf("pc of pagefault: 0x%lx\n", frame->eip);
@@ -207,7 +208,7 @@ PUBLIC void exception_handler(int is_nested, struct exception_frame * frame)
        printf("\nIntel-reserved exception %d\n", frame->vector);
   else
        printf("\n%s\n", ep->msg);
-  printf("is_nested = %d ", is_nested);
+  printf("cpu %d is_nested = %d ", cpuid, is_nested);
 
   printf("vec_nr= %d, trap_errno= 0x%x, eip= 0x%x, "
        "cs= 0x%x, eflags= 0x%x trap_esp 0x%08x\n",
index 90e70223dbe8311793555fb2a768d1c1594263bc..4885c0f06115708013c4be090396f3a894370fca 100644 (file)
@@ -5,21 +5,6 @@
 
 #define MAX_NR_INTERRUPT_ENTRIES       128
 
-#define SMP_SCHED_PROC                 0xF0
-#define SMP_DEQUEUE_PROC               0xF1
-#define SMP_CPU_REBOOT                 0xF2
-#define SMP_CPU_HALT                   0xF3
-#define SMP_ERROR_INT                  0xF4
-
-/* currently only 2 interrupt priority levels are used */
-#define SPL0                           0x0
-#define        SPLHI                           0xF
-
-#define SMP_IPI_DEST                   0
-#define SMP_IPI_SELF                   1
-#define SMP_IPI_TO_ALL                 2
-#define SMP_IPI_TO_ALL_BUT_SELF                3
-
 #ifndef __ASSEMBLY__
 
 /* returns the current cpu id */
@@ -31,6 +16,8 @@
  */
 #define smp_single_cpu_fallback() do {         \
          tss_init(0, get_k_stack_top(0));      \
+         bsp_cpu_id = 0;                       \
+         ncpus = 1;                            \
          bsp_finish_booting();                 \
 } while(0)
 
index 367be59479c4ef11269cc6d295e35a354015761f..3f6e9b5ec6a46ec3a3a8778cea22617072cb953c 100644 (file)
@@ -23,7 +23,5 @@ void wait_for_APs_to_finish_booting(void)
 
 void ap_boot_finished(unsigned cpu)
 {
-       printf("CPU %d is running\n", cpu);
-
        ap_cpus_booted++;
 }
index 312dd144fdbeddfb5aca6e970f0ecf2d8705d22b..01e00c0f76d0cc5e02e286512b1ca2456c9a19f2 100644 (file)
@@ -28,13 +28,6 @@ EXTERN unsigned bsp_cpu_id;
  */
 _PROTOTYPE(void smp_init, (void));
 
-_PROTOTYPE(void smp_ipi_err_int, (void));
-_PROTOTYPE(void smp_ipi_spv_int, (void));
-_PROTOTYPE(void smp_ipi_sched, (void));
-_PROTOTYPE(void smp_ipi_dequeue, (void));
-_PROTOTYPE(void smp_ipi_stop, (void));
-_PROTOTYPE(void smp_ipi_reboot, (void));
-
 #define CPU_IS_BSP     1
 #define CPU_IS_READY   2