diff options
author | Jon Santmyer <jon@jonsantmyer.com> | 2025-09-10 13:28:28 -0400 |
---|---|---|
committer | Jon Santmyer <jon@jonsantmyer.com> | 2025-09-10 13:28:28 -0400 |
commit | 7f350e7ee1c2c38e5ac0b6c22c17388f6c78f0b5 (patch) | |
tree | aef9904e2495ce840319f2815cd859c47294c88a | |
parent | 032a7bc4d79efea100a00cf3464bea3249a07ff6 (diff) | |
download | jove-kernel-7f350e7ee1c2c38e5ac0b6c22c17388f6c78f0b5.tar.gz jove-kernel-7f350e7ee1c2c38e5ac0b6c22c17388f6c78f0b5.tar.bz2 jove-kernel-7f350e7ee1c2c38e5ac0b6c22c17388f6c78f0b5.zip |
refactor paging code. regression on loading init program
-rw-r--r-- | arch/x86_64/boot/limine/memorymap.c | 2 | ||||
-rw-r--r-- | arch/x86_64/elf.c | 27 | ||||
-rw-r--r-- | arch/x86_64/init.c | 63 | ||||
-rw-r--r-- | arch/x86_64/lib/object.c | 59 | ||||
-rw-r--r-- | arch/x86_64/memory/koentry-ptr.c | 16 | ||||
-rw-r--r-- | arch/x86_64/memory/message.c | 40 | ||||
-rw-r--r-- | arch/x86_64/memory/page-mapping.c | 34 | ||||
-rw-r--r-- | arch/x86_64/memory/pml4.c (renamed from arch/x86_64/memory/page_directory.c) | 86 | ||||
-rw-r--r-- | arch/x86_64/memory/untyped_retype_page.c | 38 | ||||
-rw-r--r-- | arch/x86_64/syscall/invoke-mapping.c | 8 | ||||
-rw-r--r-- | arch/x86_64/syscall/wrappers.h | 2 | ||||
-rw-r--r-- | arch/x86_64/usermode.c | 137 | ||||
-rw-r--r-- | include/arch/x86_64/page-mapping.h | 12 | ||||
-rw-r--r-- | include/arch/x86_64/page.h | 13 | ||||
-rw-r--r-- | include/elf.h | 110 | ||||
-rw-r--r-- | include/init.h | 19 | ||||
-rw-r--r-- | include/jove.h | 3 | ||||
-rw-r--r-- | include/memory.h | 8 | ||||
-rw-r--r-- | include/object.h | 19 | ||||
-rw-r--r-- | lib/untyped-retype.c | 38 | ||||
-rw-r--r-- | lib/untyped.c | 16 | ||||
-rw-r--r-- | main.c | 3 | ||||
-rw-r--r-- | syscall/invoke-untyped.c | 5 |
23 files changed, 450 insertions, 308 deletions
diff --git a/arch/x86_64/boot/limine/memorymap.c b/arch/x86_64/boot/limine/memorymap.c index ec0f545..43aecf7 100644 --- a/arch/x86_64/boot/limine/memorymap.c +++ b/arch/x86_64/boot/limine/memorymap.c @@ -31,7 +31,7 @@ boot_populate_untyped(void) if(entry->type != LIMINE_MEMMAP_USABLE) continue; size_t table_index = s_untyped_dir.self.data++; - uintmax_t *untyped_data = vmem_phys_tovirt(entry->base); + uintmax_t *untyped_data = pptr_tovirt_ident(entry->base); objdir_entry_t *table_entry = &s_untyped_dir.entries[table_index]; table_entry->type = KO_MEMORY_UNTYPED; diff --git a/arch/x86_64/elf.c b/arch/x86_64/elf.c new file mode 100644 index 0000000..696b7a7 --- /dev/null +++ b/arch/x86_64/elf.c @@ -0,0 +1,27 @@ +#include "elf.h" +#include <stddef.h> + +int +elf64_ehdr_valid(Elf64_Ehdr *ehdr) +{ + if(ehdr->e_ident[EI_MAG0] != ELFMAG0 || + ehdr->e_ident[EI_MAG1] != ELFMAG1 || + ehdr->e_ident[EI_MAG2] != ELFMAG2 || + ehdr->e_ident[EI_MAG3] != ELFMAG3) + return 0; + if(ehdr->e_ident[EI_CLASS] != ELFCLASS64) return 0; + if(ehdr->e_ident[EI_DATA] != ELFDATA2LSB) return 0; + if(ehdr->e_type != ET_EXEC) return 0; + if(ehdr->e_machine != EM_X86_64) return 0; + + return 1; +} + +void* +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 new file mode 100644 index 0000000..4ec7718 --- /dev/null +++ b/arch/x86_64/init.c @@ -0,0 +1,63 @@ +#include "init.h" +#include "arch/x86_64/page.h" +#include "device/processor.h" + +uintptr_t +init_alloc_pageframe() +{ + objdir_entry_t *untyped_dir_entry = &_initDirectory.entries[INIT_OBJECT_UNTYPED_DIR]; + objdir_t *untyped_dir = ko_entry_data(untyped_dir_entry); + + /*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 pageframe; + ko_untyped_split(lastmemb, &pageframe, 0x1000); + return pageframe.data; +} + +void +init_map_pageframe(uintptr_t pptr, uintptr_t vptr, uint8_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; + for(uint8_t d = 0; d < 3; d++) { + uint16_t pmli = path[d]; + pmle_t *pmle = &pmld[pmli]; + if(!pmle->p) { + pmle->value = init_alloc_pageframe() | PAGE_PRESENT | PAGE_RW | PAGE_US; + } + pmld = pptr_tovirt_ident(pmle->paddr << 12); + } + pmld[path[3]].value = pptr | pflags; + __asm__ volatile("invlpg (%0)":: "r"(vptr): "memory"); +} + +void +init_ensure_page(uintptr_t vptr, uint8_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; + 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); + } + pmld = pptr_tovirt_ident(pmle->paddr << 12); + } +} diff --git a/arch/x86_64/lib/object.c b/arch/x86_64/lib/object.c new file mode 100644 index 0000000..4ab8f06 --- /dev/null +++ b/arch/x86_64/lib/object.c @@ -0,0 +1,59 @@ +#include "object.h" +#include "error.h" +#include "device/processor.h" +#include "arch/x86_64/page.h" +#include "arch/x86_64/page-mapping.h" + +void* +ko_entry_data(objdir_entry_t *entry) +{ + if((intmax_t)entry->data < 0) return (void*)entry->data; + return pptr_tovirt_ident(entry->data); +} + +uintptr_t +ko_data_toentry(uintptr_t vptr) +{ + return vptr_tophys((void*)vptr); +} + +int +ko_message_unmap(objdir_entry_t *message, uintptr_t *saveptr) +{ + /* message data should point to the virtual address. */ + /* If it doesn't, fail*/ + if(!(message->extra & KODE_EX_MESSAGE_MAPPED)) return KE_BADCALL; + uintptr_t vptr = message->data; + + processor_t *cproc = processor_current(); + pmle_t *pml4 = pptr_tovirt_ident(cproc->pdir); + + pmle_t *message_pmle = pml4_get_mapping(pml4, 4, vptr); + *saveptr = (uintptr_t)pptr_tovirt_ident(message_pmle->paddr << 12); + + message_pmle->p = 0; + __asm__ volatile("invlpg (%0)":: "r"(vptr): "memory"); + + message->extra &= ~KODE_EX_MESSAGE_MAPPED; + return 0; +} + +int +ko_message_remap(objdir_entry_t *message) +{ + if(message->extra & KODE_EX_MESSAGE_MAPPED) return KE_BADCALL; + uintptr_t vptr = message->data; + + processor_t *cproc = processor_current(); + pmle_t *pml4 = pptr_tovirt_ident(cproc->pdir); + + pmle_t *message_pmle = pml4_get_mapping(pml4, 4, vptr); + + message_pmle->p = 1; + __asm__ volatile("invlpg (%0)":: "r"(vptr): "memory"); + + message->extra |= KODE_EX_MESSAGE_MAPPED; + return 0; +} + +void ko_message_move(objdir_entry_t *message, uintptr_t vptr); diff --git a/arch/x86_64/memory/koentry-ptr.c b/arch/x86_64/memory/koentry-ptr.c deleted file mode 100644 index b32d4e7..0000000 --- a/arch/x86_64/memory/koentry-ptr.c +++ /dev/null @@ -1,16 +0,0 @@ -#include "memory.h" -#include "arch/x86_64/page.h" -#include <stdint.h> - -void* -ko_entry_data(objdir_entry_t *entry) -{ - if((intmax_t)entry->data < 0) return (void*)entry->data; - return vmem_phys_tovirt(entry->data); -} - -uintptr_t -ko_data_toentry(uintptr_t vptr) -{ - return vmem_ident_tophys((void*)vptr); -} diff --git a/arch/x86_64/memory/message.c b/arch/x86_64/memory/message.c index 1fbdfc8..d5bedb7 100644 --- a/arch/x86_64/memory/message.c +++ b/arch/x86_64/memory/message.c @@ -6,43 +6,3 @@ #include "arch/x86_64/page-mapping.h" #include "print.h" -int -ko_message_unmap(objdir_entry_t *message, uintptr_t *saveptr) -{ - /* message data should point to the virtual address. */ - /* If it doesn't, fail*/ - if(!(message->extra & KODE_EX_MESSAGE_MAPPED)) return KE_BADCALL; - uintptr_t vptr = message->data; - - processor_t *cproc = processor_current(); - pmle_t *pml4 = vmem_phys_tovirt(cproc->pdir); - - pmle_t *message_pmle = mem_mapping_vptr_mapping(pml4, 4, vptr); - *saveptr = (uintptr_t)vmem_phys_tovirt(message_pmle->paddr << 12); - - message_pmle->p = 0; - __asm__ volatile("invlpg (%0)":: "r"(vptr): "memory"); - - message->extra &= ~KODE_EX_MESSAGE_MAPPED; - return 0; -} - -int -ko_message_remap(objdir_entry_t *message) -{ - if(message->extra & KODE_EX_MESSAGE_MAPPED) return KE_BADCALL; - uintptr_t vptr = message->data; - - processor_t *cproc = processor_current(); - pmle_t *pml4 = vmem_phys_tovirt(cproc->pdir); - - pmle_t *message_pmle = mem_mapping_vptr_mapping(pml4, 4, vptr); - - message_pmle->p = 1; - __asm__ volatile("invlpg (%0)":: "r"(vptr): "memory"); - - message->extra |= KODE_EX_MESSAGE_MAPPED; - return 0; -} - -void ko_message_move(objdir_entry_t *message, uintptr_t vptr); diff --git a/arch/x86_64/memory/page-mapping.c b/arch/x86_64/memory/page-mapping.c index d4b4e98..bbf210a 100644 --- a/arch/x86_64/memory/page-mapping.c +++ b/arch/x86_64/memory/page-mapping.c @@ -1,28 +1,28 @@ #include "arch/x86_64/page-mapping.h" #include "arch/x86_64/page.h" +#include "memory.h" +#include "error.h" #include <stddef.h> #include "print.h" -pmle_t* -page_mapping_traverse(pmle_t *pml4, uint8_t depth, uint16_t *path) +void +mapping_setup_init() { - uint16_t pathi = path[0]; - - pmle_t *pmle = &pml4[pathi]; - pmle_t *pmle_table = vmem_phys_tovirt(pmle->paddr << 12); - if(depth == 0) return pmle; - if(!pmle->p) return NULL; - return page_mapping_traverse(pmle_table, depth - 1, path + 1); + pml4_setup_init(); } -pmle_t* -mem_mapping_vptr_mapping(pmle_t *pml4, uint8_t depth, uintptr_t vptr) +void +mapping_setup(objdir_entry_t *mapping) { - uint64_t pathval = 0; - uint16_t *path = (uint16_t*)&pathval; + pmle_t *pml4 = (pmle_t*)ko_entry_data(mapping); + pml4_setup(pml4); +} - for(uint8_t i = 0; i < depth; i++) { - path[i] = PML_I_FOR_LAYER(vptr, 4 - i); - } - return page_mapping_traverse(pml4, depth - 1, path); +int +mapping_try_map_obj(objdir_entry_t *mapping, uintptr_t vptr, objdir_entry_t *obj) +{ + if(vptr & 0xFFFF800000000000) return KE_OOB; + pmle_t *pml4 = (pmle_t*)ko_entry_data(mapping); + uintptr_t pptr = (uintptr_t)ko_entry_data(obj); + return pml4_try_map(pml4, pptr, vptr); } diff --git a/arch/x86_64/memory/page_directory.c b/arch/x86_64/memory/pml4.c index 11e4861..fcfc897 100644 --- a/arch/x86_64/memory/page_directory.c +++ b/arch/x86_64/memory/pml4.c @@ -5,37 +5,78 @@ #include "object.h" #include "string.h" #include "jove.h" +#include "error.h" #include <stdint.h> +#define IDENTITY_BASE 0xFFFF800000000000 +uintptr_t vptr_tophys(void *vptr) +{ + return ((uintptr_t)vptr) - IDENTITY_BASE; +} + physptr_t -vmem_tophys_koff(virtptr_t v) +vptr_tophys_koff(virtptr_t v) { return v - (physptr_t)&_kernel_start + _boot_kernel_phys_base; } -#define IDENTITY_BASE 0xFFFF800000000000 void* -vmem_phys_tovirt(physptr_t p) +pptr_tovirt_ident(physptr_t p) { return (void*)(p + IDENTITY_BASE); } -uintptr_t vmem_ident_tophys(void *vptr) -{ - return ((uintptr_t)vptr) - IDENTITY_BASE; -} - void* pmle_get_page(pmle_t entry) { uintptr_t pptr = entry.paddr << 12; - return vmem_phys_tovirt(pptr); + return pptr_tovirt_ident(pptr); +} + +void +pml4_get_path(uintptr_t vptr, uint8_t depth, uint16_t *path) +{ + for(uint8_t i = 0; i < depth; i++) { + path[i] = PML_I_FOR_LAYER(vptr, 4 - i); + } } -uint8_t -pmle_level(pmle_t entry) +pmle_t* +pml4_traverse(pmle_t *pml4, uint8_t depth, uint16_t *path) { - return entry.osflg; + uint16_t pathi = path[0]; + + pmle_t *pmle = &pml4[pathi]; + pmle_t *pmle_table = pptr_tovirt_ident(pmle->paddr << 12); + if(depth == 0) return pmle; + if(!pmle->p) return NULL; + return pml4_traverse(pmle_table, depth - 1, path + 1); +} + +pmle_t* +pml4_get_mapping(pmle_t *pml4, uint8_t depth, uintptr_t vptr) +{ + uint64_t pathval = 0; + uint16_t *path = (uint16_t*)&pathval; + + pml4_get_path(vptr, depth, path); + return pml4_traverse(pml4, depth - 1, path); +} + +int +pml4_try_map(pmle_t *pml4, uintptr_t pptr, uintptr_t vptr) +{ + uint64_t pathval = 0; + uint16_t *path = (uint16_t*)&pathval; + + pml4_get_path(vptr, 4, path); + pmle_t *mapping = pml4_traverse(pml4, 3, path); + + if(mapping == NULL) return KE_DNE; + if(mapping->p) return KE_FULL; + + mapping->value = pptr | PAGE_PRESENT | PAGE_RW | PAGE_US; + return KE_OK; } __attribute__((aligned(0x1000))) pmle_t s_kernel_pml4[512]; // Page L4 @@ -47,7 +88,7 @@ __attribute__((aligned(0x1000))) pmle_t s_idmap_pml3[512]; __attribute__((aligned(0x1000))) pmle_t s_idmap_pml2[512]; void -vmem_setup(void) +pml4_setup_init(void) { memset(s_kernel_pml4, 0, 0x1000); memset(s_kernel_pml3, 0, 0x1000); @@ -63,13 +104,13 @@ vmem_setup(void) size_t kernel_size = kernel_end - kernel_start; size_t kernel_size_pages = (kernel_size / 0x1000) + 1; - physptr_t kernel_pml4_base = vmem_tophys_koff((virtptr_t)&s_kernel_pml4); - physptr_t kernel_pml3_base = vmem_tophys_koff((virtptr_t)&s_kernel_pml3); - physptr_t kernel_pml2_base = vmem_tophys_koff((virtptr_t)&s_kernel_pml2); - physptr_t kernel_pml1_base = vmem_tophys_koff((virtptr_t)&s_kernel_pml1); + physptr_t kernel_pml4_base = vptr_tophys_koff((virtptr_t)&s_kernel_pml4); + physptr_t kernel_pml3_base = vptr_tophys_koff((virtptr_t)&s_kernel_pml3); + physptr_t kernel_pml2_base = vptr_tophys_koff((virtptr_t)&s_kernel_pml2); + physptr_t kernel_pml1_base = vptr_tophys_koff((virtptr_t)&s_kernel_pml1); - physptr_t idmap_pml3_base = vmem_tophys_koff((virtptr_t)&s_idmap_pml3); - physptr_t idmap_pml2_base = vmem_tophys_koff((virtptr_t)&s_idmap_pml2); + physptr_t idmap_pml3_base = vptr_tophys_koff((virtptr_t)&s_idmap_pml3); + physptr_t idmap_pml2_base = vptr_tophys_koff((virtptr_t)&s_idmap_pml2); processor_t *processor = processor_current(); processor->pdir = kernel_pml4_base; @@ -103,3 +144,10 @@ vmem_setup(void) .data = kernel_pml4_base }; } + +void +pml4_setup(pmle_t *pml4) +{ + memset(pml4, 0, 0x800); + memcpy(&pml4[256], &s_kernel_pml4[256], 0x800); +} diff --git a/arch/x86_64/memory/untyped_retype_page.c b/arch/x86_64/memory/untyped_retype_page.c deleted file mode 100644 index 32afe2c..0000000 --- a/arch/x86_64/memory/untyped_retype_page.c +++ /dev/null @@ -1,38 +0,0 @@ -#include "memory.h" -#include "arch/x86_64/page.h" -#include "print.h" -#include <stddef.h> - -static int -s_untyped_retype( - objdir_entry_t *untyped_entry, - size_t size, - size_t align, - void **dest) -{ - if(untyped_entry->type != KO_MEMORY_UNTYPED) return -1; - if((untyped_entry->data & (align - 1)) != 0) return -2; //EALIGN - - uintptr_t *untyped_data = vmem_phys_tovirt(untyped_entry->data); - uintmax_t untyped_size = *untyped_data; - - if(untyped_size <= size) { - return -3; - } - - *untyped_data -= size; - *dest = (void*)(untyped_entry->data + untyped_size - size); - - return 0; -} - -int untyped_retype_page(objdir_entry_t *untyped_entry, void **dest) -{ - int r = s_untyped_retype(untyped_entry, 0x1000, 0x1000, dest); - if(r != 0) return r; - - #ifdef DBG_MEM - klogf("Untyped block %p retyped to page at %p\n", untyped_entry->data, *dest); - #endif - return r; -} diff --git a/arch/x86_64/syscall/invoke-mapping.c b/arch/x86_64/syscall/invoke-mapping.c index be401d6..5fde8be 100644 --- a/arch/x86_64/syscall/invoke-mapping.c +++ b/arch/x86_64/syscall/invoke-mapping.c @@ -16,7 +16,7 @@ s_handle_invoke_mapping_exists( size_t payload_at ) { - pmle_t *pml4 = (pmle_t*)vmem_phys_tovirt(target_entry->data); + pmle_t *pml4 = (pmle_t*)pptr_tovirt_ident(target_entry->data); pmle_t *target_pml; uint8_t target_depth; SYSCALL_PAYLOAD_TAKEPML(payload, payload_at, pml4, target_depth, target_pml); @@ -36,7 +36,7 @@ s_handle_invoke_mapping_map( size_t payload_at ) { - pmle_t *pml4 = (pmle_t*)vmem_phys_tovirt(target_entry->data); + pmle_t *pml4 = (pmle_t*)pptr_tovirt_ident(target_entry->data); pmle_t *target_pml; uint8_t target_depth; SYSCALL_PAYLOAD_TAKEPML(payload, payload_at, pml4, target_depth, target_pml); @@ -85,7 +85,7 @@ s_handle_invoke_mapping_unmap( size_t payload_at ) { - pmle_t *pml4 = (pmle_t*)vmem_phys_tovirt(target_entry->data); + pmle_t *pml4 = (pmle_t*)pptr_tovirt_ident(target_entry->data); pmle_t *target_pml; uint8_t target_depth; SYSCALL_PAYLOAD_TAKEPML(payload, payload_at, pml4, target_depth, target_pml); @@ -105,7 +105,7 @@ s_handle_invoke_mapping_unmap( if(dest_entry->type != KO_NONE) return KE_FULL; uintptr_t pmle_addr = target_pml->paddr << 12; - size_t *untyped = vmem_phys_tovirt(pmle_addr); + size_t *untyped = pptr_tovirt_ident(pmle_addr); __asm__ volatile("invlpg (%0)":: "r"(untyped): "memory"); *untyped = 0x1000; diff --git a/arch/x86_64/syscall/wrappers.h b/arch/x86_64/syscall/wrappers.h index a6fdf88..0803262 100644 --- a/arch/x86_64/syscall/wrappers.h +++ b/arch/x86_64/syscall/wrappers.h @@ -8,7 +8,7 @@ SYSCALL_PAYLOAD_TAKEL(payload, at, depth, uint8_t); \ if(((depth + 1) * sizeof(uint16_t)) + at >= KO_MESSAGE_BYTES) return KE_BADMSG; \ if(depth == 0 && *(uint16_t*)&payload[at] > 255) return KE_OOB; \ - pml = page_mapping_traverse(pml4, depth, (uint16_t*)&payload[at]); \ + pml = pml4_traverse(pml4, depth, (uint16_t*)&payload[at]); \ at += (depth + 1) * sizeof(uint16_t) #endif diff --git a/arch/x86_64/usermode.c b/arch/x86_64/usermode.c index aa626a9..8975993 100644 --- a/arch/x86_64/usermode.c +++ b/arch/x86_64/usermode.c @@ -1,76 +1,4 @@ -#include "arch/x86_64/object.h" -#include "object.h" -#include "bootargs.h" -#include "device/initrd.h" -#include "object.h" -#include "panic.h" -#include "string.h" -#include "device/processor.h" -#include "arch/x86_64/page.h" -#include "print.h" -static tcb_t s_init_tcb; - -//Dynamic allocation hell!!! -static uintptr_t -s_new_mapping(objdir_t *untyped_dir) -{ - objdir_entry_t *untyped_entry = NULL; - for(int i = untyped_dir->self.data - 1; i != 0; i--) { - untyped_entry = &untyped_dir->entries[i]; - if(untyped_entry->type != KO_MEMORY_UNTYPED) continue; - uintptr_t mapping = 0; - int err = untyped_retype_page(untyped_entry, (void**)&mapping); - if(err != 0) continue; - return mapping; - } - kpanic("Could not allocate page for init\n"); -} - -static pmle_t* -s_ensure_mapping_layer(pmle_t *pml, objdir_t *untyped_dir, uintptr_t addr, uint8_t layer) -{ - pmli_t pmli = PML_I_FOR_LAYER(addr, layer); - if(pml[pmli].p) - return pmle_get_page(pml[pmli]); - - uintptr_t table_phys = s_new_mapping(untyped_dir); - pmle_t *table = vmem_phys_tovirt(table_phys); - memset(table, 0, 0x1000); - - pml[pmli] = (pmle_t) { - .p = 1, - .rw = 1, - .us = 1, - .osflg = (layer - 1) & 3, - .paddr = table_phys >> 12 - }; - __asm__ volatile("invlpg (%0)":: "r"(table_phys)); - return vmem_phys_tovirt(table_phys); -} - -static uintptr_t -s_map_page(pmle_t *pml4, objdir_t *untyped_dir, uintptr_t addr) -{ - pmle_t *pml3 = s_ensure_mapping_layer(pml4, untyped_dir, addr, 4); - pmle_t *pml2 = s_ensure_mapping_layer(pml3, untyped_dir, addr, 3); - pmle_t *pml1 = s_ensure_mapping_layer(pml2, untyped_dir, addr, 2); - - pmli_t pml1i = PML_I_FOR_LAYER(addr, 1); - pmle_t *pmle = &pml1[pml1i]; - - uintptr_t pptr = s_new_mapping(untyped_dir); - - *pmle = (pmle_t) { - .p = 1, - .rw = 1, - .us = 1, - .osflg = 0, - .paddr = pptr >> 12 - }; - __asm__ volatile("invlpg (%0)":: "r"(addr)); - return pptr; -} __attribute__((noreturn)) static void @@ -85,68 +13,3 @@ s_enter_usermode(void *ip, void *sp) "r"(sp), "r"(ip): "memory"); for(;;); } - -void -init_load(void) -{ - const char *init_filename = bootargs_getarg("init"); - if(init_filename == NULL) { - kpanic("Missing boot argument \"init\""); - } - tar_header_t *init_header = initrd_find_file(init_filename); - if(init_header == NULL) { - kpanic("Init file not found in initrd. (expected \"%s\")", init_filename); - } - - _initDirectory.entries[INIT_OBJECT_TCB] = (objdir_entry_t) { - .type = KO_TCB, - .data = vmem_tophys_koff((uintptr_t)&s_init_tcb) - }; - - objdir_t *untyped_dir = (objdir_t*)_initDirectory.entries[INIT_OBJECT_UNTYPED_DIR].data; - pmle_t *pml4 = vmem_phys_tovirt(_initDirectory.entries[INIT_OBJECT_PAGEMAP].data & ~3ULL); - - //Reserve and map pages for init binary - size_t init_size = initrd_file_size(init_header); - - size_t init_pages = (init_size >> 12); - uintptr_t init_base = 0x1000; - - for(size_t i = 0; i < init_pages + 1; i++) { - s_map_page(pml4, untyped_dir, init_base + (i * 0x1000)); - } - //Copy over init data - memcpy((void*)init_base, (&((tar_block_t*)init_header)[1])->data, init_size); - - //Create a user stack - uintptr_t stack_base = 0x00007FFFFFFFF000; - s_map_page(pml4, untyped_dir, stack_base); - uintptr_t sp = stack_base + 0xFF0; - - //Create a kernel stack for the init TCB - uintptr_t ksp_base = (uintptr_t)&s_init_tcb.kstack; - s_init_tcb.ksp = ksp_base + 0xFF0; - - processor_t *proc = (processor_t*)processor_current(); - proc->tss.rsp0 = s_init_tcb.ksp; - klogf("RSP0 %p\n", s_init_tcb.ksp); - - //Create a message object for init - uintptr_t message_base = init_base + (init_pages << 12); - message_base += ((~(message_base & 0xFFF)) & 0xFFF) + 1; - - uintptr_t message_phys = s_map_page(pml4, untyped_dir, message_base); - _initDirectory.entries[INIT_OBJECT_MESSAGE] = (objdir_entry_t) { - .type = KO_MESSAGE, - .extra = KODE_EX_MESSAGE_MAPPED, - .data = message_base - }; - - //Write message address to user stack. - sp -= sizeof(uintptr_t); - *((uintptr_t*)sp) = message_base; - - //Setup usermode and jump - proc->tcb = &s_init_tcb; - s_enter_usermode((void*)init_base, (void*)sp); -} diff --git a/include/arch/x86_64/page-mapping.h b/include/arch/x86_64/page-mapping.h index fd620ea..8389132 100644 --- a/include/arch/x86_64/page-mapping.h +++ b/include/arch/x86_64/page-mapping.h @@ -3,13 +3,19 @@ #include "arch/x86_64/page.h" -pmle_t *page_mapping_traverse(pmle_t *pml4, uint8_t depth, uint16_t *path); +pmle_t *pml4_traverse(pmle_t *pml4, uint8_t depth, uint16_t *path); /**@FUNC Get the pmle associated with this virtual address down to a given depth. * At depth=0, gets &pml4[pml4i] * At depth=1, gets &pml4[pml4i][pml3i] * At depth=2, gets &pml4[pml4i][pml3i][pml2i] - * etc...*/ -pmle_t *mem_mapping_vptr_mapping(pmle_t *pml4, uint8_t depth, uintptr_t vptr); + * etc... + * @PARAM pml4 table to get mapping from. + * @PARAM depth how deep to traverse for the mapping. + * @PARAM vptr address to get mapping for. + * @RETURN pointer to pmle (if exists)*/ +pmle_t *pml4_get_mapping(pmle_t *pml4, uint8_t depth, uintptr_t vptr); + +int pml4_try_map(pmle_t *pml4, uintptr_t pptr, uintptr_t vptr); #endif diff --git a/include/arch/x86_64/page.h b/include/arch/x86_64/page.h index 7c6186a..910b898 100644 --- a/include/arch/x86_64/page.h +++ b/include/arch/x86_64/page.h @@ -36,13 +36,16 @@ typedef uint16_t pmli_t; #define PML_SHL(l) (((l) * 9) + 3) #define PML_I_FOR_LAYER(v, l) (((v) >> PML_SHL(l)) % 512) -uintptr_t vmem_ident_tophys(void *vptr); -void *vmem_phys_tovirt(uintptr_t pptr); -uintptr_t vmem_tophys_koff(uintptr_t v); +uintptr_t vptr_tophys(void *vptr); +uintptr_t vptr_tophys_koff(uintptr_t v); + +void *pptr_tovirt_ident(uintptr_t pptr); void *pmle_get_page(pmle_t entry); -uint8_t pmle_level(pmle_t entry); -int untyped_retype_page(objdir_entry_t *untyped_entry, void **dest_ptr); +void pml4_setup_init(void); +void pml4_setup(pmle_t *pml4); + +void pml4_get_path(uintptr_t vptr, uint8_t depth, uint16_t *path); #endif diff --git a/include/elf.h b/include/elf.h new file mode 100644 index 0000000..05e3e83 --- /dev/null +++ b/include/elf.h @@ -0,0 +1,110 @@ +#ifndef _JOVE_ELF_H +#define _JOVE_ELF_H 1 + +#include <stdint.h> + +/*A subset of the SystemV ELF ABI that only loads statically linked binaries.*/ + +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Word; +typedef uint32_t Elf32_Addr; +typedef uint32_t Elf32_Off; + +typedef Elf32_Half Elf64_Half; +typedef Elf32_Word Elf64_Word; +typedef uint64_t Elf64_Xword; +typedef uintptr_t Elf64_Addr; +typedef uint64_t Elf64_Off; + +enum { + EI_MAG0 = 0, + EI_MAG1, + EI_MAG2, + EI_MAG3, + EI_CLASS, + EI_DATA, + EI_VERSION, + EI_OSABI, + EI_ABIVERSION, + EI_PAD +}; +#define EI_NIDENT 16 + +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' + +#define ELFCLASSNONE 0 +#define ELFCLASS64 2 + +#define ELFDATANONE 0 +#define ELFDATA2LSB 1 + +#define ET_NONE 0 +#define ET_EXEC 2 + +#define EM_X86_64 62 + +#define EV_NONE 0 +#define EV_CURRENT 1 + +typedef struct { + unsigned char e_ident[EI_NIDENT]; + Elf64_Half e_type; + Elf64_Half e_machine; + Elf64_Word e_version; + Elf64_Addr e_entry; + Elf64_Off e_phoff; + Elf64_Off e_shoff; + Elf64_Word e_flags; + Elf64_Half e_ehsize; + Elf64_Half e_phentsize; + Elf64_Half e_phnum; + Elf64_Half e_shentsize; + Elf64_Half e_shnum; + Elf64_Half e_shstrndx; +} Elf64_Ehdr; + +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_NOBITS 8 + +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 + +typedef struct { + Elf64_Word sh_name; + Elf64_Word sh_type; + Elf64_Xword sh_flags; + Elf64_Addr sh_addr; + Elf64_Off sh_offset; + Elf64_Xword sh_size; + Elf64_Word sh_link; + Elf64_Word sh_info; + Elf64_Xword sh_addralign; + Elf64_Xword sh_entsize; +} Elf64_Shdr; + +#define PT_NULL 0 +#define PT_LOAD 1 + +#define PF_X 1 +#define PF_W 2 +#define PF_R 4 + +typedef struct +{ + Elf64_Word p_type; + Elf64_Word p_flags; + Elf64_Off p_offset; + Elf64_Addr p_vaddr; + Elf64_Addr p_paddr; + Elf64_Xword p_filesz; + Elf64_Xword p_memsz; + Elf64_Xword p_align; +} Elf64_Phdr; + +int elf64_ehdr_valid(Elf64_Ehdr *ehdr); + +#endif diff --git a/include/init.h b/include/init.h index aa722b1..2174785 100644 --- a/include/init.h +++ b/include/init.h @@ -1,9 +1,24 @@ #ifndef _JOVE_INIT_H #define _JOVE_INIT_H 1 -#ifdef __x86_64__ +#include <stdint.h> -#endif +enum { + INIT_OBJECT_ROOTDIR = 0, + INIT_OBJECT_PAGEMAP, + INIT_OBJECT_PROCESSOR_DIR, + INIT_OBJECT_UNTYPED_DIR, + INIT_OBJECT_INITRD_DIR, + INIT_OBJECT_TCB, + INIT_OBJECT_MESSAGE, + INIT_OBJECT_LOG +}; + +#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); diff --git a/include/jove.h b/include/jove.h index 63d2ce9..fc4c91f 100644 --- a/include/jove.h +++ b/include/jove.h @@ -6,9 +6,6 @@ extern void (*_kernel_start)(void); extern void (*_kernel_end)(void); -#include "object.h" -extern objdir_t _initDirectory; - NORETURN void hcf(void); #endif diff --git a/include/memory.h b/include/memory.h index 2f75b60..901060c 100644 --- a/include/memory.h +++ b/include/memory.h @@ -9,11 +9,9 @@ typedef uintptr_t virtptr_t; #define KERNEL_STACK_SIZE 0x1000 -void vmem_setup(void); +void mapping_setup_init(void); +void mapping_setup(objdir_entry_t *mapping); -int untyped_retype_kernel_stack(objdir_entry_t *untyped_entry, objdir_entry_t *dest_entry); - -void *ko_entry_data(objdir_entry_t *entry); -uintptr_t ko_data_toentry(uintptr_t vptr); +int mapping_try_map_obj(objdir_entry_t *mapping, uintptr_t vptr, objdir_entry_t *obj); #endif diff --git a/include/object.h b/include/object.h index c8621ee..4cf5159 100644 --- a/include/object.h +++ b/include/object.h @@ -2,17 +2,7 @@ #define _JOVE_OBJECT_H #include <stdint.h> - -enum { - INIT_OBJECT_ROOTDIR = 0, - INIT_OBJECT_PAGEMAP, - INIT_OBJECT_PROCESSOR_DIR, - INIT_OBJECT_UNTYPED_DIR, - INIT_OBJECT_INITRD_DIR, - INIT_OBJECT_TCB, - INIT_OBJECT_MESSAGE, - INIT_OBJECT_LOG -}; +#include <stddef.h> enum { @@ -64,13 +54,18 @@ typedef struct jove_ObjectDirectory objdir_entry_t *objdir_seek(objdir_t *dir, uint8_t *path, unsigned long pathw); unsigned long objdir_pathw(objdir_t *dir, uint8_t *path); +void *ko_entry_data(objdir_entry_t *entry); +uintptr_t ko_data_toentry(uintptr_t vptr); + int ko_message_unmap(objdir_entry_t *message, uintptr_t *saveptr); int ko_message_remap(objdir_entry_t *message); void ko_message_move(objdir_entry_t *message, uintptr_t vptr); +int ko_untyped_split(objdir_entry_t *untyped, objdir_entry_t *dest, size_t bytes); + int ko_untyped_retype_objdir(objdir_entry_t *target); int ko_untyped_retype_memory_mapping(objdir_entry_t *target); int ko_untyped_retype_tcb(objdir_entry_t *target); -int ko_untyped_retype_message(objdir_entry_t *target); +int ko_untyped_retype_message(objdir_entry_t *target, uintptr_t vptr); #endif diff --git a/lib/untyped-retype.c b/lib/untyped-retype.c index 70fb4d2..526f19e 100644 --- a/lib/untyped-retype.c +++ b/lib/untyped-retype.c @@ -1,11 +1,43 @@ -#include <object.h> -#include <memory.h> +#include "object.h" +#include "memory.h" #include <stddef.h> -#include <error.h> +#include "error.h" +#include "string.h" int ko_untyped_retype_objdir(objdir_entry_t *target) { size_t *untyped = ko_entry_data(target); if(*untyped != 0x1000) return -KE_BADSIZE; + + objdir_t *objdir = (objdir_t*)untyped; + memset(objdir, 0, 0x1000); + + objdir->self = (objdir_entry_t) { + .type = KO_OBJECT_DIRECTORY, + .data = target->data + }; + *target = (objdir_entry_t) { + .type = KO_OBJECT_DIRECTORY, + .lock = 0, + .extra = 0, + .data = objdir->self.data + }; + return 0; +} + +int +ko_untyped_retype_message(objdir_entry_t *target, uintptr_t vptr) +{ + size_t *untyped = ko_entry_data(target); + if(*untyped != 0x1000) return -KE_BADSIZE; + + memset(untyped, 0, KO_MESSAGE_BYTES); + *target = (objdir_entry_t) { + .type = KO_OBJECT_DIRECTORY, + .lock = 0, + .extra = 0, + .data = target->data + }; + return 0; } diff --git a/lib/untyped.c b/lib/untyped.c new file mode 100644 index 0000000..8a20f63 --- /dev/null +++ b/lib/untyped.c @@ -0,0 +1,16 @@ +#include "include/object.h" +#include "error.h" + +int +ko_untyped_split(objdir_entry_t *target, objdir_entry_t *dest, size_t bytes) +{ + size_t *untyped = ko_entry_data(target); + if(*untyped <= bytes) return KE_TOOSMALL; + + *untyped -= bytes; + dest->data = target->data + *untyped; + *(size_t*)ko_entry_data(dest) = bytes; + dest->type = KO_MEMORY_UNTYPED; + + return 0; +} @@ -27,12 +27,11 @@ _jove_main(void) bsp_setup(); boot_populate_untyped(); - vmem_setup(); + mapping_setup_init(); #ifdef ENABLE_INITRD initrd_setup(); #endif - init_load(); kprintf("Reached end of kernel main!\n"); hcf(); } diff --git a/syscall/invoke-untyped.c b/syscall/invoke-untyped.c index a89306e..483d36f 100644 --- a/syscall/invoke-untyped.c +++ b/syscall/invoke-untyped.c @@ -95,6 +95,11 @@ s_handle_invoke_untyped_retype( switch(retype) { case KO_OBJECT_DIRECTORY: return ko_untyped_retype_objdir(target); + case KO_MESSAGE: { + uintptr_t vptr; + SYSCALL_PAYLOAD_TAKEL(payload, payload_at, vptr, uintptr_t); + return ko_untyped_retype_message(target, vptr); + } default: return KE_BADTYPE; } } |