diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_dynamic_page_manager.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_dynamic_page_manager.hpp index 2383a7869..cc772876b 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_dynamic_page_manager.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_dynamic_page_manager.hpp @@ -64,11 +64,12 @@ namespace ams::kern { this->page_bitmap.Initialize(metadata_ptr, this->count); /* Free the pages to the bitmap. */ - PageBuffer *cur_page = GetPointer(this->address); + std::memset(GetPointer(this->address), 0, this->count * sizeof(PageBuffer)); for (size_t i = 0; i < this->count; i++) { - std::memset(cur_page, 0, sizeof(*cur_page)); this->page_bitmap.SetBit(i); } + + return ResultSuccess(); } constexpr KVirtualAddress GetAddress() const { return this->address; } diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_dynamic_slab_heap.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_dynamic_slab_heap.hpp index b2a0e5d70..c8ce85326 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_dynamic_slab_heap.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_dynamic_slab_heap.hpp @@ -77,6 +77,23 @@ namespace ams::kern { this->size = this->page_allocator->GetSize(); } + void Initialize(KDynamicPageManager *page_allocator, size_t num_objects) { + MESOSPHERE_ASSERT(page_allocator != nullptr); + + /* Initialize members. */ + this->Initialize(page_allocator); + + /* Allocate until we have the correct number of objects. */ + while (this->count < num_objects) { + auto *allocated = reinterpret_cast(this->page_allocator->Allocate()); + MESOSPHERE_ABORT_UNLESS(allocated != nullptr); + for (size_t i = 0; i < sizeof(PageBuffer) / sizeof(T); i++) { + this->GetImpl()->Free(allocated + i); + } + this->count += sizeof(PageBuffer) / sizeof(T); + } + } + T *Allocate() { T *allocated = reinterpret_cast(this->GetImpl()->Allocate()); diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_page_table_manager.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_page_table_manager.hpp index 970fb62f8..dc2fe96da 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_page_table_manager.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_page_table_manager.hpp @@ -57,13 +57,13 @@ namespace ams::kern { return std::addressof(this->ref_counts[(addr - this->GetAddress()) / PageSize]); } public: - void Initialize(KDynamicPageManager *next_allocator, RefCount *rc) { - BaseHeap::Initialize(next_allocator); + void Initialize(KDynamicPageManager *page_allocator, RefCount *rc) { + BaseHeap::Initialize(page_allocator); this->Initialize(rc); } - void Initialize(KVirtualAddress memory, size_t sz, RefCount *rc) { - BaseHeap::Initialize(memory, sz); + void Initialize(KDynamicPageManager *page_allocator, size_t object_count, RefCount *rc) { + BaseHeap::Initialize(page_allocator, object_count); this->Initialize(rc); } diff --git a/libraries/libmesosphere/source/kern_kernel.cpp b/libraries/libmesosphere/source/kern_kernel.cpp index d312d270d..5c1c5a676 100644 --- a/libraries/libmesosphere/source/kern_kernel.cpp +++ b/libraries/libmesosphere/source/kern_kernel.cpp @@ -19,6 +19,8 @@ namespace ams::kern { namespace { + KDynamicPageManager g_resource_manager_page_manager; + template ALWAYS_INLINE void PrintMemoryRegion(const char *prefix, const T &extents) { static_assert(std::is_same::value); @@ -88,24 +90,29 @@ namespace ams::kern { void Kernel::InitializeResourceManagers(KVirtualAddress address, size_t size) { /* Ensure that the buffer is suitable for our use. */ - const size_t app_size = ApplicationMemoryBlockSlabHeapSize * sizeof(KMemoryBlock); - const size_t sys_size = SystemMemoryBlockSlabHeapSize * sizeof(KMemoryBlock); - const size_t info_size = BlockInfoSlabHeapSize * sizeof(KBlockInfo); - const size_t fixed_size = util::AlignUp(app_size + sys_size + info_size, PageSize); + //const size_t app_size = ApplicationMemoryBlockSlabHeapSize * sizeof(KMemoryBlock); + //const size_t sys_size = SystemMemoryBlockSlabHeapSize * sizeof(KMemoryBlock); + //const size_t info_size = BlockInfoSlabHeapSize * sizeof(KBlockInfo); + //const size_t fixed_size = util::AlignUp(app_size + sys_size + info_size, PageSize); MESOSPHERE_ABORT_UNLESS(util::IsAligned(GetInteger(address), PageSize)); MESOSPHERE_ABORT_UNLESS(util::IsAligned(size, PageSize)); - MESOSPHERE_ABORT_UNLESS(fixed_size < size); - size_t pt_size = size - fixed_size; - const size_t rc_size = util::AlignUp(KPageTableManager::CalculateReferenceCountSize(pt_size), PageSize); - MESOSPHERE_ABORT_UNLESS(rc_size < pt_size); - pt_size -= rc_size; + /* Ensure that we have space for our reference counts. */ + const size_t rc_size = util::AlignUp(KPageTableManager::CalculateReferenceCountSize(size), PageSize); + MESOSPHERE_ABORT_UNLESS(rc_size < size); + size -= rc_size; - /* Initialize the slabheaps. */ - s_app_memory_block_manager.Initialize(address + pt_size, app_size); - s_sys_memory_block_manager.Initialize(address + pt_size + app_size, sys_size); - s_block_info_manager.Initialize(address + pt_size + app_size + sys_size, info_size); - s_page_table_manager.Initialize(address, pt_size, GetPointer(address + pt_size + fixed_size)); + /* Initialize the resource managers' shared page manager. */ + g_resource_manager_page_manager.Initialize(address, size); + + /* Initialize the fixed-size slabheaps. */ + s_app_memory_block_manager.Initialize(std::addressof(g_resource_manager_page_manager), ApplicationMemoryBlockSlabHeapSize); + s_sys_memory_block_manager.Initialize(std::addressof(g_resource_manager_page_manager), SystemMemoryBlockSlabHeapSize); + s_block_info_manager.Initialize(std::addressof(g_resource_manager_page_manager), BlockInfoSlabHeapSize); + + /* Reserve all remaining pages for the page table manager. */ + const size_t num_pt_pages = g_resource_manager_page_manager.GetCount() - g_resource_manager_page_manager.GetUsed(); + s_page_table_manager.Initialize(std::addressof(g_resource_manager_page_manager), num_pt_pages, GetPointer(address + size)); } void Kernel::PrintLayout() {