summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/svc.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2020-04-17 16:33:08 -0400
committerGravatar GitHub2020-04-17 16:33:08 -0400
commitb8f5c71f2d7f819821acf036175cce65ab1ae12c (patch)
tree151d7ed4e47536dc0e149a7117387b6a502d7da6 /src/core/hle/kernel/svc.cpp
parentMerge pull request #3682 from lioncash/uam (diff)
parentcore: hle: Address various feedback & code cleanup. (diff)
downloadyuzu-b8f5c71f2d7f819821acf036175cce65ab1ae12c.tar.gz
yuzu-b8f5c71f2d7f819821acf036175cce65ab1ae12c.tar.xz
yuzu-b8f5c71f2d7f819821acf036175cce65ab1ae12c.zip
Merge pull request #3666 from bunnei/new-vmm
Implement a new virtual memory manager
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
-rw-r--r--src/core/hle/kernel/svc.cpp621
1 files changed, 125 insertions, 496 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 4ffc113c2..4134acf65 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -24,6 +24,8 @@
24#include "core/hle/kernel/errors.h" 24#include "core/hle/kernel/errors.h"
25#include "core/hle/kernel/handle_table.h" 25#include "core/hle/kernel/handle_table.h"
26#include "core/hle/kernel/kernel.h" 26#include "core/hle/kernel/kernel.h"
27#include "core/hle/kernel/memory/memory_block.h"
28#include "core/hle/kernel/memory/page_table.h"
27#include "core/hle/kernel/mutex.h" 29#include "core/hle/kernel/mutex.h"
28#include "core/hle/kernel/process.h" 30#include "core/hle/kernel/process.h"
29#include "core/hle/kernel/readable_event.h" 31#include "core/hle/kernel/readable_event.h"
@@ -31,6 +33,7 @@
31#include "core/hle/kernel/scheduler.h" 33#include "core/hle/kernel/scheduler.h"
32#include "core/hle/kernel/shared_memory.h" 34#include "core/hle/kernel/shared_memory.h"
33#include "core/hle/kernel/svc.h" 35#include "core/hle/kernel/svc.h"
36#include "core/hle/kernel/svc_types.h"
34#include "core/hle/kernel/svc_wrap.h" 37#include "core/hle/kernel/svc_wrap.h"
35#include "core/hle/kernel/synchronization.h" 38#include "core/hle/kernel/synchronization.h"
36#include "core/hle/kernel/thread.h" 39#include "core/hle/kernel/thread.h"
@@ -42,7 +45,7 @@
42#include "core/memory.h" 45#include "core/memory.h"
43#include "core/reporter.h" 46#include "core/reporter.h"
44 47
45namespace Kernel { 48namespace Kernel::Svc {
46namespace { 49namespace {
47 50
48// Checks if address + size is greater than the given address 51// Checks if address + size is greater than the given address
@@ -58,8 +61,8 @@ constexpr u64 MAIN_MEMORY_SIZE = 0x200000000;
58// Helper function that performs the common sanity checks for svcMapMemory 61// Helper function that performs the common sanity checks for svcMapMemory
59// and svcUnmapMemory. This is doable, as both functions perform their sanitizing 62// and svcUnmapMemory. This is doable, as both functions perform their sanitizing
60// in the same order. 63// in the same order.
61ResultCode MapUnmapMemorySanityChecks(const VMManager& vm_manager, VAddr dst_addr, VAddr src_addr, 64ResultCode MapUnmapMemorySanityChecks(const Memory::PageTable& manager, VAddr dst_addr,
62 u64 size) { 65 VAddr src_addr, u64 size) {
63 if (!Common::Is4KBAligned(dst_addr)) { 66 if (!Common::Is4KBAligned(dst_addr)) {
64 LOG_ERROR(Kernel_SVC, "Destination address is not aligned to 4KB, 0x{:016X}", dst_addr); 67 LOG_ERROR(Kernel_SVC, "Destination address is not aligned to 4KB, 0x{:016X}", dst_addr);
65 return ERR_INVALID_ADDRESS; 68 return ERR_INVALID_ADDRESS;
@@ -93,36 +96,33 @@ ResultCode MapUnmapMemorySanityChecks(const VMManager& vm_manager, VAddr dst_add
93 return ERR_INVALID_ADDRESS_STATE; 96 return ERR_INVALID_ADDRESS_STATE;
94 } 97 }
95 98
96 if (!vm_manager.IsWithinAddressSpace(src_addr, size)) { 99 if (!manager.IsInsideAddressSpace(src_addr, size)) {
97 LOG_ERROR(Kernel_SVC, 100 LOG_ERROR(Kernel_SVC,
98 "Source is not within the address space, addr=0x{:016X}, size=0x{:016X}", 101 "Source is not within the address space, addr=0x{:016X}, size=0x{:016X}",
99 src_addr, size); 102 src_addr, size);
100 return ERR_INVALID_ADDRESS_STATE; 103 return ERR_INVALID_ADDRESS_STATE;
101 } 104 }
102 105
103 if (!vm_manager.IsWithinStackRegion(dst_addr, size)) { 106 if (manager.IsOutsideStackRegion(dst_addr, size)) {
104 LOG_ERROR(Kernel_SVC, 107 LOG_ERROR(Kernel_SVC,
105 "Destination is not within the stack region, addr=0x{:016X}, size=0x{:016X}", 108 "Destination is not within the stack region, addr=0x{:016X}, size=0x{:016X}",
106 dst_addr, size); 109 dst_addr, size);
107 return ERR_INVALID_MEMORY_RANGE; 110 return ERR_INVALID_MEMORY_RANGE;
108 } 111 }
109 112
110 const VAddr dst_end_address = dst_addr + size; 113 if (manager.IsInsideHeapRegion(dst_addr, size)) {
111 if (dst_end_address > vm_manager.GetHeapRegionBaseAddress() &&
112 vm_manager.GetHeapRegionEndAddress() > dst_addr) {
113 LOG_ERROR(Kernel_SVC, 114 LOG_ERROR(Kernel_SVC,
114 "Destination does not fit within the heap region, addr=0x{:016X}, " 115 "Destination does not fit within the heap region, addr=0x{:016X}, "
115 "size=0x{:016X}, end_addr=0x{:016X}", 116 "size=0x{:016X}",
116 dst_addr, size, dst_end_address); 117 dst_addr, size);
117 return ERR_INVALID_MEMORY_RANGE; 118 return ERR_INVALID_MEMORY_RANGE;
118 } 119 }
119 120
120 if (dst_end_address > vm_manager.GetMapRegionBaseAddress() && 121 if (manager.IsInsideAliasRegion(dst_addr, size)) {
121 vm_manager.GetMapRegionEndAddress() > dst_addr) {
122 LOG_ERROR(Kernel_SVC, 122 LOG_ERROR(Kernel_SVC,
123 "Destination does not fit within the map region, addr=0x{:016X}, " 123 "Destination does not fit within the map region, addr=0x{:016X}, "
124 "size=0x{:016X}, end_addr=0x{:016X}", 124 "size=0x{:016X}",
125 dst_addr, size, dst_end_address); 125 dst_addr, size);
126 return ERR_INVALID_MEMORY_RANGE; 126 return ERR_INVALID_MEMORY_RANGE;
127 } 127 }
128 128
@@ -177,13 +177,10 @@ static ResultCode SetHeapSize(Core::System& system, VAddr* heap_addr, u64 heap_s
177 return ERR_INVALID_SIZE; 177 return ERR_INVALID_SIZE;
178 } 178 }
179 179
180 auto& vm_manager = system.Kernel().CurrentProcess()->VMManager(); 180 auto& page_table{system.Kernel().CurrentProcess()->PageTable()};
181 const auto alloc_result = vm_manager.SetHeapSize(heap_size); 181
182 if (alloc_result.Failed()) { 182 CASCADE_RESULT(*heap_addr, page_table.SetHeapSize(heap_size));
183 return alloc_result.Code();
184 }
185 183
186 *heap_addr = *alloc_result;
187 return RESULT_SUCCESS; 184 return RESULT_SUCCESS;
188} 185}
189 186
@@ -194,63 +191,6 @@ static ResultCode SetHeapSize32(Core::System& system, u32* heap_addr, u32 heap_s
194 return result; 191 return result;
195} 192}
196 193
197static ResultCode SetMemoryPermission(Core::System& system, VAddr addr, u64 size, u32 prot) {
198 LOG_TRACE(Kernel_SVC, "called, addr=0x{:X}, size=0x{:X}, prot=0x{:X}", addr, size, prot);
199
200 if (!Common::Is4KBAligned(addr)) {
201 LOG_ERROR(Kernel_SVC, "Address is not aligned to 4KB, addr=0x{:016X}", addr);
202 return ERR_INVALID_ADDRESS;
203 }
204
205 if (size == 0) {
206 LOG_ERROR(Kernel_SVC, "Size is 0");
207 return ERR_INVALID_SIZE;
208 }
209
210 if (!Common::Is4KBAligned(size)) {
211 LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, size=0x{:016X}", size);
212 return ERR_INVALID_SIZE;
213 }
214
215 if (!IsValidAddressRange(addr, size)) {
216 LOG_ERROR(Kernel_SVC, "Region is not a valid address range, addr=0x{:016X}, size=0x{:016X}",
217 addr, size);
218 return ERR_INVALID_ADDRESS_STATE;
219 }
220
221 const auto permission = static_cast<MemoryPermission>(prot);
222 if (permission != MemoryPermission::None && permission != MemoryPermission::Read &&
223 permission != MemoryPermission::ReadWrite) {
224 LOG_ERROR(Kernel_SVC, "Invalid memory permission specified, Got memory permission=0x{:08X}",
225 static_cast<u32>(permission));
226 return ERR_INVALID_MEMORY_PERMISSIONS;
227 }
228
229 auto* const current_process = system.Kernel().CurrentProcess();
230 auto& vm_manager = current_process->VMManager();
231
232 if (!vm_manager.IsWithinAddressSpace(addr, size)) {
233 LOG_ERROR(Kernel_SVC,
234 "Source is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr,
235 size);
236 return ERR_INVALID_ADDRESS_STATE;
237 }
238
239 const VMManager::VMAHandle iter = vm_manager.FindVMA(addr);
240 if (!vm_manager.IsValidHandle(iter)) {
241 LOG_ERROR(Kernel_SVC, "Unable to find VMA for address=0x{:016X}", addr);
242 return ERR_INVALID_ADDRESS_STATE;
243 }
244
245 LOG_WARNING(Kernel_SVC, "Uniformity check on protected memory is not implemented.");
246 // TODO: Performs a uniformity check to make sure only protected memory is changed (it doesn't
247 // make sense to allow changing permissions on kernel memory itself, etc).
248
249 const auto converted_permissions = SharedMemory::ConvertPermissions(permission);
250
251 return vm_manager.ReprotectRange(addr, size, converted_permissions);
252}
253
254static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mask, 194static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mask,
255 u32 attribute) { 195 u32 attribute) {
256 LOG_DEBUG(Kernel_SVC, 196 LOG_DEBUG(Kernel_SVC,
@@ -274,30 +214,19 @@ static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 si
274 return ERR_INVALID_ADDRESS_STATE; 214 return ERR_INVALID_ADDRESS_STATE;
275 } 215 }
276 216
277 const auto mem_attribute = static_cast<MemoryAttribute>(attribute); 217 const auto attributes{static_cast<Memory::MemoryAttribute>(mask | attribute)};
278 const auto mem_mask = static_cast<MemoryAttribute>(mask); 218 if (attributes != static_cast<Memory::MemoryAttribute>(mask) ||
279 const auto attribute_with_mask = mem_attribute | mem_mask; 219 (attributes | Memory::MemoryAttribute::Uncached) != Memory::MemoryAttribute::Uncached) {
280
281 if (attribute_with_mask != mem_mask) {
282 LOG_ERROR(Kernel_SVC, 220 LOG_ERROR(Kernel_SVC,
283 "Memory attribute doesn't match the given mask (Attribute: 0x{:X}, Mask: {:X}", 221 "Memory attribute doesn't match the given mask (Attribute: 0x{:X}, Mask: {:X}",
284 attribute, mask); 222 attribute, mask);
285 return ERR_INVALID_COMBINATION; 223 return ERR_INVALID_COMBINATION;
286 } 224 }
287 225
288 if ((attribute_with_mask | MemoryAttribute::Uncached) != MemoryAttribute::Uncached) { 226 auto& page_table{system.Kernel().CurrentProcess()->PageTable()};
289 LOG_ERROR(Kernel_SVC, "Specified attribute isn't equal to MemoryAttributeUncached (8).");
290 return ERR_INVALID_COMBINATION;
291 }
292
293 auto& vm_manager = system.Kernel().CurrentProcess()->VMManager();
294 if (!vm_manager.IsWithinAddressSpace(address, size)) {
295 LOG_ERROR(Kernel_SVC,
296 "Given address (0x{:016X}) is outside the bounds of the address space.", address);
297 return ERR_INVALID_ADDRESS_STATE;
298 }
299 227
300 return vm_manager.SetMemoryAttribute(address, size, mem_mask, mem_attribute); 228 return page_table.SetMemoryAttribute(address, size, static_cast<Memory::MemoryAttribute>(mask),
229 static_cast<Memory::MemoryAttribute>(attribute));
301} 230}
302 231
303/// Maps a memory range into a different range. 232/// Maps a memory range into a different range.
@@ -305,14 +234,14 @@ static ResultCode MapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr
305 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, 234 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
306 src_addr, size); 235 src_addr, size);
307 236
308 auto& vm_manager = system.Kernel().CurrentProcess()->VMManager(); 237 auto& page_table{system.Kernel().CurrentProcess()->PageTable()};
309 const auto result = MapUnmapMemorySanityChecks(vm_manager, dst_addr, src_addr, size);
310 238
311 if (result.IsError()) { 239 if (const ResultCode result{MapUnmapMemorySanityChecks(page_table, dst_addr, src_addr, size)};
240 result.IsError()) {
312 return result; 241 return result;
313 } 242 }
314 243
315 return vm_manager.MirrorMemory(dst_addr, src_addr, size, MemoryState::Stack); 244 return page_table.Map(dst_addr, src_addr, size);
316} 245}
317 246
318/// Unmaps a region that was previously mapped with svcMapMemory 247/// Unmaps a region that was previously mapped with svcMapMemory
@@ -320,21 +249,14 @@ static ResultCode UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_ad
320 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, 249 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
321 src_addr, size); 250 src_addr, size);
322 251
323 auto& vm_manager = system.Kernel().CurrentProcess()->VMManager(); 252 auto& page_table{system.Kernel().CurrentProcess()->PageTable()};
324 const auto result = MapUnmapMemorySanityChecks(vm_manager, dst_addr, src_addr, size);
325 253
326 if (result.IsError()) { 254 if (const ResultCode result{MapUnmapMemorySanityChecks(page_table, dst_addr, src_addr, size)};
255 result.IsError()) {
327 return result; 256 return result;
328 } 257 }
329 258
330 const auto unmap_res = vm_manager.UnmapRange(dst_addr, size); 259 return page_table.Unmap(dst_addr, src_addr, size);
331
332 // Reprotect the source mapping on success
333 if (unmap_res.IsSuccess()) {
334 ASSERT(vm_manager.ReprotectRange(src_addr, size, VMAPermission::ReadWrite).IsSuccess());
335 }
336
337 return unmap_res;
338} 260}
339 261
340/// Connect to an OS service given the port name, returns the handle to the port to out 262/// Connect to an OS service given the port name, returns the handle to the port to out
@@ -367,6 +289,8 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle,
367 return ERR_NOT_FOUND; 289 return ERR_NOT_FOUND;
368 } 290 }
369 291
292 ASSERT(kernel.CurrentProcess()->GetResourceLimit()->Reserve(ResourceType::Sessions, 1));
293
370 auto client_port = it->second; 294 auto client_port = it->second;
371 295
372 std::shared_ptr<ClientSession> client_session; 296 std::shared_ptr<ClientSession> client_session;
@@ -538,7 +462,7 @@ static ResultCode ArbitrateLock(Core::System& system, Handle holding_thread_hand
538 "requesting_current_thread_handle=0x{:08X}", 462 "requesting_current_thread_handle=0x{:08X}",
539 holding_thread_handle, mutex_addr, requesting_thread_handle); 463 holding_thread_handle, mutex_addr, requesting_thread_handle);
540 464
541 if (Memory::IsKernelVirtualAddress(mutex_addr)) { 465 if (Core::Memory::IsKernelVirtualAddress(mutex_addr)) {
542 LOG_ERROR(Kernel_SVC, "Mutex Address is a kernel virtual address, mutex_addr={:016X}", 466 LOG_ERROR(Kernel_SVC, "Mutex Address is a kernel virtual address, mutex_addr={:016X}",
543 mutex_addr); 467 mutex_addr);
544 return ERR_INVALID_ADDRESS_STATE; 468 return ERR_INVALID_ADDRESS_STATE;
@@ -558,7 +482,7 @@ static ResultCode ArbitrateLock(Core::System& system, Handle holding_thread_hand
558static ResultCode ArbitrateUnlock(Core::System& system, VAddr mutex_addr) { 482static ResultCode ArbitrateUnlock(Core::System& system, VAddr mutex_addr) {
559 LOG_TRACE(Kernel_SVC, "called mutex_addr=0x{:X}", mutex_addr); 483 LOG_TRACE(Kernel_SVC, "called mutex_addr=0x{:X}", mutex_addr);
560 484
561 if (Memory::IsKernelVirtualAddress(mutex_addr)) { 485 if (Core::Memory::IsKernelVirtualAddress(mutex_addr)) {
562 LOG_ERROR(Kernel_SVC, "Mutex Address is a kernel virtual address, mutex_addr={:016X}", 486 LOG_ERROR(Kernel_SVC, "Mutex Address is a kernel virtual address, mutex_addr={:016X}",
563 mutex_addr); 487 mutex_addr);
564 return ERR_INVALID_ADDRESS_STATE; 488 return ERR_INVALID_ADDRESS_STATE;
@@ -683,7 +607,6 @@ static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) {
683 auto* const current_thread = system.CurrentScheduler().GetCurrentThread(); 607 auto* const current_thread = system.CurrentScheduler().GetCurrentThread();
684 const auto thread_processor_id = current_thread->GetProcessorID(); 608 const auto thread_processor_id = current_thread->GetProcessorID();
685 system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace(); 609 system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace();
686 ASSERT(false);
687 610
688 system.Kernel().CurrentProcess()->PrepareForTermination(); 611 system.Kernel().CurrentProcess()->PrepareForTermination();
689 612
@@ -785,35 +708,35 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha
785 return RESULT_SUCCESS; 708 return RESULT_SUCCESS;
786 709
787 case GetInfoType::MapRegionBaseAddr: 710 case GetInfoType::MapRegionBaseAddr:
788 *result = process->VMManager().GetMapRegionBaseAddress(); 711 *result = process->PageTable().GetAliasRegionStart();
789 return RESULT_SUCCESS; 712 return RESULT_SUCCESS;
790 713
791 case GetInfoType::MapRegionSize: 714 case GetInfoType::MapRegionSize:
792 *result = process->VMManager().GetMapRegionSize(); 715 *result = process->PageTable().GetAliasRegionSize();
793 return RESULT_SUCCESS; 716 return RESULT_SUCCESS;
794 717
795 case GetInfoType::HeapRegionBaseAddr: 718 case GetInfoType::HeapRegionBaseAddr:
796 *result = process->VMManager().GetHeapRegionBaseAddress(); 719 *result = process->PageTable().GetHeapRegionStart();
797 return RESULT_SUCCESS; 720 return RESULT_SUCCESS;
798 721
799 case GetInfoType::HeapRegionSize: 722 case GetInfoType::HeapRegionSize:
800 *result = process->VMManager().GetHeapRegionSize(); 723 *result = process->PageTable().GetHeapRegionSize();
801 return RESULT_SUCCESS; 724 return RESULT_SUCCESS;
802 725
803 case GetInfoType::ASLRRegionBaseAddr: 726 case GetInfoType::ASLRRegionBaseAddr:
804 *result = process->VMManager().GetASLRRegionBaseAddress(); 727 *result = process->PageTable().GetAliasCodeRegionStart();
805 return RESULT_SUCCESS; 728 return RESULT_SUCCESS;
806 729
807 case GetInfoType::ASLRRegionSize: 730 case GetInfoType::ASLRRegionSize:
808 *result = process->VMManager().GetASLRRegionSize(); 731 *result = process->PageTable().GetAliasCodeRegionSize();
809 return RESULT_SUCCESS; 732 return RESULT_SUCCESS;
810 733
811 case GetInfoType::StackRegionBaseAddr: 734 case GetInfoType::StackRegionBaseAddr:
812 *result = process->VMManager().GetStackRegionBaseAddress(); 735 *result = process->PageTable().GetStackRegionStart();
813 return RESULT_SUCCESS; 736 return RESULT_SUCCESS;
814 737
815 case GetInfoType::StackRegionSize: 738 case GetInfoType::StackRegionSize:
816 *result = process->VMManager().GetStackRegionSize(); 739 *result = process->PageTable().GetStackRegionSize();
817 return RESULT_SUCCESS; 740 return RESULT_SUCCESS;
818 741
819 case GetInfoType::TotalPhysicalMemoryAvailable: 742 case GetInfoType::TotalPhysicalMemoryAvailable:
@@ -987,20 +910,29 @@ static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size)
987 return ERR_INVALID_MEMORY_RANGE; 910 return ERR_INVALID_MEMORY_RANGE;
988 } 911 }
989 912
990 Process* const current_process = system.Kernel().CurrentProcess(); 913 Process* const current_process{system.Kernel().CurrentProcess()};
991 auto& vm_manager = current_process->VMManager(); 914 auto& page_table{current_process->PageTable()};
992 915
993 if (current_process->GetSystemResourceSize() == 0) { 916 if (current_process->GetSystemResourceSize() == 0) {
994 LOG_ERROR(Kernel_SVC, "System Resource Size is zero"); 917 LOG_ERROR(Kernel_SVC, "System Resource Size is zero");
995 return ERR_INVALID_STATE; 918 return ERR_INVALID_STATE;
996 } 919 }
997 920
998 if (!vm_manager.IsWithinMapRegion(addr, size)) { 921 if (!page_table.IsInsideAddressSpace(addr, size)) {
999 LOG_ERROR(Kernel_SVC, "Range not within map region"); 922 LOG_ERROR(Kernel_SVC,
923 "Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr,
924 size);
925 return ERR_INVALID_MEMORY_RANGE;
926 }
927
928 if (page_table.IsOutsideAliasRegion(addr, size)) {
929 LOG_ERROR(Kernel_SVC,
930 "Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr,
931 size);
1000 return ERR_INVALID_MEMORY_RANGE; 932 return ERR_INVALID_MEMORY_RANGE;
1001 } 933 }
1002 934
1003 return vm_manager.MapPhysicalMemory(addr, size); 935 return page_table.MapPhysicalMemory(addr, size);
1004} 936}
1005 937
1006/// Unmaps memory previously mapped via MapPhysicalMemory 938/// Unmaps memory previously mapped via MapPhysicalMemory
@@ -1027,20 +959,29 @@ static ResultCode UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size
1027 return ERR_INVALID_MEMORY_RANGE; 959 return ERR_INVALID_MEMORY_RANGE;
1028 } 960 }
1029 961
1030 Process* const current_process = system.Kernel().CurrentProcess(); 962 Process* const current_process{system.Kernel().CurrentProcess()};
1031 auto& vm_manager = current_process->VMManager(); 963 auto& page_table{current_process->PageTable()};
1032 964
1033 if (current_process->GetSystemResourceSize() == 0) { 965 if (current_process->GetSystemResourceSize() == 0) {
1034 LOG_ERROR(Kernel_SVC, "System Resource Size is zero"); 966 LOG_ERROR(Kernel_SVC, "System Resource Size is zero");
1035 return ERR_INVALID_STATE; 967 return ERR_INVALID_STATE;
1036 } 968 }
1037 969
1038 if (!vm_manager.IsWithinMapRegion(addr, size)) { 970 if (!page_table.IsInsideAddressSpace(addr, size)) {
1039 LOG_ERROR(Kernel_SVC, "Range not within map region"); 971 LOG_ERROR(Kernel_SVC,
972 "Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr,
973 size);
974 return ERR_INVALID_MEMORY_RANGE;
975 }
976
977 if (page_table.IsOutsideAliasRegion(addr, size)) {
978 LOG_ERROR(Kernel_SVC,
979 "Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr,
980 size);
1040 return ERR_INVALID_MEMORY_RANGE; 981 return ERR_INVALID_MEMORY_RANGE;
1041 } 982 }
1042 983
1043 return vm_manager.UnmapPhysicalMemory(addr, size); 984 return page_table.UnmapPhysicalMemory(addr, size);
1044} 985}
1045 986
1046/// Sets the thread activity 987/// Sets the thread activity
@@ -1197,74 +1138,49 @@ static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_han
1197 return ERR_INVALID_ADDRESS_STATE; 1138 return ERR_INVALID_ADDRESS_STATE;
1198 } 1139 }
1199 1140
1200 const auto permissions_type = static_cast<MemoryPermission>(permissions); 1141 const auto permission_type = static_cast<Memory::MemoryPermission>(permissions);
1201 if (permissions_type != MemoryPermission::Read && 1142 if ((permission_type | Memory::MemoryPermission::Write) !=
1202 permissions_type != MemoryPermission::ReadWrite) { 1143 Memory::MemoryPermission::ReadAndWrite) {
1203 LOG_ERROR(Kernel_SVC, "Expected Read or ReadWrite permission but got permissions=0x{:08X}", 1144 LOG_ERROR(Kernel_SVC, "Expected Read or ReadWrite permission but got permissions=0x{:08X}",
1204 permissions); 1145 permissions);
1205 return ERR_INVALID_MEMORY_PERMISSIONS; 1146 return ERR_INVALID_MEMORY_PERMISSIONS;
1206 } 1147 }
1207 1148
1208 auto* const current_process = system.Kernel().CurrentProcess(); 1149 auto* const current_process{system.Kernel().CurrentProcess()};
1209 auto shared_memory = current_process->GetHandleTable().Get<SharedMemory>(shared_memory_handle); 1150 auto& page_table{current_process->PageTable()};
1210 if (!shared_memory) {
1211 LOG_ERROR(Kernel_SVC, "Shared memory does not exist, shared_memory_handle=0x{:08X}",
1212 shared_memory_handle);
1213 return ERR_INVALID_HANDLE;
1214 }
1215 1151
1216 const auto& vm_manager = current_process->VMManager(); 1152 if (page_table.IsInvalidRegion(addr, size)) {
1217 if (!vm_manager.IsWithinASLRRegion(addr, size)) { 1153 LOG_ERROR(Kernel_SVC,
1218 LOG_ERROR(Kernel_SVC, "Region is not within the ASLR region. addr=0x{:016X}, size={:016X}", 1154 "Addr does not fit within the valid region, addr=0x{:016X}, "
1155 "size=0x{:016X}",
1219 addr, size); 1156 addr, size);
1220 return ERR_INVALID_MEMORY_RANGE; 1157 return ERR_INVALID_MEMORY_RANGE;
1221 } 1158 }
1222 1159
1223 return shared_memory->Map(*current_process, addr, permissions_type, MemoryPermission::DontCare); 1160 if (page_table.IsInsideHeapRegion(addr, size)) {
1224} 1161 LOG_ERROR(Kernel_SVC,
1225 1162 "Addr does not fit within the heap region, addr=0x{:016X}, "
1226static ResultCode UnmapSharedMemory(Core::System& system, Handle shared_memory_handle, VAddr addr, 1163 "size=0x{:016X}",
1227 u64 size) { 1164 addr, size);
1228 LOG_WARNING(Kernel_SVC, "called, shared_memory_handle=0x{:08X}, addr=0x{:X}, size=0x{:X}", 1165 return ERR_INVALID_MEMORY_RANGE;
1229 shared_memory_handle, addr, size);
1230
1231 if (!Common::Is4KBAligned(addr)) {
1232 LOG_ERROR(Kernel_SVC, "Address is not aligned to 4KB, addr=0x{:016X}", addr);
1233 return ERR_INVALID_ADDRESS;
1234 }
1235
1236 if (size == 0) {
1237 LOG_ERROR(Kernel_SVC, "Size is 0");
1238 return ERR_INVALID_SIZE;
1239 }
1240
1241 if (!Common::Is4KBAligned(size)) {
1242 LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, size=0x{:016X}", size);
1243 return ERR_INVALID_SIZE;
1244 } 1166 }
1245 1167
1246 if (!IsValidAddressRange(addr, size)) { 1168 if (page_table.IsInsideAliasRegion(addr, size)) {
1247 LOG_ERROR(Kernel_SVC, "Region is not a valid address range, addr=0x{:016X}, size=0x{:016X}", 1169 LOG_ERROR(Kernel_SVC,
1170 "Address does not fit within the map region, addr=0x{:016X}, "
1171 "size=0x{:016X}",
1248 addr, size); 1172 addr, size);
1249 return ERR_INVALID_ADDRESS_STATE; 1173 return ERR_INVALID_MEMORY_RANGE;
1250 } 1174 }
1251 1175
1252 auto* const current_process = system.Kernel().CurrentProcess(); 1176 auto shared_memory{current_process->GetHandleTable().Get<SharedMemory>(shared_memory_handle)};
1253 auto shared_memory = current_process->GetHandleTable().Get<SharedMemory>(shared_memory_handle);
1254 if (!shared_memory) { 1177 if (!shared_memory) {
1255 LOG_ERROR(Kernel_SVC, "Shared memory does not exist, shared_memory_handle=0x{:08X}", 1178 LOG_ERROR(Kernel_SVC, "Shared memory does not exist, shared_memory_handle=0x{:08X}",
1256 shared_memory_handle); 1179 shared_memory_handle);
1257 return ERR_INVALID_HANDLE; 1180 return ERR_INVALID_HANDLE;
1258 } 1181 }
1259 1182
1260 const auto& vm_manager = current_process->VMManager(); 1183 return shared_memory->Map(*current_process, addr, size, permission_type);
1261 if (!vm_manager.IsWithinASLRRegion(addr, size)) {
1262 LOG_ERROR(Kernel_SVC, "Region is not within the ASLR region. addr=0x{:016X}, size={:016X}",
1263 addr, size);
1264 return ERR_INVALID_MEMORY_RANGE;
1265 }
1266
1267 return shared_memory->Unmap(*current_process, addr, size);
1268} 1184}
1269 1185
1270static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address, 1186static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address,
@@ -1279,18 +1195,17 @@ static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_add
1279 return ERR_INVALID_HANDLE; 1195 return ERR_INVALID_HANDLE;
1280 } 1196 }
1281 1197
1282 auto& memory = system.Memory(); 1198 auto& memory{system.Memory()};
1283 const auto& vm_manager = process->VMManager(); 1199 const auto memory_info{process->PageTable().QueryInfo(address).GetSvcMemoryInfo()};
1284 const MemoryInfo memory_info = vm_manager.QueryMemory(address); 1200
1285 1201 memory.Write64(memory_info_address + 0x00, memory_info.addr);
1286 memory.Write64(memory_info_address, memory_info.base_address); 1202 memory.Write64(memory_info_address + 0x08, memory_info.size);
1287 memory.Write64(memory_info_address + 8, memory_info.size); 1203 memory.Write32(memory_info_address + 0x10, static_cast<u32>(memory_info.state) & 0xff);
1288 memory.Write32(memory_info_address + 16, memory_info.state); 1204 memory.Write32(memory_info_address + 0x14, static_cast<u32>(memory_info.attr));
1289 memory.Write32(memory_info_address + 20, memory_info.attributes); 1205 memory.Write32(memory_info_address + 0x18, static_cast<u32>(memory_info.perm));
1290 memory.Write32(memory_info_address + 24, memory_info.permission); 1206 memory.Write32(memory_info_address + 0x1c, memory_info.ipc_refcount);
1291 memory.Write32(memory_info_address + 32, memory_info.ipc_ref_count); 1207 memory.Write32(memory_info_address + 0x20, memory_info.device_refcount);
1292 memory.Write32(memory_info_address + 28, memory_info.device_ref_count); 1208 memory.Write32(memory_info_address + 0x24, 0);
1293 memory.Write32(memory_info_address + 36, 0);
1294 1209
1295 // Page info appears to be currently unused by the kernel and is always set to zero. 1210 // Page info appears to be currently unused by the kernel and is always set to zero.
1296 memory.Write32(page_info_address, 0); 1211 memory.Write32(page_info_address, 0);
@@ -1314,142 +1229,6 @@ static ResultCode QueryMemory32(Core::System& system, u32 memory_info_address,
1314 return QueryMemory(system, memory_info_address, page_info_address, query_address); 1229 return QueryMemory(system, memory_info_address, page_info_address, query_address);
1315} 1230}
1316 1231
1317static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address,
1318 u64 src_address, u64 size) {
1319 LOG_DEBUG(Kernel_SVC,
1320 "called. process_handle=0x{:08X}, dst_address=0x{:016X}, "
1321 "src_address=0x{:016X}, size=0x{:016X}",
1322 process_handle, dst_address, src_address, size);
1323
1324 if (!Common::Is4KBAligned(src_address)) {
1325 LOG_ERROR(Kernel_SVC, "src_address is not page-aligned (src_address=0x{:016X}).",
1326 src_address);
1327 return ERR_INVALID_ADDRESS;
1328 }
1329
1330 if (!Common::Is4KBAligned(dst_address)) {
1331 LOG_ERROR(Kernel_SVC, "dst_address is not page-aligned (dst_address=0x{:016X}).",
1332 dst_address);
1333 return ERR_INVALID_ADDRESS;
1334 }
1335
1336 if (size == 0 || !Common::Is4KBAligned(size)) {
1337 LOG_ERROR(Kernel_SVC, "Size is zero or not page-aligned (size=0x{:016X})", size);
1338 return ERR_INVALID_SIZE;
1339 }
1340
1341 if (!IsValidAddressRange(dst_address, size)) {
1342 LOG_ERROR(Kernel_SVC,
1343 "Destination address range overflows the address space (dst_address=0x{:016X}, "
1344 "size=0x{:016X}).",
1345 dst_address, size);
1346 return ERR_INVALID_ADDRESS_STATE;
1347 }
1348
1349 if (!IsValidAddressRange(src_address, size)) {
1350 LOG_ERROR(Kernel_SVC,
1351 "Source address range overflows the address space (src_address=0x{:016X}, "
1352 "size=0x{:016X}).",
1353 src_address, size);
1354 return ERR_INVALID_ADDRESS_STATE;
1355 }
1356
1357 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1358 auto process = handle_table.Get<Process>(process_handle);
1359 if (!process) {
1360 LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).",
1361 process_handle);
1362 return ERR_INVALID_HANDLE;
1363 }
1364
1365 auto& vm_manager = process->VMManager();
1366 if (!vm_manager.IsWithinAddressSpace(src_address, size)) {
1367 LOG_ERROR(Kernel_SVC,
1368 "Source address range is not within the address space (src_address=0x{:016X}, "
1369 "size=0x{:016X}).",
1370 src_address, size);
1371 return ERR_INVALID_ADDRESS_STATE;
1372 }
1373
1374 if (!vm_manager.IsWithinASLRRegion(dst_address, size)) {
1375 LOG_ERROR(Kernel_SVC,
1376 "Destination address range is not within the ASLR region (dst_address=0x{:016X}, "
1377 "size=0x{:016X}).",
1378 dst_address, size);
1379 return ERR_INVALID_MEMORY_RANGE;
1380 }
1381
1382 return vm_manager.MapCodeMemory(dst_address, src_address, size);
1383}
1384
1385static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_handle,
1386 u64 dst_address, u64 src_address, u64 size) {
1387 LOG_DEBUG(Kernel_SVC,
1388 "called. process_handle=0x{:08X}, dst_address=0x{:016X}, src_address=0x{:016X}, "
1389 "size=0x{:016X}",
1390 process_handle, dst_address, src_address, size);
1391
1392 if (!Common::Is4KBAligned(dst_address)) {
1393 LOG_ERROR(Kernel_SVC, "dst_address is not page-aligned (dst_address=0x{:016X}).",
1394 dst_address);
1395 return ERR_INVALID_ADDRESS;
1396 }
1397
1398 if (!Common::Is4KBAligned(src_address)) {
1399 LOG_ERROR(Kernel_SVC, "src_address is not page-aligned (src_address=0x{:016X}).",
1400 src_address);
1401 return ERR_INVALID_ADDRESS;
1402 }
1403
1404 if (size == 0 || Common::Is4KBAligned(size)) {
1405 LOG_ERROR(Kernel_SVC, "Size is zero or not page-aligned (size=0x{:016X}).", size);
1406 return ERR_INVALID_SIZE;
1407 }
1408
1409 if (!IsValidAddressRange(dst_address, size)) {
1410 LOG_ERROR(Kernel_SVC,
1411 "Destination address range overflows the address space (dst_address=0x{:016X}, "
1412 "size=0x{:016X}).",
1413 dst_address, size);
1414 return ERR_INVALID_ADDRESS_STATE;
1415 }
1416
1417 if (!IsValidAddressRange(src_address, size)) {
1418 LOG_ERROR(Kernel_SVC,
1419 "Source address range overflows the address space (src_address=0x{:016X}, "
1420 "size=0x{:016X}).",
1421 src_address, size);
1422 return ERR_INVALID_ADDRESS_STATE;
1423 }
1424
1425 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1426 auto process = handle_table.Get<Process>(process_handle);
1427 if (!process) {
1428 LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).",
1429 process_handle);
1430 return ERR_INVALID_HANDLE;
1431 }
1432
1433 auto& vm_manager = process->VMManager();
1434 if (!vm_manager.IsWithinAddressSpace(src_address, size)) {
1435 LOG_ERROR(Kernel_SVC,
1436 "Source address range is not within the address space (src_address=0x{:016X}, "
1437 "size=0x{:016X}).",
1438 src_address, size);
1439 return ERR_INVALID_ADDRESS_STATE;
1440 }
1441
1442 if (!vm_manager.IsWithinASLRRegion(dst_address, size)) {
1443 LOG_ERROR(Kernel_SVC,
1444 "Destination address range is not within the ASLR region (dst_address=0x{:016X}, "
1445 "size=0x{:016X}).",
1446 dst_address, size);
1447 return ERR_INVALID_MEMORY_RANGE;
1448 }
1449
1450 return vm_manager.UnmapCodeMemory(dst_address, src_address, size);
1451}
1452
1453/// Exits the current process 1232/// Exits the current process
1454static void ExitProcess(Core::System& system) { 1233static void ExitProcess(Core::System& system) {
1455 auto* current_process = system.Kernel().CurrentProcess(); 1234 auto* current_process = system.Kernel().CurrentProcess();
@@ -1506,6 +1285,9 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e
1506 } 1285 }
1507 1286
1508 auto& kernel = system.Kernel(); 1287 auto& kernel = system.Kernel();
1288
1289 ASSERT(kernel.CurrentProcess()->GetResourceLimit()->Reserve(ResourceType::Threads, 1));
1290
1509 CASCADE_RESULT(std::shared_ptr<Thread> thread, 1291 CASCADE_RESULT(std::shared_ptr<Thread> thread,
1510 Thread::Create(kernel, "", entry_point, priority, arg, processor_id, stack_top, 1292 Thread::Create(kernel, "", entry_point, priority, arg, processor_id, stack_top,
1511 *current_process)); 1293 *current_process));
@@ -1610,7 +1392,7 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr mutex_add
1610 "called mutex_addr={:X}, condition_variable_addr={:X}, thread_handle=0x{:08X}, timeout={}", 1392 "called mutex_addr={:X}, condition_variable_addr={:X}, thread_handle=0x{:08X}, timeout={}",
1611 mutex_addr, condition_variable_addr, thread_handle, nano_seconds); 1393 mutex_addr, condition_variable_addr, thread_handle, nano_seconds);
1612 1394
1613 if (Memory::IsKernelVirtualAddress(mutex_addr)) { 1395 if (Core::Memory::IsKernelVirtualAddress(mutex_addr)) {
1614 LOG_ERROR( 1396 LOG_ERROR(
1615 Kernel_SVC, 1397 Kernel_SVC,
1616 "Given mutex address must not be within the kernel address space. address=0x{:016X}", 1398 "Given mutex address must not be within the kernel address space. address=0x{:016X}",
@@ -1741,7 +1523,7 @@ static ResultCode WaitForAddress(Core::System& system, VAddr address, u32 type,
1741 type, value, timeout); 1523 type, value, timeout);
1742 1524
1743 // If the passed address is a kernel virtual address, return invalid memory state. 1525 // If the passed address is a kernel virtual address, return invalid memory state.
1744 if (Memory::IsKernelVirtualAddress(address)) { 1526 if (Core::Memory::IsKernelVirtualAddress(address)) {
1745 LOG_ERROR(Kernel_SVC, "Address is a kernel virtual address, address={:016X}", address); 1527 LOG_ERROR(Kernel_SVC, "Address is a kernel virtual address, address={:016X}", address);
1746 return ERR_INVALID_ADDRESS_STATE; 1528 return ERR_INVALID_ADDRESS_STATE;
1747 } 1529 }
@@ -1769,7 +1551,7 @@ static ResultCode SignalToAddress(Core::System& system, VAddr address, u32 type,
1769 address, type, value, num_to_wake); 1551 address, type, value, num_to_wake);
1770 1552
1771 // If the passed address is a kernel virtual address, return invalid memory state. 1553 // If the passed address is a kernel virtual address, return invalid memory state.
1772 if (Memory::IsKernelVirtualAddress(address)) { 1554 if (Core::Memory::IsKernelVirtualAddress(address)) {
1773 LOG_ERROR(Kernel_SVC, "Address is a kernel virtual address, address={:016X}", address); 1555 LOG_ERROR(Kernel_SVC, "Address is a kernel virtual address, address={:016X}", address);
1774 return ERR_INVALID_ADDRESS_STATE; 1556 return ERR_INVALID_ADDRESS_STATE;
1775 } 1557 }
@@ -1865,9 +1647,9 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd
1865 return ERR_INVALID_ADDRESS_STATE; 1647 return ERR_INVALID_ADDRESS_STATE;
1866 } 1648 }
1867 1649
1868 const auto perms = static_cast<MemoryPermission>(permissions); 1650 const auto perms{static_cast<Memory::MemoryPermission>(permissions)};
1869 if (perms != MemoryPermission::None && perms != MemoryPermission::Read && 1651 if (perms > Memory::MemoryPermission::ReadAndWrite ||
1870 perms != MemoryPermission::ReadWrite) { 1652 perms == Memory::MemoryPermission::Write) {
1871 LOG_ERROR(Kernel_SVC, "Invalid memory permissions for transfer memory! (perms={:08X})", 1653 LOG_ERROR(Kernel_SVC, "Invalid memory permissions for transfer memory! (perms={:08X})",
1872 permissions); 1654 permissions);
1873 return ERR_INVALID_MEMORY_PERMISSIONS; 1655 return ERR_INVALID_MEMORY_PERMISSIONS;
@@ -1890,111 +1672,6 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd
1890 return RESULT_SUCCESS; 1672 return RESULT_SUCCESS;
1891} 1673}
1892 1674
1893static ResultCode MapTransferMemory(Core::System& system, Handle handle, VAddr address, u64 size,
1894 u32 permission_raw) {
1895 LOG_DEBUG(Kernel_SVC,
1896 "called. handle=0x{:08X}, address=0x{:016X}, size=0x{:016X}, permissions=0x{:08X}",
1897 handle, address, size, permission_raw);
1898
1899 if (!Common::Is4KBAligned(address)) {
1900 LOG_ERROR(Kernel_SVC, "Transfer memory addresses must be 4KB aligned (size=0x{:016X}).",
1901 address);
1902 return ERR_INVALID_ADDRESS;
1903 }
1904
1905 if (size == 0 || !Common::Is4KBAligned(size)) {
1906 LOG_ERROR(Kernel_SVC,
1907 "Transfer memory sizes must be 4KB aligned and not be zero (size=0x{:016X}).",
1908 size);
1909 return ERR_INVALID_SIZE;
1910 }
1911
1912 if (!IsValidAddressRange(address, size)) {
1913 LOG_ERROR(Kernel_SVC,
1914 "Given address and size overflows the 64-bit range (address=0x{:016X}, "
1915 "size=0x{:016X}).",
1916 address, size);
1917 return ERR_INVALID_ADDRESS_STATE;
1918 }
1919
1920 const auto permissions = static_cast<MemoryPermission>(permission_raw);
1921 if (permissions != MemoryPermission::None && permissions != MemoryPermission::Read &&
1922 permissions != MemoryPermission::ReadWrite) {
1923 LOG_ERROR(Kernel_SVC, "Invalid transfer memory permissions given (permissions=0x{:08X}).",
1924 permission_raw);
1925 return ERR_INVALID_STATE;
1926 }
1927
1928 const auto& kernel = system.Kernel();
1929 const auto* const current_process = kernel.CurrentProcess();
1930 const auto& handle_table = current_process->GetHandleTable();
1931
1932 auto transfer_memory = handle_table.Get<TransferMemory>(handle);
1933 if (!transfer_memory) {
1934 LOG_ERROR(Kernel_SVC, "Nonexistent transfer memory handle given (handle=0x{:08X}).",
1935 handle);
1936 return ERR_INVALID_HANDLE;
1937 }
1938
1939 if (!current_process->VMManager().IsWithinASLRRegion(address, size)) {
1940 LOG_ERROR(Kernel_SVC,
1941 "Given address and size don't fully fit within the ASLR region "
1942 "(address=0x{:016X}, size=0x{:016X}).",
1943 address, size);
1944 return ERR_INVALID_MEMORY_RANGE;
1945 }
1946
1947 return transfer_memory->MapMemory(address, size, permissions);
1948}
1949
1950static ResultCode UnmapTransferMemory(Core::System& system, Handle handle, VAddr address,
1951 u64 size) {
1952 LOG_DEBUG(Kernel_SVC, "called. handle=0x{:08X}, address=0x{:016X}, size=0x{:016X}", handle,
1953 address, size);
1954
1955 if (!Common::Is4KBAligned(address)) {
1956 LOG_ERROR(Kernel_SVC, "Transfer memory addresses must be 4KB aligned (size=0x{:016X}).",
1957 address);
1958 return ERR_INVALID_ADDRESS;
1959 }
1960
1961 if (size == 0 || !Common::Is4KBAligned(size)) {
1962 LOG_ERROR(Kernel_SVC,
1963 "Transfer memory sizes must be 4KB aligned and not be zero (size=0x{:016X}).",
1964 size);
1965 return ERR_INVALID_SIZE;
1966 }
1967
1968 if (!IsValidAddressRange(address, size)) {
1969 LOG_ERROR(Kernel_SVC,
1970 "Given address and size overflows the 64-bit range (address=0x{:016X}, "
1971 "size=0x{:016X}).",
1972 address, size);
1973 return ERR_INVALID_ADDRESS_STATE;
1974 }
1975
1976 const auto& kernel = system.Kernel();
1977 const auto* const current_process = kernel.CurrentProcess();
1978 const auto& handle_table = current_process->GetHandleTable();
1979
1980 auto transfer_memory = handle_table.Get<TransferMemory>(handle);
1981 if (!transfer_memory) {
1982 LOG_ERROR(Kernel_SVC, "Nonexistent transfer memory handle given (handle=0x{:08X}).",
1983 handle);
1984 return ERR_INVALID_HANDLE;
1985 }
1986
1987 if (!current_process->VMManager().IsWithinASLRRegion(address, size)) {
1988 LOG_ERROR(Kernel_SVC,
1989 "Given address and size don't fully fit within the ASLR region "
1990 "(address=0x{:016X}, size=0x{:016X}).",
1991 address, size);
1992 return ERR_INVALID_MEMORY_RANGE;
1993 }
1994
1995 return transfer_memory->UnmapMemory(address, size);
1996}
1997
1998static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, u32* core, 1675static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, u32* core,
1999 u64* mask) { 1676 u64* mask) {
2000 LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle); 1677 LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle);
@@ -2073,52 +1750,6 @@ static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle,
2073 return RESULT_SUCCESS; 1750 return RESULT_SUCCESS;
2074} 1751}
2075 1752
2076static ResultCode CreateSharedMemory(Core::System& system, Handle* handle, u64 size,
2077 u32 local_permissions, u32 remote_permissions) {
2078 LOG_TRACE(Kernel_SVC, "called, size=0x{:X}, localPerms=0x{:08X}, remotePerms=0x{:08X}", size,
2079 local_permissions, remote_permissions);
2080 if (size == 0) {
2081 LOG_ERROR(Kernel_SVC, "Size is 0");
2082 return ERR_INVALID_SIZE;
2083 }
2084 if (!Common::Is4KBAligned(size)) {
2085 LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, 0x{:016X}", size);
2086 return ERR_INVALID_SIZE;
2087 }
2088
2089 if (size >= MAIN_MEMORY_SIZE) {
2090 LOG_ERROR(Kernel_SVC, "Size is not less than 8GB, 0x{:016X}", size);
2091 return ERR_INVALID_SIZE;
2092 }
2093
2094 const auto local_perms = static_cast<MemoryPermission>(local_permissions);
2095 if (local_perms != MemoryPermission::Read && local_perms != MemoryPermission::ReadWrite) {
2096 LOG_ERROR(Kernel_SVC,
2097 "Invalid local memory permissions, expected Read or ReadWrite but got "
2098 "local_permissions={}",
2099 static_cast<u32>(local_permissions));
2100 return ERR_INVALID_MEMORY_PERMISSIONS;
2101 }
2102
2103 const auto remote_perms = static_cast<MemoryPermission>(remote_permissions);
2104 if (remote_perms != MemoryPermission::Read && remote_perms != MemoryPermission::ReadWrite &&
2105 remote_perms != MemoryPermission::DontCare) {
2106 LOG_ERROR(Kernel_SVC,
2107 "Invalid remote memory permissions, expected Read, ReadWrite or DontCare but got "
2108 "remote_permissions={}",
2109 static_cast<u32>(remote_permissions));
2110 return ERR_INVALID_MEMORY_PERMISSIONS;
2111 }
2112
2113 auto& kernel = system.Kernel();
2114 auto process = kernel.CurrentProcess();
2115 auto& handle_table = process->GetHandleTable();
2116 auto shared_mem_handle = SharedMemory::Create(kernel, process, size, local_perms, remote_perms);
2117
2118 CASCADE_RESULT(*handle, handle_table.Create(shared_mem_handle));
2119 return RESULT_SUCCESS;
2120}
2121
2122static ResultCode CreateEvent(Core::System& system, Handle* write_handle, Handle* read_handle) { 1753static ResultCode CreateEvent(Core::System& system, Handle* write_handle, Handle* read_handle) {
2123 LOG_DEBUG(Kernel_SVC, "called"); 1754 LOG_DEBUG(Kernel_SVC, "called");
2124 1755
@@ -2305,11 +1936,10 @@ static ResultCode GetProcessList(Core::System& system, u32* out_num_processes,
2305 } 1936 }
2306 1937
2307 const auto& kernel = system.Kernel(); 1938 const auto& kernel = system.Kernel();
2308 const auto& vm_manager = kernel.CurrentProcess()->VMManager();
2309 const auto total_copy_size = out_process_ids_size * sizeof(u64); 1939 const auto total_copy_size = out_process_ids_size * sizeof(u64);
2310 1940
2311 if (out_process_ids_size > 0 && 1941 if (out_process_ids_size > 0 && !kernel.CurrentProcess()->PageTable().IsInsideAddressSpace(
2312 !vm_manager.IsWithinAddressSpace(out_process_ids, total_copy_size)) { 1942 out_process_ids, total_copy_size)) {
2313 LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}", 1943 LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}",
2314 out_process_ids, out_process_ids + total_copy_size); 1944 out_process_ids, out_process_ids + total_copy_size);
2315 return ERR_INVALID_ADDRESS_STATE; 1945 return ERR_INVALID_ADDRESS_STATE;
@@ -2345,11 +1975,10 @@ static ResultCode GetThreadList(Core::System& system, u32* out_num_threads, VAdd
2345 } 1975 }
2346 1976
2347 const auto* const current_process = system.Kernel().CurrentProcess(); 1977 const auto* const current_process = system.Kernel().CurrentProcess();
2348 const auto& vm_manager = current_process->VMManager();
2349 const auto total_copy_size = out_thread_ids_size * sizeof(u64); 1978 const auto total_copy_size = out_thread_ids_size * sizeof(u64);
2350 1979
2351 if (out_thread_ids_size > 0 && 1980 if (out_thread_ids_size > 0 &&
2352 !vm_manager.IsWithinAddressSpace(out_thread_ids, total_copy_size)) { 1981 !current_process->PageTable().IsInsideAddressSpace(out_thread_ids, total_copy_size)) {
2353 LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}", 1982 LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}",
2354 out_thread_ids, out_thread_ids + total_copy_size); 1983 out_thread_ids, out_thread_ids + total_copy_size);
2355 return ERR_INVALID_ADDRESS_STATE; 1984 return ERR_INVALID_ADDRESS_STATE;
@@ -2510,7 +2139,7 @@ static const FunctionDef SVC_Table_32[] = {
2510static const FunctionDef SVC_Table_64[] = { 2139static const FunctionDef SVC_Table_64[] = {
2511 {0x00, nullptr, "Unknown"}, 2140 {0x00, nullptr, "Unknown"},
2512 {0x01, SvcWrap64<SetHeapSize>, "SetHeapSize"}, 2141 {0x01, SvcWrap64<SetHeapSize>, "SetHeapSize"},
2513 {0x02, SvcWrap64<SetMemoryPermission>, "SetMemoryPermission"}, 2142 {0x02, nullptr, "SetMemoryPermission"},
2514 {0x03, SvcWrap64<SetMemoryAttribute>, "SetMemoryAttribute"}, 2143 {0x03, SvcWrap64<SetMemoryAttribute>, "SetMemoryAttribute"},
2515 {0x04, SvcWrap64<MapMemory>, "MapMemory"}, 2144 {0x04, SvcWrap64<MapMemory>, "MapMemory"},
2516 {0x05, SvcWrap64<UnmapMemory>, "UnmapMemory"}, 2145 {0x05, SvcWrap64<UnmapMemory>, "UnmapMemory"},
@@ -2528,7 +2157,7 @@ static const FunctionDef SVC_Table_64[] = {
2528 {0x11, SvcWrap64<SignalEvent>, "SignalEvent"}, 2157 {0x11, SvcWrap64<SignalEvent>, "SignalEvent"},
2529 {0x12, SvcWrap64<ClearEvent>, "ClearEvent"}, 2158 {0x12, SvcWrap64<ClearEvent>, "ClearEvent"},
2530 {0x13, SvcWrap64<MapSharedMemory>, "MapSharedMemory"}, 2159 {0x13, SvcWrap64<MapSharedMemory>, "MapSharedMemory"},
2531 {0x14, SvcWrap64<UnmapSharedMemory>, "UnmapSharedMemory"}, 2160 {0x14, nullptr, "UnmapSharedMemory"},
2532 {0x15, SvcWrap64<CreateTransferMemory>, "CreateTransferMemory"}, 2161 {0x15, SvcWrap64<CreateTransferMemory>, "CreateTransferMemory"},
2533 {0x16, SvcWrap64<CloseHandle>, "CloseHandle"}, 2162 {0x16, SvcWrap64<CloseHandle>, "CloseHandle"},
2534 {0x17, SvcWrap64<ResetSignal>, "ResetSignal"}, 2163 {0x17, SvcWrap64<ResetSignal>, "ResetSignal"},
@@ -2588,9 +2217,9 @@ static const FunctionDef SVC_Table_64[] = {
2588 {0x4D, nullptr, "SleepSystem"}, 2217 {0x4D, nullptr, "SleepSystem"},
2589 {0x4E, nullptr, "ReadWriteRegister"}, 2218 {0x4E, nullptr, "ReadWriteRegister"},
2590 {0x4F, nullptr, "SetProcessActivity"}, 2219 {0x4F, nullptr, "SetProcessActivity"},
2591 {0x50, SvcWrap64<CreateSharedMemory>, "CreateSharedMemory"}, 2220 {0x50, nullptr, "CreateSharedMemory"},
2592 {0x51, SvcWrap64<MapTransferMemory>, "MapTransferMemory"}, 2221 {0x51, nullptr, "MapTransferMemory"},
2593 {0x52, SvcWrap64<UnmapTransferMemory>, "UnmapTransferMemory"}, 2222 {0x52, nullptr, "UnmapTransferMemory"},
2594 {0x53, nullptr, "CreateInterruptEvent"}, 2223 {0x53, nullptr, "CreateInterruptEvent"},
2595 {0x54, nullptr, "QueryPhysicalAddress"}, 2224 {0x54, nullptr, "QueryPhysicalAddress"},
2596 {0x55, nullptr, "QueryIoMapping"}, 2225 {0x55, nullptr, "QueryIoMapping"},
@@ -2627,8 +2256,8 @@ static const FunctionDef SVC_Table_64[] = {
2627 {0x74, nullptr, "MapProcessMemory"}, 2256 {0x74, nullptr, "MapProcessMemory"},
2628 {0x75, nullptr, "UnmapProcessMemory"}, 2257 {0x75, nullptr, "UnmapProcessMemory"},
2629 {0x76, SvcWrap64<QueryProcessMemory>, "QueryProcessMemory"}, 2258 {0x76, SvcWrap64<QueryProcessMemory>, "QueryProcessMemory"},
2630 {0x77, SvcWrap64<MapProcessCodeMemory>, "MapProcessCodeMemory"}, 2259 {0x77, nullptr, "MapProcessCodeMemory"},
2631 {0x78, SvcWrap64<UnmapProcessCodeMemory>, "UnmapProcessCodeMemory"}, 2260 {0x78, nullptr, "UnmapProcessCodeMemory"},
2632 {0x79, nullptr, "CreateProcess"}, 2261 {0x79, nullptr, "CreateProcess"},
2633 {0x7A, nullptr, "StartProcess"}, 2262 {0x7A, nullptr, "StartProcess"},
2634 {0x7B, nullptr, "TerminateProcess"}, 2263 {0x7B, nullptr, "TerminateProcess"},
@@ -2656,7 +2285,7 @@ static const FunctionDef* GetSVCInfo64(u32 func_num) {
2656 2285
2657MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70)); 2286MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70));
2658 2287
2659void CallSVC(Core::System& system, u32 immediate) { 2288void Call(Core::System& system, u32 immediate) {
2660 MICROPROFILE_SCOPE(Kernel_SVC); 2289 MICROPROFILE_SCOPE(Kernel_SVC);
2661 2290
2662 // Lock the global kernel mutex when we enter the kernel HLE. 2291 // Lock the global kernel mutex when we enter the kernel HLE.
@@ -2675,4 +2304,4 @@ void CallSVC(Core::System& system, u32 immediate) {
2675 } 2304 }
2676} 2305}
2677 2306
2678} // namespace Kernel 2307} // namespace Kernel::Svc