x86: pcpu init called before idling
[akaros.git] / kern / arch / i686 / 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 #ifdef __SHARC__
8 #pragma nosharc
9 #define SINIT(x) x
10 #endif
11
12 #include <arch/x86.h>
13 #include <arch/arch.h>
14 #include <smp.h>
15 #include <arch/console.h>
16 #include <arch/apic.h>
17 #include <arch/bitmask.h>
18 #include <arch/perfmon.h>
19 #include <timing.h>
20
21 #include <atomic.h>
22 #include <error.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <assert.h>
26 #include <pmap.h>
27 #include <env.h>
28 #include <trap.h>
29 #include <timing.h>
30 #include <kmalloc.h>
31
32 extern handler_wrapper_t (RO handler_wrappers)[NUM_HANDLER_WRAPPERS];
33 volatile uint32_t num_cpus = 0xee;
34 uintptr_t RO smp_stack_top;
35
36 #define DECLARE_HANDLER_CHECKLISTS(vector)                          \
37         INIT_CHECKLIST(f##vector##_cpu_list, MAX_NUM_CPUS);
38
39 #define INIT_HANDLER_WRAPPER(v)                                     \
40 {                                                                   \
41         handler_wrappers[(v)].vector = 0xf##v;                          \
42         handler_wrappers[(v)].cpu_list = &f##v##_cpu_list;              \
43         handler_wrappers[(v)].cpu_list->mask.size = num_cpus;           \
44 }
45
46 DECLARE_HANDLER_CHECKLISTS(0);
47 DECLARE_HANDLER_CHECKLISTS(1);
48 DECLARE_HANDLER_CHECKLISTS(2);
49 DECLARE_HANDLER_CHECKLISTS(3);
50 DECLARE_HANDLER_CHECKLISTS(4);
51
52 static void init_smp_call_function(void)
53 {
54         INIT_HANDLER_WRAPPER(0);
55         INIT_HANDLER_WRAPPER(1);
56         INIT_HANDLER_WRAPPER(2);
57         INIT_HANDLER_WRAPPER(3);
58         INIT_HANDLER_WRAPPER(4);
59 }
60
61 /******************************************************************************/
62
63 #ifdef __IVY__
64 static void smp_final_core_init(trapframe_t *tf, barrier_t *data)
65 #else
66 static void smp_final_core_init(trapframe_t *tf, void *data)
67 #endif
68 {
69         setup_default_mtrrs(data);
70         smp_percpu_init();
71         waiton_barrier(data);
72 }
73
74 // this needs to be set in smp_entry too...
75 #define trampoline_pg 0x00001000
76 extern char (SNT SREADONLY smp_entry)[];
77 extern char (SNT SREADONLY smp_entry_end)[];
78 extern char (SNT SREADONLY smp_boot_lock)[];
79 extern char (SNT SREADONLY smp_semaphore)[];
80
81 static inline volatile uint32_t *COUNT(1)
82 get_smp_semaphore()
83 {
84         return (volatile uint32_t *COUNT(1))TC(smp_semaphore - smp_entry + trampoline_pg);
85 }
86
87 static inline uint32_t *COUNT(1)
88 get_smp_bootlock()
89 {
90         return (uint32_t *COUNT(1))TC(smp_boot_lock - smp_entry + trampoline_pg);
91 }
92
93 /* hw_coreid_lookup will get packed, but keep it's hw values.  
94  * os_coreid_lookup will remain sparse, but it's values will be consecutive.
95  * for both arrays, -1 means an empty slot.  hw_step tracks the next valid entry
96  * in hw_coreid_lookup, jumping over gaps of -1's. */
97 static void smp_remap_coreids(void)
98 {
99         for (int i = 0, hw_step = 0; i < num_cpus; i++, hw_step++) {
100                 if (hw_coreid_lookup[i] == -1) {
101                         while (hw_coreid_lookup[hw_step] == -1) {
102                                 hw_step++;
103                                 if (hw_step == MAX_NUM_CPUS)
104                                         panic("Mismatch in num_cpus and hw_step");
105                         }
106                         hw_coreid_lookup[i] = hw_coreid_lookup[hw_step];
107                         hw_coreid_lookup[hw_step] = -1;
108                         os_coreid_lookup[hw_step] = i;
109                 }
110         }
111 }
112
113 void smp_boot(void)
114 {
115         /* set core0's mappings */
116         assert(lapic_get_id() == 0);
117         os_coreid_lookup[0] = 0;
118         hw_coreid_lookup[0] = 0;
119
120         page_t *smp_stack;
121         // NEED TO GRAB A LOWMEM FREE PAGE FOR AP BOOTUP CODE
122         // page1 (2nd page) is reserved, hardcoded in pmap.c
123         memset(KADDR(trampoline_pg), 0, PGSIZE);
124         memcpy(KADDR(trampoline_pg), (void *COUNT(PGSIZE))TC(smp_entry),
125            smp_entry_end - smp_entry);
126
127         // This mapping allows access to the trampoline with paging on and off
128         // via trampoline_pg
129         page_insert(boot_pgdir, pa2page(trampoline_pg), (void*SNT)trampoline_pg, PTE_W);
130
131         // Allocate a stack for the cores starting up.  One for all, must share
132         if (kpage_alloc(&smp_stack))
133                 panic("No memory for SMP boot stack!");
134         smp_stack_top = SINIT((uintptr_t)(page2kva(smp_stack) + PGSIZE));
135
136         // Start the IPI process (INIT, wait, SIPI, wait, SIPI, wait)
137         send_init_ipi();
138         // SDM 3A is a little wonky wrt the proper delays.  These are my best guess.
139         udelay(10000);
140         // first SIPI
141         send_startup_ipi(0x01);
142         /* BOCHS does not like this second SIPI.
143         // second SIPI
144         udelay(200);
145         send_startup_ipi(0x01);
146         */
147         udelay(500000);
148
149         // Each core will also increment smp_semaphore, and decrement when it is done,
150         // all in smp_entry.  It's purpose is to keep Core0 from competing for the
151         // smp_boot_lock.  So long as one AP increments the sem before the final
152         // LAPIC timer goes off, all available cores will be initialized.
153         while(*get_smp_semaphore());
154
155         // From here on, no other cores are coming up.  Grab the lock to ensure it.
156         // Another core could be in it's prelock phase and be trying to grab the lock
157         // forever....
158         // The lock exists on the trampoline, so it can be grabbed right away in
159         // real mode.  If core0 wins the race and blocks other CPUs from coming up
160         // it can crash the machine if the other cores are allowed to proceed with
161         // booting.  Specifically, it's when they turn on paging and have that temp
162         // mapping pulled out from under them.  Now, if a core loses, it will spin
163         // on the trampoline (which we must be careful to not deallocate)
164         __spin_lock(get_smp_bootlock());
165         printk("Number of Cores Detected: %d\n", num_cpus);
166 #ifdef __CONFIG_DISABLE_SMT__
167         assert(!(num_cpus % 2));
168         printk("Using only %d Idlecores (SMT Disabled)\n", num_cpus >> 1);
169 #endif /* __CONFIG_DISABLE_SMT__ */
170         smp_remap_coreids();
171
172         // Remove the mapping of the page used by the trampoline
173         page_remove(boot_pgdir, (void*SNT)trampoline_pg);
174         // It had a refcount of 2 earlier, so we need to dec once more to free it
175         // but only if all cores are in (or we reset / reinit those that failed)
176         // TODO after we parse ACPI tables
177         if (num_cpus == 8) // TODO - ghetto coded for our 8 way SMPs
178                 page_decref(pa2page(trampoline_pg));
179         // Remove the page table used for that mapping
180         pagetable_remove(boot_pgdir, (void*SNT)trampoline_pg);
181         // Dealloc the temp shared stack
182         page_decref(smp_stack);
183
184         // Set up the generic remote function call facility
185         init_smp_call_function();
186
187         /* Final core initialization */
188         barrier_t generic_barrier;
189         init_barrier(&generic_barrier, num_cpus);
190         /* This will break the cores out of their hlt in smp_entry.S */
191         smp_call_function_all(smp_final_core_init, &generic_barrier, 0);
192 }
193
194 /* This is called from smp_entry by each core to finish the core bootstrapping.
195  * There is a spinlock around this entire function in smp_entry, for a few
196  * reasons, the most important being that all cores use the same stack when
197  * entering here.
198  *
199  * Do not use per_cpu_info in here.  Do whatever you need in smp_percpu_init().
200  */
201 uint32_t smp_main(void)
202 {
203         /*
204         // Print some diagnostics.  Uncomment if there're issues.
205         cprintf("Good morning Vietnam!\n");
206         cprintf("This core's Default APIC ID: 0x%08x\n", lapic_get_default_id());
207         cprintf("This core's Current APIC ID: 0x%08x\n", lapic_get_id());
208         if (read_msr(IA32_APIC_BASE) & 0x00000100)
209                 cprintf("I am the Boot Strap Processor\n");
210         else
211                 cprintf("I am an Application Processor\n");
212         cprintf("Num_Cpus: %d\n\n", num_cpus);
213         */
214         /* set up initial mappings.  core0 will adjust it later */
215         unsigned long my_hw_id = lapic_get_id();
216         os_coreid_lookup[my_hw_id] = my_hw_id;
217         hw_coreid_lookup[my_hw_id] = my_hw_id;
218
219         // Get a per-core kernel stack
220         page_t *my_stack;
221         if (kpage_alloc(&my_stack))
222                 panic("Unable to alloc a per-core stack!");
223         memset(page2kva(my_stack), 0, PGSIZE);
224         uintptr_t my_stack_top = (uintptr_t)page2kva(my_stack) + PGSIZE;
225
226         /* This blob is the GDT, the GDT PD, and the TSS. */
227         unsigned int blob_size = sizeof(segdesc_t) * SEG_COUNT +
228                                  sizeof(pseudodesc_t) + sizeof(taskstate_t);
229         void *gdt_etc = kmalloc(blob_size, 0);          /* we'll never free this btw */
230         taskstate_t *my_ts = gdt_etc;
231         pseudodesc_t *my_gdt_pd = (void*)my_ts + sizeof(taskstate_t);
232         segdesc_t *my_gdt = (void*)my_gdt_pd + sizeof(pseudodesc_t);
233         /* This is a bit ghetto: we need to communicate our GDT and TSS's location
234          * to smp_percpu_init(), but we can't trust our coreid (since they haven't
235          * been remapped yet (so we can't write it directly to per_cpu_info)).  So
236          * we use the bottom of the stack page... */
237         *(uintptr_t*)page2kva(my_stack) = (uintptr_t)gdt_etc;
238
239         // Set up MSR for SYSENTER 
240         write_msr(MSR_IA32_SYSENTER_CS, GD_KT);
241         write_msr(MSR_IA32_SYSENTER_ESP, my_stack_top);
242         write_msr(MSR_IA32_SYSENTER_EIP, (uint32_t) &sysenter_handler);
243
244         // Build and load the gdt / gdt_pd
245         memcpy(my_gdt, gdt, sizeof(segdesc_t)*SEG_COUNT);
246         *my_gdt_pd = (pseudodesc_t) {
247                 sizeof(segdesc_t)*SEG_COUNT - 1, (uintptr_t) my_gdt };
248         asm volatile("lgdt %0" : : "m"(*my_gdt_pd));
249
250         // Need to set the TSS so we know where to trap on this core
251         my_ts->ts_esp0 = my_stack_top;
252         my_ts->ts_ss0 = GD_KD;
253         // Initialize the TSS field of my_gdt.
254         my_gdt[GD_TSS >> 3] = (segdesc_t)SEG16(STS_T32A, (uint32_t) (my_ts),
255                               sizeof(taskstate_t), 0);
256         my_gdt[GD_TSS >> 3].sd_s = 0;
257         // Load the TSS
258         ltr(GD_TSS);
259
260         // Loads the same IDT used by the other cores
261         asm volatile("lidt idt_pd");
262
263         // APIC setup
264         // set LINT0 to receive ExtINTs (KVM's default).  At reset they are 0x1000.
265         write_mmreg32(LAPIC_LVT_LINT0, 0x700);
266         // mask it to shut it up for now.  Doesn't seem to matter yet, since both
267         // KVM and Bochs seem to only route the PIC to core0.
268         mask_lapic_lvt(LAPIC_LVT_LINT0);
269         // and then turn it on
270         lapic_enable();
271
272         // set a default logical id for now
273         lapic_set_logid(lapic_get_id());
274
275         return my_stack_top; // will be loaded in smp_entry.S
276 }
277
278 /* Perform any initialization needed by per_cpu_info.  Make sure every core
279  * calls this at some point in the smp_boot process.  If you don't smp_boot, you
280  * must still call this for core 0.  This must NOT be called from smp_main,
281  * since it relies on the kernel stack pointer to find the gdt.  Be careful not
282  * to call it on too deep of a stack frame. */
283 void smp_percpu_init(void)
284 {
285         uint32_t coreid = core_id();
286         uintptr_t my_stack_bot;
287
288         /* Flushes any potentially old mappings from smp_boot() (note the page table
289          * removal) */
290         tlbflush();
291         /* Ensure the FPU units are initialized */
292         asm volatile ("fninit");
293
294         /* Enable SSE instructions.  We might have to do more, like masking certain
295          * flags or exceptions in the MXCSR, or at least handle the SIMD exceptions.
296          * We don't do it for FP yet either, so YMMV. */
297         lcr4(rcr4() | CR4_OSFXSR | CR4_OSXMME);
298
299         /* core 0 sets up via the global gdt symbol */
300         if (!coreid) {
301                 per_cpu_info[0].tss = &ts;
302                 per_cpu_info[0].gdt = gdt;
303         } else {
304                 my_stack_bot = ROUNDDOWN(read_esp(), PGSIZE);
305                 per_cpu_info[coreid].tss = (taskstate_t*)(*(uintptr_t*)my_stack_bot);
306                 per_cpu_info[coreid].gdt = (segdesc_t*)(*(uintptr_t*)my_stack_bot +
307                                            sizeof(taskstate_t) + sizeof(pseudodesc_t));
308         }
309         per_cpu_info[coreid].spare = 0;
310         spinlock_init(&per_cpu_info[coreid].immed_amsg_lock);
311         STAILQ_INIT(&per_cpu_info[coreid].immed_amsgs);
312         spinlock_init(&per_cpu_info[coreid].routine_amsg_lock);
313         STAILQ_INIT(&per_cpu_info[coreid].routine_amsgs);
314         
315         /* need to init perfctr before potentiall using it in timer handler */
316         perfmon_init();
317 }