diff --git a/libmesosphere/include/mesosphere/kern_initial_process.hpp b/libmesosphere/include/mesosphere/kern_initial_process.hpp index 2ab3b609..91129819 100644 --- a/libmesosphere/include/mesosphere/kern_initial_process.hpp +++ b/libmesosphere/include/mesosphere/kern_initial_process.hpp @@ -34,8 +34,14 @@ namespace ams::kern { uintptr_t _08; }; + struct InitialProcessBinaryLayoutWithSize { + InitialProcessBinaryLayout layout; + size_t size; + }; + KPhysicalAddress GetInitialProcessBinaryPhysicalAddress(); - void SetInitialProcessBinaryPhysicalAddress(KPhysicalAddress phys_addr); + size_t GetInitialProcessBinarySize(); + void SetInitialProcessBinaryPhysicalAddress(KPhysicalAddress phys_addr, size_t size); u64 GetInitialProcessIdMin(); u64 GetInitialProcessIdMax(); diff --git a/libmesosphere/source/init/kern_init_slab_setup.cpp b/libmesosphere/source/init/kern_init_slab_setup.cpp index 1d76900e..b82e78f8 100644 --- a/libmesosphere/source/init/kern_init_slab_setup.cpp +++ b/libmesosphere/source/init/kern_init_slab_setup.cpp @@ -171,6 +171,9 @@ namespace ams::kern::init { const KMemoryRegion &slab_region = KMemoryLayout::GetSlabRegion(); KVirtualAddress address = slab_region.GetAddress(); + /* Clear the slab region. */ + std::memset(GetVoidPointer(address), 0, slab_region.GetSize()); + /* Initialize slab type array to be in sorted order. */ KSlabType slab_types[KSlabType_Count]; for (size_t i = 0; i < util::size(slab_types); i++) { slab_types[i] = static_cast(i); } diff --git a/libmesosphere/source/kern_initial_process.cpp b/libmesosphere/source/kern_initial_process.cpp index e435deee..6b22a178 100644 --- a/libmesosphere/source/kern_initial_process.cpp +++ b/libmesosphere/source/kern_initial_process.cpp @@ -27,6 +27,7 @@ namespace ams::kern { constinit KPhysicalAddress g_initial_process_binary_phys_addr = Null; constinit KVirtualAddress g_initial_process_binary_address = Null; + constinit size_t g_initial_process_binary_size = 0; constinit InitialProcessBinaryHeader g_initial_process_binary_header = {}; constinit size_t g_initial_process_secure_memory_size = 0; constinit u64 g_initial_process_id_min = std::numeric_limits::max(); @@ -275,10 +276,11 @@ namespace ams::kern { } - void SetInitialProcessBinaryPhysicalAddress(KPhysicalAddress phys_addr) { + void SetInitialProcessBinaryPhysicalAddress(KPhysicalAddress phys_addr, size_t size) { MESOSPHERE_INIT_ABORT_UNLESS(g_initial_process_binary_phys_addr == Null); g_initial_process_binary_phys_addr = phys_addr; + g_initial_process_binary_size = size; } KPhysicalAddress GetInitialProcessBinaryPhysicalAddress() { @@ -287,6 +289,12 @@ namespace ams::kern { return g_initial_process_binary_phys_addr; } + size_t GetInitialProcessBinarySize() { + MESOSPHERE_INIT_ABORT_UNLESS(g_initial_process_binary_phys_addr != Null); + + return g_initial_process_binary_size; + } + u64 GetInitialProcessIdMin() { return g_initial_process_id_min; } @@ -305,14 +313,17 @@ namespace ams::kern { LoadInitialProcessBinaryHeader(); if (g_initial_process_binary_header.num_processes > 0) { - /* Reserve pages for the initial process binary from the system resource limit. */ - const size_t total_size = util::AlignUp(g_initial_process_binary_header.size, PageSize); - MESOSPHERE_ABORT_UNLESS(Kernel::GetSystemResourceLimit().Reserve(ams::svc::LimitableResource_PhysicalMemoryMax, total_size)); + /* Ensure that we have a non-zero size. */ + const size_t expected_size = g_initial_process_binary_size; + MESOSPHERE_INIT_ABORT_UNLESS(expected_size != 0); - /* The initial process binary is potentially over-allocated, so free any extra pages. */ - if (total_size < InitialProcessBinarySizeMax) { - Kernel::GetMemoryManager().Close(KMemoryLayout::GetLinearPhysicalAddress(g_initial_process_binary_address + total_size), (InitialProcessBinarySizeMax - total_size) / PageSize); - } + /* Ensure that the size we need to reserve is as we expect it to be. */ + const size_t total_size = util::AlignUp(g_initial_process_binary_header.size, PageSize); + MESOSPHERE_ABORT_UNLESS(total_size == expected_size); + MESOSPHERE_ABORT_UNLESS(total_size <= InitialProcessBinarySizeMax); + + /* Reserve pages for the initial process binary from the system resource limit. */ + MESOSPHERE_ABORT_UNLESS(Kernel::GetSystemResourceLimit().Reserve(ams::svc::LimitableResource_PhysicalMemoryMax, total_size)); return total_size; } else { diff --git a/libmesosphere/source/kern_k_memory_manager.cpp b/libmesosphere/source/kern_k_memory_manager.cpp index b9999be8..01dcd565 100644 --- a/libmesosphere/source/kern_k_memory_manager.cpp +++ b/libmesosphere/source/kern_k_memory_manager.cpp @@ -108,7 +108,8 @@ namespace ams::kern { /* Free each region to its corresponding heap. */ size_t reserved_sizes[MaxManagerCount] = {}; const KPhysicalAddress ini_start = GetInitialProcessBinaryPhysicalAddress(); - const KPhysicalAddress ini_end = ini_start + InitialProcessBinarySizeMax; + const size_t ini_size = GetInitialProcessBinarySize(); + const KPhysicalAddress ini_end = ini_start + ini_size; const KPhysicalAddress ini_last = ini_end - 1; for (const auto &it : KMemoryLayout::GetPhysicalMemoryRegionTree()) { if (it.IsDerivedFrom(KMemoryRegionType_DramUserPool)) { @@ -126,13 +127,13 @@ namespace ams::kern { } /* Open/reserve the ini memory. */ - manager.OpenFirst(ini_start, InitialProcessBinarySizeMax / PageSize); - reserved_sizes[it.GetAttributes()] += InitialProcessBinarySizeMax; + manager.OpenFirst(ini_start, ini_size / PageSize); + reserved_sizes[it.GetAttributes()] += ini_size; /* Free memory after the ini to the heap. */ if (ini_last != cur_last) { MESOSPHERE_ABORT_UNLESS(cur_end != Null); - manager.Free(ini_end, cur_end - ini_end); + manager.Free(ini_end, (cur_end - ini_end) / PageSize); } } else { /* Ensure there's no partial overlap with the ini image. */