diff options
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 117 |
1 files changed, 48 insertions, 69 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index ecac97a52..9962ad171 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -267,7 +267,7 @@ Result CreateSession(Core::System& system, Handle* out_server, Handle* out_clien | |||
| 267 | 267 | ||
| 268 | // Reserve a new session from the process resource limit. | 268 | // Reserve a new session from the process resource limit. |
| 269 | // FIXME: LimitableResource_SessionCountMax | 269 | // FIXME: LimitableResource_SessionCountMax |
| 270 | KScopedResourceReservation session_reservation(&process, LimitableResource::Sessions); | 270 | KScopedResourceReservation session_reservation(&process, LimitableResource::SessionCountMax); |
| 271 | if (session_reservation.Succeeded()) { | 271 | if (session_reservation.Succeeded()) { |
| 272 | session = T::Create(system.Kernel()); | 272 | session = T::Create(system.Kernel()); |
| 273 | } else { | 273 | } else { |
| @@ -298,7 +298,7 @@ Result CreateSession(Core::System& system, Handle* out_server, Handle* out_clien | |||
| 298 | 298 | ||
| 299 | // We successfully allocated a session, so add the object we allocated to the resource | 299 | // We successfully allocated a session, so add the object we allocated to the resource |
| 300 | // limit. | 300 | // limit. |
| 301 | // system.Kernel().GetSystemResourceLimit().Reserve(LimitableResource::Sessions, 1); | 301 | // system.Kernel().GetSystemResourceLimit().Reserve(LimitableResource::SessionCountMax, 1); |
| 302 | } | 302 | } |
| 303 | 303 | ||
| 304 | // Check that we successfully created a session. | 304 | // Check that we successfully created a session. |
| @@ -656,27 +656,12 @@ static Result ArbitrateUnlock32(Core::System& system, u32 address) { | |||
| 656 | return ArbitrateUnlock(system, address); | 656 | return ArbitrateUnlock(system, address); |
| 657 | } | 657 | } |
| 658 | 658 | ||
| 659 | enum class BreakType : u32 { | ||
| 660 | Panic = 0, | ||
| 661 | AssertionFailed = 1, | ||
| 662 | PreNROLoad = 3, | ||
| 663 | PostNROLoad = 4, | ||
| 664 | PreNROUnload = 5, | ||
| 665 | PostNROUnload = 6, | ||
| 666 | CppException = 7, | ||
| 667 | }; | ||
| 668 | |||
| 669 | struct BreakReason { | ||
| 670 | union { | ||
| 671 | u32 raw; | ||
| 672 | BitField<0, 30, BreakType> break_type; | ||
| 673 | BitField<31, 1, u32> signal_debugger; | ||
| 674 | }; | ||
| 675 | }; | ||
| 676 | |||
| 677 | /// Break program execution | 659 | /// Break program execution |
| 678 | static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) { | 660 | static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) { |
| 679 | BreakReason break_reason{reason}; | 661 | BreakReason break_reason = |
| 662 | static_cast<BreakReason>(reason & ~static_cast<u32>(BreakReason::NotificationOnlyFlag)); | ||
| 663 | bool notification_only = (reason & static_cast<u32>(BreakReason::NotificationOnlyFlag)) != 0; | ||
| 664 | |||
| 680 | bool has_dumped_buffer{}; | 665 | bool has_dumped_buffer{}; |
| 681 | std::vector<u8> debug_buffer; | 666 | std::vector<u8> debug_buffer; |
| 682 | 667 | ||
| @@ -705,57 +690,56 @@ static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) { | |||
| 705 | } | 690 | } |
| 706 | has_dumped_buffer = true; | 691 | has_dumped_buffer = true; |
| 707 | }; | 692 | }; |
| 708 | switch (break_reason.break_type) { | 693 | switch (break_reason) { |
| 709 | case BreakType::Panic: | 694 | case BreakReason::Panic: |
| 710 | LOG_CRITICAL(Debug_Emulated, "Signalling debugger, PANIC! info1=0x{:016X}, info2=0x{:016X}", | 695 | LOG_CRITICAL(Debug_Emulated, "Userspace PANIC! info1=0x{:016X}, info2=0x{:016X}", info1, |
| 711 | info1, info2); | 696 | info2); |
| 712 | handle_debug_buffer(info1, info2); | 697 | handle_debug_buffer(info1, info2); |
| 713 | break; | 698 | break; |
| 714 | case BreakType::AssertionFailed: | 699 | case BreakReason::Assert: |
| 715 | LOG_CRITICAL(Debug_Emulated, | 700 | LOG_CRITICAL(Debug_Emulated, "Userspace Assertion failed! info1=0x{:016X}, info2=0x{:016X}", |
| 716 | "Signalling debugger, Assertion failed! info1=0x{:016X}, info2=0x{:016X}", | ||
| 717 | info1, info2); | 701 | info1, info2); |
| 718 | handle_debug_buffer(info1, info2); | 702 | handle_debug_buffer(info1, info2); |
| 719 | break; | 703 | break; |
| 720 | case BreakType::PreNROLoad: | 704 | case BreakReason::User: |
| 721 | LOG_WARNING( | 705 | LOG_WARNING(Debug_Emulated, "Userspace Break! 0x{:016X} with size 0x{:016X}", info1, info2); |
| 722 | Debug_Emulated, | 706 | handle_debug_buffer(info1, info2); |
| 723 | "Signalling debugger, Attempting to load an NRO at 0x{:016X} with size 0x{:016X}", | ||
| 724 | info1, info2); | ||
| 725 | break; | 707 | break; |
| 726 | case BreakType::PostNROLoad: | 708 | case BreakReason::PreLoadDll: |
| 727 | LOG_WARNING(Debug_Emulated, | 709 | LOG_INFO(Debug_Emulated, |
| 728 | "Signalling debugger, Loaded an NRO at 0x{:016X} with size 0x{:016X}", info1, | 710 | "Userspace Attempting to load an NRO at 0x{:016X} with size 0x{:016X}", info1, |
| 729 | info2); | 711 | info2); |
| 730 | break; | 712 | break; |
| 731 | case BreakType::PreNROUnload: | 713 | case BreakReason::PostLoadDll: |
| 732 | LOG_WARNING( | 714 | LOG_INFO(Debug_Emulated, "Userspace Loaded an NRO at 0x{:016X} with size 0x{:016X}", info1, |
| 733 | Debug_Emulated, | 715 | info2); |
| 734 | "Signalling debugger, Attempting to unload an NRO at 0x{:016X} with size 0x{:016X}", | ||
| 735 | info1, info2); | ||
| 736 | break; | 716 | break; |
| 737 | case BreakType::PostNROUnload: | 717 | case BreakReason::PreUnloadDll: |
| 738 | LOG_WARNING(Debug_Emulated, | 718 | LOG_INFO(Debug_Emulated, |
| 739 | "Signalling debugger, Unloaded an NRO at 0x{:016X} with size 0x{:016X}", info1, | 719 | "Userspace Attempting to unload an NRO at 0x{:016X} with size 0x{:016X}", info1, |
| 740 | info2); | 720 | info2); |
| 741 | break; | 721 | break; |
| 742 | case BreakType::CppException: | 722 | case BreakReason::PostUnloadDll: |
| 723 | LOG_INFO(Debug_Emulated, "Userspace Unloaded an NRO at 0x{:016X} with size 0x{:016X}", | ||
| 724 | info1, info2); | ||
| 725 | break; | ||
| 726 | case BreakReason::CppException: | ||
| 743 | LOG_CRITICAL(Debug_Emulated, "Signalling debugger. Uncaught C++ exception encountered."); | 727 | LOG_CRITICAL(Debug_Emulated, "Signalling debugger. Uncaught C++ exception encountered."); |
| 744 | break; | 728 | break; |
| 745 | default: | 729 | default: |
| 746 | LOG_WARNING( | 730 | LOG_WARNING( |
| 747 | Debug_Emulated, | 731 | Debug_Emulated, |
| 748 | "Signalling debugger, Unknown break reason {}, info1=0x{:016X}, info2=0x{:016X}", | 732 | "Signalling debugger, Unknown break reason {:#X}, info1=0x{:016X}, info2=0x{:016X}", |
| 749 | static_cast<u32>(break_reason.break_type.Value()), info1, info2); | 733 | reason, info1, info2); |
| 750 | handle_debug_buffer(info1, info2); | 734 | handle_debug_buffer(info1, info2); |
| 751 | break; | 735 | break; |
| 752 | } | 736 | } |
| 753 | 737 | ||
| 754 | system.GetReporter().SaveSvcBreakReport( | 738 | system.GetReporter().SaveSvcBreakReport(reason, notification_only, info1, info2, |
| 755 | static_cast<u32>(break_reason.break_type.Value()), break_reason.signal_debugger.As<bool>(), | 739 | has_dumped_buffer ? std::make_optional(debug_buffer) |
| 756 | info1, info2, has_dumped_buffer ? std::make_optional(debug_buffer) : std::nullopt); | 740 | : std::nullopt); |
| 757 | 741 | ||
| 758 | if (!break_reason.signal_debugger) { | 742 | if (!notification_only) { |
| 759 | LOG_CRITICAL( | 743 | LOG_CRITICAL( |
| 760 | Debug_Emulated, | 744 | Debug_Emulated, |
| 761 | "Emulated program broke execution! reason=0x{:016X}, info1=0x{:016X}, info2=0x{:016X}", | 745 | "Emulated program broke execution! reason=0x{:016X}, info1=0x{:016X}, info2=0x{:016X}", |
| @@ -1716,13 +1700,13 @@ static Result QueryProcessMemory(Core::System& system, VAddr memory_info_address | |||
| 1716 | auto& memory{system.Memory()}; | 1700 | auto& memory{system.Memory()}; |
| 1717 | const auto memory_info{process->PageTable().QueryInfo(address).GetSvcMemoryInfo()}; | 1701 | const auto memory_info{process->PageTable().QueryInfo(address).GetSvcMemoryInfo()}; |
| 1718 | 1702 | ||
| 1719 | memory.Write64(memory_info_address + 0x00, memory_info.addr); | 1703 | memory.Write64(memory_info_address + 0x00, memory_info.base_address); |
| 1720 | memory.Write64(memory_info_address + 0x08, memory_info.size); | 1704 | memory.Write64(memory_info_address + 0x08, memory_info.size); |
| 1721 | memory.Write32(memory_info_address + 0x10, static_cast<u32>(memory_info.state) & 0xff); | 1705 | memory.Write32(memory_info_address + 0x10, static_cast<u32>(memory_info.state) & 0xff); |
| 1722 | memory.Write32(memory_info_address + 0x14, static_cast<u32>(memory_info.attr)); | 1706 | memory.Write32(memory_info_address + 0x14, static_cast<u32>(memory_info.attribute)); |
| 1723 | memory.Write32(memory_info_address + 0x18, static_cast<u32>(memory_info.perm)); | 1707 | memory.Write32(memory_info_address + 0x18, static_cast<u32>(memory_info.permission)); |
| 1724 | memory.Write32(memory_info_address + 0x1c, memory_info.ipc_refcount); | 1708 | memory.Write32(memory_info_address + 0x1c, memory_info.ipc_count); |
| 1725 | memory.Write32(memory_info_address + 0x20, memory_info.device_refcount); | 1709 | memory.Write32(memory_info_address + 0x20, memory_info.device_count); |
| 1726 | memory.Write32(memory_info_address + 0x24, 0); | 1710 | memory.Write32(memory_info_address + 0x24, 0); |
| 1727 | 1711 | ||
| 1728 | // Page info appears to be currently unused by the kernel and is always set to zero. | 1712 | // Page info appears to be currently unused by the kernel and is always set to zero. |
| @@ -1943,7 +1927,7 @@ static Result CreateThread(Core::System& system, Handle* out_handle, VAddr entry | |||
| 1943 | 1927 | ||
| 1944 | // Reserve a new thread from the process resource limit (waiting up to 100ms). | 1928 | // Reserve a new thread from the process resource limit (waiting up to 100ms). |
| 1945 | KScopedResourceReservation thread_reservation( | 1929 | KScopedResourceReservation thread_reservation( |
| 1946 | kernel.CurrentProcess(), LimitableResource::Threads, 1, | 1930 | kernel.CurrentProcess(), LimitableResource::ThreadCountMax, 1, |
| 1947 | system.CoreTiming().GetGlobalTimeNs().count() + 100000000); | 1931 | system.CoreTiming().GetGlobalTimeNs().count() + 100000000); |
| 1948 | if (!thread_reservation.Succeeded()) { | 1932 | if (!thread_reservation.Succeeded()) { |
| 1949 | LOG_ERROR(Kernel_SVC, "Could not reserve a new thread"); | 1933 | LOG_ERROR(Kernel_SVC, "Could not reserve a new thread"); |
| @@ -2344,7 +2328,7 @@ static Result CreateTransferMemory(Core::System& system, Handle* out, VAddr addr | |||
| 2344 | 2328 | ||
| 2345 | // Reserve a new transfer memory from the process resource limit. | 2329 | // Reserve a new transfer memory from the process resource limit. |
| 2346 | KScopedResourceReservation trmem_reservation(kernel.CurrentProcess(), | 2330 | KScopedResourceReservation trmem_reservation(kernel.CurrentProcess(), |
| 2347 | LimitableResource::TransferMemory); | 2331 | LimitableResource::TransferMemoryCountMax); |
| 2348 | R_UNLESS(trmem_reservation.Succeeded(), ResultLimitReached); | 2332 | R_UNLESS(trmem_reservation.Succeeded(), ResultLimitReached); |
| 2349 | 2333 | ||
| 2350 | // Create the transfer memory. | 2334 | // Create the transfer memory. |
| @@ -2496,7 +2480,7 @@ static Result CreateEvent(Core::System& system, Handle* out_write, Handle* out_r | |||
| 2496 | 2480 | ||
| 2497 | // Reserve a new event from the process resource limit | 2481 | // Reserve a new event from the process resource limit |
| 2498 | KScopedResourceReservation event_reservation(kernel.CurrentProcess(), | 2482 | KScopedResourceReservation event_reservation(kernel.CurrentProcess(), |
| 2499 | LimitableResource::Events); | 2483 | LimitableResource::EventCountMax); |
| 2500 | R_UNLESS(event_reservation.Succeeded(), ResultLimitReached); | 2484 | R_UNLESS(event_reservation.Succeeded(), ResultLimitReached); |
| 2501 | 2485 | ||
| 2502 | // Create a new event. | 2486 | // Create a new event. |
| @@ -2539,11 +2523,6 @@ static Result CreateEvent32(Core::System& system, Handle* out_write, Handle* out | |||
| 2539 | static Result GetProcessInfo(Core::System& system, u64* out, Handle process_handle, u32 type) { | 2523 | static Result GetProcessInfo(Core::System& system, u64* out, Handle process_handle, u32 type) { |
| 2540 | LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, type=0x{:X}", process_handle, type); | 2524 | LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, type=0x{:X}", process_handle, type); |
| 2541 | 2525 | ||
| 2542 | // This function currently only allows retrieving a process' status. | ||
| 2543 | enum class InfoType { | ||
| 2544 | Status, | ||
| 2545 | }; | ||
| 2546 | |||
| 2547 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 2526 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); |
| 2548 | KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle); | 2527 | KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle); |
| 2549 | if (process.IsNull()) { | 2528 | if (process.IsNull()) { |
| @@ -2552,9 +2531,9 @@ static Result GetProcessInfo(Core::System& system, u64* out, Handle process_hand | |||
| 2552 | return ResultInvalidHandle; | 2531 | return ResultInvalidHandle; |
| 2553 | } | 2532 | } |
| 2554 | 2533 | ||
| 2555 | const auto info_type = static_cast<InfoType>(type); | 2534 | const auto info_type = static_cast<ProcessInfoType>(type); |
| 2556 | if (info_type != InfoType::Status) { | 2535 | if (info_type != ProcessInfoType::ProcessState) { |
| 2557 | LOG_ERROR(Kernel_SVC, "Expected info_type to be Status but got {} instead", type); | 2536 | LOG_ERROR(Kernel_SVC, "Expected info_type to be ProcessState but got {} instead", type); |
| 2558 | return ResultInvalidEnumValue; | 2537 | return ResultInvalidEnumValue; |
| 2559 | } | 2538 | } |
| 2560 | 2539 | ||