diff --git a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_page_table.hpp b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_page_table.hpp index a12533207..d6fcd433d 100644 --- a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_page_table.hpp +++ b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_page_table.hpp @@ -22,9 +22,11 @@ namespace ams::kern::arch::arm64 { - class KPageTable : public KPageTableBase { + class KPageTable final : public KPageTableBase { NON_COPYABLE(KPageTable); NON_MOVEABLE(KPageTable); + private: + friend class KPageTableBase; public: using TraversalEntry = KPageTableImpl::TraversalEntry; using TraversalContext = KPageTableImpl::TraversalContext; @@ -96,9 +98,9 @@ namespace ams::kern::arch::arm64 { u64 m_ttbr; u8 m_asid; protected: - virtual Result Operate(PageLinkedList *page_list, KProcessAddress virt_addr, size_t num_pages, KPhysicalAddress phys_addr, bool is_pa_valid, const KPageProperties properties, OperationType operation, bool reuse_ll) override; - virtual Result Operate(PageLinkedList *page_list, KProcessAddress virt_addr, size_t num_pages, const KPageGroup &page_group, const KPageProperties properties, OperationType operation, bool reuse_ll) override; - virtual void FinalizeUpdate(PageLinkedList *page_list) override; + Result OperateImpl(PageLinkedList *page_list, KProcessAddress virt_addr, size_t num_pages, KPhysicalAddress phys_addr, bool is_pa_valid, const KPageProperties properties, OperationType operation, bool reuse_ll); + Result OperateImpl(PageLinkedList *page_list, KProcessAddress virt_addr, size_t num_pages, const KPageGroup &page_group, const KPageProperties properties, OperationType operation, bool reuse_ll); + void FinalizeUpdateImpl(PageLinkedList *page_list); KPageTableManager &GetPageTableManager() const { return *m_manager; } private: diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp index 0b1823445..1a8da836c 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp @@ -217,9 +217,13 @@ namespace ams::kern { size_t GetRegionSize(KMemoryState state) const; bool CanContain(KProcessAddress addr, size_t size, KMemoryState state) const; protected: - virtual Result Operate(PageLinkedList *page_list, KProcessAddress virt_addr, size_t num_pages, KPhysicalAddress phys_addr, bool is_pa_valid, const KPageProperties properties, OperationType operation, bool reuse_ll) = 0; - virtual Result Operate(PageLinkedList *page_list, KProcessAddress virt_addr, size_t num_pages, const KPageGroup &page_group, const KPageProperties properties, OperationType operation, bool reuse_ll) = 0; - virtual void FinalizeUpdate(PageLinkedList *page_list) = 0; + /* NOTE: These three functions (Operate, Operate, FinalizeUpdate) are virtual functions */ + /* in Nintendo's kernel. We devirtualize them, since KPageTable is the only derived */ + /* class, and this avoids unnecessary virtual function calls. See "kern_select_page_table.hpp" */ + /* for definition of these functions. */ + Result Operate(PageLinkedList *page_list, KProcessAddress virt_addr, size_t num_pages, KPhysicalAddress phys_addr, bool is_pa_valid, const KPageProperties properties, OperationType operation, bool reuse_ll); + Result Operate(PageLinkedList *page_list, KProcessAddress virt_addr, size_t num_pages, const KPageGroup &page_group, const KPageProperties properties, OperationType operation, bool reuse_ll); + void FinalizeUpdate(PageLinkedList *page_list); ALWAYS_INLINE KPageTableImpl &GetImpl() { return m_impl; } ALWAYS_INLINE const KPageTableImpl &GetImpl() const { return m_impl; } diff --git a/libraries/libmesosphere/include/mesosphere/kern_select_page_table.hpp b/libraries/libmesosphere/include/mesosphere/kern_select_page_table.hpp index 28210ff38..4a0edda23 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_select_page_table.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_select_page_table.hpp @@ -32,3 +32,24 @@ #error "Unknown architecture for KPageTable" #endif + +namespace ams::kern { + + /* NOTE: These three functions (Operate, Operate, FinalizeUpdate) are virtual functions */ + /* in Nintendo's kernel. We devirtualize them, since KPageTable is the only derived */ + /* class, and this avoids unnecessary virtual function calls. */ + static_assert(std::derived_from); + + ALWAYS_INLINE Result KPageTableBase::Operate(PageLinkedList *page_list, KProcessAddress virt_addr, size_t num_pages, KPhysicalAddress phys_addr, bool is_pa_valid, const KPageProperties properties, OperationType operation, bool reuse_ll) { + return static_cast(this)->OperateImpl(page_list, virt_addr, num_pages, phys_addr, is_pa_valid, properties, operation, reuse_ll); + } + + ALWAYS_INLINE Result KPageTableBase::Operate(PageLinkedList *page_list, KProcessAddress virt_addr, size_t num_pages, const KPageGroup &page_group, const KPageProperties properties, OperationType operation, bool reuse_ll) { + return static_cast(this)->OperateImpl(page_list, virt_addr, num_pages, page_group, properties, operation, reuse_ll); + } + + ALWAYS_INLINE void KPageTableBase::FinalizeUpdate(PageLinkedList *page_list) { + return static_cast(this)->FinalizeUpdateImpl(page_list); + } + +} \ No newline at end of file diff --git a/libraries/libmesosphere/source/arch/arm64/kern_k_page_table.cpp b/libraries/libmesosphere/source/arch/arm64/kern_k_page_table.cpp index 6e3fc2c96..cda590a80 100644 --- a/libraries/libmesosphere/source/arch/arm64/kern_k_page_table.cpp +++ b/libraries/libmesosphere/source/arch/arm64/kern_k_page_table.cpp @@ -319,7 +319,7 @@ namespace ams::kern::arch::arm64 { return ResultSuccess(); } - Result KPageTable::Operate(PageLinkedList *page_list, KProcessAddress virt_addr, size_t num_pages, KPhysicalAddress phys_addr, bool is_pa_valid, const KPageProperties properties, OperationType operation, bool reuse_ll) { + Result KPageTable::OperateImpl(PageLinkedList *page_list, KProcessAddress virt_addr, size_t num_pages, KPhysicalAddress phys_addr, bool is_pa_valid, const KPageProperties properties, OperationType operation, bool reuse_ll) { /* Check validity of parameters. */ MESOSPHERE_ASSERT(this->IsLockedByCurrentThread()); MESOSPHERE_ASSERT(num_pages > 0); @@ -350,7 +350,7 @@ namespace ams::kern::arch::arm64 { } } - Result KPageTable::Operate(PageLinkedList *page_list, KProcessAddress virt_addr, size_t num_pages, const KPageGroup &page_group, const KPageProperties properties, OperationType operation, bool reuse_ll) { + Result KPageTable::OperateImpl(PageLinkedList *page_list, KProcessAddress virt_addr, size_t num_pages, const KPageGroup &page_group, const KPageProperties properties, OperationType operation, bool reuse_ll) { /* Check validity of parameters. */ MESOSPHERE_ASSERT(this->IsLockedByCurrentThread()); MESOSPHERE_ASSERT(util::IsAligned(GetInteger(virt_addr), PageSize)); @@ -1429,7 +1429,7 @@ namespace ams::kern::arch::arm64 { return ResultSuccess(); } - void KPageTable::FinalizeUpdate(PageLinkedList *page_list) { + void KPageTable::FinalizeUpdateImpl(PageLinkedList *page_list) { while (page_list->Peek()) { KVirtualAddress page = KVirtualAddress(page_list->Pop()); MESOSPHERE_ASSERT(this->GetPageTableManager().IsInPageTableHeap(page));