From 7a564b904bcd97f220d3c38a2723d22b50f9b4e3 Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Thu, 8 Nov 2018 12:14:14 -0500 Subject: [PATCH 1/5] tests: use VMManager::MapBackingMemory --- src/tests/core/hle/kernel/hle_ipc.cpp | 25 +++++++++++++------------ src/tests/core/memory/vm_manager.cpp | 20 ++++++++++---------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/tests/core/hle/kernel/hle_ipc.cpp b/src/tests/core/hle/kernel/hle_ipc.cpp index 2e404a32d..86de36db4 100644 --- a/src/tests/core/hle/kernel/hle_ipc.cpp +++ b/src/tests/core/hle/kernel/hle_ipc.cpp @@ -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>(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>(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[]{ diff --git a/src/tests/core/memory/vm_manager.cpp b/src/tests/core/memory/vm_manager.cpp index 00d03dbc3..9fb365df2 100644 --- a/src/tests/core/memory/vm_manager.cpp +++ b/src/tests/core/memory/vm_manager.cpp @@ -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(); - 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(); - 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()); @@ -45,8 +45,8 @@ TEST_CASE("Memory Basics", "[kernel][memory]") { SECTION("changing memory permissions") { // Because of the PageTable, Kernel::VMManager is too big to be created on the stack. auto manager = std::make_unique(); - 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(); - 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(), From 0b8d2ecabefe556be1cc0c78d4ee170f00bbced2 Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Thu, 8 Nov 2018 13:53:20 -0500 Subject: [PATCH 2/5] IPC: store mapped buffer info in session context So that it doesn't have to scan over the request buffer again on reply. This also allow us to store additional info like memory mapping --- src/core/hle/kernel/ipc.cpp | 115 +++++++++------------------ src/core/hle/kernel/ipc.h | 14 +++- src/core/hle/kernel/server_session.h | 4 + src/core/hle/kernel/svc.cpp | 8 +- 4 files changed, 59 insertions(+), 82 deletions(-) diff --git a/src/core/hle/kernel/ipc.cpp b/src/core/hle/kernel/ipc.cpp index 779979fc7..d62889e5b 100644 --- a/src/core/hle/kernel/ipc.cpp +++ b/src/core/hle/kernel/ipc.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #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& dst_cmd_buf, - const std::size_t dst_command_size, std::size_t& target_index, - SharedPtr src_process, SharedPtr 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(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 src_thread, SharedPtr dst_thread, - VAddr src_address, VAddr dst_address, bool reply) { + VAddr src_address, VAddr dst_address, + std::vector& 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 src_thread, SharedPtr 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 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 src_thread, SharedPtrtarget_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; @@ -246,6 +202,9 @@ ResultCode TranslateCommandBuffer(SharedPtr src_thread, SharedPtrvm_manager.MapMemoryBlockToBase( Memory::IPC_MAPPING_VADDR, Memory::IPC_MAPPING_SIZE, reserve_buffer, 0, static_cast(reserve_buffer->size()), Kernel::MemoryState::Reserved); + + mapped_buffer_context.push_back({permissions, size, source_address, target_address}); + break; } default: diff --git a/src/core/hle/kernel/ipc.h b/src/core/hle/kernel/ipc.h index d77fd1d1f..6ca4dbb6e 100644 --- a/src/core/hle/kernel/ipc.h +++ b/src/core/hle/kernel/ipc.h @@ -4,11 +4,23 @@ #pragma once +#include #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; +}; + /// Performs IPC command buffer translation from one process to another. ResultCode TranslateCommandBuffer(SharedPtr src_thread, SharedPtr dst_thread, - VAddr src_address, VAddr dst_address, bool reply); + VAddr src_address, VAddr dst_address, + std::vector& mapped_buffer_context, + bool reply); } // namespace Kernel diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h index 18411e417..956deba3f 100644 --- a/src/core/hle/kernel/server_session.h +++ b/src/core/hle/kernel/server_session.h @@ -8,6 +8,7 @@ #include #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 currently_handling; + /// A temporary list holding mapped buffer info from IPC request, used for during IPC reply + std::vector mapped_buffer_context; + private: explicit ServerSession(KernelSystem& kernel); ~ServerSession() override; diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 53728a66d..59771e14f 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -600,8 +600,9 @@ static ResultCode ReceiveIPCRequest(SharedPtr 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. From 7f9873d7ece102eb9455b467b447925790f9f9d5 Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Thu, 8 Nov 2018 14:05:54 -0500 Subject: [PATCH 3/5] VMManager: change MapMemoryBlockToBase to use raw backing memory And let ServerSession.MappedBufferContext hold the mapped memory --- src/core/hle/kernel/ipc.cpp | 32 ++++++++++++++++-------------- src/core/hle/kernel/ipc.h | 4 ++++ src/core/hle/kernel/vm_manager.cpp | 7 +++---- src/core/hle/kernel/vm_manager.h | 8 +++----- 4 files changed, 27 insertions(+), 24 deletions(-) diff --git a/src/core/hle/kernel/ipc.cpp b/src/core/hle/kernel/ipc.cpp index d62889e5b..4daee787d 100644 --- a/src/core/hle/kernel/ipc.cpp +++ b/src/core/hle/kernel/ipc.cpp @@ -181,29 +181,31 @@ ResultCode TranslateCommandBuffer(SharedPtr src_thread, SharedPtr>(Memory::PAGE_SIZE); - dst_process->vm_manager.MapMemoryBlockToBase( - Memory::IPC_MAPPING_VADDR, Memory::IPC_MAPPING_SIZE, reserve_buffer, 0, - static_cast(reserve_buffer->size()), Kernel::MemoryState::Reserved); + auto reserve_buffer = std::make_unique(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>(num_pages * Memory::PAGE_SIZE); - Memory::ReadBlock(*src_process, source_address, buffer->data() + page_offset, size); + auto buffer = std::make_unique(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(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(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}); + mapped_buffer_context.push_back({permissions, size, source_address, target_address, + std::move(buffer), std::move(reserve_buffer)}); break; } diff --git a/src/core/hle/kernel/ipc.h b/src/core/hle/kernel/ipc.h index 6ca4dbb6e..9f2d57a96 100644 --- a/src/core/hle/kernel/ipc.h +++ b/src/core/hle/kernel/ipc.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include "common/common_types.h" #include "core/hle/ipc.h" @@ -16,6 +17,9 @@ struct MappedBufferContext { u32 size; VAddr source_address; VAddr target_address; + + std::unique_ptr buffer; + std::unique_ptr reserve_buffer; }; /// Performs IPC command buffer translation from one process to another. diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index bab8891bc..1b4577400 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp @@ -93,9 +93,8 @@ ResultVal VMManager::MapMemoryBlock(VAddr target, return MakeResult(MergeAdjacent(vma_handle)); } -ResultVal VMManager::MapMemoryBlockToBase(VAddr base, u32 region_size, - std::shared_ptr> block, - std::size_t offset, u32 size, MemoryState state) { +ResultVal 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 +114,7 @@ ResultVal 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(); diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h index 5464ad50b..865c3ee99 100644 --- a/src/core/hle/kernel/vm_manager.h +++ b/src/core/hle/kernel/vm_manager.h @@ -150,15 +150,13 @@ public: * * @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 MapMemoryBlockToBase(VAddr base, u32 region_size, - std::shared_ptr> block, - std::size_t offset, u32 size, MemoryState state); + ResultVal MapBackingMemoryToBase(VAddr base, u32 region_size, u8* memory, u32 size, + MemoryState state); /** * Maps an unmanaged host memory pointer at a given address. * From b6ab4e466b628487413ce83a467ab152788b45ea Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Thu, 8 Nov 2018 14:13:23 -0500 Subject: [PATCH 4/5] VMManager: remove all backing block related functions The shared_ptr type backing memory is unused now, and is not expected to be used in the future --- src/core/hle/kernel/vm_manager.cpp | 46 ---------------------------- src/core/hle/kernel/vm_manager.h | 27 ---------------- src/core/memory.cpp | 3 -- src/tests/core/memory/vm_manager.cpp | 2 +- 4 files changed, 1 insertion(+), 77 deletions(-) diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index 1b4577400..bf6d36cd7 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp @@ -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,28 +67,6 @@ VMManager::VMAHandle VMManager::FindVMA(VAddr target) const { } } -ResultVal VMManager::MapMemoryBlock(VAddr target, - std::shared_ptr> 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(MergeAdjacent(vma_handle)); -} - ResultVal VMManager::MapBackingMemoryToBase(VAddr base, u32 region_size, u8* memory, u32 size, MemoryState state) { @@ -197,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; @@ -246,17 +218,6 @@ ResultCode VMManager::ReprotectRange(VAddr target, u32 size, VMAPermission new_p return RESULT_SUCCESS; } -void VMManager::RefreshMemoryBlockMappings(const std::vector* 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; @@ -355,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; @@ -395,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; diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h index 865c3ee99..db48d7aed 100644 --- a/src/core/hle/kernel/vm_manager.h +++ b/src/core/hle/kernel/vm_manager.h @@ -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> 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,18 +124,6 @@ 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 MapMemoryBlock(VAddr target, std::shared_ptr> 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. * @@ -203,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* block); - /// Dumps the address space layout to the log, for debugging void LogLayout(Log::Level log_level) const; diff --git a/src/core/memory.cpp b/src/core/memory.cpp index ed5a04c9a..6469aa80b 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -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; diff --git a/src/tests/core/memory/vm_manager.cpp b/src/tests/core/memory/vm_manager.cpp index 9fb365df2..775a254a7 100644 --- a/src/tests/core/memory/vm_manager.cpp +++ b/src/tests/core/memory/vm_manager.cpp @@ -39,7 +39,7 @@ 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") { From 95bbe2302b4592d46cb19fd7514ca7ac080479fb Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Fri, 16 Nov 2018 19:47:16 -0500 Subject: [PATCH 5/5] Kernel/IPC: fix mapped buffer target address --- src/core/hle/kernel/ipc.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/core/hle/kernel/ipc.cpp b/src/core/hle/kernel/ipc.cpp index 4daee787d..7a59f0301 100644 --- a/src/core/hle/kernel/ipc.cpp +++ b/src/core/hle/kernel/ipc.cpp @@ -204,8 +204,9 @@ ResultCode TranslateCommandBuffer(SharedPtr src_thread, SharedPtr