95373b8d76c217d3d2acf0c68ef76e667a439f49
[akaros.git] / kern / arch / i386 / 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 #endif
10
11 #ifdef __IVY__
12 #pragma nodeputy
13 #endif
14
15 #include <arch/x86.h>
16 #include <arch/arch.h>
17 #include <smp.h>
18 #include <arch/console.h>
19 #include <arch/apic.h>
20 #include <timing.h>
21
22 #include <atomic.h>
23 #include <ros/error.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <assert.h>
27 #include <pmap.h>
28 #include <env.h>
29 #include <trap.h>
30 #include <timing.h>
31
32 extern handler_wrapper_t handler_wrappers[NUM_HANDLER_WRAPPERS];
33 volatile uint8_t num_cpus = 0xee;
34 uintptr_t 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 static void smp_mtrr_handler(trapframe_t *tf, TV(t) data)
64 {
65         setup_default_mtrrs(data);
66 }
67
68 // this needs to be set in smp_entry too...
69 #define trampoline_pg 0x00001000
70 extern char (SNT SREADONLY smp_entry)[];
71 extern char (SNT SREADONLY smp_entry_end)[];
72 extern char (SNT SREADONLY smp_boot_lock)[];
73 extern char (SNT SREADONLY smp_semaphore)[];
74
75 static inline volatile uint32_t *COUNT(1)
76 get_smp_semaphore()
77 {
78         return (volatile uint32_t *COUNT(1))TC(smp_semaphore - smp_entry + trampoline_pg);
79 }
80
81 static inline uint32_t *COUNT(1)
82 get_smp_bootlock()
83 {
84         return (uint32_t *COUNT(1))TC(smp_boot_lock - smp_entry + trampoline_pg);
85 }
86
87 void smp_boot(void)
88 {
89         page_t *smp_stack;
90         // NEED TO GRAB A LOWMEM FREE PAGE FOR AP BOOTUP CODE
91         // page1 (2nd page) is reserved, hardcoded in pmap.c
92         memset(KADDR(trampoline_pg), 0, PGSIZE);
93         memcpy(KADDR(trampoline_pg), (void *COUNT(PGSIZE))TC(smp_entry),
94            smp_entry_end - smp_entry);
95
96         // This mapping allows access to the trampoline with paging on and off
97         // via trampoline_pg
98         page_insert(boot_pgdir, pa2page(trampoline_pg), (void*SNT)trampoline_pg, PTE_W);
99
100         // Allocate a stack for the cores starting up.  One for all, must share
101         if (page_alloc(&smp_stack))
102                 panic("No memory for SMP boot stack!");
103         page_incref(smp_stack);
104         smp_stack_top = (uintptr_t)(page2kva(smp_stack) + PGSIZE);
105
106         // Start the IPI process (INIT, wait, SIPI, wait, SIPI, wait)
107         send_init_ipi();
108         // SDM 3A is a little wonky wrt the proper delays.  These are my best guess.
109         udelay(10000);
110         // first SIPI
111         send_startup_ipi(0x01);
112         /* BOCHS does not like this second SIPI.
113         // second SIPI
114         udelay(200);
115         send_startup_ipi(0x01);
116         */
117         udelay(100000);
118
119         // Each core will also increment smp_semaphore, and decrement when it is done,
120         // all in smp_entry.  It's purpose is to keep Core0 from competing for the
121         // smp_boot_lock.  So long as one AP increments the sem before the final
122         // LAPIC timer goes off, all available cores will be initialized.
123         while(*get_smp_semaphore());
124
125         // From here on, no other cores are coming up.  Grab the lock to ensure it.
126         // Another core could be in it's prelock phase and be trying to grab the lock
127         // forever....
128         // The lock exists on the trampoline, so it can be grabbed right away in
129         // real mode.  If core0 wins the race and blocks other CPUs from coming up
130         // it can crash the machine if the other cores are allowed to proceed with
131         // booting.  Specifically, it's when they turn on paging and have that temp
132         // mapping pulled out from under them.  Now, if a core loses, it will spin
133         // on the trampoline (which we must be careful to not deallocate)
134         spin_lock(get_smp_bootlock());
135         cprintf("Num_Cpus Detected: %d\n", num_cpus);
136
137         // Remove the mapping of the page used by the trampoline
138         page_remove(boot_pgdir, (void*SNT)trampoline_pg);
139         // It had a refcount of 2 earlier, so we need to dec once more to free it
140         // but only if all cores are in (or we reset / reinit those that failed)
141         // TODO after we parse ACPI tables
142         if (num_cpus == 8) // TODO - ghetto coded for our 8 way SMPs
143                 page_decref(pa2page(trampoline_pg));
144         // Remove the page table used for that mapping
145         pagetable_remove(boot_pgdir, (void*SNT)trampoline_pg);
146         // Dealloc the temp shared stack
147         page_decref(smp_stack);
148
149         // Set up the generic remote function call facility
150         init_smp_call_function();
151
152         // Set up all cores to use the proper MTRRs
153         barrier_t generic_barrier;
154         init_barrier(&generic_barrier, num_cpus); // barrier used by smp_mtrr_handler
155         smp_call_function_all(smp_mtrr_handler, &generic_barrier, 0);
156
157         // Should probably flush everyone's TLB at this point, to get rid of
158         // temp mappings that were removed.  TODO
159 }
160
161 /* zra: sometimes Deputy needs some hints */
162 static inline void *COUNT(sizeof(pseudodesc_t))
163 get_my_gdt_pd(page_t *my_stack)
164 {
165         return page2kva(my_stack) + (PGSIZE - sizeof(pseudodesc_t) -
166                                      sizeof(segdesc_t)*SEG_COUNT);
167 }
168
169 //static inline void *COUNT(sizeof(segdesc_t)*SEG_COUNT)
170 static inline segdesc_t *COUNT(SEG_COUNT)
171 get_my_gdt(page_t *my_stack)
172 {
173         return TC(page2kva(my_stack) + PGSIZE - sizeof(segdesc_t)*SEG_COUNT);
174 }
175
176 static inline void *COUNT(sizeof(taskstate_t))
177 get_my_ts(page_t *my_stack)
178 {
179         return page2kva(my_stack) + PGSIZE -
180                 sizeof(pseudodesc_t) - sizeof(segdesc_t)*SEG_COUNT -
181                 sizeof(taskstate_t);
182 }
183
184 /*
185  * This is called from smp_entry by each core to finish the core bootstrapping.
186  * There is a spinlock around this entire function in smp_entry, for a few reasons,
187  * the most important being that all cores use the same stack when entering here.
188  */
189 uint32_t smp_main(void)
190 {
191         /*
192         // Print some diagnostics.  Uncomment if there're issues.
193         cprintf("Good morning Vietnam!\n");
194         cprintf("This core's Default APIC ID: 0x%08x\n", lapic_get_default_id());
195         cprintf("This core's Current APIC ID: 0x%08x\n", lapic_get_id());
196         if (read_msr(IA32_APIC_BASE) & 0x00000100)
197                 cprintf("I am the Boot Strap Processor\n");
198         else
199                 cprintf("I am an Application Processor\n");
200         cprintf("Num_Cpus: %d\n\n", num_cpus);
201         */
202
203         // Get a per-core kernel stack
204         page_t *my_stack;
205         if (page_alloc(&my_stack))
206                 panic("Unable to alloc a per-core stack!");
207         page_incref(my_stack);
208         memset(page2kva(my_stack), 0, PGSIZE);
209
210         // Set up a gdt / gdt_pd for this core, stored at the top of the stack
211         // This is necessary, eagle-eyed readers know why
212         // GDT should be 4-byte aligned.  TS isn't aligned.  Not sure if it matters.
213         pseudodesc_t *my_gdt_pd = get_my_gdt_pd(my_stack);
214         segdesc_t *COUNT(SEG_COUNT) my_gdt = get_my_gdt(my_stack);
215         // TS also needs to be permanent
216         taskstate_t *my_ts = get_my_ts(my_stack);
217         // Usable portion of the KSTACK grows down from here
218         // Won't actually start using this stack til our first interrupt
219         // (issues with changing the stack pointer and then trying to "return")
220         uintptr_t my_stack_top = (uintptr_t)my_ts;
221         
222         // Set up MSR for SYSENTER 
223         write_msr(MSR_IA32_SYSENTER_CS, GD_KT);
224         write_msr(MSR_IA32_SYSENTER_ESP, my_stack_top);
225         write_msr(MSR_IA32_SYSENTER_EIP, (uint32_t) &sysenter_handler);
226
227         // Build and load the gdt / gdt_pd
228         memcpy(my_gdt, gdt, sizeof(segdesc_t)*SEG_COUNT);
229         *my_gdt_pd = (pseudodesc_t) {
230                 sizeof(segdesc_t)*SEG_COUNT - 1, (uintptr_t) my_gdt };
231         asm volatile("lgdt %0" : : "m"(*my_gdt_pd));
232
233         // Need to set the TSS so we know where to trap on this core
234         my_ts->ts_esp0 = my_stack_top;
235         my_ts->ts_ss0 = GD_KD;
236         // Initialize the TSS field of my_gdt.
237         my_gdt[GD_TSS >> 3] = (segdesc_t)SEG16(STS_T32A, (uint32_t) (my_ts),
238                               sizeof(taskstate_t), 0);
239         my_gdt[GD_TSS >> 3].sd_s = 0;
240         // Load the TSS
241         ltr(GD_TSS);
242
243         // Loads the same IDT used by the other cores
244         asm volatile("lidt idt_pd");
245
246         // APIC setup
247         // set LINT0 to receive ExtINTs (KVM's default).  At reset they are 0x1000.
248         write_mmreg32(LAPIC_LVT_LINT0, 0x700);
249         // mask it to shut it up for now.  Doesn't seem to matter yet, since both
250         // KVM and Bochs seem to only route the PIC to core0.
251         mask_lapic_lvt(LAPIC_LVT_LINT0);
252         // and then turn it on
253         lapic_enable();
254
255         // set a default logical id for now
256         lapic_set_logid(lapic_get_id());
257
258         return my_stack_top; // will be loaded in smp_entry.S
259 }
260