diff --git a/kernel/inc/mm/region.h b/kernel/inc/mm/region.h index 797736d..2236259 100644 --- a/kernel/inc/mm/region.h +++ b/kernel/inc/mm/region.h @@ -13,8 +13,9 @@ #define MEM_REGION_PROCESS 0x0000000000000000 #define MEM_REGION_PROCESS_EXEC 0x0000010000000000 #define MEM_REGION_PROCESS_THREAD_BASE 0x0000010100000000 +#define MEM_REGION_PROCESS_USABLE 0x0000080000000000 -#define MEM_REGION_KERNEL 0xFFFF800000000000 +#define MEM_REGION_KERNEL 0x0000800000000000 #define MEM_REGION_KERNEL_STACK_DUMMY 0xFFFFF00000000000 // size 0x4000 #define MEM_REGION_KERNEL_HEAP 0xFFFFF80000000000 #define MEM_REGION_KERNEL_THREAD_BASE 0xFFFFFF0000000000 diff --git a/kernel/inc/platform/syscall.h b/kernel/inc/platform/syscall.h index 8c66fdd..4b82a3e 100644 --- a/kernel/inc/platform/syscall.h +++ b/kernel/inc/platform/syscall.h @@ -26,8 +26,8 @@ typedef enum { SYSCALL_FILES_FOLLOW = 0x0107, // Warning: nx_follow will probably be kicked out of the ABI SYSCALL_FILES_INFO = 0x0108, - SYSCALL_MEMORY_ALLOC = 0x0201, - SYSCALL_MEMORY_FREE = 0x0202, + SYSCALL_MEMORY_MAP = 0x0201, + SYSCALL_MEMORY_UNMAP = 0x0202, SYSCALL_MEMORY_LABEL = 0x0203, SYSCALL_MEMORY_RANGE = 0x0204, SYSCALL_MEMORY_ACCESS = 0x0205, @@ -51,6 +51,11 @@ typedef enum { SYSCALL_KERNEL_PANIC = 0xFF01 } syscall_E; +typedef enum { + SYSCALL_NX_MMAP_FLAG_WRITE, + SYSCALL_NX_MMAP_FLAG_NO_EXEC +} syscall_nx_mmap_flags_E; + extern status_E syscall_perform(syscall_E id, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4); cpu_state_T* syscall_handle(cpu_state_T* state); diff --git a/kernel/src/kmain.c b/kernel/src/kmain.c index 06e94da..d4ed1ab 100644 --- a/kernel/src/kmain.c +++ b/kernel/src/kmain.c @@ -57,10 +57,23 @@ void kmain(boot_info_T boot_info) { log(LOG_INFO, "!=====[ Kernel Initialized ]=====!\n"); - char buffer[64]; - uint32_t needed_mem = 0; - syscall_perform(SYSCALL_FILES_LIST, (uint64_t)"/initrd/", 0, buffer, &needed_mem); - memory_hexdump(buffer, 64); + + log(LOG_DEBUG, "0x0000080000000000 --[check]--> %?", page_map_check_memory(g_kernel_page_map, 0x0000080000000000)); + log(LOG_DEBUG, "0x0000080000001000 --[check]--> %?", page_map_check_memory(g_kernel_page_map, 0x0000080000001000)); + log(LOG_DEBUG, "0x0000080000002000 --[check]--> %?", page_map_check_memory(g_kernel_page_map, 0x0000080000002000)); + log(LOG_DEBUG, "0x0000080000003000 --[check]--> %?", page_map_check_memory(g_kernel_page_map, 0x0000080000003000)); + syscall_perform(SYSCALL_MEMORY_MAP, 0x0000080000000000, 4, 0, 0); + log(LOG_DEBUG, "performed 'nx_mmap'"); + log(LOG_DEBUG, "0x0000080000000000 --[check]--> %?", page_map_check_memory(g_kernel_page_map, 0x0000080000000000)); + log(LOG_DEBUG, "0x0000080000001000 --[check]--> %?", page_map_check_memory(g_kernel_page_map, 0x0000080000001000)); + log(LOG_DEBUG, "0x0000080000002000 --[check]--> %?", page_map_check_memory(g_kernel_page_map, 0x0000080000002000)); + log(LOG_DEBUG, "0x0000080000003000 --[check]--> %?", page_map_check_memory(g_kernel_page_map, 0x0000080000003000)); + syscall_perform(SYSCALL_MEMORY_UNMAP, 0x0000080000000000, 4, 0, 0); + log(LOG_DEBUG, "performed 'nx_munmap'"); + log(LOG_DEBUG, "0x0000080000000000 --[check]--> %?", page_map_check_memory(g_kernel_page_map, 0x0000080000000000)); + log(LOG_DEBUG, "0x0000080000001000 --[check]--> %?", page_map_check_memory(g_kernel_page_map, 0x0000080000001000)); + log(LOG_DEBUG, "0x0000080000002000 --[check]--> %?", page_map_check_memory(g_kernel_page_map, 0x0000080000002000)); + log(LOG_DEBUG, "0x0000080000003000 --[check]--> %?", page_map_check_memory(g_kernel_page_map, 0x0000080000003000)); // vfs_node_T* node = vfs_resolve_path(&g_root_fs, "/initrd/test.elf"); // void* buffer = memory_allocate(node->size); diff --git a/kernel/src/platform/syscall.c b/kernel/src/platform/syscall.c index 1006bde..7cdd061 100644 --- a/kernel/src/platform/syscall.c +++ b/kernel/src/platform/syscall.c @@ -6,6 +6,8 @@ #include "utils/memory.h" #include "proc/scheduler.h" #include "drivers/fs/vfs.h" +#include "mm/page_frame.h" +#include "mm/region.h" void syscall_handle_nx_fopen(cpu_state_T* state) { string_t path = (string_t)state->rdi; // arg1 @@ -105,6 +107,61 @@ void syscall_handle_nx_flist(cpu_state_T* state) { } +void syscall_handle_nx_mmap(cpu_state_T* state) { + uint8_t* addr = (uint8_t*)state->rdi; // arg1 + uint64_t n = state->rsi; // arg2 + uint64_t flags = (uint64_t)state->rdx; // arg3 + + if ((uint64_t)&addr[n * PFRAME_SIZE] > MEM_REGION_KERNEL || + (uint64_t)addr < MEM_REGION_PROCESS_USABLE) { + state->rax = STATUS_PERMISSION_DENIED; + return; + } + + uint64_t map_flags = 0; + if (flags & (1 << SYSCALL_NX_MMAP_FLAG_WRITE)) map_flags |= PM_FLAG_READ_WRITE; + if (flags & (1 << SYSCALL_NX_MMAP_FLAG_NO_EXEC)) map_flags |= PM_FLAG_NO_EXECUTE; + + page_map_T* page_map = scheduler_get_current_process()->page_map; + + for (int i = 0; i < n; i++) { + // check if the page is already mapped + if (page_map_check_memory(page_map, &addr[i * PFRAME_SIZE])) { + // unmap all the already mapped pages + for (int j = 0; j < i; j++) { + pframe_free(page_map_get_physical_address(page_map, &addr[j * PFRAME_SIZE])); + page_map_unmap_memory(page_map, &addr[j * PFRAME_SIZE]); + } + state->rax = STATUS_RESOURCE_NOT_AVAILABLE; + return; + } + page_map_map_memory(page_map, &addr[i * PFRAME_SIZE], pframe_request(), map_flags); + } + + state->rax = STATUS_SUCCESS; +} + +void syscall_handle_nx_munmap(cpu_state_T* state) { + void* addr = (void*)state->rdi; // arg1 + uint64_t n = state->rsi; // arg2 + + if ((uint64_t)&addr[n * PFRAME_SIZE] > MEM_REGION_KERNEL || + (uint64_t)addr < MEM_REGION_PROCESS_USABLE) { + state->rax = STATUS_PERMISSION_DENIED; + return; + } + + page_map_T* page_map = scheduler_get_current_process()->page_map; + + for (int i = 0; i < n; i++) { + pframe_free(page_map_get_physical_address(page_map, &addr[i * PFRAME_SIZE])); + page_map_unmap_memory(page_map, &addr[i * PFRAME_SIZE]); + } + + state->rax = STATUS_SUCCESS; +} + + cpu_state_T* syscall_handle(cpu_state_T* state) { cpu_state_T* return_state = state; syscall_group_E group_id = (state->rax & 0xFF00) >> 8; @@ -143,6 +200,16 @@ cpu_state_T* syscall_handle(cpu_state_T* state) { } case SYSCALLS_MEMORY: { + switch (state->rax) { + case SYSCALL_MEMORY_MAP: { + syscall_handle_nx_mmap(state); + break; + } + case SYSCALL_MEMORY_UNMAP: { + syscall_handle_nx_munmap(state); + break; + } + } break; }