summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2018-12-14 15:30:02 -0500
committerGravatar GitHub2018-12-14 15:30:02 -0500
commit1a23970d172602497af57969824551e77ae9dfe7 (patch)
treeeb5c6849e4c83f70779b4f67ee6e1094421ac8e3 /src
parentMerge pull request #1871 from lioncash/move (diff)
parentsvc: Enable svcQueryProcessMemory (diff)
downloadyuzu-1a23970d172602497af57969824551e77ae9dfe7.tar.gz
yuzu-1a23970d172602497af57969824551e77ae9dfe7.tar.xz
yuzu-1a23970d172602497af57969824551e77ae9dfe7.zip
Merge pull request #1899 from lioncash/state
vm_manager/svc: Modify MemoryState enum, and correct error handling for svcQueryMemory
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/kernel/process.cpp2
-rw-r--r--src/core/hle/kernel/process.h3
-rw-r--r--src/core/hle/kernel/svc.cpp52
-rw-r--r--src/core/hle/kernel/svc.h16
-rw-r--r--src/core/hle/kernel/svc_wrap.h22
-rw-r--r--src/core/hle/kernel/vm_manager.cpp25
-rw-r--r--src/core/hle/kernel/vm_manager.h152
7 files changed, 188 insertions, 84 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) {
150 vm_manager 150 vm_manager
151 .MapMemoryBlock(vm_manager.GetTLSIORegionEndAddress() - stack_size, 151 .MapMemoryBlock(vm_manager.GetTLSIORegionEndAddress() - stack_size,
152 std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size, 152 std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size,
153 MemoryState::Mapped) 153 MemoryState::Stack)
154 .Unwrap(); 154 .Unwrap();
155 155
156 vm_manager.LogLayout(); 156 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:
262 ResultVal<VAddr> HeapAllocate(VAddr target, u64 size, VMAPermission perms); 262 ResultVal<VAddr> HeapAllocate(VAddr target, u64 size, VMAPermission perms);
263 ResultCode HeapFree(VAddr target, u32 size); 263 ResultCode HeapFree(VAddr target, u32 size);
264 264
265 ResultCode MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size, 265 ResultCode MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size, MemoryState state);
266 MemoryState state = MemoryState::Mapped);
267 266
268 ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size); 267 ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size);
269 268
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 8b0b3671a..5d36792ca 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -35,6 +35,7 @@
35#include "core/hle/lock.h" 35#include "core/hle/lock.h"
36#include "core/hle/result.h" 36#include "core/hle/result.h"
37#include "core/hle/service/service.h" 37#include "core/hle/service/service.h"
38#include "core/memory.h"
38 39
39namespace Kernel { 40namespace Kernel {
40namespace { 41namespace {
@@ -273,7 +274,7 @@ static ResultCode MapMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
273 return result; 274 return result;
274 } 275 }
275 276
276 return current_process->MirrorMemory(dst_addr, src_addr, size); 277 return current_process->MirrorMemory(dst_addr, src_addr, size, MemoryState::Stack);
277} 278}
278 279
279/// Unmaps a region that was previously mapped with svcMapMemory 280/// Unmaps a region that was previously mapped with svcMapMemory
@@ -1066,10 +1067,9 @@ static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64
1066 return shared_memory->Unmap(*current_process, addr); 1067 return shared_memory->Unmap(*current_process, addr);
1067} 1068}
1068 1069
1069/// Query process memory 1070static ResultCode QueryProcessMemory(VAddr memory_info_address, VAddr page_info_address,
1070static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* /*page_info*/, 1071 Handle process_handle, VAddr address) {
1071 Handle process_handle, u64 addr) { 1072 LOG_TRACE(Kernel_SVC, "called process=0x{:08X} address={:X}", process_handle, address);
1072 LOG_TRACE(Kernel_SVC, "called process=0x{:08X} addr={:X}", process_handle, addr);
1073 const auto& handle_table = Core::CurrentProcess()->GetHandleTable(); 1073 const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
1074 SharedPtr<Process> process = handle_table.Get<Process>(process_handle); 1074 SharedPtr<Process> process = handle_table.Get<Process>(process_handle);
1075 if (!process) { 1075 if (!process) {
@@ -1079,28 +1079,32 @@ static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* /*page_i
1079 } 1079 }
1080 1080
1081 const auto& vm_manager = process->VMManager(); 1081 const auto& vm_manager = process->VMManager();
1082 const auto vma = vm_manager.FindVMA(addr); 1082 const MemoryInfo memory_info = vm_manager.QueryMemory(address);
1083 1083
1084 memory_info->attributes = 0; 1084 Memory::Write64(memory_info_address, memory_info.base_address);
1085 if (vm_manager.IsValidHandle(vma)) { 1085 Memory::Write64(memory_info_address + 8, memory_info.size);
1086 memory_info->base_address = vma->second.base; 1086 Memory::Write32(memory_info_address + 16, memory_info.state);
1087 memory_info->permission = static_cast<u32>(vma->second.permissions); 1087 Memory::Write32(memory_info_address + 20, memory_info.attributes);
1088 memory_info->size = vma->second.size; 1088 Memory::Write32(memory_info_address + 24, memory_info.permission);
1089 memory_info->type = static_cast<u32>(vma->second.meminfo_state); 1089 Memory::Write32(memory_info_address + 32, memory_info.ipc_ref_count);
1090 } else { 1090 Memory::Write32(memory_info_address + 28, memory_info.device_ref_count);
1091 memory_info->base_address = 0; 1091 Memory::Write32(memory_info_address + 36, 0);
1092 memory_info->permission = static_cast<u32>(VMAPermission::None); 1092
1093 memory_info->size = 0; 1093 // Page info appears to be currently unused by the kernel and is always set to zero.
1094 memory_info->type = static_cast<u32>(MemoryState::Unmapped); 1094 Memory::Write32(page_info_address, 0);
1095 }
1096 1095
1097 return RESULT_SUCCESS; 1096 return RESULT_SUCCESS;
1098} 1097}
1099 1098
1100/// Query memory 1099static ResultCode QueryMemory(VAddr memory_info_address, VAddr page_info_address,
1101static ResultCode QueryMemory(MemoryInfo* memory_info, PageInfo* page_info, VAddr addr) { 1100 VAddr query_address) {
1102 LOG_TRACE(Kernel_SVC, "called, addr={:X}", addr); 1101 LOG_TRACE(Kernel_SVC,
1103 return QueryProcessMemory(memory_info, page_info, CurrentProcess, addr); 1102 "called, memory_info_address=0x{:016X}, page_info_address=0x{:016X}, "
1103 "query_address=0x{:016X}",
1104 memory_info_address, page_info_address, query_address);
1105
1106 return QueryProcessMemory(memory_info_address, page_info_address, CurrentProcess,
1107 query_address);
1104} 1108}
1105 1109
1106/// Exits the current process 1110/// Exits the current process
@@ -1907,7 +1911,7 @@ static const FunctionDef SVC_Table[] = {
1907 {0x73, nullptr, "SetProcessMemoryPermission"}, 1911 {0x73, nullptr, "SetProcessMemoryPermission"},
1908 {0x74, nullptr, "MapProcessMemory"}, 1912 {0x74, nullptr, "MapProcessMemory"},
1909 {0x75, nullptr, "UnmapProcessMemory"}, 1913 {0x75, nullptr, "UnmapProcessMemory"},
1910 {0x76, nullptr, "QueryProcessMemory"}, 1914 {0x76, SvcWrap<QueryProcessMemory>, "QueryProcessMemory"},
1911 {0x77, nullptr, "MapProcessCodeMemory"}, 1915 {0x77, nullptr, "MapProcessCodeMemory"},
1912 {0x78, nullptr, "UnmapProcessCodeMemory"}, 1916 {0x78, nullptr, "UnmapProcessCodeMemory"},
1913 {0x79, nullptr, "CreateProcess"}, 1917 {0x79, nullptr, "CreateProcess"},
diff --git a/src/core/hle/kernel/svc.h b/src/core/hle/kernel/svc.h
index b06aac4ec..c37ae0f98 100644
--- a/src/core/hle/kernel/svc.h
+++ b/src/core/hle/kernel/svc.h
@@ -8,22 +8,6 @@
8 8
9namespace Kernel { 9namespace Kernel {
10 10
11struct MemoryInfo {
12 u64 base_address;
13 u64 size;
14 u32 type;
15 u32 attributes;
16 u32 permission;
17 u32 device_refcount;
18 u32 ipc_refcount;
19 INSERT_PADDING_WORDS(1);
20};
21static_assert(sizeof(MemoryInfo) == 0x28, "MemoryInfo has incorrect size.");
22
23struct PageInfo {
24 u64 flags;
25};
26
27void CallSVC(u32 immediate); 11void CallSVC(u32 immediate);
28 12
29} // namespace Kernel 13} // namespace Kernel
diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h
index f38e0cb6f..2f758b959 100644
--- a/src/core/hle/kernel/svc_wrap.h
+++ b/src/core/hle/kernel/svc_wrap.h
@@ -7,9 +7,7 @@
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "core/arm/arm_interface.h" 8#include "core/arm/arm_interface.h"
9#include "core/core.h" 9#include "core/core.h"
10#include "core/hle/kernel/svc.h"
11#include "core/hle/result.h" 10#include "core/hle/result.h"
12#include "core/memory.h"
13 11
14namespace Kernel { 12namespace Kernel {
15 13
@@ -132,6 +130,11 @@ void SvcWrap() {
132 func(Param(0), Param(1), static_cast<u32>(Param(2)), static_cast<u32>(Param(3))).raw); 130 func(Param(0), Param(1), static_cast<u32>(Param(2)), static_cast<u32>(Param(3))).raw);
133} 131}
134 132
133template <ResultCode func(u64, u64, u32, u64)>
134void SvcWrap() {
135 FuncReturn(func(Param(0), Param(1), static_cast<u32>(Param(2)), Param(3)).raw);
136}
137
135template <ResultCode func(u32, u64, u32)> 138template <ResultCode func(u32, u64, u32)>
136void SvcWrap() { 139void SvcWrap() {
137 FuncReturn(func(static_cast<u32>(Param(0)), Param(1), static_cast<u32>(Param(2))).raw); 140 FuncReturn(func(static_cast<u32>(Param(0)), Param(1), static_cast<u32>(Param(2))).raw);
@@ -191,21 +194,6 @@ void SvcWrap() {
191 FuncReturn(retval); 194 FuncReturn(retval);
192} 195}
193 196
194template <ResultCode func(MemoryInfo*, PageInfo*, u64)>
195void SvcWrap() {
196 MemoryInfo memory_info = {};
197 PageInfo page_info = {};
198 u32 retval = func(&memory_info, &page_info, Param(2)).raw;
199
200 Memory::Write64(Param(0), memory_info.base_address);
201 Memory::Write64(Param(0) + 8, memory_info.size);
202 Memory::Write32(Param(0) + 16, memory_info.type);
203 Memory::Write32(Param(0) + 20, memory_info.attributes);
204 Memory::Write32(Param(0) + 24, memory_info.permission);
205
206 FuncReturn(retval);
207}
208
209template <ResultCode func(u32*, u64, u64, u32)> 197template <ResultCode func(u32*, u64, u64, u32)>
210void SvcWrap() { 198void SvcWrap() {
211 u32 param_1 = 0; 199 u32 param_1 = 0;
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index 6187993ce..d3b55a51e 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) {
25 "CodeMutable", "Heap", 25 "CodeMutable", "Heap",
26 "Shared", "Unknown1", 26 "Shared", "Unknown1",
27 "ModuleCodeStatic", "ModuleCodeMutable", 27 "ModuleCodeStatic", "ModuleCodeMutable",
28 "IpcBuffer0", "Mapped", 28 "IpcBuffer0", "Stack",
29 "ThreadLocal", "TransferMemoryIsolated", 29 "ThreadLocal", "TransferMemoryIsolated",
30 "TransferMemory", "ProcessMemory", 30 "TransferMemory", "ProcessMemory",
31 "Unknown2", "IpcBuffer1", 31 "Inaccessible", "IpcBuffer1",
32 "IpcBuffer3", "KernelStack", 32 "IpcBuffer3", "KernelStack",
33 }; 33 };
34 34
35 return names[static_cast<int>(state)]; 35 return names[ToSvcMemoryState(state)];
36} 36}
37 37
38bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const { 38bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const {
@@ -302,6 +302,25 @@ ResultCode VMManager::HeapFree(VAddr target, u64 size) {
302 return RESULT_SUCCESS; 302 return RESULT_SUCCESS;
303} 303}
304 304
305MemoryInfo VMManager::QueryMemory(VAddr address) const {
306 const auto vma = FindVMA(address);
307 MemoryInfo memory_info{};
308
309 if (IsValidHandle(vma)) {
310 memory_info.base_address = vma->second.base;
311 memory_info.permission = static_cast<u32>(vma->second.permissions);
312 memory_info.size = vma->second.size;
313 memory_info.state = ToSvcMemoryState(vma->second.meminfo_state);
314 } else {
315 memory_info.base_address = address_space_end;
316 memory_info.permission = static_cast<u32>(VMAPermission::None);
317 memory_info.size = 0 - address_space_end;
318 memory_info.state = static_cast<u32>(MemoryState::Inaccessible);
319 }
320
321 return memory_info;
322}
323
305ResultCode VMManager::MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size, MemoryState state) { 324ResultCode VMManager::MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size, MemoryState state) {
306 const auto vma = FindVMA(src_addr); 325 const auto vma = FindVMA(src_addr);
307 326
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h
index a12419d1e..10bacac3e 100644
--- a/src/core/hle/kernel/vm_manager.h
+++ b/src/core/hle/kernel/vm_manager.h
@@ -43,26 +43,129 @@ enum class VMAPermission : u8 {
43 ReadWriteExecute = Read | Write | Execute, 43 ReadWriteExecute = Read | Write | Execute,
44}; 44};
45 45
46/// Set of values returned in MemoryInfo.state by svcQueryMemory. 46// clang-format off
47/// Represents memory states and any relevant flags, as used by the kernel.
48/// svcQueryMemory interprets these by masking away all but the first eight
49/// bits when storing memory state into a MemoryInfo instance.
47enum class MemoryState : u32 { 50enum class MemoryState : u32 {
48 Unmapped = 0x0, 51 Mask = 0xFF,
49 Io = 0x1, 52 FlagProtect = 1U << 8,
50 Normal = 0x2, 53 FlagDebug = 1U << 9,
51 CodeStatic = 0x3, 54 FlagIPC0 = 1U << 10,
52 CodeMutable = 0x4, 55 FlagIPC3 = 1U << 11,
53 Heap = 0x5, 56 FlagIPC1 = 1U << 12,
54 Shared = 0x6, 57 FlagMapped = 1U << 13,
55 ModuleCodeStatic = 0x8, 58 FlagCode = 1U << 14,
56 ModuleCodeMutable = 0x9, 59 FlagAlias = 1U << 15,
57 IpcBuffer0 = 0xA, 60 FlagModule = 1U << 16,
58 Mapped = 0xB, 61 FlagTransfer = 1U << 17,
59 ThreadLocal = 0xC, 62 FlagQueryPhysicalAddressAllowed = 1U << 18,
60 TransferMemoryIsolated = 0xD, 63 FlagSharedDevice = 1U << 19,
61 TransferMemory = 0xE, 64 FlagSharedDeviceAligned = 1U << 20,
62 ProcessMemory = 0xF, 65 FlagIPCBuffer = 1U << 21,
63 IpcBuffer1 = 0x11, 66 FlagMemoryPoolAllocated = 1U << 22,
64 IpcBuffer3 = 0x12, 67 FlagMapProcess = 1U << 23,
65 KernelStack = 0x13, 68 FlagUncached = 1U << 24,
69 FlagCodeMemory = 1U << 25,
70
71 // Convenience flag sets to reduce repetition
72 IPCFlags = FlagIPC0 | FlagIPC3 | FlagIPC1,
73
74 CodeFlags = FlagDebug | IPCFlags | FlagMapped | FlagCode | FlagQueryPhysicalAddressAllowed |
75 FlagSharedDevice | FlagSharedDeviceAligned | FlagMemoryPoolAllocated,
76
77 DataFlags = FlagProtect | IPCFlags | FlagMapped | FlagAlias | FlagTransfer |
78 FlagQueryPhysicalAddressAllowed | FlagSharedDevice | FlagSharedDeviceAligned |
79 FlagMemoryPoolAllocated | FlagIPCBuffer | FlagUncached,
80
81 Unmapped = 0x00,
82 Io = 0x01 | FlagMapped,
83 Normal = 0x02 | FlagMapped | FlagQueryPhysicalAddressAllowed,
84 CodeStatic = 0x03 | CodeFlags | FlagMapProcess,
85 CodeMutable = 0x04 | CodeFlags | FlagMapProcess | FlagCodeMemory,
86 Heap = 0x05 | DataFlags | FlagCodeMemory,
87 Shared = 0x06 | FlagMapped | FlagMemoryPoolAllocated,
88 ModuleCodeStatic = 0x08 | CodeFlags | FlagModule | FlagMapProcess,
89 ModuleCodeMutable = 0x09 | DataFlags | FlagModule | FlagMapProcess | FlagCodeMemory,
90
91 IpcBuffer0 = 0x0A | FlagMapped | FlagQueryPhysicalAddressAllowed | FlagMemoryPoolAllocated |
92 IPCFlags | FlagSharedDevice | FlagSharedDeviceAligned,
93
94 Stack = 0x0B | FlagMapped | IPCFlags | FlagQueryPhysicalAddressAllowed |
95 FlagSharedDevice | FlagSharedDeviceAligned | FlagMemoryPoolAllocated,
96
97 ThreadLocal = 0x0C | FlagMapped | FlagMemoryPoolAllocated,
98
99 TransferMemoryIsolated = 0x0D | IPCFlags | FlagMapped | FlagQueryPhysicalAddressAllowed |
100 FlagSharedDevice | FlagSharedDeviceAligned | FlagMemoryPoolAllocated |
101 FlagUncached,
102
103 TransferMemory = 0x0E | FlagIPC3 | FlagIPC1 | FlagMapped | FlagQueryPhysicalAddressAllowed |
104 FlagSharedDevice | FlagSharedDeviceAligned | FlagMemoryPoolAllocated,
105
106 ProcessMemory = 0x0F | FlagIPC3 | FlagIPC1 | FlagMapped | FlagMemoryPoolAllocated,
107
108 // Used to signify an inaccessible or invalid memory region with memory queries
109 Inaccessible = 0x10,
110
111 IpcBuffer1 = 0x11 | FlagIPC3 | FlagIPC1 | FlagMapped | FlagQueryPhysicalAddressAllowed |
112 FlagSharedDevice | FlagSharedDeviceAligned | FlagMemoryPoolAllocated,
113
114 IpcBuffer3 = 0x12 | FlagIPC3 | FlagMapped | FlagQueryPhysicalAddressAllowed |
115 FlagSharedDeviceAligned | FlagMemoryPoolAllocated,
116
117 KernelStack = 0x13 | FlagMapped,
118};
119// clang-format on
120
121constexpr MemoryState operator|(MemoryState lhs, MemoryState rhs) {
122 return static_cast<MemoryState>(u32(lhs) | u32(rhs));
123}
124
125constexpr MemoryState operator&(MemoryState lhs, MemoryState rhs) {
126 return static_cast<MemoryState>(u32(lhs) & u32(rhs));
127}
128
129constexpr MemoryState operator^(MemoryState lhs, MemoryState rhs) {
130 return static_cast<MemoryState>(u32(lhs) ^ u32(rhs));
131}
132
133constexpr MemoryState operator~(MemoryState lhs) {
134 return static_cast<MemoryState>(~u32(lhs));
135}
136
137constexpr MemoryState& operator|=(MemoryState& lhs, MemoryState rhs) {
138 lhs = lhs | rhs;
139 return lhs;
140}
141
142constexpr MemoryState& operator&=(MemoryState& lhs, MemoryState rhs) {
143 lhs = lhs & rhs;
144 return lhs;
145}
146
147constexpr MemoryState& operator^=(MemoryState& lhs, MemoryState rhs) {
148 lhs = lhs ^ rhs;
149 return lhs;
150}
151
152constexpr u32 ToSvcMemoryState(MemoryState state) {
153 return static_cast<u32>(state & MemoryState::Mask);
154}
155
156struct MemoryInfo {
157 u64 base_address;
158 u64 size;
159 u32 state;
160 u32 attributes;
161 u32 permission;
162 u32 ipc_ref_count;
163 u32 device_ref_count;
164};
165static_assert(sizeof(MemoryInfo) == 0x28, "MemoryInfo has incorrect size.");
166
167struct PageInfo {
168 u32 flags;
66}; 169};
67 170
68/** 171/**
@@ -186,8 +289,15 @@ public:
186 ResultVal<VAddr> HeapAllocate(VAddr target, u64 size, VMAPermission perms); 289 ResultVal<VAddr> HeapAllocate(VAddr target, u64 size, VMAPermission perms);
187 ResultCode HeapFree(VAddr target, u64 size); 290 ResultCode HeapFree(VAddr target, u64 size);
188 291
189 ResultCode MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size, 292 ResultCode MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size, MemoryState state);
190 MemoryState state = MemoryState::Mapped); 293
294 /// Queries the memory manager for information about the given address.
295 ///
296 /// @param address The address to query the memory manager about for information.
297 ///
298 /// @return A MemoryInfo instance containing information about the given address.
299 ///
300 MemoryInfo QueryMemory(VAddr address) const;
191 301
192 /** 302 /**
193 * Scans all VMAs and updates the page table range of any that use the given vector as backing 303 * Scans all VMAs and updates the page table range of any that use the given vector as backing