From 30b6511467511440b95e80737755a960fd68c5be Mon Sep 17 00:00:00 2001 From: Drew Galbraith Date: Sun, 19 Nov 2023 18:55:44 -0800 Subject: [PATCH] [Zion] Add a AddressSpaceUnmap syscall to free memory. --- lib/glacier/container/binary_tree.h | 24 ++++++++++++------------ zion/CMakeLists.txt | 1 + zion/include/zcall.h | 2 ++ zion/include/ztypes.h | 2 +- zion/lib/memory_mapping_tree.cpp | 29 ++++++++++++++++++++++++++--- zion/object/address_space.h | 5 +++++ zion/syscall/address_space.cpp | 13 +++++++++++-- zion/syscall/address_space.h | 1 + zion/syscall/syscall.cpp | 1 + 9 files changed, 60 insertions(+), 18 deletions(-) diff --git a/lib/glacier/container/binary_tree.h b/lib/glacier/container/binary_tree.h index 0ca7fe1..b6beaa9 100644 --- a/lib/glacier/container/binary_tree.h +++ b/lib/glacier/container/binary_tree.h @@ -74,32 +74,32 @@ void BinaryTree::Delete(K key) { } RefPtr new_child = nullptr; - if (!node.left) { + if (!node->left) { // No children. // Right child only. - new_child = node.right; - } else if (!node.right) { + new_child = node->right; + } else if (!node->right) { // Left child only. - new_child = node.left; + new_child = node->left; } else { // Find Successor. - auto successor = node.right; - while (successor.left) { - successor = successor.left; + auto successor = node->right; + while (successor->left) { + successor = successor->left; } new_child = successor; - if (successor != node.right) { - successor.parent.left = successor.right; + if (successor != node->right) { + successor->parent->left = successor->right; } } if (node == root_) { root_ = new_child; } else { - if (node.parent.right == node) { - node.parent.right = new_child; + if (node->parent->right == node) { + node->parent->right = new_child; } else { - node.parent.left = new_child; + node->parent->left = new_child; } } } diff --git a/zion/CMakeLists.txt b/zion/CMakeLists.txt index 2156aee..4a23b55 100644 --- a/zion/CMakeLists.txt +++ b/zion/CMakeLists.txt @@ -11,6 +11,7 @@ add_executable(zion interrupt/interrupt.cpp interrupt/interrupt_enter.s interrupt/timer.cpp + lib/memory_mapping_tree.cpp lib/message_queue.cpp loader/init_loader.cpp memory/kernel_heap.cpp diff --git a/zion/include/zcall.h b/zion/include/zcall.h index 011ee04..1ea7558 100644 --- a/zion/include/zcall.h +++ b/zion/include/zcall.h @@ -19,6 +19,8 @@ SYS1(ThreadWait, z_cap_t, thread_cap); SYS4(AddressSpaceMap, z_cap_t, vmas_cap, uint64_t, vmas_offset, z_cap_t, vmmo_cap, uint64_t*, vaddr); +SYS3(AddressSpaceUnmap, z_cap_t, vmas_cap, uint64_t, lower_addr, uint64_t, + upper_addr); SYS2(MemoryObjectCreate, uint64_t, size, z_cap_t*, vmmo_cap); SYS3(MemoryObjectCreatePhysical, uint64_t, paddr, uint64_t, size, z_cap_t*, diff --git a/zion/include/ztypes.h b/zion/include/ztypes.h index 0bf4695..a57cb6a 100644 --- a/zion/include/ztypes.h +++ b/zion/include/ztypes.h @@ -21,7 +21,7 @@ const uint64_t kZionThreadWait = 0x13; // Memory Calls const uint64_t kZionAddressSpaceMap = 0x21; -const uint64_t kZionAddressSpaceUnMap = 0x21; +const uint64_t kZionAddressSpaceUnmap = 0x22; const uint64_t kZionMemoryObjectCreate = 0x30; const uint64_t kZionMemoryObjectCreatePhysical = 0x31; diff --git a/zion/lib/memory_mapping_tree.cpp b/zion/lib/memory_mapping_tree.cpp index 37d614e..72e711f 100644 --- a/zion/lib/memory_mapping_tree.cpp +++ b/zion/lib/memory_mapping_tree.cpp @@ -28,9 +28,32 @@ glcr::ErrorCode MemoryMappingTree::AddInMemoryObject( return glcr::OK; } -glcr::ErrorCode FreeMemoryRange(uint64_t vaddr_base, uint64_t vaddr_limit) { - dbgln("Unhandled free memory range!"); - return glcr::OK; +glcr::ErrorCode MemoryMappingTree::FreeMemoryRange(uint64_t vaddr_base, + uint64_t vaddr_limit) { + if (vaddr_limit <= vaddr_base) { + return glcr::INVALID_ARGUMENT; + } + auto predecessor_or = mapping_tree_.Predecessor(vaddr_base); + if (predecessor_or && predecessor_or.value().get().vaddr_limit > vaddr_base) { + return glcr::FAILED_PRECONDITION; + } + auto last_predecessor_or = mapping_tree_.Predecessor(vaddr_limit); + if (last_predecessor_or && + last_predecessor_or.value().get().vaddr_limit > vaddr_limit) { + return glcr::FAILED_PRECONDITION; + } + + auto find_or = mapping_tree_.Find(vaddr_base); + if (find_or) { + mapping_tree_.Delete(vaddr_base); + } + while (true) { + auto successor_or = mapping_tree_.Successor(vaddr_base); + if (!successor_or || successor_or.value().get().vaddr_base >= vaddr_limit) { + return glcr::OK; + } + mapping_tree_.Delete(successor_or.value().get().vaddr_base); + } } glcr::ErrorOr MemoryMappingTree::GetPhysicalPageAtVaddr( diff --git a/zion/object/address_space.h b/zion/object/address_space.h index 36fde60..cd5c1a7 100644 --- a/zion/object/address_space.h +++ b/zion/object/address_space.h @@ -76,6 +76,11 @@ class AddressSpace : public KernelObject { [[nodiscard]] glcr::ErrorOr MapInMemoryObject( const glcr::RefPtr& mem_obj); + [[nodiscard]] glcr::ErrorCode FreeAddressRange(uint64_t vaddr_base, + uint64_t vaddr_limit) { + return mapping_tree_.FreeMemoryRange(vaddr_base, vaddr_limit); + } + // Kernel Mappings. uint64_t AllocateKernelStack(); diff --git a/zion/syscall/address_space.cpp b/zion/syscall/address_space.cpp index 1582dcd..24fbec1 100644 --- a/zion/syscall/address_space.cpp +++ b/zion/syscall/address_space.cpp @@ -15,10 +15,19 @@ z_err_t AddressSpaceMap(ZAddressSpaceMapReq* req) { // FIXME: Validation necessary. if (req->vmas_offset != 0) { - vmas->MapInMemoryObject(req->vmas_offset, vmmo); + RET_ERR(vmas->MapInMemoryObject(req->vmas_offset, vmmo)); *req->vaddr = req->vmas_offset; } else { - *req->vaddr = vmas->MapInMemoryObject(vmmo); + ASSIGN_OR_RETURN(*req->vaddr, vmas->MapInMemoryObject(vmmo)); } return glcr::OK; } + +z_err_t AddressSpaceUnmap(ZAddressSpaceUnmapReq* req) { + auto& curr_proc = gScheduler->CurrentProcess(); + auto vmas_cap = curr_proc.GetCapability(req->vmas_cap); + RET_ERR(ValidateCapability(vmas_cap, kZionPerm_Write)); + + auto vmas = vmas_cap->obj(); + return vmas->FreeAddressRange(req->lower_addr, req->upper_addr); +} diff --git a/zion/syscall/address_space.h b/zion/syscall/address_space.h index 87c7876..684478c 100644 --- a/zion/syscall/address_space.h +++ b/zion/syscall/address_space.h @@ -3,3 +3,4 @@ #include "include/zcall.h" z_err_t AddressSpaceMap(ZAddressSpaceMapReq* req); +z_err_t AddressSpaceUnmap(ZAddressSpaceUnmapReq* req); diff --git a/zion/syscall/syscall.cpp b/zion/syscall/syscall.cpp index abaf609..d21392c 100644 --- a/zion/syscall/syscall.cpp +++ b/zion/syscall/syscall.cpp @@ -60,6 +60,7 @@ extern "C" z_err_t SyscallHandler(uint64_t call_id, void* req) { CASE(ThreadWait); // syscall/address_space.h CASE(AddressSpaceMap); + CASE(AddressSpaceUnmap); // syscall/memory_object.h CASE(MemoryObjectCreate); CASE(MemoryObjectCreatePhysical);