From 34b24a47e9515a6a80d1961fc2e83bcfc84b7889 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 14 Dec 2018 18:19:12 -0500 Subject: vm_manager: Add backing functionality for memory attributes Adds the barebones enumeration constants and functions in place to handle memory attributes, while also essentially leaving the attribute itself non-functional. --- src/core/hle/kernel/vm_manager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/core/hle/kernel/vm_manager.cpp') diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index d3b55a51e..ea3f59935 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp @@ -38,7 +38,7 @@ static const char* GetMemoryStateName(MemoryState state) { bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const { ASSERT(base + size == next.base); if (permissions != next.permissions || meminfo_state != next.meminfo_state || - type != next.type) { + attribute != next.attribute || type != next.type) { return false; } if (type == VMAType::AllocatedMemoryBlock && @@ -308,6 +308,7 @@ MemoryInfo VMManager::QueryMemory(VAddr address) const { if (IsValidHandle(vma)) { memory_info.base_address = vma->second.base; + memory_info.attributes = ToSvcMemoryAttribute(vma->second.attribute); memory_info.permission = static_cast(vma->second.permissions); memory_info.size = vma->second.size; memory_info.state = ToSvcMemoryState(vma->second.meminfo_state); -- cgit v1.2.3 From 4dc8a7da3f8ee53ba8a812141c03bec7b27b67bc Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 14 Dec 2018 20:59:08 -0500 Subject: vm_manager: Rename meminfo_state to state This is shorter and more concise. This also removes the now-innaccurate comment, as it's not returned wholesale to svcQueryMemory anymore. --- src/core/hle/kernel/vm_manager.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/core/hle/kernel/vm_manager.cpp') diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index ea3f59935..252f92df2 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp @@ -37,8 +37,8 @@ static const char* GetMemoryStateName(MemoryState state) { bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const { ASSERT(base + size == next.base); - if (permissions != next.permissions || meminfo_state != next.meminfo_state || - attribute != next.attribute || type != next.type) { + if (permissions != next.permissions || state != next.state || attribute != next.attribute || + type != next.type) { return false; } if (type == VMAType::AllocatedMemoryBlock && @@ -115,7 +115,7 @@ ResultVal VMManager::MapMemoryBlock(VAddr target, final_vma.type = VMAType::AllocatedMemoryBlock; final_vma.permissions = VMAPermission::ReadWrite; - final_vma.meminfo_state = state; + final_vma.state = state; final_vma.backing_block = std::move(block); final_vma.offset = offset; UpdatePageTableForVMA(final_vma); @@ -140,7 +140,7 @@ ResultVal VMManager::MapBackingMemory(VAddr target, u8* me final_vma.type = VMAType::BackingMemory; final_vma.permissions = VMAPermission::ReadWrite; - final_vma.meminfo_state = state; + final_vma.state = state; final_vma.backing_memory = memory; UpdatePageTableForVMA(final_vma); @@ -177,7 +177,7 @@ ResultVal VMManager::MapMMIO(VAddr target, PAddr paddr, u6 final_vma.type = VMAType::MMIO; final_vma.permissions = VMAPermission::ReadWrite; - final_vma.meminfo_state = state; + final_vma.state = state; final_vma.paddr = paddr; final_vma.mmio_handler = std::move(mmio_handler); UpdatePageTableForVMA(final_vma); @@ -189,7 +189,7 @@ VMManager::VMAIter VMManager::Unmap(VMAIter vma_handle) { VirtualMemoryArea& vma = vma_handle->second; vma.type = VMAType::Free; vma.permissions = VMAPermission::None; - vma.meminfo_state = MemoryState::Unmapped; + vma.state = MemoryState::Unmapped; vma.backing_block = nullptr; vma.offset = 0; @@ -311,7 +311,7 @@ MemoryInfo VMManager::QueryMemory(VAddr address) const { memory_info.attributes = ToSvcMemoryAttribute(vma->second.attribute); memory_info.permission = static_cast(vma->second.permissions); memory_info.size = vma->second.size; - memory_info.state = ToSvcMemoryState(vma->second.meminfo_state); + memory_info.state = ToSvcMemoryState(vma->second.state); } else { memory_info.base_address = address_space_end; memory_info.permission = static_cast(VMAPermission::None); @@ -365,7 +365,7 @@ void VMManager::LogLayout() const { (u8)vma.permissions & (u8)VMAPermission::Read ? 'R' : '-', (u8)vma.permissions & (u8)VMAPermission::Write ? 'W' : '-', (u8)vma.permissions & (u8)VMAPermission::Execute ? 'X' : '-', - GetMemoryStateName(vma.meminfo_state)); + GetMemoryStateName(vma.state)); } } -- cgit v1.2.3 From 603cc72168b2165a0aa77a39a14ca63a879cf8f9 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 15 Dec 2018 13:49:40 -0500 Subject: vm_manager: Add member function for checking a memory range adheres to certain attributes, permissions and states --- src/core/hle/kernel/vm_manager.cpp | 60 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) (limited to 'src/core/hle/kernel/vm_manager.cpp') diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index 252f92df2..02504d750 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp @@ -592,6 +592,66 @@ void VMManager::ClearPageTable() { Memory::PageType::Unmapped); } +VMManager::CheckResults VMManager::CheckRangeState(VAddr address, u64 size, MemoryState state_mask, + MemoryState state, VMAPermission permission_mask, + VMAPermission permissions, + MemoryAttribute attribute_mask, + MemoryAttribute attribute, + MemoryAttribute ignore_mask) const { + auto iter = FindVMA(address); + + // If we don't have a valid VMA handle at this point, then it means this is + // being called with an address outside of the address space, which is definitely + // indicative of a bug, as this function only operates on mapped memory regions. + DEBUG_ASSERT(IsValidHandle(iter)); + + const VAddr end_address = address + size - 1; + const MemoryAttribute initial_attributes = iter->second.attribute; + const VMAPermission initial_permissions = iter->second.permissions; + const MemoryState initial_state = iter->second.state; + + while (true) { + // The iterator should be valid throughout the traversal. Hitting the end of + // the mapped VMA regions is unquestionably indicative of a bug. + DEBUG_ASSERT(IsValidHandle(iter)); + + const auto& vma = iter->second; + + if (vma.state != initial_state) { + return ERR_INVALID_ADDRESS_STATE; + } + + if ((vma.state & state_mask) != state) { + return ERR_INVALID_ADDRESS_STATE; + } + + if (vma.permissions != initial_permissions) { + return ERR_INVALID_ADDRESS_STATE; + } + + if ((vma.permissions & permission_mask) != permissions) { + return ERR_INVALID_ADDRESS_STATE; + } + + if ((vma.attribute | ignore_mask) != (initial_attributes | ignore_mask)) { + return ERR_INVALID_ADDRESS_STATE; + } + + if ((vma.attribute & attribute_mask) != attribute) { + return ERR_INVALID_ADDRESS_STATE; + } + + if (end_address <= vma.EndAddress()) { + break; + } + + ++iter; + } + + return MakeResult( + std::make_tuple(initial_state, initial_permissions, initial_attributes & ~ignore_mask)); +} + u64 VMManager::GetTotalMemoryUsage() const { LOG_WARNING(Kernel, "(STUBBED) called"); return 0xF8000000; -- cgit v1.2.3 From 622242e3451fd562425f67317f3f0d7855eb5741 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 15 Dec 2018 14:29:39 -0500 Subject: vm_manager: Add member function for setting memory attributes across an address range This puts the backing functionality for svcSetMemoryAttribute in place, which will be utilized in a following change. --- src/core/hle/kernel/vm_manager.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'src/core/hle/kernel/vm_manager.cpp') diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index 02504d750..f39e096ca 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp @@ -322,6 +322,34 @@ MemoryInfo VMManager::QueryMemory(VAddr address) const { return memory_info; } +ResultCode VMManager::SetMemoryAttribute(VAddr address, u64 size, MemoryAttribute mask, + MemoryAttribute attribute) { + constexpr auto ignore_mask = MemoryAttribute::Uncached | MemoryAttribute::DeviceMapped; + constexpr auto attribute_mask = ~ignore_mask; + + const auto result = CheckRangeState( + address, size, MemoryState::FlagUncached, MemoryState::FlagUncached, VMAPermission::None, + VMAPermission::None, attribute_mask, MemoryAttribute::None, ignore_mask); + + if (result.Failed()) { + return result.Code(); + } + + const auto [prev_state, prev_permissions, prev_attributes] = *result; + const auto new_attribute = (prev_attributes & ~mask) | (mask & attribute); + + const auto carve_result = CarveVMARange(address, size); + if (carve_result.Failed()) { + return carve_result.Code(); + } + + auto vma_iter = *carve_result; + vma_iter->second.attribute = new_attribute; + + MergeAdjacent(vma_iter); + return RESULT_SUCCESS; +} + ResultCode VMManager::MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size, MemoryState state) { const auto vma = FindVMA(src_addr); -- cgit v1.2.3