From 42a2bdaecaee627247689b3f4ff2828fe3c8dc97 Mon Sep 17 00:00:00 2001 From: Jon Santmyer Date: Thu, 11 Sep 2025 14:37:04 -0400 Subject: load init from ELF executable --- arch/x86_64/boot/limine/memorymap.c | 1 + arch/x86_64/device/processor.c | 10 ++- arch/x86_64/elf.c | 2 + arch/x86_64/init.c | 129 ++++++++++++++++++++++++++++++++++-- arch/x86_64/lib/object.c | 1 + arch/x86_64/memory/pml4.c | 2 + arch/x86_64/tasking/tcb.c | 35 ++++++++++ arch/x86_64/usermode.c | 7 +- device/initrd.c | 2 +- device/portio_uart.c | 2 +- include/arch/x86_64/init.h | 12 ++++ include/arch/x86_64/tcb.h | 10 ++- include/device/processor.h | 6 +- include/elf.h | 6 +- include/init.h | 3 - include/memory.h | 2 - include/tcb.h | 2 + lib/print.c | 2 +- main.c | 12 ++++ syscall/handler.c | 2 +- 20 files changed, 220 insertions(+), 28 deletions(-) create mode 100644 arch/x86_64/tasking/tcb.c create mode 100644 include/arch/x86_64/init.h diff --git a/arch/x86_64/boot/limine/memorymap.c b/arch/x86_64/boot/limine/memorymap.c index 43aecf7..a09acab 100644 --- a/arch/x86_64/boot/limine/memorymap.c +++ b/arch/x86_64/boot/limine/memorymap.c @@ -3,6 +3,7 @@ #include "object.h" #include "print.h" #include "jove.h" +#include "init.h" #include "arch/x86_64/page.h" static struct jove_ObjectDirectory s_untyped_dir = { diff --git a/arch/x86_64/device/processor.c b/arch/x86_64/device/processor.c index f7e5cac..ff920c8 100644 --- a/arch/x86_64/device/processor.c +++ b/arch/x86_64/device/processor.c @@ -1,8 +1,6 @@ #include "device/processor.h" -#include "arch/x86_64/tables.h" #include "include/arch/x86_64/idt.h" -#include "include/arch/x86_64/object.h" -#include "jove.h" +#include "init.h" processor_t s_bsp = { .odir = &_initDirectory @@ -133,3 +131,9 @@ processor_current(void) rdmsr(MSR_GS_BASE, (uint32_t*)&r, ((uint32_t*)&r) + 1); return (void*)r; } + +objdir_t* +processor_get_objdir(void *processor) +{ + return ((processor_t*)processor)->odir; +} diff --git a/arch/x86_64/elf.c b/arch/x86_64/elf.c index 696b7a7..ae0fa71 100644 --- a/arch/x86_64/elf.c +++ b/arch/x86_64/elf.c @@ -1,4 +1,5 @@ #include "elf.h" +#include "init.h" #include int @@ -23,5 +24,6 @@ elf64_loadexec(Elf64_Ehdr *ehdr) if(!elf64_ehdr_valid(ehdr)) return NULL; void *entry = (void*)ehdr->e_entry; + return entry; } diff --git a/arch/x86_64/init.c b/arch/x86_64/init.c index 4ec7718..7a2f67d 100644 --- a/arch/x86_64/init.c +++ b/arch/x86_64/init.c @@ -1,6 +1,12 @@ #include "init.h" +#include "bootargs.h" +#include "device/initrd.h" #include "arch/x86_64/page.h" +#include "arch/x86_64/processor.h" #include "device/processor.h" +#include "print.h" +#include "elf.h" +#include "string.h" uintptr_t init_alloc_pageframe() @@ -11,7 +17,7 @@ init_alloc_pageframe() /*Seek to the last member of untyped directory.*/ uint8_t lastmembi = 1; for(; untyped_dir->entries[lastmembi].type == KO_MEMORY_UNTYPED; lastmembi++); - objdir_entry_t *lastmemb = &untyped_dir->entries[lastmembi]; + objdir_entry_t *lastmemb = &untyped_dir->entries[lastmembi-1]; objdir_entry_t pageframe; ko_untyped_split(lastmemb, &pageframe, 0x1000); @@ -19,7 +25,7 @@ init_alloc_pageframe() } void -init_map_pageframe(uintptr_t pptr, uintptr_t vptr, uint8_t pflags) +init_map_pageframe(uintptr_t pptr, uintptr_t vptr, uint64_t pflags) { uint64_t pathval; uint16_t *path = (uint16_t*)&pathval; @@ -51,13 +57,128 @@ init_ensure_page(uintptr_t vptr, uint8_t pflags) processor_t *proc = processor_current(); pmle_t *pml4 = pptr_tovirt_ident(proc->pdir); - pmle_t *pmld = pml4, *pmle; + pmle_t *pmld = pml4, *pmle = NULL; for(uint8_t d = 0; d < 4; d++) { uint16_t pmli = path[d]; pmle = &pmld[pmli]; if(!pmle->p) { - pmle->value = init_alloc_pageframe() | (d == 3 ? pflags : PAGE_PRESENT | PAGE_RW | PAGE_US); + physptr_t frame = init_alloc_pageframe(); + pmle->value = frame | (d == 3 ? pflags : (PAGE_PRESENT | PAGE_RW | PAGE_US)); + if(d != 3) memset(pptr_tovirt_ident(frame), 0, 0x1000); + pmle->p = 1; } pmld = pptr_tovirt_ident(pmle->paddr << 12); } + __asm__ volatile("invlpg (%0)":: "r"(vptr): "memory"); +} + +void +init_reperm_page(uintptr_t vptr, uint64_t pflags) +{ + uint64_t pathval; + uint16_t *path = (uint16_t*)&pathval; + pml4_get_path(vptr, 4, path); + + processor_t *proc = processor_current(); + pmle_t *pml4 = pptr_tovirt_ident(proc->pdir); + + pmle_t *pmld = pml4, *pmle = NULL; + for(uint8_t d = 0; d < 4; d++) { + uint16_t pmli = path[d]; + pmle = &pmld[pmli]; + if(!pmle->p) { + return; + } + pmld = pptr_tovirt_ident(pmle->paddr << 12); + } + pmle->rw = pflags & PAGE_RW ? 1 : 0; + pmle->xd = pflags & PAGE_XD ? 1 : 0; + __asm__ volatile("invlpg (%0)":: "r"(vptr): "memory"); +} + +void +init_ensure_range(uintptr_t base, size_t width, uint64_t pflags) +{ + if(width & 0xFFF) width = (width | 0xFFF) + 1; + width >>= 12; + for(size_t i = 0; i < width; i++) { + init_ensure_page(base + (i << 12), pflags); + } +} + +void +init_reperm_range(uintptr_t base, size_t width, uint64_t pflags) +{ + if(width & 0xFFF) width = (width | 0xFFF) + 1; + width >>= 12; + for(size_t i = 0; i < width; i++) { + init_reperm_page(base + (i << 12), pflags); + } +} + +void +init_load(void) +{ + char *init_arg = bootargs_getarg("init"); + if(init_arg == NULL) { + klogf("init not specified in bootargs!\n"); + return; + } + tar_header_t *init_file = initrd_find_file(init_arg); + if(init_file == NULL) { + klogf("init not found in initrd! (filename %s)\n", init_arg); + return; + } + uint8_t *init_data = (uint8_t*)&((tar_block_t*)init_file)[1]; + Elf64_Ehdr *init_ehdr = (Elf64_Ehdr*)init_data; + if(!elf64_ehdr_valid(init_ehdr)) { + klogf("init is not a proper ELF executable!\n"); + return; + } + + uintptr_t program_end = 0; + for(size_t phdri = 0; phdri < init_ehdr->e_phnum; phdri++) { + Elf64_Phdr *phdr = &((Elf64_Phdr*)(init_data + init_ehdr->e_phoff))[phdri]; + if(phdr->p_type == PT_LOAD) { + uintptr_t section_base = phdr->p_vaddr; + size_t section_size = phdr->p_memsz; + size_t section_cpysize = phdr->p_filesz; + + if(section_base + section_size > program_end) { + program_end = section_base + section_size; + if(program_end & 0xFFF) program_end = ((program_end >> 12) + 1) << 12; + } + klogf("ELF LOAD %p %p %p %x\n", section_base, section_size, section_cpysize, phdr->p_flags); + + init_ensure_range(section_base, section_size, PAGE_PRESENT | PAGE_US | PAGE_RW); + + memcpy((void*)section_base, init_data + phdr->p_offset, section_cpysize); + memset((void*)(section_base + section_cpysize), 0, (section_size - section_cpysize)); + + init_reperm_range(section_base, section_size, (phdr->p_flags & PF_W ? PAGE_RW : 0) | + (!(phdr->p_flags & PF_X) ? PAGE_XD : 0)); + } + } + + //Allocate usermode stack. + uintptr_t usermode_stack_base = 0x00007FFFFFFFE000; + init_ensure_range(usermode_stack_base, 0x2000, PAGE_PRESENT | PAGE_RW | PAGE_US | PAGE_XD); + + uintptr_t *usermode_sp = (uintptr_t*)(usermode_stack_base + 0x1FF8); + + //Allocate syscall message. + uintptr_t message_frame = init_alloc_pageframe(); + init_map_pageframe(message_frame, program_end, PAGE_PRESENT | PAGE_RW | PAGE_US | PAGE_XD); + + _initDirectory.entries[INIT_OBJECT_MESSAGE] = (objdir_entry_t) { + .type = KO_MESSAGE, + .extra = KODE_EX_MESSAGE_MAPPED, + .data = program_end + }; + *(--usermode_sp) = program_end; + + extern tcb_t *_init_tcb; + _init_tcb->sp = (uintptr_t)usermode_sp; + + usermode((void*)init_ehdr->e_entry, usermode_sp); } diff --git a/arch/x86_64/lib/object.c b/arch/x86_64/lib/object.c index 4ab8f06..43d490f 100644 --- a/arch/x86_64/lib/object.c +++ b/arch/x86_64/lib/object.c @@ -1,6 +1,7 @@ #include "object.h" #include "error.h" #include "device/processor.h" +#include "arch/x86_64/processor.h" #include "arch/x86_64/page.h" #include "arch/x86_64/page-mapping.h" diff --git a/arch/x86_64/memory/pml4.c b/arch/x86_64/memory/pml4.c index fcfc897..b22bcfb 100644 --- a/arch/x86_64/memory/pml4.c +++ b/arch/x86_64/memory/pml4.c @@ -1,8 +1,10 @@ #include "arch/x86_64/page.h" +#include "arch/x86_64/processor.h" #include "device/processor.h" #include "memory.h" #include "boot.h" #include "object.h" +#include "init.h" #include "string.h" #include "jove.h" #include "error.h" diff --git a/arch/x86_64/tasking/tcb.c b/arch/x86_64/tasking/tcb.c new file mode 100644 index 0000000..9877455 --- /dev/null +++ b/arch/x86_64/tasking/tcb.c @@ -0,0 +1,35 @@ +#include "arch/x86_64/tcb.h" +#include "arch/x86_64/processor.h" +#include "arch/x86_64/page.h" +#include "device/processor.h" +#include "object.h" +#include "init.h" +#include "string.h" + +#define INIT_TCB_BYTES (0x1000 + KERNEL_STACK_MINSIZE) +uint8_t _init_tcb_bytes[INIT_TCB_BYTES]; +tcb_t *_init_tcb = (tcb_t*)&_init_tcb_bytes; + +void +tcb_init(void *task_main) +{ + memset(_init_tcb, 0, INIT_TCB_BYTES); + _init_tcb->size = INIT_TCB_BYTES; + size_t kstack_bytes = (size_t)(INIT_TCB_BYTES - sizeof(tcb_t)); + + _init_tcb->ksp = (uintptr_t)_init_tcb->kstack + kstack_bytes - sizeof(intmax_t); + _init_tcb->pml4 = ko_entry_data(&_initDirectory.entries[INIT_OBJECT_PAGEMAP]); + + _initDirectory.entries[INIT_OBJECT_TCB] = (objdir_entry_t) { + .type = KO_TCB, + .data = vptr_tophys_koff((uintptr_t)_init_tcb) + }; + + ((processor_t*)processor_current())->tcb = _init_tcb; + + __asm__ volatile("\ + movq %0, %%rsp; \ + movq $0, %%rbp; \ + jmpq %1":: + "r"(_init_tcb->ksp), "r"(task_main)); +} diff --git a/arch/x86_64/usermode.c b/arch/x86_64/usermode.c index 8975993..24a31a1 100644 --- a/arch/x86_64/usermode.c +++ b/arch/x86_64/usermode.c @@ -1,8 +1,7 @@ - +#include "jove.h" __attribute__((noreturn)) -static void -s_enter_usermode(void *ip, void *sp) +void usermode(void *ip, void *sp) { __asm__ volatile("mov %0, %%rsp; \ movq %1, %%rcx; \ @@ -11,5 +10,5 @@ s_enter_usermode(void *ip, void *sp) swapgs; \ sysretq":: "r"(sp), "r"(ip): "memory"); - for(;;); + hcf(); } diff --git a/device/initrd.c b/device/initrd.c index 58f38c9..b57687c 100644 --- a/device/initrd.c +++ b/device/initrd.c @@ -5,7 +5,7 @@ #include "device/initrd.h" #include "boot.h" #include "object.h" -#include "jove.h" +#include "init.h" #include "bootargs.h" #include "print.h" #include "string.h" diff --git a/device/portio_uart.c b/device/portio_uart.c index 58314d5..9cc76f8 100644 --- a/device/portio_uart.c +++ b/device/portio_uart.c @@ -1,5 +1,5 @@ #ifdef ENABLE_PORTIO_UART -#include "jove.h" +#include "init.h" #include "device/portio_uart.h" #include "device/portio.h" diff --git a/include/arch/x86_64/init.h b/include/arch/x86_64/init.h new file mode 100644 index 0000000..d8fdf2c --- /dev/null +++ b/include/arch/x86_64/init.h @@ -0,0 +1,12 @@ +#ifndef _JOVE_x86_64_INIT_H +#define _JOVE_x86_64_INIT_H 1 + +#include + +uintptr_t init_alloc_pageframe(); +void init_map_pageframe(uintptr_t pptr, uintptr_t vptr, uint8_t pflags); + +__attribute__((noreturn)) +void usermode(void *ip, void *sp); + +#endif diff --git a/include/arch/x86_64/tcb.h b/include/arch/x86_64/tcb.h index 33da4fa..ae93bdf 100644 --- a/include/arch/x86_64/tcb.h +++ b/include/arch/x86_64/tcb.h @@ -2,17 +2,23 @@ #define _JOVE_x86_64_TCB_H 1 #include +#include + +#define KERNEL_STACK_MINSIZE 0x1000 typedef struct jove_ThreadControlBlock { - void *stack; + size_t size; + struct jove_ThreadControlBlock *tcb_next, *sched_next; + uint8_t priority; + uintptr_t sp, ksp; void *pml4; void *mailbox; /* PML caching for faster calls?*/ - uint8_t kstack[KERNEL_STACKBYTES]; + uint8_t kstack[]; } tcb_t; #endif diff --git a/include/device/processor.h b/include/device/processor.h index 33deed4..e0ec16c 100644 --- a/include/device/processor.h +++ b/include/device/processor.h @@ -1,9 +1,7 @@ #ifndef _JOVE_DEVICE_PROCESSOR_H #define _JOVE_DEVICE_PROCESSOR_H 1 -#if defined(__x86_64__) -#include "arch/x86_64/processor.h" -#endif +#include "object.h" /**@FUNC Initialize the bootstrap processor.*/ void bsp_setup(void); @@ -19,4 +17,6 @@ void processor_setup(void* processor); * @RET pointer to current processor.*/ void *processor_current(void); +objdir_t *processor_get_objdir(void *processor); + #endif diff --git a/include/elf.h b/include/elf.h index 05e3e83..acd0aea 100644 --- a/include/elf.h +++ b/include/elf.h @@ -89,9 +89,9 @@ typedef struct { #define PT_NULL 0 #define PT_LOAD 1 -#define PF_X 1 -#define PF_W 2 -#define PF_R 4 +#define PF_X 0x1 +#define PF_W 0x2 +#define PF_R 0x4 typedef struct { diff --git a/include/init.h b/include/init.h index 2174785..fc1361d 100644 --- a/include/init.h +++ b/include/init.h @@ -17,9 +17,6 @@ enum { #include "object.h" extern objdir_t _initDirectory; -uintptr_t init_alloc_pageframe(); -void init_map_pageframe(uintptr_t pptr, uintptr_t vptr, uint8_t pflags); - void init_load(void); #endif diff --git a/include/memory.h b/include/memory.h index 901060c..3e97bcf 100644 --- a/include/memory.h +++ b/include/memory.h @@ -7,8 +7,6 @@ typedef uintptr_t physptr_t; typedef uintptr_t virtptr_t; -#define KERNEL_STACK_SIZE 0x1000 - void mapping_setup_init(void); void mapping_setup(objdir_entry_t *mapping); diff --git a/include/tcb.h b/include/tcb.h index c28a860..511f69e 100644 --- a/include/tcb.h +++ b/include/tcb.h @@ -4,6 +4,8 @@ #include #include +struct jove_ThreadControlBlock; +void tcb_init(void *task_main); #endif diff --git a/lib/print.c b/lib/print.c index 6f5c551..14ed814 100644 --- a/lib/print.c +++ b/lib/print.c @@ -1,6 +1,6 @@ #include "print.h" #include "device/uart.h" -#include "jove.h" +#include "init.h" #include "string.h" #include #include diff --git a/main.c b/main.c index 579f68c..34f2dd7 100644 --- a/main.c +++ b/main.c @@ -4,6 +4,8 @@ #include "print.h" #include "init.h" #include "boot.h" +#include "tcb.h" +#include "init.h" #include "device/portio_uart.h" #include "device/processor.h" #include "device/initrd.h" @@ -18,6 +20,15 @@ struct jove_ObjectDirectory _initDirectory = { } }; +static void +_jove_tasking_main(void) +{ + init_load(); + + kprintf("Reached end of kernel task!\n"); + hcf(); +} + void _jove_main(void) { @@ -32,6 +43,7 @@ _jove_main(void) initrd_setup(); #endif + tcb_init(_jove_tasking_main); kprintf("Reached end of kernel main!\n"); hcf(); } diff --git a/syscall/handler.c b/syscall/handler.c index a586a73..5bc3c6f 100644 --- a/syscall/handler.c +++ b/syscall/handler.c @@ -52,7 +52,7 @@ s_syscall_handle_invoke(objdir_t *root_dir, uint8_t *payload) int _syscall_handler(uintmax_t argsi, int calli) { - objdir_t *root_dir = ((processor_t*)processor_current())->odir; + objdir_t *root_dir = processor_get_objdir(processor_current()); objdir_entry_t *payload_entry = objdir_seek(root_dir, (uint8_t*)&argsi, sizeof(uintmax_t)); if(payload_entry->type != KO_MESSAGE) { -- cgit v1.2.1