x86: Use ACPI/MP for num_cores detection
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 23 Jul 2015 08:47:32 +0000 (04:47 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 24 Jul 2015 07:05:13 +0000 (03:05 -0400)
Previously, we'd use whatever booted up to determine the num_cores.  But
we would not know how many cores there should have been, and which may
be responding to SIPIs still.

That info is in the ACPI/MP tables.  Now, we can detect if the wrong
number of cores come online, and if the right number booted, we can free
the trapoline without any guesswork.

A couple other things:

The volatile on num_cores was probably due to early versions of the boot
code where C code needed to worry that assembly code was concurrently
incrementing num_cores/num_cpus.  That doesn't seem to be needed for
x86_num_cores_booted, let alone num_cores.

The u32 vs int for num_cores might also be for old code, where I didn't
want the variable to be negative ever.  Or more likely it was a
scalability joke.  Now that it's an int, we just went from 4 billion to
2 billion cores!  Oh no!

Setting num_cores to 1 in entry64.S, while its value in .data was 0xee
was just crazy.

kern/arch/x86/entry64.S
kern/arch/x86/smp_boot.c
kern/arch/x86/smp_entry64.S
kern/arch/x86/trap.c
kern/include/smp.h

index e662f89..a69398d 100644 (file)
@@ -400,8 +400,6 @@ long_mode:
        # Clear the frame pointer for proper backtraces
        movq    $0x0, %rbp
        movabs  $(bootstacktop), %rsp
-       movabs  $(num_cores), %rax
-       movl    $0x1, (%rax)
        # Pass multiboot info to kernel_init (%rdi == arg1)
        movq    %rbx, %rdi
        movabs  $(kernel_init), %rax
index 8a20063..25b08c8 100644 (file)
@@ -26,7 +26,8 @@
 #include "vmm/vmm.h"
 
 extern handler_wrapper_t handler_wrappers[NUM_HANDLER_WRAPPERS];
-volatile uint32_t num_cores = 0xee;
+int num_cores = 1;
+int x86_num_cores_booted = 1;
 uintptr_t smp_stack_top;
 barrier_t generic_barrier;
 
@@ -210,7 +211,7 @@ 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);
@@ -219,11 +220,15 @@ void smp_boot(void)
 
        /* 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);
 
index 0592302..4255690 100644 (file)
@@ -78,7 +78,7 @@ long_mode:
        mov             %ax, %fs
        mov             %ax, %gs
        lldt    %ax
-       incl    num_cores               # uint32_t
+       incl    x86_num_cores_booted            # an int
        movq    (smp_stack_top), %rsp
        movq    $0, %rbp                # so backtrace works
        # We're on the trampoline, but want to be in the real location of the smp
index 162d16b..0e8c9fc 100644 (file)
@@ -163,7 +163,8 @@ void idt_init(void)
 
        ncleft = mpsinit(ncleft);
        ncleft = mpacpi(ncleft);
-       printk("MP and ACPI found %d cores\n", MAX_NUM_CORES - ncleft);
+       num_cores = MAX_NUM_CORES - ncleft;
+       printk("MP and ACPI found %d cores\n", num_cores);
 
        apiconline();
        ioapiconline();
index c9dae0b..d7e47cd 100644 (file)
@@ -86,7 +86,7 @@ struct per_cpu_info {
 typedef struct per_cpu_info  per_cpu_info_t;
 
 extern per_cpu_info_t per_cpu_info[MAX_NUM_CORES];
-extern volatile uint32_t num_cores;
+extern int num_cores;
 
 /* SMP bootup functions */
 void smp_boot(void);