From 819a24ab8d0e9f4b9724fbf64f8ddfe8851d7a3a Mon Sep 17 00:00:00 2001 From: Jozef Nagy Date: Wed, 16 Apr 2025 23:11:21 +0200 Subject: [PATCH] Fixed ELF loading again, memory management needs to be redone properly --- Brewfile | 2 + boot/arch/x86_64/common/mm/paging.c | 37 ++++++++++++------- boot/arch/x86_64/common/proto/aurix_handoff.S | 17 ++++++++- boot/common/loader/elf.c | 8 ++-- boot/common/proto/aurix.c | 25 +++++++++---- kernel/Makefile | 2 +- kernel/arch/x86_64/linker.ld | 2 +- kernel/kinit.c | 2 + machine/riscv32/qemu.mk | 1 + 9 files changed, 68 insertions(+), 28 deletions(-) create mode 100644 machine/riscv32/qemu.mk diff --git a/Brewfile b/Brewfile index 702a4e9..993024a 100644 --- a/Brewfile +++ b/Brewfile @@ -10,6 +10,8 @@ brew "make" brew "gptfdisk" brew "xorriso" brew "qemu" +brew "llvm" +brew "lld" brew "util-linux" if OS.mac? brew "gsed" if OS.mac? diff --git a/boot/arch/x86_64/common/mm/paging.c b/boot/arch/x86_64/common/mm/paging.c index 85080a3..2c65b4d 100644 --- a/boot/arch/x86_64/common/mm/paging.c +++ b/boot/arch/x86_64/common/mm/paging.c @@ -28,45 +28,55 @@ /* https://github.com/KevinAlavik/nekonix/blob/main/kernel/src/mm/vmm.c */ /* Thanks, Kevin <3 */ -void map_pages(pagetable *pm, uintptr_t virt, uintptr_t phys, size_t size, uint64_t flags) -{ - for (size_t i = 0; i < ROUND_UP(size, PAGE_SIZE); i += PAGE_SIZE) { - map_page(pm, virt + i, phys + i, flags); - } -} - -void map_page(pagetable *pm, uintptr_t virt, uintptr_t phys, uint64_t flags) +static void _map(pagetable *pm, uintptr_t virt, uintptr_t phys, uint64_t flags) { uint64_t pml1_idx = (virt >> 12) & 0x1ff; uint64_t pml2_idx = (virt >> 21) & 0x1ff; uint64_t pml3_idx = (virt >> 30) & 0x1ff; uint64_t pml4_idx = (virt >> 39) & 0x1ff; + flags |= VMM_PRESENT; + if (!(pm->entries[pml4_idx] & 1)) { void *pml4 = mem_alloc(PAGE_SIZE); memset(pml4, 0, sizeof(pagetable)); - pm->entries[pml4_idx] = (uint64_t)pml4 | VMM_PRESENT | VMM_WRITABLE | VMM_USER; + pm->entries[pml4_idx] = (uint64_t)pml4 | VMM_PRESENT | VMM_WRITABLE; } pagetable *pml3_table = (pagetable *)(pm->entries[pml4_idx] & 0x000FFFFFFFFFF000); if (!(pml3_table->entries[pml3_idx] & 1)) { void *pml3 = mem_alloc(PAGE_SIZE); memset(pml3, 0, sizeof(pagetable)); - pml3_table->entries[pml3_idx] = (uint64_t)pml3 | VMM_PRESENT | VMM_WRITABLE | VMM_USER; + pml3_table->entries[pml3_idx] = (uint64_t)pml3 | VMM_PRESENT | VMM_WRITABLE; } pagetable *pml2_table = (pagetable *)(pml3_table->entries[pml3_idx] & 0x000FFFFFFFFFF000); if (!(pml2_table->entries[pml2_idx] & 1)) { void *pml2 = mem_alloc(PAGE_SIZE); memset(pml2, 0, sizeof(pagetable)); - pml2_table->entries[pml2_idx] = (uint64_t)pml2 | VMM_PRESENT | VMM_WRITABLE | VMM_USER; + pml2_table->entries[pml2_idx] = (uint64_t)pml2 | VMM_PRESENT | VMM_WRITABLE; } pagetable *pml1_table = (pagetable *)(pml2_table->entries[pml2_idx] & 0x000FFFFFFFFFF000); - if (!(pml1_table->entries[pml1_idx] & 1)) { - pml1_table->entries[pml1_idx] = (phys | 0x000FFFFFFFFFF000) | flags; + if ((pml1_table->entries[pml1_idx] & 1)) { + debug("_map(): Remapping present page\n"); } + pml1_table->entries[pml1_idx] = (phys & 0x000FFFFFFFFFF000) | flags; +} + +void map_pages(pagetable *pm, uintptr_t virt, uintptr_t phys, size_t size, uint64_t flags) +{ + for (size_t i = 0; i < ROUND_UP(size, PAGE_SIZE); i += PAGE_SIZE) { + _map(pm, virt + i, phys + i, flags); + } + + debug("map_pages(): Mapped 0x%llx-0x%llx -> 0x%llx-0x%llx\n", phys, phys + (size * PAGE_SIZE), virt, virt + (size * PAGE_SIZE)); +} + +void map_page(pagetable *pm, uintptr_t virt, uintptr_t phys, uint64_t flags) +{ + _map(pm, virt, phys, flags); debug("map_page(): Mapped 0x%llx -> 0x%llx\n", phys, virt); } @@ -77,6 +87,7 @@ pagetable *create_pagemap() debug("create_pagemap(): Failed to allocate memory for a new pm.\n"); return NULL; } + pm = (pagetable *)ROUND_UP((uint64_t)pm, PAGE_SIZE); memset(pm, 0, sizeof(pagetable)); debug("create_pagemap(): Created new pm at 0x%llx\n", (uint64_t)pm); diff --git a/boot/arch/x86_64/common/proto/aurix_handoff.S b/boot/arch/x86_64/common/proto/aurix_handoff.S index 9d7e12b..7c8f896 100644 --- a/boot/arch/x86_64/common/proto/aurix_handoff.S +++ b/boot/arch/x86_64/common/proto/aurix_handoff.S @@ -2,10 +2,23 @@ .globl _aurix_handoff_end .globl aurix_handoff +_aurix_handoff_start: aurix_handoff: cli movq %rsi, %rsp -_aurix_handoff_start: +.section _aurix_handoff movq %rdi, %cr3 - jmpq *%rdx + xor %rax, %rax + xor %rbx, %rbx + xor %rcx, %rcx + xor %rdi, %rdi + xor %r8, %r8 + xor %r9, %r9 + xor %r10, %r10 + xor %r11, %r11 + xor %r12, %r12 + xor %r13, %r13 + xor %r14, %r14 + xor %r15, %r15 + callq *%rdx _aurix_handoff_end: \ No newline at end of file diff --git a/boot/common/loader/elf.c b/boot/common/loader/elf.c index 77ce003..bd17021 100644 --- a/boot/common/loader/elf.c +++ b/boot/common/loader/elf.c @@ -65,21 +65,21 @@ uintptr_t elf64_load(char *data, pagetable *pagemap) flags |= VMM_WRITABLE; if (!(ph[i].p_flags & PF_X)) flags |= VMM_NX; - - debug("elf64_load(): phys=0x%llx, virt=0x%llx, size=%lu\n", ph[i].p_paddr, ph[i].p_vaddr, ph[i].p_filesz); - + uint64_t phys = (uint64_t)mem_alloc(ph[i].p_memsz); if (!phys) { debug("elf64_load(): Out of memory\n"); return 0; } + + debug("elf64_load(): phys=0x%llx, virt=0x%llx, size=%lu\n", phys, ph[i].p_vaddr, ph[i].p_filesz); map_page(pagemap, ph[i].p_vaddr, phys, flags); memcpy((void*)ph[i].p_vaddr - lowest, data + ph[i].p_offset, ph[i].p_filesz); } debug("elf64_load(): ELF loaded successfully, entry: 0x%llx\n", header->e_entry); - return (uintptr_t)((uint8_t *)data + (header->e_entry - lowest)); + return (uintptr_t)((uint8_t *)data + header->e_entry); } uintptr_t elf_load(char *data, pagetable *pagemap) diff --git a/boot/common/proto/aurix.c b/boot/common/proto/aurix.c index 04674ed..10fa041 100644 --- a/boot/common/proto/aurix.c +++ b/boot/common/proto/aurix.c @@ -23,6 +23,9 @@ #include #include #include +#include +#include +#include extern __attribute__((noreturn)) void aurix_handoff(void *pagemap, void *stack, uint64_t entry, void *params); extern char _aurix_handoff_start[], _aurix_handoff_end[]; @@ -35,20 +38,24 @@ void aurix_load(char *kernel) // TODO: Do something with the kernel :p pagetable *pm = create_pagemap(); + // __asm__ volatile("mov %%cr3, %0" : "=r"(pm)); if (!pm) { debug("aurix_load(): Failed to create kernel pagemap! Halting...\n"); // TODO: Halt while (1); } - map_pages(pm, (uintptr_t)_aurix_handoff_start, (uintptr_t)_aurix_handoff_start, (uint64_t)_aurix_handoff_end - (uint64_t)_aurix_handoff_start, VMM_PRESENT | VMM_USER | VMM_WRITABLE); - + map_pages(pm, (uintptr_t)pm, (uintptr_t)pm, PAGE_SIZE, VMM_WRITABLE); + map_pages(pm, (uintptr_t)_aurix_handoff_start, (uintptr_t)_aurix_handoff_start, (uint64_t)_aurix_handoff_end - (uint64_t)_aurix_handoff_start, 0); + void *stack = mem_alloc(16*1024); // 16 KiB stack should be well more than enough if (!stack) { debug("aurix_load(): Failed to allocate stack! Halting...\n"); while (1); } + map_pages(pm, (uintptr_t)stack, (uintptr_t)stack, 16*1024, VMM_WRITABLE | VMM_NX); + void *kernel_entry = (void *)elf_load(kbuf, pm); if (!kernel_entry) { debug("aurix_load(): Failed to load '%s'! Halting...\n", kernel); @@ -60,10 +67,14 @@ void aurix_load(char *kernel) debug("aurix_load(): Handoff state: pm=0x%llx, stack=0x%llx, kernel_entry=0x%llx\n", pm, stack, kernel_entry); - aurix_handoff(pm, (void *)((uint8_t)stack + 16*1024), (uint64_t)kernel_entry, (void *)parameters); + // this triggers a #GP ???? + // aurix_handoff(pm, stack, (uint64_t)kernel_entry, (void *)parameters); + // __builtin_unreachable(); - // __asm__ volatile("movq %[pml4], %%cr3\n" :: [pml4]"r"(pm) : "memory"); + __asm__ volatile("movq %[pml4], %%cr3\n" + "movq %[stack], %%rsp\n" + "callq *%[entry]\n" + :: [pml4]"r"(pm), [stack]"r"(stack), [entry]"r"(kernel_entry) : "memory"); // __asm__ volatile("callq *%[entry]\n" - // :: [entry]"r"(kernel_entry)); - -} \ No newline at end of file + // :: [entry]"r"(kernel_entry)); +} diff --git a/kernel/Makefile b/kernel/Makefile index 54da7de..a7027f1 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -55,7 +55,7 @@ KERNEL_CFLAGS := $(foreach d, $(INCLUDE_DIRS), -I$d) \ KERNEL_LDFLAGS := -Tarch/$(ARCH)/linker.ld \ -nostdlib \ -static \ - #-no-pie + -no-pie ifeq ($(BUILD_TYPE),debug) KERNEL_CFLAGS += -O0 -g3 diff --git a/kernel/arch/x86_64/linker.ld b/kernel/arch/x86_64/linker.ld index 95a8a7a..7314b13 100644 --- a/kernel/arch/x86_64/linker.ld +++ b/kernel/arch/x86_64/linker.ld @@ -32,7 +32,7 @@ PHDRS SECTIONS { /* TODO: 0xffffffff80000000 */ - . = 0xffffffff80000000; + . = 0x1000; _linker_start_text = .; diff --git a/kernel/kinit.c b/kernel/kinit.c index 7fff330..4b35ba3 100644 --- a/kernel/kinit.c +++ b/kernel/kinit.c @@ -31,4 +31,6 @@ void _start(void) __asm__ volatile("wfe"); #endif } + + __builtin_unreachable(); } \ No newline at end of file diff --git a/machine/riscv32/qemu.mk b/machine/riscv32/qemu.mk new file mode 100644 index 0000000..7e49084 --- /dev/null +++ b/machine/riscv32/qemu.mk @@ -0,0 +1 @@ +QEMU_MACHINE_FLAGS := -M virt -bios default -nographic \ No newline at end of file