aboutsummaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
Diffstat (limited to 'boot')
-rw-r--r--boot/startup-x86_64.s157
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]