diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_memory_region.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_memory_region.hpp index a04c32d11..63ff1c239 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_memory_region.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_memory_region.hpp @@ -29,7 +29,7 @@ namespace ams::kern { private: uintptr_t address; uintptr_t pair_address; - size_t region_size; + uintptr_t last_address; u32 attributes; u32 type_id; public: @@ -43,18 +43,18 @@ namespace ams::kern { } } 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() : address(0), pair_address(0), last_address(0), attributes(0), type_id(0) { /* ... */ } + constexpr ALWAYS_INLINE KMemoryRegion(uintptr_t a, size_t la, uintptr_t p, u32 r, u32 t) : + address(a), pair_address(p), last_address(la), 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) { /* ... */ } + constexpr ALWAYS_INLINE KMemoryRegion(uintptr_t a, size_t la, u32 r, u32 t) : KMemoryRegion(a, la, 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) { + constexpr ALWAYS_INLINE void Reset(uintptr_t a, uintptr_t la, uintptr_t p, u32 r, u32 t) { this->address = a; this->pair_address = p; - this->region_size = rs; + this->last_address = la; this->attributes = r; this->type_id = t; } @@ -67,16 +67,16 @@ namespace ams::kern { return this->pair_address; } - constexpr ALWAYS_INLINE size_t GetSize() const { - return this->region_size; + constexpr ALWAYS_INLINE uintptr_t GetLastAddress() const { + return this->last_address; } constexpr ALWAYS_INLINE uintptr_t GetEndAddress() const { - return this->GetAddress() + this->GetSize(); + return this->GetLastAddress() + 1; } - constexpr ALWAYS_INLINE uintptr_t GetLastAddress() const { - return this->GetEndAddress() - 1; + constexpr ALWAYS_INLINE size_t GetSize() const { + return this->GetEndAddress() - this->GetAddress(); } constexpr ALWAYS_INLINE u32 GetAttributes() const { @@ -130,17 +130,17 @@ namespace ams::kern { return this->first_region->GetAddress(); } + constexpr ALWAYS_INLINE uintptr_t GetLastAddress() const { + return this->last_region->GetLastAddress(); + } + constexpr ALWAYS_INLINE uintptr_t GetEndAddress() const { - return this->last_region->GetEndAddress(); + return this->GetLastAddress() + 1; } 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; @@ -160,7 +160,7 @@ namespace ams::kern { constexpr ALWAYS_INLINE KMemoryRegionTree() : tree() { /* ... */ } public: KMemoryRegion *FindModifiable(uintptr_t address) { - if (auto it = this->find(KMemoryRegion(address, 1, 0, 0)); it != this->end()) { + if (auto it = this->find(KMemoryRegion(address, address, 0, 0)); it != this->end()) { return std::addressof(*it); } else { return nullptr; @@ -168,7 +168,7 @@ namespace ams::kern { } const KMemoryRegion *Find(uintptr_t address) const { - if (auto it = this->find(KMemoryRegion(address, 1, 0, 0)); it != this->cend()) { + if (auto it = this->find(KMemoryRegion(address, address, 0, 0)); it != this->cend()) { return std::addressof(*it); } else { return nullptr; @@ -234,7 +234,7 @@ namespace ams::kern { return extents; } public: - NOINLINE void InsertDirectly(uintptr_t address, size_t size, u32 attr = 0, u32 type_id = 0); + NOINLINE void InsertDirectly(uintptr_t address, uintptr_t last_address, 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); diff --git a/libraries/libmesosphere/source/kern_k_memory_layout.cpp b/libraries/libmesosphere/source/kern_k_memory_layout.cpp index 468119c60..60127e28e 100644 --- a/libraries/libmesosphere/source/kern_k_memory_layout.cpp +++ b/libraries/libmesosphere/source/kern_k_memory_layout.cpp @@ -40,8 +40,6 @@ namespace ams::kern { new (region) KMemoryRegion(std::forward(args)...); return region; - - return &this->region_heap[this->num_regions++]; } }; @@ -55,8 +53,8 @@ namespace ams::kern { } - void KMemoryRegionTree::InsertDirectly(uintptr_t address, size_t size, u32 attr, u32 type_id) { - this->insert(*AllocateRegion(address, size, attr, type_id)); + void KMemoryRegionTree::InsertDirectly(uintptr_t address, uintptr_t last_address, u32 attr, u32 type_id) { + this->insert(*AllocateRegion(address, last_address, attr, type_id)); } bool KMemoryRegionTree::Insert(uintptr_t address, size_t size, u32 type_id, u32 new_attr, u32 old_attr) { @@ -82,9 +80,7 @@ namespace ams::kern { /* Cache information from the region before we remove it. */ const uintptr_t old_address = found->GetAddress(); - const size_t old_size = found->GetSize(); - const uintptr_t old_end = old_address + old_size; - const uintptr_t old_last = old_end - 1; + const uintptr_t old_last = found->GetLastAddress(); const uintptr_t old_pair = found->GetPairAddress(); const u32 old_type = found->GetType(); @@ -92,24 +88,24 @@ namespace ams::kern { this->erase(this->iterator_to(*found)); /* Insert the new region into the tree. */ - const uintptr_t new_pair = (old_pair != std::numeric_limits::max()) ? old_pair + (address - old_address) : old_pair; if (old_address == address) { /* Reuse the old object for the new region, if we can. */ - found->Reset(address, size, new_pair, new_attr, type_id); + found->Reset(address, inserted_region_last, old_pair, new_attr, type_id); this->insert(*found); } else { /* If we can't re-use, adjust the old region. */ - found->Reset(old_address, address - old_address, old_pair, old_attr, old_type); + found->Reset(old_address, address - 1, old_pair, old_attr, old_type); this->insert(*found); /* Insert a new region for the split. */ - this->insert(*AllocateRegion(address, size, new_pair, new_attr, type_id)); + const uintptr_t new_pair = (old_pair != std::numeric_limits::max()) ? old_pair + (address - old_address) : old_pair; + this->insert(*AllocateRegion(address, inserted_region_last, new_pair, new_attr, type_id)); } /* If we need to insert a region after the region, do so. */ if (old_last != inserted_region_last) { const uintptr_t after_pair = (old_pair != std::numeric_limits::max()) ? old_pair + (inserted_region_end - old_address) : old_pair; - this->insert(*AllocateRegion(inserted_region_end, old_end - inserted_region_end, after_pair, old_attr, old_type)); + this->insert(*AllocateRegion(inserted_region_end, old_last, after_pair, old_attr, old_type)); } return true; @@ -125,8 +121,11 @@ namespace ams::kern { const uintptr_t first_address = extents.GetAddress(); const uintptr_t last_address = extents.GetLastAddress(); + const uintptr_t first_index = first_address / alignment; + const uintptr_t last_index = last_address / alignment; + while (true) { - const uintptr_t candidate = util::AlignDown(KSystemControl::Init::GenerateRandomRange(first_address, last_address), alignment); + const uintptr_t candidate = KSystemControl::Init::GenerateRandomRange(first_index, last_index) * alignment; /* Ensure that the candidate doesn't overflow with the size. */ if (!(candidate < candidate + size)) { @@ -157,13 +156,13 @@ namespace ams::kern { /* Initialize linear trees. */ for (auto ®ion : GetPhysicalMemoryRegionTree()) { if (region.HasTypeAttribute(KMemoryRegionAttr_LinearMapped)) { - GetPhysicalLinearMemoryRegionTree().InsertDirectly(region.GetAddress(), region.GetSize(), region.GetAttributes(), region.GetType()); + GetPhysicalLinearMemoryRegionTree().InsertDirectly(region.GetAddress(), region.GetLastAddress(), region.GetAttributes(), region.GetType()); } } for (auto ®ion : GetVirtualMemoryRegionTree()) { if (region.IsDerivedFrom(KMemoryRegionType_Dram)) { - GetVirtualLinearMemoryRegionTree().InsertDirectly(region.GetAddress(), region.GetSize(), region.GetAttributes(), region.GetType()); + GetVirtualLinearMemoryRegionTree().InsertDirectly(region.GetAddress(), region.GetLastAddress(), region.GetAttributes(), region.GetType()); } } } 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 f5ca2bc6b..6fe5f411e 100644 --- a/mesosphere/kernel/source/arch/arm64/init/kern_init_core.cpp +++ b/mesosphere/kernel/source/arch/arm64/init/kern_init_core.cpp @@ -139,10 +139,10 @@ namespace ams::kern::init { InitializeSlabResourceCounts(); /* Insert the root region for the virtual memory tree, from which all other regions will derive. */ - KMemoryLayout::GetVirtualMemoryRegionTree().InsertDirectly(KernelVirtualAddressSpaceBase, KernelVirtualAddressSpaceSize); + KMemoryLayout::GetVirtualMemoryRegionTree().InsertDirectly(KernelVirtualAddressSpaceBase, KernelVirtualAddressSpaceBase + KernelVirtualAddressSpaceSize - 1); /* Insert the root region for the physical memory tree, from which all other regions will derive. */ - KMemoryLayout::GetPhysicalMemoryRegionTree().InsertDirectly(KernelPhysicalAddressSpaceBase, KernelPhysicalAddressSpaceSize); + KMemoryLayout::GetPhysicalMemoryRegionTree().InsertDirectly(KernelPhysicalAddressSpaceBase, KernelPhysicalAddressSpaceBase + KernelPhysicalAddressSpaceSize - 1); /* Save start and end for ease of use. */ const uintptr_t code_start_virt_addr = reinterpret_cast(_start);