commit 9946b51c909edc0e79529971d104282dcdc77814
parent 6c8e36b21b75ce984120b1eb8a701961bc60dfa2
Author: Brian Swetland <swetland@frotz.net>
Date: Sat, 4 Jan 2014 16:26:56 -0800
enable SMP in 64bit build
- in startothers() we pass entry32mp instead of entrymp as the
address that entryother will jump to in 32bit mode
- don't initialize paging in entryother in the 64bit build
since we defer that until we switch to 64bit mode
- entry32mp is an entrypoint midway through entry64.S that
shares much of the startup code for the secondary core(s)
with the bootstrap core
Diffstat:
3 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/kernel/entry64.S b/kernel/entry64.S
@@ -75,6 +75,14 @@ ptbl_loop:
dec %ecx
jnz ptbl_loop
+# Clear ebx for initial processor boot.
+# When secondary processors boot, they'll call through
+# entry32mp (from entryother), but with a nonzero ebx.
+# We'll reuse these bootstrap pagetables and GDT.
+ xor %ebx, %ebx
+
+.global entry32mp
+entry32mp:
# CR3 -> 0x1000 (P4ML)
mov $0x1000, %eax
mov %eax, %cr3
@@ -133,6 +141,10 @@ entry64high:
mov %ax, %fs
mov %ax, %gs
+# check to see if we're booting a secondary core
+ test %ebx, %ebx
+ jnz entry64mp
+
# setup initial stack
mov $0xFFFFFFFF80010000, %rax
mov %rax, %rsp
@@ -145,6 +157,12 @@ __deadloop:
# we should never return here...
jmp .
+entry64mp:
+# obtain kstack from data block before entryother
+ mov $0x7000, %rax
+ mov -16(%rax), %rsp
+ jmp mpenter
+
.global wrmsr
wrmsr:
mov %rdi, %rcx # arg0 -> msrnum
diff --git a/kernel/entryother.S b/kernel/entryother.S
@@ -49,6 +49,11 @@ start32:
movw %ax, %fs
movw %ax, %gs
+#if X64
+ # defer paging until we switch to 64bit mode
+ # set ebx=1 so shared boot code knows we're booting a secondary core
+ mov $1, %ebx
+#else
# Turn on page size extension for 4Mbyte pages
movl %cr4, %eax
orl $(CR4_PSE), %eax
@@ -60,6 +65,7 @@ start32:
movl %cr0, %eax
orl $(CR0_PE|CR0_PG|CR0_WP), %eax
movl %eax, %cr0
+#endif
# Switch to the stack allocated by startothers()
movl (start-4), %esp
diff --git a/kernel/main.c b/kernel/main.c
@@ -44,7 +44,7 @@ main(void)
}
// Other CPUs jump here from entryother.S.
-static void
+void
mpenter(void)
{
switchkvm();
@@ -64,6 +64,7 @@ mpmain(void)
}
pde_t entrypgdir[]; // For entry.S
+void entry32mp(void);
// Start the non-boot (AP) processors.
static void
@@ -88,9 +89,15 @@ startothers(void)
// pgdir to use. We cannot use kpgdir yet, because the AP processor
// is running in low memory, so we use entrypgdir for the APs too.
stack = kalloc();
+#if X64
+ *(uint32*)(code-4) = 0x8000; // just enough stack to get us to entry64mp
+ *(uint32*)(code-8) = v2p(entry32mp);
+ *(uint64*)(code-16) = (uint64) (stack + KSTACKSIZE);
+#else
*(void**)(code-4) = stack + KSTACKSIZE;
*(void**)(code-8) = mpenter;
*(int**)(code-12) = (void *) v2p(entrypgdir);
+#endif
lapicstartap(c->id, v2p(code));