summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Liam2023-12-13 15:32:25 -0500
committerGravatar Liam2023-12-14 23:44:33 -0500
commit8ad5f2c50648c333c3c46f89533e200a39bf6ca8 (patch)
tree00cfb8d70b13db1016006a8a9de99137a9736c08 /src
parentMerge pull request #12354 from liamwhite/mackage-panager (diff)
downloadyuzu-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.cpp38
-rw-r--r--src/common/host_memory.h2
-rw-r--r--src/core/hle/kernel/k_memory_manager.cpp5
-rw-r--r--src/core/hle/kernel/k_page_table_base.cpp14
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
715void 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
701void HostMemory::EnableDirectMappedAddress() { 721void 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
84void 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
84template <typename AddressType> 89template <typename AddressType>
85Result InvalidateDataCache(AddressType addr, u64 size) { 90Result 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.