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