From 49af4fae32cc4b6c1d67b99401089fcc607bbe9d Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Tue, 25 Aug 2020 23:28:39 -0700 Subject: [PATCH] kern: begin 1.0.0 backwards compat changes (kips run, full boot fails) --- .../nintendo/nx/kern_k_system_control.hpp | 2 +- .../nintendo/nx/kern_k_system_control.cpp | 2 +- .../source/kern_initial_process.cpp | 8 +++-- .../source/kern_k_initial_process_reader.cpp | 6 ++-- ...kern_k_memory_layout.board.nintendo_nx.cpp | 36 ++++++++++++++----- .../source/svc/kern_svc_process.cpp | 5 ++- 6 files changed, 40 insertions(+), 19 deletions(-) diff --git a/libraries/libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_system_control.hpp b/libraries/libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_system_control.hpp index 080cc8c32..fdf757df7 100644 --- a/libraries/libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_system_control.hpp +++ b/libraries/libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_system_control.hpp @@ -39,7 +39,7 @@ namespace ams::kern::board::nintendo::nx { /* Initialization. */ static NOINLINE void InitializePhase1(); static NOINLINE void InitializePhase2(); - static NOINLINE u32 GetInitialProcessBinaryPool(); + static NOINLINE u32 GetCreateProcessMemoryPool(); /* Randomness. */ static void GenerateRandomBytes(void *dst, size_t size); 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 ce872df9e..4c1763cac 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 @@ -485,7 +485,7 @@ namespace ams::kern::board::nintendo::nx { } } - u32 KSystemControl::GetInitialProcessBinaryPool() { + u32 KSystemControl::GetCreateProcessMemoryPool() { return KMemoryManager::Pool_Unsafe; } diff --git a/libraries/libmesosphere/source/kern_initial_process.cpp b/libraries/libmesosphere/source/kern_initial_process.cpp index c5b4cbe14..f4c387cad 100644 --- a/libraries/libmesosphere/source/kern_initial_process.cpp +++ b/libraries/libmesosphere/source/kern_initial_process.cpp @@ -66,6 +66,10 @@ namespace ams::kern { u8 *current = GetPointer(binary_address + sizeof(InitialProcessBinaryHeader)); const u8 * const end = GetPointer(binary_address + header.size - sizeof(KInitialProcessHeader)); + /* Decide on pools to use. */ + const auto unsafe_pool = static_cast(KSystemControl::GetCreateProcessMemoryPool()); + const auto secure_pool = (GetTargetFirmware() >= TargetFirmware_2_0_0) ? KMemoryManager::Pool_Secure : unsafe_pool; + const size_t num_processes = header.num_processes; for (size_t i = 0; i < num_processes; i++) { /* Validate that we can read the current KIP. */ @@ -86,7 +90,7 @@ namespace ams::kern { /* Allocate memory for the process. */ auto &mm = Kernel::GetMemoryManager(); - const auto pool = reader.UsesSecureMemory() ? KMemoryManager::Pool_System : static_cast(KSystemControl::GetInitialProcessBinaryPool()); + const auto pool = reader.UsesSecureMemory() ? secure_pool : unsafe_pool; MESOSPHERE_R_ABORT_UNLESS(mm.Allocate(std::addressof(pg), params.code_num_pages, KMemoryManager::EncodeOption(pool, KMemoryManager::Direction_FromFront))); { @@ -164,7 +168,7 @@ namespace ams::kern { MESOSPHERE_ABORT_UNLESS(Kernel::GetSystemResourceLimit().Reserve(ams::svc::LimitableResource_PhysicalMemoryMax, total_size)); /* Allocate memory for the image. */ - const KMemoryManager::Pool pool = static_cast(KSystemControl::GetInitialProcessBinaryPool()); + const KMemoryManager::Pool pool = static_cast(KSystemControl::GetCreateProcessMemoryPool()); const auto allocate_option = KMemoryManager::EncodeOption(pool, KMemoryManager::Direction_FromFront); KVirtualAddress allocated_memory = mm.AllocateContinuous(num_pages, 1, allocate_option); MESOSPHERE_ABORT_UNLESS(allocated_memory != Null); diff --git a/libraries/libmesosphere/source/kern_k_initial_process_reader.cpp b/libraries/libmesosphere/source/kern_k_initial_process_reader.cpp index 09a65b769..8e2196a3c 100644 --- a/libraries/libmesosphere/source/kern_k_initial_process_reader.cpp +++ b/libraries/libmesosphere/source/kern_k_initial_process_reader.cpp @@ -105,8 +105,8 @@ namespace ams::kern { const uintptr_t start_address = rx_address; const uintptr_t end_address = bss_size > 0 ? bss_address + bss_size : rw_address + rw_size; - const size_t as_width = this->Is64BitAddressSpace() ? 39 : 32; - const ASType as_type = this->Is64BitAddressSpace() ? KAddressSpaceInfo::Type_Map39Bit : KAddressSpaceInfo::Type_MapSmall; + const size_t as_width = this->Is64BitAddressSpace() ? ((GetTargetFirmware() >= TargetFirmware_2_0_0) ? 39 : 36) : 32; + const ASType as_type = this->Is64BitAddressSpace() ? ((GetTargetFirmware() >= TargetFirmware_2_0_0) ? KAddressSpaceInfo::Type_Map39Bit : KAddressSpaceInfo::Type_MapSmall) : KAddressSpaceInfo::Type_MapSmall; const uintptr_t map_start = KAddressSpaceInfo::GetAddressSpaceStart(as_width, as_type); const size_t map_size = KAddressSpaceInfo::GetAddressSpaceSize(as_width, as_type); const uintptr_t map_end = map_start + map_size; @@ -135,7 +135,7 @@ namespace ams::kern { out->flags |= ams::svc::CreateProcessFlag_Is64Bit; } if (this->Is64BitAddressSpace()) { - out->flags |= ams::svc::CreateProcessFlag_AddressSpace64Bit; + out->flags |= (GetTargetFirmware() >= TargetFirmware_2_0_0) ? ams::svc::CreateProcessFlag_AddressSpace64Bit : ams::svc::CreateProcessFlag_AddressSpace64BitDeprecated; } else { out->flags |= ams::svc::CreateProcessFlag_AddressSpace32Bit; } 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 781549236..b9b6229b6 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 @@ -151,7 +151,7 @@ namespace ams::kern { /* Insert the system pool. */ const uintptr_t system_pool_size = pool_management_start - pool_partitions_start; InsertPoolPartitionRegionIntoBothTrees(pool_partitions_start, system_pool_size, KMemoryRegionType_DramSystemPool, KMemoryRegionType_VirtualDramSystemPool, cur_pool_attr); - } else if (GetTargetFirmware() >= TargetFirmware_2_0_0) { + } else { /* On < 5.0.0, setup a legacy 2-pool layout for backwards compatibility. */ static_assert(KMemoryManager::Pool_Count == 4); @@ -159,12 +159,33 @@ namespace ams::kern { static_assert(KMemoryManager::Pool_Secure == KMemoryManager::Pool_System); /* Get Secure pool size. */ - constexpr size_t LegacySecureKernelSize = 6_MB; /* KPageBuffer pages, other small kernel allocations. */ - constexpr size_t LegacySecureMiscSize = 1_MB; /* Miscellaneous pages for secure process mapping. */ - constexpr size_t LegacySecureHeapSize = 24_MB; /* Heap pages for secure process mapping (fs). */ - constexpr size_t LegacySecureEsSize = 1_MB + 232_KB; /* Size for additional secure process (es, 4.0.0+). */ + const size_t secure_pool_size = [] ALWAYS_INLINE_LAMBDA (auto target_firmware) -> size_t { + constexpr size_t LegacySecureKernelSize = 8_MB; /* KPageBuffer pages, other small kernel allocations. */ + constexpr size_t LegacySecureMiscSize = 1_MB; /* Miscellaneous pages for secure process mapping. */ + constexpr size_t LegacySecureHeapSize = 24_MB; /* Heap pages for secure process mapping (fs). */ + constexpr size_t LegacySecureEsSize = 1_MB + 232_KB; /* Size for additional secure process (es, 4.0.0+). */ - const size_t secure_pool_size = GetInitialProcessesSecureMemorySize() + LegacySecureKernelSize + LegacySecureHeapSize + LegacySecureMiscSize + (GetTargetFirmware() >= TargetFirmware_4_0_0 ? LegacySecureEsSize : 0); + /* The baseline size for the secure region is enough to cover any allocations the kernel might make. */ + size_t size = LegacySecureKernelSize; + + /* If on 2.0.0+, initial processes will fall within the secure region. */ + if (target_firmware >= TargetFirmware_2_0_0) { + /* Account for memory used directly for the processes. */ + size += GetInitialProcessesSecureMemorySize(); + + /* Account for heap and transient memory used by the processes. */ + size += LegacySecureHeapSize + LegacySecureMiscSize; + } + + /* If on 4.0.0+, any process may use secure memory via a create process flag. */ + /* In process this is used for es alone, and the secure pool's size should be */ + /* increased to accommodate es's binary. */ + if (target_firmware >= TargetFirmware_4_0_0) { + size += LegacySecureEsSize; + } + + return size; + }(GetTargetFirmware()); /* Calculate the overhead for the secure and (defunct) applet/non-secure-system pools. */ size_t total_overhead_size = KMemoryManager::CalculateManagementOverheadSize(secure_pool_size); @@ -208,9 +229,6 @@ namespace ams::kern { u32 pool_management_attr = 0; InsertPoolPartitionRegionIntoBothTrees(pool_management_start, pool_management_size, KMemoryRegionType_DramPoolManagement, KMemoryRegionType_VirtualDramPoolManagement, pool_management_attr); - } else { - /* TODO: 1.0.0 single-pool layout. */ - MESOSPHERE_UNIMPLEMENTED(); } } diff --git a/libraries/libmesosphere/source/svc/kern_svc_process.cpp b/libraries/libmesosphere/source/svc/kern_svc_process.cpp index 42bc9f63e..c279b21be 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_process.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_process.cpp @@ -219,14 +219,13 @@ namespace ams::kern::svc { if ((flags & ams::svc::CreateProcessFlag_DeprecatedUseSecureMemory) != 0) { return KMemoryManager::Pool_Secure; } else { - return KMemoryManager::Pool_Unsafe; + return static_cast(KSystemControl::GetCreateProcessMemoryPool()); } } else { - return KMemoryManager::Pool_Unsafe; + return static_cast(KSystemControl::GetCreateProcessMemoryPool()); } }(params.flags); - /* Initialize the process. */ R_TRY(process->Initialize(params, user_caps, num_caps, process_resource_limit, pool));