diff options
| author | 2023-12-13 15:32:25 -0500 | |
|---|---|---|
| committer | 2023-12-14 23:44:33 -0500 | |
| commit | 8ad5f2c50648c333c3c46f89533e200a39bf6ca8 (patch) | |
| tree | 00cfb8d70b13db1016006a8a9de99137a9736c08 /src | |
| parent | Merge pull request #12354 from liamwhite/mackage-panager (diff) | |
| download | yuzu-8ad5f2c50648c333c3c46f89533e200a39bf6ca8.tar.gz yuzu-8ad5f2c50648c333c3c46f89533e200a39bf6ca8.tar.xz yuzu-8ad5f2c50648c333c3c46f89533e200a39bf6ca8.zip | |
common: use memory holepunching when clearing memory
Diffstat (limited to 'src')
| -rw-r--r-- | src/common/host_memory.cpp | 38 | ||||
| -rw-r--r-- | src/common/host_memory.h | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_memory_manager.cpp | 5 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_page_table_base.cpp | 14 |
4 files changed, 42 insertions, 17 deletions
diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp index 4bfc64f2d..e540375b8 100644 --- a/src/common/host_memory.cpp +++ b/src/common/host_memory.cpp | |||
| @@ -11,10 +11,6 @@ | |||
| 11 | 11 | ||
| 12 | #elif defined(__linux__) || defined(__FreeBSD__) // ^^^ Windows ^^^ vvv Linux vvv | 12 | #elif defined(__linux__) || defined(__FreeBSD__) // ^^^ Windows ^^^ vvv Linux vvv |
| 13 | 13 | ||
| 14 | #ifdef ANDROID | ||
| 15 | #include <android/sharedmem.h> | ||
| 16 | #endif | ||
| 17 | |||
| 18 | #ifndef _GNU_SOURCE | 14 | #ifndef _GNU_SOURCE |
| 19 | #define _GNU_SOURCE | 15 | #define _GNU_SOURCE |
| 20 | #endif | 16 | #endif |
| @@ -193,6 +189,11 @@ public: | |||
| 193 | } | 189 | } |
| 194 | } | 190 | } |
| 195 | 191 | ||
| 192 | bool ClearBackingRegion(size_t physical_offset, size_t length) { | ||
| 193 | // TODO: This does not seem to be possible on Windows. | ||
| 194 | return false; | ||
| 195 | } | ||
| 196 | |||
| 196 | void EnableDirectMappedAddress() { | 197 | void EnableDirectMappedAddress() { |
| 197 | // TODO | 198 | // TODO |
| 198 | UNREACHABLE(); | 199 | UNREACHABLE(); |
| @@ -442,9 +443,7 @@ public: | |||
| 442 | } | 443 | } |
| 443 | 444 | ||
| 444 | // Backing memory initialization | 445 | // Backing memory initialization |
| 445 | #ifdef ANDROID | 446 | #if defined(__FreeBSD__) && __FreeBSD__ < 13 |
| 446 | fd = ASharedMemory_create("HostMemory", backing_size); | ||
| 447 | #elif defined(__FreeBSD__) && __FreeBSD__ < 13 | ||
| 448 | // XXX Drop after FreeBSD 12.* reaches EOL on 2024-06-30 | 447 | // XXX Drop after FreeBSD 12.* reaches EOL on 2024-06-30 |
| 449 | fd = shm_open(SHM_ANON, O_RDWR, 0600); | 448 | fd = shm_open(SHM_ANON, O_RDWR, 0600); |
| 450 | #else | 449 | #else |
| @@ -455,7 +454,6 @@ public: | |||
| 455 | throw std::bad_alloc{}; | 454 | throw std::bad_alloc{}; |
| 456 | } | 455 | } |
| 457 | 456 | ||
| 458 | #ifndef ANDROID | ||
| 459 | // Defined to extend the file with zeros | 457 | // Defined to extend the file with zeros |
| 460 | int ret = ftruncate(fd, backing_size); | 458 | int ret = ftruncate(fd, backing_size); |
| 461 | if (ret != 0) { | 459 | if (ret != 0) { |
| @@ -463,7 +461,6 @@ public: | |||
| 463 | strerror(errno)); | 461 | strerror(errno)); |
| 464 | throw std::bad_alloc{}; | 462 | throw std::bad_alloc{}; |
| 465 | } | 463 | } |
| 466 | #endif | ||
| 467 | 464 | ||
| 468 | backing_base = static_cast<u8*>( | 465 | backing_base = static_cast<u8*>( |
| 469 | mmap(nullptr, backing_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)); | 466 | mmap(nullptr, backing_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)); |
| @@ -552,6 +549,19 @@ public: | |||
| 552 | ASSERT_MSG(ret == 0, "mprotect failed: {}", strerror(errno)); | 549 | ASSERT_MSG(ret == 0, "mprotect failed: {}", strerror(errno)); |
| 553 | } | 550 | } |
| 554 | 551 | ||
| 552 | bool ClearBackingRegion(size_t physical_offset, size_t length) { | ||
| 553 | #ifdef __linux__ | ||
| 554 | // Set MADV_REMOVE on backing map to destroy it instantly. | ||
| 555 | // This also deletes the area from the backing file. | ||
| 556 | int ret = madvise(backing_base + physical_offset, length, MADV_REMOVE); | ||
| 557 | ASSERT_MSG(ret == 0, "madvise failed: {}", strerror(errno)); | ||
| 558 | |||
| 559 | return true; | ||
| 560 | #else | ||
| 561 | return false; | ||
| 562 | #endif | ||
| 563 | } | ||
| 564 | |||
| 555 | void EnableDirectMappedAddress() { | 565 | void EnableDirectMappedAddress() { |
| 556 | virtual_base = nullptr; | 566 | virtual_base = nullptr; |
| 557 | } | 567 | } |
| @@ -623,6 +633,10 @@ public: | |||
| 623 | 633 | ||
| 624 | void Protect(size_t virtual_offset, size_t length, bool read, bool write, bool execute) {} | 634 | void Protect(size_t virtual_offset, size_t length, bool read, bool write, bool execute) {} |
| 625 | 635 | ||
| 636 | bool ClearBackingRegion(size_t physical_offset, size_t length) { | ||
| 637 | return false; | ||
| 638 | } | ||
| 639 | |||
| 626 | void EnableDirectMappedAddress() {} | 640 | void EnableDirectMappedAddress() {} |
| 627 | 641 | ||
| 628 | u8* backing_base{nullptr}; | 642 | u8* backing_base{nullptr}; |
| @@ -698,6 +712,12 @@ void HostMemory::Protect(size_t virtual_offset, size_t length, bool read, bool w | |||
| 698 | impl->Protect(virtual_offset + virtual_base_offset, length, read, write, execute); | 712 | impl->Protect(virtual_offset + virtual_base_offset, length, read, write, execute); |
| 699 | } | 713 | } |
| 700 | 714 | ||
| 715 | void HostMemory::ClearBackingRegion(size_t physical_offset, size_t length, u32 fill_value) { | ||
| 716 | if (!impl || fill_value != 0 || !impl->ClearBackingRegion(physical_offset, length)) { | ||
| 717 | std::memset(backing_base + physical_offset, fill_value, length); | ||
| 718 | } | ||
| 719 | } | ||
| 720 | |||
| 701 | void HostMemory::EnableDirectMappedAddress() { | 721 | void HostMemory::EnableDirectMappedAddress() { |
| 702 | if (impl) { | 722 | if (impl) { |
| 703 | impl->EnableDirectMappedAddress(); | 723 | impl->EnableDirectMappedAddress(); |
diff --git a/src/common/host_memory.h b/src/common/host_memory.h index cebfacab2..747c5850c 100644 --- a/src/common/host_memory.h +++ b/src/common/host_memory.h | |||
| @@ -48,6 +48,8 @@ public: | |||
| 48 | 48 | ||
| 49 | void EnableDirectMappedAddress(); | 49 | void EnableDirectMappedAddress(); |
| 50 | 50 | ||
| 51 | void ClearBackingRegion(size_t physical_offset, size_t length, u32 fill_value); | ||
| 52 | |||
| 51 | [[nodiscard]] u8* BackingBasePointer() noexcept { | 53 | [[nodiscard]] u8* BackingBasePointer() noexcept { |
| 52 | return backing_base; | 54 | return backing_base; |
| 53 | } | 55 | } |
diff --git a/src/core/hle/kernel/k_memory_manager.cpp b/src/core/hle/kernel/k_memory_manager.cpp index 0a973ec8c..d6bd27296 100644 --- a/src/core/hle/kernel/k_memory_manager.cpp +++ b/src/core/hle/kernel/k_memory_manager.cpp | |||
| @@ -421,8 +421,9 @@ Result KMemoryManager::AllocateForProcess(KPageGroup* out, size_t num_pages, u32 | |||
| 421 | } else { | 421 | } else { |
| 422 | // Set all the allocated memory. | 422 | // Set all the allocated memory. |
| 423 | for (const auto& block : *out) { | 423 | for (const auto& block : *out) { |
| 424 | std::memset(m_system.DeviceMemory().GetPointer<void>(block.GetAddress()), fill_pattern, | 424 | m_system.DeviceMemory().buffer.ClearBackingRegion(GetInteger(block.GetAddress()) - |
| 425 | block.GetSize()); | 425 | Core::DramMemoryMap::Base, |
| 426 | block.GetSize(), fill_pattern); | ||
| 426 | } | 427 | } |
| 427 | } | 428 | } |
| 428 | 429 | ||
diff --git a/src/core/hle/kernel/k_page_table_base.cpp b/src/core/hle/kernel/k_page_table_base.cpp index 4c416d809..423289145 100644 --- a/src/core/hle/kernel/k_page_table_base.cpp +++ b/src/core/hle/kernel/k_page_table_base.cpp | |||
| @@ -81,6 +81,11 @@ void InvalidateInstructionCache(KernelCore& kernel, AddressType addr, u64 size) | |||
| 81 | } | 81 | } |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | void ClearBackingRegion(Core::System& system, KPhysicalAddress addr, u64 size, u32 fill_value) { | ||
| 85 | system.DeviceMemory().buffer.ClearBackingRegion(GetInteger(addr) - Core::DramMemoryMap::Base, | ||
| 86 | size, fill_value); | ||
| 87 | } | ||
| 88 | |||
| 84 | template <typename AddressType> | 89 | template <typename AddressType> |
| 85 | Result InvalidateDataCache(AddressType addr, u64 size) { | 90 | Result InvalidateDataCache(AddressType addr, u64 size) { |
| 86 | R_SUCCEED(); | 91 | R_SUCCEED(); |
| @@ -1363,8 +1368,7 @@ Result KPageTableBase::MapInsecureMemory(KProcessAddress address, size_t size) { | |||
| 1363 | 1368 | ||
| 1364 | // Clear all the newly allocated pages. | 1369 | // Clear all the newly allocated pages. |
| 1365 | for (const auto& it : pg) { | 1370 | for (const auto& it : pg) { |
| 1366 | std::memset(GetHeapVirtualPointer(m_kernel, it.GetAddress()), | 1371 | ClearBackingRegion(m_system, it.GetAddress(), it.GetSize(), m_heap_fill_value); |
| 1367 | static_cast<u32>(m_heap_fill_value), it.GetSize()); | ||
| 1368 | } | 1372 | } |
| 1369 | 1373 | ||
| 1370 | // Lock the table. | 1374 | // Lock the table. |
| @@ -1570,8 +1574,7 @@ Result KPageTableBase::AllocateAndMapPagesImpl(PageLinkedList* page_list, KProce | |||
| 1570 | 1574 | ||
| 1571 | // Clear all pages. | 1575 | // Clear all pages. |
| 1572 | for (const auto& it : pg) { | 1576 | for (const auto& it : pg) { |
| 1573 | std::memset(GetHeapVirtualPointer(m_kernel, it.GetAddress()), | 1577 | ClearBackingRegion(m_system, it.GetAddress(), it.GetSize(), m_heap_fill_value); |
| 1574 | static_cast<u32>(m_heap_fill_value), it.GetSize()); | ||
| 1575 | } | 1578 | } |
| 1576 | 1579 | ||
| 1577 | // Map the pages. | 1580 | // Map the pages. |
| @@ -2159,8 +2162,7 @@ Result KPageTableBase::SetHeapSize(KProcessAddress* out, size_t size) { | |||
| 2159 | 2162 | ||
| 2160 | // Clear all the newly allocated pages. | 2163 | // Clear all the newly allocated pages. |
| 2161 | for (const auto& it : pg) { | 2164 | for (const auto& it : pg) { |
| 2162 | std::memset(GetHeapVirtualPointer(m_kernel, it.GetAddress()), m_heap_fill_value, | 2165 | ClearBackingRegion(m_system, it.GetAddress(), it.GetSize(), m_heap_fill_value); |
| 2163 | it.GetSize()); | ||
| 2164 | } | 2166 | } |
| 2165 | 2167 | ||
| 2166 | // Map the pages. | 2168 | // Map the pages. |