Merge pull request #8178 from tech-ticks/skyline-icache-fix
hle: kernel: Invalidate entire icache in UnmapProcessMemory and UnmapCodeMemory (fixes #8174)
This commit is contained in:
commit
dc2dd5d5a6
|
@ -346,7 +346,8 @@ ResultCode KPageTable::MapCodeMemory(VAddr dst_address, VAddr src_address, std::
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode KPageTable::UnmapCodeMemory(VAddr dst_address, VAddr src_address, std::size_t size) {
|
ResultCode KPageTable::UnmapCodeMemory(VAddr dst_address, VAddr src_address, std::size_t size,
|
||||||
|
ICacheInvalidationStrategy icache_invalidation_strategy) {
|
||||||
// Validate the mapping request.
|
// Validate the mapping request.
|
||||||
R_UNLESS(this->CanContain(dst_address, size, KMemoryState::AliasCode),
|
R_UNLESS(this->CanContain(dst_address, size, KMemoryState::AliasCode),
|
||||||
ResultInvalidMemoryRegion);
|
ResultInvalidMemoryRegion);
|
||||||
|
@ -396,7 +397,11 @@ ResultCode KPageTable::UnmapCodeMemory(VAddr dst_address, VAddr src_address, std
|
||||||
bool reprotected_pages = false;
|
bool reprotected_pages = false;
|
||||||
SCOPE_EXIT({
|
SCOPE_EXIT({
|
||||||
if (reprotected_pages && any_code_pages) {
|
if (reprotected_pages && any_code_pages) {
|
||||||
system.InvalidateCpuInstructionCacheRange(dst_address, size);
|
if (icache_invalidation_strategy == ICacheInvalidationStrategy::InvalidateRange) {
|
||||||
|
system.InvalidateCpuInstructionCacheRange(dst_address, size);
|
||||||
|
} else {
|
||||||
|
system.InvalidateCpuInstructionCaches();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -563,6 +568,8 @@ ResultCode KPageTable::UnmapProcessMemory(VAddr dst_addr, std::size_t size,
|
||||||
block_manager->Update(dst_addr, num_pages, KMemoryState::Free, KMemoryPermission::None,
|
block_manager->Update(dst_addr, num_pages, KMemoryState::Free, KMemoryPermission::None,
|
||||||
KMemoryAttribute::None);
|
KMemoryAttribute::None);
|
||||||
|
|
||||||
|
system.InvalidateCpuInstructionCaches();
|
||||||
|
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,8 @@ class KMemoryBlockManager;
|
||||||
|
|
||||||
class KPageTable final {
|
class KPageTable final {
|
||||||
public:
|
public:
|
||||||
|
enum class ICacheInvalidationStrategy : u32 { InvalidateRange, InvalidateAll };
|
||||||
|
|
||||||
YUZU_NON_COPYABLE(KPageTable);
|
YUZU_NON_COPYABLE(KPageTable);
|
||||||
YUZU_NON_MOVEABLE(KPageTable);
|
YUZU_NON_MOVEABLE(KPageTable);
|
||||||
|
|
||||||
|
@ -38,7 +40,8 @@ public:
|
||||||
ResultCode MapProcessCode(VAddr addr, std::size_t pages_count, KMemoryState state,
|
ResultCode MapProcessCode(VAddr addr, std::size_t pages_count, KMemoryState state,
|
||||||
KMemoryPermission perm);
|
KMemoryPermission perm);
|
||||||
ResultCode MapCodeMemory(VAddr dst_address, VAddr src_address, std::size_t size);
|
ResultCode MapCodeMemory(VAddr dst_address, VAddr src_address, std::size_t size);
|
||||||
ResultCode UnmapCodeMemory(VAddr dst_address, VAddr src_address, std::size_t size);
|
ResultCode UnmapCodeMemory(VAddr dst_address, VAddr src_address, std::size_t size,
|
||||||
|
ICacheInvalidationStrategy icache_invalidation_strategy);
|
||||||
ResultCode UnmapProcessMemory(VAddr dst_addr, std::size_t size, KPageTable& src_page_table,
|
ResultCode UnmapProcessMemory(VAddr dst_addr, std::size_t size, KPageTable& src_page_table,
|
||||||
VAddr src_addr);
|
VAddr src_addr);
|
||||||
ResultCode MapPhysicalMemory(VAddr addr, std::size_t size);
|
ResultCode MapPhysicalMemory(VAddr addr, std::size_t size);
|
||||||
|
|
|
@ -1713,7 +1713,8 @@ static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_ha
|
||||||
return ResultInvalidMemoryRegion;
|
return ResultInvalidMemoryRegion;
|
||||||
}
|
}
|
||||||
|
|
||||||
return page_table.UnmapCodeMemory(dst_address, src_address, size);
|
return page_table.UnmapCodeMemory(dst_address, src_address, size,
|
||||||
|
KPageTable::ICacheInvalidationStrategy::InvalidateAll);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Exits the current process
|
/// Exits the current process
|
||||||
|
|
|
@ -389,8 +389,12 @@ public:
|
||||||
|
|
||||||
if (bss_size) {
|
if (bss_size) {
|
||||||
auto block_guard = detail::ScopeExit([&] {
|
auto block_guard = detail::ScopeExit([&] {
|
||||||
page_table.UnmapCodeMemory(addr + nro_size, bss_addr, bss_size);
|
page_table.UnmapCodeMemory(
|
||||||
page_table.UnmapCodeMemory(addr, nro_addr, nro_size);
|
addr + nro_size, bss_addr, bss_size,
|
||||||
|
Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange);
|
||||||
|
page_table.UnmapCodeMemory(
|
||||||
|
addr, nro_addr, nro_size,
|
||||||
|
Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange);
|
||||||
});
|
});
|
||||||
|
|
||||||
const ResultCode result{
|
const ResultCode result{
|
||||||
|
@ -570,17 +574,21 @@ public:
|
||||||
auto& page_table{system.CurrentProcess()->PageTable()};
|
auto& page_table{system.CurrentProcess()->PageTable()};
|
||||||
|
|
||||||
if (info.bss_size != 0) {
|
if (info.bss_size != 0) {
|
||||||
CASCADE_CODE(page_table.UnmapCodeMemory(info.nro_address + info.text_size +
|
CASCADE_CODE(page_table.UnmapCodeMemory(
|
||||||
info.ro_size + info.data_size,
|
info.nro_address + info.text_size + info.ro_size + info.data_size, info.bss_address,
|
||||||
info.bss_address, info.bss_size));
|
info.bss_size, Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange));
|
||||||
}
|
}
|
||||||
|
|
||||||
CASCADE_CODE(page_table.UnmapCodeMemory(info.nro_address + info.text_size + info.ro_size,
|
CASCADE_CODE(page_table.UnmapCodeMemory(
|
||||||
info.src_addr + info.text_size + info.ro_size,
|
info.nro_address + info.text_size + info.ro_size,
|
||||||
info.data_size));
|
info.src_addr + info.text_size + info.ro_size, info.data_size,
|
||||||
CASCADE_CODE(page_table.UnmapCodeMemory(info.nro_address + info.text_size,
|
Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange));
|
||||||
info.src_addr + info.text_size, info.ro_size));
|
CASCADE_CODE(page_table.UnmapCodeMemory(
|
||||||
CASCADE_CODE(page_table.UnmapCodeMemory(info.nro_address, info.src_addr, info.text_size));
|
info.nro_address + info.text_size, info.src_addr + info.text_size, info.ro_size,
|
||||||
|
Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange));
|
||||||
|
CASCADE_CODE(page_table.UnmapCodeMemory(
|
||||||
|
info.nro_address, info.src_addr, info.text_size,
|
||||||
|
Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange));
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in New Issue