diff options
Diffstat (limited to 'boot/startup-x86_64.s')
| -rw-r--r-- | boot/startup-x86_64.s | 115 |
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: |
