From 7e58f5fbae70971d5f84df61122ef3983345288f Mon Sep 17 00:00:00 2001 From: Alula Date: Tue, 15 Sep 2026 17:03:11 +0200 Subject: [PATCH] kern: finish shadow stack region, 64k page process segregation implementation, fix some long-standing issues --- .../arch/arm64/kern_k_page_table.hpp | 1 + .../arch/arm64/kern_k_process_page_table.hpp | 9 + .../arm64/kern_userspace_memory_access.hpp | 2 +- .../mesosphere/kern_k_page_table_base.hpp | 10 +- .../source/kern_k_page_table_base.cpp | 247 +++++------------- .../source/kern_k_system_control_base.cpp | 7 + .../source/svc/kern_svc_process.cpp | 38 ++- .../include/vapours/svc/svc_types_common.hpp | 4 + .../source/arch/arm64/init/kern_init_core.cpp | 2 +- 9 files changed, 132 insertions(+), 188 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 356dc4217..9fd7dbd2f 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 @@ -19,6 +19,7 @@ #include #include #include +#include namespace ams::kern::arch::arm64 { 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 63a357e0e..e80311a47 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 @@ -32,6 +32,11 @@ namespace ams::kern::arch::arm64 { R_RETURN(m_page_table.InitializeForProcess(flags, from_back, pool, code_address, code_size, system_resource, resource_limit, process_index)); } + static ALWAYS_INLINE u64 GetProcessTcrEl1(size_t process_index) { + /* The kernel's root table is entry zero; processes are indexed from one. */ + return KPageTable::GetTcrEL1Entry(process_index + 1); + } + void Finalize() { m_page_table.Finalize(); } ALWAYS_INLINE KScopedLightLock AcquireDeviceMapLock() { @@ -302,6 +307,10 @@ 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); } + bool IsInShadowStackRegion(KProcessAddress addr, size_t size) const { return m_page_table.IsInShadowStackRegion(addr, size); } + bool IsInShadowStackRegion(KProcessAddress addr) const { return m_page_table.IsInShadowStackRegion(addr); } + bool IsSafeUserPointer(KProcessAddress addr, size_t size) const { return m_page_table.IsSafeUserPointer(addr, size); } + KProcessAddress GetAddressSpaceStart() const { return m_page_table.GetAddressSpaceStart(); } KProcessAddress GetShadowStackRegionStart() const { return m_page_table.GetShadowStackRegionStart(); } KProcessAddress GetHeapRegionStart() const { return m_page_table.GetHeapRegionStart(); } diff --git a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_userspace_memory_access.hpp b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_userspace_memory_access.hpp index fc075178b..28580e038 100644 --- a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_userspace_memory_access.hpp +++ b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_userspace_memory_access.hpp @@ -77,7 +77,7 @@ namespace ams::kern::arch::arm64 { static bool CopyMemoryFromUserSize32BitWithSupervisorAccess(void *dst, const void *src) { /* Check that the address is within the valid userspace range. */ - if (const uintptr_t src_uptr = reinterpret_cast(src); src_uptr < ams::svc::AddressNullGuard32Size || (src_uptr + sizeof(u32) - 1) >= ams::svc::AddressMemoryRegion39Size) { + if (const uintptr_t src_uptr = reinterpret_cast(src); src_uptr < ams::svc::AddressNullGuard32Size || (src_uptr + sizeof(u32) - 1) >= ams::svc::AddressMemoryRegion42Size) { return false; } 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 759fd1758..c0139ab79 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp @@ -249,7 +249,15 @@ namespace ams::kern { } 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; + const auto start = m_region_starts[RegionType_ShadowStack]; + const auto end = m_region_ends[RegionType_ShadowStack]; + return start != end && addr < end && start < addr + size; + } + + constexpr bool IsInShadowStackRegion(KProcessAddress addr) const { + const auto start = m_region_starts[RegionType_ShadowStack]; + const auto end = m_region_ends[RegionType_ShadowStack]; + return start <= addr && addr < end; } constexpr bool IsSafeUserPointer(KProcessAddress addr, size_t size) const { diff --git a/libraries/libmesosphere/source/kern_k_page_table_base.cpp b/libraries/libmesosphere/source/kern_k_page_table_base.cpp index 98988dde6..652583fd4 100644 --- a/libraries/libmesosphere/source/kern_k_page_table_base.cpp +++ b/libraries/libmesosphere/source/kern_k_page_table_base.cpp @@ -353,182 +353,36 @@ namespace ams::kern { const KProcessAddress process_code_last = process_code_end - 1; auto IsInAddressSpace = [&](KProcessAddress addr) ALWAYS_INLINE_LAMBDA { return m_address_space_start <= addr && addr <= m_address_space_end; }; - /* Ensure that the KernelMap region is valid. */ - for (size_t k = 0; k < num_regions; ++k) { - if (const auto &kmap_region = region_layouts[k]; kmap_region.type == RegionType_KernelMap) { - /* If there's no kmap region, we have nothing to check. */ - if (kmap_region.size == 0) { - break; - } - - /* Check that the kmap region is within our address space. */ - MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_starts[RegionType_KernelMap])); - MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_ends[RegionType_KernelMap])); - - /* Check for overlap with process code. */ - const KProcessAddress kmap_start = m_region_starts[RegionType_KernelMap]; - const KProcessAddress kmap_last = m_region_ends[RegionType_KernelMap] - 1; - MESOSPHERE_ABORT_UNLESS(kernel_map_region_size == 0 || kmap_last < process_code_start || process_code_last < kmap_start); - - /* Check for overlap with stack. */ - for (size_t s = 0; s < num_regions; ++s) { - if (const auto &stack_region = region_layouts[s]; stack_region.type == RegionType_Stack) { - if (stack_region.size != 0) { - const KProcessAddress stack_start = m_region_starts[RegionType_Stack]; - const KProcessAddress stack_last = m_region_ends[RegionType_Stack] - 1; - MESOSPHERE_ABORT_UNLESS((kernel_map_region_size == 0 && stack_region_size == 0) || kmap_last < stack_start || stack_last < kmap_start); - } - break; - } - } - - /* Check for overlap with alias. */ - for (size_t a = 0; a < num_regions; ++a) { - if (const auto &alias_region = region_layouts[a]; alias_region.type == RegionType_Alias) { - if (alias_region.size != 0) { - const KProcessAddress alias_start = m_region_starts[RegionType_Alias]; - const KProcessAddress alias_last = m_region_ends[RegionType_Alias] - 1; - MESOSPHERE_ABORT_UNLESS(kmap_last < alias_start || alias_last < kmap_start); - } - break; - } - } - - /* Check for overlap with heap. */ - for (size_t h = 0; h < num_regions; ++h) { - if (const auto &heap_region = region_layouts[h]; heap_region.type == RegionType_Heap) { - if (heap_region.size != 0) { - const KProcessAddress heap_start = m_region_starts[RegionType_Heap]; - const KProcessAddress heap_last = m_region_ends[RegionType_Heap] - 1; - MESOSPHERE_ABORT_UNLESS(kmap_last < heap_start || heap_last < kmap_start); - } - 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; - } - } - } + /* Map each region type to its layout entry. */ + const RegionLayoutInfo *region_layouts_by_type[RegionType_Count] = {}; + for (size_t i = 0; i < num_regions; ++i) { + region_layouts_by_type[region_layouts[i].type] = std::addressof(region_layouts[i]); } - /* Check that the Stack region is valid. */ - for (size_t s = 0; s < num_regions; ++s) { - if (const auto &stack_region = region_layouts[s]; stack_region.type == RegionType_Stack) { - /* If there's no stack region, we have nothing to check. */ - if (stack_region.size == 0) { - break; - } - - /* Check that the stack region is within our address space. */ - MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_starts[RegionType_Stack])); - MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_ends[RegionType_Stack])); - - /* Check for overlap with process code. */ - const KProcessAddress stack_start = m_region_starts[RegionType_Stack]; - const KProcessAddress stack_last = m_region_ends[RegionType_Stack] - 1; - MESOSPHERE_ABORT_UNLESS(stack_region_size == 0 || stack_last < process_code_start || process_code_last < stack_start); - - /* Check for overlap with alias. */ - for (size_t a = 0; a < num_regions; ++a) { - if (const auto &alias_region = region_layouts[a]; alias_region.type == RegionType_Alias) { - if (alias_region.size != 0) { - const KProcessAddress alias_start = m_region_starts[RegionType_Alias]; - const KProcessAddress alias_last = m_region_ends[RegionType_Alias] - 1; - MESOSPHERE_ABORT_UNLESS(stack_last < alias_start || alias_last < stack_start); - } - break; - } - } - - /* Check for overlap with heap. */ - for (size_t h = 0; h < num_regions; ++h) { - if (const auto &heap_region = region_layouts[h]; heap_region.type == RegionType_Heap) { - if (heap_region.size != 0) { - const KProcessAddress heap_start = m_region_starts[RegionType_Heap]; - const KProcessAddress heap_last = m_region_ends[RegionType_Heap] - 1; - MESOSPHERE_ABORT_UNLESS(stack_last < heap_start || heap_last < stack_start); - } - break; - } - } + /* Validate each region. */ + for (size_t i = 0; i < RegionType_Count; ++i) { + /* If the region isn't present, there's nothing to check. */ + const RegionLayoutInfo * const region = region_layouts_by_type[i]; + if (region == nullptr || region->size == 0) { + continue; } - } - /* Check that the Alias region is valid. */ - for (size_t a = 0; a < num_regions; ++a) { - if (const auto &alias_region = region_layouts[a]; alias_region.type == RegionType_Alias) { - /* If there's no alias region, we have nothing to check. */ - if (alias_region.size == 0) { - break; + /* Check that the region is within our address space. */ + MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_starts[i])); + MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_ends[i])); + + /* Check for overlap with process code. */ + MESOSPHERE_ABORT_UNLESS(m_region_ends[i] - 1 < process_code_start || process_code_last < m_region_starts[i]); + + /* Check for overlap with every later region. */ + for (size_t j = i; j < RegionType_ShadowStack; ++j) { + /* If the other region isn't present, there's nothing to check. */ + const RegionLayoutInfo * const other = region_layouts_by_type[j + 1]; + if (other == nullptr || other->size == 0) { + continue; } - /* Check that the alias region is within our address space. */ - MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_starts[RegionType_Alias])); - MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_ends[RegionType_Alias])); - - /* Check for overlap with process code. */ - const KProcessAddress alias_start = m_region_starts[RegionType_Alias]; - const KProcessAddress alias_last = m_region_ends[RegionType_Alias] - 1; - MESOSPHERE_ABORT_UNLESS(alias_last < process_code_start || process_code_last < alias_start); - - /* Check for overlap with heap. */ - for (size_t h = 0; h < num_regions; ++h) { - if (const auto &heap_region = region_layouts[h]; heap_region.type == RegionType_Heap) { - if (heap_region.size != 0) { - const KProcessAddress heap_start = m_region_starts[RegionType_Heap]; - const KProcessAddress heap_last = m_region_ends[RegionType_Heap] - 1; - MESOSPHERE_ABORT_UNLESS(alias_last < heap_start || heap_last < alias_start); - } - break; - } - } - } - } - - /* Check that the Heap region is valid. */ - for (size_t h = 0; h < num_regions; ++h) { - if (const auto &heap_region = region_layouts[h]; heap_region.type == RegionType_Heap) { - /* If there's no heap region, we have nothing to check. */ - if (heap_region.size == 0) { - break; - } - - /* Check that the heap region is within our address space. */ - MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_starts[RegionType_Heap])); - MESOSPHERE_ABORT_UNLESS(IsInAddressSpace(m_region_ends[RegionType_Heap])); - - /* Check for overlap with process code. */ - const KProcessAddress heap_start = m_region_starts[RegionType_Heap]; - const KProcessAddress heap_last = m_region_ends[RegionType_Heap] - 1; - 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); + MESOSPHERE_ABORT_UNLESS(m_region_ends[i] - 1 < m_region_starts[j + 1] || m_region_ends[j + 1] - 1 < m_region_starts[i]); } } } @@ -598,6 +452,8 @@ namespace ams::kern { case ams::svc::MemoryState_Static: case ams::svc::MemoryState_ThreadLocal: return m_region_starts[RegionType_KernelMap]; + case ams::svc::MemoryState_ShadowStack: + return m_region_starts[RegionType_ShadowStack]; case ams::svc::MemoryState_Io: case ams::svc::MemoryState_Shared: case ams::svc::MemoryState_AliasCode: @@ -633,6 +489,8 @@ namespace ams::kern { case ams::svc::MemoryState_Static: case ams::svc::MemoryState_ThreadLocal: return m_region_ends[RegionType_KernelMap] - m_region_starts[RegionType_KernelMap]; + case ams::svc::MemoryState_ShadowStack: + return m_region_ends[RegionType_ShadowStack] - m_region_starts[RegionType_ShadowStack]; case ams::svc::MemoryState_Io: case ams::svc::MemoryState_Shared: case ams::svc::MemoryState_AliasCode: @@ -659,12 +517,20 @@ namespace ams::kern { const KProcessAddress region_start = this->GetRegionAddress(state); const size_t region_size = this->GetRegionSize(state); + if (region_size == 0) { + return false; + } + const bool is_in_region = region_start <= addr && addr < end && last <= region_start + region_size - 1; - const bool is_in_heap = !(end <= m_region_starts[RegionType_Heap] || m_region_ends[RegionType_Heap] <= addr || m_region_starts[RegionType_Heap] == m_region_ends[RegionType_Heap]); - const bool is_in_alias = !(end <= m_region_starts[RegionType_Alias] || m_region_ends[RegionType_Alias] <= addr || m_region_starts[RegionType_Alias] == m_region_ends[RegionType_Alias]); + switch (state) { case ams::svc::MemoryState_Free: + case ams::svc::MemoryState_Normal: + case ams::svc::MemoryState_Ipc: + case ams::svc::MemoryState_NonSecureIpc: + case ams::svc::MemoryState_NonDeviceIpc: case ams::svc::MemoryState_Kernel: + case ams::svc::MemoryState_ShadowStack: return is_in_region; case ams::svc::MemoryState_Io: case ams::svc::MemoryState_Static: @@ -682,17 +548,32 @@ namespace ams::kern { case ams::svc::MemoryState_CodeOut: case ams::svc::MemoryState_Coverage: case ams::svc::MemoryState_Insecure: - return is_in_region && !is_in_heap && !is_in_alias; - case ams::svc::MemoryState_Normal: - MESOSPHERE_ASSERT(is_in_heap); - return is_in_region && !is_in_alias; - case ams::svc::MemoryState_Ipc: - case ams::svc::MemoryState_NonSecureIpc: - case ams::svc::MemoryState_NonDeviceIpc: - MESOSPHERE_ASSERT(is_in_alias); - return is_in_region && !is_in_heap; - default: - return false; + { + if (!is_in_region) { + return false; + } + + const auto heap_start = m_region_starts[RegionType_Heap]; + const auto heap_end = m_region_ends[RegionType_Heap]; + if (heap_start != heap_end && addr < heap_end && heap_start < end) { + return false; + } + + const auto alias_start = m_region_starts[RegionType_Alias]; + const auto alias_end = m_region_ends[RegionType_Alias]; + if (alias_start != alias_end && addr < alias_end && alias_start < end) { + return false; + } + + const auto shadow_start = m_region_starts[RegionType_ShadowStack]; + const auto shadow_end = m_region_ends[RegionType_ShadowStack]; + if (shadow_start != shadow_end && addr < shadow_end && shadow_start < end) { + return false; + } + + return true; + } + MESOSPHERE_UNREACHABLE_DEFAULT_CASE(); } } diff --git a/libraries/libmesosphere/source/kern_k_system_control_base.cpp b/libraries/libmesosphere/source/kern_k_system_control_base.cpp index dece074ef..38c507486 100644 --- a/libraries/libmesosphere/source/kern_k_system_control_base.cpp +++ b/libraries/libmesosphere/source/kern_k_system_control_base.cpp @@ -170,6 +170,13 @@ namespace ams::kern { KAddressSpaceInfo::SetAddressSpaceSize(39, KAddressSpaceInfo::Type_Alias, alias_size); } + /* Update 42-bit address space infos. */ + { + /* Heap should be equal to the total memory size, maximum 128 GB. */ + /* Alias/Stack/MapSmall are left at their static defaults. */ + KAddressSpaceInfo::SetAddressSpaceSize(42, KAddressSpaceInfo::Type_Heap, std::min(util::AlignUp(total_memory_size, 1_GB), 128_GB)); + } + const auto &slab_counts = init::GetSlabResourceCounts(); MESOSPHERE_R_ABORT_UNLESS(sys_res_limit.SetLimitValue(ams::svc::LimitableResource_PhysicalMemoryMax, total_memory_size)); MESOSPHERE_R_ABORT_UNLESS(sys_res_limit.SetLimitValue(ams::svc::LimitableResource_ThreadCountMax, slab_counts.num_KThread)); diff --git a/libraries/libmesosphere/source/svc/kern_svc_process.cpp b/libraries/libmesosphere/source/svc/kern_svc_process.cpp index 54f598d1e..375386562 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_process.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_process.cpp @@ -86,6 +86,40 @@ namespace ams::kern::svc { R_RETURN(KProcess::GetProcessList(out_num_processes, out_process_ids, max_out_count)); } + constexpr size_t GetProcessSlotT0Sz(ams::svc::CreateProcessFlag flags) { + if ((flags & ams::svc::CreateProcessFlag_AddressSpaceMask) == ams::svc::CreateProcessFlag_AddressSpace64Bit64KPage) { + return (64 - 42); + } else { + return (64 - 39); + } + } + + KProcess *CreateProcessForAddressSpace(ams::svc::CreateProcessFlag flags) { + /* Find a process slab slot whose root page table is meant for the requested address space. */ + const size_t desired_t0sz = GetProcessSlotT0Sz(flags); + + KProcess *process = nullptr; + KProcess *rejected[init::SlabCountKProcess]; + size_t num_rejected = 0; + while ((process = KProcess::Create()) != nullptr) { + /* Stop once we find a slot whose T0SZ matches. */ + if ((KProcessPageTable::GetProcessTcrEl1(process->GetSlabIndex()) & 0x3F) == desired_t0sz) { + break; + } + + /* Otherwise, park the process and try the next slot. */ + rejected[num_rejected++] = process; + process = nullptr; + } + + /* Release every process we parked while searching. */ + for (size_t i = 0; i < num_rejected; ++i) { + rejected[i]->Close(); + } + + return process; + } + Result CreateProcess(ams::svc::Handle *out, const ams::svc::CreateProcessParameter ¶ms, KUserPointer user_caps, int32_t num_caps) { /* Validate the capabilities pointer. */ R_UNLESS(num_caps >= 0, svc::ResultInvalidPointer()); @@ -219,8 +253,8 @@ namespace ams::kern::svc { /* Get the current handle table. */ auto &handle_table = GetCurrentProcess().GetHandleTable(); - /* Create the new process. */ - KProcess *process = KProcess::Create(); + /* Create the new process, ensuring its page table slot matches the requested address space. */ + KProcess *process = CreateProcessForAddressSpace(static_cast(params.flags)); R_UNLESS(process != nullptr, svc::ResultOutOfResource()); /* Ensure that the only reference to the process is in the handle table when we're done. */ diff --git a/libraries/libvapours/include/vapours/svc/svc_types_common.hpp b/libraries/libvapours/include/vapours/svc/svc_types_common.hpp index 20aa4ea90..66f5a5648 100644 --- a/libraries/libvapours/include/vapours/svc/svc_types_common.hpp +++ b/libraries/libvapours/include/vapours/svc/svc_types_common.hpp @@ -96,6 +96,9 @@ namespace ams::svc { MemoryState_CodeOut = 0x15, MemoryState_Coverage = 0x16, MemoryState_Insecure = 0x17, + MemoryState_Remote = 0x18, + MemoryState_Protected = 0x19, + MemoryState_ShadowStack = 0x1A, }; enum MemoryPermission : u32 { @@ -483,6 +486,7 @@ namespace ams::svc { DebugThreadParam_IdealCore = 2, DebugThreadParam_CurrentCore = 3, DebugThreadParam_AffinityMask = 4, + DebugThreadParam_Unknown5 = 5, }; enum DebugException : u32 { 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 415b5bca2..e37780b7e 100644 --- a/mesosphere/kernel/source/arch/arm64/init/kern_init_core.cpp +++ b/mesosphere/kernel/source/arch/arm64/init/kern_init_core.cpp @@ -234,7 +234,7 @@ namespace ams::kern::init { 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); + const u64 tcr_el1 = (cpu::GetTcrEl1() & ~UINT64_C(0x3F)) | (64 - 39); /* Allocate pages for all ttbr0 entries. */ for (size_t i = 0; i < KPageTable::NumPTEntries; ++i) {