From df2c0ee981f997b8677bb28149272818ae51f926 Mon Sep 17 00:00:00 2001 From: Simon Date: Sat, 27 Jan 2024 02:18:08 -0500 Subject: [PATCH] Added basic long mode setup --- Makefile | 8 ++- src/arch/amd64/boot.S | 112 +++++++++++++++++++++++++++++++----------- src/arch/amd64/shim.c | 79 +++++++++++++++++------------ src/kmain.c | 3 +- 4 files changed, 138 insertions(+), 64 deletions(-) diff --git a/Makefile b/Makefile index 13ad832..1be00e9 100644 --- a/Makefile +++ b/Makefile @@ -5,10 +5,10 @@ BUILD_DIR=build K_BIN_NAME=kernel.bin ISO_NAME=os_image.iso -CC=cc +CC=gcc LD=ld -CFLAGS=-ffreestanding -g -Wall -Wextra -pedantic -lgcc -isystem $(INCLUDE_DIR) +CFLAGS= -std=c2x -ffreestanding -g -Wall -Wextra -pedantic -lgcc -isystem $(INCLUDE_DIR) C_SRC=$(shell find $(SRC_DIR) -type f -name "*.c") @@ -31,6 +31,10 @@ $(A_OBJ): $(BUILD_DIR)/%.S.o : %.S @mkdir -p $(@D) nasm $< -f elf64 -o $@ +$(BUILD_DIR)/$(SRC_DIR)/arch/amd64/shim.o: $(SRC_DIR)/arch/amd64/shim.c + @mkdir -p $(@D) + $(CC) -c $(CFLAGS) -o $@ $< -m32 + $(C_OBJ): $(BUILD_DIR)/%.o : %.c @mkdir -p $(@D) $(CC) -c $(CFLAGS) -o $@ $< diff --git a/src/arch/amd64/boot.S b/src/arch/amd64/boot.S index fc580fb..9771fe2 100644 --- a/src/arch/amd64/boot.S +++ b/src/arch/amd64/boot.S @@ -3,18 +3,6 @@ extern kmain extern amd64_shim bits 32 -; base, limit, access, flags -%macro gdt_entry 4 - db %2 & 0xff - db (%2 >> 8) & 0xff - db %1 & 0xff - db (%1 >> 8) & 0xff - db (%1 >> 16) & 0xff - db %3 - db ((%2 >> 16) & 0x0f) | (%4 << 4) - db (%1 >> 24) & 0xff -%endmacro - section .multiboot align 8 mb_start: @@ -38,33 +26,97 @@ stack_end: section .rodata align 16 -gdt_start: -gdt_entry 0, 0, 0, 0 -gdt_entry 0, 0xFFFFF, 0x9A, 0xC -gdt_entry 0, 0xFFFFF, 0x92, 0xC -gdt_end: -gdt_descriptor: - dw gdt_end - gdt_start - 1 - dd gdt_start - +; Access bits +PRESENT equ 1 << 7 +NOT_SYS equ 1 << 4 +EXEC equ 1 << 3 +DC equ 1 << 2 +RW equ 1 << 1 +ACCESSED equ 1 << 0 + +; Flags bits +GRAN_4K equ 1 << 7 +SZ_32 equ 1 << 6 +LONG_MODE equ 1 << 5 + +GDT: + .Null: equ $ - GDT + dq 0 + .Code: equ $ - GDT + dd 0xFFFF ; Limit & Base (low, bits 0-15) + db 0 ; Base (mid, bits 16-23) + db PRESENT | NOT_SYS | EXEC | RW ; Access + db GRAN_4K | LONG_MODE | 0xF ; Flags & Limit (high, bits 16-19) + db 0 ; Base (high, bits 24-31) + .Data: equ $ - GDT + dd 0xFFFF ; Limit & Base (low, bits 0-15) + db 0 ; Base (mid, bits 16-23) + db PRESENT | NOT_SYS | RW ; Access + db GRAN_4K | SZ_32 | 0xF ; Flags & Limit (high, bits 16-19) + db 0 ; Base (high, bits 24-31) + .TSS: equ $ - GDT + dd 0x00000068 + dd 0x00CF8900 + .Pointer: + dw $ - GDT - 1 + dq GDT section .text align 8 start: cli - lgdt [gdt_descriptor] - jmp 0x08:after_lgdt -after_lgdt: - mov ax, 0x10 - mov ds, ax - mov ss, ax - mov es, ax - mov fs, ax - mov gs, ax mov esp, stack_end mov ebp, stack_end + push ebx + + mov edi, 0x1000 + mov cr3, edi + xor eax, eax + mov ecx, 4096 + rep stosd + mov edi, cr3 + + mov DWORD [edi], 0x2003 ; Set the uint32_t at the destination index to 0x2003. + add edi, 0x1000 ; Add 0x1000 to the destination index. + mov DWORD [edi], 0x3003 ; Set the uint32_t at the destination index to 0x3003. + add edi, 0x1000 ; Add 0x1000 to the destination index. + mov DWORD [edi], 0x4003 ; Set the uint32_t at the destination index to 0x4003. + add edi, 0x1000 ; Add 0x1000 to the destination index. + + mov ebx, 0x00000003 ; Set the B-register to 0x00000003. + mov ecx, 512 ; Set the C-register to 512. + +.SetEntry: + mov DWORD [edi], ebx ; Set the uint32_t at the destination index to the B-register. + add ebx, 0x1000 ; Add 0x1000 to the B-register. + add edi, 8 ; Add eight to the destination index. + loop .SetEntry ; Set the next entry. + + ;push ebx ; Call our function to set up basic paging + ;call amd64_shim + + + mov eax, cr4 ; Enable the PAE bit + or eax, 1 << 5 + mov cr4, eax + + mov ecx, 0xC0000080 ; Enable long mode + rdmsr + or eax, 1 << 8 + wrmsr + + mov eax, cr0 ; Enable paging + or eax, 1 << 31 + mov cr0, eax + + lgdt [GDT.Pointer] + jmp GDT.Code:code64 + + bits 64 +code64: call amd64_shim + push rax call kmain cli halt: diff --git a/src/arch/amd64/shim.c b/src/arch/amd64/shim.c index 0c2d418..3e9cfd7 100644 --- a/src/arch/amd64/shim.c +++ b/src/arch/amd64/shim.c @@ -1,4 +1,5 @@ #include +#include #define PG_PRESENT 0x0000'0000'0000'0001 #define PG_READ_WRITE 0x0000'0000'0000'0002 @@ -8,14 +9,19 @@ #define PG_ACCESSED 0x0000'0000'0000'0020 #define PG_EXECUTE_DISABLE 0x8000'0000'0000'0000 +#define F_PRESENT 0b1 +#define F_WRITEABLE 0b10 +#define F_UNPRIVILEGED 0b100 +#define F_WRITETHROUGH 0b1000 +#define F_CACHEDISABLE 0b10000 +#define F_ACCESSED 0b100000 +#define F_DIRTY 0b1000000 +#define F_MEGABYTE 0b10000000 +#define F_GLOBAL 0b100000000 + // PAGE MAP LEVEL 4 ENTRY -struct pml4 { - uint64_t present : 1; - uint64_t rw : 1; - uint64_t user_supervisor : 1; - uint64_t write_through : 1; - uint64_t cache_disable : 1; - uint64_t accessed : 1; +struct pml4e { + uint64_t flags : 6; uint64_t _reserved : 6; uint64_t address : 40; uint64_t _reserved_2 : 11; @@ -24,12 +30,7 @@ struct pml4 { // PAGE DIRECTORY POINTER TABLE ENTRY struct pdpte { - uint64_t present : 1; - uint64_t rw : 1; - uint64_t user_supervisor : 1; - uint64_t write_through : 1; - uint64_t cache_disable : 1; - uint64_t accessed : 1; + uint64_t flags : 6; uint64_t _reserved : 1; uint64_t page_size : 1; uint64_t _reserved_2 : 2; @@ -40,12 +41,7 @@ struct pdpte { // PAGE DIRECTORY ENTRY struct pde { - uint64_t present : 1; - uint64_t rw : 1; - uint64_t user_supervisor : 1; - uint64_t write_through : 1; - uint64_t cache_disable : 1; - uint64_t accessed : 1; + uint64_t flags : 6; uint64_t _reserved : 1; uint64_t page_size : 1; uint64_t _reserved_2 : 2; @@ -56,15 +52,7 @@ struct pde { // PAGE TABLE ENTRY struct pte { - uint64_t present : 1; - uint64_t rw : 1; - uint64_t user_supervisor : 1; - uint64_t write_through : 1; - uint64_t cache_disable : 1; - uint64_t accessed : 1; - uint64_t dirty : 1; - uint64_t mem_type : 1; - uint64_t global : 1; + uint64_t flags : 9; uint64_t _reserved : 3; uint64_t address : 40; uint64_t _reserved_2 : 7; @@ -72,7 +60,36 @@ struct pte { uint64_t execute_disable : 1; }; -// entry point for amd64 -void amd64_shim(void *boot_info) { - +struct pml4e pml4[512]; +struct pdpte pdpt[512]; +struct pde pd[512]; +struct pte pt[512]; + +static int get_maxphysaddr() { + uint32_t eax, ebx, ecx, edx; + __cpuid(0x80000008, eax, ebx, ecx, edx); + return eax & 0xFF; +} + +// entry point for amd64 +void* amd64_shim(void *boot_info) { + for (int i = 0; i < 512; i++) { + pml4[i].flags = 0; + } + for (int i = 0; i < 512; i++) { + pdpt[i].flags = 0; + } + for (int i = 0; i < 512; i++) { + pd[i].flags = 0; + } + pml4[0].flags = F_PRESENT | F_WRITEABLE; + pml4[0].address = (uint64_t)&pdpt; + pdpt[0].flags = F_PRESENT | F_WRITEABLE; + pdpt[0].address = (uint64_t)&pd; + pd[0].flags = F_PRESENT | F_WRITEABLE; + pd[0].address = (uint64_t)&pt; + for (int i = 0; i < 512; i++) { + pt[i].flags = F_PRESENT | F_WRITEABLE; + pt[i].address = i * 4096; + } } diff --git a/src/kmain.c b/src/kmain.c index 9f4d63d..048cec0 100644 --- a/src/kmain.c +++ b/src/kmain.c @@ -1,5 +1,6 @@ void kmain() { + *(char*)0xB8000 = 'c'; while(1) { - asm("cli; hlt"); + __asm("cli; hlt"); } }