diff options
| author | 2020-06-28 12:37:50 -0400 | |
|---|---|---|
| committer | 2020-06-28 12:37:50 -0400 | |
| commit | b05795d704e0c194215f815a5703db09e524b59a (patch) | |
| tree | ecf4023b4ee0c91555c1d8263762fcb9dcb04a17 /src/core/hle/kernel/svc.cpp | |
| parent | Merge pull request #4196 from ogniK5377/nrr-nro-fixes (diff) | |
| parent | Core/Common: Address Feedback. (diff) | |
| download | yuzu-b05795d704e0c194215f815a5703db09e524b59a.tar.gz yuzu-b05795d704e0c194215f815a5703db09e524b59a.tar.xz yuzu-b05795d704e0c194215f815a5703db09e524b59a.zip | |
Merge pull request #3955 from FernandoS27/prometheus-2b
Remake Kernel Scheduling, CPU Management & Boot Management (Prometheus)
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 464 |
1 files changed, 339 insertions, 125 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 4ae4529f5..5db19dcf3 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -10,14 +10,15 @@ | |||
| 10 | 10 | ||
| 11 | #include "common/alignment.h" | 11 | #include "common/alignment.h" |
| 12 | #include "common/assert.h" | 12 | #include "common/assert.h" |
| 13 | #include "common/fiber.h" | ||
| 13 | #include "common/logging/log.h" | 14 | #include "common/logging/log.h" |
| 14 | #include "common/microprofile.h" | 15 | #include "common/microprofile.h" |
| 15 | #include "common/string_util.h" | 16 | #include "common/string_util.h" |
| 16 | #include "core/arm/exclusive_monitor.h" | 17 | #include "core/arm/exclusive_monitor.h" |
| 17 | #include "core/core.h" | 18 | #include "core/core.h" |
| 18 | #include "core/core_manager.h" | ||
| 19 | #include "core/core_timing.h" | 19 | #include "core/core_timing.h" |
| 20 | #include "core/core_timing_util.h" | 20 | #include "core/core_timing_util.h" |
| 21 | #include "core/cpu_manager.h" | ||
| 21 | #include "core/hle/kernel/address_arbiter.h" | 22 | #include "core/hle/kernel/address_arbiter.h" |
| 22 | #include "core/hle/kernel/client_port.h" | 23 | #include "core/hle/kernel/client_port.h" |
| 23 | #include "core/hle/kernel/client_session.h" | 24 | #include "core/hle/kernel/client_session.h" |
| @@ -27,6 +28,7 @@ | |||
| 27 | #include "core/hle/kernel/memory/memory_block.h" | 28 | #include "core/hle/kernel/memory/memory_block.h" |
| 28 | #include "core/hle/kernel/memory/page_table.h" | 29 | #include "core/hle/kernel/memory/page_table.h" |
| 29 | #include "core/hle/kernel/mutex.h" | 30 | #include "core/hle/kernel/mutex.h" |
| 31 | #include "core/hle/kernel/physical_core.h" | ||
| 30 | #include "core/hle/kernel/process.h" | 32 | #include "core/hle/kernel/process.h" |
| 31 | #include "core/hle/kernel/readable_event.h" | 33 | #include "core/hle/kernel/readable_event.h" |
| 32 | #include "core/hle/kernel/resource_limit.h" | 34 | #include "core/hle/kernel/resource_limit.h" |
| @@ -37,6 +39,7 @@ | |||
| 37 | #include "core/hle/kernel/svc_wrap.h" | 39 | #include "core/hle/kernel/svc_wrap.h" |
| 38 | #include "core/hle/kernel/synchronization.h" | 40 | #include "core/hle/kernel/synchronization.h" |
| 39 | #include "core/hle/kernel/thread.h" | 41 | #include "core/hle/kernel/thread.h" |
| 42 | #include "core/hle/kernel/time_manager.h" | ||
| 40 | #include "core/hle/kernel/transfer_memory.h" | 43 | #include "core/hle/kernel/transfer_memory.h" |
| 41 | #include "core/hle/kernel/writable_event.h" | 44 | #include "core/hle/kernel/writable_event.h" |
| 42 | #include "core/hle/lock.h" | 45 | #include "core/hle/lock.h" |
| @@ -133,6 +136,7 @@ enum class ResourceLimitValueType { | |||
| 133 | 136 | ||
| 134 | ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_limit, | 137 | ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_limit, |
| 135 | u32 resource_type, ResourceLimitValueType value_type) { | 138 | u32 resource_type, ResourceLimitValueType value_type) { |
| 139 | std::lock_guard lock{HLE::g_hle_lock}; | ||
| 136 | const auto type = static_cast<ResourceType>(resource_type); | 140 | const auto type = static_cast<ResourceType>(resource_type); |
| 137 | if (!IsValidResourceType(type)) { | 141 | if (!IsValidResourceType(type)) { |
| 138 | LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type); | 142 | LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type); |
| @@ -160,6 +164,7 @@ ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_ | |||
| 160 | 164 | ||
| 161 | /// Set the process heap to a given Size. It can both extend and shrink the heap. | 165 | /// Set the process heap to a given Size. It can both extend and shrink the heap. |
| 162 | static ResultCode SetHeapSize(Core::System& system, VAddr* heap_addr, u64 heap_size) { | 166 | static ResultCode SetHeapSize(Core::System& system, VAddr* heap_addr, u64 heap_size) { |
| 167 | std::lock_guard lock{HLE::g_hle_lock}; | ||
| 163 | LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", heap_size); | 168 | LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", heap_size); |
| 164 | 169 | ||
| 165 | // Size must be a multiple of 0x200000 (2MB) and be equal to or less than 8GB. | 170 | // Size must be a multiple of 0x200000 (2MB) and be equal to or less than 8GB. |
| @@ -190,6 +195,7 @@ static ResultCode SetHeapSize32(Core::System& system, u32* heap_addr, u32 heap_s | |||
| 190 | 195 | ||
| 191 | static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mask, | 196 | static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mask, |
| 192 | u32 attribute) { | 197 | u32 attribute) { |
| 198 | std::lock_guard lock{HLE::g_hle_lock}; | ||
| 193 | LOG_DEBUG(Kernel_SVC, | 199 | LOG_DEBUG(Kernel_SVC, |
| 194 | "called, address=0x{:016X}, size=0x{:X}, mask=0x{:08X}, attribute=0x{:08X}", address, | 200 | "called, address=0x{:016X}, size=0x{:X}, mask=0x{:08X}, attribute=0x{:08X}", address, |
| 195 | size, mask, attribute); | 201 | size, mask, attribute); |
| @@ -226,8 +232,15 @@ static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 si | |||
| 226 | static_cast<Memory::MemoryAttribute>(attribute)); | 232 | static_cast<Memory::MemoryAttribute>(attribute)); |
| 227 | } | 233 | } |
| 228 | 234 | ||
| 235 | static ResultCode SetMemoryAttribute32(Core::System& system, u32 address, u32 size, u32 mask, | ||
| 236 | u32 attribute) { | ||
| 237 | return SetMemoryAttribute(system, static_cast<VAddr>(address), static_cast<std::size_t>(size), | ||
| 238 | mask, attribute); | ||
| 239 | } | ||
| 240 | |||
| 229 | /// Maps a memory range into a different range. | 241 | /// Maps a memory range into a different range. |
| 230 | static ResultCode MapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) { | 242 | static ResultCode MapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) { |
| 243 | std::lock_guard lock{HLE::g_hle_lock}; | ||
| 231 | LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, | 244 | LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, |
| 232 | src_addr, size); | 245 | src_addr, size); |
| 233 | 246 | ||
| @@ -241,8 +254,14 @@ static ResultCode MapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr | |||
| 241 | return page_table.Map(dst_addr, src_addr, size); | 254 | return page_table.Map(dst_addr, src_addr, size); |
| 242 | } | 255 | } |
| 243 | 256 | ||
| 257 | static ResultCode MapMemory32(Core::System& system, u32 dst_addr, u32 src_addr, u32 size) { | ||
| 258 | return MapMemory(system, static_cast<VAddr>(dst_addr), static_cast<VAddr>(src_addr), | ||
| 259 | static_cast<std::size_t>(size)); | ||
| 260 | } | ||
| 261 | |||
| 244 | /// Unmaps a region that was previously mapped with svcMapMemory | 262 | /// Unmaps a region that was previously mapped with svcMapMemory |
| 245 | static ResultCode UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) { | 263 | static ResultCode UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) { |
| 264 | std::lock_guard lock{HLE::g_hle_lock}; | ||
| 246 | LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, | 265 | LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, |
| 247 | src_addr, size); | 266 | src_addr, size); |
| 248 | 267 | ||
| @@ -256,9 +275,15 @@ static ResultCode UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_ad | |||
| 256 | return page_table.Unmap(dst_addr, src_addr, size); | 275 | return page_table.Unmap(dst_addr, src_addr, size); |
| 257 | } | 276 | } |
| 258 | 277 | ||
| 278 | static ResultCode UnmapMemory32(Core::System& system, u32 dst_addr, u32 src_addr, u32 size) { | ||
| 279 | return UnmapMemory(system, static_cast<VAddr>(dst_addr), static_cast<VAddr>(src_addr), | ||
| 280 | static_cast<std::size_t>(size)); | ||
| 281 | } | ||
| 282 | |||
| 259 | /// Connect to an OS service given the port name, returns the handle to the port to out | 283 | /// Connect to an OS service given the port name, returns the handle to the port to out |
| 260 | static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle, | 284 | static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle, |
| 261 | VAddr port_name_address) { | 285 | VAddr port_name_address) { |
| 286 | std::lock_guard lock{HLE::g_hle_lock}; | ||
| 262 | auto& memory = system.Memory(); | 287 | auto& memory = system.Memory(); |
| 263 | 288 | ||
| 264 | if (!memory.IsValidVirtualAddress(port_name_address)) { | 289 | if (!memory.IsValidVirtualAddress(port_name_address)) { |
| @@ -317,11 +342,30 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) { | |||
| 317 | LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); | 342 | LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); |
| 318 | 343 | ||
| 319 | auto thread = system.CurrentScheduler().GetCurrentThread(); | 344 | auto thread = system.CurrentScheduler().GetCurrentThread(); |
| 320 | thread->InvalidateWakeupCallback(); | 345 | { |
| 321 | thread->SetStatus(ThreadStatus::WaitIPC); | 346 | SchedulerLock lock(system.Kernel()); |
| 322 | system.PrepareReschedule(thread->GetProcessorID()); | 347 | thread->InvalidateHLECallback(); |
| 348 | thread->SetStatus(ThreadStatus::WaitIPC); | ||
| 349 | session->SendSyncRequest(SharedFrom(thread), system.Memory()); | ||
| 350 | } | ||
| 351 | |||
| 352 | if (thread->HasHLECallback()) { | ||
| 353 | Handle event_handle = thread->GetHLETimeEvent(); | ||
| 354 | if (event_handle != InvalidHandle) { | ||
| 355 | auto& time_manager = system.Kernel().TimeManager(); | ||
| 356 | time_manager.UnscheduleTimeEvent(event_handle); | ||
| 357 | } | ||
| 358 | |||
| 359 | { | ||
| 360 | SchedulerLock lock(system.Kernel()); | ||
| 361 | auto* sync_object = thread->GetHLESyncObject(); | ||
| 362 | sync_object->RemoveWaitingThread(SharedFrom(thread)); | ||
| 363 | } | ||
| 364 | |||
| 365 | thread->InvokeHLECallback(SharedFrom(thread)); | ||
| 366 | } | ||
| 323 | 367 | ||
| 324 | return session->SendSyncRequest(SharedFrom(thread), system.Memory()); | 368 | return thread->GetSignalingResult(); |
| 325 | } | 369 | } |
| 326 | 370 | ||
| 327 | static ResultCode SendSyncRequest32(Core::System& system, Handle handle) { | 371 | static ResultCode SendSyncRequest32(Core::System& system, Handle handle) { |
| @@ -383,6 +427,15 @@ static ResultCode GetProcessId(Core::System& system, u64* process_id, Handle han | |||
| 383 | return ERR_INVALID_HANDLE; | 427 | return ERR_INVALID_HANDLE; |
| 384 | } | 428 | } |
| 385 | 429 | ||
| 430 | static ResultCode GetProcessId32(Core::System& system, u32* process_id_low, u32* process_id_high, | ||
| 431 | Handle handle) { | ||
| 432 | u64 process_id{}; | ||
| 433 | const auto result = GetProcessId(system, &process_id, handle); | ||
| 434 | *process_id_low = static_cast<u32>(process_id); | ||
| 435 | *process_id_high = static_cast<u32>(process_id >> 32); | ||
| 436 | return result; | ||
| 437 | } | ||
| 438 | |||
| 386 | /// Wait for the given handles to synchronize, timeout after the specified nanoseconds | 439 | /// Wait for the given handles to synchronize, timeout after the specified nanoseconds |
| 387 | static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr handles_address, | 440 | static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr handles_address, |
| 388 | u64 handle_count, s64 nano_seconds) { | 441 | u64 handle_count, s64 nano_seconds) { |
| @@ -447,10 +500,13 @@ static ResultCode CancelSynchronization(Core::System& system, Handle thread_hand | |||
| 447 | } | 500 | } |
| 448 | 501 | ||
| 449 | thread->CancelWait(); | 502 | thread->CancelWait(); |
| 450 | system.PrepareReschedule(thread->GetProcessorID()); | ||
| 451 | return RESULT_SUCCESS; | 503 | return RESULT_SUCCESS; |
| 452 | } | 504 | } |
| 453 | 505 | ||
| 506 | static ResultCode CancelSynchronization32(Core::System& system, Handle thread_handle) { | ||
| 507 | return CancelSynchronization(system, thread_handle); | ||
| 508 | } | ||
| 509 | |||
| 454 | /// Attempts to locks a mutex, creating it if it does not already exist | 510 | /// Attempts to locks a mutex, creating it if it does not already exist |
| 455 | static ResultCode ArbitrateLock(Core::System& system, Handle holding_thread_handle, | 511 | static ResultCode ArbitrateLock(Core::System& system, Handle holding_thread_handle, |
| 456 | VAddr mutex_addr, Handle requesting_thread_handle) { | 512 | VAddr mutex_addr, Handle requesting_thread_handle) { |
| @@ -475,6 +531,12 @@ static ResultCode ArbitrateLock(Core::System& system, Handle holding_thread_hand | |||
| 475 | requesting_thread_handle); | 531 | requesting_thread_handle); |
| 476 | } | 532 | } |
| 477 | 533 | ||
| 534 | static ResultCode ArbitrateLock32(Core::System& system, Handle holding_thread_handle, | ||
| 535 | u32 mutex_addr, Handle requesting_thread_handle) { | ||
| 536 | return ArbitrateLock(system, holding_thread_handle, static_cast<VAddr>(mutex_addr), | ||
| 537 | requesting_thread_handle); | ||
| 538 | } | ||
| 539 | |||
| 478 | /// Unlock a mutex | 540 | /// Unlock a mutex |
| 479 | static ResultCode ArbitrateUnlock(Core::System& system, VAddr mutex_addr) { | 541 | static ResultCode ArbitrateUnlock(Core::System& system, VAddr mutex_addr) { |
| 480 | LOG_TRACE(Kernel_SVC, "called mutex_addr=0x{:X}", mutex_addr); | 542 | LOG_TRACE(Kernel_SVC, "called mutex_addr=0x{:X}", mutex_addr); |
| @@ -494,6 +556,10 @@ static ResultCode ArbitrateUnlock(Core::System& system, VAddr mutex_addr) { | |||
| 494 | return current_process->GetMutex().Release(mutex_addr); | 556 | return current_process->GetMutex().Release(mutex_addr); |
| 495 | } | 557 | } |
| 496 | 558 | ||
| 559 | static ResultCode ArbitrateUnlock32(Core::System& system, u32 mutex_addr) { | ||
| 560 | return ArbitrateUnlock(system, static_cast<VAddr>(mutex_addr)); | ||
| 561 | } | ||
| 562 | |||
| 497 | enum class BreakType : u32 { | 563 | enum class BreakType : u32 { |
| 498 | Panic = 0, | 564 | Panic = 0, |
| 499 | AssertionFailed = 1, | 565 | AssertionFailed = 1, |
| @@ -594,6 +660,7 @@ static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) { | |||
| 594 | info2, has_dumped_buffer ? std::make_optional(debug_buffer) : std::nullopt); | 660 | info2, has_dumped_buffer ? std::make_optional(debug_buffer) : std::nullopt); |
| 595 | 661 | ||
| 596 | if (!break_reason.signal_debugger) { | 662 | if (!break_reason.signal_debugger) { |
| 663 | SchedulerLock lock(system.Kernel()); | ||
| 597 | LOG_CRITICAL( | 664 | LOG_CRITICAL( |
| 598 | Debug_Emulated, | 665 | Debug_Emulated, |
| 599 | "Emulated program broke execution! reason=0x{:016X}, info1=0x{:016X}, info2=0x{:016X}", | 666 | "Emulated program broke execution! reason=0x{:016X}, info1=0x{:016X}, info2=0x{:016X}", |
| @@ -605,14 +672,16 @@ static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) { | |||
| 605 | const auto thread_processor_id = current_thread->GetProcessorID(); | 672 | const auto thread_processor_id = current_thread->GetProcessorID(); |
| 606 | system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace(); | 673 | system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace(); |
| 607 | 674 | ||
| 608 | system.Kernel().CurrentProcess()->PrepareForTermination(); | ||
| 609 | |||
| 610 | // Kill the current thread | 675 | // Kill the current thread |
| 676 | system.Kernel().ExceptionalExit(); | ||
| 611 | current_thread->Stop(); | 677 | current_thread->Stop(); |
| 612 | system.PrepareReschedule(); | ||
| 613 | } | 678 | } |
| 614 | } | 679 | } |
| 615 | 680 | ||
| 681 | static void Break32(Core::System& system, u32 reason, u32 info1, u32 info2) { | ||
| 682 | Break(system, reason, static_cast<u64>(info1), static_cast<u64>(info2)); | ||
| 683 | } | ||
| 684 | |||
| 616 | /// Used to output a message on a debug hardware unit - does nothing on a retail unit | 685 | /// Used to output a message on a debug hardware unit - does nothing on a retail unit |
| 617 | static void OutputDebugString([[maybe_unused]] Core::System& system, VAddr address, u64 len) { | 686 | static void OutputDebugString([[maybe_unused]] Core::System& system, VAddr address, u64 len) { |
| 618 | if (len == 0) { | 687 | if (len == 0) { |
| @@ -627,6 +696,7 @@ static void OutputDebugString([[maybe_unused]] Core::System& system, VAddr addre | |||
| 627 | /// Gets system/memory information for the current process | 696 | /// Gets system/memory information for the current process |
| 628 | static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 handle, | 697 | static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 handle, |
| 629 | u64 info_sub_id) { | 698 | u64 info_sub_id) { |
| 699 | std::lock_guard lock{HLE::g_hle_lock}; | ||
| 630 | LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}", info_id, | 700 | LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}", info_id, |
| 631 | info_sub_id, handle); | 701 | info_sub_id, handle); |
| 632 | 702 | ||
| @@ -863,9 +933,9 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha | |||
| 863 | if (same_thread && info_sub_id == 0xFFFFFFFFFFFFFFFF) { | 933 | if (same_thread && info_sub_id == 0xFFFFFFFFFFFFFFFF) { |
| 864 | const u64 thread_ticks = current_thread->GetTotalCPUTimeTicks(); | 934 | const u64 thread_ticks = current_thread->GetTotalCPUTimeTicks(); |
| 865 | 935 | ||
| 866 | out_ticks = thread_ticks + (core_timing.GetTicks() - prev_ctx_ticks); | 936 | out_ticks = thread_ticks + (core_timing.GetCPUTicks() - prev_ctx_ticks); |
| 867 | } else if (same_thread && info_sub_id == system.CurrentCoreIndex()) { | 937 | } else if (same_thread && info_sub_id == system.CurrentCoreIndex()) { |
| 868 | out_ticks = core_timing.GetTicks() - prev_ctx_ticks; | 938 | out_ticks = core_timing.GetCPUTicks() - prev_ctx_ticks; |
| 869 | } | 939 | } |
| 870 | 940 | ||
| 871 | *result = out_ticks; | 941 | *result = out_ticks; |
| @@ -892,6 +962,7 @@ static ResultCode GetInfo32(Core::System& system, u32* result_low, u32* result_h | |||
| 892 | 962 | ||
| 893 | /// Maps memory at a desired address | 963 | /// Maps memory at a desired address |
| 894 | static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) { | 964 | static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) { |
| 965 | std::lock_guard lock{HLE::g_hle_lock}; | ||
| 895 | LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size); | 966 | LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size); |
| 896 | 967 | ||
| 897 | if (!Common::Is4KBAligned(addr)) { | 968 | if (!Common::Is4KBAligned(addr)) { |
| @@ -939,8 +1010,13 @@ static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) | |||
| 939 | return page_table.MapPhysicalMemory(addr, size); | 1010 | return page_table.MapPhysicalMemory(addr, size); |
| 940 | } | 1011 | } |
| 941 | 1012 | ||
| 1013 | static ResultCode MapPhysicalMemory32(Core::System& system, u32 addr, u32 size) { | ||
| 1014 | return MapPhysicalMemory(system, static_cast<VAddr>(addr), static_cast<std::size_t>(size)); | ||
| 1015 | } | ||
| 1016 | |||
| 942 | /// Unmaps memory previously mapped via MapPhysicalMemory | 1017 | /// Unmaps memory previously mapped via MapPhysicalMemory |
| 943 | static ResultCode UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size) { | 1018 | static ResultCode UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size) { |
| 1019 | std::lock_guard lock{HLE::g_hle_lock}; | ||
| 944 | LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size); | 1020 | LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size); |
| 945 | 1021 | ||
| 946 | if (!Common::Is4KBAligned(addr)) { | 1022 | if (!Common::Is4KBAligned(addr)) { |
| @@ -988,6 +1064,10 @@ static ResultCode UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size | |||
| 988 | return page_table.UnmapPhysicalMemory(addr, size); | 1064 | return page_table.UnmapPhysicalMemory(addr, size); |
| 989 | } | 1065 | } |
| 990 | 1066 | ||
| 1067 | static ResultCode UnmapPhysicalMemory32(Core::System& system, u32 addr, u32 size) { | ||
| 1068 | return UnmapPhysicalMemory(system, static_cast<VAddr>(addr), static_cast<std::size_t>(size)); | ||
| 1069 | } | ||
| 1070 | |||
| 991 | /// Sets the thread activity | 1071 | /// Sets the thread activity |
| 992 | static ResultCode SetThreadActivity(Core::System& system, Handle handle, u32 activity) { | 1072 | static ResultCode SetThreadActivity(Core::System& system, Handle handle, u32 activity) { |
| 993 | LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", handle, activity); | 1073 | LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", handle, activity); |
| @@ -1017,10 +1097,11 @@ static ResultCode SetThreadActivity(Core::System& system, Handle handle, u32 act | |||
| 1017 | return ERR_BUSY; | 1097 | return ERR_BUSY; |
| 1018 | } | 1098 | } |
| 1019 | 1099 | ||
| 1020 | thread->SetActivity(static_cast<ThreadActivity>(activity)); | 1100 | return thread->SetActivity(static_cast<ThreadActivity>(activity)); |
| 1101 | } | ||
| 1021 | 1102 | ||
| 1022 | system.PrepareReschedule(thread->GetProcessorID()); | 1103 | static ResultCode SetThreadActivity32(Core::System& system, Handle handle, u32 activity) { |
| 1023 | return RESULT_SUCCESS; | 1104 | return SetThreadActivity(system, handle, activity); |
| 1024 | } | 1105 | } |
| 1025 | 1106 | ||
| 1026 | /// Gets the thread context | 1107 | /// Gets the thread context |
| @@ -1064,6 +1145,10 @@ static ResultCode GetThreadContext(Core::System& system, VAddr thread_context, H | |||
| 1064 | return RESULT_SUCCESS; | 1145 | return RESULT_SUCCESS; |
| 1065 | } | 1146 | } |
| 1066 | 1147 | ||
| 1148 | static ResultCode GetThreadContext32(Core::System& system, u32 thread_context, Handle handle) { | ||
| 1149 | return GetThreadContext(system, static_cast<VAddr>(thread_context), handle); | ||
| 1150 | } | ||
| 1151 | |||
| 1067 | /// Gets the priority for the specified thread | 1152 | /// Gets the priority for the specified thread |
| 1068 | static ResultCode GetThreadPriority(Core::System& system, u32* priority, Handle handle) { | 1153 | static ResultCode GetThreadPriority(Core::System& system, u32* priority, Handle handle) { |
| 1069 | LOG_TRACE(Kernel_SVC, "called"); | 1154 | LOG_TRACE(Kernel_SVC, "called"); |
| @@ -1071,6 +1156,7 @@ static ResultCode GetThreadPriority(Core::System& system, u32* priority, Handle | |||
| 1071 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 1156 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); |
| 1072 | const std::shared_ptr<Thread> thread = handle_table.Get<Thread>(handle); | 1157 | const std::shared_ptr<Thread> thread = handle_table.Get<Thread>(handle); |
| 1073 | if (!thread) { | 1158 | if (!thread) { |
| 1159 | *priority = 0; | ||
| 1074 | LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", handle); | 1160 | LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", handle); |
| 1075 | return ERR_INVALID_HANDLE; | 1161 | return ERR_INVALID_HANDLE; |
| 1076 | } | 1162 | } |
| @@ -1105,18 +1191,26 @@ static ResultCode SetThreadPriority(Core::System& system, Handle handle, u32 pri | |||
| 1105 | 1191 | ||
| 1106 | thread->SetPriority(priority); | 1192 | thread->SetPriority(priority); |
| 1107 | 1193 | ||
| 1108 | system.PrepareReschedule(thread->GetProcessorID()); | ||
| 1109 | return RESULT_SUCCESS; | 1194 | return RESULT_SUCCESS; |
| 1110 | } | 1195 | } |
| 1111 | 1196 | ||
| 1197 | static ResultCode SetThreadPriority32(Core::System& system, Handle handle, u32 priority) { | ||
| 1198 | return SetThreadPriority(system, handle, priority); | ||
| 1199 | } | ||
| 1200 | |||
| 1112 | /// Get which CPU core is executing the current thread | 1201 | /// Get which CPU core is executing the current thread |
| 1113 | static u32 GetCurrentProcessorNumber(Core::System& system) { | 1202 | static u32 GetCurrentProcessorNumber(Core::System& system) { |
| 1114 | LOG_TRACE(Kernel_SVC, "called"); | 1203 | LOG_TRACE(Kernel_SVC, "called"); |
| 1115 | return system.CurrentScheduler().GetCurrentThread()->GetProcessorID(); | 1204 | return static_cast<u32>(system.CurrentPhysicalCore().CoreIndex()); |
| 1205 | } | ||
| 1206 | |||
| 1207 | static u32 GetCurrentProcessorNumber32(Core::System& system) { | ||
| 1208 | return GetCurrentProcessorNumber(system); | ||
| 1116 | } | 1209 | } |
| 1117 | 1210 | ||
| 1118 | static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_handle, VAddr addr, | 1211 | static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_handle, VAddr addr, |
| 1119 | u64 size, u32 permissions) { | 1212 | u64 size, u32 permissions) { |
| 1213 | std::lock_guard lock{HLE::g_hle_lock}; | ||
| 1120 | LOG_TRACE(Kernel_SVC, | 1214 | LOG_TRACE(Kernel_SVC, |
| 1121 | "called, shared_memory_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}", | 1215 | "called, shared_memory_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}", |
| 1122 | shared_memory_handle, addr, size, permissions); | 1216 | shared_memory_handle, addr, size, permissions); |
| @@ -1187,9 +1281,16 @@ static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_han | |||
| 1187 | return shared_memory->Map(*current_process, addr, size, permission_type); | 1281 | return shared_memory->Map(*current_process, addr, size, permission_type); |
| 1188 | } | 1282 | } |
| 1189 | 1283 | ||
| 1284 | static ResultCode MapSharedMemory32(Core::System& system, Handle shared_memory_handle, u32 addr, | ||
| 1285 | u32 size, u32 permissions) { | ||
| 1286 | return MapSharedMemory(system, shared_memory_handle, static_cast<VAddr>(addr), | ||
| 1287 | static_cast<std::size_t>(size), permissions); | ||
| 1288 | } | ||
| 1289 | |||
| 1190 | static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address, | 1290 | static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address, |
| 1191 | VAddr page_info_address, Handle process_handle, | 1291 | VAddr page_info_address, Handle process_handle, |
| 1192 | VAddr address) { | 1292 | VAddr address) { |
| 1293 | std::lock_guard lock{HLE::g_hle_lock}; | ||
| 1193 | LOG_TRACE(Kernel_SVC, "called process=0x{:08X} address={:X}", process_handle, address); | 1294 | LOG_TRACE(Kernel_SVC, "called process=0x{:08X} address={:X}", process_handle, address); |
| 1194 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 1295 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); |
| 1195 | std::shared_ptr<Process> process = handle_table.Get<Process>(process_handle); | 1296 | std::shared_ptr<Process> process = handle_table.Get<Process>(process_handle); |
| @@ -1372,6 +1473,7 @@ static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_ha | |||
| 1372 | /// Exits the current process | 1473 | /// Exits the current process |
| 1373 | static void ExitProcess(Core::System& system) { | 1474 | static void ExitProcess(Core::System& system) { |
| 1374 | auto* current_process = system.Kernel().CurrentProcess(); | 1475 | auto* current_process = system.Kernel().CurrentProcess(); |
| 1476 | UNIMPLEMENTED(); | ||
| 1375 | 1477 | ||
| 1376 | LOG_INFO(Kernel_SVC, "Process {} exiting", current_process->GetProcessID()); | 1478 | LOG_INFO(Kernel_SVC, "Process {} exiting", current_process->GetProcessID()); |
| 1377 | ASSERT_MSG(current_process->GetStatus() == ProcessStatus::Running, | 1479 | ASSERT_MSG(current_process->GetStatus() == ProcessStatus::Running, |
| @@ -1381,8 +1483,10 @@ static void ExitProcess(Core::System& system) { | |||
| 1381 | 1483 | ||
| 1382 | // Kill the current thread | 1484 | // Kill the current thread |
| 1383 | system.CurrentScheduler().GetCurrentThread()->Stop(); | 1485 | system.CurrentScheduler().GetCurrentThread()->Stop(); |
| 1486 | } | ||
| 1384 | 1487 | ||
| 1385 | system.PrepareReschedule(); | 1488 | static void ExitProcess32(Core::System& system) { |
| 1489 | ExitProcess(system); | ||
| 1386 | } | 1490 | } |
| 1387 | 1491 | ||
| 1388 | /// Creates a new thread | 1492 | /// Creates a new thread |
| @@ -1428,9 +1532,10 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e | |||
| 1428 | 1532 | ||
| 1429 | ASSERT(kernel.CurrentProcess()->GetResourceLimit()->Reserve(ResourceType::Threads, 1)); | 1533 | ASSERT(kernel.CurrentProcess()->GetResourceLimit()->Reserve(ResourceType::Threads, 1)); |
| 1430 | 1534 | ||
| 1535 | ThreadType type = THREADTYPE_USER; | ||
| 1431 | CASCADE_RESULT(std::shared_ptr<Thread> thread, | 1536 | CASCADE_RESULT(std::shared_ptr<Thread> thread, |
| 1432 | Thread::Create(kernel, "", entry_point, priority, arg, processor_id, stack_top, | 1537 | Thread::Create(system, type, "", entry_point, priority, arg, processor_id, |
| 1433 | *current_process)); | 1538 | stack_top, current_process)); |
| 1434 | 1539 | ||
| 1435 | const auto new_thread_handle = current_process->GetHandleTable().Create(thread); | 1540 | const auto new_thread_handle = current_process->GetHandleTable().Create(thread); |
| 1436 | if (new_thread_handle.Failed()) { | 1541 | if (new_thread_handle.Failed()) { |
| @@ -1444,11 +1549,15 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e | |||
| 1444 | thread->SetName( | 1549 | thread->SetName( |
| 1445 | fmt::format("thread[entry_point={:X}, handle={:X}]", entry_point, *new_thread_handle)); | 1550 | fmt::format("thread[entry_point={:X}, handle={:X}]", entry_point, *new_thread_handle)); |
| 1446 | 1551 | ||
| 1447 | system.PrepareReschedule(thread->GetProcessorID()); | ||
| 1448 | |||
| 1449 | return RESULT_SUCCESS; | 1552 | return RESULT_SUCCESS; |
| 1450 | } | 1553 | } |
| 1451 | 1554 | ||
| 1555 | static ResultCode CreateThread32(Core::System& system, Handle* out_handle, u32 priority, | ||
| 1556 | u32 entry_point, u32 arg, u32 stack_top, s32 processor_id) { | ||
| 1557 | return CreateThread(system, out_handle, static_cast<VAddr>(entry_point), static_cast<u64>(arg), | ||
| 1558 | static_cast<VAddr>(stack_top), priority, processor_id); | ||
| 1559 | } | ||
| 1560 | |||
| 1452 | /// Starts the thread for the provided handle | 1561 | /// Starts the thread for the provided handle |
| 1453 | static ResultCode StartThread(Core::System& system, Handle thread_handle) { | 1562 | static ResultCode StartThread(Core::System& system, Handle thread_handle) { |
| 1454 | LOG_DEBUG(Kernel_SVC, "called thread=0x{:08X}", thread_handle); | 1563 | LOG_DEBUG(Kernel_SVC, "called thread=0x{:08X}", thread_handle); |
| @@ -1463,13 +1572,11 @@ static ResultCode StartThread(Core::System& system, Handle thread_handle) { | |||
| 1463 | 1572 | ||
| 1464 | ASSERT(thread->GetStatus() == ThreadStatus::Dormant); | 1573 | ASSERT(thread->GetStatus() == ThreadStatus::Dormant); |
| 1465 | 1574 | ||
| 1466 | thread->ResumeFromWait(); | 1575 | return thread->Start(); |
| 1467 | 1576 | } | |
| 1468 | if (thread->GetStatus() == ThreadStatus::Ready) { | ||
| 1469 | system.PrepareReschedule(thread->GetProcessorID()); | ||
| 1470 | } | ||
| 1471 | 1577 | ||
| 1472 | return RESULT_SUCCESS; | 1578 | static ResultCode StartThread32(Core::System& system, Handle thread_handle) { |
| 1579 | return StartThread(system, thread_handle); | ||
| 1473 | } | 1580 | } |
| 1474 | 1581 | ||
| 1475 | /// Called when a thread exits | 1582 | /// Called when a thread exits |
| @@ -1477,9 +1584,12 @@ static void ExitThread(Core::System& system) { | |||
| 1477 | LOG_DEBUG(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC()); | 1584 | LOG_DEBUG(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC()); |
| 1478 | 1585 | ||
| 1479 | auto* const current_thread = system.CurrentScheduler().GetCurrentThread(); | 1586 | auto* const current_thread = system.CurrentScheduler().GetCurrentThread(); |
| 1480 | current_thread->Stop(); | ||
| 1481 | system.GlobalScheduler().RemoveThread(SharedFrom(current_thread)); | 1587 | system.GlobalScheduler().RemoveThread(SharedFrom(current_thread)); |
| 1482 | system.PrepareReschedule(); | 1588 | current_thread->Stop(); |
| 1589 | } | ||
| 1590 | |||
| 1591 | static void ExitThread32(Core::System& system) { | ||
| 1592 | ExitThread(system); | ||
| 1483 | } | 1593 | } |
| 1484 | 1594 | ||
| 1485 | /// Sleep the current thread | 1595 | /// Sleep the current thread |
| @@ -1498,15 +1608,21 @@ static void SleepThread(Core::System& system, s64 nanoseconds) { | |||
| 1498 | 1608 | ||
| 1499 | if (nanoseconds <= 0) { | 1609 | if (nanoseconds <= 0) { |
| 1500 | switch (static_cast<SleepType>(nanoseconds)) { | 1610 | switch (static_cast<SleepType>(nanoseconds)) { |
| 1501 | case SleepType::YieldWithoutLoadBalancing: | 1611 | case SleepType::YieldWithoutLoadBalancing: { |
| 1502 | is_redundant = current_thread->YieldSimple(); | 1612 | auto pair = current_thread->YieldSimple(); |
| 1613 | is_redundant = pair.second; | ||
| 1503 | break; | 1614 | break; |
| 1504 | case SleepType::YieldWithLoadBalancing: | 1615 | } |
| 1505 | is_redundant = current_thread->YieldAndBalanceLoad(); | 1616 | case SleepType::YieldWithLoadBalancing: { |
| 1617 | auto pair = current_thread->YieldAndBalanceLoad(); | ||
| 1618 | is_redundant = pair.second; | ||
| 1506 | break; | 1619 | break; |
| 1507 | case SleepType::YieldAndWaitForLoadBalancing: | 1620 | } |
| 1508 | is_redundant = current_thread->YieldAndWaitForLoadBalancing(); | 1621 | case SleepType::YieldAndWaitForLoadBalancing: { |
| 1622 | auto pair = current_thread->YieldAndWaitForLoadBalancing(); | ||
| 1623 | is_redundant = pair.second; | ||
| 1509 | break; | 1624 | break; |
| 1625 | } | ||
| 1510 | default: | 1626 | default: |
| 1511 | UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds); | 1627 | UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds); |
| 1512 | } | 1628 | } |
| @@ -1514,13 +1630,18 @@ static void SleepThread(Core::System& system, s64 nanoseconds) { | |||
| 1514 | current_thread->Sleep(nanoseconds); | 1630 | current_thread->Sleep(nanoseconds); |
| 1515 | } | 1631 | } |
| 1516 | 1632 | ||
| 1517 | if (is_redundant) { | 1633 | if (is_redundant && !system.Kernel().IsMulticore()) { |
| 1518 | // If it's redundant, the core is pretty much idle. Some games keep idling | 1634 | system.Kernel().ExitSVCProfile(); |
| 1519 | // a core while it's doing nothing, we advance timing to avoid costly continuous | 1635 | system.CoreTiming().AddTicks(1000U); |
| 1520 | // calls. | 1636 | system.GetCpuManager().PreemptSingleCore(); |
| 1521 | system.CoreTiming().AddTicks(2000); | 1637 | system.Kernel().EnterSVCProfile(); |
| 1522 | } | 1638 | } |
| 1523 | system.PrepareReschedule(current_thread->GetProcessorID()); | 1639 | } |
| 1640 | |||
| 1641 | static void SleepThread32(Core::System& system, u32 nanoseconds_low, u32 nanoseconds_high) { | ||
| 1642 | const s64 nanoseconds = static_cast<s64>(static_cast<u64>(nanoseconds_low) | | ||
| 1643 | (static_cast<u64>(nanoseconds_high) << 32)); | ||
| 1644 | SleepThread(system, nanoseconds); | ||
| 1524 | } | 1645 | } |
| 1525 | 1646 | ||
| 1526 | /// Wait process wide key atomic | 1647 | /// Wait process wide key atomic |
| @@ -1547,31 +1668,69 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr mutex_add | |||
| 1547 | } | 1668 | } |
| 1548 | 1669 | ||
| 1549 | ASSERT(condition_variable_addr == Common::AlignDown(condition_variable_addr, 4)); | 1670 | ASSERT(condition_variable_addr == Common::AlignDown(condition_variable_addr, 4)); |
| 1550 | 1671 | auto& kernel = system.Kernel(); | |
| 1672 | Handle event_handle; | ||
| 1673 | Thread* current_thread = system.CurrentScheduler().GetCurrentThread(); | ||
| 1551 | auto* const current_process = system.Kernel().CurrentProcess(); | 1674 | auto* const current_process = system.Kernel().CurrentProcess(); |
| 1552 | const auto& handle_table = current_process->GetHandleTable(); | 1675 | { |
| 1553 | std::shared_ptr<Thread> thread = handle_table.Get<Thread>(thread_handle); | 1676 | SchedulerLockAndSleep lock(kernel, event_handle, current_thread, nano_seconds); |
| 1554 | ASSERT(thread); | 1677 | const auto& handle_table = current_process->GetHandleTable(); |
| 1678 | std::shared_ptr<Thread> thread = handle_table.Get<Thread>(thread_handle); | ||
| 1679 | ASSERT(thread); | ||
| 1680 | |||
| 1681 | current_thread->SetSynchronizationResults(nullptr, RESULT_TIMEOUT); | ||
| 1682 | |||
| 1683 | if (thread->IsPendingTermination()) { | ||
| 1684 | lock.CancelSleep(); | ||
| 1685 | return ERR_THREAD_TERMINATING; | ||
| 1686 | } | ||
| 1687 | |||
| 1688 | const auto release_result = current_process->GetMutex().Release(mutex_addr); | ||
| 1689 | if (release_result.IsError()) { | ||
| 1690 | lock.CancelSleep(); | ||
| 1691 | return release_result; | ||
| 1692 | } | ||
| 1693 | |||
| 1694 | if (nano_seconds == 0) { | ||
| 1695 | lock.CancelSleep(); | ||
| 1696 | return RESULT_TIMEOUT; | ||
| 1697 | } | ||
| 1555 | 1698 | ||
| 1556 | const auto release_result = current_process->GetMutex().Release(mutex_addr); | 1699 | current_thread->SetCondVarWaitAddress(condition_variable_addr); |
| 1557 | if (release_result.IsError()) { | 1700 | current_thread->SetMutexWaitAddress(mutex_addr); |
| 1558 | return release_result; | 1701 | current_thread->SetWaitHandle(thread_handle); |
| 1702 | current_thread->SetStatus(ThreadStatus::WaitCondVar); | ||
| 1703 | current_process->InsertConditionVariableThread(SharedFrom(current_thread)); | ||
| 1559 | } | 1704 | } |
| 1560 | 1705 | ||
| 1561 | Thread* current_thread = system.CurrentScheduler().GetCurrentThread(); | 1706 | if (event_handle != InvalidHandle) { |
| 1562 | current_thread->SetCondVarWaitAddress(condition_variable_addr); | 1707 | auto& time_manager = kernel.TimeManager(); |
| 1563 | current_thread->SetMutexWaitAddress(mutex_addr); | 1708 | time_manager.UnscheduleTimeEvent(event_handle); |
| 1564 | current_thread->SetWaitHandle(thread_handle); | 1709 | } |
| 1565 | current_thread->SetStatus(ThreadStatus::WaitCondVar); | 1710 | |
| 1566 | current_thread->InvalidateWakeupCallback(); | 1711 | { |
| 1567 | current_process->InsertConditionVariableThread(SharedFrom(current_thread)); | 1712 | SchedulerLock lock(kernel); |
| 1568 | 1713 | ||
| 1569 | current_thread->WakeAfterDelay(nano_seconds); | 1714 | auto* owner = current_thread->GetLockOwner(); |
| 1715 | if (owner != nullptr) { | ||
| 1716 | owner->RemoveMutexWaiter(SharedFrom(current_thread)); | ||
| 1717 | } | ||
| 1570 | 1718 | ||
| 1719 | current_process->RemoveConditionVariableThread(SharedFrom(current_thread)); | ||
| 1720 | } | ||
| 1571 | // Note: Deliberately don't attempt to inherit the lock owner's priority. | 1721 | // Note: Deliberately don't attempt to inherit the lock owner's priority. |
| 1572 | 1722 | ||
| 1573 | system.PrepareReschedule(current_thread->GetProcessorID()); | 1723 | return current_thread->GetSignalingResult(); |
| 1574 | return RESULT_SUCCESS; | 1724 | } |
| 1725 | |||
| 1726 | static ResultCode WaitProcessWideKeyAtomic32(Core::System& system, u32 mutex_addr, | ||
| 1727 | u32 condition_variable_addr, Handle thread_handle, | ||
| 1728 | u32 nanoseconds_low, u32 nanoseconds_high) { | ||
| 1729 | const s64 nanoseconds = | ||
| 1730 | static_cast<s64>(nanoseconds_low | (static_cast<u64>(nanoseconds_high) << 32)); | ||
| 1731 | return WaitProcessWideKeyAtomic(system, static_cast<VAddr>(mutex_addr), | ||
| 1732 | static_cast<VAddr>(condition_variable_addr), thread_handle, | ||
| 1733 | nanoseconds); | ||
| 1575 | } | 1734 | } |
| 1576 | 1735 | ||
| 1577 | /// Signal process wide key | 1736 | /// Signal process wide key |
| @@ -1582,7 +1741,9 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_ | |||
| 1582 | ASSERT(condition_variable_addr == Common::AlignDown(condition_variable_addr, 4)); | 1741 | ASSERT(condition_variable_addr == Common::AlignDown(condition_variable_addr, 4)); |
| 1583 | 1742 | ||
| 1584 | // Retrieve a list of all threads that are waiting for this condition variable. | 1743 | // Retrieve a list of all threads that are waiting for this condition variable. |
| 1585 | auto* const current_process = system.Kernel().CurrentProcess(); | 1744 | auto& kernel = system.Kernel(); |
| 1745 | SchedulerLock lock(kernel); | ||
| 1746 | auto* const current_process = kernel.CurrentProcess(); | ||
| 1586 | std::vector<std::shared_ptr<Thread>> waiting_threads = | 1747 | std::vector<std::shared_ptr<Thread>> waiting_threads = |
| 1587 | current_process->GetConditionVariableThreads(condition_variable_addr); | 1748 | current_process->GetConditionVariableThreads(condition_variable_addr); |
| 1588 | 1749 | ||
| @@ -1591,7 +1752,7 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_ | |||
| 1591 | std::size_t last = waiting_threads.size(); | 1752 | std::size_t last = waiting_threads.size(); |
| 1592 | if (target > 0) | 1753 | if (target > 0) |
| 1593 | last = std::min(waiting_threads.size(), static_cast<std::size_t>(target)); | 1754 | last = std::min(waiting_threads.size(), static_cast<std::size_t>(target)); |
| 1594 | 1755 | auto& time_manager = kernel.TimeManager(); | |
| 1595 | for (std::size_t index = 0; index < last; ++index) { | 1756 | for (std::size_t index = 0; index < last; ++index) { |
| 1596 | auto& thread = waiting_threads[index]; | 1757 | auto& thread = waiting_threads[index]; |
| 1597 | 1758 | ||
| @@ -1599,7 +1760,6 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_ | |||
| 1599 | 1760 | ||
| 1600 | // liberate Cond Var Thread. | 1761 | // liberate Cond Var Thread. |
| 1601 | current_process->RemoveConditionVariableThread(thread); | 1762 | current_process->RemoveConditionVariableThread(thread); |
| 1602 | thread->SetCondVarWaitAddress(0); | ||
| 1603 | 1763 | ||
| 1604 | const std::size_t current_core = system.CurrentCoreIndex(); | 1764 | const std::size_t current_core = system.CurrentCoreIndex(); |
| 1605 | auto& monitor = system.Monitor(); | 1765 | auto& monitor = system.Monitor(); |
| @@ -1610,10 +1770,8 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_ | |||
| 1610 | u32 update_val = 0; | 1770 | u32 update_val = 0; |
| 1611 | const VAddr mutex_address = thread->GetMutexWaitAddress(); | 1771 | const VAddr mutex_address = thread->GetMutexWaitAddress(); |
| 1612 | do { | 1772 | do { |
| 1613 | monitor.SetExclusive(current_core, mutex_address); | ||
| 1614 | |||
| 1615 | // If the mutex is not yet acquired, acquire it. | 1773 | // If the mutex is not yet acquired, acquire it. |
| 1616 | mutex_val = memory.Read32(mutex_address); | 1774 | mutex_val = monitor.ExclusiveRead32(current_core, mutex_address); |
| 1617 | 1775 | ||
| 1618 | if (mutex_val != 0) { | 1776 | if (mutex_val != 0) { |
| 1619 | update_val = mutex_val | Mutex::MutexHasWaitersFlag; | 1777 | update_val = mutex_val | Mutex::MutexHasWaitersFlag; |
| @@ -1621,33 +1779,28 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_ | |||
| 1621 | update_val = thread->GetWaitHandle(); | 1779 | update_val = thread->GetWaitHandle(); |
| 1622 | } | 1780 | } |
| 1623 | } while (!monitor.ExclusiveWrite32(current_core, mutex_address, update_val)); | 1781 | } while (!monitor.ExclusiveWrite32(current_core, mutex_address, update_val)); |
| 1782 | monitor.ClearExclusive(); | ||
| 1624 | if (mutex_val == 0) { | 1783 | if (mutex_val == 0) { |
| 1625 | // We were able to acquire the mutex, resume this thread. | 1784 | // We were able to acquire the mutex, resume this thread. |
| 1626 | ASSERT(thread->GetStatus() == ThreadStatus::WaitCondVar); | ||
| 1627 | thread->ResumeFromWait(); | ||
| 1628 | |||
| 1629 | auto* const lock_owner = thread->GetLockOwner(); | 1785 | auto* const lock_owner = thread->GetLockOwner(); |
| 1630 | if (lock_owner != nullptr) { | 1786 | if (lock_owner != nullptr) { |
| 1631 | lock_owner->RemoveMutexWaiter(thread); | 1787 | lock_owner->RemoveMutexWaiter(thread); |
| 1632 | } | 1788 | } |
| 1633 | 1789 | ||
| 1634 | thread->SetLockOwner(nullptr); | 1790 | thread->SetLockOwner(nullptr); |
| 1635 | thread->SetMutexWaitAddress(0); | 1791 | thread->SetSynchronizationResults(nullptr, RESULT_SUCCESS); |
| 1636 | thread->SetWaitHandle(0); | 1792 | thread->ResumeFromWait(); |
| 1637 | thread->SetWaitSynchronizationResult(RESULT_SUCCESS); | ||
| 1638 | system.PrepareReschedule(thread->GetProcessorID()); | ||
| 1639 | } else { | 1793 | } else { |
| 1640 | // The mutex is already owned by some other thread, make this thread wait on it. | 1794 | // The mutex is already owned by some other thread, make this thread wait on it. |
| 1641 | const Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask); | 1795 | const Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask); |
| 1642 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 1796 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); |
| 1643 | auto owner = handle_table.Get<Thread>(owner_handle); | 1797 | auto owner = handle_table.Get<Thread>(owner_handle); |
| 1644 | ASSERT(owner); | 1798 | ASSERT(owner); |
| 1645 | ASSERT(thread->GetStatus() == ThreadStatus::WaitCondVar); | 1799 | if (thread->GetStatus() == ThreadStatus::WaitCondVar) { |
| 1646 | thread->InvalidateWakeupCallback(); | 1800 | thread->SetStatus(ThreadStatus::WaitMutex); |
| 1647 | thread->SetStatus(ThreadStatus::WaitMutex); | 1801 | } |
| 1648 | 1802 | ||
| 1649 | owner->AddMutexWaiter(thread); | 1803 | owner->AddMutexWaiter(thread); |
| 1650 | system.PrepareReschedule(thread->GetProcessorID()); | ||
| 1651 | } | 1804 | } |
| 1652 | } | 1805 | } |
| 1653 | } | 1806 | } |
| @@ -1678,12 +1831,15 @@ static ResultCode WaitForAddress(Core::System& system, VAddr address, u32 type, | |||
| 1678 | auto& address_arbiter = system.Kernel().CurrentProcess()->GetAddressArbiter(); | 1831 | auto& address_arbiter = system.Kernel().CurrentProcess()->GetAddressArbiter(); |
| 1679 | const ResultCode result = | 1832 | const ResultCode result = |
| 1680 | address_arbiter.WaitForAddress(address, arbitration_type, value, timeout); | 1833 | address_arbiter.WaitForAddress(address, arbitration_type, value, timeout); |
| 1681 | if (result == RESULT_SUCCESS) { | ||
| 1682 | system.PrepareReschedule(); | ||
| 1683 | } | ||
| 1684 | return result; | 1834 | return result; |
| 1685 | } | 1835 | } |
| 1686 | 1836 | ||
| 1837 | static ResultCode WaitForAddress32(Core::System& system, u32 address, u32 type, s32 value, | ||
| 1838 | u32 timeout_low, u32 timeout_high) { | ||
| 1839 | s64 timeout = static_cast<s64>(timeout_low | (static_cast<u64>(timeout_high) << 32)); | ||
| 1840 | return WaitForAddress(system, static_cast<VAddr>(address), type, value, timeout); | ||
| 1841 | } | ||
| 1842 | |||
| 1687 | // Signals to an address (via Address Arbiter) | 1843 | // Signals to an address (via Address Arbiter) |
| 1688 | static ResultCode SignalToAddress(Core::System& system, VAddr address, u32 type, s32 value, | 1844 | static ResultCode SignalToAddress(Core::System& system, VAddr address, u32 type, s32 value, |
| 1689 | s32 num_to_wake) { | 1845 | s32 num_to_wake) { |
| @@ -1707,6 +1863,11 @@ static ResultCode SignalToAddress(Core::System& system, VAddr address, u32 type, | |||
| 1707 | return address_arbiter.SignalToAddress(address, signal_type, value, num_to_wake); | 1863 | return address_arbiter.SignalToAddress(address, signal_type, value, num_to_wake); |
| 1708 | } | 1864 | } |
| 1709 | 1865 | ||
| 1866 | static ResultCode SignalToAddress32(Core::System& system, u32 address, u32 type, s32 value, | ||
| 1867 | s32 num_to_wake) { | ||
| 1868 | return SignalToAddress(system, static_cast<VAddr>(address), type, value, num_to_wake); | ||
| 1869 | } | ||
| 1870 | |||
| 1710 | static void KernelDebug([[maybe_unused]] Core::System& system, | 1871 | static void KernelDebug([[maybe_unused]] Core::System& system, |
| 1711 | [[maybe_unused]] u32 kernel_debug_type, [[maybe_unused]] u64 param1, | 1872 | [[maybe_unused]] u32 kernel_debug_type, [[maybe_unused]] u64 param1, |
| 1712 | [[maybe_unused]] u64 param2, [[maybe_unused]] u64 param3) { | 1873 | [[maybe_unused]] u64 param2, [[maybe_unused]] u64 param3) { |
| @@ -1725,14 +1886,21 @@ static u64 GetSystemTick(Core::System& system) { | |||
| 1725 | auto& core_timing = system.CoreTiming(); | 1886 | auto& core_timing = system.CoreTiming(); |
| 1726 | 1887 | ||
| 1727 | // Returns the value of cntpct_el0 (https://switchbrew.org/wiki/SVC#svcGetSystemTick) | 1888 | // Returns the value of cntpct_el0 (https://switchbrew.org/wiki/SVC#svcGetSystemTick) |
| 1728 | const u64 result{Core::Timing::CpuCyclesToClockCycles(system.CoreTiming().GetTicks())}; | 1889 | const u64 result{system.CoreTiming().GetClockTicks()}; |
| 1729 | 1890 | ||
| 1730 | // Advance time to defeat dumb games that busy-wait for the frame to end. | 1891 | if (!system.Kernel().IsMulticore()) { |
| 1731 | core_timing.AddTicks(400); | 1892 | core_timing.AddTicks(400U); |
| 1893 | } | ||
| 1732 | 1894 | ||
| 1733 | return result; | 1895 | return result; |
| 1734 | } | 1896 | } |
| 1735 | 1897 | ||
| 1898 | static void GetSystemTick32(Core::System& system, u32* time_low, u32* time_high) { | ||
| 1899 | u64 time = GetSystemTick(system); | ||
| 1900 | *time_low = static_cast<u32>(time); | ||
| 1901 | *time_high = static_cast<u32>(time >> 32); | ||
| 1902 | } | ||
| 1903 | |||
| 1736 | /// Close a handle | 1904 | /// Close a handle |
| 1737 | static ResultCode CloseHandle(Core::System& system, Handle handle) { | 1905 | static ResultCode CloseHandle(Core::System& system, Handle handle) { |
| 1738 | LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle); | 1906 | LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle); |
| @@ -1765,9 +1933,14 @@ static ResultCode ResetSignal(Core::System& system, Handle handle) { | |||
| 1765 | return ERR_INVALID_HANDLE; | 1933 | return ERR_INVALID_HANDLE; |
| 1766 | } | 1934 | } |
| 1767 | 1935 | ||
| 1936 | static ResultCode ResetSignal32(Core::System& system, Handle handle) { | ||
| 1937 | return ResetSignal(system, handle); | ||
| 1938 | } | ||
| 1939 | |||
| 1768 | /// Creates a TransferMemory object | 1940 | /// Creates a TransferMemory object |
| 1769 | static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAddr addr, u64 size, | 1941 | static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAddr addr, u64 size, |
| 1770 | u32 permissions) { | 1942 | u32 permissions) { |
| 1943 | std::lock_guard lock{HLE::g_hle_lock}; | ||
| 1771 | LOG_DEBUG(Kernel_SVC, "called addr=0x{:X}, size=0x{:X}, perms=0x{:08X}", addr, size, | 1944 | LOG_DEBUG(Kernel_SVC, "called addr=0x{:X}, size=0x{:X}, perms=0x{:08X}", addr, size, |
| 1772 | permissions); | 1945 | permissions); |
| 1773 | 1946 | ||
| @@ -1812,6 +1985,12 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd | |||
| 1812 | return RESULT_SUCCESS; | 1985 | return RESULT_SUCCESS; |
| 1813 | } | 1986 | } |
| 1814 | 1987 | ||
| 1988 | static ResultCode CreateTransferMemory32(Core::System& system, Handle* handle, u32 addr, u32 size, | ||
| 1989 | u32 permissions) { | ||
| 1990 | return CreateTransferMemory(system, handle, static_cast<VAddr>(addr), | ||
| 1991 | static_cast<std::size_t>(size), permissions); | ||
| 1992 | } | ||
| 1993 | |||
| 1815 | static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, u32* core, | 1994 | static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, u32* core, |
| 1816 | u64* mask) { | 1995 | u64* mask) { |
| 1817 | LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle); | 1996 | LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle); |
| @@ -1821,6 +2000,8 @@ static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, | |||
| 1821 | if (!thread) { | 2000 | if (!thread) { |
| 1822 | LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}", | 2001 | LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}", |
| 1823 | thread_handle); | 2002 | thread_handle); |
| 2003 | *core = 0; | ||
| 2004 | *mask = 0; | ||
| 1824 | return ERR_INVALID_HANDLE; | 2005 | return ERR_INVALID_HANDLE; |
| 1825 | } | 2006 | } |
| 1826 | 2007 | ||
| @@ -1830,6 +2011,15 @@ static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, | |||
| 1830 | return RESULT_SUCCESS; | 2011 | return RESULT_SUCCESS; |
| 1831 | } | 2012 | } |
| 1832 | 2013 | ||
| 2014 | static ResultCode GetThreadCoreMask32(Core::System& system, Handle thread_handle, u32* core, | ||
| 2015 | u32* mask_low, u32* mask_high) { | ||
| 2016 | u64 mask{}; | ||
| 2017 | const auto result = GetThreadCoreMask(system, thread_handle, core, &mask); | ||
| 2018 | *mask_high = static_cast<u32>(mask >> 32); | ||
| 2019 | *mask_low = static_cast<u32>(mask); | ||
| 2020 | return result; | ||
| 2021 | } | ||
| 2022 | |||
| 1833 | static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, u32 core, | 2023 | static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, u32 core, |
| 1834 | u64 affinity_mask) { | 2024 | u64 affinity_mask) { |
| 1835 | LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, core=0x{:X}, affinity_mask=0x{:016X}", | 2025 | LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, core=0x{:X}, affinity_mask=0x{:016X}", |
| @@ -1861,7 +2051,7 @@ static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, | |||
| 1861 | return ERR_INVALID_COMBINATION; | 2051 | return ERR_INVALID_COMBINATION; |
| 1862 | } | 2052 | } |
| 1863 | 2053 | ||
| 1864 | if (core < Core::NUM_CPU_CORES) { | 2054 | if (core < Core::Hardware::NUM_CPU_CORES) { |
| 1865 | if ((affinity_mask & (1ULL << core)) == 0) { | 2055 | if ((affinity_mask & (1ULL << core)) == 0) { |
| 1866 | LOG_ERROR(Kernel_SVC, | 2056 | LOG_ERROR(Kernel_SVC, |
| 1867 | "Core is not enabled for the current mask, core={}, mask={:016X}", core, | 2057 | "Core is not enabled for the current mask, core={}, mask={:016X}", core, |
| @@ -1883,11 +2073,14 @@ static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, | |||
| 1883 | return ERR_INVALID_HANDLE; | 2073 | return ERR_INVALID_HANDLE; |
| 1884 | } | 2074 | } |
| 1885 | 2075 | ||
| 1886 | system.PrepareReschedule(thread->GetProcessorID()); | 2076 | return thread->SetCoreAndAffinityMask(core, affinity_mask); |
| 1887 | thread->ChangeCore(core, affinity_mask); | 2077 | } |
| 1888 | system.PrepareReschedule(thread->GetProcessorID()); | ||
| 1889 | 2078 | ||
| 1890 | return RESULT_SUCCESS; | 2079 | static ResultCode SetThreadCoreMask32(Core::System& system, Handle thread_handle, u32 core, |
| 2080 | u32 affinity_mask_low, u32 affinity_mask_high) { | ||
| 2081 | const u64 affinity_mask = | ||
| 2082 | static_cast<u64>(affinity_mask_low) | (static_cast<u64>(affinity_mask_high) << 32); | ||
| 2083 | return SetThreadCoreMask(system, thread_handle, core, affinity_mask); | ||
| 1891 | } | 2084 | } |
| 1892 | 2085 | ||
| 1893 | static ResultCode CreateEvent(Core::System& system, Handle* write_handle, Handle* read_handle) { | 2086 | static ResultCode CreateEvent(Core::System& system, Handle* write_handle, Handle* read_handle) { |
| @@ -1918,6 +2111,10 @@ static ResultCode CreateEvent(Core::System& system, Handle* write_handle, Handle | |||
| 1918 | return RESULT_SUCCESS; | 2111 | return RESULT_SUCCESS; |
| 1919 | } | 2112 | } |
| 1920 | 2113 | ||
| 2114 | static ResultCode CreateEvent32(Core::System& system, Handle* write_handle, Handle* read_handle) { | ||
| 2115 | return CreateEvent(system, write_handle, read_handle); | ||
| 2116 | } | ||
| 2117 | |||
| 1921 | static ResultCode ClearEvent(Core::System& system, Handle handle) { | 2118 | static ResultCode ClearEvent(Core::System& system, Handle handle) { |
| 1922 | LOG_TRACE(Kernel_SVC, "called, event=0x{:08X}", handle); | 2119 | LOG_TRACE(Kernel_SVC, "called, event=0x{:08X}", handle); |
| 1923 | 2120 | ||
| @@ -1939,6 +2136,10 @@ static ResultCode ClearEvent(Core::System& system, Handle handle) { | |||
| 1939 | return ERR_INVALID_HANDLE; | 2136 | return ERR_INVALID_HANDLE; |
| 1940 | } | 2137 | } |
| 1941 | 2138 | ||
| 2139 | static ResultCode ClearEvent32(Core::System& system, Handle handle) { | ||
| 2140 | return ClearEvent(system, handle); | ||
| 2141 | } | ||
| 2142 | |||
| 1942 | static ResultCode SignalEvent(Core::System& system, Handle handle) { | 2143 | static ResultCode SignalEvent(Core::System& system, Handle handle) { |
| 1943 | LOG_DEBUG(Kernel_SVC, "called. Handle=0x{:08X}", handle); | 2144 | LOG_DEBUG(Kernel_SVC, "called. Handle=0x{:08X}", handle); |
| 1944 | 2145 | ||
| @@ -1951,10 +2152,13 @@ static ResultCode SignalEvent(Core::System& system, Handle handle) { | |||
| 1951 | } | 2152 | } |
| 1952 | 2153 | ||
| 1953 | writable_event->Signal(); | 2154 | writable_event->Signal(); |
| 1954 | system.PrepareReschedule(); | ||
| 1955 | return RESULT_SUCCESS; | 2155 | return RESULT_SUCCESS; |
| 1956 | } | 2156 | } |
| 1957 | 2157 | ||
| 2158 | static ResultCode SignalEvent32(Core::System& system, Handle handle) { | ||
| 2159 | return SignalEvent(system, handle); | ||
| 2160 | } | ||
| 2161 | |||
| 1958 | static ResultCode GetProcessInfo(Core::System& system, u64* out, Handle process_handle, u32 type) { | 2162 | static ResultCode GetProcessInfo(Core::System& system, u64* out, Handle process_handle, u32 type) { |
| 1959 | LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, type=0x{:X}", process_handle, type); | 2163 | LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, type=0x{:X}", process_handle, type); |
| 1960 | 2164 | ||
| @@ -1982,6 +2186,7 @@ static ResultCode GetProcessInfo(Core::System& system, u64* out, Handle process_ | |||
| 1982 | } | 2186 | } |
| 1983 | 2187 | ||
| 1984 | static ResultCode CreateResourceLimit(Core::System& system, Handle* out_handle) { | 2188 | static ResultCode CreateResourceLimit(Core::System& system, Handle* out_handle) { |
| 2189 | std::lock_guard lock{HLE::g_hle_lock}; | ||
| 1985 | LOG_DEBUG(Kernel_SVC, "called"); | 2190 | LOG_DEBUG(Kernel_SVC, "called"); |
| 1986 | 2191 | ||
| 1987 | auto& kernel = system.Kernel(); | 2192 | auto& kernel = system.Kernel(); |
| @@ -2139,6 +2344,15 @@ static ResultCode GetThreadList(Core::System& system, u32* out_num_threads, VAdd | |||
| 2139 | return RESULT_SUCCESS; | 2344 | return RESULT_SUCCESS; |
| 2140 | } | 2345 | } |
| 2141 | 2346 | ||
| 2347 | static ResultCode FlushProcessDataCache32(Core::System& system, Handle handle, u32 address, | ||
| 2348 | u32 size) { | ||
| 2349 | // Note(Blinkhawk): For emulation purposes of the data cache this is mostly a nope | ||
| 2350 | // as all emulation is done in the same cache level in host architecture, thus data cache | ||
| 2351 | // does not need flushing. | ||
| 2352 | LOG_DEBUG(Kernel_SVC, "called"); | ||
| 2353 | return RESULT_SUCCESS; | ||
| 2354 | } | ||
| 2355 | |||
| 2142 | namespace { | 2356 | namespace { |
| 2143 | struct FunctionDef { | 2357 | struct FunctionDef { |
| 2144 | using Func = void(Core::System&); | 2358 | using Func = void(Core::System&); |
| @@ -2153,57 +2367,57 @@ static const FunctionDef SVC_Table_32[] = { | |||
| 2153 | {0x00, nullptr, "Unknown"}, | 2367 | {0x00, nullptr, "Unknown"}, |
| 2154 | {0x01, SvcWrap32<SetHeapSize32>, "SetHeapSize32"}, | 2368 | {0x01, SvcWrap32<SetHeapSize32>, "SetHeapSize32"}, |
| 2155 | {0x02, nullptr, "Unknown"}, | 2369 | {0x02, nullptr, "Unknown"}, |
| 2156 | {0x03, nullptr, "SetMemoryAttribute32"}, | 2370 | {0x03, SvcWrap32<SetMemoryAttribute32>, "SetMemoryAttribute32"}, |
| 2157 | {0x04, nullptr, "MapMemory32"}, | 2371 | {0x04, SvcWrap32<MapMemory32>, "MapMemory32"}, |
| 2158 | {0x05, nullptr, "UnmapMemory32"}, | 2372 | {0x05, SvcWrap32<UnmapMemory32>, "UnmapMemory32"}, |
| 2159 | {0x06, SvcWrap32<QueryMemory32>, "QueryMemory32"}, | 2373 | {0x06, SvcWrap32<QueryMemory32>, "QueryMemory32"}, |
| 2160 | {0x07, nullptr, "ExitProcess32"}, | 2374 | {0x07, SvcWrap32<ExitProcess32>, "ExitProcess32"}, |
| 2161 | {0x08, nullptr, "CreateThread32"}, | 2375 | {0x08, SvcWrap32<CreateThread32>, "CreateThread32"}, |
| 2162 | {0x09, nullptr, "StartThread32"}, | 2376 | {0x09, SvcWrap32<StartThread32>, "StartThread32"}, |
| 2163 | {0x0a, nullptr, "ExitThread32"}, | 2377 | {0x0a, SvcWrap32<ExitThread32>, "ExitThread32"}, |
| 2164 | {0x0b, nullptr, "SleepThread32"}, | 2378 | {0x0b, SvcWrap32<SleepThread32>, "SleepThread32"}, |
| 2165 | {0x0c, SvcWrap32<GetThreadPriority32>, "GetThreadPriority32"}, | 2379 | {0x0c, SvcWrap32<GetThreadPriority32>, "GetThreadPriority32"}, |
| 2166 | {0x0d, nullptr, "SetThreadPriority32"}, | 2380 | {0x0d, SvcWrap32<SetThreadPriority32>, "SetThreadPriority32"}, |
| 2167 | {0x0e, nullptr, "GetThreadCoreMask32"}, | 2381 | {0x0e, SvcWrap32<GetThreadCoreMask32>, "GetThreadCoreMask32"}, |
| 2168 | {0x0f, nullptr, "SetThreadCoreMask32"}, | 2382 | {0x0f, SvcWrap32<SetThreadCoreMask32>, "SetThreadCoreMask32"}, |
| 2169 | {0x10, nullptr, "GetCurrentProcessorNumber32"}, | 2383 | {0x10, SvcWrap32<GetCurrentProcessorNumber32>, "GetCurrentProcessorNumber32"}, |
| 2170 | {0x11, nullptr, "SignalEvent32"}, | 2384 | {0x11, SvcWrap32<SignalEvent32>, "SignalEvent32"}, |
| 2171 | {0x12, nullptr, "ClearEvent32"}, | 2385 | {0x12, SvcWrap32<ClearEvent32>, "ClearEvent32"}, |
| 2172 | {0x13, nullptr, "MapSharedMemory32"}, | 2386 | {0x13, SvcWrap32<MapSharedMemory32>, "MapSharedMemory32"}, |
| 2173 | {0x14, nullptr, "UnmapSharedMemory32"}, | 2387 | {0x14, nullptr, "UnmapSharedMemory32"}, |
| 2174 | {0x15, nullptr, "CreateTransferMemory32"}, | 2388 | {0x15, SvcWrap32<CreateTransferMemory32>, "CreateTransferMemory32"}, |
| 2175 | {0x16, SvcWrap32<CloseHandle32>, "CloseHandle32"}, | 2389 | {0x16, SvcWrap32<CloseHandle32>, "CloseHandle32"}, |
| 2176 | {0x17, nullptr, "ResetSignal32"}, | 2390 | {0x17, SvcWrap32<ResetSignal32>, "ResetSignal32"}, |
| 2177 | {0x18, SvcWrap32<WaitSynchronization32>, "WaitSynchronization32"}, | 2391 | {0x18, SvcWrap32<WaitSynchronization32>, "WaitSynchronization32"}, |
| 2178 | {0x19, nullptr, "CancelSynchronization32"}, | 2392 | {0x19, SvcWrap32<CancelSynchronization32>, "CancelSynchronization32"}, |
| 2179 | {0x1a, nullptr, "ArbitrateLock32"}, | 2393 | {0x1a, SvcWrap32<ArbitrateLock32>, "ArbitrateLock32"}, |
| 2180 | {0x1b, nullptr, "ArbitrateUnlock32"}, | 2394 | {0x1b, SvcWrap32<ArbitrateUnlock32>, "ArbitrateUnlock32"}, |
| 2181 | {0x1c, nullptr, "WaitProcessWideKeyAtomic32"}, | 2395 | {0x1c, SvcWrap32<WaitProcessWideKeyAtomic32>, "WaitProcessWideKeyAtomic32"}, |
| 2182 | {0x1d, SvcWrap32<SignalProcessWideKey32>, "SignalProcessWideKey32"}, | 2396 | {0x1d, SvcWrap32<SignalProcessWideKey32>, "SignalProcessWideKey32"}, |
| 2183 | {0x1e, nullptr, "GetSystemTick32"}, | 2397 | {0x1e, SvcWrap32<GetSystemTick32>, "GetSystemTick32"}, |
| 2184 | {0x1f, SvcWrap32<ConnectToNamedPort32>, "ConnectToNamedPort32"}, | 2398 | {0x1f, SvcWrap32<ConnectToNamedPort32>, "ConnectToNamedPort32"}, |
| 2185 | {0x20, nullptr, "Unknown"}, | 2399 | {0x20, nullptr, "Unknown"}, |
| 2186 | {0x21, SvcWrap32<SendSyncRequest32>, "SendSyncRequest32"}, | 2400 | {0x21, SvcWrap32<SendSyncRequest32>, "SendSyncRequest32"}, |
| 2187 | {0x22, nullptr, "SendSyncRequestWithUserBuffer32"}, | 2401 | {0x22, nullptr, "SendSyncRequestWithUserBuffer32"}, |
| 2188 | {0x23, nullptr, "Unknown"}, | 2402 | {0x23, nullptr, "Unknown"}, |
| 2189 | {0x24, nullptr, "GetProcessId32"}, | 2403 | {0x24, SvcWrap32<GetProcessId32>, "GetProcessId32"}, |
| 2190 | {0x25, SvcWrap32<GetThreadId32>, "GetThreadId32"}, | 2404 | {0x25, SvcWrap32<GetThreadId32>, "GetThreadId32"}, |
| 2191 | {0x26, nullptr, "Break32"}, | 2405 | {0x26, SvcWrap32<Break32>, "Break32"}, |
| 2192 | {0x27, nullptr, "OutputDebugString32"}, | 2406 | {0x27, nullptr, "OutputDebugString32"}, |
| 2193 | {0x28, nullptr, "Unknown"}, | 2407 | {0x28, nullptr, "Unknown"}, |
| 2194 | {0x29, SvcWrap32<GetInfo32>, "GetInfo32"}, | 2408 | {0x29, SvcWrap32<GetInfo32>, "GetInfo32"}, |
| 2195 | {0x2a, nullptr, "Unknown"}, | 2409 | {0x2a, nullptr, "Unknown"}, |
| 2196 | {0x2b, nullptr, "Unknown"}, | 2410 | {0x2b, nullptr, "Unknown"}, |
| 2197 | {0x2c, nullptr, "MapPhysicalMemory32"}, | 2411 | {0x2c, SvcWrap32<MapPhysicalMemory32>, "MapPhysicalMemory32"}, |
| 2198 | {0x2d, nullptr, "UnmapPhysicalMemory32"}, | 2412 | {0x2d, SvcWrap32<UnmapPhysicalMemory32>, "UnmapPhysicalMemory32"}, |
| 2199 | {0x2e, nullptr, "Unknown"}, | 2413 | {0x2e, nullptr, "Unknown"}, |
| 2200 | {0x2f, nullptr, "Unknown"}, | 2414 | {0x2f, nullptr, "Unknown"}, |
| 2201 | {0x30, nullptr, "Unknown"}, | 2415 | {0x30, nullptr, "Unknown"}, |
| 2202 | {0x31, nullptr, "Unknown"}, | 2416 | {0x31, nullptr, "Unknown"}, |
| 2203 | {0x32, nullptr, "SetThreadActivity32"}, | 2417 | {0x32, SvcWrap32<SetThreadActivity32>, "SetThreadActivity32"}, |
| 2204 | {0x33, nullptr, "GetThreadContext32"}, | 2418 | {0x33, SvcWrap32<GetThreadContext32>, "GetThreadContext32"}, |
| 2205 | {0x34, nullptr, "WaitForAddress32"}, | 2419 | {0x34, SvcWrap32<WaitForAddress32>, "WaitForAddress32"}, |
| 2206 | {0x35, nullptr, "SignalToAddress32"}, | 2420 | {0x35, SvcWrap32<SignalToAddress32>, "SignalToAddress32"}, |
| 2207 | {0x36, nullptr, "Unknown"}, | 2421 | {0x36, nullptr, "Unknown"}, |
| 2208 | {0x37, nullptr, "Unknown"}, | 2422 | {0x37, nullptr, "Unknown"}, |
| 2209 | {0x38, nullptr, "Unknown"}, | 2423 | {0x38, nullptr, "Unknown"}, |
| @@ -2219,7 +2433,7 @@ static const FunctionDef SVC_Table_32[] = { | |||
| 2219 | {0x42, nullptr, "Unknown"}, | 2433 | {0x42, nullptr, "Unknown"}, |
| 2220 | {0x43, nullptr, "ReplyAndReceive32"}, | 2434 | {0x43, nullptr, "ReplyAndReceive32"}, |
| 2221 | {0x44, nullptr, "Unknown"}, | 2435 | {0x44, nullptr, "Unknown"}, |
| 2222 | {0x45, nullptr, "CreateEvent32"}, | 2436 | {0x45, SvcWrap32<CreateEvent32>, "CreateEvent32"}, |
| 2223 | {0x46, nullptr, "Unknown"}, | 2437 | {0x46, nullptr, "Unknown"}, |
| 2224 | {0x47, nullptr, "Unknown"}, | 2438 | {0x47, nullptr, "Unknown"}, |
| 2225 | {0x48, nullptr, "Unknown"}, | 2439 | {0x48, nullptr, "Unknown"}, |
| @@ -2245,7 +2459,7 @@ static const FunctionDef SVC_Table_32[] = { | |||
| 2245 | {0x5c, nullptr, "Unknown"}, | 2459 | {0x5c, nullptr, "Unknown"}, |
| 2246 | {0x5d, nullptr, "Unknown"}, | 2460 | {0x5d, nullptr, "Unknown"}, |
| 2247 | {0x5e, nullptr, "Unknown"}, | 2461 | {0x5e, nullptr, "Unknown"}, |
| 2248 | {0x5F, nullptr, "FlushProcessDataCache32"}, | 2462 | {0x5F, SvcWrap32<FlushProcessDataCache32>, "FlushProcessDataCache32"}, |
| 2249 | {0x60, nullptr, "Unknown"}, | 2463 | {0x60, nullptr, "Unknown"}, |
| 2250 | {0x61, nullptr, "Unknown"}, | 2464 | {0x61, nullptr, "Unknown"}, |
| 2251 | {0x62, nullptr, "Unknown"}, | 2465 | {0x62, nullptr, "Unknown"}, |
| @@ -2423,13 +2637,10 @@ static const FunctionDef* GetSVCInfo64(u32 func_num) { | |||
| 2423 | return &SVC_Table_64[func_num]; | 2637 | return &SVC_Table_64[func_num]; |
| 2424 | } | 2638 | } |
| 2425 | 2639 | ||
| 2426 | MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70)); | ||
| 2427 | |||
| 2428 | void Call(Core::System& system, u32 immediate) { | 2640 | void Call(Core::System& system, u32 immediate) { |
| 2429 | MICROPROFILE_SCOPE(Kernel_SVC); | 2641 | system.ExitDynarmicProfile(); |
| 2430 | 2642 | auto& kernel = system.Kernel(); | |
| 2431 | // Lock the global kernel mutex when we enter the kernel HLE. | 2643 | kernel.EnterSVCProfile(); |
| 2432 | std::lock_guard lock{HLE::g_hle_lock}; | ||
| 2433 | 2644 | ||
| 2434 | const FunctionDef* info = system.CurrentProcess()->Is64BitProcess() ? GetSVCInfo64(immediate) | 2645 | const FunctionDef* info = system.CurrentProcess()->Is64BitProcess() ? GetSVCInfo64(immediate) |
| 2435 | : GetSVCInfo32(immediate); | 2646 | : GetSVCInfo32(immediate); |
| @@ -2442,6 +2653,9 @@ void Call(Core::System& system, u32 immediate) { | |||
| 2442 | } else { | 2653 | } else { |
| 2443 | LOG_CRITICAL(Kernel_SVC, "Unknown SVC function 0x{:X}", immediate); | 2654 | LOG_CRITICAL(Kernel_SVC, "Unknown SVC function 0x{:X}", immediate); |
| 2444 | } | 2655 | } |
| 2656 | |||
| 2657 | kernel.ExitSVCProfile(); | ||
| 2658 | system.EnterDynarmicProfile(); | ||
| 2445 | } | 2659 | } |
| 2446 | 2660 | ||
| 2447 | } // namespace Kernel::Svc | 2661 | } // namespace Kernel::Svc |