Skip to content

Commit 2cc9f00

Browse files
committed
Almost fixed 64 bit AP trampoline code
1 parent 4f50687 commit 2cc9f00

File tree

4 files changed

+113
-63
lines changed

4 files changed

+113
-63
lines changed

kernel/build.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ target_compile_ap_startup() {
7070

7171
$NASM -f bin -o "$AP_STARTUP_OBJ" -s "$AP_STARTUP_SRC"
7272
failOnError
73-
mv "$AP_STARTUP_OBJ" "$AP_STARTUP_TGT"
73+
cp "$AP_STARTUP_OBJ" "$AP_STARTUP_TGT"
7474
list $AP_STARTUP_OBJ
7575
}
7676

kernel/inc/shared/memory/constants.hpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@
2121
#ifndef __MEMORY_CONSTANTS__
2222
#define __MEMORY_CONSTANTS__
2323

24-
#define G_SMP_STARTUP_AREA 0x00000500
25-
#define G_SMP_STARTUP_AREA_PAGEDIR 0x00000500 // initial page directory address is put here
26-
#define G_SMP_STARTUP_AREA_AP_ENTRY 0x00000504 // kernel entry point for AP
27-
#define G_SMP_STARTUP_AREA_AP_COUNTER 0x00000508 // counter for stack array indexing
28-
#define G_SMP_STARTUP_AREA_AP_STACK_ARRAY 0x0000050C // array of stacks
29-
#define G_SMP_STARTUP_AREA_CODE_START 0x00001000 // must be 000XX000, used for SIPI
30-
#define G_SMP_STARTUP_AREA_END 0x00007BFF
24+
#define G_SMP_STARTUP_AREA 0x500
25+
#define G_SMP_STARTUP_AREA_PAGEDIR 0x500 // initial page directory address is put here
26+
#define G_SMP_STARTUP_AREA_AP_ENTRY 0x508 // kernel entry point for AP
27+
#define G_SMP_STARTUP_AREA_AP_COUNTER 0x510 // counter for stack pointer array indexing
28+
#define G_SMP_STARTUP_AREA_AP_STACK_ARRAY 0x518 // array of stack pointers
29+
#define G_SMP_STARTUP_AREA_CODE_START 0x1000 // must be 000XX000, used for SIPI
30+
#define G_SMP_STARTUP_AREA_END 0x7BFF
3131

3232
// TODO change values
3333
#define G_USER_MAXIMUM_HEAP_BREAK 0xA0000000

kernel/src/ap/ap_startup.asm

Lines changed: 68 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
; Loaded by the kernel to this location
3838
org 0x1000
3939

40-
; Initial setup
40+
; Real mode
4141
BITS 16
4242
startup:
4343
; Load the GDT
@@ -49,13 +49,13 @@ startup:
4949
mov cr0, eax
5050

5151
; Far-JMP into protected mode code
52-
jmp 0x08:protectedStart
52+
jmp 0x8:protectedStart
5353

5454

55-
; Protected mode for 64-bit (transition to 64-bit long mode)
56-
BITS 64
55+
; Protected mode
56+
BITS 32
5757
protectedStart:
58-
; Set up code segments for 64-bit mode
58+
; Code segments were set by far JMP, set data segments
5959
mov ax, 0x10
6060
mov ds, ax
6161
mov es, ax
@@ -64,70 +64,97 @@ protectedStart:
6464
mov ss, ax
6565

6666
; Lock all cores
67-
acquireLock:
68-
lock bts qword [interlock], 0
67+
acquireLock:
68+
lock bts dword [interlock], 0
6969
jc acquireLock
7070

71-
; Set page directory
72-
mov rax, [0x500]
73-
mov cr3, rax
71+
; Enable PAE
72+
mov eax, cr4
73+
or eax, 1 << 5
74+
mov cr4, eax
7475

75-
; Enable paging
76-
mov rax, cr0
77-
or rax, 0x80000000
78-
mov cr0, rax
76+
; Set page directory
77+
mov eax, [0x500]
78+
mov cr3, eax
7979

80-
; Set "global pages" flag
81-
mov rax, cr4
82-
or rax, 0x80
83-
mov cr4, rax
80+
; Enable PGE
81+
mov eax, cr4
82+
or eax, 1 << 7
83+
mov cr4, eax
8484

85-
; Load stack from stack array
86-
mov rax, [0x508] ; current index
87-
shl rax, 2 ; multiply by 4 (size of one entry)
88-
mov rsp, [0x50C + rax] ; move entry to RSP
89-
mov rbp, rsp
85+
; Set up EFER MSR to enable long mode (EFER.LME)
86+
mov ecx, 0xC0000080
87+
rdmsr
88+
or eax, 1 << 8
89+
wrmsr
9090

