Removed lapic_set_id and lapic_set_logid functions
[akaros.git] / kern / arch / x86 / smp_boot.c
index 8a20063..05df791 100644 (file)
@@ -26,7 +26,7 @@
 #include "vmm/vmm.h"
 
 extern handler_wrapper_t handler_wrappers[NUM_HANDLER_WRAPPERS];
-volatile uint32_t num_cores = 0xee;
+int x86_num_cores_booted = 1;
 uintptr_t smp_stack_top;
 barrier_t generic_barrier;
 
@@ -77,17 +77,7 @@ static void setup_rdtscp(int coreid)
 /* TODO: consider merging __arch_pcpu with parts of this (sync with RISCV) */
 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.
-        * 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 (hw_core_id() == 0)
-               wait = FALSE;
-       while (wait)
-               cpu_relax();
-       /* at this point, it is safe to get the OS coreid */
+       /* Set the coreid in pcpui for fast access to it through TLS. */
        int coreid = get_os_coreid(hw_core_id());
        struct per_cpu_info *pcpui = &per_cpu_info[coreid];
        pcpui->coreid = coreid;
@@ -96,13 +86,10 @@ void smp_final_core_init(void)
        /* 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() */
+        * be able to do a proper core_id(). */
        waiton_barrier(&generic_barrier);
-       if (hw_core_id() == 0) {
+       if (coreid == 0)
                core_id_ready = TRUE;
-       }
        /* being paranoid with this, it's all a bit ugly */
        waiton_barrier(&generic_barrier);
        setup_default_mtrrs(&generic_barrier);
@@ -133,35 +120,11 @@ static void __spin_bootlock_raw(void)
                      "jne 1b;" : : "m"(*bootlock) : "eax", "cc", "memory");
 }
 
-/* hw_coreid_lookup will get packed, but keep it's hw values.  
- * os_coreid_lookup will remain sparse, but it's values will be consecutive.
- * for both arrays, -1 means an empty slot.  hw_step tracks the next valid entry
- * in hw_coreid_lookup, jumping over gaps of -1's. */
-static void smp_remap_coreids(void)
-{
-       for (int i = 0, hw_step = 0; i < num_cores; i++, hw_step++) {
-               if (hw_coreid_lookup[i] == -1) {
-                       while (hw_coreid_lookup[hw_step] == -1) {
-                               hw_step++;
-                               if (hw_step == MAX_NUM_CORES)
-                                       panic("Mismatch in num_cores and hw_step");
-                       }
-                       hw_coreid_lookup[i] = hw_coreid_lookup[hw_step];
-                       hw_coreid_lookup[hw_step] = -1;
-                       os_coreid_lookup[hw_step] = i;
-               }
-       }
-}
-
 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;
-       hw_coreid_lookup[0] = 0;
-
        page_t *smp_stack;
+
        // 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);
@@ -210,20 +173,23 @@ void smp_boot(void)
        // mapping pulled out from under them.  Now, if a core loses, it will spin
        // on the trampoline (which we must be careful to not deallocate)
        __spin_bootlock_raw();
-       printk("Number of Cores Detected: %d\n", num_cores);
+       printk("Number of Cores Detected: %d\n", x86_num_cores_booted);
 #ifdef CONFIG_DISABLE_SMT
        assert(!(num_cores % 2));
        printk("Using only %d Idlecores (SMT Disabled)\n", num_cores >> 1);
 #endif /* CONFIG_DISABLE_SMT */
-       smp_remap_coreids();
 
        /* cleans up the trampoline page, and any other low boot mem mappings */
        x86_cleanup_bootmem();
-       // It had a refcount of 2 earlier, so we need to dec once more to free it
-       // but only if all cores are in (or we reset / reinit those that failed)
-       // TODO after we parse ACPI tables
-       if (num_cores == 8) // TODO - ghetto coded for our 8 way SMPs
+       /* trampoline_pg had a refcount of 2 earlier, so we need to dec once more to free it
+        * but only if all cores are in (or we reset / reinit those that failed) */
+       if (x86_num_cores_booted == num_cores) {
                page_decref(pa2page(trampoline_pg));
+       } else {
+               warn("ACPI/MP found %d cores, smp_boot initialized %d, using %d\n",
+                    num_cores, x86_num_cores_booted, x86_num_cores_booted);
+               num_cores = x86_num_cores_booted;
+       }
        // Dealloc the temp shared stack
        page_decref(smp_stack);
 
@@ -257,10 +223,6 @@ uintptr_t smp_main(void)
                cprintf("I am an Application Processor\n");
        cprintf("Num_Cores: %d\n\n", num_cores);
        */
-       /* set up initial mappings.  core0 will adjust it later */
-       unsigned long my_hw_id = lapic_get_id();
-       os_coreid_lookup[my_hw_id] = my_hw_id;
-       hw_coreid_lookup[my_hw_id] = my_hw_id;
 
        // Get a per-core kernel stack
        uintptr_t my_stack_top = get_kstack();
@@ -299,8 +261,6 @@ uintptr_t smp_main(void)
 
        apiconline();
 
-       // set a default logical id for now
-       lapic_set_logid(lapic_get_id());
 
        return my_stack_top; // will be loaded in smp_entry.S
 }
@@ -314,17 +274,22 @@ void __arch_pcpu_init(uint32_t coreid)
 {
        uintptr_t *my_stack_bot;
        struct per_cpu_info *pcpui = &per_cpu_info[coreid];
+       uint32_t eax, edx;
 
        /* Flushes any potentially old mappings from smp_boot() (note the page table
         * removal) */
        tlbflush();
-       /* Ensure the FPU units are initialized */
-       asm volatile ("fninit");
 
        /* Enable SSE instructions.  We might have to do more, like masking certain
         * flags or exceptions in the MXCSR, or at least handle the SIMD exceptions.
         * We don't do it for FP yet either, so YMMV. */
-       lcr4(rcr4() | CR4_OSFXSR | CR4_OSXMME);
+       lcr4(rcr4() | CR4_OSFXSR | CR4_OSXMME | CR4_OSXSAVE);
+
+       // Set xcr0 to the Akaros-wide default
+       lxcr0(x86_default_xcr0);
+
+       // Initialize fpu and extended state by restoring our default XSAVE area.
+       init_fp_state();
 
        /* core 0 sets up via the global gdt symbol */
        if (!coreid) {
@@ -340,7 +305,8 @@ void __arch_pcpu_init(uint32_t coreid)
        assert(read_msr(MSR_KERN_GS_BASE) == (uint64_t)pcpui);
        /* 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();
+       /* need to init perfctr before potentially using it in timer handler */
+       perfmon_pcpu_init();
        vmm_pcpu_init();
+       lcr4(rcr4() & ~CR4_TSD);
 }