From 89f447e0298e392af96b683b2fda2064d67e52df Mon Sep 17 00:00:00 2001 From: Borchev <4501931+Borchev@users.noreply.github.com> Date: Thu, 8 Aug 2024 12:42:27 -0700 Subject: [PATCH] Avoid crash when access violation address not in page table --- src/video_core/buffer_cache/buffer_cache.cpp | 24 +++++++++++--------- src/video_core/multi_level_page_table.h | 9 ++++++++ 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/video_core/buffer_cache/buffer_cache.cpp b/src/video_core/buffer_cache/buffer_cache.cpp index 7ab0d8171..a30dec3ab 100644 --- a/src/video_core/buffer_cache/buffer_cache.cpp +++ b/src/video_core/buffer_cache/buffer_cache.cpp @@ -228,18 +228,20 @@ bool BufferCache::IsRegionRegistered(VAddr addr, size_t size) { const VAddr end_addr = addr + size; const u64 page_end = Common::DivCeil(end_addr, CACHING_PAGESIZE); for (u64 page = addr >> CACHING_PAGEBITS; page < page_end;) { - const BufferId buffer_id = page_table[page]; - if (!buffer_id) { - ++page; - continue; + if (page_table.contains_page(page)) { + const BufferId buffer_id = page_table[page]; + if (buffer_id) { + const Buffer& buffer = slot_buffers[buffer_id]; + const VAddr buf_start_addr = buffer.CpuAddr(); + const VAddr buf_end_addr = buf_start_addr + buffer.SizeBytes(); + if (buf_start_addr < end_addr && addr < buf_end_addr) { + return true; + } + page = Common::DivCeil(end_addr, CACHING_PAGESIZE); + continue; + } } - Buffer& buffer = slot_buffers[buffer_id]; - const VAddr buf_start_addr = buffer.CpuAddr(); - const VAddr buf_end_addr = buf_start_addr + buffer.SizeBytes(); - if (buf_start_addr < end_addr && addr < buf_end_addr) { - return true; - } - page = Common::DivCeil(end_addr, CACHING_PAGESIZE); + ++page; } return false; } diff --git a/src/video_core/multi_level_page_table.h b/src/video_core/multi_level_page_table.h index 527476f3b..1b5360593 100644 --- a/src/video_core/multi_level_page_table.h +++ b/src/video_core/multi_level_page_table.h @@ -31,6 +31,10 @@ public: ~MultiLevelPageTable() noexcept = default; [[nodiscard]] Entry* find(size_t page) { + if (!contains_page(page)) { + return nullptr; + } + const size_t l1_page = page >> SecondLevelBits; const size_t l2_page = page & (NumEntriesPerL1Page - 1); if (!first_level_map[l1_page]) { @@ -57,6 +61,11 @@ public: return (*first_level_map[l1_page])[l2_page]; } + [[nodiscard]] const bool contains_page(size_t page) const { + const size_t l1_page = page >> SecondLevelBits; + return l1_page < first_level_map.size(); + } + private: std::vector first_level_map{}; Common::ObjectPool page_alloc;