1+ / *
2+ Bootstrapping x86_64 kernel
3+ see also: https://wiki.osdev.org/Entering_Long_Mode
4+ * /
5+ / * prepare space for 4 - level paging to entering long mode
6+ .bss: | PML4 | PML3 | PML2 | Kernel_Stack(.bss.stack)|
7+ | 4kb | 4kb | 4kb | 16kb |
8+ * /
9+ . section .bss
10+ . align 4096
11+ p4_table:
12+ .skip 4096
13+ p3_table:
14+ .skip 4096
15+ p2_table:
16+ .skip 4096
17+
18+ / * Kernel Stack * /
19+ . section .bss.stack
20+ . align 16
21+ stack_bottom:
22+ .skip 16384
23+ stack_top:
24+
25+ / *
26+ 64 - bit Global Descriptor Table (GDT)
27+ see also: https://wiki.osdev.org/Global_Descriptor_Table
28+ * /
29+
30+ / * because of .rodata is read only now , when adding more features , we should move it to .data * /
31+ . section .rodata
32+ / * every items in gdt64 is 8 bytes * /
33+ . align 8
34+ gdt64:
35+ / * the first item is null * /
36+ .quad 0x0000000000000000
37+
38+ / * the second item is 64 - bit code segment
39+ Base 63 : 56 0x00000000
40+ G 55 0
41+ D/B 54 0
42+ L 53 1 ( 64 - bit code segment)
43+ AVL 52 0
44+ Limit 51 : 48 0x0000
45+ P 47 1
46+ DPL 46 : 45 0x00
47+ S 44 1
48+ Type 43 : 40 0x10
49+ Base 39 : 16 0x000000
50+ Limit 15 : 0 0x0000
51+ * /
52+ .quad 0x0020980000000000
53+ gdt64_pointer:
54+ / * length of gdt64 minus 1 * /
55+ . word 15
56+ / * pointer to gdt64 * /
57+ .quad gdt64
58+
59+ / *
60+ multiboot header
61+ see also: https://wiki.osdev.org/Multiboot_Specification
62+ * /
63+ . section .text.entry
64+ . align 4
65+
66+ . global multiboot_header
67+ multiboot_header:
68+ / * 0x1badb002 : magic number for multiboot protocol * /
69+ .long 0x1badb002
70+ / * 0x00010000 : flags * /
71+ .long 0x00010000
72+ / * checksum * /
73+ .long - ( 0x1badb002 + 0x00010000 )
74+
75+ / * pointer to multiboot_header * /
76+ .long multiboot_header
77+ .long stext
78+ .long edata
79+ .long ebss
80+ .long _start
81+
82+ / *
83+ start of 32 - bit code
84+ * /
85+ . global _start
86+ _start:
87+ .code32
88+ / * set stack pointer * /
89+ mov esp , offset stack_top
90+
91+ / *
92+ set up temporary page table
93+ map first 2MB of physical memory to virtual memory
94+ * /
95+ mov eax , offset p3_table
96+ or eax , 0b11 / * 0b11 means present and writable * /
97+ mov dword ptr [ p4_table ], eax
98+
99+ / * p3_table [ 0 ] - > p2_table * /
100+ mov eax , offset p2_table
101+ or eax , 0b11
102+ mov dword ptr [ p3_table ], eax
103+
104+ / * map first 2MB of physical memory to virtual memory as huge page * /
105+ mov eax , 0x83 / * 0x80 (Huge) + 0x02 (Writable) + 0x01 (Present) * /
106+ mov dword ptr [ p2_table ], eax
107+
108+ / * into long mode * /
109+ / * step 1 : set CR3 to p4_table * /
110+ mov eax , offset p4_table
111+ mov cr3 , eax
112+
113+ / * step 2 : enable PAE in CR4 * /
114+ mov eax , cr4
115+ or eax , 1 << 5
116+ mov cr4 , eax
117+
118+ / * step 3 : enable LME in EFER * /
119+ mov ecx , 0xC0000080
120+ rdmsr
121+ or eax , 1 << 8
122+ wrmsr
123+
124+ / * step 4 : enable paging in CR0 * /
125+ mov eax , cr0
126+ or eax , 1 << 31
127+ mov cr0 , eax
128+
129+ / * step 5 : load gdt64 * /
130+ lgdt [ gdt64_pointer ]
131+
132+ / * jump to 64 - bit code * /
133+ push 8 / * push 64 - bit code segment * /
134+ mov eax , offset long_mode_start
135+ push eax / * push 64 - bit code entry point * /
136+ retf / * retf to long mode * /
137+
138+ .code64
139+ long_mode_start:
140+ / * first thing: set all data segment registers to 0 * /
141+ mov ax , 0
142+ mov ss , ax
143+ mov ds , ax
144+ mov es , ax
145+ mov fs , ax
146+ mov gs , ax
147+
148+ / * call _main * /
149+ call _main
150+
151+ / * if _main returns , loop forever * /
152+ .loop64:
153+ hlt
154+ jmp .loop64
0 commit comments