96bdba6024d6f3eba8d0a272953c0cfd93868902
[akaros.git] / kern / arch / x86 / smp_boot.c
1 /*
2  * Copyright (c) 2009 The Regents of the University of California
3  * Barret Rhoden <brho@cs.berkeley.edu>
4  * See LICENSE for details.
5  */
6
7 #include <arch/x86.h>
8 #include <arch/arch.h>
9 #include <smp.h>
10 #include <arch/console.h>
11 #include <arch/apic.h>
12 #include <arch/perfmon.h>
13 #include <time.h>
14
15 #include <bitmask.h>
16 #include <atomic.h>
17 #include <error.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <assert.h>
21 #include <pmap.h>
22 #include <env.h>
23 #include <trap.h>
24 #include <kmalloc.h>
25
26 #include "vmm/vmm.h"
27
28 extern handler_wrapper_t handler_wrappers[NUM_HANDLER_WRAPPERS];
29 volatile uint32_t num_cpus = 0xee;
30 uintptr_t smp_stack_top;
31 barrier_t generic_barrier;
32
33 #define DECLARE_HANDLER_CHECKLISTS(vector)                          \
34         INIT_CHECKLIST(f##vector##_cpu_list, MAX_NUM_CPUS);
35
36 #define INIT_HANDLER_WRAPPER(v)                                     \
37 {                                                                   \
38         handler_wrappers[(v)].vector = 0xe##v;                          \
39         handler_wrappers[(v)].cpu_list = &f##v##_cpu_list;              \
40         handler_wrappers[(v)].cpu_list->mask.size = num_cpus;           \
41 }
42
43 DECLARE_HANDLER_CHECKLISTS(0);
44 DECLARE_HANDLER_CHECKLISTS(1);
45 DECLARE_HANDLER_CHECKLISTS(2);
46 DECLARE_HANDLER_CHECKLISTS(3);
47 DECLARE_HANDLER_CHECKLISTS(4);
48
49 static void init_smp_call_function(void)
50 {
51         INIT_HANDLER_WRAPPER(0);
52         INIT_HANDLER_WRAPPER(1);
53         INIT_HANDLER_WRAPPER(2);
54         INIT_HANDLER_WRAPPER(3);
55         INIT_HANDLER_WRAPPER(4);
56 }
57
58 /******************************************************************************/
59
60 bool core_id_ready = FALSE;
61
62 static void setup_rdtscp(int coreid)
63 {
64         uint32_t edx;
65         int rdtscp_ecx;
66         /* TODO: have some sort of 'cpu info structure' with flags */
67         cpuid(0x80000001, 0x0, 0, 0, 0, &edx);
68         if (edx & (1 << 27)) {
69                 write_msr(MSR_TSC_AUX, coreid);
70                 /* Busted versions of qemu bug out here (32 bit) */
71                 asm volatile ("rdtscp" : "=c"(rdtscp_ecx) : : "eax", "edx");
72                 if (!coreid && (read_msr(MSR_TSC_AUX) != rdtscp_ecx))
73                         printk("\nBroken rdtscp detected, don't trust it for pcoreid!\n\n");
74         }
75 }
76
77 /* TODO: consider merging __arch_pcpu with parts of this (sync with RISCV) */
78 void smp_final_core_init(void)
79 {
80         /* It is possible that the non-0 cores will wake up before the broadcast
81          * ipi.  this can be due to spurious IRQs or some such.  anyone other than
82          * core 0 that comes in here will wait til core 0 has set everything up.
83          * those other cores might have come up before core 0 remapped the coreids,
84          * so we can only look at the HW coreid, which is only 0 for core 0. */
85         static bool wait = TRUE;
86         if (hw_core_id() == 0)
87                 wait = FALSE;
88         while (wait)
89                 cpu_relax();
90         /* at this point, it is safe to get the OS coreid */
91         int coreid = get_os_coreid(hw_core_id());
92         struct per_cpu_info *pcpui = &per_cpu_info[coreid];
93         pcpui->coreid = coreid;
94         write_msr(MSR_GS_BASE, (uint64_t)pcpui);
95         write_msr(MSR_KERN_GS_BASE, (uint64_t)pcpui);
96         /* don't need this for the kernel anymore, but userspace can still use it */
97         setup_rdtscp(coreid);
98         /* After this point, all cores have set up their segmentation and whatnot to
99          * be able to do a proper core_id().  As a note to posterity, using the
100          * LAPIC coreid (like get_hw_coreid()) needs the LAPIC set up, which happens
101          * by the end of vm_init() */
102         waiton_barrier(&generic_barrier);
103         if (hw_core_id() == 0) {
104                 core_id_ready = TRUE;
105         }
106         /* being paranoid with this, it's all a bit ugly */
107         waiton_barrier(&generic_barrier);
108         setup_default_mtrrs(&generic_barrier);
109         smp_percpu_init();
110         waiton_barrier(&generic_barrier);
111 }
112
113 // this needs to be set in smp_entry too...
114 #define trampoline_pg 0x00001000UL
115 extern char smp_entry[];
116 extern char smp_entry_end[];
117 extern char smp_boot_lock[];
118 extern char smp_semaphore[];
119
120 static inline uint16_t *get_smp_semaphore()
121 {
122         return (uint16_t *)(smp_semaphore - smp_entry + trampoline_pg);
123 }
124
125 static void __spin_bootlock_raw(void)
126 {
127         uint16_t *bootlock = (uint16_t*)(smp_boot_lock - smp_entry + trampoline_pg);
128         /* Same lock code as in smp_entry */
129         asm volatile ("movw $1, %%ax;   "
130                                   "1:               "
131                       "xchgw %%ax, %0;  "
132                       "test %%ax, %%ax; "
133                       "jne 1b;" : : "m"(*bootlock) : "eax", "cc", "memory");
134 }
135
136 /* hw_coreid_lookup will get packed, but keep it's hw values.  
137  * os_coreid_lookup will remain sparse, but it's values will be consecutive.
138  * for both arrays, -1 means an empty slot.  hw_step tracks the next valid entry
139  * in hw_coreid_lookup, jumping over gaps of -1's. */
140 static void smp_remap_coreids(void)
141 {
142         for (int i = 0, hw_step = 0; i < num_cpus; i++, hw_step++) {
143                 if (hw_coreid_lookup[i] == -1) {
144                         while (hw_coreid_lookup[hw_step] == -1) {
145                                 hw_step++;
146                                 if (hw_step == MAX_NUM_CPUS)
147                                         panic("Mismatch in num_cpus and hw_step");
148                         }
149                         hw_coreid_lookup[i] = hw_coreid_lookup[hw_step];
150                         hw_coreid_lookup[hw_step] = -1;
151                         os_coreid_lookup[hw_step] = i;
152                 }
153         }
154 }
155
156 void smp_boot(void)
157 {
158         struct per_cpu_info *pcpui0 = &per_cpu_info[0];
159         /* set core0's mappings */
160         assert(lapic_get_id() == 0);
161         os_coreid_lookup[0] = 0;
162         hw_coreid_lookup[0] = 0;
163
164         page_t *smp_stack;
165         // NEED TO GRAB A LOWMEM FREE PAGE FOR AP BOOTUP CODE
166         // page1 (2nd page) is reserved, hardcoded in pmap.c
167         memset(KADDR(trampoline_pg), 0, PGSIZE);
168         memcpy(KADDR(trampoline_pg), (void *)smp_entry,
169            smp_entry_end - smp_entry);
170
171         /* Make sure the trampoline page is mapped.  64 bit already has the tramp pg
172          * mapped (1 GB of lowmem), so this is a nop. */
173
174         // Allocate a stack for the cores starting up.  One for all, must share
175         if (kpage_alloc(&smp_stack))
176                 panic("No memory for SMP boot stack!");
177         smp_stack_top = (uintptr_t)(page2kva(smp_stack) + PGSIZE);
178
179         /* During SMP boot, core_id_early() returns 0, so all of the cores, which
180          * grab locks concurrently, share the same pcpui and thus the same
181          * lock_depth.  We need to disable checking until core_id works properly. */
182         pcpui0->__lock_checking_enabled = 0;
183         // Start the IPI process (INIT, wait, SIPI, wait, SIPI, wait)
184         send_init_ipi();
185         // SDM 3A is a little wonky wrt the proper delays.  These are my best guess.
186         udelay(10000);
187         // first SIPI
188         send_startup_ipi(0x01);
189         /* BOCHS does not like this second SIPI.
190         // second SIPI
191         udelay(200);
192         send_startup_ipi(0x01);
193         */
194         udelay(500000);
195
196         // Each core will also increment smp_semaphore, and decrement when it is done,
197         // all in smp_entry.  It's purpose is to keep Core0 from competing for the
198         // smp_boot_lock.  So long as one AP increments the sem before the final
199         // LAPIC timer goes off, all available cores will be initialized.
200         while (*get_smp_semaphore())
201                 cpu_relax();
202
203         // From here on, no other cores are coming up.  Grab the lock to ensure it.
204         // Another core could be in it's prelock phase and be trying to grab the lock
205         // forever....
206         // The lock exists on the trampoline, so it can be grabbed right away in
207         // real mode.  If core0 wins the race and blocks other CPUs from coming up
208         // it can crash the machine if the other cores are allowed to proceed with
209         // booting.  Specifically, it's when they turn on paging and have that temp
210         // mapping pulled out from under them.  Now, if a core loses, it will spin
211         // on the trampoline (which we must be careful to not deallocate)
212         __spin_bootlock_raw();
213         printk("Number of Cores Detected: %d\n", num_cpus);
214 #ifdef CONFIG_DISABLE_SMT
215         assert(!(num_cpus % 2));
216         printk("Using only %d Idlecores (SMT Disabled)\n", num_cpus >> 1);
217 #endif /* CONFIG_DISABLE_SMT */
218         smp_remap_coreids();
219
220         /* cleans up the trampoline page, and any other low boot mem mappings */
221         x86_cleanup_bootmem();
222         // It had a refcount of 2 earlier, so we need to dec once more to free it
223         // but only if all cores are in (or we reset / reinit those that failed)
224         // TODO after we parse ACPI tables
225         if (num_cpus == 8) // TODO - ghetto coded for our 8 way SMPs
226                 page_decref(pa2page(trampoline_pg));
227         // Dealloc the temp shared stack
228         page_decref(smp_stack);
229
230         // Set up the generic remote function call facility
231         init_smp_call_function();
232
233         /* Final core initialization */
234         init_barrier(&generic_barrier, num_cpus);
235         /* This will break the cores out of their hlt in smp_entry.S */
236         send_broadcast_ipi(I_POKE_CORE);
237         smp_final_core_init();  /* need to init ourselves as well */
238 }
239
240 /* This is called from smp_entry by each core to finish the core bootstrapping.
241  * There is a spinlock around this entire function in smp_entry, for a few
242  * reasons, the most important being that all cores use the same stack when
243  * entering here.
244  *
245  * Do not use per_cpu_info in here.  Do whatever you need in smp_percpu_init().
246  */
247 uintptr_t smp_main(void)
248 {
249         /*
250         // Print some diagnostics.  Uncomment if there're issues.
251         cprintf("Good morning Vietnam!\n");
252         cprintf("This core's Default APIC ID: 0x%08x\n", lapic_get_default_id());
253         cprintf("This core's Current APIC ID: 0x%08x\n", lapic_get_id());
254         if (read_msr(IA32_APIC_BASE) & 0x00000100)
255                 cprintf("I am the Boot Strap Processor\n");
256         else
257                 cprintf("I am an Application Processor\n");
258         cprintf("Num_Cpus: %d\n\n", num_cpus);
259         */
260         /* set up initial mappings.  core0 will adjust it later */
261         unsigned long my_hw_id = lapic_get_id();
262         os_coreid_lookup[my_hw_id] = my_hw_id;
263         hw_coreid_lookup[my_hw_id] = my_hw_id;
264
265         // Get a per-core kernel stack
266         uintptr_t my_stack_top = get_kstack();
267
268         /* This blob is the GDT, the GDT PD, and the TSS. */
269         unsigned int blob_size = sizeof(segdesc_t) * SEG_COUNT +
270                                  sizeof(pseudodesc_t) + sizeof(taskstate_t);
271         /* TODO: don't use kmalloc - might have issues in the future */
272         void *gdt_etc = kmalloc(blob_size, 0);          /* we'll never free this btw */
273         taskstate_t *my_ts = gdt_etc;
274         pseudodesc_t *my_gdt_pd = (void*)my_ts + sizeof(taskstate_t);
275         segdesc_t *my_gdt = (void*)my_gdt_pd + sizeof(pseudodesc_t);
276         /* This is a bit ghetto: we need to communicate our GDT and TSS's location
277          * to smp_percpu_init(), but we can't trust our coreid (since they haven't
278          * been remapped yet (so we can't write it directly to per_cpu_info)).  So
279          * we use the bottom of the stack page... */
280         *kstack_bottom_addr(my_stack_top) = (uintptr_t)gdt_etc;
281
282         // Build and load the gdt / gdt_pd
283         memcpy(my_gdt, gdt, sizeof(segdesc_t)*SEG_COUNT);
284         *my_gdt_pd = (pseudodesc_t) {
285                 sizeof(segdesc_t)*SEG_COUNT - 1, (uintptr_t) my_gdt };
286         asm volatile("lgdt %0" : : "m"(*my_gdt_pd));
287
288         /* Set up our kernel stack when changing rings */
289         x86_set_stacktop_tss(my_ts, my_stack_top);
290         // Initialize the TSS field of my_gdt.
291         syssegdesc_t *ts_slot = (syssegdesc_t*)&my_gdt[GD_TSS >> 3];
292         *ts_slot = (syssegdesc_t)SEG_SYS_SMALL(STS_T32A, (uintptr_t)my_ts,
293                                                sizeof(taskstate_t), 0);
294         // Load the TSS
295         ltr(GD_TSS);
296
297         // Loads the same IDT used by the other cores
298         asm volatile("lidt %0" : : "m"(idt_pd));
299
300         apiconline();
301
302         // set a default logical id for now
303         lapic_set_logid(lapic_get_id());
304
305         return my_stack_top; // will be loaded in smp_entry.S
306 }
307
308 /* Perform any initialization needed by per_cpu_info.  Make sure every core
309  * calls this at some point in the smp_boot process.  If you don't smp_boot, you
310  * must still call this for core 0.  This must NOT be called from smp_main,
311  * since it relies on the kernel stack pointer to find the gdt.  Be careful not
312  * to call it on too deep of a stack frame. */
313 void __arch_pcpu_init(uint32_t coreid)
314 {
315         uintptr_t *my_stack_bot;
316         struct per_cpu_info *pcpui = &per_cpu_info[coreid];
317
318         /* Flushes any potentially old mappings from smp_boot() (note the page table
319          * removal) */
320         tlbflush();
321         /* Ensure the FPU units are initialized */
322         asm volatile ("fninit");
323
324         /* Enable SSE instructions.  We might have to do more, like masking certain
325          * flags or exceptions in the MXCSR, or at least handle the SIMD exceptions.
326          * We don't do it for FP yet either, so YMMV. */
327         lcr4(rcr4() | CR4_OSFXSR | CR4_OSXMME);
328
329         /* core 0 sets up via the global gdt symbol */
330         if (!coreid) {
331                 pcpui->tss = &ts;
332                 pcpui->gdt = gdt;
333         } else {
334                 my_stack_bot = kstack_bottom_addr(ROUNDUP(read_sp() - 1, PGSIZE));
335                 pcpui->tss = (taskstate_t*)(*my_stack_bot);
336                 pcpui->gdt = (segdesc_t*)(*my_stack_bot +
337                                           sizeof(taskstate_t) + sizeof(pseudodesc_t));
338         }
339         assert(read_msr(MSR_GS_BASE) == (uint64_t)pcpui);
340         assert(read_msr(MSR_KERN_GS_BASE) == (uint64_t)pcpui);
341         /* Don't try setting up til after setting GS */
342         x86_sysenter_init(x86_get_stacktop_tss(pcpui->tss));
343         /* need to init perfctr before potentiall using it in timer handler */
344         perfmon_init();
345         vmm_pcpu_init();
346 }