From 1983f86875e7cc55ef139653ace36ff3bf0d17ae Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Sun, 23 Aug 2020 13:19:45 -0700 Subject: [PATCH] kern: revamp KMemoryRegionType to better encode derivation hierarchies --- .../arm/kern_k_memory_region_device_types.inc | 25 ++ .../kern_k_memory_region_device_types.inc | 25 ++ ...ntendo_nx.hpp => kern_k_memory_layout.hpp} | 0 .../nx/kern_k_memory_region_device_types.inc | 27 ++ .../mesosphere/kern_k_memory_layout.hpp | 422 +----------------- .../mesosphere/kern_k_memory_region.hpp | 318 +++++++++++++ .../mesosphere/kern_k_memory_region_type.hpp | 300 +++++++++++++ .../arm/kern_generic_interrupt_controller.inc | 4 +- .../nintendo/nx/kern_k_device_page_table.cpp | 2 +- .../nintendo/nx/kern_k_system_control.cpp | 8 +- .../kern_debug_log_impl.board.nintendo_nx.cpp | 2 +- ...kern_k_memory_layout.board.nintendo_nx.cpp | 14 +- .../source/kern_k_memory_layout.cpp | 2 +- .../source/kern_k_memory_manager.cpp | 4 +- .../libmesosphere/source/kern_kernel.cpp | 2 +- libraries/libmesosphere/source/kern_main.cpp | 4 +- .../source/arch/arm64/init/kern_init_core.cpp | 13 +- 17 files changed, 746 insertions(+), 426 deletions(-) create mode 100644 libraries/libmesosphere/include/mesosphere/arch/arm/kern_k_memory_region_device_types.inc create mode 100644 libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_memory_region_device_types.inc rename libraries/libmesosphere/include/mesosphere/board/nintendo/nx/{kern_k_memory_layout.board.nintendo_nx.hpp => kern_k_memory_layout.hpp} (100%) create mode 100644 libraries/libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_memory_region_device_types.inc create mode 100644 libraries/libmesosphere/include/mesosphere/kern_k_memory_region.hpp create mode 100644 libraries/libmesosphere/include/mesosphere/kern_k_memory_region_type.hpp diff --git a/libraries/libmesosphere/include/mesosphere/arch/arm/kern_k_memory_region_device_types.inc b/libraries/libmesosphere/include/mesosphere/arch/arm/kern_k_memory_region_device_types.inc new file mode 100644 index 000000000..65f6fe8cd --- /dev/null +++ b/libraries/libmesosphere/include/mesosphere/arch/arm/kern_k_memory_region_device_types.inc @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* All architectures must define NumArchitectureDeviceRegions. */ +constexpr inline const auto NumArchitectureDeviceRegions = 3; + +constexpr inline const auto KMemoryRegionType_Uart = KMemoryRegionType_ArchDeviceBase.DeriveSparse(0, NumArchitectureDeviceRegions, 0); +constexpr inline const auto KMemoryRegionType_InterruptCpuInterface = KMemoryRegionType_ArchDeviceBase.DeriveSparse(0, NumArchitectureDeviceRegions, 1).SetAttribute(KMemoryRegionAttr_NoUserMap); +constexpr inline const auto KMemoryRegionType_InterruptDistributor = KMemoryRegionType_ArchDeviceBase.DeriveSparse(0, NumArchitectureDeviceRegions, 2).SetAttribute(KMemoryRegionAttr_NoUserMap); +static_assert(KMemoryRegionType_Uart .GetValue() == (0x1D)); +static_assert(KMemoryRegionType_InterruptCpuInterface.GetValue() == (0x2D | KMemoryRegionAttr_NoUserMap)); +static_assert(KMemoryRegionType_InterruptDistributor .GetValue() == (0x4D | KMemoryRegionAttr_NoUserMap)); diff --git a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_memory_region_device_types.inc b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_memory_region_device_types.inc new file mode 100644 index 000000000..65f6fe8cd --- /dev/null +++ b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_memory_region_device_types.inc @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* All architectures must define NumArchitectureDeviceRegions. */ +constexpr inline const auto NumArchitectureDeviceRegions = 3; + +constexpr inline const auto KMemoryRegionType_Uart = KMemoryRegionType_ArchDeviceBase.DeriveSparse(0, NumArchitectureDeviceRegions, 0); +constexpr inline const auto KMemoryRegionType_InterruptCpuInterface = KMemoryRegionType_ArchDeviceBase.DeriveSparse(0, NumArchitectureDeviceRegions, 1).SetAttribute(KMemoryRegionAttr_NoUserMap); +constexpr inline const auto KMemoryRegionType_InterruptDistributor = KMemoryRegionType_ArchDeviceBase.DeriveSparse(0, NumArchitectureDeviceRegions, 2).SetAttribute(KMemoryRegionAttr_NoUserMap); +static_assert(KMemoryRegionType_Uart .GetValue() == (0x1D)); +static_assert(KMemoryRegionType_InterruptCpuInterface.GetValue() == (0x2D | KMemoryRegionAttr_NoUserMap)); +static_assert(KMemoryRegionType_InterruptDistributor .GetValue() == (0x4D | KMemoryRegionAttr_NoUserMap)); diff --git a/libraries/libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_memory_layout.board.nintendo_nx.hpp b/libraries/libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_memory_layout.hpp similarity index 100% rename from libraries/libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_memory_layout.board.nintendo_nx.hpp rename to libraries/libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_memory_layout.hpp diff --git a/libraries/libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_memory_region_device_types.inc b/libraries/libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_memory_region_device_types.inc new file mode 100644 index 000000000..0a81445bd --- /dev/null +++ b/libraries/libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_memory_region_device_types.inc @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* All architectures must define NumBoardDeviceRegions. */ +constexpr inline const auto NumBoardDeviceRegions = 5; + /* UNUSED: .Derive(NumBoardDeviceRegions, 0); */ +constexpr inline const auto KMemoryRegionType_MemoryController = KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 1).SetAttribute(KMemoryRegionAttr_NoUserMap); +constexpr inline const auto KMemoryRegionType_MemoryController1 = KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 2).SetAttribute(KMemoryRegionAttr_NoUserMap); +constexpr inline const auto KMemoryRegionType_MemoryController0 = KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 3).SetAttribute(KMemoryRegionAttr_NoUserMap); +constexpr inline const auto KMemoryRegionType_PowerManagementController = KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 4).DeriveTransition(); +static_assert(KMemoryRegionType_MemoryController .GetValue() == (0x55 | KMemoryRegionAttr_NoUserMap)); +static_assert(KMemoryRegionType_MemoryController1 .GetValue() == (0x65 | KMemoryRegionAttr_NoUserMap)); +static_assert(KMemoryRegionType_MemoryController0 .GetValue() == (0x95 | KMemoryRegionAttr_NoUserMap)); +static_assert(KMemoryRegionType_PowerManagementController.GetValue() == (0x1A5)); diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_memory_layout.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_memory_layout.hpp index 814e64ab8..e186d4cf4 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_memory_layout.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_memory_layout.hpp @@ -16,9 +16,10 @@ #pragma once #include #include +#include #if defined(ATMOSPHERE_BOARD_NINTENDO_NX) - #include + #include #else #error "Unknown board for KMemoryLayout" #endif @@ -52,385 +53,6 @@ namespace ams::kern { constexpr size_t KernelResourceSize = KernelPageTableHeapSize + KernelInitialPageHeapSize + KernelSlabHeapSize; - enum KMemoryRegionType : u32 { - KMemoryRegionAttr_CarveoutProtected = 0x04000000, - KMemoryRegionAttr_DidKernelMap = 0x08000000, - KMemoryRegionAttr_ShouldKernelMap = 0x10000000, - KMemoryRegionAttr_UserReadOnly = 0x20000000, - KMemoryRegionAttr_NoUserMap = 0x40000000, - KMemoryRegionAttr_LinearMapped = 0x80000000, - - KMemoryRegionType_None = 0, - KMemoryRegionType_Kernel = 1, - KMemoryRegionType_Dram = 2, - KMemoryRegionType_CoreLocal = 4, - - KMemoryRegionType_VirtualKernelPtHeap = 0x2A, - KMemoryRegionType_VirtualKernelTraceBuffer = 0x4A, - KMemoryRegionType_VirtualKernelInitPt = 0x19A, - - KMemoryRegionType_VirtualDramMetadataPool = 0x29A, - KMemoryRegionType_VirtualDramManagedPool = 0x31A, - KMemoryRegionType_VirtualDramApplicationPool = 0x271A, - KMemoryRegionType_VirtualDramAppletPool = 0x1B1A, - KMemoryRegionType_VirtualDramSystemPool = 0x2B1A, - KMemoryRegionType_VirtualDramSystemNonSecurePool = 0x331A, - - KMemoryRegionType_Uart = 0x1D, - KMemoryRegionType_InterruptDistributor = 0x4D | KMemoryRegionAttr_NoUserMap, - KMemoryRegionType_InterruptCpuInterface = 0x2D | KMemoryRegionAttr_NoUserMap, - - KMemoryRegionType_MemoryController = 0x55, - KMemoryRegionType_MemoryController0 = 0x95, - KMemoryRegionType_MemoryController1 = 0x65, - KMemoryRegionType_PowerManagementController = 0x1A5, - - KMemoryRegionType_KernelAutoMap = KMemoryRegionType_Kernel | KMemoryRegionAttr_ShouldKernelMap, - - KMemoryRegionType_KernelTemp = 0x31, - - KMemoryRegionType_KernelCode = 0x19, - KMemoryRegionType_KernelStack = 0x29, - KMemoryRegionType_KernelMisc = 0x49, - KMemoryRegionType_KernelSlab = 0x89, - - KMemoryRegionType_KernelMiscMainStack = 0xB49, - KMemoryRegionType_KernelMiscMappedDevice = 0xD49, - KMemoryRegionType_KernelMiscIdleStack = 0x1349, - KMemoryRegionType_KernelMiscUnknownDebug = 0x1549, - KMemoryRegionType_KernelMiscExceptionStack = 0x2349, - - KMemoryRegionType_DramLinearMapped = KMemoryRegionType_Dram | KMemoryRegionAttr_LinearMapped, - - KMemoryRegionType_DramReservedEarly = 0x16 | KMemoryRegionAttr_NoUserMap, - KMemoryRegionType_DramPoolPartition = 0x26 | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_LinearMapped, - KMemoryRegionType_DramMetadataPool = 0x166 | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_CarveoutProtected, - - KMemoryRegionType_DramNonKernel = 0x1A6 | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_LinearMapped, - - KMemoryRegionType_DramApplicationPool = 0x7A6 | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_LinearMapped, - KMemoryRegionType_DramAppletPool = 0xBA6 | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_LinearMapped, - KMemoryRegionType_DramSystemNonSecurePool = 0xDA6 | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_LinearMapped, - KMemoryRegionType_DramSystemPool = 0x13A6 | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_CarveoutProtected, - - KMemoryRegionType_DramKernel = 0xE | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_CarveoutProtected, - KMemoryRegionType_DramKernelCode = 0xCE | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_CarveoutProtected, - KMemoryRegionType_DramKernelSlab = 0x14E | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_CarveoutProtected, - KMemoryRegionType_DramKernelPtHeap = 0x24E | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_LinearMapped, - KMemoryRegionType_DramKernelInitPt = 0x44E | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_LinearMapped, - - /* These regions aren't normally mapped in retail kernel. */ - KMemoryRegionType_KernelTraceBuffer = 0xA6 | KMemoryRegionAttr_UserReadOnly | KMemoryRegionAttr_LinearMapped, - KMemoryRegionType_OnMemoryBootImage = 0x156, - KMemoryRegionType_DTB = 0x256, - }; - - constexpr ALWAYS_INLINE KMemoryRegionType GetTypeForVirtualLinearMapping(u32 type_id) { - if (type_id == (type_id | KMemoryRegionType_KernelTraceBuffer)) { - return KMemoryRegionType_VirtualKernelTraceBuffer; - } else if (type_id == (type_id | KMemoryRegionType_DramKernelPtHeap)) { - return KMemoryRegionType_VirtualKernelPtHeap; - } else { - return KMemoryRegionType_Dram; - } - } - - class KMemoryRegionTree; - - class KMemoryRegion : public util::IntrusiveRedBlackTreeBaseNode { - NON_COPYABLE(KMemoryRegion); - NON_MOVEABLE(KMemoryRegion); - private: - friend class KMemoryRegionTree; - private: - uintptr_t address; - uintptr_t pair_address; - size_t region_size; - u32 attributes; - u32 type_id; - public: - static constexpr ALWAYS_INLINE int Compare(const KMemoryRegion &lhs, const KMemoryRegion &rhs) { - if (lhs.GetAddress() < rhs.GetAddress()) { - return -1; - } else if (lhs.GetAddress() <= rhs.GetLastAddress()) { - return 0; - } else { - return 1; - } - } - public: - constexpr ALWAYS_INLINE KMemoryRegion() : address(0), pair_address(0), region_size(0), attributes(0), type_id(0) { /* ... */ } - constexpr ALWAYS_INLINE KMemoryRegion(uintptr_t a, size_t rs, uintptr_t p, u32 r, u32 t) : - address(a), pair_address(p), region_size(rs), attributes(r), type_id(t) - { - /* ... */ - } - constexpr ALWAYS_INLINE KMemoryRegion(uintptr_t a, size_t rs, u32 r, u32 t) : KMemoryRegion(a, rs, std::numeric_limits::max(), r, t) { /* ... */ } - private: - constexpr ALWAYS_INLINE void Reset(uintptr_t a, uintptr_t rs, uintptr_t p, u32 r, u32 t) { - this->address = a; - this->pair_address = p; - this->region_size = rs; - this->attributes = r; - this->type_id = t; - } - public: - constexpr ALWAYS_INLINE uintptr_t GetAddress() const { - return this->address; - } - - constexpr ALWAYS_INLINE uintptr_t GetPairAddress() const { - return this->pair_address; - } - - constexpr ALWAYS_INLINE size_t GetSize() const { - return this->region_size; - } - - constexpr ALWAYS_INLINE uintptr_t GetEndAddress() const { - return this->GetAddress() + this->GetSize(); - } - - constexpr ALWAYS_INLINE uintptr_t GetLastAddress() const { - return this->GetEndAddress() - 1; - } - - constexpr ALWAYS_INLINE u32 GetAttributes() const { - return this->attributes; - } - - constexpr ALWAYS_INLINE u32 GetType() const { - return this->type_id; - } - - constexpr ALWAYS_INLINE void SetType(u32 type) { - MESOSPHERE_INIT_ABORT_UNLESS(this->CanDerive(type)); - this->type_id = type; - } - - constexpr ALWAYS_INLINE bool Contains(uintptr_t address) const { - return this->GetAddress() <= address && address <= this->GetLastAddress(); - } - - constexpr ALWAYS_INLINE bool IsDerivedFrom(u32 type) const { - return (this->GetType() | type) == this->GetType(); - } - - constexpr ALWAYS_INLINE bool HasTypeAttribute(KMemoryRegionType attr) const { - return (this->GetType() | attr) == this->GetType(); - } - - constexpr ALWAYS_INLINE bool CanDerive(u32 type) const { - return (this->GetType() | type) == type; - } - - constexpr ALWAYS_INLINE void SetPairAddress(uintptr_t a) { - this->pair_address = a; - } - - constexpr ALWAYS_INLINE void SetTypeAttribute(KMemoryRegionType attr) { - this->type_id |= attr; - } - }; - static_assert(std::is_trivially_destructible::value); - - class KMemoryRegionTree { - public: - struct DerivedRegionExtents { - const KMemoryRegion *first_region; - const KMemoryRegion *last_region; - - constexpr DerivedRegionExtents() : first_region(nullptr), last_region(nullptr) { /* ... */ } - - constexpr ALWAYS_INLINE uintptr_t GetAddress() const { - return this->first_region->GetAddress(); - } - - constexpr ALWAYS_INLINE uintptr_t GetEndAddress() const { - return this->last_region->GetEndAddress(); - } - - constexpr ALWAYS_INLINE size_t GetSize() const { - return this->GetEndAddress() - this->GetAddress(); - } - - constexpr ALWAYS_INLINE uintptr_t GetLastAddress() const { - return this->GetEndAddress() - 1; - } - }; - private: - using TreeType = util::IntrusiveRedBlackTreeBaseTraits::TreeType; - public: - using value_type = TreeType::value_type; - using size_type = TreeType::size_type; - using difference_type = TreeType::difference_type; - using pointer = TreeType::pointer; - using const_pointer = TreeType::const_pointer; - using reference = TreeType::reference; - using const_reference = TreeType::const_reference; - using iterator = TreeType::iterator; - using const_iterator = TreeType::const_iterator; - private: - TreeType tree; - public: - constexpr ALWAYS_INLINE KMemoryRegionTree() : tree() { /* ... */ } - public: - KMemoryRegion *FindModifiable(uintptr_t address) { - if (auto it = this->find(KMemoryRegion(address, 1, 0, 0)); it != this->end()) { - return std::addressof(*it); - } else { - return nullptr; - } - } - - const KMemoryRegion *Find(uintptr_t address) const { - if (auto it = this->find(KMemoryRegion(address, 1, 0, 0)); it != this->cend()) { - return std::addressof(*it); - } else { - return nullptr; - } - } - - const KMemoryRegion *FindByType(u32 type_id) const { - for (auto it = this->cbegin(); it != this->cend(); ++it) { - if (it->GetType() == type_id) { - return std::addressof(*it); - } - } - return nullptr; - } - - const KMemoryRegion *FindByTypeAndAttribute(u32 type_id, u32 attr) const { - for (auto it = this->cbegin(); it != this->cend(); ++it) { - if (it->GetType() == type_id && it->GetAttributes() == attr) { - return std::addressof(*it); - } - } - return nullptr; - } - - const KMemoryRegion *FindFirstDerived(u32 type_id) const { - for (auto it = this->cbegin(); it != this->cend(); it++) { - if (it->IsDerivedFrom(type_id)) { - return std::addressof(*it); - } - } - return nullptr; - } - - const KMemoryRegion *FindLastDerived(u32 type_id) const { - const KMemoryRegion *region = nullptr; - for (auto it = this->begin(); it != this->end(); it++) { - if (it->IsDerivedFrom(type_id)) { - region = std::addressof(*it); - } - } - return region; - } - - - DerivedRegionExtents GetDerivedRegionExtents(u32 type_id) const { - DerivedRegionExtents extents; - - MESOSPHERE_INIT_ABORT_UNLESS(extents.first_region == nullptr); - MESOSPHERE_INIT_ABORT_UNLESS(extents.last_region == nullptr); - - for (auto it = this->cbegin(); it != this->cend(); it++) { - if (it->IsDerivedFrom(type_id)) { - if (extents.first_region == nullptr) { - extents.first_region = std::addressof(*it); - } - extents.last_region = std::addressof(*it); - } - } - - MESOSPHERE_INIT_ABORT_UNLESS(extents.first_region != nullptr); - MESOSPHERE_INIT_ABORT_UNLESS(extents.last_region != nullptr); - - return extents; - } - public: - NOINLINE void InsertDirectly(uintptr_t address, size_t size, u32 attr = 0, u32 type_id = 0); - NOINLINE bool Insert(uintptr_t address, size_t size, u32 type_id, u32 new_attr = 0, u32 old_attr = 0); - - NOINLINE KVirtualAddress GetRandomAlignedRegion(size_t size, size_t alignment, u32 type_id); - - ALWAYS_INLINE KVirtualAddress GetRandomAlignedRegionWithGuard(size_t size, size_t alignment, u32 type_id, size_t guard_size) { - return this->GetRandomAlignedRegion(size + 2 * guard_size, alignment, type_id) + guard_size; - } - public: - /* Iterator accessors. */ - iterator begin() { - return this->tree.begin(); - } - - const_iterator begin() const { - return this->tree.begin(); - } - - iterator end() { - return this->tree.end(); - } - - const_iterator end() const { - return this->tree.end(); - } - - const_iterator cbegin() const { - return this->begin(); - } - - const_iterator cend() const { - return this->end(); - } - - iterator iterator_to(reference ref) { - return this->tree.iterator_to(ref); - } - - const_iterator iterator_to(const_reference ref) const { - return this->tree.iterator_to(ref); - } - - /* Content management. */ - bool empty() const { - return this->tree.empty(); - } - - reference back() { - return this->tree.back(); - } - - const_reference back() const { - return this->tree.back(); - } - - reference front() { - return this->tree.front(); - } - - const_reference front() const { - return this->tree.front(); - } - - /* GCC over-eagerly inlines this operation. */ - NOINLINE iterator insert(reference ref) { - return this->tree.insert(ref); - } - - NOINLINE iterator erase(iterator it) { - return this->tree.erase(it); - } - - iterator find(const_reference ref) const { - return this->tree.find(ref); - } - - iterator nfind(const_reference ref) const { - return this->tree.nfind(ref); - } - }; - class KMemoryLayout { private: static /* constinit */ inline uintptr_t s_linear_phys_to_virt_diff; @@ -512,21 +134,19 @@ namespace ams::kern { static NOINLINE KVirtualAddress GetExceptionStackTopAddress(s32 core_id) { return GetStackTopAddress(core_id, KMemoryRegionType_KernelMiscExceptionStack); } static NOINLINE KVirtualAddress GetSlabRegionAddress() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_KernelSlab)).GetAddress(); } - static NOINLINE KVirtualAddress GetCoreLocalRegionAddress() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_CoreLocal)).GetAddress(); } + static NOINLINE KVirtualAddress GetCoreLocalRegionAddress() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_CoreLocalRegion)).GetAddress(); } - static NOINLINE KVirtualAddress GetInterruptDistributorAddress() { return Dereference(GetPhysicalMemoryRegionTree().FindFirstDerived(KMemoryRegionType_InterruptDistributor)).GetPairAddress(); } - static NOINLINE KVirtualAddress GetInterruptCpuInterfaceAddress() { return Dereference(GetPhysicalMemoryRegionTree().FindFirstDerived(KMemoryRegionType_InterruptCpuInterface)).GetPairAddress(); } - static NOINLINE KVirtualAddress GetUartAddress() { return Dereference(GetPhysicalMemoryRegionTree().FindFirstDerived(KMemoryRegionType_Uart)).GetPairAddress(); } + static NOINLINE const KMemoryRegion &GetDeviceRegion(KMemoryRegionType type) { return Dereference(GetPhysicalMemoryRegionTree().FindFirstDerived(type)); } + static KPhysicalAddress GetDevicePhysicalAddress(KMemoryRegionType type) { return GetDeviceRegion(type).GetAddress(); } + static KVirtualAddress GetDeviceVirtualAddress(KMemoryRegionType type) { return GetDeviceRegion(type).GetPairAddress(); } - static NOINLINE const KMemoryRegion &GetMemoryControllerRegion() { return Dereference(GetPhysicalMemoryRegionTree().FindFirstDerived(KMemoryRegionType_MemoryController)); } + static NOINLINE const KMemoryRegion &GetPoolManagementRegion() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_DramPoolManagement)); } + static NOINLINE const KMemoryRegion &GetPageTableHeapRegion() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_VirtualDramKernelPtHeap)); } + static NOINLINE const KMemoryRegion &GetKernelStackRegion() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_KernelStack)); } + static NOINLINE const KMemoryRegion &GetTempRegion() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_KernelTemp)); } + static NOINLINE const KMemoryRegion &GetCoreLocalRegion() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_CoreLocalRegion)); } - static NOINLINE const KMemoryRegion &GetMetadataPoolRegion() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_VirtualDramMetadataPool)); } - static NOINLINE const KMemoryRegion &GetPageTableHeapRegion() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_VirtualKernelPtHeap)); } - static NOINLINE const KMemoryRegion &GetKernelStackRegion() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_KernelStack)); } - static NOINLINE const KMemoryRegion &GetTempRegion() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_KernelTemp)); } - static NOINLINE const KMemoryRegion &GetCoreLocalRegion() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_CoreLocal)); } - - static NOINLINE const KMemoryRegion &GetKernelTraceBufferRegion() { return Dereference(GetVirtualLinearMemoryRegionTree().FindByType(KMemoryRegionType_VirtualKernelTraceBuffer)); } + static NOINLINE const KMemoryRegion &GetKernelTraceBufferRegion() { return Dereference(GetVirtualLinearMemoryRegionTree().FindByType(KMemoryRegionType_VirtualDramKernelTraceBuffer)); } static NOINLINE const KMemoryRegion &GetVirtualLinearRegion(KVirtualAddress address) { return Dereference(FindLinear(address)); } @@ -534,21 +154,21 @@ namespace ams::kern { static NOINLINE const KMemoryRegion *GetPhysicalOnMemoryBootImageRegion() { return GetPhysicalMemoryRegionTree().FindFirstDerived(KMemoryRegionType_OnMemoryBootImage); } static NOINLINE const KMemoryRegion *GetPhysicalDTBRegion() { return GetPhysicalMemoryRegionTree().FindFirstDerived(KMemoryRegionType_DTB); } - static NOINLINE bool IsHeapPhysicalAddress(const KMemoryRegion *®ion, KPhysicalAddress address) { return IsTypedAddress(region, address, GetPhysicalLinearMemoryRegionTree(), KMemoryRegionType_DramNonKernel); } - static NOINLINE bool IsHeapVirtualAddress(const KMemoryRegion *®ion, KVirtualAddress address) { return IsTypedAddress(region, address, GetVirtualLinearMemoryRegionTree(), KMemoryRegionType_VirtualDramManagedPool); } + static NOINLINE bool IsHeapPhysicalAddress(const KMemoryRegion *®ion, KPhysicalAddress address) { return IsTypedAddress(region, address, GetPhysicalLinearMemoryRegionTree(), KMemoryRegionType_DramUserPool); } + static NOINLINE bool IsHeapVirtualAddress(const KMemoryRegion *®ion, KVirtualAddress address) { return IsTypedAddress(region, address, GetVirtualLinearMemoryRegionTree(), KMemoryRegionType_VirtualDramUserPool); } - static NOINLINE bool IsHeapPhysicalAddress(const KMemoryRegion *®ion, KPhysicalAddress address, size_t size) { return IsTypedAddress(region, address, size, GetPhysicalLinearMemoryRegionTree(), KMemoryRegionType_DramNonKernel); } - static NOINLINE bool IsHeapVirtualAddress(const KMemoryRegion *®ion, KVirtualAddress address, size_t size) { return IsTypedAddress(region, address, size, GetVirtualLinearMemoryRegionTree(), KMemoryRegionType_VirtualDramManagedPool); } + static NOINLINE bool IsHeapPhysicalAddress(const KMemoryRegion *®ion, KPhysicalAddress address, size_t size) { return IsTypedAddress(region, address, size, GetPhysicalLinearMemoryRegionTree(), KMemoryRegionType_DramUserPool); } + static NOINLINE bool IsHeapVirtualAddress(const KMemoryRegion *®ion, KVirtualAddress address, size_t size) { return IsTypedAddress(region, address, size, GetVirtualLinearMemoryRegionTree(), KMemoryRegionType_VirtualDramUserPool); } - static NOINLINE bool IsLinearMappedPhysicalAddress(const KMemoryRegion *®ion, KPhysicalAddress address) { return IsTypedAddress(region, address, GetPhysicalLinearMemoryRegionTree(), KMemoryRegionAttr_LinearMapped); } - static NOINLINE bool IsLinearMappedPhysicalAddress(const KMemoryRegion *®ion, KPhysicalAddress address, size_t size) { return IsTypedAddress(region, address, size, GetPhysicalLinearMemoryRegionTree(), KMemoryRegionAttr_LinearMapped); } + static NOINLINE bool IsLinearMappedPhysicalAddress(const KMemoryRegion *®ion, KPhysicalAddress address) { return IsTypedAddress(region, address, GetPhysicalLinearMemoryRegionTree(), static_cast(KMemoryRegionAttr_LinearMapped)); } + static NOINLINE bool IsLinearMappedPhysicalAddress(const KMemoryRegion *®ion, KPhysicalAddress address, size_t size) { return IsTypedAddress(region, address, size, GetPhysicalLinearMemoryRegionTree(), static_cast(KMemoryRegionAttr_LinearMapped)); } static NOINLINE std::tuple GetTotalAndKernelMemorySizes() { size_t total_size = 0, kernel_size = 0; for (const auto ®ion : GetPhysicalMemoryRegionTree()) { if (region.IsDerivedFrom(KMemoryRegionType_Dram)) { total_size += region.GetSize(); - if (!region.IsDerivedFrom(KMemoryRegionType_DramNonKernel)) { + if (!region.IsDerivedFrom(KMemoryRegionType_DramUserPool)) { kernel_size += region.GetSize(); } } @@ -576,14 +196,14 @@ namespace ams::kern { static NOINLINE auto GetMainMemoryPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_Dram); } static NOINLINE auto GetCarveoutRegionExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionAttr_CarveoutProtected); } - static NOINLINE auto GetKernelRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernel); } + static NOINLINE auto GetKernelRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelBase); } static NOINLINE auto GetKernelCodeRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelCode); } static NOINLINE auto GetKernelSlabRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelSlab); } static NOINLINE auto GetKernelPageTableHeapRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelPtHeap); } static NOINLINE auto GetKernelInitPageTableRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelInitPt); } + static NOINLINE auto GetKernelPoolManagementRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramPoolManagement); } static NOINLINE auto GetKernelPoolPartitionRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramPoolPartition); } - static NOINLINE auto GetKernelMetadataPoolRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramMetadataPool); } static NOINLINE auto GetKernelSystemPoolRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramSystemPool); } static NOINLINE auto GetKernelSystemNonSecurePoolRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramSystemNonSecurePool); } static NOINLINE auto GetKernelAppletPoolRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramAppletPool); } diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_memory_region.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_memory_region.hpp new file mode 100644 index 000000000..a04c32d11 --- /dev/null +++ b/libraries/libmesosphere/include/mesosphere/kern_k_memory_region.hpp @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include +#include + +namespace ams::kern { + + class KMemoryRegionTree; + + class KMemoryRegion : public util::IntrusiveRedBlackTreeBaseNode { + NON_COPYABLE(KMemoryRegion); + NON_MOVEABLE(KMemoryRegion); + private: + friend class KMemoryRegionTree; + private: + uintptr_t address; + uintptr_t pair_address; + size_t region_size; + u32 attributes; + u32 type_id; + public: + static constexpr ALWAYS_INLINE int Compare(const KMemoryRegion &lhs, const KMemoryRegion &rhs) { + if (lhs.GetAddress() < rhs.GetAddress()) { + return -1; + } else if (lhs.GetAddress() <= rhs.GetLastAddress()) { + return 0; + } else { + return 1; + } + } + public: + constexpr ALWAYS_INLINE KMemoryRegion() : address(0), pair_address(0), region_size(0), attributes(0), type_id(0) { /* ... */ } + constexpr ALWAYS_INLINE KMemoryRegion(uintptr_t a, size_t rs, uintptr_t p, u32 r, u32 t) : + address(a), pair_address(p), region_size(rs), attributes(r), type_id(t) + { + /* ... */ + } + constexpr ALWAYS_INLINE KMemoryRegion(uintptr_t a, size_t rs, u32 r, u32 t) : KMemoryRegion(a, rs, std::numeric_limits::max(), r, t) { /* ... */ } + private: + constexpr ALWAYS_INLINE void Reset(uintptr_t a, uintptr_t rs, uintptr_t p, u32 r, u32 t) { + this->address = a; + this->pair_address = p; + this->region_size = rs; + this->attributes = r; + this->type_id = t; + } + public: + constexpr ALWAYS_INLINE uintptr_t GetAddress() const { + return this->address; + } + + constexpr ALWAYS_INLINE uintptr_t GetPairAddress() const { + return this->pair_address; + } + + constexpr ALWAYS_INLINE size_t GetSize() const { + return this->region_size; + } + + constexpr ALWAYS_INLINE uintptr_t GetEndAddress() const { + return this->GetAddress() + this->GetSize(); + } + + constexpr ALWAYS_INLINE uintptr_t GetLastAddress() const { + return this->GetEndAddress() - 1; + } + + constexpr ALWAYS_INLINE u32 GetAttributes() const { + return this->attributes; + } + + constexpr ALWAYS_INLINE u32 GetType() const { + return this->type_id; + } + + constexpr ALWAYS_INLINE void SetType(u32 type) { + MESOSPHERE_INIT_ABORT_UNLESS(this->CanDerive(type)); + this->type_id = type; + } + + constexpr ALWAYS_INLINE bool Contains(uintptr_t address) const { + return this->GetAddress() <= address && address <= this->GetLastAddress(); + } + + constexpr ALWAYS_INLINE bool IsDerivedFrom(u32 type) const { + return (this->GetType() | type) == this->GetType(); + } + + constexpr ALWAYS_INLINE bool HasTypeAttribute(KMemoryRegionAttr attr) const { + return (this->GetType() | attr) == this->GetType(); + } + + constexpr ALWAYS_INLINE bool CanDerive(u32 type) const { + return (this->GetType() | type) == type; + } + + constexpr ALWAYS_INLINE void SetPairAddress(uintptr_t a) { + this->pair_address = a; + } + + constexpr ALWAYS_INLINE void SetTypeAttribute(KMemoryRegionAttr attr) { + this->type_id |= attr; + } + }; + static_assert(std::is_trivially_destructible::value); + + class KMemoryRegionTree { + public: + struct DerivedRegionExtents { + const KMemoryRegion *first_region; + const KMemoryRegion *last_region; + + constexpr DerivedRegionExtents() : first_region(nullptr), last_region(nullptr) { /* ... */ } + + constexpr ALWAYS_INLINE uintptr_t GetAddress() const { + return this->first_region->GetAddress(); + } + + constexpr ALWAYS_INLINE uintptr_t GetEndAddress() const { + return this->last_region->GetEndAddress(); + } + + constexpr ALWAYS_INLINE size_t GetSize() const { + return this->GetEndAddress() - this->GetAddress(); + } + + constexpr ALWAYS_INLINE uintptr_t GetLastAddress() const { + return this->GetEndAddress() - 1; + } + }; + private: + using TreeType = util::IntrusiveRedBlackTreeBaseTraits::TreeType; + public: + using value_type = TreeType::value_type; + using size_type = TreeType::size_type; + using difference_type = TreeType::difference_type; + using pointer = TreeType::pointer; + using const_pointer = TreeType::const_pointer; + using reference = TreeType::reference; + using const_reference = TreeType::const_reference; + using iterator = TreeType::iterator; + using const_iterator = TreeType::const_iterator; + private: + TreeType tree; + public: + constexpr ALWAYS_INLINE KMemoryRegionTree() : tree() { /* ... */ } + public: + KMemoryRegion *FindModifiable(uintptr_t address) { + if (auto it = this->find(KMemoryRegion(address, 1, 0, 0)); it != this->end()) { + return std::addressof(*it); + } else { + return nullptr; + } + } + + const KMemoryRegion *Find(uintptr_t address) const { + if (auto it = this->find(KMemoryRegion(address, 1, 0, 0)); it != this->cend()) { + return std::addressof(*it); + } else { + return nullptr; + } + } + + const KMemoryRegion *FindByType(u32 type_id) const { + for (auto it = this->cbegin(); it != this->cend(); ++it) { + if (it->GetType() == type_id) { + return std::addressof(*it); + } + } + return nullptr; + } + + const KMemoryRegion *FindByTypeAndAttribute(u32 type_id, u32 attr) const { + for (auto it = this->cbegin(); it != this->cend(); ++it) { + if (it->GetType() == type_id && it->GetAttributes() == attr) { + return std::addressof(*it); + } + } + return nullptr; + } + + const KMemoryRegion *FindFirstDerived(u32 type_id) const { + for (auto it = this->cbegin(); it != this->cend(); it++) { + if (it->IsDerivedFrom(type_id)) { + return std::addressof(*it); + } + } + return nullptr; + } + + const KMemoryRegion *FindLastDerived(u32 type_id) const { + const KMemoryRegion *region = nullptr; + for (auto it = this->begin(); it != this->end(); it++) { + if (it->IsDerivedFrom(type_id)) { + region = std::addressof(*it); + } + } + return region; + } + + + DerivedRegionExtents GetDerivedRegionExtents(u32 type_id) const { + DerivedRegionExtents extents; + + MESOSPHERE_INIT_ABORT_UNLESS(extents.first_region == nullptr); + MESOSPHERE_INIT_ABORT_UNLESS(extents.last_region == nullptr); + + for (auto it = this->cbegin(); it != this->cend(); it++) { + if (it->IsDerivedFrom(type_id)) { + if (extents.first_region == nullptr) { + extents.first_region = std::addressof(*it); + } + extents.last_region = std::addressof(*it); + } + } + + MESOSPHERE_INIT_ABORT_UNLESS(extents.first_region != nullptr); + MESOSPHERE_INIT_ABORT_UNLESS(extents.last_region != nullptr); + + return extents; + } + public: + NOINLINE void InsertDirectly(uintptr_t address, size_t size, u32 attr = 0, u32 type_id = 0); + NOINLINE bool Insert(uintptr_t address, size_t size, u32 type_id, u32 new_attr = 0, u32 old_attr = 0); + + NOINLINE KVirtualAddress GetRandomAlignedRegion(size_t size, size_t alignment, u32 type_id); + + ALWAYS_INLINE KVirtualAddress GetRandomAlignedRegionWithGuard(size_t size, size_t alignment, u32 type_id, size_t guard_size) { + return this->GetRandomAlignedRegion(size + 2 * guard_size, alignment, type_id) + guard_size; + } + public: + /* Iterator accessors. */ + iterator begin() { + return this->tree.begin(); + } + + const_iterator begin() const { + return this->tree.begin(); + } + + iterator end() { + return this->tree.end(); + } + + const_iterator end() const { + return this->tree.end(); + } + + const_iterator cbegin() const { + return this->begin(); + } + + const_iterator cend() const { + return this->end(); + } + + iterator iterator_to(reference ref) { + return this->tree.iterator_to(ref); + } + + const_iterator iterator_to(const_reference ref) const { + return this->tree.iterator_to(ref); + } + + /* Content management. */ + bool empty() const { + return this->tree.empty(); + } + + reference back() { + return this->tree.back(); + } + + const_reference back() const { + return this->tree.back(); + } + + reference front() { + return this->tree.front(); + } + + const_reference front() const { + return this->tree.front(); + } + + /* GCC over-eagerly inlines this operation. */ + NOINLINE iterator insert(reference ref) { + return this->tree.insert(ref); + } + + NOINLINE iterator erase(iterator it) { + return this->tree.erase(it); + } + + iterator find(const_reference ref) const { + return this->tree.find(ref); + } + + iterator nfind(const_reference ref) const { + return this->tree.nfind(ref); + } + }; + +} diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_memory_region_type.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_memory_region_type.hpp new file mode 100644 index 000000000..be8b3e440 --- /dev/null +++ b/libraries/libmesosphere/include/mesosphere/kern_k_memory_region_type.hpp @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include + +namespace ams::kern { + + enum KMemoryRegionType : u32 {}; + + enum KMemoryRegionAttr : typename std::underlying_type::type { + KMemoryRegionAttr_CarveoutProtected = 0x04000000, + KMemoryRegionAttr_DidKernelMap = 0x08000000, + KMemoryRegionAttr_ShouldKernelMap = 0x10000000, + KMemoryRegionAttr_UserReadOnly = 0x20000000, + KMemoryRegionAttr_NoUserMap = 0x40000000, + KMemoryRegionAttr_LinearMapped = 0x80000000, + }; + + namespace impl { + + consteval size_t BitsForDeriveSparse(size_t n) { + return n + 1; + } + + consteval size_t BitsForDeriveDense(size_t n) { + AMS_ASSUME(n > 0); + + size_t low = 0, high = 1; + for (size_t i = 0; i < n - 1; ++i) { + if ((++low) == high) { + ++high; + low = 0; + } + } + return high + 1; + } + + class KMemoryRegionTypeValue { + private: + using ValueType = typename std::underlying_type::type; + private: + ValueType value; + size_t next_bit; + bool finalized; + bool sparse_only; + bool dense_only; + private: + consteval KMemoryRegionTypeValue(ValueType v) : value(v), next_bit(0), finalized(false), sparse_only(false), dense_only(false) { /* ... */ } + public: + consteval KMemoryRegionTypeValue() : KMemoryRegionTypeValue(0) { /* ... */ } + + consteval operator KMemoryRegionType() const { return static_cast(this->value); } + consteval ValueType GetValue() const { return this->value; } + + consteval const KMemoryRegionTypeValue &Finalize() { this->finalized = true; return *this; } + consteval const KMemoryRegionTypeValue &SetSparseOnly() { this->sparse_only = true; return *this; } + consteval const KMemoryRegionTypeValue &SetDenseOnly() { this->dense_only = true; return *this; } + + consteval KMemoryRegionTypeValue &SetAttribute(KMemoryRegionAttr attr) { AMS_ASSUME(!this->finalized); this->value |= attr; return *this; } + + consteval KMemoryRegionTypeValue DeriveInitial(size_t i, size_t next = BITSIZEOF(ValueType)) const { + AMS_ASSUME(!this->finalized); + AMS_ASSUME(!this->value); + AMS_ASSUME(!this->next_bit); + AMS_ASSUME(next > i); + + KMemoryRegionTypeValue new_type = *this; + new_type.value = (ValueType{1} << i); + new_type.next_bit = next; + return new_type; + } + + consteval KMemoryRegionTypeValue DeriveAttribute(KMemoryRegionAttr attr) const { + AMS_ASSUME(!this->finalized); + + KMemoryRegionTypeValue new_type = *this; + new_type.value |= attr; + return new_type; + } + + consteval KMemoryRegionTypeValue DeriveTransition(size_t ofs = 0, size_t adv = 1) const { + AMS_ASSUME(!this->finalized); + AMS_ASSUME(ofs < adv); + AMS_ASSUME(this->next_bit + adv <= BITSIZEOF(ValueType)); + + KMemoryRegionTypeValue new_type = *this; + new_type.value |= (ValueType{1} << (this->next_bit + ofs)); + new_type.next_bit += adv; + return new_type; + } + + consteval KMemoryRegionTypeValue DeriveSparse(size_t ofs, size_t n, size_t i) const { + AMS_ASSUME(!this->finalized); + AMS_ASSUME(!this->dense_only); + AMS_ASSUME(this->next_bit + ofs + n + 1 <= BITSIZEOF(ValueType)); + AMS_ASSUME(i < n); + + KMemoryRegionTypeValue new_type = *this; + new_type.value |= (ValueType{1} << (this->next_bit + ofs)); + new_type.value |= (ValueType{1} << (this->next_bit + ofs + 1 + i)); + new_type.next_bit += ofs + n + 1; + return new_type; + } + + consteval KMemoryRegionTypeValue Derive(size_t n, size_t i) const { + AMS_ASSUME(!this->finalized); + AMS_ASSUME(!this->sparse_only); + AMS_ASSUME(this->next_bit + BitsForDeriveDense(n) <= BITSIZEOF(ValueType)); + AMS_ASSUME(i < n); + + size_t low = 0, high = 1; + for (size_t j = 0; j < i; ++j) { + if ((++low) == high) { + ++high; + low = 0; + } + } + AMS_ASSUME(high < BitsForDeriveDense(n)); + + + KMemoryRegionTypeValue new_type = *this; + new_type.value |= (ValueType{1} << (this->next_bit + low)); + new_type.value |= (ValueType{1} << (this->next_bit + high)); + new_type.next_bit += BitsForDeriveDense(n); + return new_type; + } + + consteval KMemoryRegionTypeValue Advance(size_t n) const { + AMS_ASSUME(!this->finalized); + AMS_ASSUME(this->next_bit + n <= BITSIZEOF(ValueType)); + + KMemoryRegionTypeValue new_type = *this; + new_type.next_bit += n; + return new_type; + } + + constexpr ALWAYS_INLINE bool IsAncestorOf(ValueType v) const { + return (this->value | v) == v; + } + }; + + } + + constexpr inline const auto KMemoryRegionType_None = impl::KMemoryRegionTypeValue(); + + constexpr inline const auto KMemoryRegionType_Kernel = KMemoryRegionType_None.DeriveInitial(0, 2); + constexpr inline const auto KMemoryRegionType_Dram = KMemoryRegionType_None.DeriveInitial(1, 2); + constexpr inline const auto KMemoryRegionType_CoreLocalRegion = KMemoryRegionType_None.DeriveInitial(2).Finalize(); + static_assert(KMemoryRegionType_Kernel .GetValue() == 0x1); + static_assert(KMemoryRegionType_Dram .GetValue() == 0x2); + static_assert(KMemoryRegionType_CoreLocalRegion.GetValue() == 0x4); + + constexpr inline const auto KMemoryRegionType_DramKernelBase = KMemoryRegionType_Dram.DeriveSparse(0, 3, 0).SetAttribute(KMemoryRegionAttr_NoUserMap).SetAttribute(KMemoryRegionAttr_CarveoutProtected); + constexpr inline const auto KMemoryRegionType_DramReservedBase = KMemoryRegionType_Dram.DeriveSparse(0, 3, 1); + constexpr inline const auto KMemoryRegionType_DramHeapBase = KMemoryRegionType_Dram.DeriveSparse(0, 3, 2).SetAttribute(KMemoryRegionAttr_LinearMapped); + static_assert(KMemoryRegionType_DramKernelBase .GetValue() == (0xE | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap)); + static_assert(KMemoryRegionType_DramReservedBase.GetValue() == (0x16)); + static_assert(KMemoryRegionType_DramHeapBase .GetValue() == (0x26 | KMemoryRegionAttr_LinearMapped)); + + constexpr inline const auto KMemoryRegionType_DramKernelCode = KMemoryRegionType_DramKernelBase.DeriveSparse(0, 4, 0); + constexpr inline const auto KMemoryRegionType_DramKernelSlab = KMemoryRegionType_DramKernelBase.DeriveSparse(0, 4, 1); + constexpr inline const auto KMemoryRegionType_DramKernelPtHeap = KMemoryRegionType_DramKernelBase.DeriveSparse(0, 4, 2).SetAttribute(KMemoryRegionAttr_LinearMapped); + constexpr inline const auto KMemoryRegionType_DramKernelInitPt = KMemoryRegionType_DramKernelBase.DeriveSparse(0, 4, 3).SetAttribute(KMemoryRegionAttr_LinearMapped); + static_assert(KMemoryRegionType_DramKernelCode .GetValue() == (0xCE | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap)); + static_assert(KMemoryRegionType_DramKernelSlab .GetValue() == (0x14E | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap)); + static_assert(KMemoryRegionType_DramKernelPtHeap.GetValue() == (0x24E | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_LinearMapped)); + static_assert(KMemoryRegionType_DramKernelInitPt.GetValue() == (0x44E | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_LinearMapped)); + + + constexpr inline const auto KMemoryRegionType_DramReservedEarly = KMemoryRegionType_DramReservedBase.DeriveAttribute(KMemoryRegionAttr_NoUserMap); + static_assert(KMemoryRegionType_DramReservedEarly.GetValue() == (0x16 | KMemoryRegionAttr_NoUserMap)); + + /* UNUSED: DeriveSparse(0, 3, 0); */ + constexpr inline const auto KMemoryRegionType_OnMemoryBootImage = KMemoryRegionType_DramReservedBase.DeriveSparse(0, 3, 1); + constexpr inline const auto KMemoryRegionType_DTB = KMemoryRegionType_DramReservedBase.DeriveSparse(0, 3, 2); + static_assert(KMemoryRegionType_OnMemoryBootImage.GetValue() == 0x156); + static_assert(KMemoryRegionType_DTB.GetValue() == 0x256); + + constexpr inline const auto KMemoryRegionType_KernelTraceBuffer = KMemoryRegionType_DramHeapBase.DeriveTransition(1, 3).SetAttribute(KMemoryRegionAttr_UserReadOnly); + static_assert(KMemoryRegionType_KernelTraceBuffer.GetValue() == (0xA6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_UserReadOnly)); + + constexpr inline const auto KMemoryRegionType_DramPoolPartition = KMemoryRegionType_DramHeapBase.DeriveAttribute(KMemoryRegionAttr_NoUserMap); + static_assert(KMemoryRegionType_DramPoolPartition.GetValue() == (0x26 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap)); + + constexpr inline const auto KMemoryRegionType_DramPoolManagement = KMemoryRegionType_DramPoolPartition.DeriveTransition(0, 2).DeriveTransition(); + constexpr inline const auto KMemoryRegionType_DramUserPool = KMemoryRegionType_DramPoolPartition.DeriveTransition(1, 2).DeriveTransition(); + static_assert(KMemoryRegionType_DramPoolManagement.GetValue() == (0x166 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap)); + static_assert(KMemoryRegionType_DramUserPool.GetValue() == (0x1A6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap)); + + constexpr inline const auto KMemoryRegionType_DramApplicationPool = KMemoryRegionType_DramUserPool.Derive(4, 0); + constexpr inline const auto KMemoryRegionType_DramAppletPool = KMemoryRegionType_DramUserPool.Derive(4, 1); + constexpr inline const auto KMemoryRegionType_DramSystemNonSecurePool = KMemoryRegionType_DramUserPool.Derive(4, 2); + constexpr inline const auto KMemoryRegionType_DramSystemPool = KMemoryRegionType_DramUserPool.Derive(4, 3).SetAttribute(KMemoryRegionAttr_CarveoutProtected); + static_assert(KMemoryRegionType_DramApplicationPool .GetValue() == (0x7A6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap)); + static_assert(KMemoryRegionType_DramAppletPool .GetValue() == (0xBA6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap)); + static_assert(KMemoryRegionType_DramSystemNonSecurePool.GetValue() == (0xDA6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap)); + static_assert(KMemoryRegionType_DramSystemPool .GetValue() == (0x13A6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_CarveoutProtected)); + + constexpr inline const auto KMemoryRegionType_VirtualDramHeapBase = KMemoryRegionType_Dram.DeriveSparse(1, 3, 0); + constexpr inline const auto KMemoryRegionType_VirtualDramKernelPtHeap = KMemoryRegionType_Dram.DeriveSparse(1, 3, 1); + constexpr inline const auto KMemoryRegionType_VirtualDramKernelTraceBuffer = KMemoryRegionType_Dram.DeriveSparse(1, 3, 2); + static_assert(KMemoryRegionType_VirtualDramHeapBase .GetValue() == 0x1A); + static_assert(KMemoryRegionType_VirtualDramKernelPtHeap .GetValue() == 0x2A); + static_assert(KMemoryRegionType_VirtualDramKernelTraceBuffer.GetValue() == 0x4A); + + constexpr inline const auto KMemoryRegionType_VirtualDramKernelInitPt = KMemoryRegionType_VirtualDramHeapBase.Derive(3, 0); + constexpr inline const auto KMemoryRegionType_VirtualDramPoolManagement = KMemoryRegionType_VirtualDramHeapBase.Derive(3, 1); + constexpr inline const auto KMemoryRegionType_VirtualDramUserPool = KMemoryRegionType_VirtualDramHeapBase.Derive(3, 2); + static_assert(KMemoryRegionType_VirtualDramKernelInitPt .GetValue() == 0x19A); + static_assert(KMemoryRegionType_VirtualDramPoolManagement.GetValue() == 0x29A); + static_assert(KMemoryRegionType_VirtualDramUserPool .GetValue() == 0x31A); + + /* NOTE: For unknown reason, the pools are derived out-of-order here. */ + /* It's worth eventually trying to understand why Nintendo made this choice. */ + /* UNUSED: .Derive(6, 0); */ + /* UNUSED: .Derive(6, 1); */ + constexpr inline const auto KMemoryRegionType_VirtualDramAppletPool = KMemoryRegionType_VirtualDramUserPool.Derive(6, 2); + constexpr inline const auto KMemoryRegionType_VirtualDramApplicationPool = KMemoryRegionType_VirtualDramUserPool.Derive(6, 3); + constexpr inline const auto KMemoryRegionType_VirtualDramSystemNonSecurePool = KMemoryRegionType_VirtualDramUserPool.Derive(6, 4); + constexpr inline const auto KMemoryRegionType_VirtualDramSystemPool = KMemoryRegionType_VirtualDramUserPool.Derive(6, 5); + static_assert(KMemoryRegionType_VirtualDramAppletPool .GetValue() == 0x1B1A); + static_assert(KMemoryRegionType_VirtualDramApplicationPool .GetValue() == 0x271A); + static_assert(KMemoryRegionType_VirtualDramSystemNonSecurePool.GetValue() == 0x2B1A); + static_assert(KMemoryRegionType_VirtualDramSystemPool .GetValue() == 0x331A); + + constexpr inline const auto KMemoryRegionType_ArchDeviceBase = KMemoryRegionType_Kernel.DeriveTransition(0, 1).SetSparseOnly(); + constexpr inline const auto KMemoryRegionType_BoardDeviceBase = KMemoryRegionType_Kernel.DeriveTransition(0, 2).SetDenseOnly(); + static_assert(KMemoryRegionType_ArchDeviceBase .GetValue() == 0x5); + static_assert(KMemoryRegionType_BoardDeviceBase.GetValue() == 0x5); + + #if defined(ATMOSPHERE_ARCH_ARM64) + #include + #elif defined(ATMOSPHERE_ARCH_ARM) + #include + #else + /* Default to no architecture devices. */ + constexpr inline const auto NumArchitectureDeviceRegions = 0; + #endif + static_assert(NumArchitectureDeviceRegions >= 0); + + #if defined(ATMOSPHERE_BOARD_NINTENDO_NX) + #include + #else + /* Default to no board devices. */ + constexpr inline const auto NumBoardDeviceRegions = 0; + #endif + static_assert(NumBoardDeviceRegions >= 0); + + constexpr inline const auto KMemoryRegionType_KernelCode = KMemoryRegionType_Kernel.DeriveSparse(1, 4, 0); + constexpr inline const auto KMemoryRegionType_KernelStack = KMemoryRegionType_Kernel.DeriveSparse(1, 4, 1); + constexpr inline const auto KMemoryRegionType_KernelMisc = KMemoryRegionType_Kernel.DeriveSparse(1, 4, 2); + constexpr inline const auto KMemoryRegionType_KernelSlab = KMemoryRegionType_Kernel.DeriveSparse(1, 4, 3); + static_assert(KMemoryRegionType_KernelCode .GetValue() == 0x19); + static_assert(KMemoryRegionType_KernelStack.GetValue() == 0x29); + static_assert(KMemoryRegionType_KernelMisc .GetValue() == 0x49); + static_assert(KMemoryRegionType_KernelSlab .GetValue() == 0x89); + + constexpr inline const auto KMemoryRegionType_KernelMiscDerivedBase = KMemoryRegionType_KernelMisc.DeriveTransition(); + static_assert(KMemoryRegionType_KernelMiscDerivedBase.GetValue() == 0x149); + + /* UNUSED: .Derive(7, 0); */ + constexpr inline const auto KMemoryRegionType_KernelMiscMainStack = KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 1); + constexpr inline const auto KMemoryRegionType_KernelMiscMappedDevice = KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 2); + constexpr inline const auto KMemoryRegionType_KernelMiscIdleStack = KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 3); + constexpr inline const auto KMemoryRegionType_KernelMiscUnknownDebug = KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 4); + /* UNUSED: .Derive(7, 5); */ + constexpr inline const auto KMemoryRegionType_KernelMiscExceptionStack = KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 6); + static_assert(KMemoryRegionType_KernelMiscMainStack .GetValue() == 0xB49); + static_assert(KMemoryRegionType_KernelMiscMappedDevice .GetValue() == 0xD49); + static_assert(KMemoryRegionType_KernelMiscIdleStack .GetValue() == 0x1349); + static_assert(KMemoryRegionType_KernelMiscUnknownDebug .GetValue() == 0x1549); + static_assert(KMemoryRegionType_KernelMiscExceptionStack.GetValue() == 0x2349); + + constexpr inline const auto KMemoryRegionType_KernelTemp = KMemoryRegionType_Kernel.Advance(2).Derive(2, 0); + static_assert(KMemoryRegionType_KernelTemp.GetValue() == 0x31); + + constexpr ALWAYS_INLINE KMemoryRegionType GetTypeForVirtualLinearMapping(u32 type_id) { + if (KMemoryRegionType_KernelTraceBuffer.IsAncestorOf(type_id)) { + return KMemoryRegionType_VirtualDramKernelTraceBuffer; + } else if (KMemoryRegionType_DramKernelPtHeap.IsAncestorOf(type_id)) { + return KMemoryRegionType_VirtualDramKernelPtHeap; + } else { + return KMemoryRegionType_Dram; + } + } + +} diff --git a/libraries/libmesosphere/source/arch/arm/kern_generic_interrupt_controller.inc b/libraries/libmesosphere/source/arch/arm/kern_generic_interrupt_controller.inc index 290701037..12fc57c2f 100644 --- a/libraries/libmesosphere/source/arch/arm/kern_generic_interrupt_controller.inc +++ b/libraries/libmesosphere/source/arch/arm/kern_generic_interrupt_controller.inc @@ -39,8 +39,8 @@ namespace ams::kern::arch::arm { void KInterruptController::Initialize(s32 core_id) { /* Setup pointers to ARM mmio. */ - this->gicd = GetPointer(KMemoryLayout::GetInterruptDistributorAddress()); - this->gicc = GetPointer(KMemoryLayout::GetInterruptCpuInterfaceAddress()); + this->gicd = GetPointer(KMemoryLayout::GetDeviceVirtualAddress(KMemoryRegionType_InterruptDistributor)); + this->gicc = GetPointer(KMemoryLayout::GetDeviceVirtualAddress(KMemoryRegionType_InterruptCpuInterface)); /* Clear CTLRs. */ this->gicc->ctlr = 0; diff --git a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_device_page_table.cpp b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_device_page_table.cpp index 4ada48c89..2140fe6e0 100644 --- a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_device_page_table.cpp +++ b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_device_page_table.cpp @@ -405,7 +405,7 @@ namespace ams::kern::board::nintendo::nx { void KDevicePageTable::Initialize() { /* Set the memory controller register address. */ - g_memory_controller_address = KMemoryLayout::GetMemoryControllerRegion().GetAddress(); + g_memory_controller_address = KMemoryLayout::GetDevicePhysicalAddress(KMemoryRegionType_MemoryController); /* Allocate a page to use as a reserved/no device table. */ const KVirtualAddress table_virt_addr = Kernel::GetPageTableManager().Allocate(); diff --git a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp index 5e23303c1..648284436 100644 --- a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp +++ b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp @@ -181,7 +181,7 @@ namespace ams::kern::board::nintendo::nx { /* Find the region for the address. */ const KMemoryRegion *region = KMemoryLayout::Find(KPhysicalAddress(address)); if (AMS_LIKELY(region != nullptr)) { - if (AMS_LIKELY(region->IsDerivedFrom(KMemoryRegionAttr_NoUserMap | KMemoryRegionType_MemoryController))) { + if (AMS_LIKELY(region->IsDerivedFrom(KMemoryRegionType_MemoryController))) { /* Get the offset within the region. */ const size_t offset = address - region->GetAddress(); MESOSPHERE_ABORT_UNLESS(offset < region->GetSize()); @@ -206,9 +206,9 @@ namespace ams::kern::board::nintendo::nx { } /* Memory controller is allowed if the register is whitelisted. */ - if (region->IsDerivedFrom(KMemoryRegionAttr_NoUserMap | KMemoryRegionType_MemoryController ) || - region->IsDerivedFrom(KMemoryRegionAttr_NoUserMap | KMemoryRegionType_MemoryController0) || - region->IsDerivedFrom(KMemoryRegionAttr_NoUserMap | KMemoryRegionType_MemoryController1)) + if (region->IsDerivedFrom(KMemoryRegionType_MemoryController ) || + region->IsDerivedFrom(KMemoryRegionType_MemoryController0) || + region->IsDerivedFrom(KMemoryRegionType_MemoryController1)) { /* Get the offset within the region. */ const size_t offset = address - region->GetAddress(); diff --git a/libraries/libmesosphere/source/kern_debug_log_impl.board.nintendo_nx.cpp b/libraries/libmesosphere/source/kern_debug_log_impl.board.nintendo_nx.cpp index dc90e1c9e..cb6d095b9 100644 --- a/libraries/libmesosphere/source/kern_debug_log_impl.board.nintendo_nx.cpp +++ b/libraries/libmesosphere/source/kern_debug_log_impl.board.nintendo_nx.cpp @@ -50,7 +50,7 @@ namespace ams::kern { bool KDebugLogImpl::Initialize() { /* Set the uart register base address. */ - g_uart_address = KMemoryLayout::GetUartAddress(); + g_uart_address = KMemoryLayout::GetDeviceVirtualAddress(KMemoryRegionType_Uart); /* Parameters for uart. */ constexpr u32 BaudRate = 115200; diff --git a/libraries/libmesosphere/source/kern_k_memory_layout.board.nintendo_nx.cpp b/libraries/libmesosphere/source/kern_k_memory_layout.board.nintendo_nx.cpp index 166113af9..e888d5bcf 100644 --- a/libraries/libmesosphere/source/kern_k_memory_layout.board.nintendo_nx.cpp +++ b/libraries/libmesosphere/source/kern_k_memory_layout.board.nintendo_nx.cpp @@ -27,9 +27,9 @@ namespace ams::kern { ALWAYS_INLINE bool SetupUartPhysicalMemoryRegion() { #if defined(MESOSPHERE_DEBUG_LOG_USE_UART_A) - return KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x70006000, 0x40, KMemoryRegionType_Uart | KMemoryRegionAttr_ShouldKernelMap); + return KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x70006000, 0x40, KMemoryRegionType_Uart | KMemoryRegionAttr_ShouldKernelMap); #elif defined(MESOSPHERE_DEBUG_LOG_USE_UART_B) - return KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x70006040, 0x40, KMemoryRegionType_Uart | KMemoryRegionAttr_ShouldKernelMap); + return KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x70006040, 0x40, KMemoryRegionType_Uart | KMemoryRegionAttr_ShouldKernelMap); #elif defined(MESOSPHERE_DEBUG_LOG_USE_UART_C) return KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x70006200, 0x100, KMemoryRegionType_Uart | KMemoryRegionAttr_ShouldKernelMap); #elif defined(MESOSPHERE_DEBUG_LOG_USE_UART_D) @@ -41,10 +41,10 @@ namespace ams::kern { ALWAYS_INLINE bool SetupPowerManagementControllerMemoryRegion() { /* For backwards compatibility, the PMC must remain mappable on < 2.0.0. */ - const auto pmc_type = GetTargetFirmware() >= TargetFirmware_2_0_0 ? (KMemoryRegionType_PowerManagementController | KMemoryRegionAttr_NoUserMap) : KMemoryRegionType_PowerManagementController; + const auto restrict_attr = GetTargetFirmware() >= TargetFirmware_2_0_0 ? KMemoryRegionAttr_NoUserMap : static_cast(0); - return KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x7000E000, 0x400, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap) && - KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x7000E400, 0xC00, pmc_type); + return KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x7000E000, 0x400, KMemoryRegionType_None | restrict_attr) && + KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x7000E400, 0xC00, KMemoryRegionType_PowerManagementController | restrict_attr); } void InsertPoolPartitionRegionIntoBothTrees(size_t start, size_t size, KMemoryRegionType phys_type, KMemoryRegionType virt_type, u32 &cur_attr) { @@ -95,7 +95,7 @@ namespace ams::kern { const size_t unsafe_system_pool_min_size = KSystemControl::Init::GetMinimumNonSecureSystemPoolSize(); /* Find the start of the kernel DRAM region. */ - const KMemoryRegion *kernel_dram_region = KMemoryLayout::GetPhysicalMemoryRegionTree().FindFirstDerived(KMemoryRegionType_DramKernel); + const KMemoryRegion *kernel_dram_region = KMemoryLayout::GetPhysicalMemoryRegionTree().FindFirstDerived(KMemoryRegionType_DramKernelBase); MESOSPHERE_INIT_ABORT_UNLESS(kernel_dram_region != nullptr); const uintptr_t kernel_dram_start = kernel_dram_region->GetAddress(); @@ -141,7 +141,7 @@ namespace ams::kern { const uintptr_t metadata_pool_start = unsafe_system_pool_start - total_overhead_size; const size_t metadata_pool_size = total_overhead_size; u32 metadata_pool_attr = 0; - InsertPoolPartitionRegionIntoBothTrees(metadata_pool_start, metadata_pool_size, KMemoryRegionType_DramMetadataPool, KMemoryRegionType_VirtualDramMetadataPool, metadata_pool_attr); + InsertPoolPartitionRegionIntoBothTrees(metadata_pool_start, metadata_pool_size, KMemoryRegionType_DramPoolManagement, KMemoryRegionType_VirtualDramPoolManagement, metadata_pool_attr); /* Insert the system pool. */ const uintptr_t system_pool_size = metadata_pool_start - pool_partitions_start; diff --git a/libraries/libmesosphere/source/kern_k_memory_layout.cpp b/libraries/libmesosphere/source/kern_k_memory_layout.cpp index 7e9047611..4eca1d728 100644 --- a/libraries/libmesosphere/source/kern_k_memory_layout.cpp +++ b/libraries/libmesosphere/source/kern_k_memory_layout.cpp @@ -234,7 +234,7 @@ namespace ams::kern { /* Get the virtual address of the core local reigon. */ const KVirtualAddress core_local_virt_start = GetCoreLocalRegionVirtualAddress(); - MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetVirtualMemoryRegionTree().Insert(GetInteger(core_local_virt_start), CoreLocalRegionSize, KMemoryRegionType_CoreLocal)); + MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetVirtualMemoryRegionTree().Insert(GetInteger(core_local_virt_start), CoreLocalRegionSize, KMemoryRegionType_CoreLocalRegion)); /* Allocate a page for each core. */ KPhysicalAddress core_local_region_start_phys[cpu::NumCores] = {}; diff --git a/libraries/libmesosphere/source/kern_k_memory_manager.cpp b/libraries/libmesosphere/source/kern_k_memory_manager.cpp index fa3799b33..cc4dab05d 100644 --- a/libraries/libmesosphere/source/kern_k_memory_manager.cpp +++ b/libraries/libmesosphere/source/kern_k_memory_manager.cpp @@ -42,7 +42,7 @@ namespace ams::kern { const KMemoryRegion *region = nullptr; for (const auto &it : KMemoryLayout::GetVirtualMemoryRegionTree()) { /* We only care about regions that we need to create managers for. */ - if (!it.IsDerivedFrom(KMemoryRegionType_VirtualDramManagedPool)) { + if (!it.IsDerivedFrom(KMemoryRegionType_VirtualDramUserPool)) { continue; } @@ -64,7 +64,7 @@ namespace ams::kern { MESOSPHERE_ASSERT(region->GetAddress() != NullGetAddress())>); MESOSPHERE_ASSERT(region->GetSize() > 0); MESOSPHERE_ASSERT(region->GetEndAddress() >= region->GetAddress()); - MESOSPHERE_ASSERT(region->IsDerivedFrom(KMemoryRegionType_VirtualDramManagedPool)); + MESOSPHERE_ASSERT(region->IsDerivedFrom(KMemoryRegionType_VirtualDramUserPool)); MESOSPHERE_ASSERT(region->GetAttributes() == this->num_managers); /* Initialize a new manager for the region. */ diff --git a/libraries/libmesosphere/source/kern_kernel.cpp b/libraries/libmesosphere/source/kern_kernel.cpp index aa5b6d29c..df80a1e17 100644 --- a/libraries/libmesosphere/source/kern_kernel.cpp +++ b/libraries/libmesosphere/source/kern_kernel.cpp @@ -153,7 +153,7 @@ namespace ams::kern { PrintMemoryRegion(" InitPageTable", KMemoryLayout::GetKernelInitPageTableRegionPhysicalExtents()); PrintMemoryRegion(" MemoryPoolRegion", KMemoryLayout::GetKernelPoolPartitionRegionPhysicalExtents()); PrintMemoryRegion(" System", KMemoryLayout::GetKernelSystemPoolRegionPhysicalExtents()); - PrintMemoryRegion(" Internal", KMemoryLayout::GetKernelMetadataPoolRegionPhysicalExtents()); + PrintMemoryRegion(" Management", KMemoryLayout::GetKernelPoolManagementRegionPhysicalExtents()); PrintMemoryRegion(" SystemUnsafe", KMemoryLayout::GetKernelSystemNonSecurePoolRegionPhysicalExtents()); PrintMemoryRegion(" Applet", KMemoryLayout::GetKernelAppletPoolRegionPhysicalExtents()); PrintMemoryRegion(" Application", KMemoryLayout::GetKernelApplicationPoolRegionPhysicalExtents()); diff --git a/libraries/libmesosphere/source/kern_main.cpp b/libraries/libmesosphere/source/kern_main.cpp index ecf96e37e..e481b8f6b 100644 --- a/libraries/libmesosphere/source/kern_main.cpp +++ b/libraries/libmesosphere/source/kern_main.cpp @@ -51,8 +51,8 @@ namespace ams::kern { /* Initialize the memory manager and the KPageBuffer slabheap. */ { - const auto &metadata_region = KMemoryLayout::GetMetadataPoolRegion(); - Kernel::GetMemoryManager().Initialize(metadata_region.GetAddress(), metadata_region.GetSize()); + const auto &management_region = KMemoryLayout::GetPoolManagementRegion(); + Kernel::GetMemoryManager().Initialize(management_region.GetAddress(), management_region.GetSize()); init::InitializeKPageBufferSlabHeap(); } diff --git a/mesosphere/kernel/source/arch/arm64/init/kern_init_core.cpp b/mesosphere/kernel/source/arch/arm64/init/kern_init_core.cpp index 090a9a802..b3765f2cf 100644 --- a/mesosphere/kernel/source/arch/arm64/init/kern_init_core.cpp +++ b/mesosphere/kernel/source/arch/arm64/init/kern_init_core.cpp @@ -170,8 +170,13 @@ namespace ams::kern::init { /* Automatically map in devices that have auto-map attributes. */ for (auto ®ion : KMemoryLayout::GetPhysicalMemoryRegionTree()) { - /* We only care about automatically-mapped regions. */ - if (!region.IsDerivedFrom(KMemoryRegionType_KernelAutoMap)) { + /* We only care about kernel regions. */ + if (!region.IsDerivedFrom(KMemoryRegionType_Kernel)) { + continue; + } + + /* Check whether we should map the region. */ + if (!region.HasTypeAttribute(KMemoryRegionAttr_ShouldKernelMap)) { continue; } @@ -301,11 +306,11 @@ namespace ams::kern::init { /* Insert regions for the initial page table region. */ MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(GetInteger(resource_end_phys_addr), init_page_table_region_size, KMemoryRegionType_DramKernelInitPt)); - MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetVirtualMemoryRegionTree().Insert(GetInteger(resource_end_phys_addr) + linear_region_phys_to_virt_diff, init_page_table_region_size, KMemoryRegionType_VirtualKernelInitPt)); + MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetVirtualMemoryRegionTree().Insert(GetInteger(resource_end_phys_addr) + linear_region_phys_to_virt_diff, init_page_table_region_size, KMemoryRegionType_VirtualDramKernelInitPt)); /* All linear-mapped DRAM regions that we haven't tagged by this point will be allocated to some pool partition. Tag them. */ for (auto ®ion : KMemoryLayout::GetPhysicalMemoryRegionTree()) { - if (region.GetType() == KMemoryRegionType_DramLinearMapped) { + if (region.GetType() == KMemoryRegionType_Dram && region.HasTypeAttribute(KMemoryRegionAttr_LinearMapped)) { region.SetType(KMemoryRegionType_DramPoolPartition); } }