summaryrefslogtreecommitdiff
path: root/src/kernel/smp_trampoline.asm
blob: 15b85e295efbe0c511f82601183a6eaf9d9ba808 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
global smp_bootstrap_stackarray
global smp_bootstrap_bsp
global smp_bootstrap_corecount

extern multicore_main

[bits 16]
smp_trampoline:
cli

xor ax, ax
mov ds, ax
lgdt [.gdt_descriptor_p]
mov eax, cr0
or eax, 0x1
mov cr0, eax ; now in long mode

jmp 0x8:.smp_protected


;________________________________________________________________________________________

;TODO find how to use old gdt
.gdt_start_p: ; we need to start with a null gdt
dd 0
dd 0

.gdt_code_p:
dw 0xffff
dw 0x0000
db 0x00
db 10011010b 
db 11001111b
db 0x0000

.gdt_data_p:
dw 0xffff
dw 0x0000
db 0x00
db 10010010b 
db 11001111b
db 0x0000

.gdt_end_p:

.gdt_descriptor_p: 
  dw .gdt_end_p - .gdt_start_p - 1 
dq .gdt_start_p

SMP_PROTECTED_CODE_SEGMENT equ .gdt_code_p - .gdt_start_p
SMP_PROTECTED_DATA_SEGMENT equ .gdt_data_p - .gdt_start_p

;________________________________________________________________________________________

.smp_protected:

[bits 32]
mov ax, SMP_PROTECTED_DATA_SEGMENT
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax

lgdt [.gdt_descriptor_l]


mov eax, 0x10000 ;TODO clarify _why_ this is a thing
mov cr3, eax

;setting up misc features
mov eax, cr4         
; PAE, OSFXSR, OSXMMEXCPT
or eax, 1 << 5 | 1 << 9 | 1 << 10
mov cr4, eax         


;set NX and LME
mov eax, 0x80000001
cpuid
and edx, 1 << 20
shr edx, 9
  
mov ecx, 0xc0000080
rdmsr
or eax, 1 << 8 | 1 << 11
or eax, edx
wrmsr


;enable paging 
mov eax, cr0
or eax, 1 << 31 | 1 << 0; 
and ax, ~(1 << 2)
mov cr0, eax


jmp SMP_LONG_CODE_SEGMENT:.counter

;________________________________________________________________________________________

[bits 64]
;TODO do we really need all this?
.gdt_start_l:
;and now we set up a temporary GDT creating a 1:1 mapping
dw 0xffff
dw 0
db 0 ;this is the invalid GDT
db 0
db 1
db 0

;now for the code GDT:
.gdt_code_l:
dw 0 ; segment limit 15:00 (I don't think this matters in 64 bit mode!)
dw 0 ; base address 15:00
db 0 ; base address 23:16
db 10011010b  
db 00100000b 
db 0

.gdt_data_l:
dw 0 
dw 0 
db 0 
db 10010010b  
db 00100000b  
db 0

.gdt_end_l: ; later calculates offset in defs below


.gdt_descriptor_l: 
  dw .gdt_end_l - .gdt_start_l - 1 
dq .gdt_start_l

SMP_LONG_CODE_SEGMENT equ .gdt_code_l - .gdt_start_l
SMP_LONG_DATA_SEGMENT equ .gdt_data_l - .gdt_start_l

.counter:
mov eax, 1
cpuid
shr ebx, 24
cmp bl, BYTE [smp_bootstrap_bsp]
jl .apic_below_bsp
sub bl, 1

.apic_below_bsp:

mov rax, QWORD [smp_bootstrap_stackarray]
debug:
mov rsp, QWORD [rax + rbx * 8]

mov rax, [smp_bootstrap_corecount]
inc BYTE [rax]

mov rax, multicore_main
jmp rax

align 8 
smp_bootstrap_stackarray: dq 0
smp_bootstrap_bsp: db 0
smp_bootstrap_corecount: db 0
times 512 - ($ - $$) db 0