#include "syscall/handles.h" #include "arch/x86_64/syscall.h" #include "arch/x86_64/page.h" #include #include "error.h" #include "lock.h" static int s_handle_invoke_mapping_release( objdir_t *root_dir, objdir_entry_t *target_entry, uint8_t *payload, size_t payload_at ) { target_entry->data = 0; target_entry->type = KO_NONE; return 0; } static int s_handle_invoke_mapping_get( objdir_t *root_dir, objdir_entry_t *target_entry, uint8_t *payload, size_t payload_at ) { pmli_t pmli; SYSCALL_PAYLOAD_TAKEL(payload, payload_at, pmli, pmli_t); if(pmli > 511) return -KE_OOB; uint8_t level = target_entry->data & 3; pmle_t *target_pml = (pmle_t*)vmem_phys_tovirt(target_entry->data & ~3ULL); if(level == 3 && pmli > 255) return -KE_OOB; if(level == 0) return -KE_BADOBJ; size_t dest_pathw; objdir_entry_t *dest_entry; SYSCALL_PAYLOAD_TAKEOBJ(payload, payload_at, dest_pathw, dest_entry); if(dest_entry->type != KO_NONE) return -KE_FULL; pmle_t pmle = target_pml[pmli]; if(!pmle.p) return -KE_DNE; *dest_entry = (objdir_entry_t) { .type = KO_MEMORY_MAPPING, .data = (((uintptr_t)target_pml[pmli].paddr) << 12ULL) | (level - 1) }; return 0; } static int s_handle_invoke_mapping_map( objdir_t *root_dir, objdir_entry_t *target_entry, uint8_t *payload, size_t payload_at ) { uint8_t level = target_entry->data & 3; pmle_t *target_pml = (pmle_t*)vmem_phys_tovirt(target_entry->data & ~3ULL); pmli_t pmli; SYSCALL_PAYLOAD_TAKEL(payload, payload_at, pmli, pmli_t); if(pmli > 511) return -KE_OOB; if(level == 3 && pmli > 255) return -KE_OOB; size_t untyped_pathw; objdir_entry_t *untyped_entry; SYSCALL_PAYLOAD_TAKEOBJ(payload, payload_at, untyped_pathw, untyped_entry); if(untyped_entry->type != KO_MEMORY_UNTYPED) return -KE_BADOBJ; mtx_acquire(&untyped_entry->lock); if((untyped_entry->data & 0xFFF) != 0) { mtx_release(&untyped_entry->lock); return -KE_ALIGN; } size_t *untyped_data = (size_t*)untyped_entry->data; size_t untyped_size = *untyped_data; if(untyped_size != 0x1000) { mtx_release(&untyped_entry->lock); return -KE_BADSIZE; } pmle_t pmle = target_pml[pmli]; if(pmle.p) { mtx_release(&untyped_entry->lock); return -KE_OCCUPIED; } target_pml[pmli].value = vmem_ident_tophys((void*)untyped_entry->data) | PAGE_RW | PAGE_US | PAGE_PRESENT; untyped_entry->type = KO_MEMORY_MAPPING; untyped_entry->data |= level - 1; mtx_release(&untyped_entry->lock); return 0; } static int (*s_invoke_handles[])(objdir_t*, objdir_entry_t*, uint8_t*, size_t) = { [INVOKE_MAPPING_RELEASE] = s_handle_invoke_mapping_release, [INVOKE_MAPPING_GET] = s_handle_invoke_mapping_get, [INVOKE_MAPPING_MAP] = s_handle_invoke_mapping_map, }; static size_t s_invoke_handles_count = sizeof(s_invoke_handles) / sizeof(void*); int syscall_handle_invoke_mapping( objdir_t *root_dir, objdir_entry_t *target, uint8_t *payload, size_t payload_at ) { uint8_t funcid; SYSCALL_PAYLOAD_TAKEL(payload, payload_at, funcid, uint8_t); if(funcid >= s_invoke_handles_count) return -KE_BADFUNC; return s_invoke_handles[funcid](root_dir, target, payload, payload_at); }