diff options
| author | 2021-12-18 13:57:14 +0800 | |
|---|---|---|
| committer | 2021-12-18 13:57:14 +0800 | |
| commit | e49184e6069a9d791d2df3c1958f5c4b1187e124 (patch) | |
| tree | b776caf722e0be0e680f67b0ad0842628162ef1c /src/core/hle/kernel/svc.cpp | |
| parent | Implement convert legacy to generic (diff) | |
| parent | Merge pull request #7570 from ameerj/favorites-expanded (diff) | |
| download | yuzu-e49184e6069a9d791d2df3c1958f5c4b1187e124.tar.gz yuzu-e49184e6069a9d791d2df3c1958f5c4b1187e124.tar.xz yuzu-e49184e6069a9d791d2df3c1958f5c4b1187e124.zip | |
Merge branch 'yuzu-emu:master' into convert_legacy
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 309 |
1 files changed, 286 insertions, 23 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index f9d99bc51..a9f7438ea 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include "core/core_timing.h" | 18 | #include "core/core_timing.h" |
| 19 | #include "core/hle/kernel/k_client_port.h" | 19 | #include "core/hle/kernel/k_client_port.h" |
| 20 | #include "core/hle/kernel/k_client_session.h" | 20 | #include "core/hle/kernel/k_client_session.h" |
| 21 | #include "core/hle/kernel/k_code_memory.h" | ||
| 21 | #include "core/hle/kernel/k_event.h" | 22 | #include "core/hle/kernel/k_event.h" |
| 22 | #include "core/hle/kernel/k_handle_table.h" | 23 | #include "core/hle/kernel/k_handle_table.h" |
| 23 | #include "core/hle/kernel/k_memory_block.h" | 24 | #include "core/hle/kernel/k_memory_block.h" |
| @@ -31,6 +32,7 @@ | |||
| 31 | #include "core/hle/kernel/k_shared_memory.h" | 32 | #include "core/hle/kernel/k_shared_memory.h" |
| 32 | #include "core/hle/kernel/k_synchronization_object.h" | 33 | #include "core/hle/kernel/k_synchronization_object.h" |
| 33 | #include "core/hle/kernel/k_thread.h" | 34 | #include "core/hle/kernel/k_thread.h" |
| 35 | #include "core/hle/kernel/k_thread_queue.h" | ||
| 34 | #include "core/hle/kernel/k_transfer_memory.h" | 36 | #include "core/hle/kernel/k_transfer_memory.h" |
| 35 | #include "core/hle/kernel/k_writable_event.h" | 37 | #include "core/hle/kernel/k_writable_event.h" |
| 36 | #include "core/hle/kernel/kernel.h" | 38 | #include "core/hle/kernel/kernel.h" |
| @@ -307,26 +309,29 @@ static ResultCode ConnectToNamedPort32(Core::System& system, Handle* out_handle, | |||
| 307 | 309 | ||
| 308 | /// Makes a blocking IPC call to an OS service. | 310 | /// Makes a blocking IPC call to an OS service. |
| 309 | static ResultCode SendSyncRequest(Core::System& system, Handle handle) { | 311 | static ResultCode SendSyncRequest(Core::System& system, Handle handle) { |
| 310 | |||
| 311 | auto& kernel = system.Kernel(); | 312 | auto& kernel = system.Kernel(); |
| 312 | 313 | ||
| 314 | // Create the wait queue. | ||
| 315 | KThreadQueue wait_queue(kernel); | ||
| 316 | |||
| 317 | // Get the client session from its handle. | ||
| 318 | KScopedAutoObject session = | ||
| 319 | kernel.CurrentProcess()->GetHandleTable().GetObject<KClientSession>(handle); | ||
| 320 | R_UNLESS(session.IsNotNull(), ResultInvalidHandle); | ||
| 321 | |||
| 322 | LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); | ||
| 323 | |||
| 313 | auto thread = kernel.CurrentScheduler()->GetCurrentThread(); | 324 | auto thread = kernel.CurrentScheduler()->GetCurrentThread(); |
| 314 | { | 325 | { |
| 315 | KScopedSchedulerLock lock(kernel); | 326 | KScopedSchedulerLock lock(kernel); |
| 316 | thread->SetState(ThreadState::Waiting); | 327 | |
| 317 | thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); | 328 | // This is a synchronous request, so we should wait for our request to complete. |
| 318 | 329 | GetCurrentThread(kernel).BeginWait(std::addressof(wait_queue)); | |
| 319 | { | 330 | GetCurrentThread(kernel).SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); |
| 320 | KScopedAutoObject session = | 331 | session->SendSyncRequest(&GetCurrentThread(kernel), system.Memory(), system.CoreTiming()); |
| 321 | kernel.CurrentProcess()->GetHandleTable().GetObject<KClientSession>(handle); | ||
| 322 | R_UNLESS(session.IsNotNull(), ResultInvalidHandle); | ||
| 323 | LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); | ||
| 324 | session->SendSyncRequest(thread, system.Memory(), system.CoreTiming()); | ||
| 325 | } | ||
| 326 | } | 332 | } |
| 327 | 333 | ||
| 328 | KSynchronizationObject* dummy{}; | 334 | return thread->GetWaitResult(); |
| 329 | return thread->GetWaitResult(std::addressof(dummy)); | ||
| 330 | } | 335 | } |
| 331 | 336 | ||
| 332 | static ResultCode SendSyncRequest32(Core::System& system, Handle handle) { | 337 | static ResultCode SendSyncRequest32(Core::System& system, Handle handle) { |
| @@ -873,7 +878,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle | |||
| 873 | const u64 thread_ticks = current_thread->GetCpuTime(); | 878 | const u64 thread_ticks = current_thread->GetCpuTime(); |
| 874 | 879 | ||
| 875 | out_ticks = thread_ticks + (core_timing.GetCPUTicks() - prev_ctx_ticks); | 880 | out_ticks = thread_ticks + (core_timing.GetCPUTicks() - prev_ctx_ticks); |
| 876 | } else if (same_thread && info_sub_id == system.CurrentCoreIndex()) { | 881 | } else if (same_thread && info_sub_id == system.Kernel().CurrentPhysicalCoreIndex()) { |
| 877 | out_ticks = core_timing.GetCPUTicks() - prev_ctx_ticks; | 882 | out_ticks = core_timing.GetCPUTicks() - prev_ctx_ticks; |
| 878 | } | 883 | } |
| 879 | 884 | ||
| @@ -887,7 +892,8 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle | |||
| 887 | return ResultInvalidHandle; | 892 | return ResultInvalidHandle; |
| 888 | } | 893 | } |
| 889 | 894 | ||
| 890 | if (info_sub_id != 0xFFFFFFFFFFFFFFFF && info_sub_id != system.CurrentCoreIndex()) { | 895 | if (info_sub_id != 0xFFFFFFFFFFFFFFFF && |
| 896 | info_sub_id != system.Kernel().CurrentPhysicalCoreIndex()) { | ||
| 891 | LOG_ERROR(Kernel_SVC, "Core is not the current core, got {}", info_sub_id); | 897 | LOG_ERROR(Kernel_SVC, "Core is not the current core, got {}", info_sub_id); |
| 892 | return ResultInvalidCombination; | 898 | return ResultInvalidCombination; |
| 893 | } | 899 | } |
| @@ -1169,6 +1175,8 @@ static u32 GetCurrentProcessorNumber32(Core::System& system) { | |||
| 1169 | return GetCurrentProcessorNumber(system); | 1175 | return GetCurrentProcessorNumber(system); |
| 1170 | } | 1176 | } |
| 1171 | 1177 | ||
| 1178 | namespace { | ||
| 1179 | |||
| 1172 | constexpr bool IsValidSharedMemoryPermission(Svc::MemoryPermission perm) { | 1180 | constexpr bool IsValidSharedMemoryPermission(Svc::MemoryPermission perm) { |
| 1173 | switch (perm) { | 1181 | switch (perm) { |
| 1174 | case Svc::MemoryPermission::Read: | 1182 | case Svc::MemoryPermission::Read: |
| @@ -1179,10 +1187,40 @@ constexpr bool IsValidSharedMemoryPermission(Svc::MemoryPermission perm) { | |||
| 1179 | } | 1187 | } |
| 1180 | } | 1188 | } |
| 1181 | 1189 | ||
| 1182 | constexpr bool IsValidRemoteSharedMemoryPermission(Svc::MemoryPermission perm) { | 1190 | [[maybe_unused]] constexpr bool IsValidRemoteSharedMemoryPermission(Svc::MemoryPermission perm) { |
| 1183 | return IsValidSharedMemoryPermission(perm) || perm == Svc::MemoryPermission::DontCare; | 1191 | return IsValidSharedMemoryPermission(perm) || perm == Svc::MemoryPermission::DontCare; |
| 1184 | } | 1192 | } |
| 1185 | 1193 | ||
| 1194 | constexpr bool IsValidProcessMemoryPermission(Svc::MemoryPermission perm) { | ||
| 1195 | switch (perm) { | ||
| 1196 | case Svc::MemoryPermission::None: | ||
| 1197 | case Svc::MemoryPermission::Read: | ||
| 1198 | case Svc::MemoryPermission::ReadWrite: | ||
| 1199 | case Svc::MemoryPermission::ReadExecute: | ||
| 1200 | return true; | ||
| 1201 | default: | ||
| 1202 | return false; | ||
| 1203 | } | ||
| 1204 | } | ||
| 1205 | |||
| 1206 | constexpr bool IsValidMapCodeMemoryPermission(Svc::MemoryPermission perm) { | ||
| 1207 | return perm == Svc::MemoryPermission::ReadWrite; | ||
| 1208 | } | ||
| 1209 | |||
| 1210 | constexpr bool IsValidMapToOwnerCodeMemoryPermission(Svc::MemoryPermission perm) { | ||
| 1211 | return perm == Svc::MemoryPermission::Read || perm == Svc::MemoryPermission::ReadExecute; | ||
| 1212 | } | ||
| 1213 | |||
| 1214 | constexpr bool IsValidUnmapCodeMemoryPermission(Svc::MemoryPermission perm) { | ||
| 1215 | return perm == Svc::MemoryPermission::None; | ||
| 1216 | } | ||
| 1217 | |||
| 1218 | constexpr bool IsValidUnmapFromOwnerCodeMemoryPermission(Svc::MemoryPermission perm) { | ||
| 1219 | return perm == Svc::MemoryPermission::None; | ||
| 1220 | } | ||
| 1221 | |||
| 1222 | } // Anonymous namespace | ||
| 1223 | |||
| 1186 | static ResultCode MapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address, | 1224 | static ResultCode MapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address, |
| 1187 | u64 size, Svc::MemoryPermission map_perm) { | 1225 | u64 size, Svc::MemoryPermission map_perm) { |
| 1188 | LOG_TRACE(Kernel_SVC, | 1226 | LOG_TRACE(Kernel_SVC, |
| @@ -1262,6 +1300,223 @@ static ResultCode UnmapSharedMemory32(Core::System& system, Handle shmem_handle, | |||
| 1262 | return UnmapSharedMemory(system, shmem_handle, address, size); | 1300 | return UnmapSharedMemory(system, shmem_handle, address, size); |
| 1263 | } | 1301 | } |
| 1264 | 1302 | ||
| 1303 | static ResultCode SetProcessMemoryPermission(Core::System& system, Handle process_handle, | ||
| 1304 | VAddr address, u64 size, Svc::MemoryPermission perm) { | ||
| 1305 | LOG_TRACE(Kernel_SVC, | ||
| 1306 | "called, process_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}", | ||
| 1307 | process_handle, address, size, perm); | ||
| 1308 | |||
| 1309 | // Validate the address/size. | ||
| 1310 | R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress); | ||
| 1311 | R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize); | ||
| 1312 | R_UNLESS(size > 0, ResultInvalidSize); | ||
| 1313 | R_UNLESS((address < address + size), ResultInvalidCurrentMemory); | ||
| 1314 | |||
| 1315 | // Validate the memory permission. | ||
| 1316 | R_UNLESS(IsValidProcessMemoryPermission(perm), ResultInvalidNewMemoryPermission); | ||
| 1317 | |||
| 1318 | // Get the process from its handle. | ||
| 1319 | KScopedAutoObject process = | ||
| 1320 | system.CurrentProcess()->GetHandleTable().GetObject<KProcess>(process_handle); | ||
| 1321 | R_UNLESS(process.IsNotNull(), ResultInvalidHandle); | ||
| 1322 | |||
| 1323 | // Validate that the address is in range. | ||
| 1324 | auto& page_table = process->PageTable(); | ||
| 1325 | R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory); | ||
| 1326 | |||
| 1327 | // Set the memory permission. | ||
| 1328 | return page_table.SetProcessMemoryPermission(address, size, ConvertToKMemoryPermission(perm)); | ||
| 1329 | } | ||
| 1330 | |||
| 1331 | static ResultCode MapProcessMemory(Core::System& system, VAddr dst_address, Handle process_handle, | ||
| 1332 | VAddr src_address, u64 size) { | ||
| 1333 | LOG_TRACE(Kernel_SVC, | ||
| 1334 | "called, dst_address=0x{:X}, process_handle=0x{:X}, src_address=0x{:X}, size=0x{:X}", | ||
| 1335 | dst_address, process_handle, src_address, size); | ||
| 1336 | |||
| 1337 | // Validate the address/size. | ||
| 1338 | R_UNLESS(Common::IsAligned(dst_address, PageSize), ResultInvalidAddress); | ||
| 1339 | R_UNLESS(Common::IsAligned(src_address, PageSize), ResultInvalidAddress); | ||
| 1340 | R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize); | ||
| 1341 | R_UNLESS(size > 0, ResultInvalidSize); | ||
| 1342 | R_UNLESS((dst_address < dst_address + size), ResultInvalidCurrentMemory); | ||
| 1343 | R_UNLESS((src_address < src_address + size), ResultInvalidCurrentMemory); | ||
| 1344 | |||
| 1345 | // Get the processes. | ||
| 1346 | KProcess* dst_process = system.CurrentProcess(); | ||
| 1347 | KScopedAutoObject src_process = | ||
| 1348 | dst_process->GetHandleTable().GetObjectWithoutPseudoHandle<KProcess>(process_handle); | ||
| 1349 | R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle); | ||
| 1350 | |||
| 1351 | // Get the page tables. | ||
| 1352 | auto& dst_pt = dst_process->PageTable(); | ||
| 1353 | auto& src_pt = src_process->PageTable(); | ||
| 1354 | |||
| 1355 | // Validate that the mapping is in range. | ||
| 1356 | R_UNLESS(src_pt.Contains(src_address, size), ResultInvalidCurrentMemory); | ||
| 1357 | R_UNLESS(dst_pt.CanContain(dst_address, size, KMemoryState::SharedCode), | ||
| 1358 | ResultInvalidMemoryRegion); | ||
| 1359 | |||
| 1360 | // Create a new page group. | ||
| 1361 | KMemoryInfo kBlockInfo = dst_pt.QueryInfo(dst_address); | ||
| 1362 | KPageLinkedList pg(kBlockInfo.GetAddress(), kBlockInfo.GetNumPages()); | ||
| 1363 | |||
| 1364 | // Map the group. | ||
| 1365 | R_TRY(dst_pt.MapPages(dst_address, pg, KMemoryState::SharedCode, | ||
| 1366 | KMemoryPermission::UserReadWrite)); | ||
| 1367 | |||
| 1368 | return ResultSuccess; | ||
| 1369 | } | ||
| 1370 | |||
| 1371 | static ResultCode UnmapProcessMemory(Core::System& system, VAddr dst_address, Handle process_handle, | ||
| 1372 | VAddr src_address, u64 size) { | ||
| 1373 | LOG_TRACE(Kernel_SVC, | ||
| 1374 | "called, dst_address=0x{:X}, process_handle=0x{:X}, src_address=0x{:X}, size=0x{:X}", | ||
| 1375 | dst_address, process_handle, src_address, size); | ||
| 1376 | |||
| 1377 | // Validate the address/size. | ||
| 1378 | R_UNLESS(Common::IsAligned(dst_address, PageSize), ResultInvalidAddress); | ||
| 1379 | R_UNLESS(Common::IsAligned(src_address, PageSize), ResultInvalidAddress); | ||
| 1380 | R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize); | ||
| 1381 | R_UNLESS(size > 0, ResultInvalidSize); | ||
| 1382 | R_UNLESS((dst_address < dst_address + size), ResultInvalidCurrentMemory); | ||
| 1383 | R_UNLESS((src_address < src_address + size), ResultInvalidCurrentMemory); | ||
| 1384 | |||
| 1385 | // Get the processes. | ||
| 1386 | KProcess* dst_process = system.CurrentProcess(); | ||
| 1387 | KScopedAutoObject src_process = | ||
| 1388 | dst_process->GetHandleTable().GetObjectWithoutPseudoHandle<KProcess>(process_handle); | ||
| 1389 | R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle); | ||
| 1390 | |||
| 1391 | // Get the page tables. | ||
| 1392 | auto& dst_pt = dst_process->PageTable(); | ||
| 1393 | auto& src_pt = src_process->PageTable(); | ||
| 1394 | |||
| 1395 | // Validate that the mapping is in range. | ||
| 1396 | R_UNLESS(src_pt.Contains(src_address, size), ResultInvalidCurrentMemory); | ||
| 1397 | R_UNLESS(dst_pt.CanContain(dst_address, size, KMemoryState::SharedCode), | ||
| 1398 | ResultInvalidMemoryRegion); | ||
| 1399 | |||
| 1400 | // Unmap the memory. | ||
| 1401 | R_TRY(dst_pt.UnmapProcessMemory(dst_address, size, src_pt, src_address)); | ||
| 1402 | |||
| 1403 | return ResultSuccess; | ||
| 1404 | } | ||
| 1405 | |||
| 1406 | static ResultCode CreateCodeMemory(Core::System& system, Handle* out, VAddr address, size_t size) { | ||
| 1407 | LOG_TRACE(Kernel_SVC, "called, handle_out=0x{:X}, address=0x{:X}, size=0x{:X}", | ||
| 1408 | static_cast<void*>(out), address, size); | ||
| 1409 | // Get kernel instance. | ||
| 1410 | auto& kernel = system.Kernel(); | ||
| 1411 | |||
| 1412 | // Validate address / size. | ||
| 1413 | R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress); | ||
| 1414 | R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize); | ||
| 1415 | R_UNLESS(size > 0, ResultInvalidSize); | ||
| 1416 | R_UNLESS((address < address + size), ResultInvalidCurrentMemory); | ||
| 1417 | |||
| 1418 | // Create the code memory. | ||
| 1419 | |||
| 1420 | KCodeMemory* code_mem = KCodeMemory::Create(kernel); | ||
| 1421 | R_UNLESS(code_mem != nullptr, ResultOutOfResource); | ||
| 1422 | |||
| 1423 | // Verify that the region is in range. | ||
| 1424 | R_UNLESS(system.CurrentProcess()->PageTable().Contains(address, size), | ||
| 1425 | ResultInvalidCurrentMemory); | ||
| 1426 | |||
| 1427 | // Initialize the code memory. | ||
| 1428 | R_TRY(code_mem->Initialize(system.DeviceMemory(), address, size)); | ||
| 1429 | |||
| 1430 | // Register the code memory. | ||
| 1431 | KCodeMemory::Register(kernel, code_mem); | ||
| 1432 | |||
| 1433 | // Add the code memory to the handle table. | ||
| 1434 | R_TRY(system.CurrentProcess()->GetHandleTable().Add(out, code_mem)); | ||
| 1435 | |||
| 1436 | code_mem->Close(); | ||
| 1437 | |||
| 1438 | return ResultSuccess; | ||
| 1439 | } | ||
| 1440 | |||
| 1441 | static ResultCode ControlCodeMemory(Core::System& system, Handle code_memory_handle, u32 operation, | ||
| 1442 | VAddr address, size_t size, Svc::MemoryPermission perm) { | ||
| 1443 | |||
| 1444 | LOG_TRACE(Kernel_SVC, | ||
| 1445 | "called, code_memory_handle=0x{:X}, operation=0x{:X}, address=0x{:X}, size=0x{:X}, " | ||
| 1446 | "permission=0x{:X}", | ||
| 1447 | code_memory_handle, operation, address, size, perm); | ||
| 1448 | |||
| 1449 | // Validate the address / size. | ||
| 1450 | R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress); | ||
| 1451 | R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize); | ||
| 1452 | R_UNLESS(size > 0, ResultInvalidSize); | ||
| 1453 | R_UNLESS((address < address + size), ResultInvalidCurrentMemory); | ||
| 1454 | |||
| 1455 | // Get the code memory from its handle. | ||
| 1456 | KScopedAutoObject code_mem = | ||
| 1457 | system.CurrentProcess()->GetHandleTable().GetObject<KCodeMemory>(code_memory_handle); | ||
| 1458 | R_UNLESS(code_mem.IsNotNull(), ResultInvalidHandle); | ||
| 1459 | |||
| 1460 | // NOTE: Here, Atmosphere extends the SVC to allow code memory operations on one's own process. | ||
| 1461 | // This enables homebrew usage of these SVCs for JIT. | ||
| 1462 | |||
| 1463 | // Perform the operation. | ||
| 1464 | switch (static_cast<CodeMemoryOperation>(operation)) { | ||
| 1465 | case CodeMemoryOperation::Map: { | ||
| 1466 | // Check that the region is in range. | ||
| 1467 | R_UNLESS( | ||
| 1468 | system.CurrentProcess()->PageTable().CanContain(address, size, KMemoryState::CodeOut), | ||
| 1469 | ResultInvalidMemoryRegion); | ||
| 1470 | |||
| 1471 | // Check the memory permission. | ||
| 1472 | R_UNLESS(IsValidMapCodeMemoryPermission(perm), ResultInvalidNewMemoryPermission); | ||
| 1473 | |||
| 1474 | // Map the memory. | ||
| 1475 | R_TRY(code_mem->Map(address, size)); | ||
| 1476 | } break; | ||
| 1477 | case CodeMemoryOperation::Unmap: { | ||
| 1478 | // Check that the region is in range. | ||
| 1479 | R_UNLESS( | ||
| 1480 | system.CurrentProcess()->PageTable().CanContain(address, size, KMemoryState::CodeOut), | ||
| 1481 | ResultInvalidMemoryRegion); | ||
| 1482 | |||
| 1483 | // Check the memory permission. | ||
| 1484 | R_UNLESS(IsValidUnmapCodeMemoryPermission(perm), ResultInvalidNewMemoryPermission); | ||
| 1485 | |||
| 1486 | // Unmap the memory. | ||
| 1487 | R_TRY(code_mem->Unmap(address, size)); | ||
| 1488 | } break; | ||
| 1489 | case CodeMemoryOperation::MapToOwner: { | ||
| 1490 | // Check that the region is in range. | ||
| 1491 | R_UNLESS(code_mem->GetOwner()->PageTable().CanContain(address, size, | ||
| 1492 | KMemoryState::GeneratedCode), | ||
| 1493 | ResultInvalidMemoryRegion); | ||
| 1494 | |||
| 1495 | // Check the memory permission. | ||
| 1496 | R_UNLESS(IsValidMapToOwnerCodeMemoryPermission(perm), ResultInvalidNewMemoryPermission); | ||
| 1497 | |||
| 1498 | // Map the memory to its owner. | ||
| 1499 | R_TRY(code_mem->MapToOwner(address, size, perm)); | ||
| 1500 | } break; | ||
| 1501 | case CodeMemoryOperation::UnmapFromOwner: { | ||
| 1502 | // Check that the region is in range. | ||
| 1503 | R_UNLESS(code_mem->GetOwner()->PageTable().CanContain(address, size, | ||
| 1504 | KMemoryState::GeneratedCode), | ||
| 1505 | ResultInvalidMemoryRegion); | ||
| 1506 | |||
| 1507 | // Check the memory permission. | ||
| 1508 | R_UNLESS(IsValidUnmapFromOwnerCodeMemoryPermission(perm), ResultInvalidNewMemoryPermission); | ||
| 1509 | |||
| 1510 | // Unmap the memory from its owner. | ||
| 1511 | R_TRY(code_mem->UnmapFromOwner(address, size)); | ||
| 1512 | } break; | ||
| 1513 | default: | ||
| 1514 | return ResultInvalidEnumValue; | ||
| 1515 | } | ||
| 1516 | |||
| 1517 | return ResultSuccess; | ||
| 1518 | } | ||
| 1519 | |||
| 1265 | static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address, | 1520 | static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address, |
| 1266 | VAddr page_info_address, Handle process_handle, | 1521 | VAddr page_info_address, Handle process_handle, |
| 1267 | VAddr address) { | 1522 | VAddr address) { |
| @@ -1459,10 +1714,14 @@ static void ExitProcess32(Core::System& system) { | |||
| 1459 | ExitProcess(system); | 1714 | ExitProcess(system); |
| 1460 | } | 1715 | } |
| 1461 | 1716 | ||
| 1462 | static constexpr bool IsValidVirtualCoreId(int32_t core_id) { | 1717 | namespace { |
| 1718 | |||
| 1719 | constexpr bool IsValidVirtualCoreId(int32_t core_id) { | ||
| 1463 | return (0 <= core_id && core_id < static_cast<int32_t>(Core::Hardware::NUM_CPU_CORES)); | 1720 | return (0 <= core_id && core_id < static_cast<int32_t>(Core::Hardware::NUM_CPU_CORES)); |
| 1464 | } | 1721 | } |
| 1465 | 1722 | ||
| 1723 | } // Anonymous namespace | ||
| 1724 | |||
| 1466 | /// Creates a new thread | 1725 | /// Creates a new thread |
| 1467 | static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point, u64 arg, | 1726 | static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point, u64 arg, |
| 1468 | VAddr stack_bottom, u32 priority, s32 core_id) { | 1727 | VAddr stack_bottom, u32 priority, s32 core_id) { |
| @@ -1846,7 +2105,9 @@ static ResultCode ResetSignal32(Core::System& system, Handle handle) { | |||
| 1846 | return ResetSignal(system, handle); | 2105 | return ResetSignal(system, handle); |
| 1847 | } | 2106 | } |
| 1848 | 2107 | ||
| 1849 | static constexpr bool IsValidTransferMemoryPermission(MemoryPermission perm) { | 2108 | namespace { |
| 2109 | |||
| 2110 | constexpr bool IsValidTransferMemoryPermission(MemoryPermission perm) { | ||
| 1850 | switch (perm) { | 2111 | switch (perm) { |
| 1851 | case MemoryPermission::None: | 2112 | case MemoryPermission::None: |
| 1852 | case MemoryPermission::Read: | 2113 | case MemoryPermission::Read: |
| @@ -1857,6 +2118,8 @@ static constexpr bool IsValidTransferMemoryPermission(MemoryPermission perm) { | |||
| 1857 | } | 2118 | } |
| 1858 | } | 2119 | } |
| 1859 | 2120 | ||
| 2121 | } // Anonymous namespace | ||
| 2122 | |||
| 1860 | /// Creates a TransferMemory object | 2123 | /// Creates a TransferMemory object |
| 1861 | static ResultCode CreateTransferMemory(Core::System& system, Handle* out, VAddr address, u64 size, | 2124 | static ResultCode CreateTransferMemory(Core::System& system, Handle* out, VAddr address, u64 size, |
| 1862 | MemoryPermission map_perm) { | 2125 | MemoryPermission map_perm) { |
| @@ -2548,8 +2811,8 @@ static const FunctionDef SVC_Table_64[] = { | |||
| 2548 | {0x48, nullptr, "MapPhysicalMemoryUnsafe"}, | 2811 | {0x48, nullptr, "MapPhysicalMemoryUnsafe"}, |
| 2549 | {0x49, nullptr, "UnmapPhysicalMemoryUnsafe"}, | 2812 | {0x49, nullptr, "UnmapPhysicalMemoryUnsafe"}, |
| 2550 | {0x4A, nullptr, "SetUnsafeLimit"}, | 2813 | {0x4A, nullptr, "SetUnsafeLimit"}, |
| 2551 | {0x4B, nullptr, "CreateCodeMemory"}, | 2814 | {0x4B, SvcWrap64<CreateCodeMemory>, "CreateCodeMemory"}, |
| 2552 | {0x4C, nullptr, "ControlCodeMemory"}, | 2815 | {0x4C, SvcWrap64<ControlCodeMemory>, "ControlCodeMemory"}, |
| 2553 | {0x4D, nullptr, "SleepSystem"}, | 2816 | {0x4D, nullptr, "SleepSystem"}, |
| 2554 | {0x4E, nullptr, "ReadWriteRegister"}, | 2817 | {0x4E, nullptr, "ReadWriteRegister"}, |
| 2555 | {0x4F, nullptr, "SetProcessActivity"}, | 2818 | {0x4F, nullptr, "SetProcessActivity"}, |
| @@ -2588,9 +2851,9 @@ static const FunctionDef SVC_Table_64[] = { | |||
| 2588 | {0x70, nullptr, "CreatePort"}, | 2851 | {0x70, nullptr, "CreatePort"}, |
| 2589 | {0x71, nullptr, "ManageNamedPort"}, | 2852 | {0x71, nullptr, "ManageNamedPort"}, |
| 2590 | {0x72, nullptr, "ConnectToPort"}, | 2853 | {0x72, nullptr, "ConnectToPort"}, |
| 2591 | {0x73, nullptr, "SetProcessMemoryPermission"}, | 2854 | {0x73, SvcWrap64<SetProcessMemoryPermission>, "SetProcessMemoryPermission"}, |
| 2592 | {0x74, nullptr, "MapProcessMemory"}, | 2855 | {0x74, SvcWrap64<MapProcessMemory>, "MapProcessMemory"}, |
| 2593 | {0x75, nullptr, "UnmapProcessMemory"}, | 2856 | {0x75, SvcWrap64<UnmapProcessMemory>, "UnmapProcessMemory"}, |
| 2594 | {0x76, SvcWrap64<QueryProcessMemory>, "QueryProcessMemory"}, | 2857 | {0x76, SvcWrap64<QueryProcessMemory>, "QueryProcessMemory"}, |
| 2595 | {0x77, SvcWrap64<MapProcessCodeMemory>, "MapProcessCodeMemory"}, | 2858 | {0x77, SvcWrap64<MapProcessCodeMemory>, "MapProcessCodeMemory"}, |
| 2596 | {0x78, SvcWrap64<UnmapProcessCodeMemory>, "UnmapProcessCodeMemory"}, | 2859 | {0x78, SvcWrap64<UnmapProcessCodeMemory>, "UnmapProcessCodeMemory"}, |