From c2788174198632e0c8bdbfa7762081f595460bdf Mon Sep 17 00:00:00 2001 From: Jon Santmyer Date: Tue, 29 Sep 2026 12:53:57 -0400 Subject: move process code into proc. add panic folder --- arch/x86_64/proc/init.c | 173 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 arch/x86_64/proc/init.c (limited to 'arch/x86_64/proc/init.c') diff --git a/arch/x86_64/proc/init.c b/arch/x86_64/proc/init.c new file mode 100644 index 0000000..4c86038 --- /dev/null +++ b/arch/x86_64/proc/init.c @@ -0,0 +1,173 @@ +#include "init.h" +#include "arch/x86_64/hal/msr.h" +#include "config.h" +#include "proc/process.h" +#include "jove.h" +#include "hal/obj.h" +#include "lib/string.h" +#include "panic/panic.h" +#include "lib/printf.h" +#include "arch/x86_64/lib/elf.h" +#include "arch/x86_64/hal/paging.h" +#include "boot/cmdline.h" +#include "boot/initrd.h" + +PAGEALIGN static uint8_t s_init_program_pages[INIT_PROGRAM_PAGES_MAX][0x1000]; +PAGEALIGN static uint8_t s_init_stack_pages[INIT_STACK_PAGES + 3][0x1000]; +PAGEALIGN static uint8_t s_init_message_page[0x1000]; + +static int +elf_is_valid(struct elf_header *ehdr) +{ + if(ehdr->e_ident[0] != EI_MAG0 || + ehdr->e_ident[1] != EI_MAG1 || + ehdr->e_ident[2] != EI_MAG2 || + ehdr->e_ident[3] != EI_MAG3) { + kprintf("ELF: Magic does not match!\n"); + return 0; + } + if(ehdr->e_ident[4] != EI_CLASS_64) { + kprintf("ELF: Class is not 64-bit!\n"); + return 0; + } + if(ehdr->e_ident[5] != EI_DATA_LE) { + kprintf("ELF: Data is not little-endian!\n"); + return 0; + } + if(ehdr->e_type != ET_EXEC) { + kprintf("ELF: Program is not standard executable type!\n"); + return 0; + } + if(ehdr->e_machine != EM_x86_64) { + kprintf("ELF: Executable is not x86_64!\n"); + return 0; + } + return 1; +} + +void +init_setup(void) +{ + //Get the init file data from the initrd. + const char *init_path = cmdline_getarg("init"); + if(init_path == NULL) { + kpanic("Kernel commandline is missing 'init' arg.\n"); + } + + jove_owned_obj_t *initrd_obj = objdir_getlocal(_rootdir_obj, ROOTDIR_INITRD_I); + jove_owned_obj_t *init_obj = initrd_seek(initrd_obj, init_path); + if(init_obj == NULL) { + kpanic("init: Cannot find file '%s' in initrd.\n", init_path); + } + obj_release(initrd_obj); + + void *init_data = initrd_file_data(init_obj); + obj_release(init_obj); + + struct elf_header *init_ehdr = init_data; + if(init_ehdr == NULL) { + kpanic("init: Cannot get file data for file '%s': %i\n", init_path, errno); + } + + if(!elf_is_valid(init_ehdr)) { + kpanic("init: Either passed file '%s' is not an ELF file or is not loadable.\n", init_path); + } + + jove_owned_obj_t *init_pagedir = objdir_getlocal(_rootdir_obj, ROOTDIR_PAGEDIR_I); + page_t *pml4 = obj_deref(init_pagedir); + size_t last_base = 0; + + //Load the init ELF + size_t last_page = 0; + for(size_t i = 0; i < init_ehdr->e_phnum; i++) { + struct elf_phdr *phdr = init_data + init_ehdr->e_phoff + i * init_ehdr->e_phentsize; + if(phdr->p_type != PT_LOAD) continue; + kprintf("init: phdr %i flags %b\n", i, phdr->p_flags); + + uintptr_t base = phdr->p_vaddr; + size_t limit = phdr->p_memsz; + if(last_base < base + limit) last_base = base + limit; + + uintptr_t page_base = base & ~0xFFFULL; + size_t pages = (limit + 4095) / 4096; + + for(size_t i = 0; i < pages; i++) { + uintptr_t page_virt = page_base + (i << 12); + if(last_page >= INIT_PROGRAM_PAGES_MAX) { + kpanic("Program exceeds size limit! (%i > %i)\n", last_page, INIT_PROGRAM_PAGES_MAX); + } + + int tblres = 0; + do { + uintptr_t tbl_frame = KPTR_TOPHYS(&s_init_program_pages[last_page++]); + tblres = pagedir_map_table(pml4, tbl_frame, page_virt); + if(tblres == EHASMAP) last_page--; + }while(!tblres); + + pagedir_map_frame(pml4, KPTR_TOPHYS(&s_init_program_pages[last_page++]), page_virt, + PAGE_WRITEABLE | PAGE_USER); + } + + //Copy data from section if SHT_PROGBITS + memcpy((void*)phdr->p_vaddr, init_data + phdr->p_offset, phdr->p_memsz); + } + + //Map the stack + size_t stack_base = 0x00007FFFFFFFF000; + int stack_mapres = 0; + + last_page = 0; + for(size_t i = 0; i < INIT_STACK_PAGES; i++) { + uintptr_t page_virt = stack_base - (i << 12); + int tblres = 0; + + do { + uintptr_t tbl_frame = KPTR_TOPHYS(&s_init_stack_pages[last_page++]); + tblres = pagedir_map_table(pml4, tbl_frame, page_virt); + if(tblres == EHASMAP) last_page--; + }while(!tblres); + + pagedir_map_frame(pml4, KPTR_TOPHYS(&s_init_stack_pages[last_page++]), page_virt, + PAGE_WRITEABLE | PAGE_USER | PAGE_XD); + } + + //Map the syscall message. + last_base = (last_base + 0xFFF) & ~0xFFF; + uintptr_t message_pptr = KPTR_TOPHYS(s_init_message_page); + pagedir_map_frame(pml4, message_pptr, last_base, + PAGE_WRITEABLE | PAGE_USER | PAGE_XD); + + extern struct init_payload _init_payload; + _init_payload.brk = last_base + 0x1000; + + memcpy((void*)last_base, &_init_payload, sizeof(struct init_payload)); + + jove_owned_obj_t *message_obj = objdir_getlocal(_rootdir_obj, ROOTDIR_MESSAGE_I); + obj_settype(message_obj, JOVE_OBJ_MESSAGE); + obj_setvalue(message_obj, (message_pptr & ~0xFFF) | 1); + obj_release(message_obj); + + obj_release(init_pagedir); + + //Enable syscalls + extern void _syscall_entry(void); + msr_set_lstar(_syscall_entry); + + //Setup KSP for syscalls + jove_owned_obj_t *pcb_obj = process_current(); + pcb_t *pcb = obj_deref(pcb_obj); + + obj_release(pcb_obj); + obj_release(_rootdir_obj); + + uintptr_t usp = 0x00007FFFFFFFFFF8; + uintptr_t uip = init_ehdr->e_entry; + + __asm__ volatile("movq %0, %%rsp; \ + movq %1, %%rcx; \ + movq %2, %%rdi; \ + movq $0x202, %%r11; \ + swapgs; \ + sysretq":: + "r"(usp), "r"(uip), "m"(last_base): "memory"); +} -- cgit v1.2.3