diff options
Diffstat (limited to 'boot/startup-x86_64.s')
| -rw-r--r-- | boot/startup-x86_64.s | 157 |
1 files changed, 67 insertions, 90 deletions
diff --git a/boot/startup-x86_64.s b/boot/startup-x86_64.s index 9b994de..bb270a1 100644 --- a/boot/startup-x86_64.s +++ b/boot/startup-x86_64.s @@ -1,21 +1,4 @@ -; THis code is copied from the OSC lab project OOStuBS @ TU Dresden - -;****************************************************************************** -;* Operating-System Construction * -;*----------------------------------------------------------------------------* -;* * -;* S T A R T U P . A S M * -;* * -;*----------------------------------------------------------------------------* -;* The 'startup' function is the entry point for the whole system. Switching * -;* to 32-bit Protected Mode has already been done (by a boot loader that runs * -;* before). Here we prepare everything to be able to start running rust code * -;* in 64-bit Long Mode as quickly as possible. * -;****************************************************************************** - -; -; Constants -; +; Contains code from from the OSC lab project OOStuBS @ TU Dresden ; stack for the main function (renamed to _entry()) STACKSIZE: equ 65536 @@ -25,21 +8,16 @@ STACKSIZE: equ 65536 MAX_MEM: equ 512 ; Multiboot constants -MULTIBOOT_PAGE_ALIGN equ 1<<0 -MULTIBOOT_MEMORY_INFO equ 1<<1 +MULTIBOOT_PAGE_ALIGN equ 1<<0 +MULTIBOOT_MEMORY_INFO equ 1<<1 ; magic number for Multiboot -MULTIBOOT_HEADER_MAGIC equ 0x1badb002 +MULTIBOOT_HEADER_MAGIC equ 0x1badb002 ; Multiboot flags (ELF specific!) -MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO +MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO MULTIBOOT_HEADER_CHKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) -MULTIBOOT_EAX_MAGIC equ 0x2badb002 - - -; -; System -; +MULTIBOOT_EAX_MAGIC equ 0x2badb002 ; exported symbols [GLOBAL startup] @@ -47,29 +25,23 @@ MULTIBOOT_EAX_MAGIC equ 0x2badb002 [GLOBAL pml4] [GLOBAL pdp] -; functions from the C parts of the system +; functions from the rust [EXTERN _entry] [EXTERN interrupt_gate] -; addresses provided by the compiler +; addresses provided by the linker [EXTERN ___BSS_START__] [EXTERN ___BSS_END__] [SECTION .text] -; -; system start, part 1 (in 32-bit Protected Mode) -; -; GDT and page-table initialization, and switch to 64-bit Long Mode -; - [BITS 32] - jmp startup ; jump over Multiboot header - align 4 ; 32-bit alignment for GRUB + jmp startup ; jump over Multiboot header + align 4 ; 32-bit alignment for GRUB ; -; Multiboot header for starting with GRUB or QEMU (w/o BIOS) +; Multiboot header for starting with GRUB or QEMU (w/o BIOS) ; dd MULTIBOOT_HEADER_MAGIC @@ -86,21 +58,23 @@ MULTIBOOT_EAX_MAGIC equ 0x2badb002 dd 0 ; depth (gets ignored) ; -; GRUB entry point +; system start, part 1 (in 32-bit Protected Mode) +; set up GDT, segmentation (dummy for long-mode, but requried). +; and pagetable. Prepare the system for long-mode ; startup: - cld ; GCC-compiled code expects the direction flag to be 0 - cli ; disable interrupts + cld ; GCC-compiled code expects the direction flag to be 0 + cli ; disable interrupts lgdt [gdt_80] ; set new segment descriptors - ; global data segment + ; global data segment mov eax, 3 * 0x8 - ; 0x8 is the length of each entry - ; these registers point to 4th entry the GDT (see also the code there) - ; in x86 long mode these are dummy pointers - ; which are not actually used in addressing. (don't use segmentation at all) - ; all the addresses are physical addresses from 0. + ; 0x8 is the length of each entry + ; these registers point to 4th entry the GDT (see also the code there) + ; in x86 long mode these are dummy pointers + ; which are not actually used in addressing. (don't use segmentation at all) + ; all the addresses are physical addresses from 0. mov ds, ax mov es, ax mov fs, ax @@ -117,7 +91,7 @@ startup: init_longmode: ; activate address extension (PAE) mov eax, cr4 - or eax, 1 << 5 + or eax, 1 << 5 mov cr4, eax ; create page table (mandatory) @@ -126,12 +100,12 @@ init_longmode: ; activate Long Mode (for now in compatibility mode) mov ecx, 0x0C0000080 ; select EFER (Extended Feature Enable Register) 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 ; jump to 64-bit code segment -> full activation of Long Mode @@ -145,23 +119,23 @@ init_longmode: setup_paging: ; PML4 (Page Map Level 4 / 1st level) mov eax, pdp - or eax, 0xf + 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 - mov ebx, 0 ; start-address bytes bit [32:38] + mov eax, 0x0 | 0x87 ; start-address bytes bit [30:31] + flags + mov ebx, 0 ; start-address bytes bit [32:38] mov ecx, 0 fill_tables2: ; fill one single PDP table, with 1G pages, 512 PDPE maps to 512 GB cmp ecx, MAX_MEM - je fill_tables2_done + je fill_tables2_done mov dword [pdp + 8*ecx + 0], eax ; low bytes mov dword [pdp + 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 ; 1G per page + adc ebx, 0 ; overflow? -> increment higher-order half of the address inc ecx - ja fill_tables2 + ja fill_tables2 fill_tables2_done: ; set base pointer to PML4 mov eax, pml4 @@ -169,10 +143,12 @@ fill_tables2_done: ret ; -; system start, part 2 (in 64-bit Long Mode) -; -; This code clears the BSS segment and initializes IDT and PICs. Then the -; constructors of global C++ objects are called, and finally _entry() is run. +; system start, part 2 (in 64-bit Long Mode) +; 1. clear BSS +; 2. enable floating poitn unit +; 3. set up idt +; 4. (optional) enable SSE +; 5. jump to rust main code ; longmode_start: @@ -188,8 +164,9 @@ clear_bss: ; initialize IDT and PICs call setup_idt - fninit ; activate FPU + 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 @@ -200,12 +177,12 @@ clear_bss: ;or rax, 3 << 9 ;set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time ;mov cr4, rax - call _entry ; call the OS kernel's C / C++ part - cli ; Usually we should not get here. + call _entry ; call the OS kernel's rust part. + cli ; Usually we should not get here. hlt ; -; Interrupt handling +; Interrupt handling ; ; template for header for each interrupt-handling routine @@ -244,7 +221,7 @@ wrapper_body: and rax, 0xff ; call the interrupt handling code with interrupt number as parameter mov rdi, rax - call interrupt_gate + call interrupt_gate ; restore volatile registers pop r11 @@ -297,42 +274,42 @@ setup_idt: ; gdt: - dw 0,0,0,0 ; NULL descriptor + dw 0,0,0,0 ; NULL descriptor ; 32-bit code segment descriptor - dw 0xFFFF ; 4Gb - (0x100000*0x1000 = 4Gb) - dw 0x0000 ; base address=0 - dw 0x9A00 ; code read/exec - dw 0x00CF ; granularity=4096, 386 (+5th nibble of limit) + dw 0xFFFF ; 4Gb - (0x100000*0x1000 = 4Gb) + dw 0x0000 ; base address=0 + dw 0x9A00 ; code read/exec + dw 0x00CF ; granularity=4096, 386 (+5th nibble of limit) ; 64-bit code segment descriptor - dw 0xFFFF ; 4Gb - (0x100000*0x1000 = 4Gb) - dw 0x0000 ; base address=0 - dw 0x9A00 ; code read/exec - dw 0x00AF ; granularity=4096, 386 (+5th nibble of limit), Long-Mode + dw 0xFFFF ; 4Gb - (0x100000*0x1000 = 4Gb) + dw 0x0000 ; base address=0 + dw 0x9A00 ; code read/exec + dw 0x00AF ; granularity=4096, 386 (+5th nibble of limit), Long-Mode ; data segment descriptor - dw 0xFFFF ; 4Gb - (0x100000*0x1000 = 4Gb) - dw 0x0000 ; base address=0 - dw 0x9200 ; data read/write - dw 0x00CF ; granularity=4096, 386 (+5th nibble of limit) + dw 0xFFFF ; 4Gb - (0x100000*0x1000 = 4Gb) + dw 0x0000 ; base address=0 + dw 0x9200 ; data read/write + dw 0x00CF ; granularity=4096, 386 (+5th nibble of limit) 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 ; ; Interrupt descriptor table with 256 entries ; - +; TODO: use a interrupt stack instead of the current stack. idt: %macro idt_entry 1 - dw (wrapper_%1 - wrapper_0) & 0xffff ; offset 0 .. 15 - dw 0x0000 | 0x8 * 2 ; selector points to 64-bit code segment selector (GDT) - dw 0x8e00 ; 8 -> interrupt is present, e -> 80386 32-bit interrupt gate - dw ((wrapper_%1 - wrapper_0) & 0xffff0000) >> 16 ; offset 16 .. 31 - dd ((wrapper_%1 - wrapper_0) & 0xffffffff00000000) >> 32 ; offset 32..63 - dd 0x00000000 ; reserved + dw (wrapper_%1 - wrapper_0) & 0xffff ; offset 0 .. 15 + dw 0x0000 | 0x8 * 2 ; selector points to 64-bit code segment selector (GDT) + dw 0x8e00 ; 8 -> interrupt is present, e -> 80386 32-bit interrupt gate + dw ((wrapper_%1 - wrapper_0) & 0xffff0000) >> 16 ; offset 16 .. 31 + dd ((wrapper_%1 - wrapper_0) & 0xffffffff00000000) >> 32 ; offset 32..63 + dd 0x00000000 ; reserved %endmacro %assign i 0 @@ -342,7 +319,7 @@ idt_entry i %endrep idt_descr: - dw 256*8 - 1 ; 256 entries + dw 256*8 - 1 ; 256 entries dq idt [SECTION .bss] |
