diff options
| author | Tianhao Wang <shrik3@mailbox.org> | 2024-06-03 21:31:24 +0200 |
|---|---|---|
| committer | Tianhao Wang <shrik3@mailbox.org> | 2024-06-11 15:17:11 +0200 |
| commit | f4b50dd826b81295dc9628b655fc5f360445230b (patch) | |
| tree | dd56d4da407b94cb293bd40d54b0646d61ee5834 | |
| parent | ae9df3200fd9e7fcc952945d105e516f9ffcf314 (diff) | |
mm: provide high memory kernel mapping in asm code.
we use the first pml4 entry (+one pdp table) to map phy 0~512G
to virt 0~512G for init code. This doesn't change.
For the kernel to work in higher half memory, we also need to create
mapping for it. We take the 256th entry of pml4 entry (hence one
additional pdp table).
Entry 0~63 are mapped to to the physical memory
(with offset 0xffff_8000_0000_0000)
Entry 64~127 are not used
Entry 128~191 are mapped to the kernel image (text and code)
(with offset 0xffff_8020_0000_0000)
details in docs/mem_layout.txt
| -rw-r--r-- | boot/startup-x86_64.s | 115 | ||||
| -rw-r--r-- | defs/x86_64-linker.ld | 8 | ||||
| -rw-r--r-- | src/defs.rs | 16 |
3 files changed, 97 insertions, 42 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: diff --git a/defs/x86_64-linker.ld b/defs/x86_64-linker.ld index ac4a86c..6be14cb 100644 --- a/defs/x86_64-linker.ld +++ b/defs/x86_64-linker.ld @@ -30,7 +30,7 @@ SECTIONS header_end = .; } - PROVIDE (___KERNEL_START__ = .); + PROVIDE (___KERNEL_PM_START__ = .); .text : { *(".text") @@ -71,10 +71,10 @@ SECTIONS .bss : { - PROVIDE (___BSS_START__ = .); + PROVIDE (___BSS_PM_START__ = .); *(".bss") *(".bss.*") - PROVIDE (___BSS_END__ = .); + PROVIDE (___BSS_PM_END__ = .); } /* global page table for 64-bit long mode */ @@ -95,5 +95,5 @@ SECTIONS *("..global_free_page_stack") } . = ALIGN(4096); - PROVIDE (___KERNEL_END__ = .); + PROVIDE (___KERNEL_PM_END__ = .); } diff --git a/src/defs.rs b/src/defs.rs index ddde0da..a89a6c7 100644 --- a/src/defs.rs +++ b/src/defs.rs @@ -1,25 +1,25 @@ // exported symbols from asm/linker. // They are always unsafe. extern "C" { - fn ___KERNEL_START__(); - fn ___KERNEL_END__(); - fn ___BSS_START__(); - fn ___BSS_END__(); + fn ___KERNEL_PM_START__(); + fn ___KERNEL_PM_END__(); + fn ___BSS_PM_START__(); + fn ___BSS_PM_END__(); } pub fn pmap_kernel_start() -> u64 { - return ___KERNEL_START__ as u64; + return ___KERNEL_PM_START__ as u64; } pub fn pmap_kernel_end() -> u64 { - return ___KERNEL_END__ as u64; + return ___KERNEL_PM_END__ as u64; } pub fn pmap_bss_start() -> u64 { - return ___BSS_START__ as u64; + return ___BSS_PM_START__ as u64; } pub fn pmap_bss_end() -> u64 { - return ___BSS_END__ as u64; + return ___BSS_PM_END__ as u64; } pub fn roundup_4k(addr: u64) -> u64 { |
