x86: Uses rbx for the initial vcoreid (XCC)
[akaros.git] / kern / arch / x86 / smp_boot.c
index 64d8714..96bdba6 100644 (file)
@@ -4,11 +4,6 @@
  * See LICENSE for details.
  */
 
-#ifdef __SHARC__
-#pragma nosharc
-#define SINIT(x) x
-#endif
-
 #include <arch/x86.h>
 #include <arch/arch.h>
 #include <smp.h>
 #include <trap.h>
 #include <kmalloc.h>
 
-extern handler_wrapper_t (RO handler_wrappers)[NUM_HANDLER_WRAPPERS];
+#include "vmm/vmm.h"
+
+extern handler_wrapper_t handler_wrappers[NUM_HANDLER_WRAPPERS];
 volatile uint32_t num_cpus = 0xee;
-uintptr_t RO smp_stack_top;
+uintptr_t smp_stack_top;
 barrier_t generic_barrier;
 
 #define DECLARE_HANDLER_CHECKLISTS(vector)                          \
@@ -38,7 +35,7 @@ barrier_t generic_barrier;
 
 #define INIT_HANDLER_WRAPPER(v)                                     \
 {                                                                   \
-       handler_wrappers[(v)].vector = 0xf##v;                          \
+       handler_wrappers[(v)].vector = 0xe##v;                          \
        handler_wrappers[(v)].cpu_list = &f##v##_cpu_list;              \
        handler_wrappers[(v)].cpu_list->mask.size = num_cpus;           \
 }
@@ -60,6 +57,8 @@ static void init_smp_call_function(void)
 
 /******************************************************************************/
 
+bool core_id_ready = FALSE;
+
 static void setup_rdtscp(int coreid)
 {
        uint32_t edx;
@@ -80,21 +79,32 @@ void smp_final_core_init(void)
 {
        /* It is possible that the non-0 cores will wake up before the broadcast
         * ipi.  this can be due to spurious IRQs or some such.  anyone other than
-        * core 0 that comes in here will wait til core 0 has set everything up */
+        * core 0 that comes in here will wait til core 0 has set everything up.
+        * those other cores might have come up before core 0 remapped the coreids,
+        * so we can only look at the HW coreid, which is only 0 for core 0. */
        static bool wait = TRUE;
-       if (get_os_coreid(hw_core_id()) == 0)
+       if (hw_core_id() == 0)
                wait = FALSE;
        while (wait)
                cpu_relax();
-#ifdef CONFIG_X86_64
+       /* at this point, it is safe to get the OS coreid */
        int coreid = get_os_coreid(hw_core_id());
        struct per_cpu_info *pcpui = &per_cpu_info[coreid];
        pcpui->coreid = coreid;
        write_msr(MSR_GS_BASE, (uint64_t)pcpui);
        write_msr(MSR_KERN_GS_BASE, (uint64_t)pcpui);
-#endif
        /* don't need this for the kernel anymore, but userspace can still use it */
        setup_rdtscp(coreid);
+       /* After this point, all cores have set up their segmentation and whatnot to
+        * be able to do a proper core_id().  As a note to posterity, using the
+        * LAPIC coreid (like get_hw_coreid()) needs the LAPIC set up, which happens
+        * by the end of vm_init() */
+       waiton_barrier(&generic_barrier);
+       if (hw_core_id() == 0) {
+               core_id_ready = TRUE;
+       }
+       /* being paranoid with this, it's all a bit ugly */
+       waiton_barrier(&generic_barrier);
        setup_default_mtrrs(&generic_barrier);
        smp_percpu_init();
        waiton_barrier(&generic_barrier);
@@ -102,10 +112,10 @@ void smp_final_core_init(void)
 
 // this needs to be set in smp_entry too...
 #define trampoline_pg 0x00001000UL
-extern char (SNT SREADONLY smp_entry)[];
-extern char (SNT SREADONLY smp_entry_end)[];
-extern char (SNT SREADONLY smp_boot_lock)[];
-extern char (SNT SREADONLY smp_semaphore)[];
+extern char smp_entry[];
+extern char smp_entry_end[];
+extern char smp_boot_lock[];
+extern char smp_semaphore[];
 
 static inline uint16_t *get_smp_semaphore()
 {
@@ -145,6 +155,7 @@ static void smp_remap_coreids(void)
 
 void smp_boot(void)
 {
+       struct per_cpu_info *pcpui0 = &per_cpu_info[0];
        /* set core0's mappings */
        assert(lapic_get_id() == 0);
        os_coreid_lookup[0] = 0;
@@ -154,21 +165,21 @@ void smp_boot(void)
        // NEED TO GRAB A LOWMEM FREE PAGE FOR AP BOOTUP CODE
        // page1 (2nd page) is reserved, hardcoded in pmap.c
        memset(KADDR(trampoline_pg), 0, PGSIZE);
-       memcpy(KADDR(trampoline_pg), (void *COUNT(PGSIZE))TC(smp_entry),
+       memcpy(KADDR(trampoline_pg), (void *)smp_entry,
            smp_entry_end - smp_entry);
 
-       /* 64 bit already has the tramp pg mapped (1 GB of lowmem)  */
-#ifndef CONFIG_X86_64
-       // This mapping allows access to the trampoline with paging on and off
-       // via trampoline_pg
-       page_insert(boot_pgdir, pa2page(trampoline_pg), (void*SNT)trampoline_pg, PTE_W);
-#endif
+       /* Make sure the trampoline page is mapped.  64 bit already has the tramp pg
+        * mapped (1 GB of lowmem), so this is a nop. */
 
        // Allocate a stack for the cores starting up.  One for all, must share
        if (kpage_alloc(&smp_stack))
                panic("No memory for SMP boot stack!");
-       smp_stack_top = SINIT((uintptr_t)(page2kva(smp_stack) + PGSIZE));
+       smp_stack_top = (uintptr_t)(page2kva(smp_stack) + PGSIZE);
 
+       /* During SMP boot, core_id_early() returns 0, so all of the cores, which
+        * grab locks concurrently, share the same pcpui and thus the same
+        * lock_depth.  We need to disable checking until core_id works properly. */
+       pcpui0->__lock_checking_enabled = 0;
        // Start the IPI process (INIT, wait, SIPI, wait, SIPI, wait)
        send_init_ipi();
        // SDM 3A is a little wonky wrt the proper delays.  These are my best guess.
@@ -286,18 +297,7 @@ uintptr_t smp_main(void)
        // Loads the same IDT used by the other cores
        asm volatile("lidt %0" : : "m"(idt_pd));
 
-#ifdef CONFIG_ENABLE_MPTABLES
        apiconline();
-#else
-       // APIC setup
-       // set LINT0 to receive ExtINTs (KVM's default).  At reset they are 0x1000.
-       write_mmreg32(LAPIC_LVT_LINT0, 0x700);
-       // mask it to shut it up for now.  Doesn't seem to matter yet, since both
-       // KVM and Bochs seem to only route the PIC to core0.
-       mask_lapic_lvt(LAPIC_LVT_LINT0);
-       // and then turn it on
-       lapic_enable();
-#endif
 
        // set a default logical id for now
        lapic_set_logid(lapic_get_id());
@@ -336,12 +336,11 @@ void __arch_pcpu_init(uint32_t coreid)
                pcpui->gdt = (segdesc_t*)(*my_stack_bot +
                                          sizeof(taskstate_t) + sizeof(pseudodesc_t));
        }
-#ifdef CONFIG_X86_64
        assert(read_msr(MSR_GS_BASE) == (uint64_t)pcpui);
        assert(read_msr(MSR_KERN_GS_BASE) == (uint64_t)pcpui);
-#endif
        /* Don't try setting up til after setting GS */
        x86_sysenter_init(x86_get_stacktop_tss(pcpui->tss));
        /* need to init perfctr before potentiall using it in timer handler */
        perfmon_init();
+       vmm_pcpu_init();
 }