summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel/vm_manager.cpp
diff options
context:
space:
mode:
authorLioncash <mathew1800@gmail.com>2019-04-12 06:38:54 +0200
committerLioncash <mathew1800@gmail.com>2019-04-13 03:56:03 +0200
commit4d293bb5cbb65d3551dd0d22e92b7065a7ebba14 (patch)
treed57782959b51296eef132a721a1b6d0600e8e117 /src/core/hle/kernel/vm_manager.cpp
parentkernel/svc: Implement svcMapProcessCodeMemory (diff)
downloadyuzu-4d293bb5cbb65d3551dd0d22e92b7065a7ebba14.tar
yuzu-4d293bb5cbb65d3551dd0d22e92b7065a7ebba14.tar.gz
yuzu-4d293bb5cbb65d3551dd0d22e92b7065a7ebba14.tar.bz2
yuzu-4d293bb5cbb65d3551dd0d22e92b7065a7ebba14.tar.lz
yuzu-4d293bb5cbb65d3551dd0d22e92b7065a7ebba14.tar.xz
yuzu-4d293bb5cbb65d3551dd0d22e92b7065a7ebba14.tar.zst
yuzu-4d293bb5cbb65d3551dd0d22e92b7065a7ebba14.zip
Diffstat (limited to 'src/core/hle/kernel/vm_manager.cpp')
-rw-r--r--src/core/hle/kernel/vm_manager.cpp51
1 files changed, 51 insertions, 0 deletions
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index 76b491c47..f0c0c12fc 100644
--- a/src/core/hle/kernel/vm_manager.cpp
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -331,6 +331,57 @@ ResultCode VMManager::MapCodeMemory(VAddr dst_address, VAddr src_address, u64 si
return ReprotectRange(dst_address, size, VMAPermission::Read);
}
+ResultCode VMManager::UnmapCodeMemory(VAddr dst_address, VAddr src_address, u64 size) {
+ constexpr auto ignore_attribute = MemoryAttribute::LockedForIPC | MemoryAttribute::DeviceMapped;
+ const auto src_check_result = CheckRangeState(
+ src_address, size, MemoryState::All, MemoryState::Heap, VMAPermission::None,
+ VMAPermission::None, MemoryAttribute::Mask, MemoryAttribute::Locked, ignore_attribute);
+
+ if (src_check_result.Failed()) {
+ return src_check_result.Code();
+ }
+
+ // Yes, the kernel only checks the first page of the region.
+ const auto dst_check_result =
+ CheckRangeState(dst_address, Memory::PAGE_SIZE, MemoryState::FlagModule,
+ MemoryState::FlagModule, VMAPermission::None, VMAPermission::None,
+ MemoryAttribute::Mask, MemoryAttribute::None, ignore_attribute);
+
+ if (dst_check_result.Failed()) {
+ return dst_check_result.Code();
+ }
+
+ const auto dst_memory_state = std::get<MemoryState>(*dst_check_result);
+ const auto dst_contiguous_check_result = CheckRangeState(
+ dst_address, size, MemoryState::All, dst_memory_state, VMAPermission::None,
+ VMAPermission::None, MemoryAttribute::Mask, MemoryAttribute::None, ignore_attribute);
+
+ if (dst_contiguous_check_result.Failed()) {
+ return dst_contiguous_check_result.Code();
+ }
+
+ const auto unmap_result = UnmapRange(dst_address, size);
+ if (unmap_result.IsError()) {
+ return unmap_result;
+ }
+
+ // With the mirrored portion unmapped, restore the original region's traits.
+ const auto src_vma_result = CarveVMARange(src_address, size);
+ if (src_vma_result.Failed()) {
+ return src_vma_result.Code();
+ }
+ auto src_vma_iter = *src_vma_result;
+ src_vma_iter->second.state = MemoryState::Heap;
+ src_vma_iter->second.attribute = MemoryAttribute::None;
+ Reprotect(src_vma_iter, VMAPermission::ReadWrite);
+
+ if (dst_memory_state == MemoryState::ModuleCode) {
+ Core::System::GetInstance().InvalidateCpuInstructionCaches();
+ }
+
+ return unmap_result;
+}
+
MemoryInfo VMManager::QueryMemory(VAddr address) const {
const auto vma = FindVMA(address);
MemoryInfo memory_info{};