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