From 3e19e4d004755f94aeb4dc8fce6c98455e68e2a9 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 30 Apr 2025 18:56:47 -0700 Subject: [PATCH] kern: update KAddressSpaceInfo to reflect 20.0.0 changes --- .../mesosphere/kern_k_address_space_info.hpp | 2 +- .../source/kern_k_address_space_info.cpp | 31 +++++++++++++++++-- .../source/kern_k_initial_process_reader.cpp | 5 ++- .../source/kern_k_page_table_base.cpp | 8 +---- .../libmesosphere/source/kern_k_process.cpp | 2 +- .../source/svc/kern_svc_process.cpp | 8 ++--- 6 files changed, 40 insertions(+), 16 deletions(-) diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_address_space_info.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_address_space_info.hpp index 8af8404cc..775c0054c 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_address_space_info.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_address_space_info.hpp @@ -37,7 +37,7 @@ namespace ams::kern { size_t m_size; Type m_type; public: - static uintptr_t GetAddressSpaceStart(ams::svc::CreateProcessFlag flags, Type type); + static uintptr_t GetAddressSpaceStart(ams::svc::CreateProcessFlag flags, Type type, size_t code_size); static size_t GetAddressSpaceSize(ams::svc::CreateProcessFlag flags, Type type); static void SetAddressSpaceSize(size_t width, Type type, size_t size); diff --git a/libraries/libmesosphere/source/kern_k_address_space_info.cpp b/libraries/libmesosphere/source/kern_k_address_space_info.cpp index b23f6e929..3aa24c5de 100644 --- a/libraries/libmesosphere/source/kern_k_address_space_info.cpp +++ b/libraries/libmesosphere/source/kern_k_address_space_info.cpp @@ -66,12 +66,39 @@ namespace ams::kern { } - uintptr_t KAddressSpaceInfo::GetAddressSpaceStart(ams::svc::CreateProcessFlag flags, KAddressSpaceInfo::Type type) { + uintptr_t KAddressSpaceInfo::GetAddressSpaceStart(ams::svc::CreateProcessFlag flags, KAddressSpaceInfo::Type type, size_t code_size) { + MESOSPHERE_UNUSED(code_size); return GetAddressSpaceInfo(GetAddressSpaceWidth(flags), type).GetAddress(); } size_t KAddressSpaceInfo::GetAddressSpaceSize(ams::svc::CreateProcessFlag flags, KAddressSpaceInfo::Type type) { - return GetAddressSpaceInfo(GetAddressSpaceWidth(flags), type).GetSize(); + /* Extract the address space from the create process flags. */ + const auto as_flags = (flags & ams::svc::CreateProcessFlag_AddressSpaceMask); + + /* Get the address space width. */ + const auto as_width = GetAddressSpaceWidth(flags); + + /* Get the size. */ + size_t as_size = GetAddressSpaceInfo(as_width, type).GetSize(); + + /* If we're getting size for 32-bit without alias, adjust the sizes accordingly. */ + if (as_flags == ams::svc::CreateProcessFlag_AddressSpace32BitWithoutAlias) { + switch (type) { + /* The heap space receives space that would otherwise go to the alias space. */ + case KAddressSpaceInfo::Type_Heap: + as_size += GetAddressSpaceInfo(as_width, KAddressSpaceInfo::Type_Alias).GetSize(); + break; + /* The alias space doesn't exist. */ + case KAddressSpaceInfo::Type_Alias: + as_size = 0; + break; + /* Nothing to do by default. */ + default: + break; + } + } + + return as_size; } void KAddressSpaceInfo::SetAddressSpaceSize(size_t width, Type type, size_t size) { diff --git a/libraries/libmesosphere/source/kern_k_initial_process_reader.cpp b/libraries/libmesosphere/source/kern_k_initial_process_reader.cpp index 9c91889f9..5d9164efb 100644 --- a/libraries/libmesosphere/source/kern_k_initial_process_reader.cpp +++ b/libraries/libmesosphere/source/kern_k_initial_process_reader.cpp @@ -229,9 +229,12 @@ namespace ams::kern { out->flags |= ams::svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge; /* Set and check code address. */ + /* NOTE: Even though Nintendo passes a size to GetAddressSpaceStart at other call sites, they pass */ + /* a number of pages here. Even though this is presumably only used for debug assertions, this is */ + /* almost certainly a bug. */ using ASType = KAddressSpaceInfo::Type; 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(static_cast(out->flags), as_type); + const uintptr_t map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast(out->flags), as_type, out->code_num_pages); const size_t map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast(out->flags), as_type); const uintptr_t map_end = map_start + map_size; out->code_address = map_start + start_address; diff --git a/libraries/libmesosphere/source/kern_k_page_table_base.cpp b/libraries/libmesosphere/source/kern_k_page_table_base.cpp index 4ebaad0bd..d7068a763 100644 --- a/libraries/libmesosphere/source/kern_k_page_table_base.cpp +++ b/libraries/libmesosphere/source/kern_k_page_table_base.cpp @@ -141,7 +141,7 @@ namespace ams::kern { /* Define helpers. */ auto GetSpaceStart = [&](KAddressSpaceInfo::Type type) ALWAYS_INLINE_LAMBDA { - return KAddressSpaceInfo::GetAddressSpaceStart(flags, type); + return KAddressSpaceInfo::GetAddressSpaceStart(flags, type, code_size); }; auto GetSpaceSize = [&](KAddressSpaceInfo::Type type) ALWAYS_INLINE_LAMBDA { return KAddressSpaceInfo::GetAddressSpaceSize(flags, type); @@ -155,12 +155,6 @@ namespace ams::kern { size_t alias_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Alias); size_t heap_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Heap); - /* Adjust heap/alias size if we don't have an alias region. */ - if ((flags & ams::svc::CreateProcessFlag_AddressSpaceMask) == ams::svc::CreateProcessFlag_AddressSpace32BitWithoutAlias) { - heap_region_size += alias_region_size; - alias_region_size = 0; - } - /* Set code regions and determine remaining sizes. */ KProcessAddress process_code_start; KProcessAddress process_code_end; diff --git a/libraries/libmesosphere/source/kern_k_process.cpp b/libraries/libmesosphere/source/kern_k_process.cpp index 19a9fd85e..08a79f5c0 100644 --- a/libraries/libmesosphere/source/kern_k_process.cpp +++ b/libraries/libmesosphere/source/kern_k_process.cpp @@ -221,7 +221,7 @@ namespace ams::kern { } /* Set max memory. */ - m_max_process_memory = m_page_table.GetHeapRegionSize(); + m_max_process_memory = KAddressSpaceInfo::GetAddressSpaceSize(static_cast(m_flags), KAddressSpaceInfo::Type_Heap); /* Generate random entropy. */ KSystemControl::GenerateRandom(m_entropy, util::size(m_entropy)); diff --git a/libraries/libmesosphere/source/svc/kern_svc_process.cpp b/libraries/libmesosphere/source/svc/kern_svc_process.cpp index 27ff14b4f..6e516a51f 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_process.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_process.cpp @@ -109,11 +109,12 @@ namespace ams::kern::svc { /* Decide on an address space map region. */ uintptr_t map_start, map_end; size_t map_size; + const size_t code_size = params.code_num_pages * PageSize; switch (params.flags & ams::svc::CreateProcessFlag_AddressSpaceMask) { case ams::svc::CreateProcessFlag_AddressSpace32Bit: case ams::svc::CreateProcessFlag_AddressSpace32BitWithoutAlias: { - map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast(params.flags), KAddressSpaceInfo::Type_MapSmall); + map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast(params.flags), KAddressSpaceInfo::Type_MapSmall, code_size); map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast(params.flags), KAddressSpaceInfo::Type_MapSmall); map_end = map_start + map_size; } @@ -123,7 +124,7 @@ namespace ams::kern::svc { /* 64-bit address space requires 64-bit process. */ R_UNLESS(is_64_bit, svc::ResultInvalidCombination()); - map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast(params.flags), KAddressSpaceInfo::Type_MapSmall); + map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast(params.flags), KAddressSpaceInfo::Type_MapSmall, code_size); map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast(params.flags), KAddressSpaceInfo::Type_MapSmall); map_end = map_start + map_size; } @@ -133,7 +134,7 @@ namespace ams::kern::svc { /* 64-bit address space requires 64-bit process. */ R_UNLESS(is_64_bit, svc::ResultInvalidCombination()); - map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast(params.flags), KAddressSpaceInfo::Type_Map39Bit); + map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast(params.flags), KAddressSpaceInfo::Type_Map39Bit, code_size); map_end = map_start + KAddressSpaceInfo::GetAddressSpaceSize(static_cast(params.flags), KAddressSpaceInfo::Type_Map39Bit); map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast(params.flags), KAddressSpaceInfo::Type_Heap); @@ -181,7 +182,6 @@ namespace ams::kern::svc { const size_t code_num_pages = params.code_num_pages; const size_t system_resource_num_pages = params.system_resource_num_pages; const size_t total_pages = code_num_pages + system_resource_num_pages; - const size_t code_size = code_num_pages * PageSize; const size_t system_resource_size = system_resource_num_pages * PageSize; const size_t total_size = code_size + system_resource_size;