summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/svc.cpp
diff options
context:
space:
mode:
authorGravatar raven022018-09-19 19:53:11 +0800
committerGravatar GitHub2018-09-19 19:53:11 +0800
commitc8f9bbbf859c0e38cf691b64c67761382fcebfc2 (patch)
tree99529c2277a6b740a6e278985c5147fa649c5497 /src/core/hle/kernel/svc.cpp
parentAdd 1D sampler for TLDS - TexelFetch (Mario Rabbids) (diff)
parentMerge pull request #1348 from ogniK5377/GetImageSize (diff)
downloadyuzu-c8f9bbbf859c0e38cf691b64c67761382fcebfc2.tar.gz
yuzu-c8f9bbbf859c0e38cf691b64c67761382fcebfc2.tar.xz
yuzu-c8f9bbbf859c0e38cf691b64c67761382fcebfc2.zip
Merge branch 'master' into tlds
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
-rw-r--r--src/core/hle/kernel/svc.cpp128
1 files changed, 95 insertions, 33 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index f500fd2e7..371fc439e 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -35,10 +35,21 @@
35#include "core/hle/service/service.h" 35#include "core/hle/service/service.h"
36 36
37namespace Kernel { 37namespace Kernel {
38namespace {
39constexpr bool Is4KBAligned(VAddr address) {
40 return (address & 0xFFF) == 0;
41}
42} // Anonymous namespace
38 43
39/// Set the process heap to a given Size. It can both extend and shrink the heap. 44/// Set the process heap to a given Size. It can both extend and shrink the heap.
40static ResultCode SetHeapSize(VAddr* heap_addr, u64 heap_size) { 45static ResultCode SetHeapSize(VAddr* heap_addr, u64 heap_size) {
41 LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", heap_size); 46 LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", heap_size);
47
48 // Size must be a multiple of 0x200000 (2MB) and be equal to or less than 4GB.
49 if ((heap_size & 0xFFFFFFFE001FFFFF) != 0) {
50 return ERR_INVALID_SIZE;
51 }
52
42 auto& process = *Core::CurrentProcess(); 53 auto& process = *Core::CurrentProcess();
43 CASCADE_RESULT(*heap_addr, 54 CASCADE_RESULT(*heap_addr,
44 process.HeapAllocate(Memory::HEAP_VADDR, heap_size, VMAPermission::ReadWrite)); 55 process.HeapAllocate(Memory::HEAP_VADDR, heap_size, VMAPermission::ReadWrite));
@@ -56,6 +67,15 @@ static ResultCode SetMemoryAttribute(VAddr addr, u64 size, u32 state0, u32 state
56static ResultCode MapMemory(VAddr dst_addr, VAddr src_addr, u64 size) { 67static ResultCode MapMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
57 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, 68 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
58 src_addr, size); 69 src_addr, size);
70
71 if (!Is4KBAligned(dst_addr) || !Is4KBAligned(src_addr)) {
72 return ERR_INVALID_ADDRESS;
73 }
74
75 if (size == 0 || !Is4KBAligned(size)) {
76 return ERR_INVALID_SIZE;
77 }
78
59 return Core::CurrentProcess()->MirrorMemory(dst_addr, src_addr, size); 79 return Core::CurrentProcess()->MirrorMemory(dst_addr, src_addr, size);
60} 80}
61 81
@@ -63,6 +83,15 @@ static ResultCode MapMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
63static ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size) { 83static ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
64 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, 84 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
65 src_addr, size); 85 src_addr, size);
86
87 if (!Is4KBAligned(dst_addr) || !Is4KBAligned(src_addr)) {
88 return ERR_INVALID_ADDRESS;
89 }
90
91 if (size == 0 || !Is4KBAligned(size)) {
92 return ERR_INVALID_SIZE;
93 }
94
66 return Core::CurrentProcess()->UnmapMemory(dst_addr, src_addr, size); 95 return Core::CurrentProcess()->UnmapMemory(dst_addr, src_addr, size);
67} 96}
68 97
@@ -146,7 +175,7 @@ static ResultCode GetProcessId(u32* process_id, Handle process_handle) {
146 175
147/// Default thread wakeup callback for WaitSynchronization 176/// Default thread wakeup callback for WaitSynchronization
148static bool DefaultThreadWakeupCallback(ThreadWakeupReason reason, SharedPtr<Thread> thread, 177static bool DefaultThreadWakeupCallback(ThreadWakeupReason reason, SharedPtr<Thread> thread,
149 SharedPtr<WaitObject> object, size_t index) { 178 SharedPtr<WaitObject> object, std::size_t index) {
150 ASSERT(thread->status == ThreadStatus::WaitSynchAny); 179 ASSERT(thread->status == ThreadStatus::WaitSynchAny);
151 180
152 if (reason == ThreadWakeupReason::Timeout) { 181 if (reason == ThreadWakeupReason::Timeout) {
@@ -251,6 +280,10 @@ static ResultCode ArbitrateLock(Handle holding_thread_handle, VAddr mutex_addr,
251 "requesting_current_thread_handle=0x{:08X}", 280 "requesting_current_thread_handle=0x{:08X}",
252 holding_thread_handle, mutex_addr, requesting_thread_handle); 281 holding_thread_handle, mutex_addr, requesting_thread_handle);
253 282
283 if (Memory::IsKernelVirtualAddress(mutex_addr)) {
284 return ERR_INVALID_ADDRESS_STATE;
285 }
286
254 auto& handle_table = Core::System::GetInstance().Kernel().HandleTable(); 287 auto& handle_table = Core::System::GetInstance().Kernel().HandleTable();
255 return Mutex::TryAcquire(handle_table, mutex_addr, holding_thread_handle, 288 return Mutex::TryAcquire(handle_table, mutex_addr, holding_thread_handle,
256 requesting_thread_handle); 289 requesting_thread_handle);
@@ -260,6 +293,10 @@ static ResultCode ArbitrateLock(Handle holding_thread_handle, VAddr mutex_addr,
260static ResultCode ArbitrateUnlock(VAddr mutex_addr) { 293static ResultCode ArbitrateUnlock(VAddr mutex_addr) {
261 LOG_TRACE(Kernel_SVC, "called mutex_addr=0x{:X}", mutex_addr); 294 LOG_TRACE(Kernel_SVC, "called mutex_addr=0x{:X}", mutex_addr);
262 295
296 if (Memory::IsKernelVirtualAddress(mutex_addr)) {
297 return ERR_INVALID_ADDRESS_STATE;
298 }
299
263 return Mutex::Release(mutex_addr); 300 return Mutex::Release(mutex_addr);
264} 301}
265 302
@@ -415,35 +452,43 @@ static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 s
415 "called, shared_memory_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}", 452 "called, shared_memory_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}",
416 shared_memory_handle, addr, size, permissions); 453 shared_memory_handle, addr, size, permissions);
417 454
455 if (!Is4KBAligned(addr)) {
456 return ERR_INVALID_ADDRESS;
457 }
458
459 if (size == 0 || !Is4KBAligned(size)) {
460 return ERR_INVALID_SIZE;
461 }
462
463 const auto permissions_type = static_cast<MemoryPermission>(permissions);
464 if (permissions_type != MemoryPermission::Read &&
465 permissions_type != MemoryPermission::ReadWrite) {
466 LOG_ERROR(Kernel_SVC, "Invalid permissions=0x{:08X}", permissions);
467 return ERR_INVALID_MEMORY_PERMISSIONS;
468 }
469
418 auto& kernel = Core::System::GetInstance().Kernel(); 470 auto& kernel = Core::System::GetInstance().Kernel();
419 auto shared_memory = kernel.HandleTable().Get<SharedMemory>(shared_memory_handle); 471 auto shared_memory = kernel.HandleTable().Get<SharedMemory>(shared_memory_handle);
420 if (!shared_memory) { 472 if (!shared_memory) {
421 return ERR_INVALID_HANDLE; 473 return ERR_INVALID_HANDLE;
422 } 474 }
423 475
424 MemoryPermission permissions_type = static_cast<MemoryPermission>(permissions); 476 return shared_memory->Map(Core::CurrentProcess().get(), addr, permissions_type,
425 switch (permissions_type) { 477 MemoryPermission::DontCare);
426 case MemoryPermission::Read:
427 case MemoryPermission::Write:
428 case MemoryPermission::ReadWrite:
429 case MemoryPermission::Execute:
430 case MemoryPermission::ReadExecute:
431 case MemoryPermission::WriteExecute:
432 case MemoryPermission::ReadWriteExecute:
433 case MemoryPermission::DontCare:
434 return shared_memory->Map(Core::CurrentProcess().get(), addr, permissions_type,
435 MemoryPermission::DontCare);
436 default:
437 LOG_ERROR(Kernel_SVC, "unknown permissions=0x{:08X}", permissions);
438 }
439
440 return RESULT_SUCCESS;
441} 478}
442 479
443static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size) { 480static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size) {
444 LOG_WARNING(Kernel_SVC, "called, shared_memory_handle=0x{:08X}, addr=0x{:X}, size=0x{:X}", 481 LOG_WARNING(Kernel_SVC, "called, shared_memory_handle=0x{:08X}, addr=0x{:X}, size=0x{:X}",
445 shared_memory_handle, addr, size); 482 shared_memory_handle, addr, size);
446 483
484 if (!Is4KBAligned(addr)) {
485 return ERR_INVALID_ADDRESS;
486 }
487
488 if (size == 0 || !Is4KBAligned(size)) {
489 return ERR_INVALID_SIZE;
490 }
491
447 auto& kernel = Core::System::GetInstance().Kernel(); 492 auto& kernel = Core::System::GetInstance().Kernel();
448 auto shared_memory = kernel.HandleTable().Get<SharedMemory>(shared_memory_handle); 493 auto shared_memory = kernel.HandleTable().Get<SharedMemory>(shared_memory_handle);
449 494
@@ -524,7 +569,7 @@ static void ExitProcess() {
524/// Creates a new thread 569/// Creates a new thread
525static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, VAddr stack_top, 570static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, VAddr stack_top,
526 u32 priority, s32 processor_id) { 571 u32 priority, s32 processor_id) {
527 std::string name = fmt::format("unknown-{:X}", entry_point); 572 std::string name = fmt::format("thread-{:X}", entry_point);
528 573
529 if (priority > THREADPRIO_LOWEST) { 574 if (priority > THREADPRIO_LOWEST) {
530 return ERR_INVALID_THREAD_PRIORITY; 575 return ERR_INVALID_THREAD_PRIORITY;
@@ -647,16 +692,17 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
647 LOG_TRACE(Kernel_SVC, "called, condition_variable_addr=0x{:X}, target=0x{:08X}", 692 LOG_TRACE(Kernel_SVC, "called, condition_variable_addr=0x{:X}, target=0x{:08X}",
648 condition_variable_addr, target); 693 condition_variable_addr, target);
649 694
650 auto RetrieveWaitingThreads = 695 auto RetrieveWaitingThreads = [](std::size_t core_index,
651 [](size_t core_index, std::vector<SharedPtr<Thread>>& waiting_threads, VAddr condvar_addr) { 696 std::vector<SharedPtr<Thread>>& waiting_threads,
652 const auto& scheduler = Core::System::GetInstance().Scheduler(core_index); 697 VAddr condvar_addr) {
653 auto& thread_list = scheduler->GetThreadList(); 698 const auto& scheduler = Core::System::GetInstance().Scheduler(core_index);
699 auto& thread_list = scheduler->GetThreadList();
654 700
655 for (auto& thread : thread_list) { 701 for (auto& thread : thread_list) {
656 if (thread->condvar_wait_address == condvar_addr) 702 if (thread->condvar_wait_address == condvar_addr)
657 waiting_threads.push_back(thread); 703 waiting_threads.push_back(thread);
658 } 704 }
659 }; 705 };
660 706
661 // Retrieve a list of all threads that are waiting for this condition variable. 707 // Retrieve a list of all threads that are waiting for this condition variable.
662 std::vector<SharedPtr<Thread>> waiting_threads; 708 std::vector<SharedPtr<Thread>> waiting_threads;
@@ -672,7 +718,7 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
672 718
673 // Only process up to 'target' threads, unless 'target' is -1, in which case process 719 // Only process up to 'target' threads, unless 'target' is -1, in which case process
674 // them all. 720 // them all.
675 size_t last = waiting_threads.size(); 721 std::size_t last = waiting_threads.size();
676 if (target != -1) 722 if (target != -1)
677 last = target; 723 last = target;
678 724
@@ -680,12 +726,12 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
680 if (last > waiting_threads.size()) 726 if (last > waiting_threads.size())
681 return RESULT_SUCCESS; 727 return RESULT_SUCCESS;
682 728
683 for (size_t index = 0; index < last; ++index) { 729 for (std::size_t index = 0; index < last; ++index) {
684 auto& thread = waiting_threads[index]; 730 auto& thread = waiting_threads[index];
685 731
686 ASSERT(thread->condvar_wait_address == condition_variable_addr); 732 ASSERT(thread->condvar_wait_address == condition_variable_addr);
687 733
688 size_t current_core = Core::System::GetInstance().CurrentCoreIndex(); 734 std::size_t current_core = Core::System::GetInstance().CurrentCoreIndex();
689 735
690 auto& monitor = Core::System::GetInstance().Monitor(); 736 auto& monitor = Core::System::GetInstance().Monitor();
691 737
@@ -898,12 +944,28 @@ static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permiss
898 LOG_TRACE(Kernel_SVC, "called, size=0x{:X}, localPerms=0x{:08X}, remotePerms=0x{:08X}", size, 944 LOG_TRACE(Kernel_SVC, "called, size=0x{:X}, localPerms=0x{:08X}, remotePerms=0x{:08X}", size,
899 local_permissions, remote_permissions); 945 local_permissions, remote_permissions);
900 946
947 // Size must be a multiple of 4KB and be less than or equal to
948 // approx. 8 GB (actually (1GB - 512B) * 8)
949 if (size == 0 || (size & 0xFFFFFFFE00000FFF) != 0) {
950 return ERR_INVALID_SIZE;
951 }
952
953 const auto local_perms = static_cast<MemoryPermission>(local_permissions);
954 if (local_perms != MemoryPermission::Read && local_perms != MemoryPermission::ReadWrite) {
955 return ERR_INVALID_MEMORY_PERMISSIONS;
956 }
957
958 const auto remote_perms = static_cast<MemoryPermission>(remote_permissions);
959 if (remote_perms != MemoryPermission::Read && remote_perms != MemoryPermission::ReadWrite &&
960 remote_perms != MemoryPermission::DontCare) {
961 return ERR_INVALID_MEMORY_PERMISSIONS;
962 }
963
901 auto& kernel = Core::System::GetInstance().Kernel(); 964 auto& kernel = Core::System::GetInstance().Kernel();
902 auto& handle_table = kernel.HandleTable(); 965 auto& handle_table = kernel.HandleTable();
903 auto shared_mem_handle = 966 auto shared_mem_handle =
904 SharedMemory::Create(kernel, handle_table.Get<Process>(KernelHandle::CurrentProcess), size, 967 SharedMemory::Create(kernel, handle_table.Get<Process>(KernelHandle::CurrentProcess), size,
905 static_cast<MemoryPermission>(local_permissions), 968 local_perms, remote_perms);
906 static_cast<MemoryPermission>(remote_permissions));
907 969
908 CASCADE_RESULT(*handle, handle_table.Create(shared_mem_handle)); 970 CASCADE_RESULT(*handle, handle_table.Create(shared_mem_handle));
909 return RESULT_SUCCESS; 971 return RESULT_SUCCESS;