diff --git a/kernel/arch/x86/boot.s b/kernel/arch/x86/boot.s new file mode 100644 index 0000000..7181352 --- /dev/null +++ b/kernel/arch/x86/boot.s @@ -0,0 +1,163 @@ +; boot.s + +; entry is from bootloader + +section .text +bits 32 + +%include "defines.mac" + +; externs given by the linker script +extern _edata +extern _end + +; extern to the load.s +extern start64 +extern stack + +; define the starting point for this module +global start +global _start +start: +_start: + + ; Stash values for multiboot we won't touch until 64 bit mode + mov esi, ebx + mov edi, eax + + jmp start32 + + ; the multiboot header needs to be aligned at + ; a 32 bit boundary + align 4 + + multiboot_header: + + dd MULTIBOOT_HEADER_MAGIC + dd MULTIBOOT_HEADER_FLAGS + dd -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) + dd multiboot_header + dd _start + dd (_edata-KERNEL_VMA_BASE) + dd (_end-KERNEL_VMA_BASE) + dd _start + +; the 32 bit entry +global start32 +start32: + + ; disable interrupts + cli + + ; enable 64-bit page translation table entries + ; by setting CR4.PAE = 1. + ; + ; Paging is not enabled until long mode. + mov eax, cr4 + bts eax, 5 + mov cr4, eax + + ; Create long mode page table and init CR3 to + ; point to the base of the PML4 page table + mov eax, pml4_base + mov cr3, eax + + ; Enable Long mode and SYSCALL / SYSRET instructions + mov ecx, 0xC0000080 + rdmsr + bts eax, 8 + bts eax, 0 + wrmsr + + ; Load the 32 bit GDT + lgdt [pGDT32] + + ; Load the 32 bit IDT + ; lidt [pIDT32] + + ; establish a stack for 32 bit code + mov esp, (stack-KERNEL_VMA_BASE) + STACK_SIZE + + ; enable paging to activate long mode + mov eax, cr0 + bts eax, 31 + mov cr0, eax + + jmp CS_KERNEL:(start64-KERNEL_VMA_BASE) + +bits 64 +code64Jump: + jmp (start64-KERNEL_VMA_BASE) + + + + +; Data Structures Follow +bits 32 + +; 32 bit gdt + +align 4096 + +pGDT32: + dw GDT_END - GDT_TABLE - 1 + dq GDT_TABLE - KERNEL_VMA_BASE + +GDT_TABLE: + + dq 0x0000000000000000 ; Null Descriptor + dq 0x00cf9a000000ffff ; CS_KERNEL32 + dq 0x00af9a000000ffff,0 ; CS_KERNEL + dq 0x00af93000000ffff,0 ; DS_KERNEL + dq 0x00affa000000ffff,0 ; CS_USER + dq 0x00aff3000000ffff,0 ; DS_USER + dq 0,0 ; + dq 0,0 ; + dq 0,0 ; + dq 0,0 ; + + dq 0,0,0 ; Three TLS descriptors + dq 0x0000f40000000000 ; + +GDT_END: + + + + +; Temporary page tables + +; These assume linking to 0xFFFF800000000000 +align 4096 +pml4_base: + dq (pml3_base + 0x7) + times 255 dq 0 + dq (pml3_base + 0x7) + times 255 dq 0 + +align 4096 +pml3_base: + dq (pml2_base + 0x7) + times 511 dq 0 + +align 4096 +pml2_base: + %assign i 0 + %rep 25 + dq (pml1_base + i + 0x7) + %assign i i+4096 + %endrep + + times (512-25) dq 0 + +align 4096 +; 15 tables are described here +; this maps 40 MB from address 0x0 +; to an identity mapping +pml1_base: + %assign i 0 + %rep 512*25 + dq (i << 12) | 0x087 + %assign i i+1 + %endrep + + diff --git a/kernel/arch/x86/defines.mac b/kernel/arch/x86/defines.mac new file mode 100644 index 0000000..0442163 --- /dev/null +++ b/kernel/arch/x86/defines.mac @@ -0,0 +1,17 @@ +; multiboot definitions +%define MULTIBOOT_HEADER_MAGIC 0x1BADB002 +%define MULTIBOOT_HEADER_FLAGS 0x00010003 + +; where is the kernel? +%define KERNEL_VMA_BASE 0xFFFF800000000000 +%define KERNEL_LMA_BASE 0x100000 + +; the gdt entry to use for the kernel +%define CS_KERNEL 0x10 +%define CS_KERNEL32 0x08 + +; other definitions + +%define STACK_SIZE 0x4000 + + diff --git a/kernel/arch/x86/load.s b/kernel/arch/x86/load.s new file mode 100644 index 0000000..35b2d02 --- /dev/null +++ b/kernel/arch/x86/load.s @@ -0,0 +1,101 @@ +; load.s + +; entry is from boot.s + +bits 64 + +; Everywhere you see some weird addition logic +; This is to fit the addresses into 32 bit sizes +; Note, they will sign extend! + +section .text + +; include useful definitions +%include "defines.mac" + +; extern to kmain.d +extern kmain + +global start64 + +start64: + + ; Initialize the 64 bit stack pointer. + mov rsp, ((stack - KERNEL_VMA_BASE) + STACK_SIZE) + + ; Set up the stack for the return. + push CS_KERNEL + + ; RAX - the address to return to + mov rax, KERNEL_VMA_BASE >> 32 + shl rax, 32 + or rax, long_entry - (KERNEL_VMA_BASE & 0xffffffff00000000) + push rax + + ; Go into canonical higher half + ; It uses a trick to update the program counter + ; across a 64 bit address space + ret + +long_entry: + + ; From here on out, we are running instructions + ; within the higher half (0xffffffff80000000 ... ) + + ; We can safely upmap the lower half, we do not + ; need an identity mapping of this region + + ; set up a 64 bit virtual stack + mov rax, KERNEL_VMA_BASE >> 32 + shl rax, 32 + or rax, stack - (KERNEL_VMA_BASE & 0xffffffff00000000) + mov rsp, rax + + ; set cpu flags + push 0 + lss eax, [rsp] + popf + + ; set the input/output permission level to 3 + ; it will allow all access + + pushf + pop rax + or rax, 0x3000 + push rax + popf + + ; update the multiboot struct to point to a + ; virtual address + add rsi, (KERNEL_VMA_BASE & 0xffffffff) + + ; push the parameters (just in case) + push rsi + push rdi + + ; call kmain + call kmain + + + + ; we should not get here + +haltloop: + + hlt + jmp haltloop + nop + nop + nop + + + +; stack space +global stack +align 4096 + +stack: + %rep STACK_SIZE + dd 0 + %endrep + diff --git a/kernel/arch/x86_64/boot/boot.h b/kernel/arch/x86_64/boot/boot.h deleted file mode 100644 index a5792fe..0000000 --- a/kernel/arch/x86_64/boot/boot.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - -boot.h - -- Contains information pertinant to the bootstrap about where - the kernel is located - -*/ - -/* the code section for the kernel - 0x10 = code section 2 ( right shift it by 3 ) */ -#define CS_KERNEL 0x10 -#define CS_KERNEL32 0x8 - -/* the location, in physical address (LMA) and virtual (VMA) */ -/* these should correspond to linker.ld */ - -#define KERNEL_LMA_BASE 0x100000 -#define KERNEL_VMA_BASE (0xffffffff80000000) -#define KERNEL_LOCATION (KERNEL_VMA_BASE + KERNEL_LMA_BASE) - diff --git a/kernel/dev/console.d b/kernel/dev/console.d index f954a4f..3b1ff42 100644 --- a/kernel/dev/console.d +++ b/kernel/dev/console.d @@ -36,7 +36,7 @@ public: // The default color. const ubyte DEFAULTCOLORS = Color.LightGray; - ubyte* videoMemoryLocation = cast(ubyte*)0xFFFFFFFF800B8000; + ubyte* videoMemoryLocation = cast(ubyte*)0xFFFF8000000B8000; // The cursor position private int xpos = 0;