From 366985ca925c28867b4cdf847db978acd6c2db1e Mon Sep 17 00:00:00 2001 From: Lioncash Date: Wed, 12 Dec 2018 10:08:46 -0500 Subject: [PATCH] vm_manager: Amend MemoryState enum members Amends the MemoryState enum to use the same values like the actual kernel does. Also provides the necessary operators to operate on them. This will be necessary in the future for implementing svcSetMemoryAttribute, as memory block state is checked before applying the attribute. --- src/core/hle/kernel/process.cpp | 2 +- src/core/hle/kernel/process.h | 3 +- src/core/hle/kernel/svc.cpp | 4 +- src/core/hle/kernel/vm_manager.cpp | 4 +- src/core/hle/kernel/vm_manager.h | 126 ++++++++++++++++++++++++----- 5 files changed, 111 insertions(+), 28 deletions(-) diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index c817fb449..5356a4a3f 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -150,7 +150,7 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) { vm_manager .MapMemoryBlock(vm_manager.GetTLSIORegionEndAddress() - stack_size, std::make_shared>(stack_size, 0), 0, stack_size, - MemoryState::Mapped) + MemoryState::Stack) .Unwrap(); vm_manager.LogLayout(); diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index bcb9ac4b8..459eedfa6 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h @@ -262,8 +262,7 @@ public: ResultVal HeapAllocate(VAddr target, u64 size, VMAPermission perms); ResultCode HeapFree(VAddr target, u32 size); - ResultCode MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size, - MemoryState state = MemoryState::Mapped); + ResultCode MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size, MemoryState state); ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size); diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index f43c7201c..4ae92ff9e 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -273,7 +273,7 @@ static ResultCode MapMemory(VAddr dst_addr, VAddr src_addr, u64 size) { return result; } - return current_process->MirrorMemory(dst_addr, src_addr, size); + return current_process->MirrorMemory(dst_addr, src_addr, size, MemoryState::Stack); } /// Unmaps a region that was previously mapped with svcMapMemory @@ -1086,7 +1086,7 @@ static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* /*page_i memory_info->base_address = vma->second.base; memory_info->permission = static_cast(vma->second.permissions); memory_info->size = vma->second.size; - memory_info->type = static_cast(vma->second.meminfo_state); + memory_info->type = ToSvcMemoryState(vma->second.meminfo_state); } else { memory_info->base_address = 0; memory_info->permission = static_cast(VMAPermission::None); diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index 6187993ce..e0f204b0b 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp @@ -25,14 +25,14 @@ static const char* GetMemoryStateName(MemoryState state) { "CodeMutable", "Heap", "Shared", "Unknown1", "ModuleCodeStatic", "ModuleCodeMutable", - "IpcBuffer0", "Mapped", + "IpcBuffer0", "Stack", "ThreadLocal", "TransferMemoryIsolated", "TransferMemory", "ProcessMemory", "Unknown2", "IpcBuffer1", "IpcBuffer3", "KernelStack", }; - return names[static_cast(state)]; + return names[ToSvcMemoryState(state)]; } bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const { diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h index a12419d1e..0a600c23c 100644 --- a/src/core/hle/kernel/vm_manager.h +++ b/src/core/hle/kernel/vm_manager.h @@ -43,27 +43,112 @@ enum class VMAPermission : u8 { ReadWriteExecute = Read | Write | Execute, }; -/// Set of values returned in MemoryInfo.state by svcQueryMemory. +// clang-format off +/// Represents memory states and any relevant flags, as used by the kernel. +/// svcQueryMemory interprets these by masking away all but the first eight +/// bits when storing memory state into a MemoryInfo instance. enum class MemoryState : u32 { - Unmapped = 0x0, - Io = 0x1, - Normal = 0x2, - CodeStatic = 0x3, - CodeMutable = 0x4, - Heap = 0x5, - Shared = 0x6, - ModuleCodeStatic = 0x8, - ModuleCodeMutable = 0x9, - IpcBuffer0 = 0xA, - Mapped = 0xB, - ThreadLocal = 0xC, - TransferMemoryIsolated = 0xD, - TransferMemory = 0xE, - ProcessMemory = 0xF, - IpcBuffer1 = 0x11, - IpcBuffer3 = 0x12, - KernelStack = 0x13, + Mask = 0xFF, + FlagProtect = 1U << 8, + FlagDebug = 1U << 9, + FlagIPC0 = 1U << 10, + FlagIPC3 = 1U << 11, + FlagIPC1 = 1U << 12, + FlagMapped = 1U << 13, + FlagCode = 1U << 14, + FlagAlias = 1U << 15, + FlagModule = 1U << 16, + FlagTransfer = 1U << 17, + FlagQueryPhysicalAddressAllowed = 1U << 18, + FlagSharedDevice = 1U << 19, + FlagSharedDeviceAligned = 1U << 20, + FlagIPCBuffer = 1U << 21, + FlagMemoryPoolAllocated = 1U << 22, + FlagMapProcess = 1U << 23, + FlagUncached = 1U << 24, + FlagCodeMemory = 1U << 25, + + // Convenience flag sets to reduce repetition + IPCFlags = FlagIPC0 | FlagIPC3 | FlagIPC1, + + CodeFlags = FlagDebug | IPCFlags | FlagMapped | FlagCode | FlagQueryPhysicalAddressAllowed | + FlagSharedDevice | FlagSharedDeviceAligned | FlagMemoryPoolAllocated, + + DataFlags = FlagProtect | IPCFlags | FlagMapped | FlagAlias | FlagTransfer | + FlagQueryPhysicalAddressAllowed | FlagSharedDevice | FlagSharedDeviceAligned | + FlagMemoryPoolAllocated | FlagIPCBuffer | FlagUncached, + + Unmapped = 0x00, + Io = 0x01 | FlagMapped, + Normal = 0x02 | FlagMapped | FlagQueryPhysicalAddressAllowed, + CodeStatic = 0x03 | CodeFlags | FlagMapProcess, + CodeMutable = 0x04 | CodeFlags | FlagMapProcess | FlagCodeMemory, + Heap = 0x05 | DataFlags | FlagCodeMemory, + Shared = 0x06 | FlagMapped | FlagMemoryPoolAllocated, + ModuleCodeStatic = 0x08 | CodeFlags | FlagModule | FlagMapProcess, + ModuleCodeMutable = 0x09 | DataFlags | FlagModule | FlagMapProcess | FlagCodeMemory, + + IpcBuffer0 = 0x0A | FlagMapped | FlagQueryPhysicalAddressAllowed | FlagMemoryPoolAllocated | + IPCFlags | FlagSharedDevice | FlagSharedDeviceAligned, + + Stack = 0x0B | FlagMapped | IPCFlags | FlagQueryPhysicalAddressAllowed | + FlagSharedDevice | FlagSharedDeviceAligned | FlagMemoryPoolAllocated, + + ThreadLocal = 0x0C | FlagMapped | FlagMemoryPoolAllocated, + + TransferMemoryIsolated = 0x0D | IPCFlags | FlagMapped | FlagQueryPhysicalAddressAllowed | + FlagSharedDevice | FlagSharedDeviceAligned | FlagMemoryPoolAllocated | + FlagUncached, + + TransferMemory = 0x0E | FlagIPC3 | FlagIPC1 | FlagMapped | FlagQueryPhysicalAddressAllowed | + FlagSharedDevice | FlagSharedDeviceAligned | FlagMemoryPoolAllocated, + + ProcessMemory = 0x0F | FlagIPC3 | FlagIPC1 | FlagMapped | FlagMemoryPoolAllocated, + + IpcBuffer1 = 0x11 | FlagIPC3 | FlagIPC1 | FlagMapped | FlagQueryPhysicalAddressAllowed | + FlagSharedDevice | FlagSharedDeviceAligned | FlagMemoryPoolAllocated, + + IpcBuffer3 = 0x12 | FlagIPC3 | FlagMapped | FlagQueryPhysicalAddressAllowed | + FlagSharedDeviceAligned | FlagMemoryPoolAllocated, + + KernelStack = 0x13 | FlagMapped, }; +// clang-format on + +constexpr MemoryState operator|(MemoryState lhs, MemoryState rhs) { + return static_cast(u32(lhs) | u32(rhs)); +} + +constexpr MemoryState operator&(MemoryState lhs, MemoryState rhs) { + return static_cast(u32(lhs) & u32(rhs)); +} + +constexpr MemoryState operator^(MemoryState lhs, MemoryState rhs) { + return static_cast(u32(lhs) ^ u32(rhs)); +} + +constexpr MemoryState operator~(MemoryState lhs) { + return static_cast(~u32(lhs)); +} + +constexpr MemoryState& operator|=(MemoryState& lhs, MemoryState rhs) { + lhs = lhs | rhs; + return lhs; +} + +constexpr MemoryState& operator&=(MemoryState& lhs, MemoryState rhs) { + lhs = lhs & rhs; + return lhs; +} + +constexpr MemoryState& operator^=(MemoryState& lhs, MemoryState rhs) { + lhs = lhs ^ rhs; + return lhs; +} + +constexpr u32 ToSvcMemoryState(MemoryState state) { + return static_cast(state & MemoryState::Mask); +} /** * Represents a VMA in an address space. A VMA is a contiguous region of virtual addressing space @@ -186,8 +271,7 @@ public: ResultVal HeapAllocate(VAddr target, u64 size, VMAPermission perms); ResultCode HeapFree(VAddr target, u64 size); - ResultCode MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size, - MemoryState state = MemoryState::Mapped); + ResultCode MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size, MemoryState state); /** * Scans all VMAs and updates the page table range of any that use the given vector as backing