diff options
Diffstat (limited to '')
-rw-r--r-- | src/core/hle/kernel/svc.cpp | 143 |
1 files changed, 66 insertions, 77 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index ecac97a52..e520cab47 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 // Reserve a new session from the process resource limit. // FIXME: LimitableResource_SessionCountMax - KScopedResourceReservation session_reservation(&process, LimitableResource::Sessions); + KScopedResourceReservation session_reservation(&process, LimitableResource::SessionCountMax); if (session_reservation.Succeeded()) { session = T::Create(system.Kernel()); } else { @@ -298,7 +298,7 @@ Result CreateSession(Core::System& system, Handle* out_server, Handle* out_clien // We successfully allocated a session, so add the object we allocated to the resource // limit. - // system.Kernel().GetSystemResourceLimit().Reserve(LimitableResource::Sessions, 1); + // system.Kernel().GetSystemResourceLimit().Reserve(LimitableResource::SessionCountMax, 1); } // Check that we successfully created a session. @@ -656,27 +656,12 @@ static Result ArbitrateUnlock32(Core::System& system, u32 address) { return ArbitrateUnlock(system, address); } -enum class BreakType : u32 { - Panic = 0, - AssertionFailed = 1, - PreNROLoad = 3, - PostNROLoad = 4, - PreNROUnload = 5, - PostNROUnload = 6, - CppException = 7, -}; - -struct BreakReason { - union { - u32 raw; - BitField<0, 30, BreakType> break_type; - BitField<31, 1, u32> signal_debugger; - }; -}; - /// Break program execution static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) { - BreakReason break_reason{reason}; + BreakReason break_reason = + static_cast<BreakReason>(reason & ~static_cast<u32>(BreakReason::NotificationOnlyFlag)); + bool notification_only = (reason & static_cast<u32>(BreakReason::NotificationOnlyFlag)) != 0; + bool has_dumped_buffer{}; std::vector<u8> debug_buffer; @@ -705,57 +690,56 @@ static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) { } has_dumped_buffer = true; }; - switch (break_reason.break_type) { - case BreakType::Panic: - LOG_CRITICAL(Debug_Emulated, "Signalling debugger, PANIC! info1=0x{:016X}, info2=0x{:016X}", - info1, info2); + switch (break_reason) { + case BreakReason::Panic: + LOG_CRITICAL(Debug_Emulated, "Userspace PANIC! info1=0x{:016X}, info2=0x{:016X}", info1, + info2); handle_debug_buffer(info1, info2); break; - case BreakType::AssertionFailed: - LOG_CRITICAL(Debug_Emulated, - "Signalling debugger, Assertion failed! info1=0x{:016X}, info2=0x{:016X}", + case BreakReason::Assert: + LOG_CRITICAL(Debug_Emulated, "Userspace Assertion failed! info1=0x{:016X}, info2=0x{:016X}", info1, info2); handle_debug_buffer(info1, info2); break; - case BreakType::PreNROLoad: - LOG_WARNING( - Debug_Emulated, - "Signalling debugger, Attempting to load an NRO at 0x{:016X} with size 0x{:016X}", - info1, info2); + case BreakReason::User: + LOG_WARNING(Debug_Emulated, "Userspace Break! 0x{:016X} with size 0x{:016X}", info1, info2); + handle_debug_buffer(info1, info2); break; - case BreakType::PostNROLoad: - LOG_WARNING(Debug_Emulated, - "Signalling debugger, Loaded an NRO at 0x{:016X} with size 0x{:016X}", info1, - info2); + case BreakReason::PreLoadDll: + LOG_INFO(Debug_Emulated, + "Userspace Attempting to load an NRO at 0x{:016X} with size 0x{:016X}", info1, + info2); break; - case BreakType::PreNROUnload: - LOG_WARNING( - Debug_Emulated, - "Signalling debugger, Attempting to unload an NRO at 0x{:016X} with size 0x{:016X}", - info1, info2); + case BreakReason::PostLoadDll: + LOG_INFO(Debug_Emulated, "Userspace Loaded an NRO at 0x{:016X} with size 0x{:016X}", info1, + info2); break; - case BreakType::PostNROUnload: - LOG_WARNING(Debug_Emulated, - "Signalling debugger, Unloaded an NRO at 0x{:016X} with size 0x{:016X}", info1, - info2); + case BreakReason::PreUnloadDll: + LOG_INFO(Debug_Emulated, + "Userspace Attempting to unload an NRO at 0x{:016X} with size 0x{:016X}", info1, + info2); break; - case BreakType::CppException: + case BreakReason::PostUnloadDll: + LOG_INFO(Debug_Emulated, "Userspace Unloaded an NRO at 0x{:016X} with size 0x{:016X}", + info1, info2); + break; + case BreakReason::CppException: LOG_CRITICAL(Debug_Emulated, "Signalling debugger. Uncaught C++ exception encountered."); break; default: LOG_WARNING( Debug_Emulated, - "Signalling debugger, Unknown break reason {}, info1=0x{:016X}, info2=0x{:016X}", - static_cast<u32>(break_reason.break_type.Value()), info1, info2); + "Signalling debugger, Unknown break reason {:#X}, info1=0x{:016X}, info2=0x{:016X}", + reason, info1, info2); handle_debug_buffer(info1, info2); break; } - system.GetReporter().SaveSvcBreakReport( - static_cast<u32>(break_reason.break_type.Value()), break_reason.signal_debugger.As<bool>(), - info1, info2, has_dumped_buffer ? std::make_optional(debug_buffer) : std::nullopt); + system.GetReporter().SaveSvcBreakReport(reason, notification_only, info1, info2, + has_dumped_buffer ? std::make_optional(debug_buffer) + : std::nullopt); - if (!break_reason.signal_debugger) { + if (!notification_only) { LOG_CRITICAL( Debug_Emulated, "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 auto& memory{system.Memory()}; const auto memory_info{process->PageTable().QueryInfo(address).GetSvcMemoryInfo()}; - memory.Write64(memory_info_address + 0x00, memory_info.addr); + memory.Write64(memory_info_address + 0x00, memory_info.base_address); memory.Write64(memory_info_address + 0x08, memory_info.size); memory.Write32(memory_info_address + 0x10, static_cast<u32>(memory_info.state) & 0xff); - memory.Write32(memory_info_address + 0x14, static_cast<u32>(memory_info.attr)); - memory.Write32(memory_info_address + 0x18, static_cast<u32>(memory_info.perm)); - memory.Write32(memory_info_address + 0x1c, memory_info.ipc_refcount); - memory.Write32(memory_info_address + 0x20, memory_info.device_refcount); + memory.Write32(memory_info_address + 0x14, static_cast<u32>(memory_info.attribute)); + memory.Write32(memory_info_address + 0x18, static_cast<u32>(memory_info.permission)); + memory.Write32(memory_info_address + 0x1c, memory_info.ipc_count); + memory.Write32(memory_info_address + 0x20, memory_info.device_count); memory.Write32(memory_info_address + 0x24, 0); // 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 // Reserve a new thread from the process resource limit (waiting up to 100ms). KScopedResourceReservation thread_reservation( - kernel.CurrentProcess(), LimitableResource::Threads, 1, + kernel.CurrentProcess(), LimitableResource::ThreadCountMax, 1, system.CoreTiming().GetGlobalTimeNs().count() + 100000000); if (!thread_reservation.Succeeded()) { LOG_ERROR(Kernel_SVC, "Could not reserve a new thread"); @@ -2344,7 +2328,7 @@ static Result CreateTransferMemory(Core::System& system, Handle* out, VAddr addr // Reserve a new transfer memory from the process resource limit. KScopedResourceReservation trmem_reservation(kernel.CurrentProcess(), - LimitableResource::TransferMemory); + LimitableResource::TransferMemoryCountMax); R_UNLESS(trmem_reservation.Succeeded(), ResultLimitReached); // Create the transfer memory. @@ -2496,7 +2480,7 @@ static Result CreateEvent(Core::System& system, Handle* out_write, Handle* out_r // Reserve a new event from the process resource limit KScopedResourceReservation event_reservation(kernel.CurrentProcess(), - LimitableResource::Events); + LimitableResource::EventCountMax); R_UNLESS(event_reservation.Succeeded(), ResultLimitReached); // Create a new event. @@ -2539,11 +2523,6 @@ static Result CreateEvent32(Core::System& system, Handle* out_write, Handle* out static Result GetProcessInfo(Core::System& system, u64* out, Handle process_handle, u32 type) { LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, type=0x{:X}", process_handle, type); - // This function currently only allows retrieving a process' status. - enum class InfoType { - Status, - }; - const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle); if (process.IsNull()) { @@ -2552,9 +2531,9 @@ static Result GetProcessInfo(Core::System& system, u64* out, Handle process_hand return ResultInvalidHandle; } - const auto info_type = static_cast<InfoType>(type); - if (info_type != InfoType::Status) { - LOG_ERROR(Kernel_SVC, "Expected info_type to be Status but got {} instead", type); + const auto info_type = static_cast<ProcessInfoType>(type); + if (info_type != ProcessInfoType::ProcessState) { + LOG_ERROR(Kernel_SVC, "Expected info_type to be ProcessState but got {} instead", type); return ResultInvalidEnumValue; } @@ -2722,14 +2701,24 @@ static Result GetThreadList(Core::System& system, u32* out_num_threads, VAddr ou return ResultSuccess; } -static Result FlushProcessDataCache32([[maybe_unused]] Core::System& system, - [[maybe_unused]] Handle handle, [[maybe_unused]] u32 address, - [[maybe_unused]] u32 size) { - // Note(Blinkhawk): For emulation purposes of the data cache this is mostly a no-op, - // as all emulation is done in the same cache level in host architecture, thus data cache - // does not need flushing. - LOG_DEBUG(Kernel_SVC, "called"); - return ResultSuccess; +static Result FlushProcessDataCache32(Core::System& system, Handle process_handle, u64 address, + u64 size) { + // Validate address/size. + R_UNLESS(size > 0, ResultInvalidSize); + R_UNLESS(address == static_cast<uintptr_t>(address), ResultInvalidCurrentMemory); + R_UNLESS(size == static_cast<size_t>(size), ResultInvalidCurrentMemory); + + // Get the process from its handle. + KScopedAutoObject process = + system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KProcess>(process_handle); + R_UNLESS(process.IsNotNull(), ResultInvalidHandle); + + // Verify the region is within range. + auto& page_table = process->PageTable(); + R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory); + + // Perform the operation. + R_RETURN(system.Memory().FlushDataCache(*process, address, size)); } namespace { |