aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTianhao Wang <shrik3@mailbox.org>2024-06-04 18:37:21 +0200
committerTianhao Wang <shrik3@mailbox.org>2024-06-11 15:17:12 +0200
commit7973bfef5300c214150f74b3c700403ada56b89c (patch)
tree949f125ace03d94c1425bc4b6552243c9adbb7d5
parent1c7233d83f1d81ee9b211a9d61e482e94524222e (diff)
chore: cleanup
Signed-off-by: Tianhao Wang <shrik3@mailbox.org>
-rw-r--r--boot/startup-x86_64.s136
-rw-r--r--defs/x86_64-hm-linker.ld11
-rw-r--r--src/arch/x86_64/asm/vectors.s8
-rw-r--r--src/arch/x86_64/interrupt/mod.rs2
4 files changed, 69 insertions, 88 deletions
diff --git a/boot/startup-x86_64.s b/boot/startup-x86_64.s
index c97db5e..b6b3b2e 100644
--- a/boot/startup-x86_64.s
+++ b/boot/startup-x86_64.s
@@ -4,21 +4,21 @@
; stack for the main function (renamed to _entry())
STACKSIZE: equ 65536
-; 512 GB maximum RAM size for page table
-; DON'T MODIFY THIS UNLESS YOU UPDATE THE setup_paging accordingly.
+; 512 GB maximum RAM size for page table. Do not further increment this because
+; one PML4 table (and by extension, one pdp table) covers only 512 GB address.
+; And we only provision one such entry/table.
; 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
; kernel: regardless where they are physically loaded
; 1) extern symbols may have 64 bit virtual addresses or values. Do not use them
-; in the 32bit part of the startup code.
+; in the 32bit part of the startup code.
; 2) if the exported (global) symbols are mapped to low (virtual) addresses,
-; they would be no longer accessable after the kernel switch to a higher half
-; mapping. This is especially true for the multiboot info data.
+; 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
@@ -30,35 +30,31 @@ MAX_MEM: equ 512
[GLOBAL mb_magic]
[GLOBAL mb_info_addr]
; functions from other parts of rustubs
+; NOTE: this are all from 64bit code, so do not use them in 32bit assembly
[EXTERN ___BSS_PM_START__]
[EXTERN ___BSS_PM_END__]
[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
-; =====================================================================
+; =============================================================================
+; 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
-; gdt_80
-; init_stack
[BITS 32]
startup:
cld
cli
; with multiboot specs, grub initialzes the registers:
; 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
+ ; 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
; see docs/x86_gdt.txt
lgdt [gdt_80]
@@ -76,12 +72,11 @@ startup:
init_longmode:
; activate address extension (PAE)
mov eax, cr4
- or eax, 1 << 5
+ or eax, 1 << 5
mov cr4, eax
setup_paging:
-
- ; zero out the initial page tables (2 pages in total)
+ ; zero out the initial page tables (3 x 4K pages in total)
mov edi, pml4
clear_pt:
mov dword [edi], 0
@@ -90,29 +85,31 @@ clear_pt:
jl clear_pt
; Provisional identical page mapping, using 1G huge page, therefore only 2
- ; table levels needed. see docs/x86_paging.txt
+ ; table levels needed. see docs/x86_paging.txt We provide two additional
+ ; mappings later in the long mode for higher half memory
; PML4 (Page Map Level 4 / 1st level)
; PML4 entry flag: 0xf = PRESENG | R/W | USER | Write Through
mov eax, pdp0
- or eax, 0xf
+ or eax, 0xf
mov dword [pml4+0], eax
mov dword [pml4+4], 0
; 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 eax, 0x0 | 0x83 ; start-address bytes bit [30:31] + flags
+ mov ebx, 0 ; start-address bytes bit [32:38]
mov ecx, 0
-fill_tables2:
+fill_pdp0:
; fill one single PDP table, with 1G pages, 512 PDPE maps to 512 GB
cmp ecx, MAX_MEM
- je fill_tables2_done
+ je fill_pdp0_done
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
+ add eax, 0x40000000
+ ; increment high half address on carry (overflow)
+ adc ebx, 0
inc ecx
- ja fill_tables2
-fill_tables2_done:
+ ja fill_pdp0
+fill_pdp0_done:
; set base pointer to PML4
mov eax, pml4
mov cr3, eax
@@ -121,11 +118,11 @@ activate_long_mode:
; select EFER (Extended Feature Enable Register)
mov ecx, 0x0C0000080
rdmsr
- or eax, 1 << 8 ; LME (Long Mode Enable)
+ or eax, 1 << 8 ; LME (Long Mode Enable)
wrmsr
; activate paging
mov eax, cr0
- or eax, 1 << 31
+ or eax, 1 << 31
mov cr0, eax
; use the 2nd gdt entry (see definition below)
@@ -146,7 +143,7 @@ longmode_start:
; the 256th entry of pml4 points to memory from 0xffff_8000_0000_0000
mov rax, pdp1
; privileged, r/w, present
- or rax, 0x3
+ or rax, 0x3
mov qword [pml4+256*8], rax
; entry 0~63 is an identical mapping with offset 0x8000_0000_0000
; 1G Page | Privileged | R/W | PRESENT
@@ -160,7 +157,6 @@ fill_kvma1:
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
@@ -184,10 +180,8 @@ clear_bss:
inc rdi
cmp rdi, rax
jne clear_bss
-
; enable FPU
fninit
-
; NOTE: must NOT use sse target features for rust compiler, if sse not
; enabled here.
@@ -202,58 +196,58 @@ clear_bss:
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
-; 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)
-; =====================================================================
+; =============================================================================
+; 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 .data32]
gdt:
; see docs/x86_gdt.txt
; GDT[0] should always be NULL descriptor
- dw 0,0,0,0
+ dw 0,0,0,0
; 32-bit code segment descriptor
; limit=0xFFFF, base=0
; Types: P|Ring0|Code/Data|Exec|NonConforming|Readable|NotAccessed
; Flags: 4K|32-bit|Not Long Mode
- dw 0xFFFF
- dw 0x0000
- dw 0x9A00
- dw 0x00CF
+ dw 0xFFFF
+ dw 0x0000
+ dw 0x9A00
+ dw 0x00CF
; 64-bit code segment descriptor
; limit=0xFFFF, base=0
; Types: P|Ring0|Code/Data|Exec|NonConforming|Readable|NotAccessed
; Flags: 4K|-|LongMode|-
- dw 0xFFFF
- dw 0x0000
- dw 0x9A00
- dw 0x00AF
+ dw 0xFFFF
+ dw 0x0000
+ dw 0x9A00
+ dw 0x00AF
; data segment descriptor
; limit=0xFFFF, base=0
; Types: Present|Ring0|Code/Data|NoExec|GrowUp|Writable|NotAccessed
; Flags: 4K|32-bit|Not Long Mode
- dw 0xFFFF
- dw 0x0000
- dw 0x9200
- dw 0x00CF
+ dw 0xFFFF
+ dw 0x0000
+ dw 0x9200
+ dw 0x00CF
gdt_80:
- dw 4*8 - 1 ; GDT limit=24, 4 GDT entries - 1
- dq gdt ; GDT address
+ dw 4*8 - 1 ; GDT limit=24, 4 GDT entries - 1
+ dq gdt ; GDT address
; multiboot info
mb_magic:
- dd 0x00000000
+ dd 0x00000000
mb_info_addr:
- dd 0x00000000
+ dd 0x00000000
-[SECTION .init_k_stack]
+[SECTION .reserved_0.init_stack]
global init_stack:data (init_stack.end - init_stack)
init_stack:
resb STACKSIZE
@@ -261,11 +255,9 @@ 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
+; 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
diff --git a/defs/x86_64-hm-linker.ld b/defs/x86_64-hm-linker.ld
index 2b12539..fd689dc 100644
--- a/defs/x86_64-hm-linker.ld
+++ b/defs/x86_64-hm-linker.ld
@@ -33,17 +33,10 @@ SECTIONS
header_end = .;
}
-
.d32 :
{
*(".data32")
- }
-
- .reserved :
- {
- *(".reserved")
- *(".reserved.*")
- *(".gdt")
+ *(".data32.*")
}
/*
@@ -53,10 +46,8 @@ SECTIONS
*/
.reserved_0 (NOLOAD) :
{
- *(".init_k_stack")
*(".reserved_0")
*(".reserved_0.*")
- *(".reserved_0.init_stack")
}
diff --git a/src/arch/x86_64/asm/vectors.s b/src/arch/x86_64/asm/vectors.s
index 56aabf4..4267369 100644
--- a/src/arch/x86_64/asm/vectors.s
+++ b/src/arch/x86_64/asm/vectors.s
@@ -7,24 +7,22 @@
[EXTERN interrupt_gate]
[SECTION .reserved_0.idt]
-;
; Interrupt descriptor table with 256 entries
; TODO: use a interrupt stack instead of the current stack.
-
idt:
; reserve space for 256x idt entries (16 bytes each)
resb 16 * 256
-[SECTION .reserved]
+[SECTION .data32]
idt_descr:
- dw 256*8 - 1 ; 256 entries
+ dw 256*8 - 1 ; 256 entries
dq idt
; NOTE: vectors MUST have fixed instruction length currently aligned to 16
; bytes. DO NOT modify the wrapper, instead change the wrapper_body if needed.
; if the vector has to be modified into more than 16 bytes,
; arch::x86_64:: interrupt::_idt_init() must be modified accordingly
-[SECTION .reserved.vectors]
+[SECTION .data32.vectors]
%macro vector 1
align 16
vector_%1:
diff --git a/src/arch/x86_64/interrupt/mod.rs b/src/arch/x86_64/interrupt/mod.rs
index 7e0cbb8..ae2847a 100644
--- a/src/arch/x86_64/interrupt/mod.rs
+++ b/src/arch/x86_64/interrupt/mod.rs
@@ -64,7 +64,7 @@ extern "C" fn interrupt_gate(_slot: u16) {
// able to release the lock if the interrupt handler blocks on it. Try
// spamming the keyboard with the following line of code uncommented: it
// will deadlock!
- // println!("interrupt received 0x{:x}", slot);
+ // println!("interrupt received 0x{:x}", _slot);
interrupt_enable();
}