aboutsummaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
Diffstat (limited to 'boot')
-rw-r--r--boot/startup-x86_64.s68
1 files changed, 44 insertions, 24 deletions
diff --git a/boot/startup-x86_64.s b/boot/startup-x86_64.s
index f08c752..c97db5e 100644
--- a/boot/startup-x86_64.s
+++ b/boot/startup-x86_64.s
@@ -20,18 +20,29 @@ MAX_MEM: equ 512
; they would be no longer accessable after the kernel switch to a higher half
; mapping. This is especially true for the multiboot info data.
+; Also be careful with imm width in asm instructions
+; many instructions does not take 64 bit imm value. e.g. cmp. If the operand is
+; an extern symbol the linker may tell you xyz "truncate to fit". In which case
+; you should load the addresses or values into an register before using them
; exported symbols
[GLOBAL startup]
[GLOBAL mb_magic]
[GLOBAL mb_info_addr]
; functions from other parts of rustubs
-[EXTERN _entry]
[EXTERN ___BSS_PM_START__]
[EXTERN ___BSS_PM_END__]
-
-[SECTION .text]
-
+[EXTERN KERNEL_OFFSET]
+[EXTERN _entry]
+; =====================================================================
+; begin of the text secion: unlike the text* sections from the rust code
+; the text here is not supposed to be relocated to an higher memory,
+; as we can not use high memory until we completely set up longmode paging.
+; Therefore we explicitly link the startup text section to low address.
+; the same goes for the ".data32" section: they are not necessarily 32bit,
+; the point is to confine all address within 4GB (32bit) range
+; =====================================================================
+[SECTION .text32]
; symbols used in 32bit mode:
; mb_magic
; mab_info_addr
@@ -45,6 +56,7 @@ startup:
; EAX: magic value 0x2BADB002
; EBX: 32-bit physical address of the multiboot information struct
; we store them in global variables for future uses in rust code.
+ ; TODO place them on the stack and pass as parameters to _entry
mov dword [mb_magic], eax
mov dword [mb_info_addr], ebx
; setup GDT by loading GDT descriptor
@@ -59,7 +71,7 @@ startup:
; define stack
mov ss, ax
- mov esp, init_stack+STACKSIZE
+ lea esp, init_stack+STACKSIZE
init_longmode:
; activate address extension (PAE)
@@ -81,12 +93,13 @@ clear_pt:
; table levels needed. see docs/x86_paging.txt
; PML4 (Page Map Level 4 / 1st level)
+ ; PML4 entry flag: 0xf = PRESENG | R/W | USER | Write Through
mov eax, pdp0
or eax, 0xf
mov dword [pml4+0], eax
mov dword [pml4+4], 0
- ; PDPE flags
- mov eax, 0x0 | 0x87 ; start-address bytes bit [30:31] + flags
+ ; PDPE flags 0x87 = PageSize=1G | USER | R/W | PRESENT
+ mov eax, 0x0 | 0x83 ; start-address bytes bit [30:31] + flags
mov ebx, 0 ; start-address bytes bit [32:38]
mov ecx, 0
fill_tables2:
@@ -126,22 +139,20 @@ activate_long_mode:
; - symbols defined in 64 bit code below, if mapped to higher memory (VA)
; - all symbols exported from rust code or linker script
; =====================================================================
-
[BITS 64]
longmode_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
-
+ ; the 256th entry of pml4 points to memory from 0xffff_8000_0000_0000
+ mov rax, pdp1
+ ; privileged, r/w, present
+ or rax, 0x3
+ mov qword [pml4+256*8], rax
; entry 0~63 is an identical mapping with offset 0x8000_0000_0000
- ; clear the BSS section before going to rust code
+ ; 1G Page | Privileged | R/W | PRESENT
; TODO this should not be executable
mov rax, 0x0
- or rax, 0x87
+ or rax, 0x83
mov rdi, 0
fill_kvma1:
mov qword [pdp1 + 8*rdi], rax
@@ -153,7 +164,7 @@ 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
+ or rax, 0x83
mov rdi, 128
fill_kvma2:
mov qword [pdp1 + 8*rdi], rax
@@ -162,22 +173,31 @@ fill_kvma2:
cmp rdi, 192
jne fill_kvma2
; done :-)
-
; clear BSS section for the rust code.
mov rdi, ___BSS_PM_START__
+ mov rax, ___BSS_PM_END__
clear_bss:
+ ; clear the BSS section before going to rust code
+ ; TODO speed this up by clearing 8 bytes at once. Alignment should be taken
+ ; care of..
mov byte [rdi], 0
inc rdi
- cmp rdi, ___BSS_PM_END__
+ cmp rdi, rax
jne clear_bss
+
; enable FPU
fninit
; NOTE: must NOT use sse target features for rust compiler, if sse not
; enabled here.
+ ; shift the rsp to high memory mapping:
+ mov rax, KERNEL_OFFSET,
+ or rsp, rax
; finally go to the rust code!
- call _entry
+ mov rax, _entry
+ jmp rax
+
; should not reach below
cli
hlt
@@ -185,10 +205,11 @@ clear_bss:
; =====================================================================
; data sections they should all have VAs identical to their PAs
; so we map these symbols differently than those generated by rust code
+; the "data" itself doesn't care about 64 or 32 bit width, but we need
+; to make sure they are not relocated to an address bigger then 4G (32)
; =====================================================================
-[SECTION .data]
-
+[SECTION .data32]
gdt:
; see docs/x86_gdt.txt
@@ -232,8 +253,7 @@ mb_magic:
mb_info_addr:
dd 0x00000000
-[SECTION .bss]
-
+[SECTION .init_k_stack]
global init_stack:data (init_stack.end - init_stack)
init_stack:
resb STACKSIZE