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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
|
#include <comus/limits.h>
.globl _start
.globl kernel_pml4
.globl kernel_pdpt_0
.globl kernel_pd_0
.globl kernel_pd_0_ents
.globl kernel_pd_1
.globl paging_pt
.extern main
.extern GDT
.section .multiboot
# multiboot header
mb_start:
# magic
.align 8
.long 0xe85250d6
.long 0
.long mb_end - mb_start
.long 0x100000000 - (0xe85250d6 + (mb_end - mb_start))
# info request
.align 8
.short 1
.short 1
.long 36
.long 1 # cmdline
.long 6 # mmap
.long 9 # elf section
.long 12 # efi64
.long 14 # rsdp
.long 15 # xsdp
.long 20 # efi64 IH
# bios entry
.align 8
.short 3
.short 0
.long 12
.long _start
# framebuffer
.align 8
.short 5
.short 1
.long 20
.long 720 # width
.long 480 # height
.long 32 # bpp
# efi boot services
.align 8
.short 7
.short 0
.long 8
# efi amd64 entry
.align 8
.short 9
.short 0
.long 12
.long _start_efi
# null
.align 8
.short 0
.short 0
.long 8
mb_end:
.section .bss
# kernel page tables
.align 4096
kernel_pml4:
.skip 4096
kernel_pdpt_0:
.skip 4096
kernel_pd_0:
.skip 4096
kernel_pd_0_ents:
.skip (4096*N_IDENT_PTS)
kernel_pd_1:
.skip 4096
paging_pt:
.skip 4096
# kernel stack
.align 16
kern_stack_start:
.skip 8192
kern_stack_end:
.section .data
.align 16
# access bits
.set PRESENT, 1 << 7
.set NOT_SYS, 1 << 4
.set EXEC, 1 << 3
.set DC, 1 << 2
.set RW, 1 << 1
.set ACCESSED, 1 << 0
# privlage level (access bit)
.set RING0, 0 << 5
.set RING1, 1 << 5
.set RING2, 2 << 5
.set RING3, 3 << 5
# flag bits
.set GRAN_4K, 1 << 7
.set SZ_32, 1 << 6
.set LONG_MODE, 1 << 5
# kernel gdt (long mode)
GDT:
# Null Segment (0x00)
.equ GDT.Null, . - GDT
.quad 0
# Kernel Code segment (0x08)
.equ GDT.Code, . - GDT
.long 0xFFFF
.byte 0
.byte PRESENT | NOT_SYS | EXEC | RW | RING0
.byte GRAN_4K | LONG_MODE | 0xF
.byte 0
# Kernel Data segment (0x10)
.equ GDT.Data, . - GDT
.long 0xFFFF
.byte 0
.byte PRESENT | NOT_SYS | RW | RING0
.byte GRAN_4K | SZ_32 | 0xF
.byte 0
# User Code Segment (0x18)
.equ GDT.UserCode, . - GDT
.long 0xFFFF
.byte 0
.byte PRESENT | NOT_SYS | EXEC | RW | RING3
.byte GRAN_4K | LONG_MODE | 0xF
.byte 0
# User Data Segment (0x20)
.equ GDT.UserData, . - GDT
.long 0xFFFF
.byte 0
.byte PRESENT | NOT_SYS | RW | RING3
.byte GRAN_4K | SZ_32 | 0xF
.byte 0
# TSS segment (0x28)
.equ GDT.TSS, . - GDT
.quad 0 # to be modified in kernel
# GDT Pointer
.equ GDT.Pointer, .
.word . - GDT - 1
.quad GDT
.section .text
.code32
_start:
# disable interrupts
cli
# setup stack
movl $kern_stack_end, %esp
movl $kern_stack_end, %ebp
# save multiboot (if using multiboot)
pushl $0
push %ebx
pushl $0
push %eax
# setup kernel paging structures
movl $kernel_pml4, %edi # zero out pml4
movl %edi, %cr3
xorl %eax, %eax
movl $0x1000, %ecx
rep stosl
movl %cr3, %edi
movl $kernel_pdpt_0 + 3, (%edi) # map pdpt
movl $kernel_pdpt_0, %edi
movl $kernel_pd_0 + 3, (%edi) # map pd 0
addl $8, %edi # map pd 1
movl $kernel_pd_1 + 3, (%edi)
movl $kernel_pd_0, %edi # map pd 0 ents
movl $kernel_pd_0_ents + 3, %ebx
movl $N_IDENT_PTS, %ecx
_start.map_pd_0:
movl %ebx, (%edi)
addl $(8 * 512), %ebx
addl $8, %edi
loop _start.map_pd_0
movl $kernel_pd_0_ents, %edi # identity map kernel
movl $0x03, %ebx
movl $(512 * N_IDENT_PTS), %ecx
_start.map_pd_0_ents:
movl %ebx, (%edi)
addl $0x1000, %ebx
addl $8, %edi
loop _start.map_pd_0_ents
# enable page address extension
movl %cr4, %eax
orl $(1 << 5), %eax
movl %eax, %cr4
# enable long mode
movl $0xC0000080, %ecx
rdmsr
orl $(1 << 8), %eax
wrmsr
# enable paging
movl %cr0, %eax
orl $(1 << 31), %eax
movl %eax, %cr0
# load gdt
lgdt GDT.Pointer
ljmp $GDT.Code, $code64
.code64
_start_efi:
# disable interrupts
cli
# setup stack
movq $kern_stack_end, %rsp
movq $kern_stack_end, %rbp
# save multiboot
pushq %rbx
pushq %rax
# load gdt
lgdt GDT.Pointer
pushq $GDT.Code
pushq $code64
retfq
code64:
# set segment registers
movw $GDT.Data, %dx
movw %dx, %ds
movw %dx, %es
movw %dx, %fs
movw %dx, %gs
movw %dx, %ss
# set ebp to 0 so we know where to end stack traces
xorq %rbp, %rbp
# pop multiboot header
pop %rdi
pop %rsi
call main
halt:
cli
hlt
jmp halt
|