aboutsummaryrefslogtreecommitdiff
path: root/boot/startup-x86_64.s
diff options
context:
space:
mode:
Diffstat (limited to 'boot/startup-x86_64.s')
-rw-r--r--boot/startup-x86_64.s115
1 files changed, 85 insertions, 30 deletions
diff --git a/boot/startup-x86_64.s b/boot/startup-x86_64.s
index 2c7562e..f08c752 100644
--- a/boot/startup-x86_64.s
+++ b/boot/startup-x86_64.s
@@ -5,7 +5,11 @@
STACKSIZE: equ 65536
; 512 GB maximum RAM size for page table
-; DON'T MODIFY THIS UNLESS YOU UPDATE THE setup_paging accordingly
+; DON'T MODIFY THIS UNLESS YOU UPDATE THE setup_paging accordingly.
+; IMPORTANT! regardless of the initial mapping size, we limit the phy memory to
+; 64GB in the actual paging, so that all kernel VMAs could fit into one pml4
+; entry and one pdp (level 3) table. See docs/mem_layout.txt
+
MAX_MEM: equ 512
; be careful with the extern and exported symbols when mapping a higher-half
@@ -23,8 +27,8 @@ MAX_MEM: equ 512
[GLOBAL mb_info_addr]
; functions from other parts of rustubs
[EXTERN _entry]
-[EXTERN ___BSS_START__]
-[EXTERN ___BSS_END__]
+[EXTERN ___BSS_PM_START__]
+[EXTERN ___BSS_PM_END__]
[SECTION .text]
@@ -68,16 +72,16 @@ setup_paging:
; zero out the initial page tables (2 pages in total)
mov edi, pml4
clear_pt:
- mov byte [edi], 0
- inc edi
+ mov dword [edi], 0
+ add edi, 4
cmp edi, pt_end
- jne clear_pt
+ jl clear_pt
; Provisional identical page mapping, using 1G huge page, therefore only 2
; table levels needed. see docs/x86_paging.txt
; PML4 (Page Map Level 4 / 1st level)
- mov eax, pdp
+ mov eax, pdp0
or eax, 0xf
mov dword [pml4+0], eax
mov dword [pml4+4], 0
@@ -89,8 +93,8 @@ fill_tables2:
; fill one single PDP table, with 1G pages, 512 PDPE maps to 512 GB
cmp ecx, MAX_MEM
je fill_tables2_done
- mov dword [pdp + 8*ecx + 0], eax ; low bytes
- mov dword [pdp + 8*ecx + 4], ebx ; high bytes
+ mov dword [pdp0 + 8*ecx + 0], eax ; low bytes
+ mov dword [pdp0 + 8*ecx + 4], ebx ; high bytes
add eax, 0x40000000 ; 1G per page
adc ebx, 0 ; overflow? -> increment higher-order half of the address
inc ecx
@@ -115,32 +119,74 @@ activate_long_mode:
; jump to 64-bit code segment -> full activation of Long Mode
jmp 2 * 0x8 : longmode_start
+
+; =====================================================================
+; MUST NOT USE ANY 64 BIT SYMBOLS BEFORE THIS POINT!
+; may include:
+; - symbols defined in 64 bit code below, if mapped to higher memory (VA)
+; - all symbols exported from rust code or linker script
+; =====================================================================
+
[BITS 64]
- ; system start, part 2 (in 64-bit Long Mode)
longmode_start:
- mov rdi, ___BSS_START__
+ ; now we set the pagetables for higher half memory
+ ; since we have Provisional paging now, why not using 64bit code?
+ mov eax, pdp1
+ or eax, 0xf
+ mov dword [pml4+256], eax
+ mov dword [pml4+256+4], 0
+ ; PDPE flags, see above
+
+ ; entry 0~63 is an identical mapping with offset 0x8000_0000_0000
+ ; clear the BSS section before going to rust code
+ ; TODO this should not be executable
+ mov rax, 0x0
+ or rax, 0x87
+ mov rdi, 0
+fill_kvma1:
+ mov qword [pdp1 + 8*rdi], rax
+ inc rdi
+ add rax, 0x40000000
+ cmp rdi, 64
+ jne fill_kvma1
+
+ ; entry 64~127 is a hole (also some sort of protection)
+ ; entry 128~191 are mapping of the kernel image itself
+ mov rax, 0x0
+ or rax, 0x87
+ mov rdi, 128
+fill_kvma2:
+ mov qword [pdp1 + 8*rdi], rax
+ inc rdi
+ add rax, 0x40000000
+ cmp rdi, 192
+ jne fill_kvma2
+ ; done :-)
+
+ ; clear BSS section for the rust code.
+ mov rdi, ___BSS_PM_START__
clear_bss:
mov byte [rdi], 0
inc rdi
- cmp rdi, ___BSS_END__
+ cmp rdi, ___BSS_PM_END__
jne clear_bss
- fninit ; activate FPU
-
-init_sse:
- ; init SSE
- ; NOTE: must NOT use sse target features for rust compiler, if sse not enabled here.
- ;mov rax, cr0
- ;and rax, ~(1 << 2) ;clear coprocessor emulation CR0.EM
- ;or rax, 1 << 1 ;set coprocessor monitoring CR0.MP
- ;mov cr0, rax
- ;mov rax, cr4
- ;or rax, 3 << 9 ;set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time
- ;mov cr4, rax
-
- call _entry ; call the OS kernel's rust part.
- cli ; Usually we should not get here.
+ ; enable FPU
+ fninit
+
+ ; NOTE: must NOT use sse target features for rust compiler, if sse not
+ ; enabled here.
+
+ ; finally go to the rust code!
+ call _entry
+ ; should not reach below
+ cli
hlt
+; =====================================================================
+; data sections they should all have VAs identical to their PAs
+; so we map these symbols differently than those generated by rust code
+; =====================================================================
+
[SECTION .data]
gdt:
@@ -195,12 +241,21 @@ init_stack:
[SECTION .global_pagetable]
-
+; create initial page tables wrt. the memory layout
+; we use entry 0 and 256 of the PML4 table
+; the whole of the first first pdp table (512G)
+; and entry 0, 2 of the second pdp table
+; all pages here are 1 GiB huge pages
pml4:
resb 4096
alignb 4096
-
-pdp:
+; the first PDP covers the lower 512GiB memory
+pdp0:
+ resb 4096
+ alignb 4096
+; pdp1 does the same but in higher half memory with offset
+; 0xffff_8000_0000_0000, i.e. the 256th entry of pml4
+pdp1:
resb 4096
alignb 4096
pt_end: