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:
bunnei 2022-04-12 11:23:20 -07:00 committed by GitHub
commit dc2dd5d5a6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 34 additions and 15 deletions

View file

@ -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) {
if (icache_invalidation_strategy == ICacheInvalidationStrategy::InvalidateRange) {
system.InvalidateCpuInstructionCacheRange(dst_address, size); 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;
} }

View file

@ -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);

View file

@ -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

View file

@ -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;
} }