summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorGravatar liamwhite2024-01-31 11:22:29 -0500
committerGravatar GitHub2024-01-31 11:22:29 -0500
commit22492b68b73b4e8c865c4907cc4609db8cc07afd (patch)
tree75d356cf8a9d8e4ae93dda3d35647c80bd51c11c /src/core
parentMerge pull request #12864 from Kelebek1/small_time_fixes (diff)
parentDevice Memory Manager: ensure raster protection only within mapped device add... (diff)
downloadyuzu-22492b68b73b4e8c865c4907cc4609db8cc07afd.tar.gz
yuzu-22492b68b73b4e8c865c4907cc4609db8cc07afd.tar.xz
yuzu-22492b68b73b4e8c865c4907cc4609db8cc07afd.zip
Merge pull request #12869 from FernandoS27/smmu-fixes
SMMU: A set of different fixes.
Diffstat (limited to 'src/core')
-rw-r--r--src/core/device_memory_manager.h18
-rw-r--r--src/core/device_memory_manager.inc63
-rw-r--r--src/core/hle/service/nvdrv/core/container.cpp4
3 files changed, 45 insertions, 40 deletions
diff --git a/src/core/device_memory_manager.h b/src/core/device_memory_manager.h
index ffeed46cc..0568a821b 100644
--- a/src/core/device_memory_manager.h
+++ b/src/core/device_memory_manager.h
@@ -5,11 +5,13 @@
5 5
6#include <array> 6#include <array>
7#include <atomic> 7#include <atomic>
8#include <bit>
8#include <deque> 9#include <deque>
9#include <memory> 10#include <memory>
10#include <mutex> 11#include <mutex>
11 12
12#include "common/common_types.h" 13#include "common/common_types.h"
14#include "common/range_mutex.h"
13#include "common/scratch_buffer.h" 15#include "common/scratch_buffer.h"
14#include "common/virtual_buffer.h" 16#include "common/virtual_buffer.h"
15 17
@@ -180,31 +182,35 @@ private:
180 } 182 }
181 183
182 Common::VirtualBuffer<VAddr> cpu_backing_address; 184 Common::VirtualBuffer<VAddr> cpu_backing_address;
183 static constexpr size_t subentries = 8 / sizeof(u8); 185 using CounterType = u8;
186 using CounterAtomicType = std::atomic_uint8_t;
187 static constexpr size_t subentries = 8 / sizeof(CounterType);
184 static constexpr size_t subentries_mask = subentries - 1; 188 static constexpr size_t subentries_mask = subentries - 1;
189 static constexpr size_t subentries_shift =
190 std::countr_zero(sizeof(u64)) - std::countr_zero(sizeof(CounterType));
185 class CounterEntry final { 191 class CounterEntry final {
186 public: 192 public:
187 CounterEntry() = default; 193 CounterEntry() = default;
188 194
189 std::atomic_uint8_t& Count(std::size_t page) { 195 CounterAtomicType& Count(std::size_t page) {
190 return values[page & subentries_mask]; 196 return values[page & subentries_mask];
191 } 197 }
192 198
193 const std::atomic_uint8_t& Count(std::size_t page) const { 199 const CounterAtomicType& Count(std::size_t page) const {
194 return values[page & subentries_mask]; 200 return values[page & subentries_mask];
195 } 201 }
196 202
197 private: 203 private:
198 std::array<std::atomic_uint8_t, subentries> values{}; 204 std::array<CounterAtomicType, subentries> values{};
199 }; 205 };
200 static_assert(sizeof(CounterEntry) == subentries * sizeof(u8), 206 static_assert(sizeof(CounterEntry) == subentries * sizeof(CounterType),
201 "CounterEntry should be 8 bytes!"); 207 "CounterEntry should be 8 bytes!");
202 208
203 static constexpr size_t num_counter_entries = 209 static constexpr size_t num_counter_entries =
204 (1ULL << (device_virtual_bits - page_bits)) / subentries; 210 (1ULL << (device_virtual_bits - page_bits)) / subentries;
205 using CachedPages = std::array<CounterEntry, num_counter_entries>; 211 using CachedPages = std::array<CounterEntry, num_counter_entries>;
206 std::unique_ptr<CachedPages> cached_pages; 212 std::unique_ptr<CachedPages> cached_pages;
207 std::mutex counter_guard; 213 Common::RangeMutex counter_guard;
208 std::mutex mapping_guard; 214 std::mutex mapping_guard;
209}; 215};
210 216
diff --git a/src/core/device_memory_manager.inc b/src/core/device_memory_manager.inc
index eab8a2731..b026f4220 100644
--- a/src/core/device_memory_manager.inc
+++ b/src/core/device_memory_manager.inc
@@ -213,8 +213,8 @@ void DeviceMemoryManager<Traits>::Free(DAddr start, size_t size) {
213} 213}
214 214
215template <typename Traits> 215template <typename Traits>
216void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size_t size, 216void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size_t size, Asid asid,
217 Asid asid, bool track) { 217 bool track) {
218 Core::Memory::Memory* process_memory = registered_processes[asid.id]; 218 Core::Memory::Memory* process_memory = registered_processes[asid.id];
219 size_t start_page_d = address >> Memory::YUZU_PAGEBITS; 219 size_t start_page_d = address >> Memory::YUZU_PAGEBITS;
220 size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS; 220 size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS;
@@ -508,12 +508,7 @@ void DeviceMemoryManager<Traits>::UnregisterProcess(Asid asid) {
508 508
509template <typename Traits> 509template <typename Traits>
510void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size, s32 delta) { 510void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size, s32 delta) {
511 std::unique_lock<std::mutex> lk(counter_guard, std::defer_lock); 511 Common::ScopedRangeLock lk(counter_guard, addr, size);
512 const auto Lock = [&] {
513 if (!lk) {
514 lk.lock();
515 }
516 };
517 u64 uncache_begin = 0; 512 u64 uncache_begin = 0;
518 u64 cache_begin = 0; 513 u64 cache_begin = 0;
519 u64 uncache_bytes = 0; 514 u64 uncache_bytes = 0;
@@ -524,22 +519,36 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
524 const size_t page_end = Common::DivCeil(addr + size, Memory::YUZU_PAGESIZE); 519 const size_t page_end = Common::DivCeil(addr + size, Memory::YUZU_PAGESIZE);
525 size_t page = addr >> Memory::YUZU_PAGEBITS; 520 size_t page = addr >> Memory::YUZU_PAGEBITS;
526 auto [asid, base_vaddress] = ExtractCPUBacking(page); 521 auto [asid, base_vaddress] = ExtractCPUBacking(page);
527 size_t vpage = base_vaddress >> Memory::YUZU_PAGEBITS;
528 auto* memory_device_inter = registered_processes[asid.id]; 522 auto* memory_device_inter = registered_processes[asid.id];
523 const auto release_pending = [&] {
524 if (uncache_bytes > 0) {
525 MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS,
526 uncache_bytes, false);
527 uncache_bytes = 0;
528 }
529 if (cache_bytes > 0) {
530 MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS,
531 cache_bytes, true);
532 cache_bytes = 0;
533 }
534 };
529 for (; page != page_end; ++page) { 535 for (; page != page_end; ++page) {
530 std::atomic_uint8_t& count = cached_pages->at(page >> 3).Count(page); 536 CounterAtomicType& count = cached_pages->at(page >> subentries_shift).Count(page);
537 auto [asid_2, vpage] = ExtractCPUBacking(page);
538 vpage >>= Memory::YUZU_PAGEBITS;
531 539
532 if (delta > 0) { 540 if (vpage == 0) [[unlikely]] {
533 ASSERT_MSG(count.load(std::memory_order::relaxed) < std::numeric_limits<u8>::max(), 541 release_pending();
534 "Count may overflow!"); 542 continue;
535 } else if (delta < 0) { 543 }
536 ASSERT_MSG(count.load(std::memory_order::relaxed) > 0, "Count may underflow!"); 544
537 } else { 545 if (asid.id != asid_2.id) [[unlikely]] {
538 ASSERT_MSG(false, "Delta must be non-zero!"); 546 release_pending();
547 memory_device_inter = registered_processes[asid_2.id];
539 } 548 }
540 549
541 // Adds or subtracts 1, as count is a unsigned 8-bit value 550 // Adds or subtracts 1, as count is a unsigned 8-bit value
542 count.fetch_add(static_cast<u8>(delta), std::memory_order_release); 551 count.fetch_add(static_cast<CounterType>(delta), std::memory_order_release);
543 552
544 // Assume delta is either -1 or 1 553 // Assume delta is either -1 or 1
545 if (count.load(std::memory_order::relaxed) == 0) { 554 if (count.load(std::memory_order::relaxed) == 0) {
@@ -548,7 +557,6 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
548 } 557 }
549 uncache_bytes += Memory::YUZU_PAGESIZE; 558 uncache_bytes += Memory::YUZU_PAGESIZE;
550 } else if (uncache_bytes > 0) { 559 } else if (uncache_bytes > 0) {
551 Lock();
552 MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, 560 MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS,
553 uncache_bytes, false); 561 uncache_bytes, false);
554 uncache_bytes = 0; 562 uncache_bytes = 0;
@@ -559,23 +567,12 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
559 } 567 }
560 cache_bytes += Memory::YUZU_PAGESIZE; 568 cache_bytes += Memory::YUZU_PAGESIZE;
561 } else if (cache_bytes > 0) { 569 } else if (cache_bytes > 0) {
562 Lock(); 570 MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS,
563 MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes, 571 cache_bytes, true);
564 true);
565 cache_bytes = 0; 572 cache_bytes = 0;
566 } 573 }
567 vpage++;
568 }
569 if (uncache_bytes > 0) {
570 Lock();
571 MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, uncache_bytes,
572 false);
573 }
574 if (cache_bytes > 0) {
575 Lock();
576 MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes,
577 true);
578 } 574 }
575 release_pending();
579} 576}
580 577
581} // namespace Core 578} // namespace Core
diff --git a/src/core/hle/service/nvdrv/core/container.cpp b/src/core/hle/service/nvdrv/core/container.cpp
index dc1b4d5be..e89cca6f2 100644
--- a/src/core/hle/service/nvdrv/core/container.cpp
+++ b/src/core/hle/service/nvdrv/core/container.cpp
@@ -83,7 +83,9 @@ SessionId Container::OpenSession(Kernel::KProcess* process) {
83 83
84 // Check if this memory block is heap. 84 // Check if this memory block is heap.
85 if (svc_mem_info.state == Kernel::Svc::MemoryState::Normal) { 85 if (svc_mem_info.state == Kernel::Svc::MemoryState::Normal) {
86 if (svc_mem_info.size > region_size) { 86 if (region_start + region_size == svc_mem_info.base_address) {
87 region_size += svc_mem_info.size;
88 } else if (svc_mem_info.size > region_size) {
87 region_size = svc_mem_info.size; 89 region_size = svc_mem_info.size;
88 region_start = svc_mem_info.base_address; 90 region_start = svc_mem_info.base_address;
89 } 91 }