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
|
.globl _start
.globl kernel_pml4
.globl kernel_pdpt_0
.globl kernel_pd_0
.globl kernel_pt_0
.globl paging_pt
.globl bootstrap_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 20
.long 1 # cmdline
.long 6 # mmap
.long 9 # elf section
# 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: # reserve memory for initial 512 pml4 entires
.skip 4096
kernel_pdpt_0: # reserve memory for initial 512 pdpt entires
.skip 4096
kernel_pd_0: # reserve memory for initial 512 pd entries
.skip 4096
kernel_pt_0: # reserve memory for initial 512 pt entries
.skip 4096
paging_pt: # reserve pages for pager mappings
.skip 4096
bootstrap_pt: # reserve pages to bootstrap pager
.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
# zero out kernel page table
movl $kernel_pml4, %edi
movl %edi, %cr3
xorl %eax, %eax
movl $4096, %ecx # zero 4096 pages
rep stosl
movl %cr3, %edi
# identity map kernel
movl $kernel_pdpt_0 + 3, (%edi) # Set the uint32_t at the desination index to 0x2003.
movl $kernel_pdpt_0, %edi # Add 0x1000 to the desination index.
movl $kernel_pd_0 + 3, (%edi) # Set the uint32_t at the desination index to 0x3003.
movl $kernel_pd_0, %edi # Add 0x1000 to the desination index.
movl $kernel_pt_0 + 3, (%edi) # Set the uint32_t at the desination index to 0x4003.
movl $kernel_pt_0, %edi # Add 0x1000 to the desination index.
movl $0x03, %ebx # Entry value to set
movl $512, %ecx # Loop count
_start.SetEntry:
# set entires in mapping
movl %ebx, (%edi) # Set the uint32_t at the desination index to the B-register
addl $0x1000, %ebx # Add 0x1000 to the B-register
addl $8, %edi # Add eight to the desination index
loop _start.SetEntry
# 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
code64:
movw $GDT.Data, %dx # set segment registers
movw %dx, %ds
movw %dx, %ss
xorq %rbp, %rbp # set ebp to 0 so we know where to end stack traces
pop %rdi # pop possible multiboot header
pop %rsi
call main
jmp halt
_start_efi:
# disable interrupts
cli
# setup stack
movq $kern_stack_end, %rsp
movq $kern_stack_end, %rbp
# load gdt
lgdt GDT.Pointer
# set segment registers
movw $GDT.Code, %dx
movw %dx, %cs
movw %dx, %es
movw $GDT.Data, %dx
movw %dx, %ds
movw %dx, %ss
xorq %rbp, %rbp # set ebp to 0 so we know where to end stack traces
movq %rax, %rdi
movq %rbx, %rsi
call main
jmp halt
halt:
cli
hlt
jmp halt
|