91-
; Increment AP counter
92-
inc qword [0x508]
91+
; Enable paging
92+
mov eax, cr0
93+
or eax, 1 << 31
94+
mov cr0, eax
95+
96+
; Get index of this AP and increment counter
97+
mov eax, [0x510]
98+
inc dword [0x510]
9399

94100
; Release lock
95-
lock btr qword [interlock], 0
101+
lock btr dword [interlock], 0
102+
103+
; Far-jump to 64 bits
104+
jmp 0x18:longStart
96105

97-
; Jump to kernel
98-
call [0x504]
106+
; Long mode
107+
[BITS 64]
108+
longStart:
109+
; Set data segments
110+
mov bx, 0x10
111+
mov ds, bx
112+
mov ss, bx
99113

100-
; AP should never exit, just for safety
101-
hang:
102-
hlt
103-
jmp hang
114+
; 32-bit code provides AP index in EAX
115+
; From the stack array, take the entry at offset multiplied by 8
116+
shl rax, 3
117+
mov rsp, [0x518 + rax]
118+
mov rbp, rsp
104119

120+
; Jump into kernel code
121+
mov rax, [0x508]
122+
jmp rax
105123

106124
; Inter-core synchronization
107125
interlock:
108-
dd 0x00000000
126+
dd 0
109127

110128

111129
; Pointer to the GDT
112130
gdtPointer:
113-
dw 24
131+
dw 31
114132
dd gdt
115133

116-
; Basic setup GDT for x86_64
134+
; Basic setup GDT
117135
gdt:
118136
; null descriptor
119-
dq 0x0000000000000000
137+
dw 0x0000
138+
dw 0x0000
139+
dw 0x0000
140+
dw 0x0000
120141

121-
; code descriptor (64-bit)
142+
; code descriptor
122143
dw 0xFFFF
123144
dw 0x0000
124-
dw 0x9A00
145+
dw 0x9800
125146
dw 0x00CF
126-
dq 0x0000000000000000
127147

128-
; data descriptor (64-bit)
148+
; data descriptor
129149
dw 0xFFFF
130150
dw 0x0000
131151
dw 0x9200
132152
dw 0x00CF
133-
dq 0x0000000000000000
153+
154+
; code descriptor (64-bit)
155+
dw 0xFFFF
156+
dw 0x0000
157+
dw 0x9A00
158+
dw 0x00A0
159+
160+
; TODO 64 bit data segment?

kernel/src/kernel/system/smp.cpp

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,31 +26,51 @@
2626
#include "kernel/kernel.hpp"
2727
#include "shared/memory/constants.hpp"
2828
#include "shared/logger/logger.hpp"
29+
#include "kernel/memory/paging.hpp"
2930

3031
bool smpInitialized = false;
3132

