From 5e63792a672f0c61849fbe8069ff015b33711c53 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 28 Mar 2024 02:07:04 -0700 Subject: [PATCH] kern/os: support CreateProcessFlag_EnableAliasRegionExtraSize --- .../arch/arm64/kern_k_page_table.hpp | 2 +- .../arch/arm64/kern_k_process_page_table.hpp | 6 +++-- .../mesosphere/kern_k_page_table_base.hpp | 7 ++++-- .../source/arch/arm64/kern_k_page_table.cpp | 6 ++--- .../source/kern_k_page_table_base.cpp | 22 ++++++++++++++----- .../libmesosphere/source/kern_k_process.cpp | 12 ++++------ .../source/svc/kern_svc_info.cpp | 4 ++++ .../source/svc/kern_svc_process.cpp | 12 ++++++++++ .../impl/os_vamm_manager_impl.os.horizon.hpp | 9 ++++---- .../include/vapours/svc/svc_types_common.hpp | 21 +++++++++++------- 10 files changed, 68 insertions(+), 33 deletions(-) diff --git a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_page_table.hpp b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_page_table.hpp index f8ab5e680..14aba9913 100644 --- a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_page_table.hpp +++ b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_page_table.hpp @@ -178,7 +178,7 @@ namespace ams::kern::arch::arm64 { } NOINLINE Result InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end); - NOINLINE Result InitializeForProcess(ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_das_merge, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit); + NOINLINE Result InitializeForProcess(ams::svc::CreateProcessFlag flags, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit); Result Finalize(); private: Result MapL1Blocks(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, bool disable_head_merge, PageLinkedList *page_list, bool reuse_ll); diff --git a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_process_page_table.hpp b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_process_page_table.hpp index 7209dbfa1..640b9e5e5 100644 --- a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_process_page_table.hpp +++ b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_process_page_table.hpp @@ -28,8 +28,8 @@ namespace ams::kern::arch::arm64 { m_page_table.Activate(id); } - Result Initialize(ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_das_merge, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit) { - R_RETURN(m_page_table.InitializeForProcess(as_type, enable_aslr, enable_das_merge, from_back, pool, code_address, code_size, system_resource, resource_limit)); + Result Initialize(ams::svc::CreateProcessFlag flags, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit) { + R_RETURN(m_page_table.InitializeForProcess(flags, from_back, pool, code_address, code_size, system_resource, resource_limit)); } void Finalize() { m_page_table.Finalize(); } @@ -316,6 +316,8 @@ namespace ams::kern::arch::arm64 { size_t GetKernelMapRegionSize() const { return m_page_table.GetKernelMapRegionSize(); } size_t GetAliasCodeRegionSize() const { return m_page_table.GetAliasCodeRegionSize(); } + size_t GetAliasRegionExtraSize() const { return m_page_table.GetAliasRegionExtraSize(); } + size_t GetNormalMemorySize() const { return m_page_table.GetNormalMemorySize(); } size_t GetCodeSize() const { return m_page_table.GetCodeSize(); } diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp index f53ccfea3..bc5623163 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp @@ -186,6 +186,7 @@ namespace ams::kern { size_t m_mapped_unsafe_physical_memory; size_t m_mapped_insecure_memory; size_t m_mapped_ipc_server_memory; + size_t m_alias_region_extra_size; mutable KLightLock m_general_lock; mutable KLightLock m_map_physical_memory_lock; KLightLock m_device_map_lock; @@ -211,7 +212,7 @@ namespace ams::kern { m_region_ends{Null, Null, Null, Null}, m_current_heap_end(Null), m_alias_code_region_start(Null), m_alias_code_region_end(Null), m_code_region_start(Null), m_code_region_end(Null), - m_max_heap_size(), m_mapped_physical_memory_size(), m_mapped_unsafe_physical_memory(), m_mapped_insecure_memory(), m_mapped_ipc_server_memory(), + m_max_heap_size(), m_mapped_physical_memory_size(), m_mapped_unsafe_physical_memory(), m_mapped_insecure_memory(), m_mapped_ipc_server_memory(), m_alias_region_extra_size(), m_general_lock(), m_map_physical_memory_lock(), m_device_map_lock(), m_impl(util::ConstantInitialize), m_memory_block_manager(util::ConstantInitialize), m_allocate_option(), m_address_space_width(), m_is_kernel(), m_enable_aslr(), m_enable_device_address_space_merge(), m_memory_block_slab_manager(), m_block_info_manager(), m_resource_limit(), m_cached_physical_linear_region(), m_cached_physical_heap_region(), @@ -223,7 +224,7 @@ namespace ams::kern { explicit KPageTableBase() { /* ... */ } NOINLINE Result InitializeForKernel(bool is_64_bit, void *table, KVirtualAddress start, KVirtualAddress end); - NOINLINE Result InitializeForProcess(ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_device_address_space_merge, bool from_back, KMemoryManager::Pool pool, void *table, KProcessAddress start, KProcessAddress end, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit); + NOINLINE Result InitializeForProcess(ams::svc::CreateProcessFlag flags, bool from_back, KMemoryManager::Pool pool, void *table, KProcessAddress start, KProcessAddress end, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit); void Finalize(); @@ -499,6 +500,8 @@ namespace ams::kern { size_t GetAliasCodeRegionSize() const { return m_alias_code_region_end - m_alias_code_region_start; } + size_t GetAliasRegionExtraSize() const { return m_alias_region_extra_size; } + size_t GetNormalMemorySize() const { /* Lock the table. */ KScopedLightLock lk(m_general_lock); diff --git a/libraries/libmesosphere/source/arch/arm64/kern_k_page_table.cpp b/libraries/libmesosphere/source/arch/arm64/kern_k_page_table.cpp index 8ad4a5dd4..0558b5b34 100644 --- a/libraries/libmesosphere/source/arch/arm64/kern_k_page_table.cpp +++ b/libraries/libmesosphere/source/arch/arm64/kern_k_page_table.cpp @@ -207,7 +207,7 @@ namespace ams::kern::arch::arm64 { R_SUCCEED(); } - Result KPageTable::InitializeForProcess(ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_das_merge, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit) { + Result KPageTable::InitializeForProcess(ams::svc::CreateProcessFlag flags, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit) { /* Get an ASID */ m_asid = g_asid_manager.Reserve(); ON_RESULT_FAILURE { g_asid_manager.Release(m_asid); }; @@ -222,10 +222,10 @@ namespace ams::kern::arch::arm64 { ON_RESULT_FAILURE_2 { m_manager->Free(new_table); }; /* Initialize our base table. */ - const size_t as_width = GetAddressSpaceWidth(as_type); + const size_t as_width = GetAddressSpaceWidth(flags); const KProcessAddress as_start = 0; const KProcessAddress as_end = (1ul << as_width); - R_TRY(KPageTableBase::InitializeForProcess(as_type, enable_aslr, enable_das_merge, from_back, pool, GetVoidPointer(new_table), as_start, as_end, code_address, code_size, system_resource, resource_limit)); + R_TRY(KPageTableBase::InitializeForProcess(flags, from_back, pool, GetVoidPointer(new_table), as_start, as_end, code_address, code_size, system_resource, resource_limit)); /* Note that we've updated the table (since we created it). */ this->NoteUpdated(); diff --git a/libraries/libmesosphere/source/kern_k_page_table_base.cpp b/libraries/libmesosphere/source/kern_k_page_table_base.cpp index 647949121..d58ceb717 100644 --- a/libraries/libmesosphere/source/kern_k_page_table_base.cpp +++ b/libraries/libmesosphere/source/kern_k_page_table_base.cpp @@ -112,6 +112,7 @@ namespace ams::kern { m_mapped_unsafe_physical_memory = 0; m_mapped_insecure_memory = 0; m_mapped_ipc_server_memory = 0; + m_alias_region_extra_size = 0; m_memory_block_slab_manager = Kernel::GetSystemSystemResource().GetMemoryBlockSlabManagerPointer(); m_block_info_manager = Kernel::GetSystemSystemResource().GetBlockInfoManagerPointer(); @@ -132,7 +133,7 @@ namespace ams::kern { R_RETURN(m_memory_block_manager.Initialize(m_address_space_start, m_address_space_end, m_memory_block_slab_manager)); } - Result KPageTableBase::InitializeForProcess(ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_das_merge, bool from_back, KMemoryManager::Pool pool, void *table, KProcessAddress start, KProcessAddress end, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit) { + Result KPageTableBase::InitializeForProcess(ams::svc::CreateProcessFlag flags, bool from_back, KMemoryManager::Pool pool, void *table, KProcessAddress start, KProcessAddress end, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit) { /* Validate the region. */ MESOSPHERE_ABORT_UNLESS(start <= code_address); MESOSPHERE_ABORT_UNLESS(code_address < code_address + code_size); @@ -146,13 +147,16 @@ namespace ams::kern { return KAddressSpaceInfo::GetAddressSpaceSize(m_address_space_width, type); }; + /* Default to zero alias region extra size. */ + m_alias_region_extra_size = 0; + /* Set our width and heap/alias sizes. */ - m_address_space_width = GetAddressSpaceWidth(as_type); + m_address_space_width = GetAddressSpaceWidth(flags); 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 ((as_type & ams::svc::CreateProcessFlag_AddressSpaceMask) == ams::svc::CreateProcessFlag_AddressSpace32BitWithoutAlias) { + if ((flags & ams::svc::CreateProcessFlag_AddressSpaceMask) == ams::svc::CreateProcessFlag_AddressSpace32BitWithoutAlias) { heap_region_size += alias_region_size; alias_region_size = 0; } @@ -180,6 +184,14 @@ namespace ams::kern { before_process_code_size = process_code_start - before_process_code_start; after_process_code_start = process_code_end; after_process_code_size = m_code_region_end - process_code_end; + + /* If we have a 39-bit address space and should, enable extra size to the alias region. */ + if (flags & ams::svc::CreateProcessFlag_EnableAliasRegionExtraSize) { + /* Extra size is 1/8th of the address space. */ + m_alias_region_extra_size = (static_cast(1) << m_address_space_width) / 8; + + alias_region_size += m_alias_region_extra_size; + } } else { stack_region_size = 0; kernel_map_region_size = 0; @@ -203,8 +215,8 @@ namespace ams::kern { } /* Set other basic fields. */ - m_enable_aslr = enable_aslr; - m_enable_device_address_space_merge = enable_das_merge; + m_enable_aslr = (flags & ams::svc::CreateProcessFlag_EnableAslr) != 0; + m_enable_device_address_space_merge = (flags & ams::svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge) == 0; m_address_space_start = start; m_address_space_end = end; m_is_kernel = false; diff --git a/libraries/libmesosphere/source/kern_k_process.cpp b/libraries/libmesosphere/source/kern_k_process.cpp index a82d94bec..789bdbc09 100644 --- a/libraries/libmesosphere/source/kern_k_process.cpp +++ b/libraries/libmesosphere/source/kern_k_process.cpp @@ -298,10 +298,8 @@ namespace ams::kern { /* Setup page table. */ { - const auto as_type = static_cast(params.flags & ams::svc::CreateProcessFlag_AddressSpaceMask); - const bool enable_aslr = (params.flags & ams::svc::CreateProcessFlag_EnableAslr) != 0; - const bool enable_das_merge = (params.flags & ams::svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge) == 0; - R_TRY(m_page_table.Initialize(as_type, enable_aslr, enable_das_merge, !enable_aslr, pool, params.code_address, params.code_num_pages * PageSize, m_system_resource, res_limit)); + const bool from_back = (params.flags & ams::svc::CreateProcessFlag_EnableAslr) == 0; + R_TRY(m_page_table.Initialize(static_cast(params.flags), from_back, pool, params.code_address, params.code_num_pages * PageSize, m_system_resource, res_limit)); } ON_RESULT_FAILURE_2 { m_page_table.Finalize(); }; @@ -379,10 +377,8 @@ namespace ams::kern { /* Setup page table. */ { - const auto as_type = static_cast(params.flags & ams::svc::CreateProcessFlag_AddressSpaceMask); - const bool enable_aslr = (params.flags & ams::svc::CreateProcessFlag_EnableAslr) != 0; - const bool enable_das_merge = (params.flags & ams::svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge) == 0; - R_TRY(m_page_table.Initialize(as_type, enable_aslr, enable_das_merge, !enable_aslr, pool, params.code_address, code_size, m_system_resource, res_limit)); + const bool from_back = (params.flags & ams::svc::CreateProcessFlag_EnableAslr) == 0; + R_TRY(m_page_table.Initialize(static_cast(params.flags), from_back, pool, params.code_address, code_size, m_system_resource, res_limit)); } ON_RESULT_FAILURE_2 { m_page_table.Finalize(); }; diff --git a/libraries/libmesosphere/source/svc/kern_svc_info.cpp b/libraries/libmesosphere/source/svc/kern_svc_info.cpp index 3c107b590..e9153edbb 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_info.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_info.cpp @@ -106,6 +106,9 @@ namespace ams::kern::svc { *out = 0; } break; + case ams::svc::InfoType_AliasRegionExtraSize: + *out = process->GetPageTable().GetAliasRegionExtraSize(); + break; MESOSPHERE_UNREACHABLE_DEFAULT_CASE(); } @@ -134,6 +137,7 @@ namespace ams::kern::svc { case ams::svc::InfoType_UsedNonSystemMemorySize: case ams::svc::InfoType_IsApplication: case ams::svc::InfoType_FreeThreadCount: + case ams::svc::InfoType_AliasRegionExtraSize: { /* These info types don't support non-zero subtypes. */ R_UNLESS(info_subtype == 0, svc::ResultInvalidCombination()); diff --git a/libraries/libmesosphere/source/svc/kern_svc_process.cpp b/libraries/libmesosphere/source/svc/kern_svc_process.cpp index e73e5829c..76e36302b 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_process.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_process.cpp @@ -162,6 +162,18 @@ namespace ams::kern::svc { /* Check that the number of extra resource pages is >= 0. */ R_UNLESS(params.system_resource_num_pages >= 0, svc::ResultInvalidSize()); + /* Validate that the alias region extra size is allowed, if enabled. */ + if (params.flags & ams::svc::CreateProcessFlag_EnableAliasRegionExtraSize) { + /* Check that we have a 64-bit address space. */ + R_UNLESS((params.flags & ams::svc::CreateProcessFlag_AddressSpaceMask) == ams::svc::CreateProcessFlag_AddressSpace64Bit, svc::ResultInvalidState()); + + /* Check that the system resource page count is non-zero. */ + R_UNLESS(params.system_resource_num_pages > 0, svc::ResultInvalidState()); + + /* Check that debug mode is enabled. */ + R_UNLESS(KTargetSystem::IsDebugMode(), svc::ResultInvalidState()); + } + /* Convert to sizes. */ const size_t code_num_pages = params.code_num_pages; const size_t system_resource_num_pages = params.system_resource_num_pages; diff --git a/libraries/libstratosphere/source/os/impl/os_vamm_manager_impl.os.horizon.hpp b/libraries/libstratosphere/source/os/impl/os_vamm_manager_impl.os.horizon.hpp index dad8aee6f..fb1519f88 100644 --- a/libraries/libstratosphere/source/os/impl/os_vamm_manager_impl.os.horizon.hpp +++ b/libraries/libstratosphere/source/os/impl/os_vamm_manager_impl.os.horizon.hpp @@ -21,11 +21,12 @@ namespace ams::os::impl { class VammManagerHorizonImpl { public: static void GetReservedRegionImpl(uintptr_t *out_start, uintptr_t *out_size) { - u64 start, size; - R_ABORT_UNLESS(svc::GetInfo(std::addressof(start), svc::InfoType_AliasRegionAddress, svc::PseudoHandle::CurrentProcess, 0)); - R_ABORT_UNLESS(svc::GetInfo(std::addressof(size), svc::InfoType_AliasRegionSize, svc::PseudoHandle::CurrentProcess, 0)); + u64 start, size, extra_size; + R_ABORT_UNLESS(svc::GetInfo(std::addressof(start), svc::InfoType_AliasRegionAddress, svc::PseudoHandle::CurrentProcess, 0)); + R_ABORT_UNLESS(svc::GetInfo(std::addressof(size), svc::InfoType_AliasRegionSize, svc::PseudoHandle::CurrentProcess, 0)); + R_ABORT_UNLESS(svc::GetInfo(std::addressof(extra_size), svc::InfoType_AliasRegionExtraSize, svc::PseudoHandle::CurrentProcess, 0)); *out_start = start; - *out_size = size; + *out_size = size - extra_size; } static Result AllocatePhysicalMemoryImpl(uintptr_t address, size_t size) { diff --git a/libraries/libvapours/include/vapours/svc/svc_types_common.hpp b/libraries/libvapours/include/vapours/svc/svc_types_common.hpp index f71d2c486..5668cd2dd 100644 --- a/libraries/libvapours/include/vapours/svc/svc_types_common.hpp +++ b/libraries/libvapours/include/vapours/svc/svc_types_common.hpp @@ -190,6 +190,7 @@ namespace ams::svc { InfoType_ThreadTickCount = 25, InfoType_IsSvcPermitted = 26, InfoType_IoRegionHint = 27, + InfoType_AliasRegionExtraSize = 28, InfoType_MesosphereMeta = 65000, InfoType_MesosphereCurrentProcess = 65001, @@ -436,15 +437,19 @@ namespace ams::svc { /* 11.x+ DisableDeviceAddressSpaceMerge. */ CreateProcessFlag_DisableDeviceAddressSpaceMerge = (1 << 12), + /* 18.x EnableAliasRegionExtraSize. */ + CreateProcessFlag_EnableAliasRegionExtraSize = (1 << 13), + /* Mask of all flags. */ - CreateProcessFlag_All = CreateProcessFlag_Is64Bit | - CreateProcessFlag_AddressSpaceMask | - CreateProcessFlag_EnableDebug | - CreateProcessFlag_EnableAslr | - CreateProcessFlag_IsApplication | - CreateProcessFlag_PoolPartitionMask | - CreateProcessFlag_OptimizeMemoryAllocation | - CreateProcessFlag_DisableDeviceAddressSpaceMerge, + CreateProcessFlag_All = CreateProcessFlag_Is64Bit | + CreateProcessFlag_AddressSpaceMask | + CreateProcessFlag_EnableDebug | + CreateProcessFlag_EnableAslr | + CreateProcessFlag_IsApplication | + CreateProcessFlag_PoolPartitionMask | + CreateProcessFlag_OptimizeMemoryAllocation | + CreateProcessFlag_DisableDeviceAddressSpaceMerge | + CreateProcessFlag_EnableAliasRegionExtraSize, }; /* Debug types. */