From ae2c25e9c80daf51115e4599aca1290c0e1177ce Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 11 Oct 2023 05:00:23 -0700 Subject: [PATCH] kern: update KMemoryState, remove bijection (separate IoRegister/IoMemory) --- .../arch/arm64/kern_k_process_page_table.hpp | 9 +- .../mesosphere/kern_k_memory_block.hpp | 61 +++--- .../mesosphere/kern_k_page_table_base.hpp | 28 +-- .../source/kern_k_debug_base.cpp | 8 +- .../source/kern_k_memory_block_manager.cpp | 3 +- .../source/kern_k_page_table_base.cpp | 185 +++++++++--------- .../source/svc/kern_svc_io_pool.cpp | 4 +- .../include/vapours/svc/svc_types_common.hpp | 9 +- 8 files changed, 163 insertions(+), 144 deletions(-) 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 0d074a6b2..135c6696e 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 @@ -154,16 +154,16 @@ namespace ams::kern::arch::arm64 { R_RETURN(m_page_table.ReadDebugMemory(buffer, address, size)); } - Result ReadDebugIoMemory(void *buffer, KProcessAddress address, size_t size) { - R_RETURN(m_page_table.ReadDebugIoMemory(buffer, address, size)); + Result ReadDebugIoMemory(void *buffer, KProcessAddress address, size_t size, KMemoryState state) { + R_RETURN(m_page_table.ReadDebugIoMemory(buffer, address, size, state)); } Result WriteDebugMemory(KProcessAddress address, const void *buffer, size_t size) { R_RETURN(m_page_table.WriteDebugMemory(address, buffer, size)); } - Result WriteDebugIoMemory(KProcessAddress address, const void *buffer, size_t size) { - R_RETURN(m_page_table.WriteDebugIoMemory(address, buffer, size)); + Result WriteDebugIoMemory(KProcessAddress address, const void *buffer, size_t size, KMemoryState state) { + R_RETURN(m_page_table.WriteDebugIoMemory(address, buffer, size, state)); } Result LockForMapDeviceAddressSpace(bool *out_is_io, KProcessAddress address, size_t size, KMemoryPermission perm, bool is_aligned, bool check_heap) { @@ -296,6 +296,7 @@ namespace ams::kern::arch::arm64 { bool IsInUnsafeAliasRegion(KProcessAddress addr, size_t size) const { return m_page_table.IsInUnsafeAliasRegion(addr, size); } 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(); } diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_memory_block.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_memory_block.hpp index faed32239..eacf909af 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_memory_block.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_memory_block.hpp @@ -44,6 +44,7 @@ namespace ams::kern { KMemoryState_FlagCanChangeAttribute = (1 << 24), KMemoryState_FlagCanCodeMemory = (1 << 25), KMemoryState_FlagLinearMapped = (1 << 26), + KMemoryState_FlagCanPermissionLock = (1 << 27), KMemoryState_FlagsData = KMemoryState_FlagCanReprotect | KMemoryState_FlagCanUseIpc | KMemoryState_FlagCanUseNonDeviceIpc | KMemoryState_FlagCanUseNonSecureIpc | @@ -66,18 +67,22 @@ namespace ams::kern { KMemoryState_Free = ams::svc::MemoryState_Free, - KMemoryState_Io = ams::svc::MemoryState_Io | KMemoryState_FlagMapped | KMemoryState_FlagCanDeviceMap | KMemoryState_FlagCanAlignedDeviceMap, - KMemoryState_Static = ams::svc::MemoryState_Static | KMemoryState_FlagMapped | KMemoryState_FlagCanQueryPhysical, + + KMemoryState_IoMemory = ams::svc::MemoryState_Io | KMemoryState_FlagMapped | KMemoryState_FlagCanDeviceMap | KMemoryState_FlagCanAlignedDeviceMap, + KMemoryState_IoRegister = ams::svc::MemoryState_Io | KMemoryState_FlagCanDeviceMap | KMemoryState_FlagCanAlignedDeviceMap, + + + KMemoryState_Static = ams::svc::MemoryState_Static | KMemoryState_FlagCanQueryPhysical, KMemoryState_Code = ams::svc::MemoryState_Code | KMemoryState_FlagsCode | KMemoryState_FlagCanMapProcess, - KMemoryState_CodeData = ams::svc::MemoryState_CodeData | KMemoryState_FlagsData | KMemoryState_FlagCanMapProcess | KMemoryState_FlagCanCodeMemory, + KMemoryState_CodeData = ams::svc::MemoryState_CodeData | KMemoryState_FlagsData | KMemoryState_FlagCanMapProcess | KMemoryState_FlagCanCodeMemory | KMemoryState_FlagCanPermissionLock, KMemoryState_Normal = ams::svc::MemoryState_Normal | KMemoryState_FlagsData | KMemoryState_FlagCanCodeMemory, KMemoryState_Shared = ams::svc::MemoryState_Shared | KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted | KMemoryState_FlagLinearMapped, /* KMemoryState_Alias was removed after 1.0.0. */ KMemoryState_AliasCode = ams::svc::MemoryState_AliasCode | KMemoryState_FlagsCode | KMemoryState_FlagCanMapProcess | KMemoryState_FlagCanCodeAlias, - KMemoryState_AliasCodeData = ams::svc::MemoryState_AliasCodeData | KMemoryState_FlagsData | KMemoryState_FlagCanMapProcess | KMemoryState_FlagCanCodeAlias | KMemoryState_FlagCanCodeMemory, - + KMemoryState_AliasCodeData = ams::svc::MemoryState_AliasCodeData | KMemoryState_FlagsData | KMemoryState_FlagCanMapProcess | KMemoryState_FlagCanCodeAlias | KMemoryState_FlagCanCodeMemory + | KMemoryState_FlagCanPermissionLock, KMemoryState_Ipc = ams::svc::MemoryState_Ipc | KMemoryState_FlagsMisc | KMemoryState_FlagCanAlignedDeviceMap | KMemoryState_FlagCanUseIpc | KMemoryState_FlagCanUseNonSecureIpc | KMemoryState_FlagCanUseNonDeviceIpc, @@ -85,7 +90,7 @@ namespace ams::kern { KMemoryState_Stack = ams::svc::MemoryState_Stack | KMemoryState_FlagsMisc | KMemoryState_FlagCanAlignedDeviceMap | KMemoryState_FlagCanUseIpc | KMemoryState_FlagCanUseNonSecureIpc | KMemoryState_FlagCanUseNonDeviceIpc, - KMemoryState_ThreadLocal = ams::svc::MemoryState_ThreadLocal | KMemoryState_FlagMapped | KMemoryState_FlagLinearMapped, + KMemoryState_ThreadLocal = ams::svc::MemoryState_ThreadLocal | KMemoryState_FlagLinearMapped, KMemoryState_Transfered = ams::svc::MemoryState_Transfered | KMemoryState_FlagsMisc | KMemoryState_FlagCanAlignedDeviceMap | KMemoryState_FlagCanChangeAttribute | KMemoryState_FlagCanUseIpc | KMemoryState_FlagCanUseNonSecureIpc | KMemoryState_FlagCanUseNonDeviceIpc, @@ -104,43 +109,44 @@ namespace ams::kern { KMemoryState_NonDeviceIpc = ams::svc::MemoryState_NonDeviceIpc | KMemoryState_FlagsMisc | KMemoryState_FlagCanUseNonDeviceIpc, - KMemoryState_Kernel = ams::svc::MemoryState_Kernel | KMemoryState_FlagMapped, + KMemoryState_Kernel = ams::svc::MemoryState_Kernel, KMemoryState_GeneratedCode = ams::svc::MemoryState_GeneratedCode | KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted | KMemoryState_FlagCanDebug | KMemoryState_FlagLinearMapped, KMemoryState_CodeOut = ams::svc::MemoryState_CodeOut | KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted | KMemoryState_FlagLinearMapped, KMemoryState_Coverage = ams::svc::MemoryState_Coverage | KMemoryState_FlagMapped, - KMemoryState_Insecure = ams::svc::MemoryState_Insecure | KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted | KMemoryState_FlagLinearMapped | KMemoryState_FlagCanChangeAttribute - | KMemoryState_FlagCanDeviceMap | KMemoryState_FlagCanAlignedDeviceMap + KMemoryState_Insecure = ams::svc::MemoryState_Insecure | KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted | KMemoryState_FlagLinearMapped | KMemoryState_FlagCanChangeAttribute + | KMemoryState_FlagCanDeviceMap | KMemoryState_FlagCanAlignedDeviceMap | KMemoryState_FlagCanQueryPhysical | KMemoryState_FlagCanUseNonSecureIpc | KMemoryState_FlagCanUseNonDeviceIpc, }; #if 1 static_assert(KMemoryState_Free == 0x00000000); - static_assert(KMemoryState_Io == 0x00182001); - static_assert(KMemoryState_Static == 0x00042002); + static_assert(KMemoryState_IoMemory == 0x00182001); + static_assert(KMemoryState_IoRegister == 0x00180001); + static_assert(KMemoryState_Static == 0x00040002); static_assert(KMemoryState_Code == 0x04DC7E03); - static_assert(KMemoryState_CodeData == 0x07FEBD04); + static_assert(KMemoryState_CodeData == 0x0FFEBD04); static_assert(KMemoryState_Normal == 0x077EBD05); static_assert(KMemoryState_Shared == 0x04402006); static_assert(KMemoryState_AliasCode == 0x04DD7E08); - static_assert(KMemoryState_AliasCodeData == 0x07FFBD09); + static_assert(KMemoryState_AliasCodeData == 0x0FFFBD09); static_assert(KMemoryState_Ipc == 0x045C3C0A); static_assert(KMemoryState_Stack == 0x045C3C0B); - static_assert(KMemoryState_ThreadLocal == 0x0400200C); + static_assert(KMemoryState_ThreadLocal == 0x0400000C); static_assert(KMemoryState_Transfered == 0x055C3C0D); static_assert(KMemoryState_SharedTransfered == 0x045C380E); static_assert(KMemoryState_SharedCode == 0x0440380F); static_assert(KMemoryState_Inaccessible == 0x00000010); static_assert(KMemoryState_NonSecureIpc == 0x045C3811); static_assert(KMemoryState_NonDeviceIpc == 0x044C2812); - static_assert(KMemoryState_Kernel == 0x00002013); + static_assert(KMemoryState_Kernel == 0x00000013); static_assert(KMemoryState_GeneratedCode == 0x04402214); static_assert(KMemoryState_CodeOut == 0x04402015); - static_assert(KMemoryState_Coverage == 0x00002016); - static_assert(KMemoryState_Insecure == 0x05583817); + static_assert(KMemoryState_Coverage == 0x00002016); /* TODO: Is this correct? */ + static_assert(KMemoryState_Insecure == 0x055C3817); #endif enum KMemoryPermission : u8 { @@ -175,16 +181,17 @@ namespace ams::kern { } enum KMemoryAttribute : u8 { - KMemoryAttribute_None = 0x00, - KMemoryAttribute_All = 0xFF, - KMemoryAttribute_UserMask = KMemoryAttribute_All, + KMemoryAttribute_None = 0x00, + KMemoryAttribute_All = 0xFF, + KMemoryAttribute_UserMask = KMemoryAttribute_All, - KMemoryAttribute_Locked = ams::svc::MemoryAttribute_Locked, - KMemoryAttribute_IpcLocked = ams::svc::MemoryAttribute_IpcLocked, - KMemoryAttribute_DeviceShared = ams::svc::MemoryAttribute_DeviceShared, - KMemoryAttribute_Uncached = ams::svc::MemoryAttribute_Uncached, + KMemoryAttribute_Locked = ams::svc::MemoryAttribute_Locked, + KMemoryAttribute_IpcLocked = ams::svc::MemoryAttribute_IpcLocked, + KMemoryAttribute_DeviceShared = ams::svc::MemoryAttribute_DeviceShared, + KMemoryAttribute_Uncached = ams::svc::MemoryAttribute_Uncached, + KMemoryAttribute_PermissionLocked = ams::svc::MemoryAttribute_PermissionLocked, - KMemoryAttribute_SetMask = KMemoryAttribute_Uncached, + KMemoryAttribute_SetMask = KMemoryAttribute_Uncached, }; enum KMemoryBlockDisableMergeAttribute : u8 { @@ -258,6 +265,10 @@ namespace ams::kern { return m_state; } + constexpr ams::svc::MemoryState GetSvcState() const { + return static_cast(m_state & KMemoryState_Mask); + } + constexpr KMemoryPermission GetPermission() const { return m_permission; } 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 06d735504..765ec2db4 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp @@ -241,16 +241,20 @@ namespace ams::kern { 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, KMemoryState_AliasCode); + return this->CanContain(addr, size, ams::svc::MemoryState_AliasCode); } ALWAYS_INLINE KScopedLightLock AcquireDeviceMapLock() { return KScopedLightLock(m_device_map_lock); } - KProcessAddress GetRegionAddress(KMemoryState state) const; - size_t GetRegionSize(KMemoryState state) const; - bool CanContain(KProcessAddress addr, size_t size, KMemoryState state) const; + KProcessAddress GetRegionAddress(ams::svc::MemoryState state) const; + size_t GetRegionSize(ams::svc::MemoryState state) const; + bool CanContain(KProcessAddress addr, size_t size, ams::svc::MemoryState state) const; + + ALWAYS_INLINE KProcessAddress GetRegionAddress(KMemoryState state) const { return this->GetRegionAddress(static_cast(state & KMemoryState_Mask)); } + ALWAYS_INLINE size_t GetRegionSize(KMemoryState state) const { return this->GetRegionSize(static_cast(state & KMemoryState_Mask)); } + ALWAYS_INLINE bool CanContain(KProcessAddress addr, size_t size, KMemoryState state) const { return this->CanContain(addr, size, static_cast(state & KMemoryState_Mask)); } protected: /* NOTE: These three functions (Operate, Operate, FinalizeUpdate) are virtual functions */ /* in Nintendo's kernel. We devirtualize them, since KPageTable is the only derived */ @@ -321,7 +325,7 @@ namespace ams::kern { Result QueryInfoImpl(KMemoryInfo *out_info, ams::svc::PageInfo *out_page, KProcessAddress address) const; - Result QueryMappingImpl(KProcessAddress *out, KPhysicalAddress address, size_t size, KMemoryState state) const; + Result QueryMappingImpl(KProcessAddress *out, KPhysicalAddress address, size_t size, ams::svc::MemoryState state) const; Result AllocateAndMapPagesImpl(PageLinkedList *page_list, KProcessAddress address, size_t num_pages, KMemoryPermission perm); Result MapPageGroupImpl(PageLinkedList *page_list, KProcessAddress address, const KPageGroup &pg, const KPageProperties properties, bool reuse_ll); @@ -335,9 +339,9 @@ namespace ams::kern { NOINLINE Result MapPages(KProcessAddress *out_addr, size_t num_pages, size_t alignment, KPhysicalAddress phys_addr, bool is_pa_valid, KProcessAddress region_start, size_t region_num_pages, KMemoryState state, KMemoryPermission perm); - Result MapIoImpl(KProcessAddress *out, PageLinkedList *page_list, KPhysicalAddress phys_addr, size_t size, KMemoryPermission perm); - Result ReadIoMemoryImpl(void *buffer, KPhysicalAddress phys_addr, size_t size); - Result WriteIoMemoryImpl(KPhysicalAddress phys_addr, const void *buffer, size_t size); + Result MapIoImpl(KProcessAddress *out, PageLinkedList *page_list, KPhysicalAddress phys_addr, size_t size, KMemoryState state, KMemoryPermission perm); + Result ReadIoMemoryImpl(void *buffer, KPhysicalAddress phys_addr, size_t size, KMemoryState state); + Result WriteIoMemoryImpl(KPhysicalAddress phys_addr, const void *buffer, size_t size, KMemoryState state); Result SetupForIpcClient(PageLinkedList *page_list, size_t *out_blocks_needed, KProcessAddress address, size_t size, KMemoryPermission test_perm, KMemoryState dst_state); Result SetupForIpcServer(KProcessAddress *out_addr, size_t size, KProcessAddress src_addr, KMemoryPermission test_perm, KMemoryState dst_state, KPageTableBase &src_page_table, bool send); @@ -371,8 +375,8 @@ namespace ams::kern { Result SetMaxHeapSize(size_t size); Result QueryInfo(KMemoryInfo *out_info, ams::svc::PageInfo *out_page_info, KProcessAddress addr) const; Result QueryPhysicalAddress(ams::svc::PhysicalMemoryInfo *out, KProcessAddress address) const; - Result QueryStaticMapping(KProcessAddress *out, KPhysicalAddress address, size_t size) const { R_RETURN(this->QueryMappingImpl(out, address, size, KMemoryState_Static)); } - Result QueryIoMapping(KProcessAddress *out, KPhysicalAddress address, size_t size) const { R_RETURN(this->QueryMappingImpl(out, address, size, KMemoryState_Io)); } + Result QueryStaticMapping(KProcessAddress *out, KPhysicalAddress address, size_t size) const { R_RETURN(this->QueryMappingImpl(out, address, size, ams::svc::MemoryState_Static)); } + Result QueryIoMapping(KProcessAddress *out, KPhysicalAddress address, size_t size) const { R_RETURN(this->QueryMappingImpl(out, address, size, ams::svc::MemoryState_Io)); } Result MapMemory(KProcessAddress dst_address, KProcessAddress src_address, size_t size); Result UnmapMemory(KProcessAddress dst_address, KProcessAddress src_address, size_t size); Result MapCodeMemory(KProcessAddress dst_address, KProcessAddress src_address, size_t size); @@ -409,10 +413,10 @@ namespace ams::kern { Result InvalidateProcessDataCache(KProcessAddress address, size_t size); Result ReadDebugMemory(void *buffer, KProcessAddress address, size_t size); - Result ReadDebugIoMemory(void *buffer, KProcessAddress address, size_t size); + Result ReadDebugIoMemory(void *buffer, KProcessAddress address, size_t size, KMemoryState state); Result WriteDebugMemory(KProcessAddress address, const void *buffer, size_t size); - Result WriteDebugIoMemory(KProcessAddress address, const void *buffer, size_t size); + Result WriteDebugIoMemory(KProcessAddress address, const void *buffer, size_t size, KMemoryState state); Result LockForMapDeviceAddressSpace(bool *out_is_io, KProcessAddress address, size_t size, KMemoryPermission perm, bool is_aligned, bool check_heap); Result LockForUnmapDeviceAddressSpace(KProcessAddress address, size_t size, bool check_heap); diff --git a/libraries/libmesosphere/source/kern_k_debug_base.cpp b/libraries/libmesosphere/source/kern_k_debug_base.cpp index 3388e1ce3..418d804f3 100644 --- a/libraries/libmesosphere/source/kern_k_debug_base.cpp +++ b/libraries/libmesosphere/source/kern_k_debug_base.cpp @@ -118,12 +118,12 @@ namespace ams::kern { const size_t cur_size = std::min(remaining, info.GetEndAddress() - GetInteger(cur_address)); /* Read the memory. */ - if (info.GetState() != KMemoryState_Io) { + if (info.GetSvcState() != ams::svc::MemoryState_Io) { /* The memory is normal memory. */ R_TRY(target_pt.ReadDebugMemory(GetVoidPointer(buffer), cur_address, cur_size)); } else { /* The memory is IO memory. */ - R_TRY(target_pt.ReadDebugIoMemory(GetVoidPointer(buffer), cur_address, cur_size)); + R_TRY(target_pt.ReadDebugIoMemory(GetVoidPointer(buffer), cur_address, cur_size, info.GetState())); } /* Advance. */ @@ -181,12 +181,12 @@ namespace ams::kern { const size_t cur_size = std::min(remaining, info.GetEndAddress() - GetInteger(cur_address)); /* Read the memory. */ - if (info.GetState() != KMemoryState_Io) { + if (info.GetSvcState() != ams::svc::MemoryState_Io) { /* The memory is normal memory. */ R_TRY(target_pt.WriteDebugMemory(cur_address, GetVoidPointer(buffer), cur_size)); } else { /* The memory is IO memory. */ - R_TRY(target_pt.WriteDebugIoMemory(cur_address, GetVoidPointer(buffer), cur_size)); + R_TRY(target_pt.WriteDebugIoMemory(cur_address, GetVoidPointer(buffer), cur_size, info.GetState())); } /* Advance. */ diff --git a/libraries/libmesosphere/source/kern_k_memory_block_manager.cpp b/libraries/libmesosphere/source/kern_k_memory_block_manager.cpp index 0a5732032..4ccf06895 100644 --- a/libraries/libmesosphere/source/kern_k_memory_block_manager.cpp +++ b/libraries/libmesosphere/source/kern_k_memory_block_manager.cpp @@ -21,7 +21,8 @@ namespace ams::kern { constexpr const std::pair MemoryStateNames[] = { {KMemoryState_Free , "----- Free -----"}, - {KMemoryState_Io , "Io "}, + {KMemoryState_IoMemory , "IoMemory "}, + {KMemoryState_IoRegister , "IoRegister "}, {KMemoryState_Static , "Static "}, {KMemoryState_Code , "Code "}, {KMemoryState_CodeData , "CodeData "}, diff --git a/libraries/libmesosphere/source/kern_k_page_table_base.cpp b/libraries/libmesosphere/source/kern_k_page_table_base.cpp index 06aa158c6..c60a6ccdb 100644 --- a/libraries/libmesosphere/source/kern_k_page_table_base.cpp +++ b/libraries/libmesosphere/source/kern_k_page_table_base.cpp @@ -368,77 +368,77 @@ namespace ams::kern { cpu::InvalidateEntireInstructionCache(); } - KProcessAddress KPageTableBase::GetRegionAddress(KMemoryState state) const { + KProcessAddress KPageTableBase::GetRegionAddress(ams::svc::MemoryState state) const { switch (state) { - case KMemoryState_Free: - case KMemoryState_Kernel: + case ams::svc::MemoryState_Free: + case ams::svc::MemoryState_Kernel: return m_address_space_start; - case KMemoryState_Normal: + case ams::svc::MemoryState_Normal: return m_heap_region_start; - case KMemoryState_Ipc: - case KMemoryState_NonSecureIpc: - case KMemoryState_NonDeviceIpc: + case ams::svc::MemoryState_Ipc: + case ams::svc::MemoryState_NonSecureIpc: + case ams::svc::MemoryState_NonDeviceIpc: return m_alias_region_start; - case KMemoryState_Stack: + case ams::svc::MemoryState_Stack: return m_stack_region_start; - case KMemoryState_Static: - case KMemoryState_ThreadLocal: + case ams::svc::MemoryState_Static: + case ams::svc::MemoryState_ThreadLocal: return m_kernel_map_region_start; - case KMemoryState_Io: - case KMemoryState_Shared: - case KMemoryState_AliasCode: - case KMemoryState_AliasCodeData: - case KMemoryState_Transfered: - case KMemoryState_SharedTransfered: - case KMemoryState_SharedCode: - case KMemoryState_GeneratedCode: - case KMemoryState_CodeOut: - case KMemoryState_Coverage: - case KMemoryState_Insecure: + case ams::svc::MemoryState_Io: + case ams::svc::MemoryState_Shared: + case ams::svc::MemoryState_AliasCode: + case ams::svc::MemoryState_AliasCodeData: + case ams::svc::MemoryState_Transfered: + case ams::svc::MemoryState_SharedTransfered: + case ams::svc::MemoryState_SharedCode: + case ams::svc::MemoryState_GeneratedCode: + case ams::svc::MemoryState_CodeOut: + case ams::svc::MemoryState_Coverage: + case ams::svc::MemoryState_Insecure: return m_alias_code_region_start; - case KMemoryState_Code: - case KMemoryState_CodeData: + case ams::svc::MemoryState_Code: + case ams::svc::MemoryState_CodeData: return m_code_region_start; MESOSPHERE_UNREACHABLE_DEFAULT_CASE(); } } - size_t KPageTableBase::GetRegionSize(KMemoryState state) const { + size_t KPageTableBase::GetRegionSize(ams::svc::MemoryState state) const { switch (state) { - case KMemoryState_Free: - case KMemoryState_Kernel: + case ams::svc::MemoryState_Free: + case ams::svc::MemoryState_Kernel: return m_address_space_end - m_address_space_start; - case KMemoryState_Normal: + case ams::svc::MemoryState_Normal: return m_heap_region_end - m_heap_region_start; - case KMemoryState_Ipc: - case KMemoryState_NonSecureIpc: - case KMemoryState_NonDeviceIpc: + case ams::svc::MemoryState_Ipc: + case ams::svc::MemoryState_NonSecureIpc: + case ams::svc::MemoryState_NonDeviceIpc: return m_alias_region_end - m_alias_region_start; - case KMemoryState_Stack: + case ams::svc::MemoryState_Stack: return m_stack_region_end - m_stack_region_start; - case KMemoryState_Static: - case KMemoryState_ThreadLocal: + case ams::svc::MemoryState_Static: + case ams::svc::MemoryState_ThreadLocal: return m_kernel_map_region_end - m_kernel_map_region_start; - case KMemoryState_Io: - case KMemoryState_Shared: - case KMemoryState_AliasCode: - case KMemoryState_AliasCodeData: - case KMemoryState_Transfered: - case KMemoryState_SharedTransfered: - case KMemoryState_SharedCode: - case KMemoryState_GeneratedCode: - case KMemoryState_CodeOut: - case KMemoryState_Coverage: - case KMemoryState_Insecure: + case ams::svc::MemoryState_Io: + case ams::svc::MemoryState_Shared: + case ams::svc::MemoryState_AliasCode: + case ams::svc::MemoryState_AliasCodeData: + case ams::svc::MemoryState_Transfered: + case ams::svc::MemoryState_SharedTransfered: + case ams::svc::MemoryState_SharedCode: + case ams::svc::MemoryState_GeneratedCode: + case ams::svc::MemoryState_CodeOut: + case ams::svc::MemoryState_Coverage: + case ams::svc::MemoryState_Insecure: return m_alias_code_region_end - m_alias_code_region_start; - case KMemoryState_Code: - case KMemoryState_CodeData: + case ams::svc::MemoryState_Code: + case ams::svc::MemoryState_CodeData: return m_code_region_end - m_code_region_start; MESOSPHERE_UNREACHABLE_DEFAULT_CASE(); } } - bool KPageTableBase::CanContain(KProcessAddress addr, size_t size, KMemoryState state) const { + bool KPageTableBase::CanContain(KProcessAddress addr, size_t size, ams::svc::MemoryState state) const { const KProcessAddress end = addr + size; const KProcessAddress last = end - 1; @@ -449,32 +449,32 @@ namespace ams::kern { const bool is_in_heap = !(end <= m_heap_region_start || m_heap_region_end <= addr || m_heap_region_start == m_heap_region_end); const bool is_in_alias = !(end <= m_alias_region_start || m_alias_region_end <= addr || m_alias_region_start == m_alias_region_end); switch (state) { - case KMemoryState_Free: - case KMemoryState_Kernel: + case ams::svc::MemoryState_Free: + case ams::svc::MemoryState_Kernel: return is_in_region; - case KMemoryState_Io: - case KMemoryState_Static: - case KMemoryState_Code: - case KMemoryState_CodeData: - case KMemoryState_Shared: - case KMemoryState_AliasCode: - case KMemoryState_AliasCodeData: - case KMemoryState_Stack: - case KMemoryState_ThreadLocal: - case KMemoryState_Transfered: - case KMemoryState_SharedTransfered: - case KMemoryState_SharedCode: - case KMemoryState_GeneratedCode: - case KMemoryState_CodeOut: - case KMemoryState_Coverage: - case KMemoryState_Insecure: + case ams::svc::MemoryState_Io: + case ams::svc::MemoryState_Static: + case ams::svc::MemoryState_Code: + case ams::svc::MemoryState_CodeData: + case ams::svc::MemoryState_Shared: + case ams::svc::MemoryState_AliasCode: + case ams::svc::MemoryState_AliasCodeData: + case ams::svc::MemoryState_Stack: + case ams::svc::MemoryState_ThreadLocal: + case ams::svc::MemoryState_Transfered: + case ams::svc::MemoryState_SharedTransfered: + case ams::svc::MemoryState_SharedCode: + case ams::svc::MemoryState_GeneratedCode: + 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 KMemoryState_Normal: + case ams::svc::MemoryState_Normal: MESOSPHERE_ASSERT(is_in_heap); return is_in_region && !is_in_alias; - case KMemoryState_Ipc: - case KMemoryState_NonSecureIpc: - case KMemoryState_NonDeviceIpc: + 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: @@ -705,7 +705,7 @@ namespace ams::kern { R_SUCCEED(); } - Result KPageTableBase::QueryMappingImpl(KProcessAddress *out, KPhysicalAddress address, size_t size, KMemoryState state) const { + Result KPageTableBase::QueryMappingImpl(KProcessAddress *out, KPhysicalAddress address, size_t size, ams::svc::MemoryState state) const { MESOSPHERE_ASSERT(!this->IsLockedByCurrentThread()); MESOSPHERE_ASSERT(out != nullptr); @@ -739,7 +739,7 @@ namespace ams::kern { if (cur_valid && cur_entry.phys_addr <= address && address + size <= cur_entry.phys_addr + cur_entry.block_size) { /* Check if this region is valid. */ const KProcessAddress mapped_address = (region_start + tot_size) + (address - cur_entry.phys_addr); - if (R_SUCCEEDED(this->CheckMemoryState(mapped_address, size, KMemoryState_All, state, KMemoryPermission_UserRead, KMemoryPermission_UserRead, KMemoryAttribute_None, KMemoryAttribute_None))) { + if (R_SUCCEEDED(this->CheckMemoryState(mapped_address, size, KMemoryState_Mask, static_cast(util::ToUnderlying(state)), KMemoryPermission_UserRead, KMemoryPermission_UserRead, KMemoryAttribute_None, KMemoryAttribute_None))) { /* It is! */ *out = mapped_address; R_SUCCEED(); @@ -1899,7 +1899,7 @@ namespace ams::kern { R_SUCCEED(); } - Result KPageTableBase::MapIoImpl(KProcessAddress *out, PageLinkedList *page_list, KPhysicalAddress phys_addr, size_t size, KMemoryPermission perm) { + Result KPageTableBase::MapIoImpl(KProcessAddress *out, PageLinkedList *page_list, KPhysicalAddress phys_addr, size_t size, KMemoryState state, KMemoryPermission perm) { /* Check pre-conditions. */ MESOSPHERE_ASSERT(this->IsLockedByCurrentThread()); MESOSPHERE_ASSERT(util::IsAligned(GetInteger(phys_addr), PageSize)); @@ -1915,7 +1915,7 @@ namespace ams::kern { const size_t region_size = m_kernel_map_region_end - m_kernel_map_region_start; const size_t region_num_pages = region_size / PageSize; - MESOSPHERE_ASSERT(this->CanContain(region_start, region_size, KMemoryState_Io)); + MESOSPHERE_ASSERT(this->CanContain(region_start, region_size, state)); /* Locate the memory region. */ const KMemoryRegion *region = KMemoryLayout::Find(phys_addr); @@ -1960,11 +1960,11 @@ namespace ams::kern { R_UNLESS(addr != Null, svc::ResultOutOfMemory()); /* Check that we can map IO here. */ - MESOSPHERE_ASSERT(this->CanContain(addr, size, KMemoryState_Io)); + MESOSPHERE_ASSERT(this->CanContain(addr, size, state)); MESOSPHERE_R_ASSERT(this->CheckMemoryState(addr, size, KMemoryState_All, KMemoryState_Free, KMemoryPermission_None, KMemoryPermission_None, KMemoryAttribute_None, KMemoryAttribute_None)); /* Perform mapping operation. */ - const KPageProperties properties = { perm, true, false, DisableMergeAttribute_DisableHead }; + const KPageProperties properties = { perm, state == KMemoryState_IoRegister, false, DisableMergeAttribute_DisableHead }; R_TRY(this->Operate(page_list, addr, num_pages, phys_addr, true, properties, OperationType_Map, false)); /* Set the output address. */ @@ -1987,10 +1987,10 @@ namespace ams::kern { /* Map the io memory. */ KProcessAddress addr; - R_TRY(this->MapIoImpl(std::addressof(addr), updater.GetPageList(), phys_addr, size, perm)); + R_TRY(this->MapIoImpl(std::addressof(addr), updater.GetPageList(), phys_addr, size, KMemoryState_IoRegister, perm)); /* Update the blocks. */ - m_memory_block_manager.Update(std::addressof(allocator), addr, size / PageSize, KMemoryState_Io, perm, KMemoryAttribute_Locked, KMemoryBlockDisableMergeAttribute_Normal, KMemoryBlockDisableMergeAttribute_None); + m_memory_block_manager.Update(std::addressof(allocator), addr, size / PageSize, KMemoryState_IoRegister, perm, KMemoryAttribute_Locked, KMemoryBlockDisableMergeAttribute_Normal, KMemoryBlockDisableMergeAttribute_None); /* We successfully mapped the pages. */ R_SUCCEED(); @@ -2020,7 +2020,8 @@ namespace ams::kern { R_TRY(this->Operate(updater.GetPageList(), dst_address, num_pages, phys_addr, true, properties, OperationType_Map, false)); /* Update the blocks. */ - m_memory_block_manager.Update(std::addressof(allocator), dst_address, num_pages, KMemoryState_Io, perm, KMemoryAttribute_Locked, KMemoryBlockDisableMergeAttribute_Normal, KMemoryBlockDisableMergeAttribute_None); + const auto state = mapping == ams::svc::MemoryMapping_Memory ? KMemoryState_IoMemory : KMemoryState_IoRegister; + m_memory_block_manager.Update(std::addressof(allocator), dst_address, num_pages, state, perm, KMemoryAttribute_Locked, KMemoryBlockDisableMergeAttribute_Normal, KMemoryBlockDisableMergeAttribute_None); /* We successfully mapped the pages. */ R_SUCCEED(); @@ -2039,7 +2040,7 @@ namespace ams::kern { size_t num_allocator_blocks; R_TRY(this->CheckMemoryState(std::addressof(old_state), std::addressof(old_perm), std::addressof(old_attr), std::addressof(num_allocator_blocks), dst_address, size, - KMemoryState_All, KMemoryState_Io, + KMemoryState_All, mapping == ams::svc::MemoryMapping_Memory ? KMemoryState_IoMemory : KMemoryState_IoRegister, KMemoryPermission_None, KMemoryPermission_None, KMemoryAttribute_All, KMemoryAttribute_Locked)); @@ -2308,7 +2309,7 @@ namespace ams::kern { KScopedPageTableUpdater updater(this); /* Perform mapping operation. */ - const KPageProperties properties = { perm, state == KMemoryState_Io, false, DisableMergeAttribute_DisableHead }; + const KPageProperties properties = { perm, false, false, DisableMergeAttribute_DisableHead }; R_TRY(this->MapPageGroupImpl(updater.GetPageList(), addr, pg, properties, false)); /* Update the blocks. */ @@ -2343,7 +2344,7 @@ namespace ams::kern { KScopedPageTableUpdater updater(this); /* Perform mapping operation. */ - const KPageProperties properties = { perm, state == KMemoryState_Io, false, DisableMergeAttribute_DisableHead }; + const KPageProperties properties = { perm, false, false, DisableMergeAttribute_DisableHead }; R_TRY(this->MapPageGroupImpl(updater.GetPageList(), addr, pg, properties, false)); /* Update the blocks. */ @@ -2653,7 +2654,7 @@ namespace ams::kern { R_SUCCEED(); } - Result KPageTableBase::ReadIoMemoryImpl(void *buffer, KPhysicalAddress phys_addr, size_t size) { + Result KPageTableBase::ReadIoMemoryImpl(void *buffer, KPhysicalAddress phys_addr, size_t size, KMemoryState state) { /* Check pre-conditions. */ MESOSPHERE_ASSERT(this->IsLockedByCurrentThread()); @@ -2667,7 +2668,7 @@ namespace ams::kern { /* Temporarily map the io memory. */ KProcessAddress io_addr; - R_TRY(this->MapIoImpl(std::addressof(io_addr), updater.GetPageList(), map_start, map_size, KMemoryPermission_UserRead)); + R_TRY(this->MapIoImpl(std::addressof(io_addr), updater.GetPageList(), map_start, map_size, state, KMemoryPermission_UserRead)); /* Ensure we unmap the io memory when we're done with it. */ ON_SCOPE_EXIT { @@ -2698,7 +2699,7 @@ namespace ams::kern { R_SUCCEED(); } - Result KPageTableBase::WriteIoMemoryImpl(KPhysicalAddress phys_addr, const void *buffer, size_t size) { + Result KPageTableBase::WriteIoMemoryImpl(KPhysicalAddress phys_addr, const void *buffer, size_t size, KMemoryState state) { /* Check pre-conditions. */ MESOSPHERE_ASSERT(this->IsLockedByCurrentThread()); @@ -2712,7 +2713,7 @@ namespace ams::kern { /* Temporarily map the io memory. */ KProcessAddress io_addr; - R_TRY(this->MapIoImpl(std::addressof(io_addr), updater.GetPageList(), map_start, map_size, KMemoryPermission_UserReadWrite)); + R_TRY(this->MapIoImpl(std::addressof(io_addr), updater.GetPageList(), map_start, map_size, state, KMemoryPermission_UserReadWrite)); /* Ensure we unmap the io memory when we're done with it. */ ON_SCOPE_EXIT { @@ -2743,7 +2744,7 @@ namespace ams::kern { R_SUCCEED(); } - Result KPageTableBase::ReadDebugIoMemory(void *buffer, KProcessAddress address, size_t size) { + Result KPageTableBase::ReadDebugIoMemory(void *buffer, KProcessAddress address, size_t size, KMemoryState state) { /* Lightly validate the range before doing anything else. */ R_UNLESS(this->Contains(address, size), svc::ResultInvalidCurrentMemory()); @@ -2755,7 +2756,7 @@ namespace ams::kern { KScopedLightLockPair lk(src_page_table.m_general_lock, dst_page_table.m_general_lock); /* Check that the desired range is readable io memory. */ - R_TRY(this->CheckMemoryStateContiguous(address, size, KMemoryState_All, KMemoryState_Io, KMemoryPermission_UserRead, KMemoryPermission_UserRead, KMemoryAttribute_None, KMemoryAttribute_None)); + R_TRY(this->CheckMemoryStateContiguous(address, size, KMemoryState_All, state, KMemoryPermission_UserRead, KMemoryPermission_UserRead, KMemoryAttribute_None, KMemoryAttribute_None)); /* Read the memory. */ u8 *dst = static_cast(buffer); @@ -2769,7 +2770,7 @@ namespace ams::kern { const size_t cur_size = std::min(last_address - address + 1, util::AlignDown(GetInteger(address) + PageSize, PageSize) - GetInteger(address)); /* Read. */ - R_TRY(dst_page_table.ReadIoMemoryImpl(dst, phys_addr, cur_size)); + R_TRY(dst_page_table.ReadIoMemoryImpl(dst, phys_addr, cur_size, state)); /* Advance. */ address += cur_size; @@ -2779,7 +2780,7 @@ namespace ams::kern { R_SUCCEED(); } - Result KPageTableBase::WriteDebugIoMemory(KProcessAddress address, const void *buffer, size_t size) { + Result KPageTableBase::WriteDebugIoMemory(KProcessAddress address, const void *buffer, size_t size, KMemoryState state) { /* Lightly validate the range before doing anything else. */ R_UNLESS(this->Contains(address, size), svc::ResultInvalidCurrentMemory()); @@ -2791,7 +2792,7 @@ namespace ams::kern { KScopedLightLockPair lk(src_page_table.m_general_lock, dst_page_table.m_general_lock); /* Check that the desired range is writable io memory. */ - R_TRY(this->CheckMemoryStateContiguous(address, size, KMemoryState_All, KMemoryState_Io, KMemoryPermission_UserReadWrite, KMemoryPermission_UserReadWrite, KMemoryAttribute_None, KMemoryAttribute_None)); + R_TRY(this->CheckMemoryStateContiguous(address, size, KMemoryState_All, state, KMemoryPermission_UserReadWrite, KMemoryPermission_UserReadWrite, KMemoryAttribute_None, KMemoryAttribute_None)); /* Read the memory. */ const u8 *src = static_cast(buffer); @@ -2805,7 +2806,7 @@ namespace ams::kern { const size_t cur_size = std::min(last_address - address + 1, util::AlignDown(GetInteger(address) + PageSize, PageSize) - GetInteger(address)); /* Read. */ - R_TRY(dst_page_table.WriteIoMemoryImpl(phys_addr, src, cur_size)); + R_TRY(dst_page_table.WriteIoMemoryImpl(phys_addr, src, cur_size, state)); /* Advance. */ address += cur_size; @@ -2838,7 +2839,7 @@ namespace ams::kern { m_memory_block_manager.UpdateLock(std::addressof(allocator), address, num_pages, &KMemoryBlock::ShareToDevice, KMemoryPermission_None); /* Set whether the locked memory was io. */ - *out_is_io = old_state == KMemoryState_Io; + *out_is_io = static_cast(old_state & KMemoryState_Mask) == ams::svc::MemoryState_Io; R_SUCCEED(); } diff --git a/libraries/libmesosphere/source/svc/kern_svc_io_pool.cpp b/libraries/libmesosphere/source/svc/kern_svc_io_pool.cpp index ffa65f723..a5d132e61 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_io_pool.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_io_pool.cpp @@ -127,7 +127,7 @@ namespace ams::kern::svc { R_UNLESS((address < address + size), svc::ResultInvalidCurrentMemory()); /* Verify that the mapping is in range. */ - R_UNLESS(GetCurrentProcess().GetPageTable().CanContain(address, size, KMemoryState_Io), svc::ResultInvalidMemoryRegion()); + R_UNLESS(GetCurrentProcess().GetPageTable().CanContain(address, size, ams::svc::MemoryState_Io), svc::ResultInvalidMemoryRegion()); /* Validate the map permission. */ R_UNLESS(IsValidIoRegionPermission(map_perm), svc::ResultInvalidNewMemoryPermission()); @@ -156,7 +156,7 @@ namespace ams::kern::svc { R_UNLESS((address < address + size), svc::ResultInvalidCurrentMemory()); /* Verify that the mapping is in range. */ - R_UNLESS(GetCurrentProcess().GetPageTable().CanContain(address, size, KMemoryState_Io), svc::ResultInvalidMemoryRegion()); + R_UNLESS(GetCurrentProcess().GetPageTable().CanContain(address, size, ams::svc::MemoryState_Io), svc::ResultInvalidMemoryRegion()); /* Get the io region. */ KScopedAutoObject io_region = GetCurrentProcess().GetHandleTable().GetObject(io_region_handle); diff --git a/libraries/libvapours/include/vapours/svc/svc_types_common.hpp b/libraries/libvapours/include/vapours/svc/svc_types_common.hpp index c600519df..f71d2c486 100644 --- a/libraries/libvapours/include/vapours/svc/svc_types_common.hpp +++ b/libraries/libvapours/include/vapours/svc/svc_types_common.hpp @@ -112,10 +112,11 @@ namespace ams::svc { }; enum MemoryAttribute : u32 { - MemoryAttribute_Locked = (1 << 0), - MemoryAttribute_IpcLocked = (1 << 1), - MemoryAttribute_DeviceShared = (1 << 2), - MemoryAttribute_Uncached = (1 << 3), + MemoryAttribute_Locked = (1 << 0), + MemoryAttribute_IpcLocked = (1 << 1), + MemoryAttribute_DeviceShared = (1 << 2), + MemoryAttribute_Uncached = (1 << 3), + MemoryAttribute_PermissionLocked = (1 << 4), }; enum MemoryMapping : u32 {