3233
void smpInitialize(g_physical_address initialPageDirectoryPhysical)
3334
{
35+
// TODO: For all physical allocations below we must make sure that the memory is in 32 bit address range
36+
37+
// Identity-map lower memory
38+
for(g_address phys = 0; phys < G_SMP_STARTUP_AREA_END; phys += G_PAGE_SIZE)
39+
{
40+
pagingMapPage(phys, phys, G_PAGE_TABLE_KERNEL_DEFAULT, G_PAGE_KERNEL_DEFAULT);
41+
logInfo("Identitiy map %x to %x: %x", phys, phys, pagingVirtualToPhysical(phys));
42+
}
43+
44+
// Map it so we can write it here
45+
g_virtual_address mappedLower = addressRangePoolAllocate(memoryVirtualRangePool,
46+
G_PAGE_ALIGN_UP(G_SMP_STARTUP_AREA_END) / G_PAGE_SIZE);
47+
for(g_address phys = 0; phys < G_SMP_STARTUP_AREA_END; phys += G_PAGE_SIZE)
48+
{
49+
pagingMapPage(mappedLower + phys, phys, G_PAGE_TABLE_KERNEL_DEFAULT, G_PAGE_KERNEL_DEFAULT);
50+
}
51+
3452
// Write values to lower memory for use within startup code
35-
*((uint32_t*) G_SMP_STARTUP_AREA_PAGEDIR) = initialPageDirectoryPhysical;
36-
*((uint32_t*) G_SMP_STARTUP_AREA_AP_ENTRY) = (g_virtual_address) kernelRunApplicationCore;
37-
*((uint32_t*) G_SMP_STARTUP_AREA_AP_COUNTER) = 0;
53+
*((g_address*) (mappedLower + G_SMP_STARTUP_AREA_PAGEDIR)) = initialPageDirectoryPhysical;
54+
*((g_address*) (mappedLower + G_SMP_STARTUP_AREA_AP_ENTRY)) = (g_virtual_address) kernelRunApplicationCore;
55+
*((g_size*) (mappedLower + G_SMP_STARTUP_AREA_AP_COUNTER)) = 0;
3856

39-
logDebug("%! initial page directory for APs: %h", "smp", *((uint32_t*) G_SMP_STARTUP_AREA_PAGEDIR));
40-
logDebug("%! kernel entry point for APs: %h", "smp", *((uint32_t*) G_SMP_STARTUP_AREA_AP_ENTRY));
41-
logDebug("%! initial AP counter value: %i", "smp", *((uint32_t*) G_SMP_STARTUP_AREA_AP_COUNTER));
57+
logInfo("%! initial page directory for APs: %h, %x", "smp",
58+
*((g_address*) (mappedLower+G_SMP_STARTUP_AREA_PAGEDIR)),
59+
initialPageDirectoryPhysical);
60+
logInfo("%! kernel entry point for APs: %h", "smp", *((g_address*) (mappedLower+G_SMP_STARTUP_AREA_AP_ENTRY)));
61+
logInfo("%! initial AP counter value: %i", "smp", *((uint32_t*) (mappedLower+G_SMP_STARTUP_AREA_AP_COUNTER)));
4262

4363
// Create enough stacks for all APs
44-
g_physical_address* stackArray = (g_physical_address*) G_SMP_STARTUP_AREA_AP_STACK_ARRAY;
64+
auto stackArray = (g_physical_address*) (mappedLower + G_SMP_STARTUP_AREA_AP_STACK_ARRAY);
4565
for(uint32_t i = 0; i < processorGetNumberOfProcessors(); i++)
4666
{
47-
4867
g_physical_address stackPhysical = memoryPhysicalAllocate();
4968
if(stackPhysical == 0)
5069
{
5170
logInfo("%*%! could not allocate physical page for AP stack", 0x0C, "smp");
5271
return;
5372
}
73+
5474
g_virtual_address stackVirtual = addressRangePoolAllocate(memoryVirtualRangePool, 1);
5575
if(stackPhysical == 0)
5676
{
@@ -63,18 +83,19 @@ void smpInitialize(g_physical_address initialPageDirectoryPhysical)
6383
g_virtual_address stackTop = (stackVirtual + G_PAGE_SIZE);
6484
stackArray[i] = stackTop;
6585

66-
logDebug("%! created AP stack (%h) placed at %h", "smp", stackArray[i], &stackArray[i]);
86+
logInfo("%! created AP stack (%h -> %h) placed at %h", "smp", stackArray[i], stackPhysical,
87+
((g_address)&stackArray[i]) - mappedLower);
6788
}
6889

6990
// Copy start object from ramdisk to lower memory
70-
const char* ap_startup_location = "system/lib/apstartup.o";
71-
g_ramdisk_entry* startupObject = ramdiskFindAbsolute(ap_startup_location);
72-
if(startupObject == 0)
91+
const char* apStartupPath = "system/lib/apstartup.o";
92+
g_ramdisk_entry* startupObject = ramdiskFindAbsolute(apStartupPath);
93+
if(startupObject == nullptr)
7394
{
74-
logInfo("%*%! could not initialize due to missing apstartup object at '%s'", 0x0C, "smp", ap_startup_location);
95+
logInfo("%*%! could not initialize due to missing apstartup object at '%s'", 0x0C, "smp", apStartupPath);
7596
return;
7697
}
77-
memoryCopy((uint8_t*) G_SMP_STARTUP_AREA_CODE_START, (uint8_t*) startupObject->data, startupObject->dataSize);
98+
memoryCopy((uint8_t*) (mappedLower + G_SMP_STARTUP_AREA_CODE_START), startupObject->data, startupObject->dataSize);
7899

79100
smpInitialized = true;
80101

@@ -88,6 +109,8 @@ void smpInitialize(g_physical_address initialPageDirectoryPhysical)
88109
}
89110
core = core->next;
90111
}
112+
113+
logInfo("%! initial AP counter value: %i", "smp", *((uint32_t*) (mappedLower+G_SMP_STARTUP_AREA_AP_COUNTER)));
91114
}
92115

93116
void smpInitializeCore(g_processor* cpu)

0 commit comments

Comments
 (0)