diff options
| -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 @@  #elif defined(__linux__) || defined(__FreeBSD__) // ^^^ Windows ^^^ vvv Linux vvv -#ifdef ANDROID -#include <android/sharedmem.h> -#endif -  #ifndef _GNU_SOURCE  #define _GNU_SOURCE  #endif @@ -193,6 +189,11 @@ public:          }      } +    bool ClearBackingRegion(size_t physical_offset, size_t length) { +        // TODO: This does not seem to be possible on Windows. +        return false; +    } +      void EnableDirectMappedAddress() {          // TODO          UNREACHABLE(); @@ -442,9 +443,7 @@ public:          }          // Backing memory initialization -#ifdef ANDROID -        fd = ASharedMemory_create("HostMemory", backing_size); -#elif defined(__FreeBSD__) && __FreeBSD__ < 13 +#if defined(__FreeBSD__) && __FreeBSD__ < 13          // XXX Drop after FreeBSD 12.* reaches EOL on 2024-06-30          fd = shm_open(SHM_ANON, O_RDWR, 0600);  #else @@ -455,7 +454,6 @@ public:              throw std::bad_alloc{};          } -#ifndef ANDROID          // Defined to extend the file with zeros          int ret = ftruncate(fd, backing_size);          if (ret != 0) { @@ -463,7 +461,6 @@ public:                           strerror(errno));              throw std::bad_alloc{};          } -#endif          backing_base = static_cast<u8*>(              mmap(nullptr, backing_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)); @@ -552,6 +549,19 @@ public:          ASSERT_MSG(ret == 0, "mprotect failed: {}", strerror(errno));      } +    bool ClearBackingRegion(size_t physical_offset, size_t length) { +#ifdef __linux__ +        // Set MADV_REMOVE on backing map to destroy it instantly. +        // This also deletes the area from the backing file. +        int ret = madvise(backing_base + physical_offset, length, MADV_REMOVE); +        ASSERT_MSG(ret == 0, "madvise failed: {}", strerror(errno)); + +        return true; +#else +        return false; +#endif +    } +      void EnableDirectMappedAddress() {          virtual_base = nullptr;      } @@ -623,6 +633,10 @@ public:      void Protect(size_t virtual_offset, size_t length, bool read, bool write, bool execute) {} +    bool ClearBackingRegion(size_t physical_offset, size_t length) { +        return false; +    } +      void EnableDirectMappedAddress() {}      u8* backing_base{nullptr}; @@ -698,6 +712,12 @@ void HostMemory::Protect(size_t virtual_offset, size_t length, bool read, bool w      impl->Protect(virtual_offset + virtual_base_offset, length, read, write, execute);  } +void HostMemory::ClearBackingRegion(size_t physical_offset, size_t length, u32 fill_value) { +    if (!impl || fill_value != 0 || !impl->ClearBackingRegion(physical_offset, length)) { +        std::memset(backing_base + physical_offset, fill_value, length); +    } +} +  void HostMemory::EnableDirectMappedAddress() {      if (impl) {          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:      void EnableDirectMappedAddress(); +    void ClearBackingRegion(size_t physical_offset, size_t length, u32 fill_value); +      [[nodiscard]] u8* BackingBasePointer() noexcept {          return backing_base;      } 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      } else {          // Set all the allocated memory.          for (const auto& block : *out) { -            std::memset(m_system.DeviceMemory().GetPointer<void>(block.GetAddress()), fill_pattern, -                        block.GetSize()); +            m_system.DeviceMemory().buffer.ClearBackingRegion(GetInteger(block.GetAddress()) - +                                                                  Core::DramMemoryMap::Base, +                                                              block.GetSize(), fill_pattern);          }      } 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)      }  } +void ClearBackingRegion(Core::System& system, KPhysicalAddress addr, u64 size, u32 fill_value) { +    system.DeviceMemory().buffer.ClearBackingRegion(GetInteger(addr) - Core::DramMemoryMap::Base, +                                                    size, fill_value); +} +  template <typename AddressType>  Result InvalidateDataCache(AddressType addr, u64 size) {      R_SUCCEED(); @@ -1363,8 +1368,7 @@ Result KPageTableBase::MapInsecureMemory(KProcessAddress address, size_t size) {      // Clear all the newly allocated pages.      for (const auto& it : pg) { -        std::memset(GetHeapVirtualPointer(m_kernel, it.GetAddress()), -                    static_cast<u32>(m_heap_fill_value), it.GetSize()); +        ClearBackingRegion(m_system, it.GetAddress(), it.GetSize(), m_heap_fill_value);      }      // Lock the table. @@ -1570,8 +1574,7 @@ Result KPageTableBase::AllocateAndMapPagesImpl(PageLinkedList* page_list, KProce      // Clear all pages.      for (const auto& it : pg) { -        std::memset(GetHeapVirtualPointer(m_kernel, it.GetAddress()), -                    static_cast<u32>(m_heap_fill_value), it.GetSize()); +        ClearBackingRegion(m_system, it.GetAddress(), it.GetSize(), m_heap_fill_value);      }      // Map the pages. @@ -2159,8 +2162,7 @@ Result KPageTableBase::SetHeapSize(KProcessAddress* out, size_t size) {      // Clear all the newly allocated pages.      for (const auto& it : pg) { -        std::memset(GetHeapVirtualPointer(m_kernel, it.GetAddress()), m_heap_fill_value, -                    it.GetSize()); +        ClearBackingRegion(m_system, it.GetAddress(), it.GetSize(), m_heap_fill_value);      }      // Map the pages. | 
