diff options
| author | 2018-04-26 14:28:54 -0700 | |
|---|---|---|
| committer | 2018-04-26 14:28:54 -0700 | |
| commit | 7391741a204d6f25a06132eda214b2199b60a084 (patch) | |
| tree | aeeb723744c4563ad608361b82dd938b062a3e09 /src/core/hle/kernel/svc.cpp | |
| parent | Added PREPO to logging backend, Removed comments from SaveReportWithUser (diff) | |
| parent | Merge pull request #403 from lioncash/common (diff) | |
| download | yuzu-7391741a204d6f25a06132eda214b2199b60a084.tar.gz yuzu-7391741a204d6f25a06132eda214b2199b60a084.tar.xz yuzu-7391741a204d6f25a06132eda214b2199b60a084.zip | |
Merge branch 'master' of https://github.com/yuzu-emu/yuzu into service-impl
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 296 |
1 files changed, 122 insertions, 174 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 633740992..cb19b1a69 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -13,7 +13,6 @@ | |||
| 13 | #include "core/core_timing.h" | 13 | #include "core/core_timing.h" |
| 14 | #include "core/hle/kernel/client_port.h" | 14 | #include "core/hle/kernel/client_port.h" |
| 15 | #include "core/hle/kernel/client_session.h" | 15 | #include "core/hle/kernel/client_session.h" |
| 16 | #include "core/hle/kernel/condition_variable.h" | ||
| 17 | #include "core/hle/kernel/event.h" | 16 | #include "core/hle/kernel/event.h" |
| 18 | #include "core/hle/kernel/handle_table.h" | 17 | #include "core/hle/kernel/handle_table.h" |
| 19 | #include "core/hle/kernel/mutex.h" | 18 | #include "core/hle/kernel/mutex.h" |
| @@ -32,7 +31,7 @@ namespace Kernel { | |||
| 32 | 31 | ||
| 33 | /// Set the process heap to a given Size. It can both extend and shrink the heap. | 32 | /// Set the process heap to a given Size. It can both extend and shrink the heap. |
| 34 | static ResultCode SetHeapSize(VAddr* heap_addr, u64 heap_size) { | 33 | static ResultCode SetHeapSize(VAddr* heap_addr, u64 heap_size) { |
| 35 | LOG_TRACE(Kernel_SVC, "called, heap_size=0x%llx", heap_size); | 34 | NGLOG_TRACE(Kernel_SVC, "called, heap_size={:#X}", heap_size); |
| 36 | auto& process = *Core::CurrentProcess(); | 35 | auto& process = *Core::CurrentProcess(); |
| 37 | CASCADE_RESULT(*heap_addr, | 36 | CASCADE_RESULT(*heap_addr, |
| 38 | process.HeapAllocate(Memory::HEAP_VADDR, heap_size, VMAPermission::ReadWrite)); | 37 | process.HeapAllocate(Memory::HEAP_VADDR, heap_size, VMAPermission::ReadWrite)); |
| @@ -40,21 +39,21 @@ static ResultCode SetHeapSize(VAddr* heap_addr, u64 heap_size) { | |||
| 40 | } | 39 | } |
| 41 | 40 | ||
| 42 | static ResultCode SetMemoryAttribute(VAddr addr, u64 size, u32 state0, u32 state1) { | 41 | static ResultCode SetMemoryAttribute(VAddr addr, u64 size, u32 state0, u32 state1) { |
| 43 | LOG_WARNING(Kernel_SVC, "(STUBBED) called, addr=0x%lx", addr); | 42 | NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, addr={:#X}", addr); |
| 44 | return RESULT_SUCCESS; | 43 | return RESULT_SUCCESS; |
| 45 | } | 44 | } |
| 46 | 45 | ||
| 47 | /// Maps a memory range into a different range. | 46 | /// Maps a memory range into a different range. |
| 48 | static ResultCode MapMemory(VAddr dst_addr, VAddr src_addr, u64 size) { | 47 | static ResultCode MapMemory(VAddr dst_addr, VAddr src_addr, u64 size) { |
| 49 | LOG_TRACE(Kernel_SVC, "called, dst_addr=0x%llx, src_addr=0x%llx, size=0x%llx", dst_addr, | 48 | NGLOG_TRACE(Kernel_SVC, "called, dst_addr={:#X}, src_addr={:#X}, size={:#X}", dst_addr, |
| 50 | src_addr, size); | 49 | src_addr, size); |
| 51 | return Core::CurrentProcess()->MirrorMemory(dst_addr, src_addr, size); | 50 | return Core::CurrentProcess()->MirrorMemory(dst_addr, src_addr, size); |
| 52 | } | 51 | } |
| 53 | 52 | ||
| 54 | /// Unmaps a region that was previously mapped with svcMapMemory | 53 | /// Unmaps a region that was previously mapped with svcMapMemory |
| 55 | static ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size) { | 54 | static ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size) { |
| 56 | LOG_TRACE(Kernel_SVC, "called, dst_addr=0x%llx, src_addr=0x%llx, size=0x%llx", dst_addr, | 55 | NGLOG_TRACE(Kernel_SVC, "called, dst_addr={:#X}, src_addr={:#X}, size={:#X}", dst_addr, |
| 57 | src_addr, size); | 56 | src_addr, size); |
| 58 | return Core::CurrentProcess()->UnmapMemory(dst_addr, src_addr, size); | 57 | return Core::CurrentProcess()->UnmapMemory(dst_addr, src_addr, size); |
| 59 | } | 58 | } |
| 60 | 59 | ||
| @@ -69,11 +68,11 @@ static ResultCode ConnectToNamedPort(Handle* out_handle, VAddr port_name_address | |||
| 69 | if (port_name.size() > PortNameMaxLength) | 68 | if (port_name.size() > PortNameMaxLength) |
| 70 | return ERR_PORT_NAME_TOO_LONG; | 69 | return ERR_PORT_NAME_TOO_LONG; |
| 71 | 70 | ||
| 72 | LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name.c_str()); | 71 | NGLOG_TRACE(Kernel_SVC, "called port_name={}", port_name); |
| 73 | 72 | ||
| 74 | auto it = Service::g_kernel_named_ports.find(port_name); | 73 | auto it = Service::g_kernel_named_ports.find(port_name); |
| 75 | if (it == Service::g_kernel_named_ports.end()) { | 74 | if (it == Service::g_kernel_named_ports.end()) { |
| 76 | LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: %s", port_name.c_str()); | 75 | NGLOG_WARNING(Kernel_SVC, "tried to connect to unknown port: {}", port_name); |
| 77 | return ERR_NOT_FOUND; | 76 | return ERR_NOT_FOUND; |
| 78 | } | 77 | } |
| 79 | 78 | ||
| @@ -91,11 +90,11 @@ static ResultCode ConnectToNamedPort(Handle* out_handle, VAddr port_name_address | |||
| 91 | static ResultCode SendSyncRequest(Handle handle) { | 90 | static ResultCode SendSyncRequest(Handle handle) { |
| 92 | SharedPtr<ClientSession> session = g_handle_table.Get<ClientSession>(handle); | 91 | SharedPtr<ClientSession> session = g_handle_table.Get<ClientSession>(handle); |
| 93 | if (!session) { | 92 | if (!session) { |
| 94 | LOG_ERROR(Kernel_SVC, "called with invalid handle=0x%08X", handle); | 93 | NGLOG_ERROR(Kernel_SVC, "called with invalid handle={:#010X}", handle); |
| 95 | return ERR_INVALID_HANDLE; | 94 | return ERR_INVALID_HANDLE; |
| 96 | } | 95 | } |
| 97 | 96 | ||
| 98 | LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s)", handle, session->GetName().c_str()); | 97 | NGLOG_TRACE(Kernel_SVC, "called handle={:#010X}({})", handle, session->GetName()); |
| 99 | 98 | ||
| 100 | Core::System::GetInstance().PrepareReschedule(); | 99 | Core::System::GetInstance().PrepareReschedule(); |
| 101 | 100 | ||
| @@ -106,7 +105,7 @@ static ResultCode SendSyncRequest(Handle handle) { | |||
| 106 | 105 | ||
| 107 | /// Get the ID for the specified thread. | 106 | /// Get the ID for the specified thread. |
| 108 | static ResultCode GetThreadId(u32* thread_id, Handle thread_handle) { | 107 | static ResultCode GetThreadId(u32* thread_id, Handle thread_handle) { |
| 109 | LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle); | 108 | NGLOG_TRACE(Kernel_SVC, "called thread={:#010X}", thread_handle); |
| 110 | 109 | ||
| 111 | const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle); | 110 | const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle); |
| 112 | if (!thread) { | 111 | if (!thread) { |
| @@ -119,7 +118,7 @@ static ResultCode GetThreadId(u32* thread_id, Handle thread_handle) { | |||
| 119 | 118 | ||
| 120 | /// Get the ID of the specified process | 119 | /// Get the ID of the specified process |
| 121 | static ResultCode GetProcessId(u32* process_id, Handle process_handle) { | 120 | static ResultCode GetProcessId(u32* process_id, Handle process_handle) { |
| 122 | LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle); | 121 | NGLOG_TRACE(Kernel_SVC, "called process={:#010X}", process_handle); |
| 123 | 122 | ||
| 124 | const SharedPtr<Process> process = g_handle_table.Get<Process>(process_handle); | 123 | const SharedPtr<Process> process = g_handle_table.Get<Process>(process_handle); |
| 125 | if (!process) { | 124 | if (!process) { |
| @@ -179,8 +178,8 @@ static ResultCode WaitSynchronization1( | |||
| 179 | /// Wait for the given handles to synchronize, timeout after the specified nanoseconds | 178 | /// Wait for the given handles to synchronize, timeout after the specified nanoseconds |
| 180 | static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64 handle_count, | 179 | static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64 handle_count, |
| 181 | s64 nano_seconds) { | 180 | s64 nano_seconds) { |
| 182 | LOG_TRACE(Kernel_SVC, "called handles_address=0x%llx, handle_count=%d, nano_seconds=%d", | 181 | NGLOG_TRACE(Kernel_SVC, "called handles_address={:#X}, handle_count={}, nano_seconds={}", |
| 183 | handles_address, handle_count, nano_seconds); | 182 | handles_address, handle_count, nano_seconds); |
| 184 | 183 | ||
| 185 | if (!Memory::IsValidVirtualAddress(handles_address)) | 184 | if (!Memory::IsValidVirtualAddress(handles_address)) |
| 186 | return ERR_INVALID_POINTER; | 185 | return ERR_INVALID_POINTER; |
| @@ -240,7 +239,7 @@ static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64 | |||
| 240 | 239 | ||
| 241 | /// Resumes a thread waiting on WaitSynchronization | 240 | /// Resumes a thread waiting on WaitSynchronization |
| 242 | static ResultCode CancelSynchronization(Handle thread_handle) { | 241 | static ResultCode CancelSynchronization(Handle thread_handle) { |
| 243 | LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle); | 242 | NGLOG_TRACE(Kernel_SVC, "called thread={:#X}", thread_handle); |
| 244 | 243 | ||
| 245 | const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle); | 244 | const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle); |
| 246 | if (!thread) { | 245 | if (!thread) { |
| @@ -257,56 +256,38 @@ static ResultCode CancelSynchronization(Handle thread_handle) { | |||
| 257 | /// Attempts to locks a mutex, creating it if it does not already exist | 256 | /// Attempts to locks a mutex, creating it if it does not already exist |
| 258 | static ResultCode ArbitrateLock(Handle holding_thread_handle, VAddr mutex_addr, | 257 | static ResultCode ArbitrateLock(Handle holding_thread_handle, VAddr mutex_addr, |
| 259 | Handle requesting_thread_handle) { | 258 | Handle requesting_thread_handle) { |
| 260 | LOG_TRACE(Kernel_SVC, | 259 | NGLOG_TRACE(Kernel_SVC, |
| 261 | "called holding_thread_handle=0x%08X, mutex_addr=0x%llx, " | 260 | "called holding_thread_handle={:#010X}, mutex_addr={:#X}, " |
| 262 | "requesting_current_thread_handle=0x%08X", | 261 | "requesting_current_thread_handle={:#010X}", |
| 263 | holding_thread_handle, mutex_addr, requesting_thread_handle); | 262 | holding_thread_handle, mutex_addr, requesting_thread_handle); |
| 264 | |||
| 265 | SharedPtr<Thread> holding_thread = g_handle_table.Get<Thread>(holding_thread_handle); | ||
| 266 | SharedPtr<Thread> requesting_thread = g_handle_table.Get<Thread>(requesting_thread_handle); | ||
| 267 | |||
| 268 | ASSERT(requesting_thread); | ||
| 269 | ASSERT(requesting_thread == GetCurrentThread()); | ||
| 270 | |||
| 271 | SharedPtr<Mutex> mutex = g_object_address_table.Get<Mutex>(mutex_addr); | ||
| 272 | if (!mutex) { | ||
| 273 | // Create a new mutex for the specified address if one does not already exist | ||
| 274 | mutex = Mutex::Create(holding_thread, mutex_addr); | ||
| 275 | mutex->name = Common::StringFromFormat("mutex-%llx", mutex_addr); | ||
| 276 | } | ||
| 277 | |||
| 278 | ASSERT(holding_thread == mutex->GetHoldingThread()); | ||
| 279 | 263 | ||
| 280 | return WaitSynchronization1(mutex, requesting_thread.get()); | 264 | return Mutex::TryAcquire(mutex_addr, holding_thread_handle, requesting_thread_handle); |
| 281 | } | 265 | } |
| 282 | 266 | ||
| 283 | /// Unlock a mutex | 267 | /// Unlock a mutex |
| 284 | static ResultCode ArbitrateUnlock(VAddr mutex_addr) { | 268 | static ResultCode ArbitrateUnlock(VAddr mutex_addr) { |
| 285 | LOG_TRACE(Kernel_SVC, "called mutex_addr=0x%llx", mutex_addr); | 269 | NGLOG_TRACE(Kernel_SVC, "called mutex_addr={:#X}", mutex_addr); |
| 286 | 270 | ||
| 287 | SharedPtr<Mutex> mutex = g_object_address_table.Get<Mutex>(mutex_addr); | 271 | return Mutex::Release(mutex_addr); |
| 288 | ASSERT(mutex); | ||
| 289 | |||
| 290 | return mutex->Release(GetCurrentThread()); | ||
| 291 | } | 272 | } |
| 292 | 273 | ||
| 293 | /// Break program execution | 274 | /// Break program execution |
| 294 | static void Break(u64 unk_0, u64 unk_1, u64 unk_2) { | 275 | static void Break(u64 unk_0, u64 unk_1, u64 unk_2) { |
| 295 | LOG_CRITICAL(Debug_Emulated, "Emulated program broke execution!"); | 276 | NGLOG_CRITICAL(Debug_Emulated, "Emulated program broke execution!"); |
| 296 | ASSERT(false); | 277 | ASSERT(false); |
| 297 | } | 278 | } |
| 298 | 279 | ||
| 299 | /// Used to output a message on a debug hardware unit - does nothing on a retail unit | 280 | /// Used to output a message on a debug hardware unit - does nothing on a retail unit |
| 300 | static void OutputDebugString(VAddr address, s32 len) { | 281 | static void OutputDebugString(VAddr address, s32 len) { |
| 301 | std::vector<char> string(len); | 282 | std::string str(len, '\0'); |
| 302 | Memory::ReadBlock(address, string.data(), len); | 283 | Memory::ReadBlock(address, str.data(), str.size()); |
| 303 | LOG_DEBUG(Debug_Emulated, "%.*s", len, string.data()); | 284 | NGLOG_DEBUG(Debug_Emulated, "{}", str); |
| 304 | } | 285 | } |
| 305 | 286 | ||
| 306 | /// Gets system/memory information for the current process | 287 | /// Gets system/memory information for the current process |
| 307 | static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) { | 288 | static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) { |
| 308 | LOG_TRACE(Kernel_SVC, "called info_id=0x%X, info_sub_id=0x%X, handle=0x%08X", info_id, | 289 | NGLOG_TRACE(Kernel_SVC, "called info_id={:#X}, info_sub_id={:#X}, handle={:#010X}", info_id, |
| 309 | info_sub_id, handle); | 290 | info_sub_id, handle); |
| 310 | 291 | ||
| 311 | auto& vm_manager = Core::CurrentProcess()->vm_manager; | 292 | auto& vm_manager = Core::CurrentProcess()->vm_manager; |
| 312 | 293 | ||
| @@ -357,12 +338,12 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) | |||
| 357 | *result = Core::CurrentProcess()->is_virtual_address_memory_enabled; | 338 | *result = Core::CurrentProcess()->is_virtual_address_memory_enabled; |
| 358 | break; | 339 | break; |
| 359 | case GetInfoType::TitleId: | 340 | case GetInfoType::TitleId: |
| 360 | LOG_WARNING(Kernel_SVC, "(STUBBED) Attempted to query titleid, returned 0"); | 341 | NGLOG_WARNING(Kernel_SVC, "(STUBBED) Attempted to query titleid, returned 0"); |
| 361 | *result = 0; | 342 | *result = 0; |
| 362 | break; | 343 | break; |
| 363 | case GetInfoType::PrivilegedProcessId: | 344 | case GetInfoType::PrivilegedProcessId: |
| 364 | LOG_WARNING(Kernel_SVC, | 345 | NGLOG_WARNING(Kernel_SVC, |
| 365 | "(STUBBED) Attempted to query priviledged process id bounds, returned 0"); | 346 | "(STUBBED) Attempted to query privileged process id bounds, returned 0"); |
| 366 | *result = 0; | 347 | *result = 0; |
| 367 | break; | 348 | break; |
| 368 | default: | 349 | default: |
| @@ -374,13 +355,14 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) | |||
| 374 | 355 | ||
| 375 | /// Sets the thread activity | 356 | /// Sets the thread activity |
| 376 | static ResultCode SetThreadActivity(Handle handle, u32 unknown) { | 357 | static ResultCode SetThreadActivity(Handle handle, u32 unknown) { |
| 377 | LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x%08X, unknown=0x%08X", handle, unknown); | 358 | NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, handle={:#010X}, unknown={:#010X}", handle, |
| 359 | unknown); | ||
| 378 | return RESULT_SUCCESS; | 360 | return RESULT_SUCCESS; |
| 379 | } | 361 | } |
| 380 | 362 | ||
| 381 | /// Gets the thread context | 363 | /// Gets the thread context |
| 382 | static ResultCode GetThreadContext(Handle handle, VAddr addr) { | 364 | static ResultCode GetThreadContext(Handle handle, VAddr addr) { |
| 383 | LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x%08X, addr=0x%" PRIx64, handle, addr); | 365 | NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, handle={:#010X}, addr={:#X}", handle, addr); |
| 384 | return RESULT_SUCCESS; | 366 | return RESULT_SUCCESS; |
| 385 | } | 367 | } |
| 386 | 368 | ||
| @@ -412,11 +394,6 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) { | |||
| 412 | } | 394 | } |
| 413 | 395 | ||
| 414 | thread->SetPriority(priority); | 396 | thread->SetPriority(priority); |
| 415 | thread->UpdatePriority(); | ||
| 416 | |||
| 417 | // Update the mutexes that this thread is waiting for | ||
| 418 | for (auto& mutex : thread->pending_mutexes) | ||
| 419 | mutex->UpdatePriority(); | ||
| 420 | 397 | ||
| 421 | Core::System::GetInstance().PrepareReschedule(); | 398 | Core::System::GetInstance().PrepareReschedule(); |
| 422 | return RESULT_SUCCESS; | 399 | return RESULT_SUCCESS; |
| @@ -424,15 +401,15 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) { | |||
| 424 | 401 | ||
| 425 | /// Get which CPU core is executing the current thread | 402 | /// Get which CPU core is executing the current thread |
| 426 | static u32 GetCurrentProcessorNumber() { | 403 | static u32 GetCurrentProcessorNumber() { |
| 427 | LOG_WARNING(Kernel_SVC, "(STUBBED) called, defaulting to processor 0"); | 404 | NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, defaulting to processor 0"); |
| 428 | return 0; | 405 | return 0; |
| 429 | } | 406 | } |
| 430 | 407 | ||
| 431 | static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size, | 408 | static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size, |
| 432 | u32 permissions) { | 409 | u32 permissions) { |
| 433 | LOG_TRACE(Kernel_SVC, | 410 | NGLOG_TRACE(Kernel_SVC, |
| 434 | "called, shared_memory_handle=0x%08X, addr=0x%llx, size=0x%llx, permissions=0x%08X", | 411 | "called, shared_memory_handle={:#X}, addr={:#X}, size={:#X}, permissions={:#010X}", |
| 435 | shared_memory_handle, addr, size, permissions); | 412 | shared_memory_handle, addr, size, permissions); |
| 436 | 413 | ||
| 437 | SharedPtr<SharedMemory> shared_memory = g_handle_table.Get<SharedMemory>(shared_memory_handle); | 414 | SharedPtr<SharedMemory> shared_memory = g_handle_table.Get<SharedMemory>(shared_memory_handle); |
| 438 | if (!shared_memory) { | 415 | if (!shared_memory) { |
| @@ -452,16 +429,15 @@ static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 s | |||
| 452 | return shared_memory->Map(Core::CurrentProcess().get(), addr, permissions_type, | 429 | return shared_memory->Map(Core::CurrentProcess().get(), addr, permissions_type, |
| 453 | MemoryPermission::DontCare); | 430 | MemoryPermission::DontCare); |
| 454 | default: | 431 | default: |
| 455 | LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions); | 432 | NGLOG_ERROR(Kernel_SVC, "unknown permissions={:#010X}", permissions); |
| 456 | } | 433 | } |
| 457 | 434 | ||
| 458 | return RESULT_SUCCESS; | 435 | return RESULT_SUCCESS; |
| 459 | } | 436 | } |
| 460 | 437 | ||
| 461 | static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size) { | 438 | static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size) { |
| 462 | LOG_WARNING(Kernel_SVC, | 439 | NGLOG_WARNING(Kernel_SVC, "called, shared_memory_handle={:#010X}, addr={:#X}, size={:#X}", |
| 463 | "called, shared_memory_handle=0x%08X, addr=0x%" PRIx64 ", size=0x%" PRIx64 "", | 440 | shared_memory_handle, addr, size); |
| 464 | shared_memory_handle, addr, size); | ||
| 465 | 441 | ||
| 466 | SharedPtr<SharedMemory> shared_memory = g_handle_table.Get<SharedMemory>(shared_memory_handle); | 442 | SharedPtr<SharedMemory> shared_memory = g_handle_table.Get<SharedMemory>(shared_memory_handle); |
| 467 | 443 | ||
| @@ -489,19 +465,19 @@ static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* /*page_i | |||
| 489 | memory_info->type = static_cast<u32>(vma->second.meminfo_state); | 465 | memory_info->type = static_cast<u32>(vma->second.meminfo_state); |
| 490 | } | 466 | } |
| 491 | 467 | ||
| 492 | LOG_TRACE(Kernel_SVC, "called process=0x%08X addr=%llx", process_handle, addr); | 468 | NGLOG_TRACE(Kernel_SVC, "called process={:#010X} addr={:X}", process_handle, addr); |
| 493 | return RESULT_SUCCESS; | 469 | return RESULT_SUCCESS; |
| 494 | } | 470 | } |
| 495 | 471 | ||
| 496 | /// Query memory | 472 | /// Query memory |
| 497 | static ResultCode QueryMemory(MemoryInfo* memory_info, PageInfo* page_info, VAddr addr) { | 473 | static ResultCode QueryMemory(MemoryInfo* memory_info, PageInfo* page_info, VAddr addr) { |
| 498 | LOG_TRACE(Kernel_SVC, "called, addr=%llx", addr); | 474 | NGLOG_TRACE(Kernel_SVC, "called, addr={:X}", addr); |
| 499 | return QueryProcessMemory(memory_info, page_info, CurrentProcess, addr); | 475 | return QueryProcessMemory(memory_info, page_info, CurrentProcess, addr); |
| 500 | } | 476 | } |
| 501 | 477 | ||
| 502 | /// Exits the current process | 478 | /// Exits the current process |
| 503 | static void ExitProcess() { | 479 | static void ExitProcess() { |
| 504 | LOG_INFO(Kernel_SVC, "Process %u exiting", Core::CurrentProcess()->process_id); | 480 | NGLOG_INFO(Kernel_SVC, "Process {} exiting", Core::CurrentProcess()->process_id); |
| 505 | 481 | ||
| 506 | ASSERT_MSG(Core::CurrentProcess()->status == ProcessStatus::Running, | 482 | ASSERT_MSG(Core::CurrentProcess()->status == ProcessStatus::Running, |
| 507 | "Process has already exited"); | 483 | "Process has already exited"); |
| @@ -558,9 +534,9 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V | |||
| 558 | case THREADPROCESSORID_2: | 534 | case THREADPROCESSORID_2: |
| 559 | case THREADPROCESSORID_3: | 535 | case THREADPROCESSORID_3: |
| 560 | // TODO(bunnei): Implement support for other processor IDs | 536 | // TODO(bunnei): Implement support for other processor IDs |
| 561 | LOG_ERROR(Kernel_SVC, | 537 | NGLOG_ERROR(Kernel_SVC, |
| 562 | "Newly created thread must run in another thread (%u), unimplemented.", | 538 | "Newly created thread must run in another thread ({}), unimplemented.", |
| 563 | processor_id); | 539 | processor_id); |
| 564 | break; | 540 | break; |
| 565 | default: | 541 | default: |
| 566 | ASSERT_MSG(false, "Unsupported thread processor ID: %d", processor_id); | 542 | ASSERT_MSG(false, "Unsupported thread processor ID: %d", processor_id); |
| @@ -575,17 +551,17 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V | |||
| 575 | 551 | ||
| 576 | Core::System::GetInstance().PrepareReschedule(); | 552 | Core::System::GetInstance().PrepareReschedule(); |
| 577 | 553 | ||
| 578 | LOG_TRACE(Kernel_SVC, | 554 | NGLOG_TRACE(Kernel_SVC, |
| 579 | "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " | 555 | "called entrypoint={:#010X} ({}), arg={:#010X}, stacktop={:#010X}, " |
| 580 | "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", | 556 | "threadpriority={:#010X}, processorid={:#010X} : created handle={:#010X}", |
| 581 | entry_point, name.c_str(), arg, stack_top, priority, processor_id, *out_handle); | 557 | entry_point, name, arg, stack_top, priority, processor_id, *out_handle); |
| 582 | 558 | ||
| 583 | return RESULT_SUCCESS; | 559 | return RESULT_SUCCESS; |
| 584 | } | 560 | } |
| 585 | 561 | ||
| 586 | /// Starts the thread for the provided handle | 562 | /// Starts the thread for the provided handle |
| 587 | static ResultCode StartThread(Handle thread_handle) { | 563 | static ResultCode StartThread(Handle thread_handle) { |
| 588 | LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle); | 564 | NGLOG_TRACE(Kernel_SVC, "called thread={:#010X}", thread_handle); |
| 589 | 565 | ||
| 590 | const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle); | 566 | const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle); |
| 591 | if (!thread) { | 567 | if (!thread) { |
| @@ -599,7 +575,7 @@ static ResultCode StartThread(Handle thread_handle) { | |||
| 599 | 575 | ||
| 600 | /// Called when a thread exits | 576 | /// Called when a thread exits |
| 601 | static void ExitThread() { | 577 | static void ExitThread() { |
| 602 | LOG_TRACE(Kernel_SVC, "called, pc=0x%08X", Core::CPU().GetPC()); | 578 | NGLOG_TRACE(Kernel_SVC, "called, pc={:#010X}", Core::CPU().GetPC()); |
| 603 | 579 | ||
| 604 | ExitCurrentThread(); | 580 | ExitCurrentThread(); |
| 605 | Core::System::GetInstance().PrepareReschedule(); | 581 | Core::System::GetInstance().PrepareReschedule(); |
| @@ -607,7 +583,7 @@ static void ExitThread() { | |||
| 607 | 583 | ||
| 608 | /// Sleep the current thread | 584 | /// Sleep the current thread |
| 609 | static void SleepThread(s64 nanoseconds) { | 585 | static void SleepThread(s64 nanoseconds) { |
| 610 | LOG_TRACE(Kernel_SVC, "called nanoseconds=%lld", nanoseconds); | 586 | NGLOG_TRACE(Kernel_SVC, "called nanoseconds={}", nanoseconds); |
| 611 | 587 | ||
| 612 | // Don't attempt to yield execution if there are no available threads to run, | 588 | // Don't attempt to yield execution if there are no available threads to run, |
| 613 | // this way we avoid a useless reschedule to the idle thread. | 589 | // this way we avoid a useless reschedule to the idle thread. |
| @@ -626,111 +602,83 @@ static void SleepThread(s64 nanoseconds) { | |||
| 626 | /// Signal process wide key atomic | 602 | /// Signal process wide key atomic |
| 627 | static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_variable_addr, | 603 | static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_variable_addr, |
| 628 | Handle thread_handle, s64 nano_seconds) { | 604 | Handle thread_handle, s64 nano_seconds) { |
| 629 | LOG_TRACE( | 605 | NGLOG_TRACE( |
| 630 | Kernel_SVC, | 606 | Kernel_SVC, |
| 631 | "called mutex_addr=%llx, condition_variable_addr=%llx, thread_handle=0x%08X, timeout=%d", | 607 | "called mutex_addr={:X}, condition_variable_addr={:X}, thread_handle={:#010X}, timeout={}", |
| 632 | mutex_addr, condition_variable_addr, thread_handle, nano_seconds); | 608 | mutex_addr, condition_variable_addr, thread_handle, nano_seconds); |
| 633 | 609 | ||
| 634 | SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle); | 610 | SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle); |
| 635 | ASSERT(thread); | 611 | ASSERT(thread); |
| 636 | 612 | ||
| 637 | SharedPtr<Mutex> mutex = g_object_address_table.Get<Mutex>(mutex_addr); | 613 | CASCADE_CODE(Mutex::Release(mutex_addr)); |
| 638 | if (!mutex) { | ||
| 639 | // Create a new mutex for the specified address if one does not already exist | ||
| 640 | mutex = Mutex::Create(thread, mutex_addr); | ||
| 641 | mutex->name = Common::StringFromFormat("mutex-%llx", mutex_addr); | ||
| 642 | } | ||
| 643 | 614 | ||
| 644 | SharedPtr<ConditionVariable> condition_variable = | 615 | SharedPtr<Thread> current_thread = GetCurrentThread(); |
| 645 | g_object_address_table.Get<ConditionVariable>(condition_variable_addr); | 616 | current_thread->condvar_wait_address = condition_variable_addr; |
| 646 | if (!condition_variable) { | 617 | current_thread->mutex_wait_address = mutex_addr; |
| 647 | // Create a new condition_variable for the specified address if one does not already exist | 618 | current_thread->wait_handle = thread_handle; |
| 648 | condition_variable = ConditionVariable::Create(condition_variable_addr).Unwrap(); | 619 | current_thread->status = THREADSTATUS_WAIT_MUTEX; |
| 649 | condition_variable->name = | 620 | current_thread->wakeup_callback = nullptr; |
| 650 | Common::StringFromFormat("condition-variable-%llx", condition_variable_addr); | ||
| 651 | } | ||
| 652 | 621 | ||
| 653 | if (condition_variable->mutex_addr) { | 622 | current_thread->WakeAfterDelay(nano_seconds); |
| 654 | // Previously created the ConditionVariable using WaitProcessWideKeyAtomic, verify | ||
| 655 | // everything is correct | ||
| 656 | ASSERT(condition_variable->mutex_addr == mutex_addr); | ||
| 657 | } else { | ||
| 658 | // Previously created the ConditionVariable using SignalProcessWideKey, set the mutex | ||
| 659 | // associated with it | ||
| 660 | condition_variable->mutex_addr = mutex_addr; | ||
| 661 | } | ||
| 662 | 623 | ||
| 663 | if (mutex->GetOwnerHandle()) { | 624 | // Note: Deliberately don't attempt to inherit the lock owner's priority. |
| 664 | // Release the mutex if the current thread is holding it | ||
| 665 | mutex->Release(thread.get()); | ||
| 666 | } | ||
| 667 | 625 | ||
| 668 | auto wakeup_callback = [mutex, nano_seconds](ThreadWakeupReason reason, | 626 | Core::System::GetInstance().PrepareReschedule(); |
| 669 | SharedPtr<Thread> thread, | 627 | return RESULT_SUCCESS; |
| 670 | SharedPtr<WaitObject> object, size_t index) { | 628 | } |
| 671 | ASSERT(thread->status == THREADSTATUS_WAIT_SYNCH_ANY); | ||
| 672 | 629 | ||
| 673 | if (reason == ThreadWakeupReason::Timeout) { | 630 | /// Signal process wide key |
| 674 | thread->SetWaitSynchronizationResult(RESULT_TIMEOUT); | 631 | static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target) { |
| 675 | return true; | 632 | NGLOG_TRACE(Kernel_SVC, "called, condition_variable_addr={:#X}, target={:#010X}", |
| 676 | } | 633 | condition_variable_addr, target); |
| 677 | 634 | ||
| 678 | ASSERT(reason == ThreadWakeupReason::Signal); | 635 | u32 processed = 0; |
| 636 | auto& thread_list = Core::System::GetInstance().Scheduler().GetThreadList(); | ||
| 679 | 637 | ||
| 680 | // Now try to acquire the mutex and don't resume if it's not available. | 638 | for (auto& thread : thread_list) { |
| 681 | if (!mutex->ShouldWait(thread.get())) { | 639 | if (thread->condvar_wait_address != condition_variable_addr) |
| 682 | mutex->Acquire(thread.get()); | 640 | continue; |
| 683 | thread->SetWaitSynchronizationResult(RESULT_SUCCESS); | ||
| 684 | return true; | ||
| 685 | } | ||
| 686 | 641 | ||
| 687 | if (nano_seconds == 0) { | 642 | // Only process up to 'target' threads, unless 'target' is -1, in which case process |
| 688 | thread->SetWaitSynchronizationResult(RESULT_TIMEOUT); | 643 | // them all. |
| 689 | return true; | 644 | if (target != -1 && processed >= target) |
| 690 | } | 645 | break; |
| 691 | 646 | ||
| 692 | thread->wait_objects = {mutex}; | 647 | // If the mutex is not yet acquired, acquire it. |
| 693 | mutex->AddWaitingThread(thread); | 648 | u32 mutex_val = Memory::Read32(thread->mutex_wait_address); |
| 694 | thread->status = THREADSTATUS_WAIT_SYNCH_ANY; | ||
| 695 | 649 | ||
| 696 | // Create an event to wake the thread up after the | 650 | if (mutex_val == 0) { |
| 697 | // specified nanosecond delay has passed | 651 | // We were able to acquire the mutex, resume this thread. |
| 698 | thread->WakeAfterDelay(nano_seconds); | 652 | Memory::Write32(thread->mutex_wait_address, thread->wait_handle); |
| 699 | thread->wakeup_callback = DefaultThreadWakeupCallback; | 653 | ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX); |
| 654 | thread->ResumeFromWait(); | ||
| 700 | 655 | ||
| 701 | Core::System::GetInstance().PrepareReschedule(); | 656 | auto lock_owner = thread->lock_owner; |
| 657 | if (lock_owner) | ||
| 658 | lock_owner->RemoveMutexWaiter(thread); | ||
| 702 | 659 | ||
| 703 | return false; | 660 | thread->lock_owner = nullptr; |
| 704 | }; | 661 | thread->mutex_wait_address = 0; |
| 705 | CASCADE_CODE( | 662 | thread->condvar_wait_address = 0; |
| 706 | WaitSynchronization1(condition_variable, thread.get(), nano_seconds, wakeup_callback)); | 663 | thread->wait_handle = 0; |
| 664 | } else { | ||
| 665 | // Couldn't acquire the mutex, block the thread. | ||
| 666 | Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask); | ||
| 667 | auto owner = g_handle_table.Get<Thread>(owner_handle); | ||
| 668 | ASSERT(owner); | ||
| 669 | ASSERT(thread->status != THREADSTATUS_RUNNING); | ||
| 670 | thread->status = THREADSTATUS_WAIT_MUTEX; | ||
| 671 | thread->wakeup_callback = nullptr; | ||
| 707 | 672 | ||
| 708 | return RESULT_SUCCESS; | 673 | // Signal that the mutex now has a waiting thread. |
| 709 | } | 674 | Memory::Write32(thread->mutex_wait_address, mutex_val | Mutex::MutexHasWaitersFlag); |
| 710 | 675 | ||
| 711 | /// Signal process wide key | 676 | owner->AddMutexWaiter(thread); |
| 712 | static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target) { | ||
| 713 | LOG_TRACE(Kernel_SVC, "called, condition_variable_addr=0x%llx, target=0x%08x", | ||
| 714 | condition_variable_addr, target); | ||
| 715 | |||
| 716 | // Wakeup all or one thread - Any other value is unimplemented | ||
| 717 | ASSERT(target == -1 || target == 1); | ||
| 718 | |||
| 719 | SharedPtr<ConditionVariable> condition_variable = | ||
| 720 | g_object_address_table.Get<ConditionVariable>(condition_variable_addr); | ||
| 721 | if (!condition_variable) { | ||
| 722 | // Create a new condition_variable for the specified address if one does not already exist | ||
| 723 | condition_variable = ConditionVariable::Create(condition_variable_addr).Unwrap(); | ||
| 724 | condition_variable->name = | ||
| 725 | Common::StringFromFormat("condition-variable-%llx", condition_variable_addr); | ||
| 726 | } | ||
| 727 | 677 | ||
| 728 | CASCADE_CODE(condition_variable->Release(target)); | 678 | Core::System::GetInstance().PrepareReschedule(); |
| 679 | } | ||
| 729 | 680 | ||
| 730 | if (condition_variable->mutex_addr) { | 681 | ++processed; |
| 731 | // If a mutex was created for this condition_variable, wait the current thread on it | ||
| 732 | SharedPtr<Mutex> mutex = g_object_address_table.Get<Mutex>(condition_variable->mutex_addr); | ||
| 733 | return WaitSynchronization1(mutex, GetCurrentThread()); | ||
| 734 | } | 682 | } |
| 735 | 683 | ||
| 736 | return RESULT_SUCCESS; | 684 | return RESULT_SUCCESS; |
| @@ -748,13 +696,13 @@ static u64 GetSystemTick() { | |||
| 748 | 696 | ||
| 749 | /// Close a handle | 697 | /// Close a handle |
| 750 | static ResultCode CloseHandle(Handle handle) { | 698 | static ResultCode CloseHandle(Handle handle) { |
| 751 | LOG_TRACE(Kernel_SVC, "Closing handle 0x%08X", handle); | 699 | NGLOG_TRACE(Kernel_SVC, "Closing handle {:#010X}", handle); |
| 752 | return g_handle_table.Close(handle); | 700 | return g_handle_table.Close(handle); |
| 753 | } | 701 | } |
| 754 | 702 | ||
| 755 | /// Reset an event | 703 | /// Reset an event |
| 756 | static ResultCode ResetSignal(Handle handle) { | 704 | static ResultCode ResetSignal(Handle handle) { |
| 757 | LOG_WARNING(Kernel_SVC, "(STUBBED) called handle 0x%08X", handle); | 705 | NGLOG_WARNING(Kernel_SVC, "(STUBBED) called handle {:#010X}", handle); |
| 758 | auto event = g_handle_table.Get<Event>(handle); | 706 | auto event = g_handle_table.Get<Event>(handle); |
| 759 | ASSERT(event != nullptr); | 707 | ASSERT(event != nullptr); |
| 760 | event->Clear(); | 708 | event->Clear(); |
| @@ -763,29 +711,29 @@ static ResultCode ResetSignal(Handle handle) { | |||
| 763 | 711 | ||
| 764 | /// Creates a TransferMemory object | 712 | /// Creates a TransferMemory object |
| 765 | static ResultCode CreateTransferMemory(Handle* handle, VAddr addr, u64 size, u32 permissions) { | 713 | static ResultCode CreateTransferMemory(Handle* handle, VAddr addr, u64 size, u32 permissions) { |
| 766 | LOG_WARNING(Kernel_SVC, "(STUBBED) called addr=0x%lx, size=0x%lx, perms=%08X", addr, size, | 714 | NGLOG_WARNING(Kernel_SVC, "(STUBBED) called addr={:#X}, size={:#X}, perms={:010X}", addr, size, |
| 767 | permissions); | 715 | permissions); |
| 768 | *handle = 0; | 716 | *handle = 0; |
| 769 | return RESULT_SUCCESS; | 717 | return RESULT_SUCCESS; |
| 770 | } | 718 | } |
| 771 | 719 | ||
| 772 | static ResultCode GetThreadCoreMask(Handle handle, u32* mask, u64* unknown) { | 720 | static ResultCode GetThreadCoreMask(Handle handle, u32* mask, u64* unknown) { |
| 773 | LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x%08X", handle); | 721 | NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, handle={:010X}", handle); |
| 774 | *mask = 0x0; | 722 | *mask = 0x0; |
| 775 | *unknown = 0xf; | 723 | *unknown = 0xf; |
| 776 | return RESULT_SUCCESS; | 724 | return RESULT_SUCCESS; |
| 777 | } | 725 | } |
| 778 | 726 | ||
| 779 | static ResultCode SetThreadCoreMask(Handle handle, u32 mask, u64 unknown) { | 727 | static ResultCode SetThreadCoreMask(Handle handle, u32 mask, u64 unknown) { |
| 780 | LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x%08X, mask=0x%08X, unknown=0x%lx", handle, | 728 | NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, handle={:#010X}, mask={:#010X}, unknown={:#X}", |
| 781 | mask, unknown); | 729 | handle, mask, unknown); |
| 782 | return RESULT_SUCCESS; | 730 | return RESULT_SUCCESS; |
| 783 | } | 731 | } |
| 784 | 732 | ||
| 785 | static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permissions, | 733 | static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permissions, |
| 786 | u32 remote_permissions) { | 734 | u32 remote_permissions) { |
| 787 | LOG_TRACE(Kernel_SVC, "called, size=0x%llx, localPerms=0x%08x, remotePerms=0x%08x", size, | 735 | NGLOG_TRACE(Kernel_SVC, "called, size={:#X}, localPerms={:#010X}, remotePerms={:#010X}", size, |
| 788 | local_permissions, remote_permissions); | 736 | local_permissions, remote_permissions); |
| 789 | auto sharedMemHandle = | 737 | auto sharedMemHandle = |
| 790 | SharedMemory::Create(g_handle_table.Get<Process>(KernelHandle::CurrentProcess), size, | 738 | SharedMemory::Create(g_handle_table.Get<Process>(KernelHandle::CurrentProcess), size, |
| 791 | static_cast<MemoryPermission>(local_permissions), | 739 | static_cast<MemoryPermission>(local_permissions), |
| @@ -796,7 +744,7 @@ static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permiss | |||
| 796 | } | 744 | } |
| 797 | 745 | ||
| 798 | static ResultCode ClearEvent(Handle handle) { | 746 | static ResultCode ClearEvent(Handle handle) { |
| 799 | LOG_TRACE(Kernel_SVC, "called, event=0xX", handle); | 747 | NGLOG_TRACE(Kernel_SVC, "called, event={:010X}", handle); |
| 800 | 748 | ||
| 801 | SharedPtr<Event> evt = g_handle_table.Get<Event>(handle); | 749 | SharedPtr<Event> evt = g_handle_table.Get<Event>(handle); |
| 802 | if (evt == nullptr) | 750 | if (evt == nullptr) |
| @@ -948,7 +896,7 @@ static const FunctionDef SVC_Table[] = { | |||
| 948 | 896 | ||
| 949 | static const FunctionDef* GetSVCInfo(u32 func_num) { | 897 | static const FunctionDef* GetSVCInfo(u32 func_num) { |
| 950 | if (func_num >= std::size(SVC_Table)) { | 898 | if (func_num >= std::size(SVC_Table)) { |
| 951 | LOG_ERROR(Kernel_SVC, "unknown svc=0x%02X", func_num); | 899 | NGLOG_ERROR(Kernel_SVC, "Unknown svc={:#04X}", func_num); |
| 952 | return nullptr; | 900 | return nullptr; |
| 953 | } | 901 | } |
| 954 | return &SVC_Table[func_num]; | 902 | return &SVC_Table[func_num]; |
| @@ -967,10 +915,10 @@ void CallSVC(u32 immediate) { | |||
| 967 | if (info->func) { | 915 | if (info->func) { |
| 968 | info->func(); | 916 | info->func(); |
| 969 | } else { | 917 | } else { |
| 970 | LOG_CRITICAL(Kernel_SVC, "unimplemented SVC function %s(..)", info->name); | 918 | NGLOG_CRITICAL(Kernel_SVC, "Unimplemented SVC function {}(..)", info->name); |
| 971 | } | 919 | } |
| 972 | } else { | 920 | } else { |
| 973 | LOG_CRITICAL(Kernel_SVC, "unknown SVC function 0x%x", immediate); | 921 | NGLOG_CRITICAL(Kernel_SVC, "Unknown SVC function {:#X}", immediate); |
| 974 | } | 922 | } |
| 975 | } | 923 | } |
| 976 | 924 | ||