mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	Merge pull request #4433 from wwylele/vmmanager-simple
VMManager: remove shared_ptr<vector> backing type
This commit is contained in:
		
						commit
						2b768da531
					
				
					 9 changed files with 110 additions and 204 deletions
				
			
		|  | @ -2,6 +2,7 @@ | |||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include "common/alignment.h" | ||||
| #include "core/hle/ipc.h" | ||||
| #include "core/hle/kernel/handle_table.h" | ||||
|  | @ -14,70 +15,10 @@ | |||
| 
 | ||||
| namespace Kernel { | ||||
| 
 | ||||
| void ScanForAndUnmapBuffer(std::array<u32, IPC::COMMAND_BUFFER_LENGTH>& dst_cmd_buf, | ||||
|                            const std::size_t dst_command_size, std::size_t& target_index, | ||||
|                            SharedPtr<Process> src_process, SharedPtr<Process> dst_process, | ||||
|                            const VAddr source_address, const VAddr page_start, const u32 num_pages, | ||||
|                            const u32 size, const IPC::MappedBufferPermissions permissions) { | ||||
|     while (target_index < dst_command_size) { | ||||
|         u32 desc = dst_cmd_buf[target_index++]; | ||||
| 
 | ||||
|         if (IPC::GetDescriptorType(desc) == IPC::DescriptorType::CopyHandle || | ||||
|             IPC::GetDescriptorType(desc) == IPC::DescriptorType::MoveHandle) { | ||||
|             u32 num_handles = IPC::HandleNumberFromDesc(desc); | ||||
|             for (u32 j = 0; j < num_handles; ++j) { | ||||
|                 target_index += 1; | ||||
|             } | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         if (IPC::GetDescriptorType(desc) == IPC::DescriptorType::CallingPid || | ||||
|             IPC::GetDescriptorType(desc) == IPC::DescriptorType::StaticBuffer) { | ||||
|             target_index += 1; | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         if (IPC::GetDescriptorType(desc) == IPC::DescriptorType::MappedBuffer) { | ||||
|             VAddr dest_address = dst_cmd_buf[target_index]; | ||||
|             IPC::MappedBufferDescInfo dest_descInfo{desc}; | ||||
|             u32 dest_size = static_cast<u32>(dest_descInfo.size); | ||||
|             IPC::MappedBufferPermissions dest_permissions = dest_descInfo.perms; | ||||
| 
 | ||||
|             if (dest_size == 0) { | ||||
|                 target_index += 1; | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             ASSERT(permissions == dest_permissions && size == dest_size); | ||||
|             // Readonly buffers do not need to be copied over to the target
 | ||||
|             // process again because they were (presumably) not modified. This
 | ||||
|             // behavior is consistent with the real kernel.
 | ||||
|             if (permissions != IPC::MappedBufferPermissions::R) { | ||||
|                 // Copy the modified buffer back into the target process
 | ||||
|                 Memory::CopyBlock(*src_process, *dst_process, source_address, dest_address, size); | ||||
|             } | ||||
| 
 | ||||
|             VAddr prev_reserve = page_start - Memory::PAGE_SIZE; | ||||
|             VAddr next_reserve = page_start + num_pages * Memory::PAGE_SIZE; | ||||
| 
 | ||||
|             auto& prev_vma = src_process->vm_manager.FindVMA(prev_reserve)->second; | ||||
|             auto& next_vma = src_process->vm_manager.FindVMA(next_reserve)->second; | ||||
|             ASSERT(prev_vma.meminfo_state == MemoryState::Reserved && | ||||
|                    next_vma.meminfo_state == MemoryState::Reserved); | ||||
| 
 | ||||
|             // Unmap the buffer and guard pages from the source process
 | ||||
|             ResultCode result = src_process->vm_manager.UnmapRange( | ||||
|                 page_start - Memory::PAGE_SIZE, (num_pages + 2) * Memory::PAGE_SIZE); | ||||
|             ASSERT(result == RESULT_SUCCESS); | ||||
| 
 | ||||
|             target_index += 1; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| ResultCode TranslateCommandBuffer(SharedPtr<Thread> src_thread, SharedPtr<Thread> dst_thread, | ||||
|                                   VAddr src_address, VAddr dst_address, bool reply) { | ||||
|                                   VAddr src_address, VAddr dst_address, | ||||
|                                   std::vector<MappedBufferContext>& mapped_buffer_context, | ||||
|                                   bool reply) { | ||||
| 
 | ||||
|     auto& src_process = src_thread->owner_process; | ||||
|     auto& dst_process = dst_thread->owner_process; | ||||
|  | @ -95,18 +36,6 @@ ResultCode TranslateCommandBuffer(SharedPtr<Thread> src_thread, SharedPtr<Thread | |||
|     std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf; | ||||
|     Memory::ReadBlock(*src_process, src_address, cmd_buf.data(), command_size * sizeof(u32)); | ||||
| 
 | ||||
|     // Create a copy of the target's command buffer
 | ||||
|     IPC::Header dst_header; | ||||
|     Memory::ReadBlock(*dst_process, dst_address, &dst_header.raw, sizeof(dst_header.raw)); | ||||
| 
 | ||||
|     std::size_t dst_untranslated_size = 1u + dst_header.normal_params_size; | ||||
|     std::size_t dst_command_size = dst_untranslated_size + dst_header.translate_params_size; | ||||
|     std::size_t target_index = dst_untranslated_size; | ||||
| 
 | ||||
|     std::array<u32, IPC::COMMAND_BUFFER_LENGTH> dst_cmd_buf; | ||||
|     Memory::ReadBlock(*dst_process, dst_address, dst_cmd_buf.data(), | ||||
|                       dst_command_size * sizeof(u32)); | ||||
| 
 | ||||
|     std::size_t i = untranslated_size; | ||||
|     while (i < command_size) { | ||||
|         u32 descriptor = cmd_buf[i]; | ||||
|  | @ -212,9 +141,36 @@ ResultCode TranslateCommandBuffer(SharedPtr<Thread> src_thread, SharedPtr<Thread | |||
|             if (reply) { | ||||
|                 // Scan the target's command buffer for the matching mapped buffer.
 | ||||
|                 // The real kernel panics if you try to reply with an unsolicited MappedBuffer.
 | ||||
|                 ScanForAndUnmapBuffer(dst_cmd_buf, dst_command_size, target_index, src_process, | ||||
|                                       dst_process, source_address, page_start, num_pages, size, | ||||
|                                       permissions); | ||||
|                 auto found = std::find_if( | ||||
|                     mapped_buffer_context.begin(), mapped_buffer_context.end(), | ||||
|                     [permissions, size, source_address](const MappedBufferContext& context) { | ||||
|                         // Note: reply's source_address is request's target_address
 | ||||
|                         return context.permissions == permissions && context.size == size && | ||||
|                                context.target_address == source_address; | ||||
|                     }); | ||||
| 
 | ||||
|                 ASSERT(found != mapped_buffer_context.end()); | ||||
| 
 | ||||
|                 if (permissions != IPC::MappedBufferPermissions::R) { | ||||
|                     // Copy the modified buffer back into the target process
 | ||||
|                     Memory::CopyBlock(*src_process, *dst_process, found->target_address, | ||||
|                                       found->source_address, size); | ||||
|                 } | ||||
| 
 | ||||
|                 VAddr prev_reserve = page_start - Memory::PAGE_SIZE; | ||||
|                 VAddr next_reserve = page_start + num_pages * Memory::PAGE_SIZE; | ||||
| 
 | ||||
|                 auto& prev_vma = src_process->vm_manager.FindVMA(prev_reserve)->second; | ||||
|                 auto& next_vma = src_process->vm_manager.FindVMA(next_reserve)->second; | ||||
|                 ASSERT(prev_vma.meminfo_state == MemoryState::Reserved && | ||||
|                        next_vma.meminfo_state == MemoryState::Reserved); | ||||
| 
 | ||||
|                 // Unmap the buffer and guard pages from the source process
 | ||||
|                 ResultCode result = src_process->vm_manager.UnmapRange( | ||||
|                     page_start - Memory::PAGE_SIZE, (num_pages + 2) * Memory::PAGE_SIZE); | ||||
|                 ASSERT(result == RESULT_SUCCESS); | ||||
| 
 | ||||
|                 mapped_buffer_context.erase(found); | ||||
| 
 | ||||
|                 i += 1; | ||||
|                 break; | ||||
|  | @ -225,27 +181,33 @@ ResultCode TranslateCommandBuffer(SharedPtr<Thread> src_thread, SharedPtr<Thread | |||
|             // TODO(Subv): Perform permission checks.
 | ||||
| 
 | ||||
|             // Reserve a page of memory before the mapped buffer
 | ||||
|             auto reserve_buffer = std::make_shared<std::vector<u8>>(Memory::PAGE_SIZE); | ||||
|             dst_process->vm_manager.MapMemoryBlockToBase( | ||||
|                 Memory::IPC_MAPPING_VADDR, Memory::IPC_MAPPING_SIZE, reserve_buffer, 0, | ||||
|                 static_cast<u32>(reserve_buffer->size()), Kernel::MemoryState::Reserved); | ||||
|             auto reserve_buffer = std::make_unique<u8[]>(Memory::PAGE_SIZE); | ||||
|             dst_process->vm_manager.MapBackingMemoryToBase( | ||||
|                 Memory::IPC_MAPPING_VADDR, Memory::IPC_MAPPING_SIZE, reserve_buffer.get(), | ||||
|                 Memory::PAGE_SIZE, Kernel::MemoryState::Reserved); | ||||
| 
 | ||||
|             auto buffer = std::make_shared<std::vector<u8>>(num_pages * Memory::PAGE_SIZE); | ||||
|             Memory::ReadBlock(*src_process, source_address, buffer->data() + page_offset, size); | ||||
|             auto buffer = std::make_unique<u8[]>(num_pages * Memory::PAGE_SIZE); | ||||
|             Memory::ReadBlock(*src_process, source_address, buffer.get() + page_offset, size); | ||||
| 
 | ||||
|             // Map the page(s) into the target process' address space.
 | ||||
|             target_address = dst_process->vm_manager | ||||
|                                  .MapMemoryBlockToBase( | ||||
|                                      Memory::IPC_MAPPING_VADDR, Memory::IPC_MAPPING_SIZE, buffer, 0, | ||||
|                                      static_cast<u32>(buffer->size()), Kernel::MemoryState::Shared) | ||||
|                                  .Unwrap(); | ||||
|             target_address = | ||||
|                 dst_process->vm_manager | ||||
|                     .MapBackingMemoryToBase(Memory::IPC_MAPPING_VADDR, Memory::IPC_MAPPING_SIZE, | ||||
|                                             buffer.get(), num_pages * Memory::PAGE_SIZE, | ||||
|                                             Kernel::MemoryState::Shared) | ||||
|                     .Unwrap(); | ||||
| 
 | ||||
|             cmd_buf[i++] = target_address + page_offset; | ||||
| 
 | ||||
|             // Reserve a page of memory after the mapped buffer
 | ||||
|             dst_process->vm_manager.MapMemoryBlockToBase( | ||||
|                 Memory::IPC_MAPPING_VADDR, Memory::IPC_MAPPING_SIZE, reserve_buffer, 0, | ||||
|                 static_cast<u32>(reserve_buffer->size()), Kernel::MemoryState::Reserved); | ||||
|             dst_process->vm_manager.MapBackingMemoryToBase( | ||||
|                 Memory::IPC_MAPPING_VADDR, Memory::IPC_MAPPING_SIZE, reserve_buffer.get(), | ||||
|                 Memory::PAGE_SIZE, Kernel::MemoryState::Reserved); | ||||
| 
 | ||||
|             mapped_buffer_context.push_back({permissions, size, source_address, | ||||
|                                              target_address + page_offset, std::move(buffer), | ||||
|                                              std::move(reserve_buffer)}); | ||||
| 
 | ||||
|             break; | ||||
|         } | ||||
|         default: | ||||
|  |  | |||
|  | @ -4,11 +4,27 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <memory> | ||||
| #include <vector> | ||||
| #include "common/common_types.h" | ||||
| #include "core/hle/ipc.h" | ||||
| #include "core/hle/kernel/thread.h" | ||||
| 
 | ||||
| namespace Kernel { | ||||
| 
 | ||||
| struct MappedBufferContext { | ||||
|     IPC::MappedBufferPermissions permissions; | ||||
|     u32 size; | ||||
|     VAddr source_address; | ||||
|     VAddr target_address; | ||||
| 
 | ||||
|     std::unique_ptr<u8[]> buffer; | ||||
|     std::unique_ptr<u8[]> reserve_buffer; | ||||
| }; | ||||
| 
 | ||||
| /// Performs IPC command buffer translation from one process to another.
 | ||||
| ResultCode TranslateCommandBuffer(SharedPtr<Thread> src_thread, SharedPtr<Thread> dst_thread, | ||||
|                                   VAddr src_address, VAddr dst_address, bool reply); | ||||
|                                   VAddr src_address, VAddr dst_address, | ||||
|                                   std::vector<MappedBufferContext>& mapped_buffer_context, | ||||
|                                   bool reply); | ||||
| } // namespace Kernel
 | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ | |||
| #include <string> | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "core/hle/kernel/ipc.h" | ||||
| #include "core/hle/kernel/object.h" | ||||
| #include "core/hle/kernel/wait_object.h" | ||||
| #include "core/hle/result.h" | ||||
|  | @ -83,6 +84,9 @@ public: | |||
|     /// TODO(Subv): Find a better name for this.
 | ||||
|     SharedPtr<Thread> currently_handling; | ||||
| 
 | ||||
|     /// A temporary list holding mapped buffer info from IPC request, used for during IPC reply
 | ||||
|     std::vector<MappedBufferContext> mapped_buffer_context; | ||||
| 
 | ||||
| private: | ||||
|     explicit ServerSession(KernelSystem& kernel); | ||||
|     ~ServerSession() override; | ||||
|  |  | |||
|  | @ -600,8 +600,9 @@ static ResultCode ReceiveIPCRequest(SharedPtr<ServerSession> server_session, | |||
|     VAddr target_address = thread->GetCommandBufferAddress(); | ||||
|     VAddr source_address = server_session->currently_handling->GetCommandBufferAddress(); | ||||
| 
 | ||||
|     ResultCode translation_result = TranslateCommandBuffer( | ||||
|         server_session->currently_handling, thread, source_address, target_address, false); | ||||
|     ResultCode translation_result = | ||||
|         TranslateCommandBuffer(server_session->currently_handling, thread, source_address, | ||||
|                                target_address, server_session->mapped_buffer_context, false); | ||||
| 
 | ||||
|     // If a translation error occurred, immediately resume the client thread.
 | ||||
|     if (translation_result.IsError()) { | ||||
|  | @ -667,7 +668,8 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co | |||
|         VAddr target_address = request_thread->GetCommandBufferAddress(); | ||||
| 
 | ||||
|         ResultCode translation_result = | ||||
|             TranslateCommandBuffer(thread, request_thread, source_address, target_address, true); | ||||
|             TranslateCommandBuffer(thread, request_thread, source_address, target_address, | ||||
|                                    session->mapped_buffer_context, true); | ||||
| 
 | ||||
|         // Note: The real kernel seems to always panic if the Server->Client buffer translation
 | ||||
|         // fails for whatever reason.
 | ||||
|  |  | |||
|  | @ -28,10 +28,6 @@ bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const { | |||
|         type != next.type) { | ||||
|         return false; | ||||
|     } | ||||
|     if (type == VMAType::AllocatedMemoryBlock && | ||||
|         (backing_block != next.backing_block || offset + size != next.offset)) { | ||||
|         return false; | ||||
|     } | ||||
|     if (type == VMAType::BackingMemory && backing_memory + size != next.backing_memory) { | ||||
|         return false; | ||||
|     } | ||||
|  | @ -71,31 +67,8 @@ VMManager::VMAHandle VMManager::FindVMA(VAddr target) const { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target, | ||||
|                                                           std::shared_ptr<std::vector<u8>> block, | ||||
|                                                           std::size_t offset, u32 size, | ||||
|                                                           MemoryState state) { | ||||
|     ASSERT(block != nullptr); | ||||
|     ASSERT(offset + size <= block->size()); | ||||
| 
 | ||||
|     // This is the appropriately sized VMA that will turn into our allocation.
 | ||||
|     CASCADE_RESULT(VMAIter vma_handle, CarveVMA(target, size)); | ||||
|     VirtualMemoryArea& final_vma = vma_handle->second; | ||||
|     ASSERT(final_vma.size == size); | ||||
| 
 | ||||
|     final_vma.type = VMAType::AllocatedMemoryBlock; | ||||
|     final_vma.permissions = VMAPermission::ReadWrite; | ||||
|     final_vma.meminfo_state = state; | ||||
|     final_vma.backing_block = block; | ||||
|     final_vma.offset = offset; | ||||
|     UpdatePageTableForVMA(final_vma); | ||||
| 
 | ||||
|     return MakeResult<VMAHandle>(MergeAdjacent(vma_handle)); | ||||
| } | ||||
| 
 | ||||
| ResultVal<VAddr> VMManager::MapMemoryBlockToBase(VAddr base, u32 region_size, | ||||
|                                                  std::shared_ptr<std::vector<u8>> block, | ||||
|                                                  std::size_t offset, u32 size, MemoryState state) { | ||||
| ResultVal<VAddr> VMManager::MapBackingMemoryToBase(VAddr base, u32 region_size, u8* memory, | ||||
|                                                    u32 size, MemoryState state) { | ||||
| 
 | ||||
|     // Find the first Free VMA.
 | ||||
|     VMAHandle vma_handle = std::find_if(vma_map.begin(), vma_map.end(), [&](const auto& vma) { | ||||
|  | @ -115,7 +88,7 @@ ResultVal<VAddr> VMManager::MapMemoryBlockToBase(VAddr base, u32 region_size, | |||
|                           ErrorSummary::OutOfResource, ErrorLevel::Permanent); | ||||
|     } | ||||
| 
 | ||||
|     auto result = MapMemoryBlock(target, block, offset, size, state); | ||||
|     auto result = MapBackingMemory(target, memory, size, state); | ||||
| 
 | ||||
|     if (result.Failed()) | ||||
|         return result.Code(); | ||||
|  | @ -198,8 +171,6 @@ VMManager::VMAIter VMManager::Unmap(VMAIter vma_handle) { | |||
|     vma.permissions = VMAPermission::None; | ||||
|     vma.meminfo_state = MemoryState::Free; | ||||
| 
 | ||||
|     vma.backing_block = nullptr; | ||||
|     vma.offset = 0; | ||||
|     vma.backing_memory = nullptr; | ||||
|     vma.paddr = 0; | ||||
| 
 | ||||
|  | @ -247,17 +218,6 @@ ResultCode VMManager::ReprotectRange(VAddr target, u32 size, VMAPermission new_p | |||
|     return RESULT_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| void VMManager::RefreshMemoryBlockMappings(const std::vector<u8>* block) { | ||||
|     // If this ever proves to have a noticeable performance impact, allow users of the function to
 | ||||
|     // specify a specific range of addresses to limit the scan to.
 | ||||
|     for (const auto& p : vma_map) { | ||||
|         const VirtualMemoryArea& vma = p.second; | ||||
|         if (block == vma.backing_block.get()) { | ||||
|             UpdatePageTableForVMA(vma); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void VMManager::LogLayout(Log::Level log_level) const { | ||||
|     for (const auto& p : vma_map) { | ||||
|         const VirtualMemoryArea& vma = p.second; | ||||
|  | @ -356,9 +316,6 @@ VMManager::VMAIter VMManager::SplitVMA(VMAIter vma_handle, u32 offset_in_vma) { | |||
|     switch (new_vma.type) { | ||||
|     case VMAType::Free: | ||||
|         break; | ||||
|     case VMAType::AllocatedMemoryBlock: | ||||
|         new_vma.offset += offset_in_vma; | ||||
|         break; | ||||
|     case VMAType::BackingMemory: | ||||
|         new_vma.backing_memory += offset_in_vma; | ||||
|         break; | ||||
|  | @ -396,10 +353,6 @@ void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) { | |||
|     case VMAType::Free: | ||||
|         Memory::UnmapRegion(page_table, vma.base, vma.size); | ||||
|         break; | ||||
|     case VMAType::AllocatedMemoryBlock: | ||||
|         Memory::MapMemoryRegion(page_table, vma.base, vma.size, | ||||
|                                 vma.backing_block->data() + vma.offset); | ||||
|         break; | ||||
|     case VMAType::BackingMemory: | ||||
|         Memory::MapMemoryRegion(page_table, vma.base, vma.size, vma.backing_memory); | ||||
|         break; | ||||
|  |  | |||
|  | @ -18,13 +18,10 @@ namespace Kernel { | |||
| enum class VMAType : u8 { | ||||
|     /// VMA represents an unmapped region of the address space.
 | ||||
|     Free, | ||||
|     /// VMA is backed by a ref-counted allocate memory block.
 | ||||
|     AllocatedMemoryBlock, | ||||
|     /// VMA is backed by a raw, unmanaged pointer.
 | ||||
|     BackingMemory, | ||||
|     /// VMA is mapped to MMIO registers at a fixed PAddr.
 | ||||
|     MMIO, | ||||
|     // TODO(yuriks): Implement MemoryAlias to support MAP/UNMAP
 | ||||
| }; | ||||
| 
 | ||||
| /// Permissions for mapped memory blocks
 | ||||
|  | @ -72,12 +69,6 @@ struct VirtualMemoryArea { | |||
|     /// Tag returned by svcQueryMemory. Not otherwise used.
 | ||||
|     MemoryState meminfo_state = MemoryState::Free; | ||||
| 
 | ||||
|     // Settings for type = AllocatedMemoryBlock
 | ||||
|     /// Memory block backing this VMA.
 | ||||
|     std::shared_ptr<std::vector<u8>> backing_block = nullptr; | ||||
|     /// Offset into the backing_memory the mapping starts from.
 | ||||
|     std::size_t offset = 0; | ||||
| 
 | ||||
|     // Settings for type = BackingMemory
 | ||||
|     /// Pointer backing this VMA. It will not be destroyed or freed when the VMA is removed.
 | ||||
|     u8* backing_memory = nullptr; | ||||
|  | @ -133,32 +124,18 @@ public: | |||
| 
 | ||||
|     // TODO(yuriks): Should these functions actually return the handle?
 | ||||
| 
 | ||||
|     /**
 | ||||
|      * Maps part of a ref-counted block of memory at a given address. | ||||
|      * | ||||
|      * @param target The guest address to start the mapping at. | ||||
|      * @param block The block to be mapped. | ||||
|      * @param offset Offset into `block` to map from. | ||||
|      * @param size Size of the mapping. | ||||
|      * @param state MemoryState tag to attach to the VMA. | ||||
|      */ | ||||
|     ResultVal<VMAHandle> MapMemoryBlock(VAddr target, std::shared_ptr<std::vector<u8>> block, | ||||
|                                         std::size_t offset, u32 size, MemoryState state); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Maps part of a ref-counted block of memory at the first free address after the given base. | ||||
|      * | ||||
|      * @param base The base address to start the mapping at. | ||||
|      * @param region_size The max size of the region from where we'll try to find an address. | ||||
|      * @param block The block to be mapped. | ||||
|      * @param offset Offset into `block` to map from. | ||||
|      * @param memory The memory to be mapped. | ||||
|      * @param size Size of the mapping. | ||||
|      * @param state MemoryState tag to attach to the VMA. | ||||
|      * @returns The address at which the memory was mapped. | ||||
|      */ | ||||
|     ResultVal<VAddr> MapMemoryBlockToBase(VAddr base, u32 region_size, | ||||
|                                           std::shared_ptr<std::vector<u8>> block, | ||||
|                                           std::size_t offset, u32 size, MemoryState state); | ||||
|     ResultVal<VAddr> MapBackingMemoryToBase(VAddr base, u32 region_size, u8* memory, u32 size, | ||||
|                                             MemoryState state); | ||||
|     /**
 | ||||
|      * Maps an unmanaged host memory pointer at a given address. | ||||
|      * | ||||
|  | @ -205,12 +182,6 @@ public: | |||
|     /// Changes the permissions of a range of addresses, splitting VMAs as necessary.
 | ||||
|     ResultCode ReprotectRange(VAddr target, u32 size, VMAPermission new_perms); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Scans all VMAs and updates the page table range of any that use the given vector as backing | ||||
|      * memory. This should be called after any operation that causes reallocation of the vector. | ||||
|      */ | ||||
|     void RefreshMemoryBlockMappings(const std::vector<u8>* block); | ||||
| 
 | ||||
|     /// Dumps the address space layout to the log, for debugging
 | ||||
|     void LogLayout(Log::Level log_level) const; | ||||
| 
 | ||||
|  |  | |||
|  | @ -92,9 +92,6 @@ static u8* GetPointerFromVMA(const Kernel::Process& process, VAddr vaddr) { | |||
| 
 | ||||
|     auto& vma = it->second; | ||||
|     switch (vma.type) { | ||||
|     case Kernel::VMAType::AllocatedMemoryBlock: | ||||
|         direct_pointer = vma.backing_block->data() + vma.offset; | ||||
|         break; | ||||
|     case Kernel::VMAType::BackingMemory: | ||||
|         direct_pointer = vma.backing_memory; | ||||
|         break; | ||||
|  |  | |||
|  | @ -139,8 +139,8 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel | |||
|         std::fill(buffer->begin(), buffer->end(), 0xAB); | ||||
| 
 | ||||
|         VAddr target_address = 0x10000000; | ||||
|         auto result = process->vm_manager.MapMemoryBlock(target_address, buffer, 0, buffer->size(), | ||||
|                                                          MemoryState::Private); | ||||
|         auto result = process->vm_manager.MapBackingMemory(target_address, buffer->data(), | ||||
|                                                            buffer->size(), MemoryState::Private); | ||||
|         REQUIRE(result.Code() == RESULT_SUCCESS); | ||||
| 
 | ||||
|         const u32_le input[]{ | ||||
|  | @ -161,8 +161,8 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel | |||
|         std::fill(buffer->begin(), buffer->end(), 0xCD); | ||||
| 
 | ||||
|         VAddr target_address = 0x10000000; | ||||
|         auto result = process->vm_manager.MapMemoryBlock(target_address, buffer, 0, buffer->size(), | ||||
|                                                          MemoryState::Private); | ||||
|         auto result = process->vm_manager.MapBackingMemory(target_address, buffer->data(), | ||||
|                                                            buffer->size(), MemoryState::Private); | ||||
| 
 | ||||
|         const u32_le input[]{ | ||||
|             IPC::MakeHeader(0, 0, 2), | ||||
|  | @ -188,13 +188,14 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel | |||
|         std::fill(buffer_mapped->begin(), buffer_mapped->end(), 0xDF); | ||||
| 
 | ||||
|         VAddr target_address_static = 0x10000000; | ||||
|         auto result = process->vm_manager.MapMemoryBlock( | ||||
|             target_address_static, buffer_static, 0, buffer_static->size(), MemoryState::Private); | ||||
|         auto result = | ||||
|             process->vm_manager.MapBackingMemory(target_address_static, buffer_static->data(), | ||||
|                                                  buffer_static->size(), MemoryState::Private); | ||||
|         REQUIRE(result.Code() == RESULT_SUCCESS); | ||||
| 
 | ||||
|         VAddr target_address_mapped = 0x20000000; | ||||
|         result = process->vm_manager.MapMemoryBlock(target_address_mapped, buffer_mapped, 0, | ||||
|                                                     buffer_mapped->size(), MemoryState::Private); | ||||
|         result = process->vm_manager.MapBackingMemory(target_address_mapped, buffer_mapped->data(), | ||||
|                                                       buffer_mapped->size(), MemoryState::Private); | ||||
|         REQUIRE(result.Code() == RESULT_SUCCESS); | ||||
| 
 | ||||
|         auto a = MakeObject(kernel); | ||||
|  | @ -315,8 +316,8 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") { | |||
| 
 | ||||
|         auto output_buffer = std::make_shared<std::vector<u8>>(Memory::PAGE_SIZE); | ||||
|         VAddr target_address = 0x10000000; | ||||
|         auto result = process->vm_manager.MapMemoryBlock( | ||||
|             target_address, output_buffer, 0, output_buffer->size(), MemoryState::Private); | ||||
|         auto result = process->vm_manager.MapBackingMemory( | ||||
|             target_address, output_buffer->data(), output_buffer->size(), MemoryState::Private); | ||||
|         REQUIRE(result.Code() == RESULT_SUCCESS); | ||||
| 
 | ||||
|         input[0] = IPC::MakeHeader(0, 0, 2); | ||||
|  | @ -344,8 +345,8 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") { | |||
| 
 | ||||
|         auto output_buffer = std::make_shared<std::vector<u8>>(Memory::PAGE_SIZE); | ||||
|         VAddr target_address = 0x10000000; | ||||
|         auto result = process->vm_manager.MapMemoryBlock( | ||||
|             target_address, output_buffer, 0, output_buffer->size(), MemoryState::Private); | ||||
|         auto result = process->vm_manager.MapBackingMemory( | ||||
|             target_address, output_buffer->data(), output_buffer->size(), MemoryState::Private); | ||||
|         REQUIRE(result.Code() == RESULT_SUCCESS); | ||||
| 
 | ||||
|         const u32_le input_cmdbuff[]{ | ||||
|  |  | |||
|  | @ -14,23 +14,23 @@ TEST_CASE("Memory Basics", "[kernel][memory]") { | |||
|     SECTION("mapping memory") { | ||||
|         // Because of the PageTable, Kernel::VMManager is too big to be created on the stack.
 | ||||
|         auto manager = std::make_unique<Kernel::VMManager>(); | ||||
|         auto result = manager->MapMemoryBlock(Memory::HEAP_VADDR, block, 0, block->size(), | ||||
|                                               Kernel::MemoryState::Private); | ||||
|         auto result = manager->MapBackingMemory(Memory::HEAP_VADDR, block->data(), block->size(), | ||||
|                                                 Kernel::MemoryState::Private); | ||||
|         REQUIRE(result.Code() == RESULT_SUCCESS); | ||||
| 
 | ||||
|         auto vma = manager->FindVMA(Memory::HEAP_VADDR); | ||||
|         CHECK(vma != manager->vma_map.end()); | ||||
|         CHECK(vma->second.size == block->size()); | ||||
|         CHECK(vma->second.type == Kernel::VMAType::AllocatedMemoryBlock); | ||||
|         CHECK(vma->second.backing_block == block); | ||||
|         CHECK(vma->second.type == Kernel::VMAType::BackingMemory); | ||||
|         CHECK(vma->second.backing_memory == block->data()); | ||||
|         CHECK(vma->second.meminfo_state == Kernel::MemoryState::Private); | ||||
|     } | ||||
| 
 | ||||
|     SECTION("unmapping memory") { | ||||
|         // Because of the PageTable, Kernel::VMManager is too big to be created on the stack.
 | ||||
|         auto manager = std::make_unique<Kernel::VMManager>(); | ||||
|         auto result = manager->MapMemoryBlock(Memory::HEAP_VADDR, block, 0, block->size(), | ||||
|                                               Kernel::MemoryState::Private); | ||||
|         auto result = manager->MapBackingMemory(Memory::HEAP_VADDR, block->data(), block->size(), | ||||
|                                                 Kernel::MemoryState::Private); | ||||
|         REQUIRE(result.Code() == RESULT_SUCCESS); | ||||
| 
 | ||||
|         ResultCode code = manager->UnmapRange(Memory::HEAP_VADDR, block->size()); | ||||
|  | @ -39,14 +39,14 @@ TEST_CASE("Memory Basics", "[kernel][memory]") { | |||
|         auto vma = manager->FindVMA(Memory::HEAP_VADDR); | ||||
|         CHECK(vma != manager->vma_map.end()); | ||||
|         CHECK(vma->second.type == Kernel::VMAType::Free); | ||||
|         CHECK(vma->second.backing_block == nullptr); | ||||
|         CHECK(vma->second.backing_memory == nullptr); | ||||
|     } | ||||
| 
 | ||||
|     SECTION("changing memory permissions") { | ||||
|         // Because of the PageTable, Kernel::VMManager is too big to be created on the stack.
 | ||||
|         auto manager = std::make_unique<Kernel::VMManager>(); | ||||
|         auto result = manager->MapMemoryBlock(Memory::HEAP_VADDR, block, 0, block->size(), | ||||
|                                               Kernel::MemoryState::Private); | ||||
|         auto result = manager->MapBackingMemory(Memory::HEAP_VADDR, block->data(), block->size(), | ||||
|                                                 Kernel::MemoryState::Private); | ||||
|         REQUIRE(result.Code() == RESULT_SUCCESS); | ||||
| 
 | ||||
|         ResultCode code = manager->ReprotectRange(Memory::HEAP_VADDR, block->size(), | ||||
|  | @ -64,8 +64,8 @@ TEST_CASE("Memory Basics", "[kernel][memory]") { | |||
|     SECTION("changing memory state") { | ||||
|         // Because of the PageTable, Kernel::VMManager is too big to be created on the stack.
 | ||||
|         auto manager = std::make_unique<Kernel::VMManager>(); | ||||
|         auto result = manager->MapMemoryBlock(Memory::HEAP_VADDR, block, 0, block->size(), | ||||
|                                               Kernel::MemoryState::Private); | ||||
|         auto result = manager->MapBackingMemory(Memory::HEAP_VADDR, block->data(), block->size(), | ||||
|                                                 Kernel::MemoryState::Private); | ||||
|         REQUIRE(result.Code() == RESULT_SUCCESS); | ||||
| 
 | ||||
|         ResultCode code = manager->ReprotectRange(Memory::HEAP_VADDR, block->size(), | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue