diff --git a/src/common/page_table.h b/src/common/page_table.h index 3124b4a7fb..0dfd152331 100644 --- a/src/common/page_table.h +++ b/src/common/page_table.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project @@ -142,10 +142,8 @@ struct PageTable { VirtualBuffer entries; static_assert(sizeof(PageEntryData) == 32); - std::size_t current_address_space_width_in_bits{}; - u8* fastmem_arena{}; - + std::size_t current_address_space_width_in_bits{}; std::size_t page_size{}; }; diff --git a/src/common/virtual_buffer.h b/src/common/virtual_buffer.h index 4f6e3e6e5c..af96317288 100644 --- a/src/common/virtual_buffer.h +++ b/src/common/virtual_buffer.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -21,7 +24,9 @@ public: // "with the current allocator"); constexpr VirtualBuffer() = default; - explicit VirtualBuffer(std::size_t count) : alloc_size{count * sizeof(T)} { + explicit VirtualBuffer(std::size_t count) noexcept + : alloc_size{count * sizeof(T)} + { base_ptr = reinterpret_cast(AllocateMemoryPages(alloc_size)); } @@ -33,8 +38,8 @@ public: VirtualBuffer& operator=(const VirtualBuffer&) = delete; VirtualBuffer(VirtualBuffer&& other) noexcept - : alloc_size{std::exchange(other.alloc_size, 0)}, base_ptr{std::exchange(other.base_ptr), - nullptr} {} + : alloc_size{std::exchange(other.alloc_size, 0)}, base_ptr{std::exchange(other.base_ptr), nullptr} + {} VirtualBuffer& operator=(VirtualBuffer&& other) noexcept { alloc_size = std::exchange(other.alloc_size, 0); @@ -42,35 +47,31 @@ public: return *this; } - void resize(std::size_t count) { - const auto new_size = count * sizeof(T); - if (new_size == alloc_size) { - return; + void resize(std::size_t count) noexcept { + if (auto const new_size = count * sizeof(T); new_size != alloc_size) { + FreeMemoryPages(base_ptr, alloc_size); + alloc_size = new_size; + base_ptr = reinterpret_cast(AllocateMemoryPages(alloc_size)); } - - FreeMemoryPages(base_ptr, alloc_size); - - alloc_size = new_size; - base_ptr = reinterpret_cast(AllocateMemoryPages(alloc_size)); } - [[nodiscard]] constexpr const T& operator[](std::size_t index) const { + [[nodiscard]] constexpr const T& operator[](std::size_t index) const noexcept { return base_ptr[index]; } - [[nodiscard]] constexpr T& operator[](std::size_t index) { + [[nodiscard]] constexpr T& operator[](std::size_t index) noexcept { return base_ptr[index]; } - [[nodiscard]] constexpr T* data() { + [[nodiscard]] constexpr T* data() noexcept { return base_ptr; } - [[nodiscard]] constexpr const T* data() const { + [[nodiscard]] constexpr const T* data() const noexcept { return base_ptr; } - [[nodiscard]] constexpr std::size_t size() const { + [[nodiscard]] constexpr std::size_t size() const noexcept { return alloc_size / sizeof(T); } diff --git a/src/core/hle/kernel/k_page_table_base.cpp b/src/core/hle/kernel/k_page_table_base.cpp index 6b3f60f52e..e5b2ed7041 100644 --- a/src/core/hle/kernel/k_page_table_base.cpp +++ b/src/core/hle/kernel/k_page_table_base.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -191,8 +191,7 @@ Result KPageTableBase::InitializeForKernel(bool is_64_bit, KVirtualAddress start m_cached_physical_heap_region = nullptr; // Initialize our implementation. - m_impl = std::make_unique(); - m_impl->Resize(m_address_space_width, PageBits); + m_impl.Resize(m_address_space_width, PageBits); // Set the tracking memory. m_memory = std::addressof(memory); @@ -202,13 +201,7 @@ Result KPageTableBase::InitializeForKernel(bool is_64_bit, KVirtualAddress start m_memory_block_slab_manager)); } -Result KPageTableBase::InitializeForProcess(Svc::CreateProcessFlag as_type, bool enable_aslr, - bool enable_das_merge, bool from_back, - KMemoryManager::Pool pool, KProcessAddress code_address, - size_t code_size, KSystemResource* system_resource, - KResourceLimit* resource_limit, - Core::Memory::Memory& memory, - KProcessAddress aslr_space_start) { +Result KPageTableBase::InitializeForProcess(Svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_das_merge, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource* system_resource, KResourceLimit* resource_limit, Core::Memory::Memory& memory, KProcessAddress aslr_space_start) { // Calculate region extents. const size_t as_width = GetAddressSpaceWidth(as_type); const KProcessAddress start = 0; @@ -319,14 +312,10 @@ Result KPageTableBase::InitializeForProcess(Svc::CreateProcessFlag as_type, bool // Determine random placements for each region. size_t alias_rnd = 0, heap_rnd = 0, stack_rnd = 0, kmap_rnd = 0; if (enable_aslr) { - alias_rnd = KSystemControl::GenerateRandomRange(0, remaining_size / RegionAlignment) * - RegionAlignment; - heap_rnd = KSystemControl::GenerateRandomRange(0, remaining_size / RegionAlignment) * - RegionAlignment; - stack_rnd = KSystemControl::GenerateRandomRange(0, remaining_size / RegionAlignment) * - RegionAlignment; - kmap_rnd = KSystemControl::GenerateRandomRange(0, remaining_size / RegionAlignment) * - RegionAlignment; + alias_rnd = KSystemControl::GenerateRandomRange(0, remaining_size / RegionAlignment) * RegionAlignment; + heap_rnd = KSystemControl::GenerateRandomRange(0, remaining_size / RegionAlignment) * RegionAlignment; + stack_rnd = KSystemControl::GenerateRandomRange(0, remaining_size / RegionAlignment) * RegionAlignment; + kmap_rnd = KSystemControl::GenerateRandomRange(0, remaining_size / RegionAlignment) * RegionAlignment; } // Setup heap and alias regions. @@ -445,15 +434,13 @@ Result KPageTableBase::InitializeForProcess(Svc::CreateProcessFlag as_type, bool ASSERT(heap_last < kmap_start || kmap_last < heap_start); // Initialize our implementation. - m_impl = std::make_unique(); - m_impl->Resize(m_address_space_width, PageBits); + m_impl.Resize(m_address_space_width, PageBits); // Set the tracking memory. m_memory = std::addressof(memory); // Initialize our memory block manager. - R_RETURN(m_memory_block_manager.Initialize(m_address_space_start, m_address_space_end, - m_memory_block_slab_manager)); + R_RETURN(m_memory_block_manager.Initialize(m_address_space_start, m_address_space_end, m_memory_block_slab_manager)); } Result KPageTableBase::FinalizeProcess() { @@ -476,7 +463,7 @@ void KPageTableBase::Finalize() { this->FinalizeProcess(); auto BlockCallback = [&](KProcessAddress addr, u64 size) { - if (m_impl->fastmem_arena) { + if (m_impl.fastmem_arena) { m_system.DeviceMemory().buffer.Unmap(GetInteger(addr), size, false); } @@ -514,9 +501,6 @@ void KPageTableBase::Finalize() { m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, m_mapped_ipc_server_memory); } - - // Close the backing page table, as the destructor is not called for guest objects. - m_impl.reset(); } KProcessAddress KPageTableBase::GetRegionAddress(Svc::MemoryState state) const { @@ -2349,7 +2333,7 @@ Result KPageTableBase::QueryPhysicalAddress(Svc::lp64::PhysicalMemoryInfo* out, TraversalContext context; TraversalEntry next_entry; bool traverse_valid = - m_impl->BeginTraversal(std::addressof(next_entry), std::addressof(context), virt_addr); + m_impl.BeginTraversal(std::addressof(next_entry), std::addressof(context), virt_addr); R_UNLESS(traverse_valid, ResultInvalidCurrentMemory); // Set tracking variables. @@ -2360,7 +2344,7 @@ Result KPageTableBase::QueryPhysicalAddress(Svc::lp64::PhysicalMemoryInfo* out, while (true) { // Continue the traversal. traverse_valid = - m_impl->ContinueTraversal(std::addressof(next_entry), std::addressof(context)); + m_impl.ContinueTraversal(std::addressof(next_entry), std::addressof(context)); if (!traverse_valid) { break; } @@ -5730,14 +5714,14 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a this->MakePageGroup(pages_to_close, virt_addr, num_pages); // Unmap. - m_memory->UnmapRegion(*m_impl, virt_addr, num_pages * PageSize, separate_heap); + m_memory->UnmapRegion(m_impl, virt_addr, num_pages * PageSize, separate_heap); R_SUCCEED(); } case OperationType::Map: { ASSERT(virt_addr != 0); ASSERT(Common::IsAligned(GetInteger(virt_addr), PageSize)); - m_memory->MapMemoryRegion(*m_impl, virt_addr, num_pages * PageSize, phys_addr, + m_memory->MapMemoryRegion(m_impl, virt_addr, num_pages * PageSize, phys_addr, ConvertToMemoryPermission(properties.perm), false); // Open references to pages, if we should. @@ -5754,7 +5738,7 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a case OperationType::ChangePermissions: case OperationType::ChangePermissionsAndRefresh: case OperationType::ChangePermissionsAndRefreshAndFlush: { - m_memory->ProtectRegion(*m_impl, virt_addr, num_pages * PageSize, + m_memory->ProtectRegion(m_impl, virt_addr, num_pages * PageSize, ConvertToMemoryPermission(properties.perm)); R_SUCCEED(); } @@ -5788,7 +5772,7 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a const size_t size{node.GetNumPages() * PageSize}; // Map the pages. - m_memory->MapMemoryRegion(*m_impl, virt_addr, size, node.GetAddress(), + m_memory->MapMemoryRegion(m_impl, virt_addr, size, node.GetAddress(), ConvertToMemoryPermission(properties.perm), separate_heap); virt_addr += size; diff --git a/src/core/hle/kernel/k_page_table_base.h b/src/core/hle/kernel/k_page_table_base.h index fc5d3876c7..90f8124a24 100644 --- a/src/core/hle/kernel/k_page_table_base.h +++ b/src/core/hle/kernel/k_page_table_base.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -215,7 +215,7 @@ private: mutable KLightLock m_general_lock; mutable KLightLock m_map_physical_memory_lock; KLightLock m_device_map_lock; - std::unique_ptr m_impl{}; + Common::PageTable m_impl{}; Core::Memory::Memory* m_memory{}; KMemoryBlockManager m_memory_block_manager{}; u32 m_allocate_option{}; @@ -300,26 +300,11 @@ public: } public: - Core::Memory::Memory& GetMemory() { - return *m_memory; - } - - Core::Memory::Memory& GetMemory() const { - return *m_memory; - } - - Common::PageTable& GetImpl() { - return *m_impl; - } - - Common::PageTable& GetImpl() const { - return *m_impl; - } - - size_t GetNumGuardPages() const { - return this->IsKernel() ? 1 : 4; - } - + [[nodiscard]] Core::Memory::Memory& GetMemory() noexcept { return *m_memory; } + [[nodiscard]] Core::Memory::Memory const& GetMemory() const noexcept { return *m_memory; } + [[nodiscard]] Common::PageTable& GetImpl() noexcept { return m_impl; } + [[nodiscard]] Common::PageTable const& GetImpl() const noexcept { return m_impl; } + [[nodiscard]] size_t GetNumGuardPages() const noexcept { return this->IsKernel() ? 1 : 4; } protected: // NOTE: These three functions (Operate, Operate, FinalizeUpdate) are virtual functions // in Nintendo's kernel. We devirtualize them, since KPageTable is the only derived diff --git a/src/core/hle/kernel/k_process_page_table.h b/src/core/hle/kernel/k_process_page_table.h index 0601f9f6d8..6462e44a99 100644 --- a/src/core/hle/kernel/k_process_page_table.h +++ b/src/core/hle/kernel/k_process_page_table.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -33,21 +33,10 @@ public: m_page_table.Finalize(); } - Core::Memory::Memory& GetMemory() { - return m_page_table.GetMemory(); - } - - Core::Memory::Memory& GetMemory() const { - return m_page_table.GetMemory(); - } - - Common::PageTable& GetImpl() { - return m_page_table.GetImpl(); - } - - Common::PageTable& GetImpl() const { - return m_page_table.GetImpl(); - } + [[nodiscard]] Core::Memory::Memory& GetMemory() noexcept { return m_page_table.GetMemory(); } + [[nodiscard]] Core::Memory::Memory const& GetMemory() const noexcept { return m_page_table.GetMemory(); } + [[nodiscard]] Common::PageTable& GetImpl() noexcept { return m_page_table.GetImpl(); } + [[nodiscard]] Common::PageTable const& GetImpl() const noexcept { return m_page_table.GetImpl(); } size_t GetNumGuardPages() const { return m_page_table.GetNumGuardPages();