diff --git a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_cpu_system_registers.hpp b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_cpu_system_registers.hpp index 61e066fee..1b6d93201 100644 --- a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_cpu_system_registers.hpp +++ b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_cpu_system_registers.hpp @@ -81,6 +81,7 @@ namespace ams::kern::arch::arm64::cpu { MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(SpEl0, sp_el0) MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(IdAa64Dfr0El1, id_aa64dfr0_el1) + MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(IdAa64Mmfr0El1, id_aa64mmfr0_el1) MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(PmcrEl0, pmcr_el0) MESOSPHERE_CPU_DEFINE_SYSREG_ACCESSORS(PmUserEnrEl0, pmuserenr_el0) 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 2ab8527c9..356dc4217 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 @@ -94,10 +94,10 @@ namespace ams::kern::arch::arm64 { return KPageTable::GetBlockSize(static_cast(KPageTable::GetBlockType(alignment) + 1)); } public: - /* TODO: How should this size be determined. Does the KProcess slab count need to go in a header as a define? */ - static constexpr size_t NumTtbr0Entries = 81; + static constexpr size_t NumPTEntries = ::ams::kern::init::SlabCountKProcess + 1; /* +1 for kernel. */ private: - static constinit inline const volatile u64 s_ttbr0_entries[NumTtbr0Entries] = {}; + static constinit inline const volatile u64 s_ttbr0_entries[NumPTEntries] = {}; + static constinit inline const volatile u64 s_tcr_el1_entries[NumPTEntries] = {}; private: KPageTableManager *m_manager; u8 m_asid; @@ -188,6 +188,12 @@ namespace ams::kern::arch::arm64 { return s_ttbr0_entries[0]; } + static const volatile u64 &GetTcrEL1Entry(size_t index) { return s_tcr_el1_entries[index]; } + + static ALWAYS_INLINE u64 GetKernelTcrEL1() { + return s_tcr_el1_entries[0]; + } + static ALWAYS_INLINE void ActivateKernel() { /* Activate, using asid 0 and process id = 0xFFFFFFFF */ cpu::SwitchProcess(GetKernelTtbr0(), 0xFFFFFFFF); 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 e18a6fbc8..63a357e0e 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 @@ -302,19 +302,21 @@ namespace ams::kern::arch::arm64 { bool CanContain(KProcessAddress addr, size_t size, KMemoryState state) const { return m_page_table.CanContain(addr, size, state); } bool CanContain(KProcessAddress addr, size_t size, ams::svc::MemoryState state) const { return m_page_table.CanContain(addr, size, state); } - KProcessAddress GetAddressSpaceStart() const { return m_page_table.GetAddressSpaceStart(); } - KProcessAddress GetHeapRegionStart() const { return m_page_table.GetHeapRegionStart(); } - KProcessAddress GetAliasRegionStart() const { return m_page_table.GetAliasRegionStart(); } - KProcessAddress GetStackRegionStart() const { return m_page_table.GetStackRegionStart(); } - KProcessAddress GetKernelMapRegionStart() const { return m_page_table.GetKernelMapRegionStart(); } - KProcessAddress GetAliasCodeRegionStart() const { return m_page_table.GetAliasCodeRegionStart(); } + KProcessAddress GetAddressSpaceStart() const { return m_page_table.GetAddressSpaceStart(); } + KProcessAddress GetShadowStackRegionStart() const { return m_page_table.GetShadowStackRegionStart(); } + KProcessAddress GetHeapRegionStart() const { return m_page_table.GetHeapRegionStart(); } + KProcessAddress GetAliasRegionStart() const { return m_page_table.GetAliasRegionStart(); } + KProcessAddress GetStackRegionStart() const { return m_page_table.GetStackRegionStart(); } + KProcessAddress GetKernelMapRegionStart() const { return m_page_table.GetKernelMapRegionStart(); } + KProcessAddress GetAliasCodeRegionStart() const { return m_page_table.GetAliasCodeRegionStart(); } - size_t GetAddressSpaceSize() const { return m_page_table.GetAddressSpaceSize(); } - size_t GetHeapRegionSize() const { return m_page_table.GetHeapRegionSize(); } - size_t GetAliasRegionSize() const { return m_page_table.GetAliasRegionSize(); } - size_t GetStackRegionSize() const { return m_page_table.GetStackRegionSize(); } - size_t GetKernelMapRegionSize() const { return m_page_table.GetKernelMapRegionSize(); } - size_t GetAliasCodeRegionSize() const { return m_page_table.GetAliasCodeRegionSize(); } + size_t GetAddressSpaceSize() const { return m_page_table.GetAddressSpaceSize(); } + size_t GetShadowStackRegionSize() const { return m_page_table.GetShadowStackRegionSize(); } + size_t GetHeapRegionSize() const { return m_page_table.GetHeapRegionSize(); } + size_t GetAliasRegionSize() const { return m_page_table.GetAliasRegionSize(); } + size_t GetStackRegionSize() const { return m_page_table.GetStackRegionSize(); } + 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(); } diff --git a/libraries/libmesosphere/include/mesosphere/init/kern_init_slab_setup.hpp b/libraries/libmesosphere/include/mesosphere/init/kern_init_slab_setup.hpp index 209b8d732..32bba1e5a 100644 --- a/libraries/libmesosphere/include/mesosphere/init/kern_init_slab_setup.hpp +++ b/libraries/libmesosphere/include/mesosphere/init/kern_init_slab_setup.hpp @@ -18,6 +18,25 @@ #include namespace ams::kern::init { + /* Constexpr counts. */ + constexpr size_t SlabCountKProcess = 80; + constexpr size_t SlabCountKThread = 800; + constexpr size_t SlabCountKEvent = 900; + constexpr size_t SlabCountKInterruptEvent = 100; + constexpr size_t SlabCountKPort = 384; + constexpr size_t SlabCountKSharedMemory = 80; + constexpr size_t SlabCountKTransferMemory = 200; + constexpr size_t SlabCountKCodeMemory = 10; + constexpr size_t SlabCountKDeviceAddressSpace = 300; + constexpr size_t SlabCountKSession = 1133; + constexpr size_t SlabCountKLightSession = 100; + constexpr size_t SlabCountKObjectName = 7; + constexpr size_t SlabCountKResourceLimit = 5; + constexpr size_t SlabCountKDebug = cpu::NumCores; + constexpr size_t SlabCountKIoPool = 1; + constexpr size_t SlabCountKIoRegion = 6; + constexpr size_t SlabcountKSessionRequestMappings = 40; + struct KSlabResourceCounts { size_t num_KProcess; 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 775c0054c..00d942a66 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_address_space_info.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_address_space_info.hpp @@ -24,7 +24,7 @@ namespace ams::kern { enum Type { Type_MapSmall = 0, Type_MapLarge = 1, - Type_Map39Bit = 2, + Type_MapHuge = 2, Type_Heap = 3, Type_Stack = 4, Type_Alias = 5, diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_memory_block.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_memory_block.hpp index 57876fbcb..9e9e9c7a4 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_memory_block.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_memory_block.hpp @@ -211,15 +211,15 @@ namespace ams::kern { uintptr_t m_address; size_t m_size; KMemoryState m_state; - u16 m_device_disable_merge_left_count; - u16 m_device_disable_merge_right_count; - u16 m_ipc_lock_count; - u16 m_device_use_count; - u16 m_ipc_disable_merge_count; KMemoryPermission m_permission; KMemoryAttribute m_attribute; KMemoryPermission m_original_permission; + u16 m_ipc_lock_count; + u16 m_device_use_count; KMemoryBlockDisableMergeAttribute m_disable_merge_attribute; + u16 m_ipc_disable_merge_count; + u16 m_device_disable_merge_left_count; + u16 m_device_disable_merge_right_count; constexpr ams::svc::MemoryInfo GetSvcMemoryInfo() const { return { @@ -365,15 +365,15 @@ namespace ams::kern { .m_address = GetInteger(this->GetAddress()), .m_size = this->GetSize(), .m_state = m_memory_state, - .m_device_disable_merge_left_count = m_device_disable_merge_left_count, - .m_device_disable_merge_right_count = m_device_disable_merge_right_count, - .m_ipc_lock_count = m_ipc_lock_count, - .m_device_use_count = m_device_use_count, - .m_ipc_disable_merge_count = m_ipc_disable_merge_count, .m_permission = m_permission, .m_attribute = m_attribute, .m_original_permission = m_original_permission, + .m_ipc_lock_count = m_ipc_lock_count, + .m_device_use_count = m_device_use_count, .m_disable_merge_attribute = m_disable_merge_attribute, + .m_ipc_disable_merge_count = m_ipc_disable_merge_count, + .m_device_disable_merge_left_count = m_device_disable_merge_left_count, + .m_device_disable_merge_right_count = m_device_disable_merge_right_count, }; } public: 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 25c149b7f..759fd1758 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp @@ -90,10 +90,11 @@ namespace ams::kern { }; enum RegionType { - RegionType_KernelMap = 0, - RegionType_Stack = 1, - RegionType_Alias = 2, - RegionType_Heap = 3, + RegionType_KernelMap = 0, + RegionType_Stack = 1, + RegionType_Alias = 2, + RegionType_Heap = 3, + RegionType_ShadowStack = 4, RegionType_Count, }; @@ -196,7 +197,6 @@ namespace ams::kern { KPageTableImpl m_impl; KMemoryBlockManager m_memory_block_manager; u32 m_allocate_option; - u32 m_address_space_width; bool m_is_kernel; bool m_enable_aslr; bool m_enable_device_address_space_merge; @@ -212,23 +212,24 @@ namespace ams::kern { public: constexpr explicit KPageTableBase(util::ConstantInitializeTag) : m_address_space_start(Null), m_address_space_end(Null), - m_region_starts{Null, Null, Null, Null}, - m_region_ends{Null, Null, Null, Null}, + m_region_starts{Null, Null, Null, Null, Null}, + m_region_ends{Null, 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_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_allowed_exec_device_mapping(), - m_memory_block_slab_manager(), m_block_info_manager(), m_resource_limit(), m_cached_physical_linear_region(), m_cached_physical_heap_region(), - m_heap_fill_value(), m_ipc_fill_value(), m_stack_fill_value() + 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_is_kernel(), m_enable_aslr(), m_enable_device_address_space_merge(), m_allowed_exec_device_mapping(), + m_memory_block_slab_manager(), m_block_info_manager(), m_resource_limit(), m_cached_physical_linear_region(), + m_cached_physical_heap_region(), m_heap_fill_value(), m_ipc_fill_value(), m_stack_fill_value() { /* ... */ } explicit KPageTableBase() { /* ... */ } - NOINLINE void InitializeForKernel(bool is_64_bit, void *table, KVirtualAddress start, KVirtualAddress end); - 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); + NOINLINE void InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end); + NOINLINE Result InitializeForProcess(ams::svc::CreateProcessFlag flags, bool from_back, void *table, KProcessAddress start, KProcessAddress end, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit); void Finalize(); @@ -247,6 +248,14 @@ namespace ams::kern { return this->Contains(addr, size) && m_region_starts[RegionType_Alias] <= addr && addr + size - 1 <= m_region_ends[RegionType_Alias] - 1; } + constexpr bool IsInShadowStackRegion(KProcessAddress addr, size_t size) const { + return this->Contains(addr, size) && m_region_starts[RegionType_ShadowStack] <= addr && addr + size - 1 <= m_region_ends[RegionType_ShadowStack] - 1; + } + + constexpr bool IsSafeUserPointer(KProcessAddress addr, size_t size) const { + return this->Contains(addr, size) && !this->IsInShadowStackRegion(addr, size); + } + bool IsInUnsafeAliasRegion(KProcessAddress addr, size_t size) const { /* Even though Unsafe physical memory is KMemoryState_Normal, it must be mapped inside the alias code region. */ return this->CanContain(addr, size, ams::svc::MemoryState_AliasCode); @@ -490,19 +499,21 @@ namespace ams::kern { public: KProcessAddress GetAddressSpaceStart() const { return m_address_space_start; } - KProcessAddress GetHeapRegionStart() const { return m_region_starts[RegionType_Heap]; } - KProcessAddress GetAliasRegionStart() const { return m_region_starts[RegionType_Alias]; } - KProcessAddress GetStackRegionStart() const { return m_region_starts[RegionType_Stack]; } - KProcessAddress GetKernelMapRegionStart() const { return m_region_starts[RegionType_KernelMap]; } + KProcessAddress GetShadowStackRegionStart() const { return m_region_starts[RegionType_ShadowStack]; } + KProcessAddress GetHeapRegionStart() const { return m_region_starts[RegionType_Heap]; } + KProcessAddress GetAliasRegionStart() const { return m_region_starts[RegionType_Alias]; } + KProcessAddress GetStackRegionStart() const { return m_region_starts[RegionType_Stack]; } + KProcessAddress GetKernelMapRegionStart() const { return m_region_starts[RegionType_KernelMap]; } KProcessAddress GetAliasCodeRegionStart() const { return m_alias_code_region_start; } size_t GetAddressSpaceSize() const { return m_address_space_end - m_address_space_start; } - size_t GetHeapRegionSize() const { return m_region_ends[RegionType_Heap] - m_region_starts[RegionType_Heap]; } - size_t GetAliasRegionSize() const { return m_region_ends[RegionType_Alias] - m_region_starts[RegionType_Alias]; } - size_t GetStackRegionSize() const { return m_region_ends[RegionType_Stack] - m_region_starts[RegionType_Stack]; } - size_t GetKernelMapRegionSize() const { return m_region_ends[RegionType_KernelMap] - m_region_starts[RegionType_KernelMap]; } + size_t GetShadowStackRegionSize() const { return m_region_ends[RegionType_ShadowStack] - m_region_starts[RegionType_ShadowStack]; } + size_t GetHeapRegionSize() const { return m_region_ends[RegionType_Heap] - m_region_starts[RegionType_Heap]; } + size_t GetAliasRegionSize() const { return m_region_ends[RegionType_Alias] - m_region_starts[RegionType_Alias]; } + size_t GetStackRegionSize() const { return m_region_ends[RegionType_Stack] - m_region_starts[RegionType_Stack]; } + size_t GetKernelMapRegionSize() const { return m_region_ends[RegionType_KernelMap] - m_region_starts[RegionType_KernelMap]; } size_t GetAliasCodeRegionSize() const { return m_alias_code_region_end - m_alias_code_region_start; } diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp index 0b0622869..d20e49c7c 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp @@ -215,6 +215,7 @@ namespace ams::kern { } u32 GetAllocateOption() const { return m_page_table.GetAllocateOption(); } + size_t GetAddressSpaceSize() const { return m_page_table.GetAddressSpaceSize(); } ThreadList &GetThreadList() { return m_thread_list; } const ThreadList &GetThreadList() const { return m_thread_list; } 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 6992281dd..b22874027 100644 --- a/libraries/libmesosphere/source/arch/arm64/kern_k_page_table.cpp +++ b/libraries/libmesosphere/source/arch/arm64/kern_k_page_table.cpp @@ -125,7 +125,7 @@ namespace ams::kern::arch::arm64 { m_manager = Kernel::GetSystemSystemResource().GetPageTableManagerPointer(); /* Initialize the base page table. */ - KPageTableBase::InitializeForKernel(true, table, start, end); + KPageTableBase::InitializeForKernel(table, start, end); } 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, size_t process_index) { @@ -144,7 +144,7 @@ namespace ams::kern::arch::arm64 { const size_t as_width = GetAddressSpaceWidth(flags); const KProcessAddress as_start = 0; const KProcessAddress as_end = (1ul << as_width); - R_TRY(KPageTableBase::InitializeForProcess(flags, from_back, pool, GetVoidPointer(ttbr0_virt), as_start, as_end, code_address, code_size, system_resource, resource_limit)); + R_TRY(KPageTableBase::InitializeForProcess(flags, from_back, GetVoidPointer(ttbr0_virt), as_start, as_end, pool, 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/init/kern_init_slab_setup.cpp b/libraries/libmesosphere/source/init/kern_init_slab_setup.cpp index b82e78f84..3336c94a9 100644 --- a/libraries/libmesosphere/source/init/kern_init_slab_setup.cpp +++ b/libraries/libmesosphere/source/init/kern_init_slab_setup.cpp @@ -60,25 +60,6 @@ namespace ams::kern::init { #undef DEFINE_SLAB_TYPE_ENUM_MEMBER - /* Constexpr counts. */ - constexpr size_t SlabCountKProcess = 80; - constexpr size_t SlabCountKThread = 800; - constexpr size_t SlabCountKEvent = 900; - constexpr size_t SlabCountKInterruptEvent = 100; - constexpr size_t SlabCountKPort = 384; - constexpr size_t SlabCountKSharedMemory = 80; - constexpr size_t SlabCountKTransferMemory = 200; - constexpr size_t SlabCountKCodeMemory = 10; - constexpr size_t SlabCountKDeviceAddressSpace = 300; - constexpr size_t SlabCountKSession = 1133; - constexpr size_t SlabCountKLightSession = 100; - constexpr size_t SlabCountKObjectName = 7; - constexpr size_t SlabCountKResourceLimit = 5; - constexpr size_t SlabCountKDebug = cpu::NumCores; - constexpr size_t SlabCountKIoPool = 1; - constexpr size_t SlabCountKIoRegion = 6; - constexpr size_t SlabcountKSessionRequestMappings = 40; - constexpr size_t SlabCountExtraKThread = (1024 + 256 + 256) - SlabCountKThread; namespace test { diff --git a/libraries/libmesosphere/source/kern_k_address_space_info.cpp b/libraries/libmesosphere/source/kern_k_address_space_info.cpp index 3aa24c5de..022dc9b54 100644 --- a/libraries/libmesosphere/source/kern_k_address_space_info.cpp +++ b/libraries/libmesosphere/source/kern_k_address_space_info.cpp @@ -30,15 +30,20 @@ namespace ams::kern { { 36, ams::svc::AddressLargeMap36Start, ams::svc::AddressLargeMap36Size, KAddressSpaceInfo::Type_MapLarge, }, { 36, Invalid, ams::svc::AddressMemoryRegionHeap36Size, KAddressSpaceInfo::Type_Heap, }, { 36, Invalid, ams::svc::AddressMemoryRegionAlias36Size, KAddressSpaceInfo::Type_Alias, }, - { 39, ams::svc::AddressMap39Start, ams::svc::AddressMap39Size, KAddressSpaceInfo::Type_Map39Bit, }, + { 39, ams::svc::AddressMap39Start, ams::svc::AddressMap39Size, KAddressSpaceInfo::Type_MapHuge, }, { 39, Invalid, ams::svc::AddressMemoryRegionSmall39Size, KAddressSpaceInfo::Type_MapSmall, }, { 39, Invalid, ams::svc::AddressMemoryRegionHeap39Size, KAddressSpaceInfo::Type_Heap, }, { 39, Invalid, ams::svc::AddressMemoryRegionAlias39Size, KAddressSpaceInfo::Type_Alias, }, { 39, Invalid, ams::svc::AddressMemoryRegionStack39Size, KAddressSpaceInfo::Type_Stack, }, + { 42, ams::svc::AddressMap42Start, ams::svc::AddressMap42Size, KAddressSpaceInfo::Type_MapHuge, }, + { 42, Invalid, ams::svc::AddressMemoryRegionSmall42Size, KAddressSpaceInfo::Type_MapSmall, }, + { 42, Invalid, 0, KAddressSpaceInfo::Type_Heap, }, + { 42, Invalid, ams::svc::AddressMemoryRegionAlias42Size, KAddressSpaceInfo::Type_Alias, }, + { 42, Invalid, ams::svc::AddressMemoryRegionStack42Size, KAddressSpaceInfo::Type_Stack, }, }; - constexpr u8 FlagsToAddressSpaceWidthTable[4] = { - 32, 36, 32, 39 + constexpr u8 FlagsToAddressSpaceWidthTable[5] = { + 32, 36, 32, 39, 42 }; constexpr size_t GetAddressSpaceWidth(ams::svc::CreateProcessFlag flags) { @@ -54,6 +59,7 @@ namespace ams::kern { static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessFlag_AddressSpace64BitDeprecated) == 36); static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessFlag_AddressSpace32BitWithoutAlias) == 32); static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessFlag_AddressSpace64Bit) == 39); + static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessFlag_AddressSpace64Bit64KPage) == 42); KAddressSpaceInfo &GetAddressSpaceInfo(size_t width, KAddressSpaceInfo::Type type) { for (auto &info : AddressSpaceInfos) { diff --git a/libraries/libmesosphere/source/kern_k_initial_process_reader.cpp b/libraries/libmesosphere/source/kern_k_initial_process_reader.cpp index 5d9164efb..61c04dd18 100644 --- a/libraries/libmesosphere/source/kern_k_initial_process_reader.cpp +++ b/libraries/libmesosphere/source/kern_k_initial_process_reader.cpp @@ -233,7 +233,7 @@ namespace ams::kern { /* 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 ASType as_type = this->Is64BitAddressSpace() ? ((GetTargetFirmware() >= TargetFirmware_2_0_0) ? KAddressSpaceInfo::Type_MapHuge : KAddressSpaceInfo::Type_MapSmall) : KAddressSpaceInfo::Type_MapSmall; 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; diff --git a/libraries/libmesosphere/source/kern_k_page_table_base.cpp b/libraries/libmesosphere/source/kern_k_page_table_base.cpp index 5d34dbe1f..98988dde6 100644 --- a/libraries/libmesosphere/source/kern_k_page_table_base.cpp +++ b/libraries/libmesosphere/source/kern_k_page_table_base.cpp @@ -88,14 +88,14 @@ namespace ams::kern { } } - void KPageTableBase::InitializeForKernel(bool is_64_bit, void *table, KVirtualAddress start, KVirtualAddress end) { + void KPageTableBase::InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end) { /* Initialize our members. */ - m_address_space_width = (is_64_bit) ? BITSIZEOF(u64) : BITSIZEOF(u32); m_address_space_start = KProcessAddress(GetInteger(start)); m_address_space_end = KProcessAddress(GetInteger(end)); m_is_kernel = true; m_enable_aslr = true; m_enable_device_address_space_merge = false; + m_allowed_exec_device_mapping = false; for (auto i = 0; i < RegionType_Count; ++i) { m_region_starts[i] = 0; @@ -133,7 +133,7 @@ namespace ams::kern { MESOSPHERE_R_ABORT_UNLESS(m_memory_block_manager.Initialize(m_address_space_start, m_address_space_end, m_memory_block_slab_manager)); } - 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) { + Result KPageTableBase::InitializeForProcess(ams::svc::CreateProcessFlag flags, bool from_back, void *table, KProcessAddress start, KProcessAddress end, KMemoryManager::Pool pool, 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); @@ -151,9 +151,9 @@ namespace ams::kern { m_alias_region_extra_size = 0; /* Set our width and heap/alias sizes. */ - m_address_space_width = GetAddressSpaceWidth(flags); - size_t alias_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Alias); - size_t heap_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Heap); + size_t address_space_width = GetAddressSpaceWidth(flags); + size_t alias_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Alias); + size_t heap_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Heap); /* Set code regions and determine remaining sizes. */ KProcessAddress process_code_start; @@ -162,12 +162,12 @@ namespace ams::kern { size_t kernel_map_region_size; KProcessAddress before_process_code_start, after_process_code_start; size_t before_process_code_size, after_process_code_size; - if (m_address_space_width == 39) { + if (address_space_width == 39 || address_space_width == 42) { stack_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Stack); kernel_map_region_size = GetSpaceSize(KAddressSpaceInfo::Type_MapSmall); - m_code_region_start = GetSpaceStart(KAddressSpaceInfo::Type_Map39Bit); - m_code_region_end = m_code_region_start + GetSpaceSize(KAddressSpaceInfo::Type_Map39Bit); + m_code_region_start = GetSpaceStart(KAddressSpaceInfo::Type_MapHuge); + m_code_region_end = m_code_region_start + GetSpaceSize(KAddressSpaceInfo::Type_MapHuge); m_alias_code_region_start = m_code_region_start; m_alias_code_region_end = m_code_region_end; @@ -182,7 +182,7 @@ namespace ams::kern { /* 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; + m_alias_region_extra_size = (static_cast(1) << address_space_width) / 8; alias_region_size += m_alias_region_extra_size; } @@ -208,6 +208,9 @@ namespace ams::kern { after_process_code_size = GetSpaceSize(KAddressSpaceInfo::Type_MapLarge); } + m_region_starts[RegionType_ShadowStack] = Null; + m_region_ends[RegionType_ShadowStack] = Null; + /* Set other basic fields. */ m_enable_aslr = (flags & ams::svc::CreateProcessFlag_EnableAslr) != 0; m_enable_device_address_space_merge = (flags & ams::svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge) == 0; @@ -237,6 +240,9 @@ namespace ams::kern { region_layouts[num_regions++] = { .size = alias_region_size, .type = RegionType_Alias, .alloc_index = 0, }; region_layouts[num_regions++] = { .size = heap_region_size, .type = RegionType_Heap, .alloc_index = 0, }; + if (flags & ams::svc::CreateProcessFlag_EnableShadowStack) { + region_layouts[num_regions++] = { .size = ams::svc::AddressShadowStackRegionSize, .type = RegionType_ShadowStack, .alloc_index = 0, }; + } /* Selection-sort the regions by size largest-to-smallest. */ for (size_t i = 0; i < num_regions - 1; ++i) { @@ -399,6 +405,18 @@ namespace ams::kern { break; } } + + /* Check for overlap with shadow stack. */ + for (size_t ss = 0; ss < num_regions; ++ss) { + if (const auto &shadow_stack_region = region_layouts[ss]; shadow_stack_region.type == RegionType_ShadowStack) { + if (shadow_stack_region.size != 0) { + const KProcessAddress shadow_stack_start = m_region_starts[RegionType_ShadowStack]; + const KProcessAddress shadow_stack_last = m_region_ends[RegionType_ShadowStack] - 1; + MESOSPHERE_ABORT_UNLESS(kmap_last < shadow_stack_start || shadow_stack_last < kmap_start); + } + break; + } + } } } @@ -494,6 +512,25 @@ namespace ams::kern { MESOSPHERE_ABORT_UNLESS(heap_last < process_code_start || process_code_last < heap_start); } } + + /* Check that the ShadowStack region is valid. */ + for (size_t ss = 0; ss < num_regions; ++ss) { + if (const auto &shadow_stack_region = region_layouts[ss]; shadow_stack_region.type == RegionType_ShadowStack) { + /* If there's no shadow stack region, we have nothing to check. */ + if (shadow_stack_region.size == 0) { + break; + } + + /* Check that the shadow stack region is within our address space. */ + MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_starts[RegionType_ShadowStack])); + MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_ends[RegionType_ShadowStack])); + + /* Check for overlap with process code. */ + const KProcessAddress shadow_stack_start = m_region_starts[RegionType_ShadowStack]; + const KProcessAddress shadow_stack_last = m_region_ends[RegionType_ShadowStack] - 1; + MESOSPHERE_ABORT_UNLESS(shadow_stack_last < process_code_start || process_code_last < shadow_stack_start); + } + } } /* Set heap and fill members. */ @@ -1997,15 +2034,15 @@ namespace ams::kern { .m_address = GetInteger(m_address_space_end), .m_size = 0 - GetInteger(m_address_space_end), .m_state = static_cast(ams::svc::MemoryState_Inaccessible), - .m_device_disable_merge_left_count = 0, - .m_device_disable_merge_right_count = 0, - .m_ipc_lock_count = 0, - .m_device_use_count = 0, - .m_ipc_disable_merge_count = 0, .m_permission = KMemoryPermission_None, .m_attribute = KMemoryAttribute_None, .m_original_permission = KMemoryPermission_None, + .m_ipc_lock_count = 0, + .m_device_use_count = 0, .m_disable_merge_attribute = KMemoryBlockDisableMergeAttribute_None, + .m_ipc_disable_merge_count = 0, + .m_device_disable_merge_left_count = 0, + .m_device_disable_merge_right_count = 0, }; out_page_info->flags = 0; diff --git a/libraries/libmesosphere/source/svc/kern_svc_info.cpp b/libraries/libmesosphere/source/svc/kern_svc_info.cpp index ec41ef59a..8b51c7fba 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_info.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_info.cpp @@ -109,6 +109,15 @@ namespace ams::kern::svc { case ams::svc::InfoType_AliasRegionExtraSize: *out = process->GetPageTable().GetAliasRegionExtraSize(); break; + case ams::svc::InfoType_AddressSpaceSize: + *out = process->GetAddressSpaceSize(); + break; + case ams::svc::InfoType_ShadowStackRegionAddress: + *out = GetInteger(process->GetPageTable().GetShadowStackRegionStart()); + break; + case ams::svc::InfoType_ShadowStackRegionSize: + *out = process->GetPageTable().GetShadowStackRegionSize(); + break; MESOSPHERE_UNREACHABLE_DEFAULT_CASE(); } @@ -138,6 +147,9 @@ namespace ams::kern::svc { case ams::svc::InfoType_IsApplication: case ams::svc::InfoType_FreeThreadCount: case ams::svc::InfoType_AliasRegionExtraSize: + case ams::svc::InfoType_AddressSpaceSize: + case ams::svc::InfoType_ShadowStackRegionAddress: + case ams::svc::InfoType_ShadowStackRegionSize: { /* 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 6e516a51f..54f598d1e 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_process.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_process.cpp @@ -100,6 +100,9 @@ namespace ams::kern::svc { /* Validate that the parameter flags are valid. */ R_UNLESS((params.flags & ~ams::svc::CreateProcessFlag_All) == 0, svc::ResultInvalidEnumValue()); + /* The 64KB page size is not yet allowed. */ + R_UNLESS((params.flags & ams::svc::CreateProcessFlag_AddressSpaceMask) != ams::svc::CreateProcessFlag_AddressSpace64Bit64KPage, svc::ResultInvalidCombination()); + /* Validate that 64-bit process is okay. */ const bool is_64_bit = (params.flags & ams::svc::CreateProcessFlag_Is64Bit) != 0; if constexpr (sizeof(void *) < sizeof(u64)) { @@ -130,12 +133,13 @@ namespace ams::kern::svc { } break; case ams::svc::CreateProcessFlag_AddressSpace64Bit: + case ams::svc::CreateProcessFlag_AddressSpace64Bit64KPage: { /* 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, code_size); - map_end = map_start + KAddressSpaceInfo::GetAddressSpaceSize(static_cast(params.flags), KAddressSpaceInfo::Type_Map39Bit); + map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast(params.flags), KAddressSpaceInfo::Type_MapHuge, code_size); + map_end = map_start + KAddressSpaceInfo::GetAddressSpaceSize(static_cast(params.flags), KAddressSpaceInfo::Type_MapHuge); map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast(params.flags), KAddressSpaceInfo::Type_Heap); } diff --git a/libraries/libstratosphere/include/stratosphere/cfg/cfg_types.hpp b/libraries/libstratosphere/include/stratosphere/cfg/cfg_types.hpp index dd898a96f..20976587c 100644 --- a/libraries/libstratosphere/include/stratosphere/cfg/cfg_types.hpp +++ b/libraries/libstratosphere/include/stratosphere/cfg/cfg_types.hpp @@ -35,6 +35,7 @@ namespace ams::cfg { OverrideStatusFlag_AddressSpace64BitDeprecated = (svc::CreateProcessFlag_AddressSpace64BitDeprecated >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift, OverrideStatusFlag_AddressSpace32BitWithoutAlias = (svc::CreateProcessFlag_AddressSpace32BitWithoutAlias >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift, OverrideStatusFlag_AddressSpace64Bit = (svc::CreateProcessFlag_AddressSpace64Bit >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift, + OverrideStatusFlag_AddressSpace64Bit64KPage = (svc::CreateProcessFlag_AddressSpace64Bit64KPage >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift, #endif }; diff --git a/libraries/libstratosphere/include/stratosphere/ldr/ldr_types.hpp b/libraries/libstratosphere/include/stratosphere/ldr/ldr_types.hpp index aa33b4e15..c97711a53 100644 --- a/libraries/libstratosphere/include/stratosphere/ldr/ldr_types.hpp +++ b/libraries/libstratosphere/include/stratosphere/ldr/ldr_types.hpp @@ -235,11 +235,16 @@ namespace ams::ldr { MetaFlag_PreventCodeReads = (1 << 7), }; + enum MetaFlag2 { + MetaFlag2_EnableShadowStack = (1 << 0), + }; + enum AddressSpaceType { AddressSpaceType_32Bit = 0, AddressSpaceType_64BitDeprecated = 1, AddressSpaceType_32BitWithoutAlias = 2, AddressSpaceType_64Bit = 3, + AddressSpaceType_64Bit64KPage = 4, }; #if defined(ATMOSPHERE_OS_HORIZON) @@ -247,13 +252,14 @@ namespace ams::ldr { static_assert(AddressSpaceType_64BitDeprecated == (svc::CreateProcessFlag_AddressSpace64BitDeprecated >> svc::CreateProcessFlag_AddressSpaceShift)); static_assert(AddressSpaceType_32BitWithoutAlias == (svc::CreateProcessFlag_AddressSpace32BitWithoutAlias >> svc::CreateProcessFlag_AddressSpaceShift)); static_assert(AddressSpaceType_64Bit == (svc::CreateProcessFlag_AddressSpace64Bit >> svc::CreateProcessFlag_AddressSpaceShift)); + static_assert(AddressSpaceType_64Bit64KPage == (svc::CreateProcessFlag_AddressSpace64Bit64KPage >> svc::CreateProcessFlag_AddressSpaceShift)); #endif u32 magic; u32 signature_key_generation; u8 reserved_08[4]; u8 flags; - u8 reserved_0D; + u8 flags2; u8 main_thread_priority; u8 default_cpu_id; u8 reserved_10[4]; diff --git a/libraries/libstratosphere/source/cfg/cfg_override.board.nintendo_nx.inc b/libraries/libstratosphere/source/cfg/cfg_override.board.nintendo_nx.inc index a91da9268..420f71198 100644 --- a/libraries/libstratosphere/source/cfg/cfg_override.board.nintendo_nx.inc +++ b/libraries/libstratosphere/source/cfg/cfg_override.board.nintendo_nx.inc @@ -153,6 +153,8 @@ namespace ams::cfg { impl::OverrideStatusFlag ParseOverrideAddressSpace(const char *value) { if (strcasecmp(value, "39_bit") == 0 || strcasecmp(value, "39") == 0) { return impl::OverrideStatusFlag_AddressSpace64Bit; + } else if (strcasecmp(value, "42_bit") == 0 || strcasecmp(value, "42") == 0) { + return impl::OverrideStatusFlag_AddressSpace64Bit64KPage; } else if (strcasecmp(value, "36_bit") == 0 || strcasecmp(value, "36") == 0) { return impl::OverrideStatusFlag_AddressSpace64BitDeprecated; } else if (strcasecmp(value, "32_bit") == 0 || strcasecmp(value, "32") == 0) { diff --git a/libraries/libstratosphere/source/osdbg/impl/osdbg_thread_info.os.horizon.hpp b/libraries/libstratosphere/source/osdbg/impl/osdbg_thread_info.os.horizon.hpp index e43fec1e1..1bd74bfba 100644 --- a/libraries/libstratosphere/source/osdbg/impl/osdbg_thread_info.os.horizon.hpp +++ b/libraries/libstratosphere/source/osdbg/impl/osdbg_thread_info.os.horizon.hpp @@ -28,7 +28,9 @@ namespace ams::osdbg::impl { constexpr inline bool IsLp64(const ThreadInfo *info) { const auto as = info->_debug_info_create_process.flags & svc::CreateProcessFlag_AddressSpaceMask; - return as == svc::CreateProcessFlag_AddressSpace64Bit || as == svc::CreateProcessFlag_AddressSpace64BitDeprecated; + return as == svc::CreateProcessFlag_AddressSpace64Bit + || as == svc::CreateProcessFlag_AddressSpace64BitDeprecated + || as == svc::CreateProcessFlag_AddressSpace64Bit64KPage; } constexpr inline bool Is64BitArch(const ThreadInfo *info) { diff --git a/libraries/libvapours/include/vapours/svc/svc_memory_map.hpp b/libraries/libvapours/include/vapours/svc/svc_memory_map.hpp index 08bf1773b..55bb5ec36 100644 --- a/libraries/libvapours/include/vapours/svc/svc_memory_map.hpp +++ b/libraries/libvapours/include/vapours/svc/svc_memory_map.hpp @@ -37,6 +37,13 @@ namespace ams::svc { constexpr inline size_t AddressMemoryRegion39Size = 512_GB; + constexpr inline size_t AddressMemoryRegionSmall42Size = 64_GB; + constexpr inline size_t AddressMemoryRegionAlias42Size = 512_GB; + constexpr inline size_t AddressMemoryRegionStack42Size = 2_GB; + + constexpr inline size_t AddressMemoryRegion42Size = 4096_GB; + + constexpr inline size_t AddressShadowStackRegionSize = 4_GB; #elif defined(ATMOSPHERE_ARCH_ARM) constexpr inline size_t AddressMemoryRegionSmall32Size = 512_MB; @@ -56,6 +63,12 @@ namespace ams::svc { constexpr inline size_t AddressMemoryRegion39Size = 0; + constexpr inline size_t AddressMemoryRegionSmall42Size = 0; + constexpr inline size_t AddressMemoryRegionAlias42Size = 0; + constexpr inline size_t AddressMemoryRegionStack42Size = 0; + + constexpr inline size_t AddressMemoryRegion42Size = 0; + #else #error "Unknown architecture for svc::AddressMemoryRegion*Size" @@ -97,4 +110,7 @@ namespace ams::svc { constexpr inline uintptr_t AddressMap39End = AddressMemoryRegion39Size; constexpr inline size_t AddressMap39Size = AddressMap39End - AddressMap39Start; + constexpr inline uintptr_t AddressMap42Start = 0 + AddressNullGuard64Size; + constexpr inline uintptr_t AddressMap42End = AddressMemoryRegion42Size; + constexpr inline size_t AddressMap42Size = AddressMap42End - AddressMap42Start; } diff --git a/libraries/libvapours/include/vapours/svc/svc_types_common.hpp b/libraries/libvapours/include/vapours/svc/svc_types_common.hpp index 21ab685d0..20aa4ea90 100644 --- a/libraries/libvapours/include/vapours/svc/svc_types_common.hpp +++ b/libraries/libvapours/include/vapours/svc/svc_types_common.hpp @@ -191,8 +191,16 @@ namespace ams::svc { InfoType_IsSvcPermitted = 26, InfoType_IoRegionHint = 27, InfoType_AliasRegionExtraSize = 28, - /* ... */ + InfoType_RemoteRegionAddress = 29, + InfoType_RemoteRegionSize = 30, + InfoType_RemoteMemorySize = 31, + InfoType_RemoteMemoryUsageMax = 32, + InfoType_AllocateAlignment = 33, InfoType_TransferMemoryHint = 34, + /* ... */ + InfoType_AddressSpaceSize = 36, + InfoType_ShadowStackRegionAddress = 37, + InfoType_ShadowStackRegionSize = 38, InfoType_MesosphereMeta = 65000, InfoType_MesosphereCurrentProcess = 65001, @@ -408,11 +416,12 @@ namespace ams::svc { /* What kind of address space? */ CreateProcessFlag_AddressSpaceShift = 1, - CreateProcessFlag_AddressSpaceMask = (7 << CreateProcessFlag_AddressSpaceShift), + CreateProcessFlag_AddressSpaceMask = (7 << CreateProcessFlag_AddressSpaceShift), /* Should be 15 but Nintendo didn't make 64K isn't usable yet */ CreateProcessFlag_AddressSpace32Bit = (0 << CreateProcessFlag_AddressSpaceShift), CreateProcessFlag_AddressSpace64BitDeprecated = (1 << CreateProcessFlag_AddressSpaceShift), CreateProcessFlag_AddressSpace32BitWithoutAlias = (2 << CreateProcessFlag_AddressSpaceShift), CreateProcessFlag_AddressSpace64Bit = (3 << CreateProcessFlag_AddressSpaceShift), + CreateProcessFlag_AddressSpace64Bit64KPage = (4 << CreateProcessFlag_AddressSpaceShift), /* Should JIT debug be done on crash? */ CreateProcessFlag_EnableDebug = (1 << 4), @@ -443,6 +452,9 @@ namespace ams::svc { /* 18.x EnableAliasRegionExtraSize. */ CreateProcessFlag_EnableAliasRegionExtraSize = (1 << 13), + /* 23.x EnableShadowStack. */ + CreateProcessFlag_EnableShadowStack = (1 << 17), + /* Mask of all flags. */ CreateProcessFlag_All = CreateProcessFlag_Is64Bit | CreateProcessFlag_AddressSpaceMask | @@ -452,7 +464,8 @@ namespace ams::svc { CreateProcessFlag_PoolPartitionMask | CreateProcessFlag_OptimizeMemoryAllocation | CreateProcessFlag_DisableDeviceAddressSpaceMerge | - CreateProcessFlag_EnableAliasRegionExtraSize, + CreateProcessFlag_EnableAliasRegionExtraSize | + CreateProcessFlag_EnableShadowStack, }; /* Debug types. */ diff --git a/libraries/libvapours/include/vapours/svc/svc_version.hpp b/libraries/libvapours/include/vapours/svc/svc_version.hpp index 500da0e21..e8c2b3ae8 100644 --- a/libraries/libvapours/include/vapours/svc/svc_version.hpp +++ b/libraries/libvapours/include/vapours/svc/svc_version.hpp @@ -57,7 +57,7 @@ namespace ams::svc { /* This is the highest SVC version supported by Atmosphere, to be updated on new kernel releases. */ /* NOTE: Official kernel versions have SVC major = SDK major + 4, SVC minor = SDK minor. */ - constexpr inline u32 SupportedKernelMajorVersion = ConvertToSvcMajorVersion(22); + constexpr inline u32 SupportedKernelMajorVersion = ConvertToSvcMajorVersion(23); constexpr inline u32 SupportedKernelMinorVersion = ConvertToSvcMinorVersion( 2); constexpr inline u32 SupportedKernelVersion = EncodeKernelVersion(SupportedKernelMajorVersion, SupportedKernelMinorVersion); diff --git a/mesosphere/kernel/source/arch/arm64/init/kern_init_core.cpp b/mesosphere/kernel/source/arch/arm64/init/kern_init_core.cpp index 10a000c6d..415b5bca2 100644 --- a/mesosphere/kernel/source/arch/arm64/init/kern_init_core.cpp +++ b/mesosphere/kernel/source/arch/arm64/init/kern_init_core.cpp @@ -224,15 +224,20 @@ namespace ams::kern::init { static_assert(kern::arch::arm64::init::IsInitialPageAllocator); void SetupAllTtbr0Entries(KInitialPageTable &init_pt, KInitialPageAllocator &allocator) { - /* Validate that the ttbr0 array is in rodata. */ + /* Validate that the ttbr0/tcr_el1 arrays are in rodata. */ const uintptr_t rodata_start = reinterpret_cast(__rodata_start); const uintptr_t rodata_end = reinterpret_cast(__rodata_end); MESOSPHERE_INIT_ABORT_UNLESS(rodata_start < rodata_end); MESOSPHERE_INIT_ABORT_UNLESS(rodata_start <= reinterpret_cast(std::addressof(KPageTable::GetTtbr0Entry(0)))); - MESOSPHERE_INIT_ABORT_UNLESS(reinterpret_cast(std::addressof(KPageTable::GetTtbr0Entry(KPageTable::NumTtbr0Entries))) < rodata_end); + MESOSPHERE_INIT_ABORT_UNLESS(reinterpret_cast(std::addressof(KPageTable::GetTtbr0Entry(KPageTable::NumPTEntries))) < rodata_end); + MESOSPHERE_INIT_ABORT_UNLESS(rodata_start <= reinterpret_cast(std::addressof(KPageTable::GetTcrEL1Entry(0)))); + MESOSPHERE_INIT_ABORT_UNLESS(reinterpret_cast(std::addressof(KPageTable::GetTcrEL1Entry(KPageTable::NumPTEntries))) < rodata_end); + + /* Get the default tcr_el1 value, with T0SZ set for a 39-bit address space. */ + const u64 tcr_el1 = (cpu::GetTcrEl1() & ~UINT64_C(0x3F)) | UINT64_C(64 - 39); /* Allocate pages for all ttbr0 entries. */ - for (size_t i = 0; i < KPageTable::NumTtbr0Entries; ++i) { + for (size_t i = 0; i < KPageTable::NumPTEntries; ++i) { /* Allocate a page. */ KPhysicalAddress page = allocator.Allocate(PageSize); MESOSPHERE_INIT_ABORT_UNLESS(page != Null); @@ -245,6 +250,12 @@ namespace ams::kern::init { /* Set the entry to the newly allocated page. */ *reinterpret_cast(GetInteger(ttbr0_phys_ptr)) = (static_cast(i) << 48) | GetInteger(page); + + /* Get the physical address of the tcr_el1 entry. */ + const auto tcr_el1_phys_ptr = init_pt.GetPhysicalAddress(KVirtualAddress(std::addressof(KPageTable::GetTcrEL1Entry(i)))); + + /* Set the entry to the default tcr_el1 value. */ + *reinterpret_cast(GetInteger(tcr_el1_phys_ptr)) = tcr_el1; } } diff --git a/stratosphere/loader/source/ldr_meta.cpp b/stratosphere/loader/source/ldr_meta.cpp index d6b6d7852..f7da96292 100644 --- a/stratosphere/loader/source/ldr_meta.cpp +++ b/stratosphere/loader/source/ldr_meta.cpp @@ -270,6 +270,7 @@ namespace ams::ldr { case cfg::impl::OverrideStatusFlag_AddressSpace64BitDeprecated: meta->npdm->flags |= (Npdm::AddressSpaceType_64BitDeprecated) << Npdm::MetaFlag_AddressSpaceTypeShift; break; case cfg::impl::OverrideStatusFlag_AddressSpace32BitWithoutAlias: meta->npdm->flags |= (Npdm::AddressSpaceType_32BitWithoutAlias) << Npdm::MetaFlag_AddressSpaceTypeShift; break; case cfg::impl::OverrideStatusFlag_AddressSpace64Bit: meta->npdm->flags |= (Npdm::AddressSpaceType_64Bit) << Npdm::MetaFlag_AddressSpaceTypeShift; break; + case cfg::impl::OverrideStatusFlag_AddressSpace64Bit64KPage: meta->npdm->flags |= (Npdm::AddressSpaceType_64Bit64KPage) << Npdm::MetaFlag_AddressSpaceTypeShift; break; AMS_UNREACHABLE_DEFAULT_CASE(); } } diff --git a/stratosphere/loader/source/ldr_process_creation.cpp b/stratosphere/loader/source/ldr_process_creation.cpp index bea773f44..d05450541 100644 --- a/stratosphere/loader/source/ldr_process_creation.cpp +++ b/stratosphere/loader/source/ldr_process_creation.cpp @@ -423,6 +423,9 @@ namespace ams::ldr { case Npdm::AddressSpaceType_64Bit: flags |= svc::CreateProcessFlag_AddressSpace64Bit; break; + case Npdm::AddressSpaceType_64Bit64KPage: + flags |= svc::CreateProcessFlag_AddressSpace64Bit64KPage; + break; default: R_THROW(ldr::ResultInvalidMeta()); } @@ -597,6 +600,10 @@ namespace ams::ldr { aslr_start = svc::AddressMap39Start; aslr_size = svc::AddressMap39Size; break; + case svc::CreateProcessFlag_AddressSpace64Bit64KPage: + aslr_start = svc::AddressMap42Start; + aslr_size = svc::AddressMap42Size; + break; AMS_UNREACHABLE_DEFAULT_CASE(); } } else {