mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-15 01:26:34 +00:00
kern: update KMemoryState, remove bijection (separate IoRegister/IoMemory)
This commit is contained in:
parent
545ddaf92c
commit
5aba96d029
8 changed files with 163 additions and 144 deletions
|
@ -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(); }
|
||||
|
|
|
@ -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,7 +109,7 @@ 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,
|
||||
|
@ -112,35 +117,36 @@ namespace ams::kern {
|
|||
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_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 {
|
||||
|
@ -183,6 +189,7 @@ namespace ams::kern {
|
|||
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,
|
||||
};
|
||||
|
@ -258,6 +265,10 @@ namespace ams::kern {
|
|||
return m_state;
|
||||
}
|
||||
|
||||
constexpr ams::svc::MemoryState GetSvcState() const {
|
||||
return static_cast<ams::svc::MemoryState>(m_state & KMemoryState_Mask);
|
||||
}
|
||||
|
||||
constexpr KMemoryPermission GetPermission() const {
|
||||
return m_permission;
|
||||
}
|
||||
|
|
|
@ -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<ams::svc::MemoryState>(state & KMemoryState_Mask)); }
|
||||
ALWAYS_INLINE size_t GetRegionSize(KMemoryState state) const { return this->GetRegionSize(static_cast<ams::svc::MemoryState>(state & KMemoryState_Mask)); }
|
||||
ALWAYS_INLINE bool CanContain(KProcessAddress addr, size_t size, KMemoryState state) const { return this->CanContain(addr, size, static_cast<ams::svc::MemoryState>(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);
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -21,7 +21,8 @@ namespace ams::kern {
|
|||
|
||||
constexpr const std::pair<KMemoryState, const char *> MemoryStateNames[] = {
|
||||
{KMemoryState_Free , "----- Free -----"},
|
||||
{KMemoryState_Io , "Io "},
|
||||
{KMemoryState_IoMemory , "IoMemory "},
|
||||
{KMemoryState_IoRegister , "IoRegister "},
|
||||
{KMemoryState_Static , "Static "},
|
||||
{KMemoryState_Code , "Code "},
|
||||
{KMemoryState_CodeData , "CodeData "},
|
||||
|
|
|
@ -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<KMemoryState>(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<KProcessAddress>, 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<u8 *>(buffer);
|
||||
|
@ -2769,7 +2770,7 @@ namespace ams::kern {
|
|||
const size_t cur_size = std::min<size_t>(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<const u8 *>(buffer);
|
||||
|
@ -2805,7 +2806,7 @@ namespace ams::kern {
|
|||
const size_t cur_size = std::min<size_t>(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<ams::svc::MemoryState>(old_state & KMemoryState_Mask) == ams::svc::MemoryState_Io;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
|
|
@ -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<KIoRegion>(io_region_handle);
|
||||
|
|
|
@ -116,6 +116,7 @@ namespace ams::svc {
|
|||
MemoryAttribute_IpcLocked = (1 << 1),
|
||||
MemoryAttribute_DeviceShared = (1 << 2),
|
||||
MemoryAttribute_Uncached = (1 << 3),
|
||||
MemoryAttribute_PermissionLocked = (1 << 4),
|
||||
};
|
||||
|
||||
enum MemoryMapping : u32 {
|
||||
|
|
Loading…
Reference in a new issue