44; stack for the main function (renamed to _entry())
55STACKSIZE: equ 65536
66
7- ; 512 GB maximum RAM size for page table
8- ; DON'T MODIFY THIS UNLESS YOU UPDATE THE setup_paging accordingly.
7+ ; 512 GB maximum RAM size for page table. Do not further increment this because
8+ ; one PML4 table (and by extension, one pdp table) covers only 512 GB address.
9+ ; And we only provision one such entry/table.
910; IMPORTANT! regardless of the initial mapping size, we limit the phy memory to
1011; 64GB in the actual paging, so that all kernel VMAs could fit into one pml4
1112; entry and one pdp (level 3) table. See docs/mem_layout.txt
12-
1313MAX_MEM: equ 512
1414
1515; be careful with the extern and exported symbols when mapping a higher-half
1616; kernel: regardless where they are physically loaded
1717; 1) extern symbols may have 64 bit virtual addresses or values. Do not use them
18- ; in the 32bit part of the startup code.
18+ ; in the 32bit part of the startup code.
1919; 2) if the exported (global) symbols are mapped to low (virtual) addresses,
20- ; they would be no longer accessable after the kernel switch to a higher half
21- ; mapping. This is especially true for the multiboot info data.
20+ ; they would be no longer accessable after the kernel switch to a higher half
21+ ; mapping. This is especially true for the multiboot info data.
2222
2323; Also be careful with imm width in asm instructions
2424; many instructions does not take 64 bit imm value. e.g. cmp. If the operand is
@@ -30,35 +30,31 @@ MAX_MEM: equ 512
3030[GLOBAL mb_magic]
3131[GLOBAL mb_info_addr]
3232; functions from other parts of rustubs
33+ ; NOTE: this are all from 64bit code, so do not use them in 32bit assembly
3334[EXTERN ___BSS_PM_START__]
3435[EXTERN ___BSS_PM_END__]
3536[EXTERN KERNEL_OFFSET]
3637[EXTERN _entry]
37- ; =====================================================================
38- ; begin of the text secion: unlike the text* sections from the rust code
39- ; the text here is not supposed to be relocated to an higher memory,
40- ; as we can not use high memory until we completely set up longmode paging.
41- ; Therefore we explicitly link the startup text section to low address.
42- ; the same goes for the ".data32" section: they are not necessarily 32bit,
43- ; the point is to confine all address within 4GB (32bit) range
44- ; =====================================================================
38+ ; =============================================================================
39+ ; begin of the text secion: unlike the text* sections from the rust code the
40+ ; text here is not supposed to be relocated to an higher memory, as we can not
41+ ; use high memory until we completely set up longmode paging. Therefore we
42+ ; explicitly link the startup text section to low address. the same goes for the
43+ ; ".data32" section: they are not necessarily 32bit, the point is to confine all
44+ ; address within 4GB (32bit) range
45+ ; =============================================================================
4546[SECTION .text32]
46- ; symbols used in 32bit mode:
47- ; mb_magic
48- ; mab_info_addr
49- ; gdt_80
50- ; init_stack
5147[BITS 32]
5248startup:
5349 cld
5450 cli
5551 ; with multiboot specs, grub initialzes the registers:
5652 ; EAX: magic value 0x2BADB002
57- ; EBX: 32-bit physical address of the multiboot information struct
58- ; we store them in global variables for future uses in rust code.
59- ; TODO place them on the stack and pass as parameters to _entry
60- mov dword [ mb_magic ], eax
61- mov dword [ mb_info_addr ], ebx
53+ ; EBX: 32-bit physical address of the multiboot information struct we store
54+ ; them in global variables for future uses in rust code. TODO place them on
55+ ; the stack and pass as parameters to _entry
56+ mov dword [ mb_magic ], eax
57+ mov dword [ mb_info_addr ], ebx
6258 ; setup GDT by loading GDT descriptor
6359 ; see docs/x86_gdt.txt
6460 lgdt [ gdt_80 ]
@@ -76,12 +72,11 @@ startup:
7672init_longmode:
7773 ; activate address extension (PAE)
7874 mov eax , cr4
79- or eax , 1 << 5
75+ or eax , 1 << 5
8076 mov cr4 , eax
8177
8278setup_paging:
83-
84- ; zero out the initial page tables (2 pages in total)
79+ ; zero out the initial page tables (3 x 4K pages in total)
8580 mov edi , pml4
8681clear_pt:
8782 mov dword [ edi ], 0
@@ -90,29 +85,31 @@ clear_pt:
9085 jl clear_pt
9186
9287 ; Provisional identical page mapping, using 1G huge page, therefore only 2
93- ; table levels needed. see docs/x86_paging.txt
88+ ; table levels needed. see docs/x86_paging.txt We provide two additional
89+ ; mappings later in the long mode for higher half memory
9490
9591 ; PML4 (Page Map Level 4 / 1st level)
9692 ; PML4 entry flag: 0xf = PRESENG | R/W | USER | Write Through
9793 mov eax , pdp0
98- or eax , 0xf
94+ or eax , 0xf
9995 mov dword [ pml4 + 0 ], eax
10096 mov dword [ pml4 + 4 ], 0
10197 ; PDPE flags 0x87 = PageSize=1G | USER | R/W | PRESENT
102- mov eax , 0x0 | 0x83 ; start-address bytes bit [30:31] + flags
103- mov ebx , 0 ; start-address bytes bit [32:38]
98+ mov eax , 0x0 | 0x83 ; start-address bytes bit [30:31] + flags
99+ mov ebx , 0 ; start-address bytes bit [32:38]
104100 mov ecx , 0
105- fill_tables2 :
101+ fill_pdp0 :
106102 ; fill one single PDP table, with 1G pages, 512 PDPE maps to 512 GB
107103 cmp ecx , MAX_MEM
108- je fill_tables2_done
104+ je fill_pdp0_done
109105 mov dword [ pdp0 + 8 * ecx + 0 ], eax ; low bytes
110106 mov dword [ pdp0 + 8 * ecx + 4 ], ebx ; high bytes
111- add eax , 0x40000000 ; 1G per page
112- adc ebx , 0 ; overflow? -> increment higher-order half of the address
107+ add eax , 0x40000000
108+ ; increment high half address on carry (overflow)
109+ adc ebx , 0
113110 inc ecx
114- ja fill_tables2
115- fill_tables2_done :
111+ ja fill_pdp0
112+ fill_pdp0_done :
116113 ; set base pointer to PML4
117114 mov eax , pml4
118115 mov cr3 , eax
@@ -121,11 +118,11 @@ activate_long_mode:
121118 ; select EFER (Extended Feature Enable Register)
122119 mov ecx , 0x0C0000080
123120 rdmsr
124- or eax , 1 << 8 ; LME (Long Mode Enable)
121+ or eax , 1 << 8 ; LME (Long Mode Enable)
125122 wrmsr
126123 ; activate paging
127124 mov eax , cr0
128- or eax , 1 << 31
125+ or eax , 1 << 31
129126 mov cr0 , eax
130127
131128 ; use the 2nd gdt entry (see definition below)
@@ -146,7 +143,7 @@ longmode_start:
146143 ; the 256th entry of pml4 points to memory from 0xffff_8000_0000_0000
147144 mov rax , pdp1
148145 ; privileged, r/w, present
149- or rax , 0x3
146+ or rax , 0x3
150147 mov qword [ pml4 + 256 * 8 ], rax
151148 ; entry 0~63 is an identical mapping with offset 0x8000_0000_0000
152149 ; 1G Page | Privileged | R/W | PRESENT
@@ -160,7 +157,6 @@ fill_kvma1:
160157 add rax , 0x40000000
161158 cmp rdi , 64
162159 jne fill_kvma1
163-
164160 ; entry 64~127 is a hole (also some sort of protection)
165161 ; entry 128~191 are mapping of the kernel image itself
166162 mov rax , 0x0
@@ -184,10 +180,8 @@ clear_bss:
184180 inc rdi
185181 cmp rdi , rax
186182 jne clear_bss
187-
188183 ; enable FPU
189184 fninit
190-
191185 ; NOTE: must NOT use sse target features for rust compiler, if sse not
192186 ; enabled here.
193187
@@ -202,70 +196,68 @@ clear_bss:
202196 cli
203197 hlt
204198
205- ; =====================================================================
206- ; data sections they should all have VAs identical to their PAs
207- ; so we map these symbols differently than those generated by rust code
208- ; the "data" itself doesn't care about 64 or 32 bit width, but we need
209- ; to make sure they are not relocated to an address bigger then 4G (32)
210- ; =====================================================================
199+ ; =============================================================================
200+ ; data sections they should all have VAs identical to their PAs so we map these
201+ ; symbols differently than those generated by rust code the "data" itself
202+ ; doesn't care about 64 or 32 bit width, but we need to make sure they are not
203+ ; relocated to an address bigger then 4G (32)
204+ ; =============================================================================
211205
212206[SECTION .data32]
213207gdt:
214208 ; see docs/x86_gdt.txt
215209
216210 ; GDT[0] should always be NULL descriptor
217- dw 0 , 0 , 0 , 0
211+ dw 0 , 0 , 0 , 0
218212
219213 ; 32-bit code segment descriptor
220214 ; limit=0xFFFF, base=0
221215 ; Types: P|Ring0|Code/Data|Exec|NonConforming|Readable|NotAccessed
222216 ; Flags: 4K|32-bit|Not Long Mode
223- dw 0xFFFF
224- dw 0x0000
225- dw 0x9A00
226- dw 0x00CF
217+ dw 0xFFFF
218+ dw 0x0000
219+ dw 0x9A00
220+ dw 0x00CF
227221
228222 ; 64-bit code segment descriptor
229223 ; limit=0xFFFF, base=0
230224 ; Types: P|Ring0|Code/Data|Exec|NonConforming|Readable|NotAccessed
231225 ; Flags: 4K|-|LongMode|-
232- dw 0xFFFF
233- dw 0x0000
234- dw 0x9A00
235- dw 0x00AF
226+ dw 0xFFFF
227+ dw 0x0000
228+ dw 0x9A00
229+ dw 0x00AF
236230
237231 ; data segment descriptor
238232 ; limit=0xFFFF, base=0
239233 ; Types: Present|Ring0|Code/Data|NoExec|GrowUp|Writable|NotAccessed
240234 ; Flags: 4K|32-bit|Not Long Mode
241- dw 0xFFFF
242- dw 0x0000
243- dw 0x9200
244- dw 0x00CF
235+ dw 0xFFFF
236+ dw 0x0000
237+ dw 0x9200
238+ dw 0x00CF
245239
246240gdt_80:
247- dw 4 * 8 - 1 ; GDT limit=24, 4 GDT entries - 1
248- dq gdt ; GDT address
241+ dw 4 * 8 - 1 ; GDT limit=24, 4 GDT entries - 1
242+ dq gdt ; GDT address
249243
250244; multiboot info
251245mb_magic:
252- dd 0x00000000
246+ dd 0x00000000
253247mb_info_addr:
254- dd 0x00000000
248+ dd 0x00000000
255249
256- [SECTION .init_k_stack ]
250+ [SECTION .reserved_0.init_stack ]
257251global init_stack:data (init_stack.end - init_stack)
258252init_stack:
259253 resb STACKSIZE
260254.end:
261255
262256[SECTION .global_pagetable]
263257
264- ; create initial page tables wrt. the memory layout
265- ; we use entry 0 and 256 of the PML4 table
266- ; the whole of the first first pdp table (512G)
267- ; and entry 0, 2 of the second pdp table
268- ; all pages here are 1 GiB huge pages
258+ ; create initial page tables wrt. the memory layout we use entry 0 and 256 of
259+ ; the PML4 table the whole of the first first pdp table (512G) and entry 0, 2 of
260+ ; the second pdp table all pages here are 1 GiB huge pages
269261pml4:
270262 resb 4096
271263 alignb 4096
0 commit comments