diff options
| author | Tianhao Wang <shrik3@mailbox.org> | 2024-06-04 18:37:21 +0200 |
|---|---|---|
| committer | Tianhao Wang <shrik3@mailbox.org> | 2024-06-11 15:17:12 +0200 |
| commit | 7973bfef5300c214150f74b3c700403ada56b89c (patch) | |
| tree | 949f125ace03d94c1425bc4b6552243c9adbb7d5 | |
| parent | 1c7233d83f1d81ee9b211a9d61e482e94524222e (diff) | |
chore: cleanup
Signed-off-by: Tianhao Wang <shrik3@mailbox.org>
| -rw-r--r-- | boot/startup-x86_64.s | 136 | ||||
| -rw-r--r-- | defs/x86_64-hm-linker.ld | 11 | ||||
| -rw-r--r-- | src/arch/x86_64/asm/vectors.s | 8 | ||||
| -rw-r--r-- | src/arch/x86_64/interrupt/mod.rs | 2 |
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(); } |
