diff options
| author | 2022-04-08 21:31:56 +0200 | |
|---|---|---|
| committer | 2022-04-09 13:29:19 +0200 | |
| commit | 3b91d213b172a0f66ba421d4583f1bf1a3dbdca6 (patch) | |
| tree | b6c7d389b3217543cf2b40794bb3c15934039166 /src | |
| parent | Merge pull request #8162 from german77/bombslinger (diff) | |
| download | yuzu-3b91d213b172a0f66ba421d4583f1bf1a3dbdca6.tar.gz yuzu-3b91d213b172a0f66ba421d4583f1bf1a3dbdca6.tar.xz yuzu-3b91d213b172a0f66ba421d4583f1bf1a3dbdca6.zip | |
hle: kernel: Invalidate entire icache in UnmapProcessMemory and UnmapCodeMemory (fixes #8174)
Diffstat (limited to '')
| -rw-r--r-- | src/core/hle/kernel/k_page_table.cpp | 11 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_page_table.h | 5 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 3 | ||||
| -rw-r--r-- | src/core/hle/service/ldr/ldr.cpp | 30 |
4 files changed, 34 insertions, 15 deletions
diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp index 599013cf6..47ea3c89c 100644 --- a/src/core/hle/kernel/k_page_table.cpp +++ b/src/core/hle/kernel/k_page_table.cpp | |||
| @@ -346,7 +346,8 @@ ResultCode KPageTable::MapCodeMemory(VAddr dst_address, VAddr src_address, std:: | |||
| 346 | return ResultSuccess; | 346 | return ResultSuccess; |
| 347 | } | 347 | } |
| 348 | 348 | ||
| 349 | ResultCode KPageTable::UnmapCodeMemory(VAddr dst_address, VAddr src_address, std::size_t size) { | 349 | ResultCode KPageTable::UnmapCodeMemory(VAddr dst_address, VAddr src_address, std::size_t size, |
| 350 | ICacheInvalidationStrategy icache_invalidation_strategy) { | ||
| 350 | // Validate the mapping request. | 351 | // Validate the mapping request. |
| 351 | R_UNLESS(this->CanContain(dst_address, size, KMemoryState::AliasCode), | 352 | R_UNLESS(this->CanContain(dst_address, size, KMemoryState::AliasCode), |
| 352 | ResultInvalidMemoryRegion); | 353 | ResultInvalidMemoryRegion); |
| @@ -396,7 +397,11 @@ ResultCode KPageTable::UnmapCodeMemory(VAddr dst_address, VAddr src_address, std | |||
| 396 | bool reprotected_pages = false; | 397 | bool reprotected_pages = false; |
| 397 | SCOPE_EXIT({ | 398 | SCOPE_EXIT({ |
| 398 | if (reprotected_pages && any_code_pages) { | 399 | if (reprotected_pages && any_code_pages) { |
| 399 | system.InvalidateCpuInstructionCacheRange(dst_address, size); | 400 | if (icache_invalidation_strategy == ICacheInvalidationStrategy::InvalidateRange) { |
| 401 | system.InvalidateCpuInstructionCacheRange(dst_address, size); | ||
| 402 | } else { | ||
| 403 | system.InvalidateCpuInstructionCaches(); | ||
| 404 | } | ||
| 400 | } | 405 | } |
| 401 | }); | 406 | }); |
| 402 | 407 | ||
| @@ -563,6 +568,8 @@ ResultCode KPageTable::UnmapProcessMemory(VAddr dst_addr, std::size_t size, | |||
| 563 | block_manager->Update(dst_addr, num_pages, KMemoryState::Free, KMemoryPermission::None, | 568 | block_manager->Update(dst_addr, num_pages, KMemoryState::Free, KMemoryPermission::None, |
| 564 | KMemoryAttribute::None); | 569 | KMemoryAttribute::None); |
| 565 | 570 | ||
| 571 | system.InvalidateCpuInstructionCaches(); | ||
| 572 | |||
| 566 | return ResultSuccess; | 573 | return ResultSuccess; |
| 567 | } | 574 | } |
| 568 | 575 | ||
diff --git a/src/core/hle/kernel/k_page_table.h b/src/core/hle/kernel/k_page_table.h index bfabdf38c..dd6022975 100644 --- a/src/core/hle/kernel/k_page_table.h +++ b/src/core/hle/kernel/k_page_table.h | |||
| @@ -26,6 +26,8 @@ class KMemoryBlockManager; | |||
| 26 | 26 | ||
| 27 | class KPageTable final { | 27 | class KPageTable final { |
| 28 | public: | 28 | public: |
| 29 | enum class ICacheInvalidationStrategy : u32 { InvalidateRange, InvalidateAll }; | ||
| 30 | |||
| 29 | YUZU_NON_COPYABLE(KPageTable); | 31 | YUZU_NON_COPYABLE(KPageTable); |
| 30 | YUZU_NON_MOVEABLE(KPageTable); | 32 | YUZU_NON_MOVEABLE(KPageTable); |
| 31 | 33 | ||
| @@ -38,7 +40,8 @@ public: | |||
| 38 | ResultCode MapProcessCode(VAddr addr, std::size_t pages_count, KMemoryState state, | 40 | ResultCode MapProcessCode(VAddr addr, std::size_t pages_count, KMemoryState state, |
| 39 | KMemoryPermission perm); | 41 | KMemoryPermission perm); |
| 40 | ResultCode MapCodeMemory(VAddr dst_address, VAddr src_address, std::size_t size); | 42 | ResultCode MapCodeMemory(VAddr dst_address, VAddr src_address, std::size_t size); |
| 41 | ResultCode UnmapCodeMemory(VAddr dst_address, VAddr src_address, std::size_t size); | 43 | ResultCode UnmapCodeMemory(VAddr dst_address, VAddr src_address, std::size_t size, |
| 44 | ICacheInvalidationStrategy icache_invalidation_strategy); | ||
| 42 | ResultCode UnmapProcessMemory(VAddr dst_addr, std::size_t size, KPageTable& src_page_table, | 45 | ResultCode UnmapProcessMemory(VAddr dst_addr, std::size_t size, KPageTable& src_page_table, |
| 43 | VAddr src_addr); | 46 | VAddr src_addr); |
| 44 | ResultCode MapPhysicalMemory(VAddr addr, std::size_t size); | 47 | ResultCode MapPhysicalMemory(VAddr addr, std::size_t size); |
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 976d63234..0c86435b5 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -1713,7 +1713,8 @@ static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_ha | |||
| 1713 | return ResultInvalidMemoryRegion; | 1713 | return ResultInvalidMemoryRegion; |
| 1714 | } | 1714 | } |
| 1715 | 1715 | ||
| 1716 | return page_table.UnmapCodeMemory(dst_address, src_address, size); | 1716 | return page_table.UnmapCodeMemory(dst_address, src_address, size, |
| 1717 | KPageTable::ICacheInvalidationStrategy::InvalidateAll); | ||
| 1717 | } | 1718 | } |
| 1718 | 1719 | ||
| 1719 | /// Exits the current process | 1720 | /// Exits the current process |
diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index 2477c5612..cf727c167 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp | |||
| @@ -389,8 +389,12 @@ public: | |||
| 389 | 389 | ||
| 390 | if (bss_size) { | 390 | if (bss_size) { |
| 391 | auto block_guard = detail::ScopeExit([&] { | 391 | auto block_guard = detail::ScopeExit([&] { |
| 392 | page_table.UnmapCodeMemory(addr + nro_size, bss_addr, bss_size); | 392 | page_table.UnmapCodeMemory( |
| 393 | page_table.UnmapCodeMemory(addr, nro_addr, nro_size); | 393 | addr + nro_size, bss_addr, bss_size, |
| 394 | Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange); | ||
| 395 | page_table.UnmapCodeMemory( | ||
| 396 | addr, nro_addr, nro_size, | ||
| 397 | Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange); | ||
| 394 | }); | 398 | }); |
| 395 | 399 | ||
| 396 | const ResultCode result{ | 400 | const ResultCode result{ |
| @@ -570,17 +574,21 @@ public: | |||
| 570 | auto& page_table{system.CurrentProcess()->PageTable()}; | 574 | auto& page_table{system.CurrentProcess()->PageTable()}; |
| 571 | 575 | ||
| 572 | if (info.bss_size != 0) { | 576 | if (info.bss_size != 0) { |
| 573 | CASCADE_CODE(page_table.UnmapCodeMemory(info.nro_address + info.text_size + | 577 | CASCADE_CODE(page_table.UnmapCodeMemory( |
| 574 | info.ro_size + info.data_size, | 578 | info.nro_address + info.text_size + info.ro_size + info.data_size, info.bss_address, |
| 575 | info.bss_address, info.bss_size)); | 579 | info.bss_size, Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange)); |
| 576 | } | 580 | } |
| 577 | 581 | ||
| 578 | CASCADE_CODE(page_table.UnmapCodeMemory(info.nro_address + info.text_size + info.ro_size, | 582 | CASCADE_CODE(page_table.UnmapCodeMemory( |
| 579 | info.src_addr + info.text_size + info.ro_size, | 583 | info.nro_address + info.text_size + info.ro_size, |
| 580 | info.data_size)); | 584 | info.src_addr + info.text_size + info.ro_size, info.data_size, |
| 581 | CASCADE_CODE(page_table.UnmapCodeMemory(info.nro_address + info.text_size, | 585 | Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange)); |
| 582 | info.src_addr + info.text_size, info.ro_size)); | 586 | CASCADE_CODE(page_table.UnmapCodeMemory( |
| 583 | CASCADE_CODE(page_table.UnmapCodeMemory(info.nro_address, info.src_addr, info.text_size)); | 587 | info.nro_address + info.text_size, info.src_addr + info.text_size, info.ro_size, |
| 588 | Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange)); | ||
| 589 | CASCADE_CODE(page_table.UnmapCodeMemory( | ||
| 590 | info.nro_address, info.src_addr, info.text_size, | ||
| 591 | Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange)); | ||
| 584 | return ResultSuccess; | 592 | return ResultSuccess; |
| 585 | } | 593 | } |
| 586 | 594 | ||