diff --git a/libmesosphere/include/mesosphere/kern_k_memory_region_type.hpp b/libmesosphere/include/mesosphere/kern_k_memory_region_type.hpp index 5c77ed36..e80e246a 100644 --- a/libmesosphere/include/mesosphere/kern_k_memory_region_type.hpp +++ b/libmesosphere/include/mesosphere/kern_k_memory_region_type.hpp @@ -21,7 +21,8 @@ namespace ams::kern { enum KMemoryRegionType : u32 {}; enum KMemoryRegionAttr : typename std::underlying_type::type { - KMemoryRegionAttr_CarveoutProtected = 0x04000000, + KMemoryRegionAttr_CarveoutProtected = 0x02000000, + KMemoryRegionAttr_Uncached = 0x04000000, KMemoryRegionAttr_DidKernelMap = 0x08000000, KMemoryRegionAttr_ShouldKernelMap = 0x10000000, KMemoryRegionAttr_UserReadOnly = 0x20000000, @@ -216,6 +217,10 @@ namespace ams::kern { static_assert(KMemoryRegionType_VirtualDramKernelPtHeap .GetValue() == 0x2A); static_assert(KMemoryRegionType_VirtualDramKernelTraceBuffer.GetValue() == 0x4A); + /* UNUSED: .DeriveSparse(2, 2, 0); */ + constexpr inline const auto KMemoryRegionType_VirtualDramUnknownDebug = KMemoryRegionType_Dram.DeriveSparse(2, 2, 1); + static_assert(KMemoryRegionType_VirtualDramUnknownDebug.GetValue() == (0x52)); + constexpr inline const auto KMemoryRegionType_VirtualDramKernelInitPt = KMemoryRegionType_VirtualDramHeapBase.Derive(3, 0); constexpr inline const auto KMemoryRegionType_VirtualDramPoolManagement = KMemoryRegionType_VirtualDramHeapBase.Derive(3, 1); constexpr inline const auto KMemoryRegionType_VirtualDramUserPool = KMemoryRegionType_VirtualDramHeapBase.Derive(3, 2); @@ -292,6 +297,8 @@ namespace ams::kern { return KMemoryRegionType_VirtualDramKernelTraceBuffer; } else if (KMemoryRegionType_DramKernelPtHeap.IsAncestorOf(type_id)) { return KMemoryRegionType_VirtualDramKernelPtHeap; + } else if ((type_id | KMemoryRegionAttr_ShouldKernelMap) == type_id) { + return KMemoryRegionType_VirtualDramUnknownDebug; } else { return KMemoryRegionType_Dram; } diff --git a/libmesosphere/source/arch/arm64/kern_k_page_table.cpp b/libmesosphere/source/arch/arm64/kern_k_page_table.cpp index 53539e92..6df32849 100644 --- a/libmesosphere/source/arch/arm64/kern_k_page_table.cpp +++ b/libmesosphere/source/arch/arm64/kern_k_page_table.cpp @@ -556,13 +556,13 @@ namespace ams::kern::arch::arm64 { /* If we're not forcing an unmap, separate pages immediately. */ if (!force) { const size_t size = num_pages * PageSize; - R_TRY(this->SeparatePages(virt_addr, std::min(GetInteger(virt_addr) & -GetInteger(virt_addr), size), page_list, reuse_ll)); + R_TRY(this->SeparatePages(virt_addr, std::min(util::GetAlignment(GetInteger(virt_addr)), size), page_list, reuse_ll)); if (num_pages > 1) { const auto end_page = virt_addr + size; const auto last_page = end_page - PageSize; auto merge_guard = SCOPE_GUARD { this->MergePages(virt_addr, page_list); }; - R_TRY(this->SeparatePages(last_page, std::min(GetInteger(end_page) & -GetInteger(end_page), size), page_list, reuse_ll)); + R_TRY(this->SeparatePages(last_page, std::min(util::GetAlignment(GetInteger(end_page)), size), page_list, reuse_ll)); merge_guard.Cancel(); } } @@ -1194,13 +1194,13 @@ namespace ams::kern::arch::arm64 { /* Separate pages before we change permissions. */ const size_t size = num_pages * PageSize; - R_TRY(this->SeparatePages(virt_addr, std::min(GetInteger(virt_addr) & -GetInteger(virt_addr), size), page_list, reuse_ll)); + R_TRY(this->SeparatePages(virt_addr, std::min(util::GetAlignment(GetInteger(virt_addr)), size), page_list, reuse_ll)); if (num_pages > 1) { const auto end_page = virt_addr + size; const auto last_page = end_page - PageSize; auto merge_guard = SCOPE_GUARD { this->MergePages(virt_addr, page_list); }; - R_TRY(this->SeparatePages(last_page, std::min(GetInteger(end_page) & -GetInteger(end_page), size), page_list, reuse_ll)); + R_TRY(this->SeparatePages(last_page, std::min(util::GetAlignment(GetInteger(end_page)), size), page_list, reuse_ll)); merge_guard.Cancel(); } diff --git a/libmesosphere/source/kern_k_page_table_base.cpp b/libmesosphere/source/kern_k_page_table_base.cpp index 166cce17..3f2aff67 100644 --- a/libmesosphere/source/kern_k_page_table_base.cpp +++ b/libmesosphere/source/kern_k_page_table_base.cpp @@ -1810,7 +1810,7 @@ namespace ams::kern { /* Select an address to map at. */ KProcessAddress addr = Null; - const size_t phys_alignment = std::min(std::min(GetInteger(phys_addr) & -GetInteger(phys_addr), size & -size), MaxPhysicalMapAlignment); + const size_t phys_alignment = std::min(std::min(util::GetAlignment(GetInteger(phys_addr)), util::GetAlignment(size)), MaxPhysicalMapAlignment); for (s32 block_type = KPageTable::GetMaxBlockType(); block_type >= 0; block_type--) { const size_t alignment = KPageTable::GetBlockSize(static_cast(block_type)); if (alignment > phys_alignment) { @@ -1892,7 +1892,7 @@ namespace ams::kern { /* Select an address to map at. */ KProcessAddress addr = Null; - const size_t phys_alignment = std::min(std::min(GetInteger(phys_addr) & -GetInteger(phys_addr), size & -size), MaxPhysicalMapAlignment); + const size_t phys_alignment = std::min(std::min(util::GetAlignment(GetInteger(phys_addr)), util::GetAlignment(size)), MaxPhysicalMapAlignment); for (s32 block_type = KPageTable::GetMaxBlockType(); block_type >= 0; block_type--) { const size_t alignment = KPageTable::GetBlockSize(static_cast(block_type)); if (alignment > phys_alignment) { diff --git a/libvapours/include/vapours/util/util_alignment.hpp b/libvapours/include/vapours/util/util_alignment.hpp index 3fa95150..79e0ffd0 100644 --- a/libvapours/include/vapours/util/util_alignment.hpp +++ b/libvapours/include/vapours/util/util_alignment.hpp @@ -43,6 +43,11 @@ namespace ams::util { return (value & invmask) == 0; } + template requires std::unsigned_integral + constexpr ALWAYS_INLINE T GetAlignment(T value) { + return value & -value; + } + template<> constexpr ALWAYS_INLINE void *AlignUp(void *value, size_t alignment) { return reinterpret_cast(AlignUp(reinterpret_cast(value), alignment));