mirror of
https://github.com/yuzu-emu/yuzu-android.git
synced 2025-06-15 07:57:56 -05:00
kernel/svc: Implement svcUnmapProcessCodeMemory
Essentially performs the inverse of svcMapProcessCodeMemory. This unmaps the aliasing region first, then restores the general traits of the aliased memory. What this entails, is: - Restoring Read/Write permissions to the VMA. - Restoring its memory state to reflect it as a general heap memory region. - Clearing the memory attributes on the region.
This commit is contained in:
@ -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{};
|
||||
|
Reference in New Issue
Block a user