diff --git a/Ryujinx.HLE/HOS/GlobalStateTable.cs b/Ryujinx.HLE/HOS/GlobalStateTable.cs index a350dee236..5e5e5ecfa9 100644 --- a/Ryujinx.HLE/HOS/GlobalStateTable.cs +++ b/Ryujinx.HLE/HOS/GlobalStateTable.cs @@ -1,4 +1,4 @@ -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Process; using System.Collections.Concurrent; using System.Collections.Generic; diff --git a/Ryujinx.HLE/HOS/Horizon.cs b/Ryujinx.HLE/HOS/Horizon.cs index a5ea535471..5c2ca9b3af 100644 --- a/Ryujinx.HLE/HOS/Horizon.cs +++ b/Ryujinx.HLE/HOS/Horizon.cs @@ -2,7 +2,10 @@ using LibHac; using Ryujinx.Common.Logging; using Ryujinx.HLE.FileSystem.Content; using Ryujinx.HLE.HOS.Font; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Memory; +using Ryujinx.HLE.HOS.Kernel.Process; +using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.SystemState; using Ryujinx.HLE.Loaders.Executables; using Ryujinx.HLE.Loaders.Npdm; diff --git a/Ryujinx.HLE/HOS/Ipc/IpcHandler.cs b/Ryujinx.HLE/HOS/Ipc/IpcHandler.cs index e5d19236bb..ecfa25ed02 100644 --- a/Ryujinx.HLE/HOS/Ipc/IpcHandler.cs +++ b/Ryujinx.HLE/HOS/Ipc/IpcHandler.cs @@ -1,5 +1,7 @@ using ChocolArm64.Memory; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Ipc; +using Ryujinx.HLE.HOS.Kernel.Process; using System; using System.IO; @@ -7,7 +9,7 @@ namespace Ryujinx.HLE.HOS.Ipc { static class IpcHandler { - public static long IpcCall( + public static KernelResult IpcCall( Switch device, KProcess process, MemoryManager memory, @@ -100,7 +102,7 @@ namespace Ryujinx.HLE.HOS.Ipc memory.WriteBytes(cmdPtr, response.GetBytes(cmdPtr)); } - return 0; + return KernelResult.Success; } private static IpcMessage FillResponse(IpcMessage response, long result, params int[] values) diff --git a/Ryujinx.HLE/HOS/Kernel/IKFutureSchedulerObject.cs b/Ryujinx.HLE/HOS/Kernel/Common/IKFutureSchedulerObject.cs similarity index 65% rename from Ryujinx.HLE/HOS/Kernel/IKFutureSchedulerObject.cs rename to Ryujinx.HLE/HOS/Kernel/Common/IKFutureSchedulerObject.cs index 6a255e6552..473683ff72 100644 --- a/Ryujinx.HLE/HOS/Kernel/IKFutureSchedulerObject.cs +++ b/Ryujinx.HLE/HOS/Kernel/Common/IKFutureSchedulerObject.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Common { interface IKFutureSchedulerObject { diff --git a/Ryujinx.HLE/HOS/Kernel/KAutoObject.cs b/Ryujinx.HLE/HOS/Kernel/Common/KAutoObject.cs similarity index 95% rename from Ryujinx.HLE/HOS/Kernel/KAutoObject.cs rename to Ryujinx.HLE/HOS/Kernel/Common/KAutoObject.cs index f49beaac94..ddb0c71f7b 100644 --- a/Ryujinx.HLE/HOS/Kernel/KAutoObject.cs +++ b/Ryujinx.HLE/HOS/Kernel/Common/KAutoObject.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Common { class KAutoObject { diff --git a/Ryujinx.HLE/HOS/Kernel/KResourceLimit.cs b/Ryujinx.HLE/HOS/Kernel/Common/KResourceLimit.cs similarity index 98% rename from Ryujinx.HLE/HOS/Kernel/KResourceLimit.cs rename to Ryujinx.HLE/HOS/Kernel/Common/KResourceLimit.cs index 09c53e5b09..01bba65f79 100644 --- a/Ryujinx.HLE/HOS/Kernel/KResourceLimit.cs +++ b/Ryujinx.HLE/HOS/Kernel/Common/KResourceLimit.cs @@ -1,7 +1,8 @@ using Ryujinx.Common; +using Ryujinx.HLE.HOS.Kernel.Threading; using System.Collections.Generic; -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Common { class KResourceLimit { diff --git a/Ryujinx.HLE/HOS/Kernel/KSynchronizationObject.cs b/Ryujinx.HLE/HOS/Kernel/Common/KSynchronizationObject.cs similarity index 90% rename from Ryujinx.HLE/HOS/Kernel/KSynchronizationObject.cs rename to Ryujinx.HLE/HOS/Kernel/Common/KSynchronizationObject.cs index 79f0673ff3..87e5531210 100644 --- a/Ryujinx.HLE/HOS/Kernel/KSynchronizationObject.cs +++ b/Ryujinx.HLE/HOS/Kernel/Common/KSynchronizationObject.cs @@ -1,6 +1,7 @@ +using Ryujinx.HLE.HOS.Kernel.Threading; using System.Collections.Generic; -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Common { class KSynchronizationObject : KAutoObject { diff --git a/Ryujinx.HLE/HOS/Kernel/KTimeManager.cs b/Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs similarity index 98% rename from Ryujinx.HLE/HOS/Kernel/KTimeManager.cs rename to Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs index 0c2551a393..f6a9e6f9d1 100644 --- a/Ryujinx.HLE/HOS/Kernel/KTimeManager.cs +++ b/Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Common { class KTimeManager : IDisposable { diff --git a/Ryujinx.HLE/HOS/Kernel/KernelInit.cs b/Ryujinx.HLE/HOS/Kernel/Common/KernelInit.cs similarity index 98% rename from Ryujinx.HLE/HOS/Kernel/KernelInit.cs rename to Ryujinx.HLE/HOS/Kernel/Common/KernelInit.cs index a797951b0b..2a2aa74369 100644 --- a/Ryujinx.HLE/HOS/Kernel/KernelInit.cs +++ b/Ryujinx.HLE/HOS/Kernel/Common/KernelInit.cs @@ -1,6 +1,7 @@ +using Ryujinx.HLE.HOS.Kernel.Memory; using System; -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Common { static class KernelInit { diff --git a/Ryujinx.HLE/HOS/Kernel/KernelResult.cs b/Ryujinx.HLE/HOS/Kernel/Common/KernelResult.cs similarity index 92% rename from Ryujinx.HLE/HOS/Kernel/KernelResult.cs rename to Ryujinx.HLE/HOS/Kernel/Common/KernelResult.cs index 9870d17549..cea24693f6 100644 --- a/Ryujinx.HLE/HOS/Kernel/KernelResult.cs +++ b/Ryujinx.HLE/HOS/Kernel/Common/KernelResult.cs @@ -1,9 +1,10 @@ -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Common { enum KernelResult { Success = 0, InvalidCapability = 0x1c01, + ThreadNotStarted = 0x7201, ThreadTerminating = 0x7601, InvalidSize = 0xca01, InvalidAddress = 0xcc01, diff --git a/Ryujinx.HLE/HOS/Kernel/Common/KernelTransfer.cs b/Ryujinx.HLE/HOS/Kernel/Common/KernelTransfer.cs new file mode 100644 index 0000000000..a29b1722cc --- /dev/null +++ b/Ryujinx.HLE/HOS/Kernel/Common/KernelTransfer.cs @@ -0,0 +1,72 @@ +using Ryujinx.HLE.HOS.Kernel.Process; +using ChocolArm64.Memory; + +namespace Ryujinx.HLE.HOS.Kernel.Common +{ + static class KernelTransfer + { + public static bool UserToKernelInt32(Horizon system, ulong address, out int value) + { + KProcess currentProcess = system.Scheduler.GetCurrentProcess(); + + if (currentProcess.CpuMemory.IsMapped((long)address) && + currentProcess.CpuMemory.IsMapped((long)address + 3)) + { + value = currentProcess.CpuMemory.ReadInt32((long)address); + + return true; + } + + value = 0; + + return false; + } + + public static bool UserToKernelString(Horizon system, ulong address, int size, out string value) + { + KProcess currentProcess = system.Scheduler.GetCurrentProcess(); + + if (currentProcess.CpuMemory.IsMapped((long)address) && + currentProcess.CpuMemory.IsMapped((long)address + size - 1)) + { + value = MemoryHelper.ReadAsciiString(currentProcess.CpuMemory, (long)address, size); + + return true; + } + + value = null; + + return false; + } + + public static bool KernelToUserInt32(Horizon system, ulong address, int value) + { + KProcess currentProcess = system.Scheduler.GetCurrentProcess(); + + if (currentProcess.CpuMemory.IsMapped((long)address) && + currentProcess.CpuMemory.IsMapped((long)address + 3)) + { + currentProcess.CpuMemory.WriteInt32ToSharedAddr((long)address, value); + + return true; + } + + return false; + } + + public static bool KernelToUserInt64(Horizon system, ulong address, long value) + { + KProcess currentProcess = system.Scheduler.GetCurrentProcess(); + + if (currentProcess.CpuMemory.IsMapped((long)address) && + currentProcess.CpuMemory.IsMapped((long)address + 7)) + { + currentProcess.CpuMemory.WriteInt64((long)address, value); + + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/LimitableResource.cs b/Ryujinx.HLE/HOS/Kernel/Common/LimitableResource.cs similarity index 83% rename from Ryujinx.HLE/HOS/Kernel/LimitableResource.cs rename to Ryujinx.HLE/HOS/Kernel/Common/LimitableResource.cs index baab422238..2e6a3e4552 100644 --- a/Ryujinx.HLE/HOS/Kernel/LimitableResource.cs +++ b/Ryujinx.HLE/HOS/Kernel/Common/LimitableResource.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Common { enum LimitableResource : byte { diff --git a/Ryujinx.HLE/HOS/Kernel/MersenneTwister.cs b/Ryujinx.HLE/HOS/Kernel/Common/MersenneTwister.cs similarity index 98% rename from Ryujinx.HLE/HOS/Kernel/MersenneTwister.cs rename to Ryujinx.HLE/HOS/Kernel/Common/MersenneTwister.cs index 5307bdc9fb..6b68690193 100644 --- a/Ryujinx.HLE/HOS/Kernel/MersenneTwister.cs +++ b/Ryujinx.HLE/HOS/Kernel/Common/MersenneTwister.cs @@ -1,6 +1,6 @@ using Ryujinx.Common; -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Common { class MersenneTwister { diff --git a/Ryujinx.HLE/HOS/Kernel/KClientPort.cs b/Ryujinx.HLE/HOS/Kernel/Ipc/KClientPort.cs similarity index 91% rename from Ryujinx.HLE/HOS/Kernel/KClientPort.cs rename to Ryujinx.HLE/HOS/Kernel/Ipc/KClientPort.cs index 5754762770..ddfe20960d 100644 --- a/Ryujinx.HLE/HOS/Kernel/KClientPort.cs +++ b/Ryujinx.HLE/HOS/Kernel/Ipc/KClientPort.cs @@ -1,4 +1,6 @@ -namespace Ryujinx.HLE.HOS.Kernel +using Ryujinx.HLE.HOS.Kernel.Common; + +namespace Ryujinx.HLE.HOS.Kernel.Ipc { class KClientPort : KSynchronizationObject { diff --git a/Ryujinx.HLE/HOS/Kernel/KPort.cs b/Ryujinx.HLE/HOS/Kernel/Ipc/KPort.cs similarity index 90% rename from Ryujinx.HLE/HOS/Kernel/KPort.cs rename to Ryujinx.HLE/HOS/Kernel/Ipc/KPort.cs index a6c5b375f1..16e9a1119a 100644 --- a/Ryujinx.HLE/HOS/Kernel/KPort.cs +++ b/Ryujinx.HLE/HOS/Kernel/Ipc/KPort.cs @@ -1,4 +1,6 @@ -namespace Ryujinx.HLE.HOS.Kernel +using Ryujinx.HLE.HOS.Kernel.Common; + +namespace Ryujinx.HLE.HOS.Kernel.Ipc { class KPort : KAutoObject { diff --git a/Ryujinx.HLE/HOS/Kernel/KServerPort.cs b/Ryujinx.HLE/HOS/Kernel/Ipc/KServerPort.cs similarity index 77% rename from Ryujinx.HLE/HOS/Kernel/KServerPort.cs rename to Ryujinx.HLE/HOS/Kernel/Ipc/KServerPort.cs index 0aa74e487b..d4d3bcd29a 100644 --- a/Ryujinx.HLE/HOS/Kernel/KServerPort.cs +++ b/Ryujinx.HLE/HOS/Kernel/Ipc/KServerPort.cs @@ -1,4 +1,6 @@ -namespace Ryujinx.HLE.HOS.Kernel +using Ryujinx.HLE.HOS.Kernel.Common; + +namespace Ryujinx.HLE.HOS.Kernel.Ipc { class KServerPort : KSynchronizationObject { diff --git a/Ryujinx.HLE/HOS/Kernel/KSession.cs b/Ryujinx.HLE/HOS/Kernel/Ipc/KSession.cs similarity index 94% rename from Ryujinx.HLE/HOS/Kernel/KSession.cs rename to Ryujinx.HLE/HOS/Kernel/Ipc/KSession.cs index 361a7479f4..f2b3049339 100644 --- a/Ryujinx.HLE/HOS/Kernel/KSession.cs +++ b/Ryujinx.HLE/HOS/Kernel/Ipc/KSession.cs @@ -1,7 +1,7 @@ using Ryujinx.HLE.HOS.Services; using System; -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Ipc { class KSession : IDisposable { diff --git a/Ryujinx.HLE/HOS/Kernel/KernelErr.cs b/Ryujinx.HLE/HOS/Kernel/KernelErr.cs deleted file mode 100644 index e0b196f412..0000000000 --- a/Ryujinx.HLE/HOS/Kernel/KernelErr.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Ryujinx.HLE.HOS.Kernel -{ - static class KernelErr - { - public const int ThreadTerminating = 59; - public const int InvalidSize = 101; - public const int InvalidAddress = 102; - public const int OutOfMemory = 104; - public const int HandleTableFull = 105; - public const int NoAccessPerm = 106; - public const int InvalidPermission = 108; - public const int InvalidMemRange = 110; - public const int InvalidPriority = 112; - public const int InvalidCoreId = 113; - public const int InvalidHandle = 114; - public const int InvalidMaskValue = 116; - public const int Timeout = 117; - public const int Cancelled = 118; - public const int CountOutOfRange = 119; - public const int InvalidEnumValue = 120; - public const int InvalidThread = 122; - public const int InvalidState = 125; - } -} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/KernelTransfer.cs b/Ryujinx.HLE/HOS/Kernel/KernelTransfer.cs deleted file mode 100644 index c0ce72c0cb..0000000000 --- a/Ryujinx.HLE/HOS/Kernel/KernelTransfer.cs +++ /dev/null @@ -1,71 +0,0 @@ -using ChocolArm64.Memory; - -namespace Ryujinx.HLE.HOS.Kernel -{ - static class KernelTransfer - { - public static bool UserToKernelInt32(Horizon system, long address, out int value) - { - KProcess currentProcess = system.Scheduler.GetCurrentProcess(); - - if (currentProcess.CpuMemory.IsMapped(address) && - currentProcess.CpuMemory.IsMapped(address + 3)) - { - value = currentProcess.CpuMemory.ReadInt32(address); - - return true; - } - - value = 0; - - return false; - } - - public static bool UserToKernelString(Horizon system, long address, int size, out string value) - { - KProcess currentProcess = system.Scheduler.GetCurrentProcess(); - - if (currentProcess.CpuMemory.IsMapped(address) && - currentProcess.CpuMemory.IsMapped(address + size - 1)) - { - value = MemoryHelper.ReadAsciiString(currentProcess.CpuMemory, address, size); - - return true; - } - - value = null; - - return false; - } - - public static bool KernelToUserInt32(Horizon system, long address, int value) - { - KProcess currentProcess = system.Scheduler.GetCurrentProcess(); - - if (currentProcess.CpuMemory.IsMapped(address) && - currentProcess.CpuMemory.IsMapped(address + 3)) - { - currentProcess.CpuMemory.WriteInt32ToSharedAddr(address, value); - - return true; - } - - return false; - } - - public static bool KernelToUserInt64(Horizon system, long address, long value) - { - KProcess currentProcess = system.Scheduler.GetCurrentProcess(); - - if (currentProcess.CpuMemory.IsMapped(address) && - currentProcess.CpuMemory.IsMapped(address + 7)) - { - currentProcess.CpuMemory.WriteInt64(address, value); - - return true; - } - - return false; - } - } -} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/AddressSpaceType.cs b/Ryujinx.HLE/HOS/Kernel/Memory/AddressSpaceType.cs similarity index 79% rename from Ryujinx.HLE/HOS/Kernel/AddressSpaceType.cs rename to Ryujinx.HLE/HOS/Kernel/Memory/AddressSpaceType.cs index 6f7b230e70..8395c5777a 100644 --- a/Ryujinx.HLE/HOS/Kernel/AddressSpaceType.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/AddressSpaceType.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Memory { enum AddressSpaceType { diff --git a/Ryujinx.HLE/HOS/Kernel/DramMemoryMap.cs b/Ryujinx.HLE/HOS/Kernel/Memory/DramMemoryMap.cs similarity index 92% rename from Ryujinx.HLE/HOS/Kernel/DramMemoryMap.cs rename to Ryujinx.HLE/HOS/Kernel/Memory/DramMemoryMap.cs index b20a83e2a9..261c2972b3 100644 --- a/Ryujinx.HLE/HOS/Kernel/DramMemoryMap.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/DramMemoryMap.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Memory { static class DramMemoryMap { diff --git a/Ryujinx.HLE/HOS/Kernel/KMemoryArrange.cs b/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryArrange.cs similarity index 94% rename from Ryujinx.HLE/HOS/Kernel/KMemoryArrange.cs rename to Ryujinx.HLE/HOS/Kernel/Memory/KMemoryArrange.cs index de8bf3b1fa..7dfc2b7780 100644 --- a/Ryujinx.HLE/HOS/Kernel/KMemoryArrange.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryArrange.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Memory { class KMemoryArrange { diff --git a/Ryujinx.HLE/HOS/Kernel/KMemoryArrangeRegion.cs b/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryArrangeRegion.cs similarity index 89% rename from Ryujinx.HLE/HOS/Kernel/KMemoryArrangeRegion.cs rename to Ryujinx.HLE/HOS/Kernel/Memory/KMemoryArrangeRegion.cs index 4fe58d730a..eaf0fe5fb8 100644 --- a/Ryujinx.HLE/HOS/Kernel/KMemoryArrangeRegion.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryArrangeRegion.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Memory { struct KMemoryArrangeRegion { diff --git a/Ryujinx.HLE/HOS/Kernel/KMemoryBlock.cs b/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryBlock.cs similarity index 96% rename from Ryujinx.HLE/HOS/Kernel/KMemoryBlock.cs rename to Ryujinx.HLE/HOS/Kernel/Memory/KMemoryBlock.cs index 44b7a68341..89a194980a 100644 --- a/Ryujinx.HLE/HOS/Kernel/KMemoryBlock.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryBlock.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Memory { class KMemoryBlock { diff --git a/Ryujinx.HLE/HOS/Kernel/KMemoryBlockAllocator.cs b/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryBlockAllocator.cs similarity index 90% rename from Ryujinx.HLE/HOS/Kernel/KMemoryBlockAllocator.cs rename to Ryujinx.HLE/HOS/Kernel/Memory/KMemoryBlockAllocator.cs index 375685e678..ae68bf3912 100644 --- a/Ryujinx.HLE/HOS/Kernel/KMemoryBlockAllocator.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryBlockAllocator.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Memory { class KMemoryBlockAllocator { diff --git a/Ryujinx.HLE/HOS/Kernel/KMemoryInfo.cs b/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryInfo.cs similarity index 96% rename from Ryujinx.HLE/HOS/Kernel/KMemoryInfo.cs rename to Ryujinx.HLE/HOS/Kernel/Memory/KMemoryInfo.cs index 0372e0d382..226ce77c52 100644 --- a/Ryujinx.HLE/HOS/Kernel/KMemoryInfo.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryInfo.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Memory { class KMemoryInfo { diff --git a/Ryujinx.HLE/HOS/Kernel/KMemoryManager.cs b/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryManager.cs similarity index 99% rename from Ryujinx.HLE/HOS/Kernel/KMemoryManager.cs rename to Ryujinx.HLE/HOS/Kernel/Memory/KMemoryManager.cs index 831844c72e..fb5dec0433 100644 --- a/Ryujinx.HLE/HOS/Kernel/KMemoryManager.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryManager.cs @@ -1,9 +1,11 @@ using ChocolArm64.Memory; using Ryujinx.Common; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Process; using System; using System.Collections.Generic; -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Memory { class KMemoryManager { diff --git a/Ryujinx.HLE/HOS/Kernel/KMemoryRegionBlock.cs b/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryRegionBlock.cs similarity index 96% rename from Ryujinx.HLE/HOS/Kernel/KMemoryRegionBlock.cs rename to Ryujinx.HLE/HOS/Kernel/Memory/KMemoryRegionBlock.cs index f7e85e9a53..3334ff439a 100644 --- a/Ryujinx.HLE/HOS/Kernel/KMemoryRegionBlock.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryRegionBlock.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Memory { class KMemoryRegionBlock { diff --git a/Ryujinx.HLE/HOS/Kernel/KMemoryRegionManager.cs b/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryRegionManager.cs similarity index 99% rename from Ryujinx.HLE/HOS/Kernel/KMemoryRegionManager.cs rename to Ryujinx.HLE/HOS/Kernel/Memory/KMemoryRegionManager.cs index b9265b13c6..777e9aa941 100644 --- a/Ryujinx.HLE/HOS/Kernel/KMemoryRegionManager.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryRegionManager.cs @@ -1,6 +1,7 @@ using Ryujinx.Common; +using Ryujinx.HLE.HOS.Kernel.Common; -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Memory { class KMemoryRegionManager { diff --git a/Ryujinx.HLE/HOS/Kernel/KPageList.cs b/Ryujinx.HLE/HOS/Kernel/Memory/KPageList.cs similarity index 96% rename from Ryujinx.HLE/HOS/Kernel/KPageList.cs rename to Ryujinx.HLE/HOS/Kernel/Memory/KPageList.cs index b24d126f50..f0935dcc1c 100644 --- a/Ryujinx.HLE/HOS/Kernel/KPageList.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/KPageList.cs @@ -1,7 +1,8 @@ +using Ryujinx.HLE.HOS.Kernel.Common; using System.Collections; using System.Collections.Generic; -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Memory { class KPageList : IEnumerable { diff --git a/Ryujinx.HLE/HOS/Kernel/KPageNode.cs b/Ryujinx.HLE/HOS/Kernel/Memory/KPageNode.cs similarity index 86% rename from Ryujinx.HLE/HOS/Kernel/KPageNode.cs rename to Ryujinx.HLE/HOS/Kernel/Memory/KPageNode.cs index 5cdb1c4934..ada41687ea 100644 --- a/Ryujinx.HLE/HOS/Kernel/KPageNode.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/KPageNode.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Memory { struct KPageNode { diff --git a/Ryujinx.HLE/HOS/Kernel/KSharedMemory.cs b/Ryujinx.HLE/HOS/Kernel/Memory/KSharedMemory.cs similarity index 94% rename from Ryujinx.HLE/HOS/Kernel/KSharedMemory.cs rename to Ryujinx.HLE/HOS/Kernel/Memory/KSharedMemory.cs index 0e9f8840e5..f2a05bda0b 100644 --- a/Ryujinx.HLE/HOS/Kernel/KSharedMemory.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/KSharedMemory.cs @@ -1,6 +1,8 @@ using Ryujinx.Common; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Process; -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Memory { class KSharedMemory { diff --git a/Ryujinx.HLE/HOS/Kernel/KSlabHeap.cs b/Ryujinx.HLE/HOS/Kernel/Memory/KSlabHeap.cs similarity index 96% rename from Ryujinx.HLE/HOS/Kernel/KSlabHeap.cs rename to Ryujinx.HLE/HOS/Kernel/Memory/KSlabHeap.cs index 84c4dc0172..9051e84cc2 100644 --- a/Ryujinx.HLE/HOS/Kernel/KSlabHeap.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/KSlabHeap.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Memory { class KSlabHeap { diff --git a/Ryujinx.HLE/HOS/Kernel/KTransferMemory.cs b/Ryujinx.HLE/HOS/Kernel/Memory/KTransferMemory.cs similarity index 87% rename from Ryujinx.HLE/HOS/Kernel/KTransferMemory.cs rename to Ryujinx.HLE/HOS/Kernel/Memory/KTransferMemory.cs index d883785184..02367e896f 100644 --- a/Ryujinx.HLE/HOS/Kernel/KTransferMemory.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/KTransferMemory.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Memory { class KTransferMemory { diff --git a/Ryujinx.HLE/HOS/Kernel/MemoryAttribute.cs b/Ryujinx.HLE/HOS/Kernel/Memory/MemoryAttribute.cs similarity index 91% rename from Ryujinx.HLE/HOS/Kernel/MemoryAttribute.cs rename to Ryujinx.HLE/HOS/Kernel/Memory/MemoryAttribute.cs index 8f3197cb0c..42407ffe2a 100644 --- a/Ryujinx.HLE/HOS/Kernel/MemoryAttribute.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/MemoryAttribute.cs @@ -1,6 +1,6 @@ using System; -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Memory { [Flags] enum MemoryAttribute : byte diff --git a/Ryujinx.HLE/HOS/Kernel/MemoryOperation.cs b/Ryujinx.HLE/HOS/Kernel/Memory/MemoryOperation.cs similarity index 79% rename from Ryujinx.HLE/HOS/Kernel/MemoryOperation.cs rename to Ryujinx.HLE/HOS/Kernel/Memory/MemoryOperation.cs index b93501210d..7f7f29deed 100644 --- a/Ryujinx.HLE/HOS/Kernel/MemoryOperation.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/MemoryOperation.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Memory { enum MemoryOperation { diff --git a/Ryujinx.HLE/HOS/Kernel/MemoryPermission.cs b/Ryujinx.HLE/HOS/Kernel/Memory/MemoryPermission.cs similarity index 87% rename from Ryujinx.HLE/HOS/Kernel/MemoryPermission.cs rename to Ryujinx.HLE/HOS/Kernel/Memory/MemoryPermission.cs index 63539c2eba..0ad90abd7c 100644 --- a/Ryujinx.HLE/HOS/Kernel/MemoryPermission.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/MemoryPermission.cs @@ -1,6 +1,6 @@ using System; -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Memory { [Flags] enum MemoryPermission : byte diff --git a/Ryujinx.HLE/HOS/Kernel/MemoryRegion.cs b/Ryujinx.HLE/HOS/Kernel/Memory/MemoryRegion.cs similarity index 77% rename from Ryujinx.HLE/HOS/Kernel/MemoryRegion.cs rename to Ryujinx.HLE/HOS/Kernel/Memory/MemoryRegion.cs index ea4f33c9ce..ad719bdedc 100644 --- a/Ryujinx.HLE/HOS/Kernel/MemoryRegion.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/MemoryRegion.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Memory { enum MemoryRegion { diff --git a/Ryujinx.HLE/HOS/Kernel/MemoryState.cs b/Ryujinx.HLE/HOS/Kernel/Memory/MemoryState.cs similarity index 97% rename from Ryujinx.HLE/HOS/Kernel/MemoryState.cs rename to Ryujinx.HLE/HOS/Kernel/Memory/MemoryState.cs index e2ce27ef2f..f7161a88c3 100644 --- a/Ryujinx.HLE/HOS/Kernel/MemoryState.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/MemoryState.cs @@ -1,6 +1,6 @@ using System; -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Memory { [Flags] enum MemoryState : uint diff --git a/Ryujinx.HLE/HOS/Kernel/HleProcessDebugger.cs b/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs similarity index 99% rename from Ryujinx.HLE/HOS/Kernel/HleProcessDebugger.cs rename to Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs index fd3ac1f5a2..30fa4a5f4c 100644 --- a/Ryujinx.HLE/HOS/Kernel/HleProcessDebugger.cs +++ b/Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs @@ -2,13 +2,14 @@ using ChocolArm64.Memory; using ChocolArm64.State; using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Diagnostics.Demangler; +using Ryujinx.HLE.HOS.Kernel.Memory; using Ryujinx.HLE.Loaders.Elf; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Process { class HleProcessDebugger { diff --git a/Ryujinx.HLE/HOS/Kernel/KContextIdManager.cs b/Ryujinx.HLE/HOS/Kernel/Process/KContextIdManager.cs similarity index 98% rename from Ryujinx.HLE/HOS/Kernel/KContextIdManager.cs rename to Ryujinx.HLE/HOS/Kernel/Process/KContextIdManager.cs index 80a1c1c711..0392b9304b 100644 --- a/Ryujinx.HLE/HOS/Kernel/KContextIdManager.cs +++ b/Ryujinx.HLE/HOS/Kernel/Process/KContextIdManager.cs @@ -1,7 +1,7 @@ using Ryujinx.Common; using System; -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Process { class KContextIdManager { diff --git a/Ryujinx.HLE/HOS/Kernel/KHandleEntry.cs b/Ryujinx.HLE/HOS/Kernel/Process/KHandleEntry.cs similarity index 88% rename from Ryujinx.HLE/HOS/Kernel/KHandleEntry.cs rename to Ryujinx.HLE/HOS/Kernel/Process/KHandleEntry.cs index 42e5932954..87137d0fc1 100644 --- a/Ryujinx.HLE/HOS/Kernel/KHandleEntry.cs +++ b/Ryujinx.HLE/HOS/Kernel/Process/KHandleEntry.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Process { class KHandleEntry { diff --git a/Ryujinx.HLE/HOS/Kernel/KHandleTable.cs b/Ryujinx.HLE/HOS/Kernel/Process/KHandleTable.cs similarity index 97% rename from Ryujinx.HLE/HOS/Kernel/KHandleTable.cs rename to Ryujinx.HLE/HOS/Kernel/Process/KHandleTable.cs index 88d0c51362..413edf94b9 100644 --- a/Ryujinx.HLE/HOS/Kernel/KHandleTable.cs +++ b/Ryujinx.HLE/HOS/Kernel/Process/KHandleTable.cs @@ -1,6 +1,8 @@ +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Threading; using System; -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Process { class KHandleTable { diff --git a/Ryujinx.HLE/HOS/Kernel/KProcess.cs b/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs similarity index 99% rename from Ryujinx.HLE/HOS/Kernel/KProcess.cs rename to Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs index 6d91f41cd8..0d77a4959a 100644 --- a/Ryujinx.HLE/HOS/Kernel/KProcess.cs +++ b/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs @@ -3,12 +3,16 @@ using ChocolArm64.Events; using ChocolArm64.Memory; using Ryujinx.Common; using Ryujinx.Common.Logging; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Memory; +using Ryujinx.HLE.HOS.Kernel.SupervisorCall; +using Ryujinx.HLE.HOS.Kernel.Threading; using System; using System.Collections.Generic; using System.Linq; using System.Threading; -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Process { class KProcess : KSynchronizationObject { diff --git a/Ryujinx.HLE/HOS/Kernel/KProcessCapabilities.cs b/Ryujinx.HLE/HOS/Kernel/Process/KProcessCapabilities.cs similarity index 98% rename from Ryujinx.HLE/HOS/Kernel/KProcessCapabilities.cs rename to Ryujinx.HLE/HOS/Kernel/Process/KProcessCapabilities.cs index 4dc8500c6a..033f0a2cfb 100644 --- a/Ryujinx.HLE/HOS/Kernel/KProcessCapabilities.cs +++ b/Ryujinx.HLE/HOS/Kernel/Process/KProcessCapabilities.cs @@ -1,6 +1,9 @@ using Ryujinx.Common; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Memory; +using Ryujinx.HLE.HOS.Kernel.Threading; -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Process { class KProcessCapabilities { diff --git a/Ryujinx.HLE/HOS/Kernel/KTlsPageInfo.cs b/Ryujinx.HLE/HOS/Kernel/Process/KTlsPageInfo.cs similarity index 95% rename from Ryujinx.HLE/HOS/Kernel/KTlsPageInfo.cs rename to Ryujinx.HLE/HOS/Kernel/Process/KTlsPageInfo.cs index ff5ecf1391..5ce5a299da 100644 --- a/Ryujinx.HLE/HOS/Kernel/KTlsPageInfo.cs +++ b/Ryujinx.HLE/HOS/Kernel/Process/KTlsPageInfo.cs @@ -1,4 +1,6 @@ -namespace Ryujinx.HLE.HOS.Kernel +using Ryujinx.HLE.HOS.Kernel.Memory; + +namespace Ryujinx.HLE.HOS.Kernel.Process { class KTlsPageInfo { diff --git a/Ryujinx.HLE/HOS/Kernel/KTlsPageManager.cs b/Ryujinx.HLE/HOS/Kernel/Process/KTlsPageManager.cs similarity index 94% rename from Ryujinx.HLE/HOS/Kernel/KTlsPageManager.cs rename to Ryujinx.HLE/HOS/Kernel/Process/KTlsPageManager.cs index 75f595ebcb..03174e5bbc 100644 --- a/Ryujinx.HLE/HOS/Kernel/KTlsPageManager.cs +++ b/Ryujinx.HLE/HOS/Kernel/Process/KTlsPageManager.cs @@ -1,6 +1,7 @@ +using Ryujinx.HLE.HOS.Kernel.Memory; using System; -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Process { class KTlsPageManager { diff --git a/Ryujinx.HLE/HOS/Kernel/ProcessCreationInfo.cs b/Ryujinx.HLE/HOS/Kernel/Process/ProcessCreationInfo.cs similarity index 96% rename from Ryujinx.HLE/HOS/Kernel/ProcessCreationInfo.cs rename to Ryujinx.HLE/HOS/Kernel/Process/ProcessCreationInfo.cs index 7b2e8b72fa..ba9f54bf36 100644 --- a/Ryujinx.HLE/HOS/Kernel/ProcessCreationInfo.cs +++ b/Ryujinx.HLE/HOS/Kernel/Process/ProcessCreationInfo.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Process { struct ProcessCreationInfo { diff --git a/Ryujinx.HLE/HOS/Kernel/ProcessState.cs b/Ryujinx.HLE/HOS/Kernel/Process/ProcessState.cs similarity index 87% rename from Ryujinx.HLE/HOS/Kernel/ProcessState.cs rename to Ryujinx.HLE/HOS/Kernel/Process/ProcessState.cs index 98ff4207e7..5ef3077e36 100644 --- a/Ryujinx.HLE/HOS/Kernel/ProcessState.cs +++ b/Ryujinx.HLE/HOS/Kernel/Process/ProcessState.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Process { enum ProcessState : byte { diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/InvalidSvcException.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/InvalidSvcException.cs new file mode 100644 index 0000000000..b78a228471 --- /dev/null +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/InvalidSvcException.cs @@ -0,0 +1,9 @@ +using System; + +namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall +{ + public class InvalidSvcException : Exception + { + public InvalidSvcException(string message) : base(message) { } + } +} diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcHandler.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcHandler.cs new file mode 100644 index 0000000000..08340b06bb --- /dev/null +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcHandler.cs @@ -0,0 +1,61 @@ +using ChocolArm64.Events; +using ChocolArm64.Memory; +using ChocolArm64.State; +using Ryujinx.HLE.HOS.Ipc; +using Ryujinx.HLE.HOS.Kernel.Ipc; +using Ryujinx.HLE.HOS.Kernel.Process; +using Ryujinx.HLE.HOS.Kernel.Threading; +using System; + +namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall +{ + partial class SvcHandler + { + private Switch _device; + private KProcess _process; + private Horizon _system; + private MemoryManager _memory; + + private struct HleIpcMessage + { + public KThread Thread { get; private set; } + public KSession Session { get; private set; } + public IpcMessage Message { get; private set; } + public long MessagePtr { get; private set; } + + public HleIpcMessage( + KThread thread, + KSession session, + IpcMessage message, + long messagePtr) + { + Thread = thread; + Session = session; + Message = message; + MessagePtr = messagePtr; + } + } + + public SvcHandler(Switch device, KProcess process) + { + _device = device; + _process = process; + _system = device.System; + _memory = process.CpuMemory; + } + + public void SvcCall(object sender, InstExceptionEventArgs e) + { + Action svcFunc = SvcTable.GetSvcFunc(e.Id); + + if (svcFunc == null) + { + throw new NotImplementedException($"SVC 0x{e.Id:X4} is not implemented."); + } + + CpuThreadState threadState = (CpuThreadState)sender; + + svcFunc(this, threadState); + } + } +} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcMemory.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcMemory.cs new file mode 100644 index 0000000000..e6590522e7 --- /dev/null +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcMemory.cs @@ -0,0 +1,394 @@ +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Memory; +using Ryujinx.HLE.HOS.Kernel.Process; + +namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall +{ + partial class SvcHandler + { + public KernelResult SetHeapSize64(ulong size, out ulong position) + { + return SetHeapSize(size, out position); + } + + private KernelResult SetHeapSize(ulong size, out ulong position) + { + if ((size & 0xfffffffe001fffff) != 0) + { + position = 0; + + return KernelResult.InvalidSize; + } + + return _process.MemoryManager.SetHeapSize(size, out position); + } + + public KernelResult SetMemoryAttribute64( + ulong position, + ulong size, + MemoryAttribute attributeMask, + MemoryAttribute attributeValue) + { + return SetMemoryAttribute(position, size, attributeMask, attributeValue); + } + + private KernelResult SetMemoryAttribute( + ulong position, + ulong size, + MemoryAttribute attributeMask, + MemoryAttribute attributeValue) + { + if (!PageAligned(position)) + { + return KernelResult.InvalidAddress; + } + + if (!PageAligned(size) || size == 0) + { + return KernelResult.InvalidSize; + } + + MemoryAttribute attributes = attributeMask | attributeValue; + + if (attributes != attributeMask || + (attributes | MemoryAttribute.Uncached) != MemoryAttribute.Uncached) + { + return KernelResult.InvalidCombination; + } + + KernelResult result = _process.MemoryManager.SetMemoryAttribute( + position, + size, + attributeMask, + attributeValue); + + if (result == KernelResult.Success) + { + _memory.StopObservingRegion((long)position, (long)size); + } + + return result; + } + + public KernelResult MapMemory64(ulong dst, ulong src, ulong size) + { + return MapMemory(dst, src, size); + } + + private KernelResult MapMemory(ulong dst, ulong src, ulong size) + { + if (!PageAligned(src | dst)) + { + return KernelResult.InvalidAddress; + } + + if (!PageAligned(size) || size == 0) + { + return KernelResult.InvalidSize; + } + + if (src + size <= src || dst + size <= dst) + { + return KernelResult.InvalidMemState; + } + + KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); + + if (!currentProcess.MemoryManager.InsideAddrSpace(src, size)) + { + return KernelResult.InvalidMemState; + } + + if (currentProcess.MemoryManager.OutsideStackRegion(dst, size) || + currentProcess.MemoryManager.InsideHeapRegion (dst, size) || + currentProcess.MemoryManager.InsideAliasRegion (dst, size)) + { + return KernelResult.InvalidMemRange; + } + + return _process.MemoryManager.Map(dst, src, size); + } + + public KernelResult UnmapMemory64(ulong dst, ulong src, ulong size) + { + return UnmapMemory(dst, src, size); + } + + private KernelResult UnmapMemory(ulong dst, ulong src, ulong size) + { + if (!PageAligned(src | dst)) + { + return KernelResult.InvalidAddress; + } + + if (!PageAligned(size) || size == 0) + { + return KernelResult.InvalidSize; + } + + if (src + size <= src || dst + size <= dst) + { + return KernelResult.InvalidMemState; + } + + KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); + + if (!currentProcess.MemoryManager.InsideAddrSpace(src, size)) + { + return KernelResult.InvalidMemState; + } + + if (currentProcess.MemoryManager.OutsideStackRegion(dst, size) || + currentProcess.MemoryManager.InsideHeapRegion (dst, size) || + currentProcess.MemoryManager.InsideAliasRegion (dst, size)) + { + return KernelResult.InvalidMemRange; + } + + return _process.MemoryManager.Unmap(dst, src, size); + } + + public KernelResult QueryMemory64(ulong infoPtr, ulong x1, ulong position) + { + return QueryMemory(infoPtr, position); + } + + private KernelResult QueryMemory(ulong infoPtr, ulong position) + { + KMemoryInfo blkInfo = _process.MemoryManager.QueryMemory(position); + + _memory.WriteUInt64((long)infoPtr + 0x00, blkInfo.Address); + _memory.WriteUInt64((long)infoPtr + 0x08, blkInfo.Size); + _memory.WriteInt32 ((long)infoPtr + 0x10, (int)blkInfo.State & 0xff); + _memory.WriteInt32 ((long)infoPtr + 0x14, (int)blkInfo.Attribute); + _memory.WriteInt32 ((long)infoPtr + 0x18, (int)blkInfo.Permission); + _memory.WriteInt32 ((long)infoPtr + 0x1c, blkInfo.IpcRefCount); + _memory.WriteInt32 ((long)infoPtr + 0x20, blkInfo.DeviceRefCount); + _memory.WriteInt32 ((long)infoPtr + 0x24, 0); + + return KernelResult.Success; + } + + public KernelResult MapSharedMemory64(int handle, ulong address, ulong size, MemoryPermission permission) + { + return MapSharedMemory(handle, address, size, permission); + } + + private KernelResult MapSharedMemory(int handle, ulong address, ulong size, MemoryPermission permission) + { + if (!PageAligned(address)) + { + return KernelResult.InvalidAddress; + } + + if (!PageAligned(size) || size == 0) + { + return KernelResult.InvalidSize; + } + + if (address + size <= address) + { + return KernelResult.InvalidMemState; + } + + if ((permission | MemoryPermission.Write) != MemoryPermission.ReadAndWrite) + { + return KernelResult.InvalidPermission; + } + + KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); + + KSharedMemory sharedMemory = currentProcess.HandleTable.GetObject(handle); + + if (sharedMemory == null) + { + return KernelResult.InvalidHandle; + } + + if (currentProcess.MemoryManager.IsInvalidRegion (address, size) || + currentProcess.MemoryManager.InsideHeapRegion (address, size) || + currentProcess.MemoryManager.InsideAliasRegion(address, size)) + { + return KernelResult.InvalidMemRange; + } + + return sharedMemory.MapIntoProcess( + currentProcess.MemoryManager, + address, + size, + currentProcess, + permission); + } + + public KernelResult UnmapSharedMemory64(int handle, ulong address, ulong size) + { + return UnmapSharedMemory(handle, address, size); + } + + private KernelResult UnmapSharedMemory(int handle, ulong address, ulong size) + { + if (!PageAligned(address)) + { + return KernelResult.InvalidAddress; + } + + if (!PageAligned(size) || size == 0) + { + return KernelResult.InvalidSize; + } + + if (address + size <= address) + { + return KernelResult.InvalidMemState; + } + + KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); + + KSharedMemory sharedMemory = currentProcess.HandleTable.GetObject(handle); + + if (sharedMemory == null) + { + return KernelResult.InvalidHandle; + } + + if (currentProcess.MemoryManager.IsInvalidRegion (address, size) || + currentProcess.MemoryManager.InsideHeapRegion (address, size) || + currentProcess.MemoryManager.InsideAliasRegion(address, size)) + { + return KernelResult.InvalidMemRange; + } + + return sharedMemory.UnmapFromProcess( + currentProcess.MemoryManager, + address, + size, + currentProcess); + } + + public KernelResult CreateTransferMemory64( + ulong address, + ulong size, + MemoryPermission permission, + out int handle) + { + return CreateTransferMemory(address, size, permission, out handle); + } + + private KernelResult CreateTransferMemory(ulong address, ulong size, MemoryPermission permission, out int handle) + { + handle = 0; + + if (!PageAligned(address)) + { + return KernelResult.InvalidAddress; + } + + if (!PageAligned(size) || size == 0) + { + return KernelResult.InvalidSize; + } + + if (address + size <= address) + { + return KernelResult.InvalidMemState; + } + + if (permission > MemoryPermission.ReadAndWrite || permission == MemoryPermission.Write) + { + return KernelResult.InvalidPermission; + } + + KernelResult result = _process.MemoryManager.ReserveTransferMemory(address, size, permission); + + if (result != KernelResult.Success) + { + return result; + } + + KTransferMemory transferMemory = new KTransferMemory(address, size); + + return _process.HandleTable.GenerateHandle(transferMemory, out handle); + } + + public KernelResult MapPhysicalMemory64(ulong address, ulong size) + { + return MapPhysicalMemory(address, size); + } + + private KernelResult MapPhysicalMemory(ulong address, ulong size) + { + if (!PageAligned(address)) + { + return KernelResult.InvalidAddress; + } + + if (!PageAligned(size) || size == 0) + { + return KernelResult.InvalidSize; + } + + if (address + size <= address) + { + return KernelResult.InvalidMemRange; + } + + KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); + + if ((currentProcess.PersonalMmHeapPagesCount & 0xfffffffffffff) == 0) + { + return KernelResult.InvalidState; + } + + if (!currentProcess.MemoryManager.InsideAddrSpace (address, size) || + currentProcess.MemoryManager.OutsideAliasRegion(address, size)) + { + return KernelResult.InvalidMemRange; + } + + return _process.MemoryManager.MapPhysicalMemory(address, size); + } + + public KernelResult UnmapPhysicalMemory64(ulong address, ulong size) + { + return MapPhysicalMemory(address, size); + } + + private KernelResult UnmapPhysicalMemory(ulong address, ulong size) + { + if (!PageAligned(address)) + { + return KernelResult.InvalidAddress; + } + + if (!PageAligned(size) || size == 0) + { + return KernelResult.InvalidSize; + } + + if (address + size <= address) + { + return KernelResult.InvalidMemRange; + } + + KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); + + if ((currentProcess.PersonalMmHeapPagesCount & 0xfffffffffffff) == 0) + { + return KernelResult.InvalidState; + } + + if (!currentProcess.MemoryManager.InsideAddrSpace (address, size) || + currentProcess.MemoryManager.OutsideAliasRegion(address, size)) + { + return KernelResult.InvalidMemRange; + } + + return _process.MemoryManager.UnmapPhysicalMemory(address, size); + } + + private static bool PageAligned(ulong position) + { + return (position & (KMemoryManager.PageSize - 1)) == 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/SvcSystem.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs similarity index 74% rename from Ryujinx.HLE/HOS/Kernel/SvcSystem.cs rename to Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs index e42c2b4ec5..b05633567f 100644 --- a/Ryujinx.HLE/HOS/Kernel/SvcSystem.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs @@ -1,27 +1,33 @@ using ChocolArm64.Memory; -using ChocolArm64.State; using Ryujinx.Common; using Ryujinx.Common.Logging; using Ryujinx.HLE.Exceptions; using Ryujinx.HLE.HOS.Ipc; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Ipc; +using Ryujinx.HLE.HOS.Kernel.Memory; +using Ryujinx.HLE.HOS.Kernel.Process; +using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.Services; -using System; using System.Threading; -using static Ryujinx.HLE.HOS.ErrorCode; - -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall { partial class SvcHandler { - private void SvcExitProcess(CpuThreadState threadState) + public void ExitProcess64() + { + ExitProcess(); + } + + private void ExitProcess() { _system.Scheduler.GetCurrentProcess().Terminate(); } - private void SignalEvent64(CpuThreadState threadState) + public KernelResult SignalEvent64(int handle) { - threadState.X0 = (ulong)SignalEvent((int)threadState.X0); + return SignalEvent(handle); } private KernelResult SignalEvent(int handle) @@ -41,17 +47,12 @@ namespace Ryujinx.HLE.HOS.Kernel result = KernelResult.InvalidHandle; } - if (result != KernelResult.Success) - { - Logger.PrintWarning(LogClass.KernelSvc, "Operation failed with error: " + result + "!"); - } - return result; } - private void ClearEvent64(CpuThreadState threadState) + public KernelResult ClearEvent64(int handle) { - threadState.X0 = (ulong)ClearEvent((int)threadState.X0); + return ClearEvent(handle); } private KernelResult ClearEvent(int handle) @@ -71,29 +72,23 @@ namespace Ryujinx.HLE.HOS.Kernel result = writableEvent.Clear(); } - if (result != KernelResult.Success) - { - Logger.PrintWarning(LogClass.KernelSvc, "Operation failed with error: " + result + "!"); - } - return result; } - private void SvcCloseHandle(CpuThreadState threadState) + public KernelResult CloseHandle64(int handle) { - int handle = (int)threadState.X0; + return CloseHandle(handle); + } + private KernelResult CloseHandle(int handle) + { object obj = _process.HandleTable.GetObject(handle); _process.HandleTable.CloseHandle(handle); if (obj == null) { - Logger.PrintWarning(LogClass.KernelSvc, $"Invalid handle 0x{handle:x8}!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - - return; + return KernelResult.InvalidHandle; } if (obj is KSession session) @@ -107,12 +102,12 @@ namespace Ryujinx.HLE.HOS.Kernel transferMemory.Size); } - threadState.X0 = 0; + return KernelResult.Success; } - private void ResetSignal64(CpuThreadState threadState) + public KernelResult ResetSignal64(int handle) { - threadState.X0 = (ulong)ResetSignal((int)threadState.X0); + return ResetSignal(handle); } private KernelResult ResetSignal(int handle) @@ -141,60 +136,43 @@ namespace Ryujinx.HLE.HOS.Kernel } } - if (result == KernelResult.InvalidState) - { - Logger.PrintDebug(LogClass.KernelSvc, "Operation failed with error: " + result + "!"); - } - else if (result != KernelResult.Success) - { - Logger.PrintWarning(LogClass.KernelSvc, "Operation failed with error: " + result + "!"); - } - return result; } - private void SvcGetSystemTick(CpuThreadState threadState) + public ulong GetSystemTick64() { - threadState.X0 = threadState.CntpctEl0; + return _system.Scheduler.GetCurrentThread().Context.ThreadState.CntpctEl0; } - private void SvcConnectToNamedPort(CpuThreadState threadState) + public KernelResult ConnectToNamedPort64(ulong namePtr, out int handle) { - long stackPtr = (long)threadState.X0; - long namePtr = (long)threadState.X1; + return ConnectToNamedPort(namePtr, out handle); + } - string name = MemoryHelper.ReadAsciiString(_memory, namePtr, 8); + private KernelResult ConnectToNamedPort(ulong namePtr, out int handle) + { + string name = MemoryHelper.ReadAsciiString(_memory, (long)namePtr, 8); //TODO: Validate that app has perms to access the service, and that the service //actually exists, return error codes otherwise. KSession session = new KSession(ServiceFactory.MakeService(_system, name), name); - if (_process.HandleTable.GenerateHandle(session, out int handle) != KernelResult.Success) - { - throw new InvalidOperationException("Out of handles!"); - } - - threadState.X0 = 0; - threadState.X1 = (uint)handle; + return _process.HandleTable.GenerateHandle(session, out handle); } - private void SvcSendSyncRequest(CpuThreadState threadState) + public KernelResult SendSyncRequest64(int handle) { - SendSyncRequest(threadState, threadState.Tpidr, 0x100, (int)threadState.X0); + return SendSyncRequest((ulong)_system.Scheduler.GetCurrentThread().Context.ThreadState.Tpidr, 0x100, handle); } - private void SvcSendSyncRequestWithUserBuffer(CpuThreadState threadState) + public KernelResult SendSyncRequestWithUserBuffer64(ulong messagePtr, ulong size, int handle) { - SendSyncRequest( - threadState, - (long)threadState.X0, - (long)threadState.X1, - (int)threadState.X2); + return SendSyncRequest(messagePtr, size, handle); } - private void SendSyncRequest(CpuThreadState threadState, long messagePtr, long size, int handle) + private KernelResult SendSyncRequest(ulong messagePtr, ulong size, int handle) { - byte[] messageData = _memory.ReadBytes(messagePtr, size); + byte[] messageData = _memory.ReadBytes((long)messagePtr, (long)size); KSession session = _process.HandleTable.GetObject(handle); @@ -205,29 +183,29 @@ namespace Ryujinx.HLE.HOS.Kernel KThread currentThread = _system.Scheduler.GetCurrentThread(); currentThread.SignaledObj = null; - currentThread.ObjSyncResult = 0; + currentThread.ObjSyncResult = KernelResult.Success; currentThread.Reschedule(ThreadSchedState.Paused); - IpcMessage message = new IpcMessage(messageData, messagePtr); + IpcMessage message = new IpcMessage(messageData, (long)messagePtr); ThreadPool.QueueUserWorkItem(ProcessIpcRequest, new HleIpcMessage( currentThread, session, message, - messagePtr)); + (long)messagePtr)); _system.ThreadCounter.AddCount(); _system.CriticalSection.Leave(); - threadState.X0 = (ulong)currentThread.ObjSyncResult; + return currentThread.ObjSyncResult; } else { Logger.PrintWarning(LogClass.KernelSvc, $"Invalid session handle 0x{handle:x8}!"); - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); + return KernelResult.InvalidHandle; } } @@ -235,7 +213,7 @@ namespace Ryujinx.HLE.HOS.Kernel { HleIpcMessage ipcMessage = (HleIpcMessage)state; - ipcMessage.Thread.ObjSyncResult = (int)IpcHandler.IpcCall( + ipcMessage.Thread.ObjSyncResult = IpcHandler.IpcCall( _device, _process, _memory, @@ -248,14 +226,9 @@ namespace Ryujinx.HLE.HOS.Kernel ipcMessage.Thread.Reschedule(ThreadSchedState.Running); } - private void GetProcessId64(CpuThreadState threadState) + public KernelResult GetProcessId64(int handle, out long pid) { - int handle = (int)threadState.X1; - - KernelResult result = GetProcessId(handle, out long pid); - - threadState.X0 = (ulong)result; - threadState.X1 = (ulong)pid; + return GetProcessId(handle, out pid); } private KernelResult GetProcessId(int handle, out long pid) @@ -283,15 +256,16 @@ namespace Ryujinx.HLE.HOS.Kernel : KernelResult.InvalidHandle; } - private void SvcBreak(CpuThreadState threadState) + public void Break64(ulong reason, ulong x1, ulong info) { - long reason = (long)threadState.X0; - long unknown = (long)threadState.X1; - long info = (long)threadState.X2; + Break(reason); + } + private void Break(ulong reason) + { KThread currentThread = _system.Scheduler.GetCurrentThread(); - if ((reason & (1 << 31)) == 0) + if ((reason & (1UL << 31)) == 0) { currentThread.PrintGuestStackTrace(); @@ -305,29 +279,21 @@ namespace Ryujinx.HLE.HOS.Kernel } } - private void SvcOutputDebugString(CpuThreadState threadState) + public void OutputDebugString64(ulong strPtr, ulong size) { - long position = (long)threadState.X0; - long size = (long)threadState.X1; - - string str = MemoryHelper.ReadAsciiString(_memory, position, size); - - Logger.PrintWarning(LogClass.KernelSvc, str); - - threadState.X0 = 0; + OutputDebugString(strPtr, size); } - private void GetInfo64(CpuThreadState threadState) + private void OutputDebugString(ulong strPtr, ulong size) { - long stackPtr = (long)threadState.X0; - uint id = (uint)threadState.X1; - int handle = (int)threadState.X2; - long subId = (long)threadState.X3; + string str = MemoryHelper.ReadAsciiString(_memory, (long)strPtr, (long)size); - KernelResult result = GetInfo(id, handle, subId, out long value); + Logger.PrintWarning(LogClass.KernelSvc, str); + } - threadState.X0 = (ulong)result; - threadState.X1 = (ulong)value; + public KernelResult GetInfo64(uint id, int handle, long subId, out long value) + { + return GetInfo(id, handle, subId, out value); } private KernelResult GetInfo(uint id, int handle, long subId, out long value) @@ -556,13 +522,9 @@ namespace Ryujinx.HLE.HOS.Kernel return KernelResult.Success; } - private void CreateEvent64(CpuThreadState state) + public KernelResult CreateEvent64(out int wEventHandle, out int rEventHandle) { - KernelResult result = CreateEvent(out int wEventHandle, out int rEventHandle); - - state.X0 = (ulong)result; - state.X1 = (ulong)wEventHandle; - state.X2 = (ulong)rEventHandle; + return CreateEvent(out wEventHandle, out rEventHandle); } private KernelResult CreateEvent(out int wEventHandle, out int rEventHandle) @@ -588,15 +550,9 @@ namespace Ryujinx.HLE.HOS.Kernel return result; } - private void GetProcessList64(CpuThreadState state) + public KernelResult GetProcessList64(ulong address, int maxCount, out int count) { - ulong address = state.X1; - int maxOut = (int)state.X2; - - KernelResult result = GetProcessList(address, maxOut, out int count); - - state.X0 = (ulong)result; - state.X1 = (ulong)count; + return GetProcessList(address, maxCount, out count); } private KernelResult GetProcessList(ulong address, int maxCount, out int count) @@ -633,7 +589,7 @@ namespace Ryujinx.HLE.HOS.Kernel { if (copyCount < maxCount) { - if (!KernelTransfer.KernelToUserInt64(_system, (long)address + copyCount * 8, process.Pid)) + if (!KernelTransfer.KernelToUserInt64(_system, address + (ulong)copyCount * 8, process.Pid)) { return KernelResult.UserCopyFailed; } @@ -648,16 +604,9 @@ namespace Ryujinx.HLE.HOS.Kernel return KernelResult.Success; } - private void GetSystemInfo64(CpuThreadState state) + public KernelResult GetSystemInfo64(uint id, int handle, long subId, out long value) { - uint id = (uint)state.X1; - int handle = (int)state.X2; - long subId = (long)state.X3; - - KernelResult result = GetSystemInfo(id, handle, subId, out long value); - - state.X0 = (ulong)result; - state.X1 = (ulong)value; + return GetSystemInfo(id, handle, subId, out value); } private KernelResult GetSystemInfo(uint id, int handle, long subId, out long value) @@ -716,28 +665,20 @@ namespace Ryujinx.HLE.HOS.Kernel return KernelResult.Success; } - private void CreatePort64(CpuThreadState state) + public KernelResult CreatePort64( + int maxSessions, + bool isLight, + ulong namePtr, + out int serverPortHandle, + out int clientPortHandle) { - int maxSessions = (int)state.X2; - bool isLight = (state.X3 & 1) != 0; - long nameAddress = (long)state.X4; - - KernelResult result = CreatePort( - maxSessions, - isLight, - nameAddress, - out int serverPortHandle, - out int clientPortHandle); - - state.X0 = (ulong)result; - state.X1 = (ulong)serverPortHandle; - state.X2 = (ulong)clientPortHandle; + return CreatePort(maxSessions, isLight, namePtr, out serverPortHandle, out clientPortHandle); } private KernelResult CreatePort( int maxSessions, bool isLight, - long nameAddress, + ulong namePtr, out int serverPortHandle, out int clientPortHandle) { @@ -750,7 +691,7 @@ namespace Ryujinx.HLE.HOS.Kernel KPort port = new KPort(_system); - port.Initialize(maxSessions, isLight, nameAddress); + port.Initialize(maxSessions, isLight, (long)namePtr); KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); @@ -771,22 +712,16 @@ namespace Ryujinx.HLE.HOS.Kernel return result; } - private void ManageNamedPort64(CpuThreadState state) + public KernelResult ManageNamedPort64(ulong namePtr, int maxSessions, out int handle) { - long nameAddress = (long)state.X1; - int maxSessions = (int)state.X2; - - KernelResult result = ManageNamedPort(nameAddress, maxSessions, out int handle); - - state.X0 = (ulong)result; - state.X1 = (ulong)handle; + return ManageNamedPort(namePtr, maxSessions, out handle); } - private KernelResult ManageNamedPort(long nameAddress, int maxSessions, out int handle) + private KernelResult ManageNamedPort(ulong namePtr, int maxSessions, out int handle) { handle = 0; - if (!KernelTransfer.UserToKernelString(_system, nameAddress, 12, out string name)) + if (!KernelTransfer.UserToKernelString(_system, namePtr, 12, out string name)) { return KernelResult.UserCopyFailed; } diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcTable.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcTable.cs new file mode 100644 index 0000000000..a6111777da --- /dev/null +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcTable.cs @@ -0,0 +1,340 @@ +using ChocolArm64.State; +using Ryujinx.Common.Logging; +using Ryujinx.HLE.HOS.Kernel.Common; +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Reflection.Emit; + +namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall +{ + static class SvcTable + { + private const int SvcFuncMaxArguments = 8; + + private static Dictionary _svcFuncs64; + + private static Action[] _svcTable64; + + static SvcTable() + { + _svcFuncs64 = new Dictionary + { + { 0x01, nameof(SvcHandler.SetHeapSize64) }, + { 0x03, nameof(SvcHandler.SetMemoryAttribute64) }, + { 0x04, nameof(SvcHandler.MapMemory64) }, + { 0x05, nameof(SvcHandler.UnmapMemory64) }, + { 0x06, nameof(SvcHandler.QueryMemory64) }, + { 0x07, nameof(SvcHandler.ExitProcess64) }, + { 0x08, nameof(SvcHandler.CreateThread64) }, + { 0x09, nameof(SvcHandler.StartThread64) }, + { 0x0a, nameof(SvcHandler.ExitThread64) }, + { 0x0b, nameof(SvcHandler.SleepThread64) }, + { 0x0c, nameof(SvcHandler.GetThreadPriority64) }, + { 0x0d, nameof(SvcHandler.SetThreadPriority64) }, + { 0x0e, nameof(SvcHandler.GetThreadCoreMask64) }, + { 0x0f, nameof(SvcHandler.SetThreadCoreMask64) }, + { 0x10, nameof(SvcHandler.GetCurrentProcessorNumber64) }, + { 0x11, nameof(SvcHandler.SignalEvent64) }, + { 0x12, nameof(SvcHandler.ClearEvent64) }, + { 0x13, nameof(SvcHandler.MapSharedMemory64) }, + { 0x14, nameof(SvcHandler.UnmapSharedMemory64) }, + { 0x15, nameof(SvcHandler.CreateTransferMemory64) }, + { 0x16, nameof(SvcHandler.CloseHandle64) }, + { 0x17, nameof(SvcHandler.ResetSignal64) }, + { 0x18, nameof(SvcHandler.WaitSynchronization64) }, + { 0x19, nameof(SvcHandler.CancelSynchronization64) }, + { 0x1a, nameof(SvcHandler.ArbitrateLock64) }, + { 0x1b, nameof(SvcHandler.ArbitrateUnlock64) }, + { 0x1c, nameof(SvcHandler.WaitProcessWideKeyAtomic64) }, + { 0x1d, nameof(SvcHandler.SignalProcessWideKey64) }, + { 0x1e, nameof(SvcHandler.GetSystemTick64) }, + { 0x1f, nameof(SvcHandler.ConnectToNamedPort64) }, + { 0x21, nameof(SvcHandler.SendSyncRequest64) }, + { 0x22, nameof(SvcHandler.SendSyncRequestWithUserBuffer64) }, + { 0x24, nameof(SvcHandler.GetProcessId64) }, + { 0x25, nameof(SvcHandler.GetThreadId64) }, + { 0x26, nameof(SvcHandler.Break64) }, + { 0x27, nameof(SvcHandler.OutputDebugString64) }, + { 0x29, nameof(SvcHandler.GetInfo64) }, + { 0x2c, nameof(SvcHandler.MapPhysicalMemory64) }, + { 0x2d, nameof(SvcHandler.UnmapPhysicalMemory64) }, + { 0x32, nameof(SvcHandler.SetThreadActivity64) }, + { 0x33, nameof(SvcHandler.GetThreadContext364) }, + { 0x34, nameof(SvcHandler.WaitForAddress64) }, + { 0x35, nameof(SvcHandler.SignalToAddress64) }, + { 0x45, nameof(SvcHandler.CreateEvent64) }, + { 0x65, nameof(SvcHandler.GetProcessList64) }, + { 0x6f, nameof(SvcHandler.GetSystemInfo64) }, + { 0x70, nameof(SvcHandler.CreatePort64) }, + { 0x71, nameof(SvcHandler.ManageNamedPort64) } + }; + + _svcTable64 = new Action[0x80]; + } + + public static Action GetSvcFunc(int svcId) + { + if (_svcTable64[svcId] != null) + { + return _svcTable64[svcId]; + } + + if (_svcFuncs64.TryGetValue(svcId, out string svcName)) + { + return _svcTable64[svcId] = GenerateMethod(svcName); + } + + return null; + } + + private static Action GenerateMethod(string svcName) + { + Type[] argTypes = new Type[] { typeof(SvcHandler), typeof(CpuThreadState) }; + + DynamicMethod method = new DynamicMethod(svcName, null, argTypes); + + MethodInfo methodInfo = typeof(SvcHandler).GetMethod(svcName); + + ParameterInfo[] methodArgs = methodInfo.GetParameters(); + + if (methodArgs.Length > SvcFuncMaxArguments) + { + throw new InvalidOperationException($"Method \"{svcName}\" has too many arguments, max is 8."); + } + + ILGenerator generator = method.GetILGenerator(); + + void ConvertToArgType(Type sourceType) + { + CheckIfTypeIsSupported(sourceType, svcName); + + switch (Type.GetTypeCode(sourceType)) + { + case TypeCode.UInt32: generator.Emit(OpCodes.Conv_U4); break; + case TypeCode.Int32: generator.Emit(OpCodes.Conv_I4); break; + case TypeCode.UInt16: generator.Emit(OpCodes.Conv_U2); break; + case TypeCode.Int16: generator.Emit(OpCodes.Conv_I2); break; + case TypeCode.Byte: generator.Emit(OpCodes.Conv_U1); break; + case TypeCode.SByte: generator.Emit(OpCodes.Conv_I1); break; + + case TypeCode.Boolean: + generator.Emit(OpCodes.Conv_I4); + generator.Emit(OpCodes.Ldc_I4_1); + generator.Emit(OpCodes.And); + break; + } + } + + void ConvertToFieldType(Type sourceType) + { + CheckIfTypeIsSupported(sourceType, svcName); + + switch (Type.GetTypeCode(sourceType)) + { + case TypeCode.UInt32: + case TypeCode.Int32: + case TypeCode.UInt16: + case TypeCode.Int16: + case TypeCode.Byte: + case TypeCode.SByte: + case TypeCode.Boolean: + generator.Emit(OpCodes.Conv_U8); + break; + } + } + + //For functions returning output values, the first registers + //are used to hold pointers where the value will be stored, + //so they can't be used to pass argument and we must + //skip them. + int byRefArgsCount = 0; + + for (int index = 0; index < methodArgs.Length; index++) + { + if (methodArgs[index].ParameterType.IsByRef) + { + byRefArgsCount++; + } + } + + //Print all the arguments for debugging purposes. + int inputArgsCount = methodArgs.Length - byRefArgsCount; + + generator.Emit(OpCodes.Ldc_I4_S, inputArgsCount); + + generator.Emit(OpCodes.Newarr, typeof(object)); + + string argsFormat = svcName; + + for (int index = 0; index < inputArgsCount; index++) + { + argsFormat += $" {methodArgs[index].Name}: 0x{{{index}:X8}},"; + + generator.Emit(OpCodes.Dup); + generator.Emit(OpCodes.Ldc_I4_S, index); + generator.Emit(OpCodes.Conv_I); + + generator.Emit(OpCodes.Ldarg_1); + generator.Emit(OpCodes.Ldfld, GetStateFieldX(byRefArgsCount + index)); + + generator.Emit(OpCodes.Box, typeof(ulong)); + + generator.Emit(OpCodes.Stelem_Ref); + } + + argsFormat = argsFormat.Substring(0, argsFormat.Length - 1); + + generator.Emit(OpCodes.Ldstr, argsFormat); + + BindingFlags staticNonPublic = BindingFlags.NonPublic | BindingFlags.Static; + + MethodInfo printArgsMethod = typeof(SvcTable).GetMethod(nameof(PrintArguments), staticNonPublic); + + generator.Emit(OpCodes.Call, printArgsMethod); + + //Call the SVC function handler. + generator.Emit(OpCodes.Ldarg_0); + + List locals = new List(); + + for (int index = 0; index < methodArgs.Length; index++) + { + Type argType = methodArgs[index].ParameterType; + + if (argType.IsByRef) + { + argType = argType.GetElementType(); + + LocalBuilder local = generator.DeclareLocal(argType); + + locals.Add(local); + + if (!methodArgs[index].IsOut) + { + throw new InvalidOperationException($"Method \"{svcName}\" has a invalid ref type \"{argType.Name}\"."); + } + + generator.Emit(OpCodes.Ldloca_S, (byte)local.LocalIndex); + } + else + { + generator.Emit(OpCodes.Ldarg_1); + generator.Emit(OpCodes.Ldfld, GetStateFieldX(byRefArgsCount + index)); + + ConvertToArgType(argType); + } + } + + generator.Emit(OpCodes.Call, methodInfo); + + int outRegIndex = 0; + + Type retType = methodInfo.ReturnType; + + //Print result code. + if (retType == typeof(KernelResult)) + { + MethodInfo printResultMethod = typeof(SvcTable).GetMethod(nameof(PrintResult), staticNonPublic); + + generator.Emit(OpCodes.Dup); + generator.Emit(OpCodes.Ldstr, svcName); + generator.Emit(OpCodes.Call, printResultMethod); + } + + //Save return value into register X0 (when the method has a return value). + if (retType != typeof(void)) + { + CheckIfTypeIsSupported(retType, svcName); + + LocalBuilder tempLocal = generator.DeclareLocal(retType); + + generator.Emit(OpCodes.Stloc, tempLocal); + generator.Emit(OpCodes.Ldarg_1); + generator.Emit(OpCodes.Ldloc, tempLocal); + + ConvertToFieldType(retType); + + generator.Emit(OpCodes.Stfld, GetStateFieldX(outRegIndex++)); + } + + for (int index = 0; index < locals.Count; index++) + { + generator.Emit(OpCodes.Ldarg_1); + generator.Emit(OpCodes.Ldloc, locals[index]); + + ConvertToFieldType(locals[index].LocalType); + + generator.Emit(OpCodes.Stfld, GetStateFieldX(outRegIndex++)); + } + + //Zero out the remaining unused registers. + while (outRegIndex < SvcFuncMaxArguments) + { + generator.Emit(OpCodes.Ldarg_1); + generator.Emit(OpCodes.Ldc_I8, 0L); + generator.Emit(OpCodes.Stfld, GetStateFieldX(outRegIndex++)); + } + + generator.Emit(OpCodes.Ret); + + return (Action)method.CreateDelegate(typeof(Action)); + } + + private static FieldInfo GetStateFieldX(int index) + { + switch (index) + { + case 0: return typeof(CpuThreadState).GetField(nameof(CpuThreadState.X0)); + case 1: return typeof(CpuThreadState).GetField(nameof(CpuThreadState.X1)); + case 2: return typeof(CpuThreadState).GetField(nameof(CpuThreadState.X2)); + case 3: return typeof(CpuThreadState).GetField(nameof(CpuThreadState.X3)); + case 4: return typeof(CpuThreadState).GetField(nameof(CpuThreadState.X4)); + case 5: return typeof(CpuThreadState).GetField(nameof(CpuThreadState.X5)); + case 6: return typeof(CpuThreadState).GetField(nameof(CpuThreadState.X6)); + case 7: return typeof(CpuThreadState).GetField(nameof(CpuThreadState.X7)); + } + + throw new ArgumentOutOfRangeException(nameof(index)); + } + + private static void CheckIfTypeIsSupported(Type type, string svcName) + { + switch (Type.GetTypeCode(type)) + { + case TypeCode.UInt64: + case TypeCode.Int64: + case TypeCode.UInt32: + case TypeCode.Int32: + case TypeCode.UInt16: + case TypeCode.Int16: + case TypeCode.Byte: + case TypeCode.SByte: + case TypeCode.Boolean: + return; + } + + throw new InvalidSvcException($"Method \"{svcName}\" has a invalid ref type \"{type.Name}\"."); + } + + private static void PrintResult(KernelResult result, string svcName) + { + if (result != KernelResult.Success && + result != KernelResult.TimedOut && + result != KernelResult.Cancelled && + result != KernelResult.InvalidState) + { + Logger.PrintWarning(LogClass.KernelSvc, $"{svcName} returned error {result}."); + } + else + { + Logger.PrintDebug(LogClass.KernelSvc, $"{svcName} returned result {result}."); + } + } + + private static void PrintArguments(object[] argValues, string format) + { + Logger.PrintDebug(LogClass.KernelSvc, string.Format(format, argValues)); + } + } +} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThread.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThread.cs new file mode 100644 index 0000000000..1e1927fec1 --- /dev/null +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThread.cs @@ -0,0 +1,420 @@ +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Process; +using Ryujinx.HLE.HOS.Kernel.Threading; + +namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall +{ + partial class SvcHandler + { + public KernelResult CreateThread64( + ulong entrypoint, + ulong argsPtr, + ulong stackTop, + int priority, + int cpuCore, + out int handle) + { + return CreateThread(entrypoint, argsPtr, stackTop, priority, cpuCore, out handle); + } + + private KernelResult CreateThread( + ulong entrypoint, + ulong argsPtr, + ulong stackTop, + int priority, + int cpuCore, + out int handle) + { + handle = 0; + + KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); + + if (cpuCore == -2) + { + cpuCore = currentProcess.DefaultCpuCore; + } + + if ((uint)cpuCore >= KScheduler.CpuCoresCount || !currentProcess.IsCpuCoreAllowed(cpuCore)) + { + return KernelResult.InvalidCpuCore; + } + + if ((uint)priority >= KScheduler.PrioritiesCount || !currentProcess.IsPriorityAllowed(priority)) + { + return KernelResult.InvalidPriority; + } + + long timeout = KTimeManager.ConvertMillisecondsToNanoseconds(100); + + if (currentProcess.ResourceLimit != null && + !currentProcess.ResourceLimit.Reserve(LimitableResource.Thread, 1, timeout)) + { + return KernelResult.ResLimitExceeded; + } + + KThread thread = new KThread(_system); + + KernelResult result = currentProcess.InitializeThread( + thread, + entrypoint, + argsPtr, + stackTop, + priority, + cpuCore); + + if (result != KernelResult.Success) + { + currentProcess.ResourceLimit?.Release(LimitableResource.Thread, 1); + + return result; + } + + result = _process.HandleTable.GenerateHandle(thread, out handle); + + if (result != KernelResult.Success) + { + thread.Terminate(); + + currentProcess.ResourceLimit?.Release(LimitableResource.Thread, 1); + } + + return result; + } + + public KernelResult StartThread64(int handle) + { + return StartThread(handle); + } + + private KernelResult StartThread(int handle) + { + KThread thread = _process.HandleTable.GetObject(handle); + + if (thread != null) + { + return thread.Start(); + } + else + { + return KernelResult.InvalidHandle; + } + } + + public void ExitThread64() + { + ExitThread(); + } + + private void ExitThread() + { + KThread currentThread = _system.Scheduler.GetCurrentThread(); + + _system.Scheduler.ExitThread(currentThread); + + currentThread.Exit(); + } + + public void SleepThread64(long timeout) + { + SleepThread(timeout); + } + + private void SleepThread(long timeout) + { + KThread currentThread = _system.Scheduler.GetCurrentThread(); + + if (timeout < 1) + { + switch (timeout) + { + case 0: currentThread.Yield(); break; + case -1: currentThread.YieldWithLoadBalancing(); break; + case -2: currentThread.YieldAndWaitForLoadBalancing(); break; + } + } + else + { + currentThread.Sleep(timeout); + } + } + + public KernelResult GetThreadPriority64(int handle, out int priority) + { + return GetThreadPriority(handle, out priority); + } + + private KernelResult GetThreadPriority(int handle, out int priority) + { + KThread thread = _process.HandleTable.GetKThread(handle); + + if (thread != null) + { + priority = thread.DynamicPriority; + + return KernelResult.Success; + } + else + { + priority = 0; + + return KernelResult.InvalidHandle; + } + } + + public KernelResult SetThreadPriority64(int handle, int priority) + { + return SetThreadPriority(handle, priority); + } + + public KernelResult SetThreadPriority(int handle, int priority) + { + //TODO: NPDM check. + + KThread thread = _process.HandleTable.GetKThread(handle); + + if (thread == null) + { + return KernelResult.InvalidHandle; + } + + thread.SetPriority(priority); + + return KernelResult.Success; + } + + public KernelResult GetThreadCoreMask64(int handle, out int preferredCore, out long affinityMask) + { + return GetThreadCoreMask(handle, out preferredCore, out affinityMask); + } + + private KernelResult GetThreadCoreMask(int handle, out int preferredCore, out long affinityMask) + { + KThread thread = _process.HandleTable.GetKThread(handle); + + if (thread != null) + { + preferredCore = thread.PreferredCore; + affinityMask = thread.AffinityMask; + + return KernelResult.Success; + } + else + { + preferredCore = 0; + affinityMask = 0; + + return KernelResult.InvalidHandle; + } + } + + public KernelResult SetThreadCoreMask64(int handle, int preferredCore, long affinityMask) + { + return SetThreadCoreMask(handle, preferredCore, affinityMask); + } + + private KernelResult SetThreadCoreMask(int handle, int preferredCore, long affinityMask) + { + KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); + + if (preferredCore == -2) + { + preferredCore = currentProcess.DefaultCpuCore; + + affinityMask = 1 << preferredCore; + } + else + { + if ((currentProcess.Capabilities.AllowedCpuCoresMask | affinityMask) != + currentProcess.Capabilities.AllowedCpuCoresMask) + { + return KernelResult.InvalidCpuCore; + } + + if (affinityMask == 0) + { + return KernelResult.InvalidCombination; + } + + if ((uint)preferredCore > 3) + { + if ((preferredCore | 2) != -1) + { + return KernelResult.InvalidCpuCore; + } + } + else if ((affinityMask & (1 << preferredCore)) == 0) + { + return KernelResult.InvalidCombination; + } + } + + KThread thread = _process.HandleTable.GetKThread(handle); + + if (thread == null) + { + return KernelResult.InvalidHandle; + } + + return thread.SetCoreAndAffinityMask(preferredCore, affinityMask); + } + + public int GetCurrentProcessorNumber64() + { + return _system.Scheduler.GetCurrentThread().CurrentCore; + } + + public KernelResult GetThreadId64(int handle, out long threadUid) + { + return GetThreadId(handle, out threadUid); + } + + private KernelResult GetThreadId(int handle, out long threadUid) + { + KThread thread = _process.HandleTable.GetKThread(handle); + + if (thread != null) + { + threadUid = thread.ThreadUid; + + return KernelResult.Success; + } + else + { + threadUid = 0; + + return KernelResult.InvalidHandle; + } + } + + public KernelResult SetThreadActivity64(int handle, bool pause) + { + return SetThreadActivity(handle, pause); + } + + private KernelResult SetThreadActivity(int handle, bool pause) + { + KThread thread = _process.HandleTable.GetObject(handle); + + if (thread == null) + { + return KernelResult.InvalidHandle; + } + + if (thread.Owner != _system.Scheduler.GetCurrentProcess()) + { + return KernelResult.InvalidHandle; + } + + if (thread == _system.Scheduler.GetCurrentThread()) + { + return KernelResult.InvalidThread; + } + + return thread.SetActivity(pause); + } + + public KernelResult GetThreadContext364(ulong address, int handle) + { + return GetThreadContext3(address, handle); + } + + private KernelResult GetThreadContext3(ulong address, int handle) + { + KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); + KThread currentThread = _system.Scheduler.GetCurrentThread(); + + KThread thread = _process.HandleTable.GetObject(handle); + + if (thread == null) + { + return KernelResult.InvalidHandle; + } + + if (thread.Owner != currentProcess) + { + return KernelResult.InvalidHandle; + } + + if (currentThread == thread) + { + return KernelResult.InvalidThread; + } + + _memory.WriteUInt64((long)address + 0x0, thread.Context.ThreadState.X0); + _memory.WriteUInt64((long)address + 0x8, thread.Context.ThreadState.X1); + _memory.WriteUInt64((long)address + 0x10, thread.Context.ThreadState.X2); + _memory.WriteUInt64((long)address + 0x18, thread.Context.ThreadState.X3); + _memory.WriteUInt64((long)address + 0x20, thread.Context.ThreadState.X4); + _memory.WriteUInt64((long)address + 0x28, thread.Context.ThreadState.X5); + _memory.WriteUInt64((long)address + 0x30, thread.Context.ThreadState.X6); + _memory.WriteUInt64((long)address + 0x38, thread.Context.ThreadState.X7); + _memory.WriteUInt64((long)address + 0x40, thread.Context.ThreadState.X8); + _memory.WriteUInt64((long)address + 0x48, thread.Context.ThreadState.X9); + _memory.WriteUInt64((long)address + 0x50, thread.Context.ThreadState.X10); + _memory.WriteUInt64((long)address + 0x58, thread.Context.ThreadState.X11); + _memory.WriteUInt64((long)address + 0x60, thread.Context.ThreadState.X12); + _memory.WriteUInt64((long)address + 0x68, thread.Context.ThreadState.X13); + _memory.WriteUInt64((long)address + 0x70, thread.Context.ThreadState.X14); + _memory.WriteUInt64((long)address + 0x78, thread.Context.ThreadState.X15); + _memory.WriteUInt64((long)address + 0x80, thread.Context.ThreadState.X16); + _memory.WriteUInt64((long)address + 0x88, thread.Context.ThreadState.X17); + _memory.WriteUInt64((long)address + 0x90, thread.Context.ThreadState.X18); + _memory.WriteUInt64((long)address + 0x98, thread.Context.ThreadState.X19); + _memory.WriteUInt64((long)address + 0xa0, thread.Context.ThreadState.X20); + _memory.WriteUInt64((long)address + 0xa8, thread.Context.ThreadState.X21); + _memory.WriteUInt64((long)address + 0xb0, thread.Context.ThreadState.X22); + _memory.WriteUInt64((long)address + 0xb8, thread.Context.ThreadState.X23); + _memory.WriteUInt64((long)address + 0xc0, thread.Context.ThreadState.X24); + _memory.WriteUInt64((long)address + 0xc8, thread.Context.ThreadState.X25); + _memory.WriteUInt64((long)address + 0xd0, thread.Context.ThreadState.X26); + _memory.WriteUInt64((long)address + 0xd8, thread.Context.ThreadState.X27); + _memory.WriteUInt64((long)address + 0xe0, thread.Context.ThreadState.X28); + _memory.WriteUInt64((long)address + 0xe8, thread.Context.ThreadState.X29); + _memory.WriteUInt64((long)address + 0xf0, thread.Context.ThreadState.X30); + _memory.WriteUInt64((long)address + 0xf8, thread.Context.ThreadState.X31); + + _memory.WriteInt64((long)address + 0x100, thread.LastPc); + + _memory.WriteUInt64((long)address + 0x108, (ulong)thread.Context.ThreadState.Psr); + + _memory.WriteVector128((long)address + 0x110, thread.Context.ThreadState.V0); + _memory.WriteVector128((long)address + 0x120, thread.Context.ThreadState.V1); + _memory.WriteVector128((long)address + 0x130, thread.Context.ThreadState.V2); + _memory.WriteVector128((long)address + 0x140, thread.Context.ThreadState.V3); + _memory.WriteVector128((long)address + 0x150, thread.Context.ThreadState.V4); + _memory.WriteVector128((long)address + 0x160, thread.Context.ThreadState.V5); + _memory.WriteVector128((long)address + 0x170, thread.Context.ThreadState.V6); + _memory.WriteVector128((long)address + 0x180, thread.Context.ThreadState.V7); + _memory.WriteVector128((long)address + 0x190, thread.Context.ThreadState.V8); + _memory.WriteVector128((long)address + 0x1a0, thread.Context.ThreadState.V9); + _memory.WriteVector128((long)address + 0x1b0, thread.Context.ThreadState.V10); + _memory.WriteVector128((long)address + 0x1c0, thread.Context.ThreadState.V11); + _memory.WriteVector128((long)address + 0x1d0, thread.Context.ThreadState.V12); + _memory.WriteVector128((long)address + 0x1e0, thread.Context.ThreadState.V13); + _memory.WriteVector128((long)address + 0x1f0, thread.Context.ThreadState.V14); + _memory.WriteVector128((long)address + 0x200, thread.Context.ThreadState.V15); + _memory.WriteVector128((long)address + 0x210, thread.Context.ThreadState.V16); + _memory.WriteVector128((long)address + 0x220, thread.Context.ThreadState.V17); + _memory.WriteVector128((long)address + 0x230, thread.Context.ThreadState.V18); + _memory.WriteVector128((long)address + 0x240, thread.Context.ThreadState.V19); + _memory.WriteVector128((long)address + 0x250, thread.Context.ThreadState.V20); + _memory.WriteVector128((long)address + 0x260, thread.Context.ThreadState.V21); + _memory.WriteVector128((long)address + 0x270, thread.Context.ThreadState.V22); + _memory.WriteVector128((long)address + 0x280, thread.Context.ThreadState.V23); + _memory.WriteVector128((long)address + 0x290, thread.Context.ThreadState.V24); + _memory.WriteVector128((long)address + 0x2a0, thread.Context.ThreadState.V25); + _memory.WriteVector128((long)address + 0x2b0, thread.Context.ThreadState.V26); + _memory.WriteVector128((long)address + 0x2c0, thread.Context.ThreadState.V27); + _memory.WriteVector128((long)address + 0x2d0, thread.Context.ThreadState.V28); + _memory.WriteVector128((long)address + 0x2e0, thread.Context.ThreadState.V29); + _memory.WriteVector128((long)address + 0x2f0, thread.Context.ThreadState.V30); + _memory.WriteVector128((long)address + 0x300, thread.Context.ThreadState.V31); + + _memory.WriteInt32((long)address + 0x310, thread.Context.ThreadState.Fpcr); + _memory.WriteInt32((long)address + 0x314, thread.Context.ThreadState.Fpsr); + _memory.WriteInt64((long)address + 0x318, thread.Context.ThreadState.Tpidr); + + return KernelResult.Success; + } + } +} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThreadSync.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThreadSync.cs new file mode 100644 index 0000000000..ecda9e2d00 --- /dev/null +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThreadSync.cs @@ -0,0 +1,250 @@ +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Process; +using Ryujinx.HLE.HOS.Kernel.Threading; +using System.Collections.Generic; + +namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall +{ + partial class SvcHandler + { + public KernelResult WaitSynchronization64(ulong handlesPtr, int handlesCount, long timeout, out int handleIndex) + { + return WaitSynchronization(handlesPtr, handlesCount, timeout, out handleIndex); + } + + private KernelResult WaitSynchronization(ulong handlesPtr, int handlesCount, long timeout, out int handleIndex) + { + handleIndex = 0; + + if ((uint)handlesCount > 0x40) + { + return KernelResult.MaximumExceeded; + } + + List syncObjs = new List(); + + for (int index = 0; index < handlesCount; index++) + { + int handle = _memory.ReadInt32((long)handlesPtr + index * 4); + + KSynchronizationObject syncObj = _process.HandleTable.GetObject(handle); + + if (syncObj == null) + { + break; + } + + syncObjs.Add(syncObj); + } + + return _system.Synchronization.WaitFor(syncObjs.ToArray(), timeout, out handleIndex); + } + + public KernelResult CancelSynchronization64(int handle) + { + return CancelSynchronization(handle); + } + + private KernelResult CancelSynchronization(int handle) + { + KThread thread = _process.HandleTable.GetKThread(handle); + + if (thread == null) + { + return KernelResult.InvalidHandle; + } + + thread.CancelSynchronization(); + + return KernelResult.Success; + } + + public KernelResult ArbitrateLock64(int ownerHandle, ulong mutexAddress, int requesterHandle) + { + return ArbitrateLock(ownerHandle, mutexAddress, requesterHandle); + } + + private KernelResult ArbitrateLock(int ownerHandle, ulong mutexAddress, int requesterHandle) + { + if (IsPointingInsideKernel(mutexAddress)) + { + return KernelResult.InvalidMemState; + } + + if (IsAddressNotWordAligned(mutexAddress)) + { + return KernelResult.InvalidAddress; + } + + KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); + + return currentProcess.AddressArbiter.ArbitrateLock(ownerHandle, mutexAddress, requesterHandle); + } + + public KernelResult ArbitrateUnlock64(ulong mutexAddress) + { + return ArbitrateUnlock(mutexAddress); + } + + private KernelResult ArbitrateUnlock(ulong mutexAddress) + { + if (IsPointingInsideKernel(mutexAddress)) + { + return KernelResult.InvalidMemState; + } + + if (IsAddressNotWordAligned(mutexAddress)) + { + return KernelResult.InvalidAddress; + } + + KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); + + return currentProcess.AddressArbiter.ArbitrateUnlock(mutexAddress); + } + + public KernelResult WaitProcessWideKeyAtomic64( + ulong mutexAddress, + ulong condVarAddress, + int handle, + long timeout) + { + return WaitProcessWideKeyAtomic(mutexAddress, condVarAddress, handle, timeout); + } + + private KernelResult WaitProcessWideKeyAtomic( + ulong mutexAddress, + ulong condVarAddress, + int handle, + long timeout) + { + if (IsPointingInsideKernel(mutexAddress)) + { + return KernelResult.InvalidMemState; + } + + if (IsAddressNotWordAligned(mutexAddress)) + { + return KernelResult.InvalidAddress; + } + + KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); + + return currentProcess.AddressArbiter.WaitProcessWideKeyAtomic( + mutexAddress, + condVarAddress, + handle, + timeout); + } + + public KernelResult SignalProcessWideKey64(ulong address, int count) + { + return SignalProcessWideKey(address, count); + } + + private KernelResult SignalProcessWideKey(ulong address, int count) + { + KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); + + currentProcess.AddressArbiter.SignalProcessWideKey(address, count); + + return KernelResult.Success; + } + + public KernelResult WaitForAddress64(ulong address, ArbitrationType type, int value, long timeout) + { + return WaitForAddress(address, type, value, timeout); + } + + private KernelResult WaitForAddress(ulong address, ArbitrationType type, int value, long timeout) + { + if (IsPointingInsideKernel(address)) + { + return KernelResult.InvalidMemState; + } + + if (IsAddressNotWordAligned(address)) + { + return KernelResult.InvalidAddress; + } + + KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); + + KernelResult result; + + switch (type) + { + case ArbitrationType.WaitIfLessThan: + result = currentProcess.AddressArbiter.WaitForAddressIfLessThan(address, value, false, timeout); + break; + + case ArbitrationType.DecrementAndWaitIfLessThan: + result = currentProcess.AddressArbiter.WaitForAddressIfLessThan(address, value, true, timeout); + break; + + case ArbitrationType.WaitIfEqual: + result = currentProcess.AddressArbiter.WaitForAddressIfEqual(address, value, timeout); + break; + + default: + result = KernelResult.InvalidEnumValue; + break; + } + + return result; + } + + public KernelResult SignalToAddress64(ulong address, SignalType type, int value, int count) + { + return SignalToAddress(address, type, value, count); + } + + private KernelResult SignalToAddress(ulong address, SignalType type, int value, int count) + { + if (IsPointingInsideKernel(address)) + { + return KernelResult.InvalidMemState; + } + + if (IsAddressNotWordAligned(address)) + { + return KernelResult.InvalidAddress; + } + + KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); + + KernelResult result; + + switch (type) + { + case SignalType.Signal: + result = currentProcess.AddressArbiter.Signal(address, count); + break; + + case SignalType.SignalAndIncrementIfEqual: + result = currentProcess.AddressArbiter.SignalAndIncrementIfEqual(address, value, count); + break; + + case SignalType.SignalAndModifyIfEqual: + result = currentProcess.AddressArbiter.SignalAndModifyIfEqual(address, value, count); + break; + + default: + result = KernelResult.InvalidEnumValue; + break; + } + + return result; + } + + private bool IsPointingInsideKernel(ulong address) + { + return (address + 0x1000000000) < 0xffffff000; + } + + private bool IsAddressNotWordAligned(ulong address) + { + return (address & 3) != 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/SvcHandler.cs b/Ryujinx.HLE/HOS/Kernel/SvcHandler.cs deleted file mode 100644 index 78a0cc851e..0000000000 --- a/Ryujinx.HLE/HOS/Kernel/SvcHandler.cs +++ /dev/null @@ -1,122 +0,0 @@ -using ChocolArm64.Events; -using ChocolArm64.Memory; -using ChocolArm64.State; -using Ryujinx.HLE.HOS.Ipc; -using Ryujinx.Common.Logging; -using System; -using System.Collections.Generic; - -namespace Ryujinx.HLE.HOS.Kernel -{ - partial class SvcHandler - { - private delegate void SvcFunc(CpuThreadState threadState); - - private Dictionary _svcFuncs; - - private Switch _device; - private KProcess _process; - private Horizon _system; - private MemoryManager _memory; - - private struct HleIpcMessage - { - public KThread Thread { get; private set; } - public KSession Session { get; private set; } - public IpcMessage Message { get; private set; } - public long MessagePtr { get; private set; } - - public HleIpcMessage( - KThread thread, - KSession session, - IpcMessage message, - long messagePtr) - { - Thread = thread; - Session = session; - Message = message; - MessagePtr = messagePtr; - } - } - - public SvcHandler(Switch device, KProcess process) - { - _svcFuncs = new Dictionary - { - { 0x01, SvcSetHeapSize }, - { 0x03, SvcSetMemoryAttribute }, - { 0x04, SvcMapMemory }, - { 0x05, SvcUnmapMemory }, - { 0x06, SvcQueryMemory }, - { 0x07, SvcExitProcess }, - { 0x08, CreateThread64 }, - { 0x09, SvcStartThread }, - { 0x0a, SvcExitThread }, - { 0x0b, SvcSleepThread }, - { 0x0c, SvcGetThreadPriority }, - { 0x0d, SvcSetThreadPriority }, - { 0x0e, SvcGetThreadCoreMask }, - { 0x0f, SetThreadCoreMask64 }, - { 0x10, SvcGetCurrentProcessorNumber }, - { 0x11, SignalEvent64 }, - { 0x12, ClearEvent64 }, - { 0x13, SvcMapSharedMemory }, - { 0x14, SvcUnmapSharedMemory }, - { 0x15, SvcCreateTransferMemory }, - { 0x16, SvcCloseHandle }, - { 0x17, ResetSignal64 }, - { 0x18, SvcWaitSynchronization }, - { 0x19, SvcCancelSynchronization }, - { 0x1a, SvcArbitrateLock }, - { 0x1b, SvcArbitrateUnlock }, - { 0x1c, SvcWaitProcessWideKeyAtomic }, - { 0x1d, SvcSignalProcessWideKey }, - { 0x1e, SvcGetSystemTick }, - { 0x1f, SvcConnectToNamedPort }, - { 0x21, SvcSendSyncRequest }, - { 0x22, SvcSendSyncRequestWithUserBuffer }, - { 0x24, GetProcessId64 }, - { 0x25, SvcGetThreadId }, - { 0x26, SvcBreak }, - { 0x27, SvcOutputDebugString }, - { 0x29, GetInfo64 }, - { 0x2c, SvcMapPhysicalMemory }, - { 0x2d, SvcUnmapPhysicalMemory }, - { 0x32, SvcSetThreadActivity }, - { 0x33, SvcGetThreadContext3 }, - { 0x34, SvcWaitForAddress }, - { 0x35, SvcSignalToAddress }, - { 0x45, CreateEvent64 }, - { 0x65, GetProcessList64 }, - { 0x6f, GetSystemInfo64 }, - { 0x70, CreatePort64 }, - { 0x71, ManageNamedPort64 } - }; - - _device = device; - _process = process; - _system = device.System; - _memory = process.CpuMemory; - } - - public void SvcCall(object sender, InstExceptionEventArgs e) - { - CpuThreadState threadState = (CpuThreadState)sender; - - if (_svcFuncs.TryGetValue(e.Id, out SvcFunc func)) - { - Logger.PrintDebug(LogClass.KernelSvc, $"{func.Method.Name} called."); - - func(threadState); - - Logger.PrintDebug(LogClass.KernelSvc, $"{func.Method.Name} ended."); - } - else - { - //Process.PrintStackTrace(ThreadState); - - throw new NotImplementedException($"0x{e.Id:x4}"); - } - } - } -} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/SvcMemory.cs b/Ryujinx.HLE/HOS/Kernel/SvcMemory.cs deleted file mode 100644 index c99c1e9859..0000000000 --- a/Ryujinx.HLE/HOS/Kernel/SvcMemory.cs +++ /dev/null @@ -1,581 +0,0 @@ -using ChocolArm64.State; -using Ryujinx.Common.Logging; - -using static Ryujinx.HLE.HOS.ErrorCode; - -namespace Ryujinx.HLE.HOS.Kernel -{ - partial class SvcHandler - { - private void SvcSetHeapSize(CpuThreadState threadState) - { - ulong size = threadState.X1; - - if ((size & 0xfffffffe001fffff) != 0) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Heap size 0x{size:x16} is not aligned!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize); - - return; - } - - KernelResult result = _process.MemoryManager.SetHeapSize(size, out ulong position); - - threadState.X0 = (ulong)result; - - if (result == KernelResult.Success) - { - threadState.X1 = position; - } - else - { - Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error \"{result}\"."); - } - } - - private void SvcSetMemoryAttribute(CpuThreadState threadState) - { - ulong position = threadState.X0; - ulong size = threadState.X1; - - if (!PageAligned(position)) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Address 0x{position:x16} is not page aligned!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - if (!PageAligned(size) || size == 0) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Size 0x{size:x16} is not page aligned or is zero!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize); - - return; - } - - MemoryAttribute attributeMask = (MemoryAttribute)threadState.X2; - MemoryAttribute attributeValue = (MemoryAttribute)threadState.X3; - - MemoryAttribute attributes = attributeMask | attributeValue; - - if (attributes != attributeMask || - (attributes | MemoryAttribute.Uncached) != MemoryAttribute.Uncached) - { - Logger.PrintWarning(LogClass.KernelSvc, "Invalid memory attributes!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMaskValue); - - return; - } - - KernelResult result = _process.MemoryManager.SetMemoryAttribute( - position, - size, - attributeMask, - attributeValue); - - if (result != KernelResult.Success) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error \"{result}\"."); - } - else - { - _memory.StopObservingRegion((long)position, (long)size); - } - - threadState.X0 = (ulong)result; - } - - private void SvcMapMemory(CpuThreadState threadState) - { - ulong dst = threadState.X0; - ulong src = threadState.X1; - ulong size = threadState.X2; - - if (!PageAligned(src | dst)) - { - Logger.PrintWarning(LogClass.KernelSvc, "Addresses are not page aligned!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - if (!PageAligned(size) || size == 0) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Size 0x{size:x16} is not page aligned or is zero!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize); - - return; - } - - if (src + size <= src || dst + size <= dst) - { - Logger.PrintWarning(LogClass.KernelSvc, "Addresses outside of range!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - if (!currentProcess.MemoryManager.InsideAddrSpace(src, size)) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Src address 0x{src:x16} out of range!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - if (currentProcess.MemoryManager.OutsideStackRegion(dst, size) || - currentProcess.MemoryManager.InsideHeapRegion (dst, size) || - currentProcess.MemoryManager.InsideAliasRegion (dst, size)) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Dst address 0x{dst:x16} out of range!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange); - - return; - } - - KernelResult result = _process.MemoryManager.Map(dst, src, size); - - if (result != KernelResult.Success) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!"); - } - - threadState.X0 = (ulong)result; - } - - private void SvcUnmapMemory(CpuThreadState threadState) - { - ulong dst = threadState.X0; - ulong src = threadState.X1; - ulong size = threadState.X2; - - if (!PageAligned(src | dst)) - { - Logger.PrintWarning(LogClass.KernelSvc, "Addresses are not page aligned!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - if (!PageAligned(size) || size == 0) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Size 0x{size:x16} is not page aligned or is zero!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize); - - return; - } - - if (src + size <= src || dst + size <= dst) - { - Logger.PrintWarning(LogClass.KernelSvc, "Addresses outside of range!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - if (!currentProcess.MemoryManager.InsideAddrSpace(src, size)) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Src address 0x{src:x16} out of range!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - if (currentProcess.MemoryManager.OutsideStackRegion(dst, size) || - currentProcess.MemoryManager.InsideHeapRegion (dst, size) || - currentProcess.MemoryManager.InsideAliasRegion (dst, size)) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Dst address 0x{dst:x16} out of range!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange); - - return; - } - - KernelResult result = _process.MemoryManager.Unmap(dst, src, size); - - if (result != KernelResult.Success) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!"); - } - - threadState.X0 = (ulong)result; - } - - private void SvcQueryMemory(CpuThreadState threadState) - { - long infoPtr = (long)threadState.X0; - ulong position = threadState.X2; - - KMemoryInfo blkInfo = _process.MemoryManager.QueryMemory(position); - - _memory.WriteUInt64(infoPtr + 0x00, blkInfo.Address); - _memory.WriteUInt64(infoPtr + 0x08, blkInfo.Size); - _memory.WriteInt32 (infoPtr + 0x10, (int)blkInfo.State & 0xff); - _memory.WriteInt32 (infoPtr + 0x14, (int)blkInfo.Attribute); - _memory.WriteInt32 (infoPtr + 0x18, (int)blkInfo.Permission); - _memory.WriteInt32 (infoPtr + 0x1c, blkInfo.IpcRefCount); - _memory.WriteInt32 (infoPtr + 0x20, blkInfo.DeviceRefCount); - _memory.WriteInt32 (infoPtr + 0x24, 0); - - threadState.X0 = 0; - threadState.X1 = 0; - } - - private void SvcMapSharedMemory(CpuThreadState threadState) - { - int handle = (int)threadState.X0; - ulong address = threadState.X1; - ulong size = threadState.X2; - - if (!PageAligned(address)) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Address 0x{address:x16} is not page aligned!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - if (!PageAligned(size) || size == 0) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Size 0x{size:x16} is not page aligned or is zero!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize); - - return; - } - - if (address + size <= address) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{address:x16} / size 0x{size:x16}!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - MemoryPermission permission = (MemoryPermission)threadState.X3; - - if ((permission | MemoryPermission.Write) != MemoryPermission.ReadAndWrite) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Invalid permission {permission}!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidPermission); - - return; - } - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - KSharedMemory sharedMemory = currentProcess.HandleTable.GetObject(handle); - - if (sharedMemory == null) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Invalid shared memory handle 0x{handle:x8}!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - - return; - } - - if (currentProcess.MemoryManager.IsInvalidRegion (address, size) || - currentProcess.MemoryManager.InsideHeapRegion (address, size) || - currentProcess.MemoryManager.InsideAliasRegion(address, size)) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Address 0x{address:x16} out of range!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - KernelResult result = sharedMemory.MapIntoProcess( - currentProcess.MemoryManager, - address, - size, - currentProcess, - permission); - - if (result != KernelResult.Success) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error \"{result}\"."); - } - - threadState.X0 = (ulong)result; - } - - private void SvcUnmapSharedMemory(CpuThreadState threadState) - { - int handle = (int)threadState.X0; - ulong address = threadState.X1; - ulong size = threadState.X2; - - if (!PageAligned(address)) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Address 0x{address:x16} is not page aligned!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - if (!PageAligned(size) || size == 0) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Size 0x{size:x16} is not page aligned or is zero!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize); - - return; - } - - if (address + size <= address) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{address:x16} / size 0x{size:x16}!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - KSharedMemory sharedMemory = currentProcess.HandleTable.GetObject(handle); - - if (sharedMemory == null) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Invalid shared memory handle 0x{handle:x8}!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - - return; - } - - if (currentProcess.MemoryManager.IsInvalidRegion (address, size) || - currentProcess.MemoryManager.InsideHeapRegion (address, size) || - currentProcess.MemoryManager.InsideAliasRegion(address, size)) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Address 0x{address:x16} out of range!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - KernelResult result = sharedMemory.UnmapFromProcess( - currentProcess.MemoryManager, - address, - size, - currentProcess); - - if (result != KernelResult.Success) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error \"{result}\"."); - } - - threadState.X0 = (ulong)result; - } - - private void SvcCreateTransferMemory(CpuThreadState threadState) - { - ulong address = threadState.X1; - ulong size = threadState.X2; - - if (!PageAligned(address)) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Address 0x{address:x16} is not page aligned!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - if (!PageAligned(size) || size == 0) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Size 0x{size:x16} is not page aligned or is zero!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - if (address + size <= address) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{address:x16} / size 0x{size:x16}!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - MemoryPermission permission = (MemoryPermission)threadState.X3; - - if (permission > MemoryPermission.ReadAndWrite || permission == MemoryPermission.Write) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Invalid permission {permission}!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidPermission); - - return; - } - - _process.MemoryManager.ReserveTransferMemory(address, size, permission); - - KTransferMemory transferMemory = new KTransferMemory(address, size); - - KernelResult result = _process.HandleTable.GenerateHandle(transferMemory, out int handle); - - threadState.X0 = (uint)result; - threadState.X1 = (ulong)handle; - } - - private void SvcMapPhysicalMemory(CpuThreadState threadState) - { - ulong address = threadState.X0; - ulong size = threadState.X1; - - if (!PageAligned(address)) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Address 0x{address:x16} is not page aligned!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - if (!PageAligned(size) || size == 0) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Size 0x{size:x16} is not page aligned or is zero!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize); - - return; - } - - if (address + size <= address) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{address:x16} / size 0x{size:x16}!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - if ((currentProcess.PersonalMmHeapPagesCount & 0xfffffffffffff) == 0) - { - Logger.PrintWarning(LogClass.KernelSvc, $"System resource size is zero."); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidState); - - return; - } - - if (!currentProcess.MemoryManager.InsideAddrSpace (address, size) || - currentProcess.MemoryManager.OutsideAliasRegion(address, size)) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Invalid address {address:x16}."); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - KernelResult result = _process.MemoryManager.MapPhysicalMemory(address, size); - - if (result != KernelResult.Success) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!"); - } - - threadState.X0 = (ulong)result; - } - - private void SvcUnmapPhysicalMemory(CpuThreadState threadState) - { - ulong address = threadState.X0; - ulong size = threadState.X1; - - if (!PageAligned(address)) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Address 0x{address:x16} is not page aligned!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - if (!PageAligned(size) || size == 0) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Size 0x{size:x16} is not page aligned or is zero!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize); - - return; - } - - if (address + size <= address) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{address:x16} / size 0x{size:x16}!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - if ((currentProcess.PersonalMmHeapPagesCount & 0xfffffffffffff) == 0) - { - Logger.PrintWarning(LogClass.KernelSvc, $"System resource size is zero."); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidState); - - return; - } - - if (!currentProcess.MemoryManager.InsideAddrSpace (address, size) || - currentProcess.MemoryManager.OutsideAliasRegion(address, size)) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Invalid address {address:x16}."); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - KernelResult result = _process.MemoryManager.UnmapPhysicalMemory(address, size); - - if (result != KernelResult.Success) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!"); - } - - threadState.X0 = (ulong)result; - } - - private static bool PageAligned(ulong position) - { - return (position & (KMemoryManager.PageSize - 1)) == 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/SvcThread.cs b/Ryujinx.HLE/HOS/Kernel/SvcThread.cs deleted file mode 100644 index 0121303d90..0000000000 --- a/Ryujinx.HLE/HOS/Kernel/SvcThread.cs +++ /dev/null @@ -1,464 +0,0 @@ -using ChocolArm64.State; -using Ryujinx.Common.Logging; - -using static Ryujinx.HLE.HOS.ErrorCode; - -namespace Ryujinx.HLE.HOS.Kernel -{ - partial class SvcHandler - { - private void CreateThread64(CpuThreadState threadState) - { - ulong entrypoint = threadState.X1; - ulong argsPtr = threadState.X2; - ulong stackTop = threadState.X3; - int priority = (int)threadState.X4; - int cpuCore = (int)threadState.X5; - - KernelResult result = CreateThread(entrypoint, argsPtr, stackTop, priority, cpuCore, out int handle); - - threadState.X0 = (ulong)result; - threadState.X1 = (ulong)handle; - } - - private KernelResult CreateThread( - ulong entrypoint, - ulong argsPtr, - ulong stackTop, - int priority, - int cpuCore, - out int handle) - { - handle = 0; - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - if (cpuCore == -2) - { - cpuCore = currentProcess.DefaultCpuCore; - } - - if ((uint)cpuCore >= KScheduler.CpuCoresCount || !currentProcess.IsCpuCoreAllowed(cpuCore)) - { - return KernelResult.InvalidCpuCore; - } - - if ((uint)priority >= KScheduler.PrioritiesCount || !currentProcess.IsPriorityAllowed(priority)) - { - return KernelResult.InvalidPriority; - } - - long timeout = KTimeManager.ConvertMillisecondsToNanoseconds(100); - - if (currentProcess.ResourceLimit != null && - !currentProcess.ResourceLimit.Reserve(LimitableResource.Thread, 1, timeout)) - { - return KernelResult.ResLimitExceeded; - } - - KThread thread = new KThread(_system); - - KernelResult result = currentProcess.InitializeThread( - thread, - entrypoint, - argsPtr, - stackTop, - priority, - cpuCore); - - if (result != KernelResult.Success) - { - currentProcess.ResourceLimit?.Release(LimitableResource.Thread, 1); - - return result; - } - - result = _process.HandleTable.GenerateHandle(thread, out handle); - - if (result != KernelResult.Success) - { - thread.Terminate(); - - currentProcess.ResourceLimit?.Release(LimitableResource.Thread, 1); - } - - return result; - } - - private void SvcStartThread(CpuThreadState threadState) - { - int handle = (int)threadState.X0; - - KThread thread = _process.HandleTable.GetObject(handle); - - if (thread != null) - { - KernelResult result = thread.Start(); - - if (result != KernelResult.Success) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error \"{result}\"."); - } - - threadState.X0 = (ulong)result; - } - else - { - Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{handle:x8}!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - } - } - - private void SvcExitThread(CpuThreadState threadState) - { - KThread currentThread = _system.Scheduler.GetCurrentThread(); - - _system.Scheduler.ExitThread(currentThread); - - currentThread.Exit(); - } - - private void SvcSleepThread(CpuThreadState threadState) - { - long timeout = (long)threadState.X0; - - Logger.PrintDebug(LogClass.KernelSvc, "Timeout = 0x" + timeout.ToString("x16")); - - KThread currentThread = _system.Scheduler.GetCurrentThread(); - - if (timeout < 1) - { - switch (timeout) - { - case 0: currentThread.Yield(); break; - case -1: currentThread.YieldWithLoadBalancing(); break; - case -2: currentThread.YieldAndWaitForLoadBalancing(); break; - } - } - else - { - currentThread.Sleep(timeout); - - threadState.X0 = 0; - } - } - - private void SvcGetThreadPriority(CpuThreadState threadState) - { - int handle = (int)threadState.X1; - - KThread thread = _process.HandleTable.GetKThread(handle); - - if (thread != null) - { - threadState.X0 = 0; - threadState.X1 = (ulong)thread.DynamicPriority; - } - else - { - Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{handle:x8}!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - } - } - - private void SvcSetThreadPriority(CpuThreadState threadState) - { - int handle = (int)threadState.X0; - int priority = (int)threadState.X1; - - Logger.PrintDebug(LogClass.KernelSvc, - "Handle = 0x" + handle .ToString("x8") + ", " + - "Priority = 0x" + priority.ToString("x8")); - - //TODO: NPDM check. - - KThread thread = _process.HandleTable.GetKThread(handle); - - if (thread == null) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{handle:x8}!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - - return; - } - - thread.SetPriority(priority); - - threadState.X0 = 0; - } - - private void SvcGetThreadCoreMask(CpuThreadState threadState) - { - int handle = (int)threadState.X2; - - Logger.PrintDebug(LogClass.KernelSvc, "Handle = 0x" + handle.ToString("x8")); - - KThread thread = _process.HandleTable.GetKThread(handle); - - if (thread != null) - { - threadState.X0 = 0; - threadState.X1 = (ulong)thread.PreferredCore; - threadState.X2 = (ulong)thread.AffinityMask; - } - else - { - Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{handle:x8}!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - } - } - - private void SetThreadCoreMask64(CpuThreadState threadState) - { - int handle = (int)threadState.X0; - int preferredCore = (int)threadState.X1; - long affinityMask = (long)threadState.X2; - - Logger.PrintDebug(LogClass.KernelSvc, - "Handle = 0x" + handle .ToString("x8") + ", " + - "PreferredCore = 0x" + preferredCore.ToString("x8") + ", " + - "AffinityMask = 0x" + affinityMask .ToString("x16")); - - KernelResult result = SetThreadCoreMask(handle, preferredCore, affinityMask); - - if (result != KernelResult.Success) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error \"{result}\"."); - } - - threadState.X0 = (ulong)result; - } - - private KernelResult SetThreadCoreMask(int handle, int preferredCore, long affinityMask) - { - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - if (preferredCore == -2) - { - preferredCore = currentProcess.DefaultCpuCore; - - affinityMask = 1 << preferredCore; - } - else - { - if ((currentProcess.Capabilities.AllowedCpuCoresMask | affinityMask) != - currentProcess.Capabilities.AllowedCpuCoresMask) - { - return KernelResult.InvalidCpuCore; - } - - if (affinityMask == 0) - { - return KernelResult.InvalidCombination; - } - - if ((uint)preferredCore > 3) - { - if ((preferredCore | 2) != -1) - { - return KernelResult.InvalidCpuCore; - } - } - else if ((affinityMask & (1 << preferredCore)) == 0) - { - return KernelResult.InvalidCombination; - } - } - - KThread thread = _process.HandleTable.GetKThread(handle); - - if (thread == null) - { - return KernelResult.InvalidHandle; - } - - return thread.SetCoreAndAffinityMask(preferredCore, affinityMask); - } - - private void SvcGetCurrentProcessorNumber(CpuThreadState threadState) - { - threadState.X0 = (ulong)_system.Scheduler.GetCurrentThread().CurrentCore; - } - - private void SvcGetThreadId(CpuThreadState threadState) - { - int handle = (int)threadState.X1; - - KThread thread = _process.HandleTable.GetKThread(handle); - - if (thread != null) - { - threadState.X0 = 0; - threadState.X1 = (ulong)thread.ThreadUid; - } - else - { - Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{handle:x8}!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - } - } - - private void SvcSetThreadActivity(CpuThreadState threadState) - { - int handle = (int)threadState.X0; - bool pause = (int)threadState.X1 == 1; - - KThread thread = _process.HandleTable.GetObject(handle); - - if (thread == null) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{handle:x8}!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - - return; - } - - if (thread.Owner != _system.Scheduler.GetCurrentProcess()) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread, it belongs to another process."); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - - return; - } - - if (thread == _system.Scheduler.GetCurrentThread()) - { - Logger.PrintWarning(LogClass.KernelSvc, "Invalid thread, current thread is not accepted."); - - threadState.X0 = (ulong)KernelResult.InvalidThread; - - return; - } - - long result = thread.SetActivity(pause); - - if (result != 0) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!"); - } - - threadState.X0 = (ulong)result; - } - - private void SvcGetThreadContext3(CpuThreadState threadState) - { - long position = (long)threadState.X0; - int handle = (int)threadState.X1; - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - KThread currentThread = _system.Scheduler.GetCurrentThread(); - - KThread thread = _process.HandleTable.GetObject(handle); - - if (thread == null) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{handle:x8}!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - - return; - } - - if (thread.Owner != currentProcess) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread, it belongs to another process."); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - - return; - } - - if (currentThread == thread) - { - Logger.PrintWarning(LogClass.KernelSvc, "Invalid thread, current thread is not accepted."); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidThread); - - return; - } - - _memory.WriteUInt64(position + 0x0, thread.Context.ThreadState.X0); - _memory.WriteUInt64(position + 0x8, thread.Context.ThreadState.X1); - _memory.WriteUInt64(position + 0x10, thread.Context.ThreadState.X2); - _memory.WriteUInt64(position + 0x18, thread.Context.ThreadState.X3); - _memory.WriteUInt64(position + 0x20, thread.Context.ThreadState.X4); - _memory.WriteUInt64(position + 0x28, thread.Context.ThreadState.X5); - _memory.WriteUInt64(position + 0x30, thread.Context.ThreadState.X6); - _memory.WriteUInt64(position + 0x38, thread.Context.ThreadState.X7); - _memory.WriteUInt64(position + 0x40, thread.Context.ThreadState.X8); - _memory.WriteUInt64(position + 0x48, thread.Context.ThreadState.X9); - _memory.WriteUInt64(position + 0x50, thread.Context.ThreadState.X10); - _memory.WriteUInt64(position + 0x58, thread.Context.ThreadState.X11); - _memory.WriteUInt64(position + 0x60, thread.Context.ThreadState.X12); - _memory.WriteUInt64(position + 0x68, thread.Context.ThreadState.X13); - _memory.WriteUInt64(position + 0x70, thread.Context.ThreadState.X14); - _memory.WriteUInt64(position + 0x78, thread.Context.ThreadState.X15); - _memory.WriteUInt64(position + 0x80, thread.Context.ThreadState.X16); - _memory.WriteUInt64(position + 0x88, thread.Context.ThreadState.X17); - _memory.WriteUInt64(position + 0x90, thread.Context.ThreadState.X18); - _memory.WriteUInt64(position + 0x98, thread.Context.ThreadState.X19); - _memory.WriteUInt64(position + 0xa0, thread.Context.ThreadState.X20); - _memory.WriteUInt64(position + 0xa8, thread.Context.ThreadState.X21); - _memory.WriteUInt64(position + 0xb0, thread.Context.ThreadState.X22); - _memory.WriteUInt64(position + 0xb8, thread.Context.ThreadState.X23); - _memory.WriteUInt64(position + 0xc0, thread.Context.ThreadState.X24); - _memory.WriteUInt64(position + 0xc8, thread.Context.ThreadState.X25); - _memory.WriteUInt64(position + 0xd0, thread.Context.ThreadState.X26); - _memory.WriteUInt64(position + 0xd8, thread.Context.ThreadState.X27); - _memory.WriteUInt64(position + 0xe0, thread.Context.ThreadState.X28); - _memory.WriteUInt64(position + 0xe8, thread.Context.ThreadState.X29); - _memory.WriteUInt64(position + 0xf0, thread.Context.ThreadState.X30); - _memory.WriteUInt64(position + 0xf8, thread.Context.ThreadState.X31); - - _memory.WriteInt64(position + 0x100, thread.LastPc); - - _memory.WriteUInt64(position + 0x108, (ulong)thread.Context.ThreadState.Psr); - - _memory.WriteVector128(position + 0x110, thread.Context.ThreadState.V0); - _memory.WriteVector128(position + 0x120, thread.Context.ThreadState.V1); - _memory.WriteVector128(position + 0x130, thread.Context.ThreadState.V2); - _memory.WriteVector128(position + 0x140, thread.Context.ThreadState.V3); - _memory.WriteVector128(position + 0x150, thread.Context.ThreadState.V4); - _memory.WriteVector128(position + 0x160, thread.Context.ThreadState.V5); - _memory.WriteVector128(position + 0x170, thread.Context.ThreadState.V6); - _memory.WriteVector128(position + 0x180, thread.Context.ThreadState.V7); - _memory.WriteVector128(position + 0x190, thread.Context.ThreadState.V8); - _memory.WriteVector128(position + 0x1a0, thread.Context.ThreadState.V9); - _memory.WriteVector128(position + 0x1b0, thread.Context.ThreadState.V10); - _memory.WriteVector128(position + 0x1c0, thread.Context.ThreadState.V11); - _memory.WriteVector128(position + 0x1d0, thread.Context.ThreadState.V12); - _memory.WriteVector128(position + 0x1e0, thread.Context.ThreadState.V13); - _memory.WriteVector128(position + 0x1f0, thread.Context.ThreadState.V14); - _memory.WriteVector128(position + 0x200, thread.Context.ThreadState.V15); - _memory.WriteVector128(position + 0x210, thread.Context.ThreadState.V16); - _memory.WriteVector128(position + 0x220, thread.Context.ThreadState.V17); - _memory.WriteVector128(position + 0x230, thread.Context.ThreadState.V18); - _memory.WriteVector128(position + 0x240, thread.Context.ThreadState.V19); - _memory.WriteVector128(position + 0x250, thread.Context.ThreadState.V20); - _memory.WriteVector128(position + 0x260, thread.Context.ThreadState.V21); - _memory.WriteVector128(position + 0x270, thread.Context.ThreadState.V22); - _memory.WriteVector128(position + 0x280, thread.Context.ThreadState.V23); - _memory.WriteVector128(position + 0x290, thread.Context.ThreadState.V24); - _memory.WriteVector128(position + 0x2a0, thread.Context.ThreadState.V25); - _memory.WriteVector128(position + 0x2b0, thread.Context.ThreadState.V26); - _memory.WriteVector128(position + 0x2c0, thread.Context.ThreadState.V27); - _memory.WriteVector128(position + 0x2d0, thread.Context.ThreadState.V28); - _memory.WriteVector128(position + 0x2e0, thread.Context.ThreadState.V29); - _memory.WriteVector128(position + 0x2f0, thread.Context.ThreadState.V30); - _memory.WriteVector128(position + 0x300, thread.Context.ThreadState.V31); - - _memory.WriteInt32(position + 0x310, thread.Context.ThreadState.Fpcr); - _memory.WriteInt32(position + 0x314, thread.Context.ThreadState.Fpsr); - _memory.WriteInt64(position + 0x318, thread.Context.ThreadState.Tpidr); - - threadState.X0 = 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/SvcThreadSync.cs b/Ryujinx.HLE/HOS/Kernel/SvcThreadSync.cs deleted file mode 100644 index 11cfffe9b2..0000000000 --- a/Ryujinx.HLE/HOS/Kernel/SvcThreadSync.cs +++ /dev/null @@ -1,373 +0,0 @@ -using ChocolArm64.State; -using Ryujinx.Common.Logging; -using System.Collections.Generic; - -using static Ryujinx.HLE.HOS.ErrorCode; - -namespace Ryujinx.HLE.HOS.Kernel -{ - partial class SvcHandler - { - private void SvcWaitSynchronization(CpuThreadState threadState) - { - long handlesPtr = (long)threadState.X1; - int handlesCount = (int)threadState.X2; - long timeout = (long)threadState.X3; - - Logger.PrintDebug(LogClass.KernelSvc, - "HandlesPtr = 0x" + handlesPtr .ToString("x16") + ", " + - "HandlesCount = 0x" + handlesCount.ToString("x8") + ", " + - "Timeout = 0x" + timeout .ToString("x16")); - - if ((uint)handlesCount > 0x40) - { - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.CountOutOfRange); - - return; - } - - List syncObjs = new List(); - - for (int index = 0; index < handlesCount; index++) - { - int handle = _memory.ReadInt32(handlesPtr + index * 4); - - Logger.PrintDebug(LogClass.KernelSvc, $"Sync handle 0x{handle:x8}"); - - KSynchronizationObject syncObj = _process.HandleTable.GetObject(handle); - - if (syncObj == null) - { - break; - } - - syncObjs.Add(syncObj); - } - - int hndIndex = (int)threadState.X1; - - ulong high = threadState.X1 & (0xffffffffUL << 32); - - long result = _system.Synchronization.WaitFor(syncObjs.ToArray(), timeout, ref hndIndex); - - if (result != 0) - { - if (result == MakeError(ErrorModule.Kernel, KernelErr.Timeout) || - result == MakeError(ErrorModule.Kernel, KernelErr.Cancelled)) - { - Logger.PrintDebug(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!"); - } - else - { - Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!"); - } - } - - threadState.X0 = (ulong)result; - threadState.X1 = (uint)hndIndex | high; - } - - private void SvcCancelSynchronization(CpuThreadState threadState) - { - int threadHandle = (int)threadState.X0; - - Logger.PrintDebug(LogClass.KernelSvc, "ThreadHandle = 0x" + threadHandle.ToString("x8")); - - KThread thread = _process.HandleTable.GetKThread(threadHandle); - - if (thread == null) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{threadHandle:x8}!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - - return; - } - - thread.CancelSynchronization(); - - threadState.X0 = 0; - } - - private void SvcArbitrateLock(CpuThreadState threadState) - { - int ownerHandle = (int)threadState.X0; - long mutexAddress = (long)threadState.X1; - int requesterHandle = (int)threadState.X2; - - Logger.PrintDebug(LogClass.KernelSvc, - "OwnerHandle = 0x" + ownerHandle .ToString("x8") + ", " + - "MutexAddress = 0x" + mutexAddress .ToString("x16") + ", " + - "RequesterHandle = 0x" + requesterHandle.ToString("x8")); - - if (IsPointingInsideKernel(mutexAddress)) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Invalid mutex address 0x{mutexAddress:x16}!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - if (IsAddressNotWordAligned(mutexAddress)) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Unaligned mutex address 0x{mutexAddress:x16}!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - long result = currentProcess.AddressArbiter.ArbitrateLock(ownerHandle, mutexAddress, requesterHandle); - - if (result != 0) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!"); - } - - threadState.X0 = (ulong)result; - } - - private void SvcArbitrateUnlock(CpuThreadState threadState) - { - long mutexAddress = (long)threadState.X0; - - Logger.PrintDebug(LogClass.KernelSvc, "MutexAddress = 0x" + mutexAddress.ToString("x16")); - - if (IsPointingInsideKernel(mutexAddress)) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Invalid mutex address 0x{mutexAddress:x16}!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - if (IsAddressNotWordAligned(mutexAddress)) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Unaligned mutex address 0x{mutexAddress:x16}!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - long result = currentProcess.AddressArbiter.ArbitrateUnlock(mutexAddress); - - if (result != 0) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!"); - } - - threadState.X0 = (ulong)result; - } - - private void SvcWaitProcessWideKeyAtomic(CpuThreadState threadState) - { - long mutexAddress = (long)threadState.X0; - long condVarAddress = (long)threadState.X1; - int threadHandle = (int)threadState.X2; - long timeout = (long)threadState.X3; - - Logger.PrintDebug(LogClass.KernelSvc, - "MutexAddress = 0x" + mutexAddress .ToString("x16") + ", " + - "CondVarAddress = 0x" + condVarAddress.ToString("x16") + ", " + - "ThreadHandle = 0x" + threadHandle .ToString("x8") + ", " + - "Timeout = 0x" + timeout .ToString("x16")); - - if (IsPointingInsideKernel(mutexAddress)) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Invalid mutex address 0x{mutexAddress:x16}!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - if (IsAddressNotWordAligned(mutexAddress)) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Unaligned mutex address 0x{mutexAddress:x16}!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - long result = currentProcess.AddressArbiter.WaitProcessWideKeyAtomic( - mutexAddress, - condVarAddress, - threadHandle, - timeout); - - if (result != 0) - { - if (result == MakeError(ErrorModule.Kernel, KernelErr.Timeout)) - { - Logger.PrintDebug(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!"); - } - else - { - Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!"); - } - } - - threadState.X0 = (ulong)result; - } - - private void SvcSignalProcessWideKey(CpuThreadState threadState) - { - long address = (long)threadState.X0; - int count = (int)threadState.X1; - - Logger.PrintDebug(LogClass.KernelSvc, - "Address = 0x" + address.ToString("x16") + ", " + - "Count = 0x" + count .ToString("x8")); - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - currentProcess.AddressArbiter.SignalProcessWideKey(address, count); - - threadState.X0 = 0; - } - - private void SvcWaitForAddress(CpuThreadState threadState) - { - long address = (long)threadState.X0; - ArbitrationType type = (ArbitrationType)threadState.X1; - int value = (int)threadState.X2; - long timeout = (long)threadState.X3; - - Logger.PrintDebug(LogClass.KernelSvc, - "Address = 0x" + address.ToString("x16") + ", " + - "Type = " + type .ToString() + ", " + - "Value = 0x" + value .ToString("x8") + ", " + - "Timeout = 0x" + timeout.ToString("x16")); - - if (IsPointingInsideKernel(address)) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Invalid address 0x{address:x16}!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - if (IsAddressNotWordAligned(address)) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Unaligned address 0x{address:x16}!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - long result; - - switch (type) - { - case ArbitrationType.WaitIfLessThan: - result = currentProcess.AddressArbiter.WaitForAddressIfLessThan(address, value, false, timeout); - break; - - case ArbitrationType.DecrementAndWaitIfLessThan: - result = currentProcess.AddressArbiter.WaitForAddressIfLessThan(address, value, true, timeout); - break; - - case ArbitrationType.WaitIfEqual: - result = currentProcess.AddressArbiter.WaitForAddressIfEqual(address, value, timeout); - break; - - default: - result = MakeError(ErrorModule.Kernel, KernelErr.InvalidEnumValue); - break; - } - - if (result != 0) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!"); - } - - threadState.X0 = (ulong)result; - } - - private void SvcSignalToAddress(CpuThreadState threadState) - { - long address = (long)threadState.X0; - SignalType type = (SignalType)threadState.X1; - int value = (int)threadState.X2; - int count = (int)threadState.X3; - - Logger.PrintDebug(LogClass.KernelSvc, - "Address = 0x" + address.ToString("x16") + ", " + - "Type = " + type .ToString() + ", " + - "Value = 0x" + value .ToString("x8") + ", " + - "Count = 0x" + count .ToString("x8")); - - if (IsPointingInsideKernel(address)) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Invalid address 0x{address:x16}!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - if (IsAddressNotWordAligned(address)) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Unaligned address 0x{address:x16}!"); - - threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - long result; - - switch (type) - { - case SignalType.Signal: - result = currentProcess.AddressArbiter.Signal(address, count); - break; - - case SignalType.SignalAndIncrementIfEqual: - result = currentProcess.AddressArbiter.SignalAndIncrementIfEqual(address, value, count); - break; - - case SignalType.SignalAndModifyIfEqual: - result = currentProcess.AddressArbiter.SignalAndModifyIfEqual(address, value, count); - break; - - default: - result = MakeError(ErrorModule.Kernel, KernelErr.InvalidEnumValue); - break; - } - - if (result != 0) - { - Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!"); - } - - threadState.X0 = (ulong)result; - } - - private bool IsPointingInsideKernel(long address) - { - return ((ulong)address + 0x1000000000) < 0xffffff000; - } - - private bool IsAddressNotWordAligned(long address) - { - return (address & 3) != 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/ArbitrationType.cs b/Ryujinx.HLE/HOS/Kernel/Threading/ArbitrationType.cs similarity index 78% rename from Ryujinx.HLE/HOS/Kernel/ArbitrationType.cs rename to Ryujinx.HLE/HOS/Kernel/Threading/ArbitrationType.cs index b584d7192b..89c1bf1fa0 100644 --- a/Ryujinx.HLE/HOS/Kernel/ArbitrationType.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/ArbitrationType.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Threading { enum ArbitrationType { diff --git a/Ryujinx.HLE/HOS/Kernel/HleCoreManager.cs b/Ryujinx.HLE/HOS/Kernel/Threading/HleCoreManager.cs similarity index 97% rename from Ryujinx.HLE/HOS/Kernel/HleCoreManager.cs rename to Ryujinx.HLE/HOS/Kernel/Threading/HleCoreManager.cs index 04017d6d8a..c25979904d 100644 --- a/Ryujinx.HLE/HOS/Kernel/HleCoreManager.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/HleCoreManager.cs @@ -1,7 +1,7 @@ using System.Collections.Concurrent; using System.Threading; -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Threading { class HleCoreManager { diff --git a/Ryujinx.HLE/HOS/Kernel/HleScheduler.cs b/Ryujinx.HLE/HOS/Kernel/Threading/HleScheduler.cs similarity index 99% rename from Ryujinx.HLE/HOS/Kernel/HleScheduler.cs rename to Ryujinx.HLE/HOS/Kernel/Threading/HleScheduler.cs index 1a4c9dfef8..835c2a2f83 100644 --- a/Ryujinx.HLE/HOS/Kernel/HleScheduler.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/HleScheduler.cs @@ -1,7 +1,7 @@ using System; using System.Threading; -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Threading { partial class KScheduler { diff --git a/Ryujinx.HLE/HOS/Kernel/KAddressArbiter.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs similarity index 75% rename from Ryujinx.HLE/HOS/Kernel/KAddressArbiter.cs rename to Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs index b435248556..faeea5c54b 100644 --- a/Ryujinx.HLE/HOS/Kernel/KAddressArbiter.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs @@ -1,9 +1,9 @@ +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Process; using System.Collections.Generic; using System.Linq; -using static Ryujinx.HLE.HOS.ErrorCode; - -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Threading { class KAddressArbiter { @@ -22,14 +22,14 @@ namespace Ryujinx.HLE.HOS.Kernel ArbiterThreads = new List(); } - public long ArbitrateLock(int ownerHandle, long mutexAddress, int requesterHandle) + public KernelResult ArbitrateLock(int ownerHandle, ulong mutexAddress, int requesterHandle) { KThread currentThread = _system.Scheduler.GetCurrentThread(); _system.CriticalSection.Enter(); currentThread.SignaledObj = null; - currentThread.ObjSyncResult = 0; + currentThread.ObjSyncResult = KernelResult.Success; KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); @@ -37,7 +37,7 @@ namespace Ryujinx.HLE.HOS.Kernel { _system.CriticalSection.Leave(); - return MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); + return KernelResult.InvalidMemState; } if (mutexValue != (ownerHandle | HasListenersMask)) @@ -53,7 +53,7 @@ namespace Ryujinx.HLE.HOS.Kernel { _system.CriticalSection.Leave(); - return MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); + return KernelResult.InvalidHandle; } currentThread.MutexAddress = mutexAddress; @@ -73,21 +73,21 @@ namespace Ryujinx.HLE.HOS.Kernel _system.CriticalSection.Leave(); - return (uint)currentThread.ObjSyncResult; + return (KernelResult)currentThread.ObjSyncResult; } - public long ArbitrateUnlock(long mutexAddress) + public KernelResult ArbitrateUnlock(ulong mutexAddress) { _system.CriticalSection.Enter(); KThread currentThread = _system.Scheduler.GetCurrentThread(); - (long result, KThread newOwnerThread) = MutexUnlock(currentThread, mutexAddress); + (KernelResult result, KThread newOwnerThread) = MutexUnlock(currentThread, mutexAddress); - if (result != 0 && newOwnerThread != null) + if (result != KernelResult.Success && newOwnerThread != null) { newOwnerThread.SignaledObj = null; - newOwnerThread.ObjSyncResult = (int)result; + newOwnerThread.ObjSyncResult = result; } _system.CriticalSection.Leave(); @@ -95,30 +95,30 @@ namespace Ryujinx.HLE.HOS.Kernel return result; } - public long WaitProcessWideKeyAtomic( - long mutexAddress, - long condVarAddress, - int threadHandle, - long timeout) + public KernelResult WaitProcessWideKeyAtomic( + ulong mutexAddress, + ulong condVarAddress, + int threadHandle, + long timeout) { _system.CriticalSection.Enter(); KThread currentThread = _system.Scheduler.GetCurrentThread(); currentThread.SignaledObj = null; - currentThread.ObjSyncResult = (int)MakeError(ErrorModule.Kernel, KernelErr.Timeout); + currentThread.ObjSyncResult = KernelResult.TimedOut; if (currentThread.ShallBeTerminated || currentThread.SchedFlags == ThreadSchedState.TerminationPending) { _system.CriticalSection.Leave(); - return MakeError(ErrorModule.Kernel, KernelErr.ThreadTerminating); + return KernelResult.ThreadTerminating; } - (long result, _) = MutexUnlock(currentThread, mutexAddress); + (KernelResult result, _) = MutexUnlock(currentThread, mutexAddress); - if (result != 0) + if (result != KernelResult.Success) { _system.CriticalSection.Leave(); @@ -159,10 +159,10 @@ namespace Ryujinx.HLE.HOS.Kernel _system.CriticalSection.Leave(); - return (uint)currentThread.ObjSyncResult; + return (KernelResult)currentThread.ObjSyncResult; } - private (long, KThread) MutexUnlock(KThread currentThread, long mutexAddress) + private (KernelResult, KThread) MutexUnlock(KThread currentThread, ulong mutexAddress) { KThread newOwnerThread = currentThread.RelinquishMutex(mutexAddress, out int count); @@ -178,22 +178,22 @@ namespace Ryujinx.HLE.HOS.Kernel } newOwnerThread.SignaledObj = null; - newOwnerThread.ObjSyncResult = 0; + newOwnerThread.ObjSyncResult = KernelResult.Success; newOwnerThread.ReleaseAndResume(); } - long result = 0; + KernelResult result = KernelResult.Success; if (!KernelTransfer.KernelToUserInt32(_system, mutexAddress, mutexValue)) { - result = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); + result = KernelResult.InvalidMemState; } return (result, newOwnerThread); } - public void SignalProcessWideKey(long address, int count) + public void SignalProcessWideKey(ulong address, int count) { Queue signaledThreads = new Queue(); @@ -224,11 +224,11 @@ namespace Ryujinx.HLE.HOS.Kernel private KThread TryAcquireMutex(KThread requester) { - long address = requester.MutexAddress; + ulong address = requester.MutexAddress; KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - currentProcess.CpuMemory.SetExclusive(0, address); + currentProcess.CpuMemory.SetExclusive(0, (long)address); if (!KernelTransfer.UserToKernelInt32(_system, address, out int mutexValue)) { @@ -236,24 +236,24 @@ namespace Ryujinx.HLE.HOS.Kernel currentProcess.CpuMemory.ClearExclusive(0); requester.SignaledObj = null; - requester.ObjSyncResult = (int)MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); + requester.ObjSyncResult = KernelResult.InvalidMemState; return null; } while (true) { - if (currentProcess.CpuMemory.TestExclusive(0, address)) + if (currentProcess.CpuMemory.TestExclusive(0, (long)address)) { if (mutexValue != 0) { //Update value to indicate there is a mutex waiter now. - currentProcess.CpuMemory.WriteInt32(address, mutexValue | HasListenersMask); + currentProcess.CpuMemory.WriteInt32((long)address, mutexValue | HasListenersMask); } else { //No thread owning the mutex, assign to requesting thread. - currentProcess.CpuMemory.WriteInt32(address, requester.ThreadHandleForUserMutex); + currentProcess.CpuMemory.WriteInt32((long)address, requester.ThreadHandleForUserMutex); } currentProcess.CpuMemory.ClearExclusiveForStore(0); @@ -261,16 +261,16 @@ namespace Ryujinx.HLE.HOS.Kernel break; } - currentProcess.CpuMemory.SetExclusive(0, address); + currentProcess.CpuMemory.SetExclusive(0, (long)address); - mutexValue = currentProcess.CpuMemory.ReadInt32(address); + mutexValue = currentProcess.CpuMemory.ReadInt32((long)address); } if (mutexValue == 0) { //We now own the mutex. requester.SignaledObj = null; - requester.ObjSyncResult = 0; + requester.ObjSyncResult = KernelResult.Success; requester.ReleaseAndResume(); @@ -290,7 +290,7 @@ namespace Ryujinx.HLE.HOS.Kernel { //Invalid mutex owner. requester.SignaledObj = null; - requester.ObjSyncResult = (int)MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); + requester.ObjSyncResult = KernelResult.InvalidHandle; requester.ReleaseAndResume(); } @@ -298,7 +298,7 @@ namespace Ryujinx.HLE.HOS.Kernel return mutexOwner; } - public long WaitForAddressIfEqual(long address, int value, long timeout) + public KernelResult WaitForAddressIfEqual(ulong address, int value, long timeout) { KThread currentThread = _system.Scheduler.GetCurrentThread(); @@ -309,17 +309,17 @@ namespace Ryujinx.HLE.HOS.Kernel { _system.CriticalSection.Leave(); - return MakeError(ErrorModule.Kernel, KernelErr.ThreadTerminating); + return KernelResult.ThreadTerminating; } currentThread.SignaledObj = null; - currentThread.ObjSyncResult = (int)MakeError(ErrorModule.Kernel, KernelErr.Timeout); + currentThread.ObjSyncResult = KernelResult.TimedOut; if (!KernelTransfer.UserToKernelInt32(_system, address, out int currentValue)) { _system.CriticalSection.Leave(); - return MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); + return KernelResult.InvalidMemState; } if (currentValue == value) @@ -328,7 +328,7 @@ namespace Ryujinx.HLE.HOS.Kernel { _system.CriticalSection.Leave(); - return MakeError(ErrorModule.Kernel, KernelErr.Timeout); + return KernelResult.TimedOut; } currentThread.MutexAddress = address; @@ -361,15 +361,19 @@ namespace Ryujinx.HLE.HOS.Kernel _system.CriticalSection.Leave(); - return currentThread.ObjSyncResult; + return (KernelResult)currentThread.ObjSyncResult; } _system.CriticalSection.Leave(); - return MakeError(ErrorModule.Kernel, KernelErr.InvalidState); + return KernelResult.InvalidState; } - public long WaitForAddressIfLessThan(long address, int value, bool shouldDecrement, long timeout) + public KernelResult WaitForAddressIfLessThan( + ulong address, + int value, + bool shouldDecrement, + long timeout) { KThread currentThread = _system.Scheduler.GetCurrentThread(); @@ -380,40 +384,40 @@ namespace Ryujinx.HLE.HOS.Kernel { _system.CriticalSection.Leave(); - return MakeError(ErrorModule.Kernel, KernelErr.ThreadTerminating); + return KernelResult.ThreadTerminating; } currentThread.SignaledObj = null; - currentThread.ObjSyncResult = (int)MakeError(ErrorModule.Kernel, KernelErr.Timeout); + currentThread.ObjSyncResult = KernelResult.TimedOut; KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); //If ShouldDecrement is true, do atomic decrement of the value at Address. - currentProcess.CpuMemory.SetExclusive(0, address); + currentProcess.CpuMemory.SetExclusive(0, (long)address); if (!KernelTransfer.UserToKernelInt32(_system, address, out int currentValue)) { _system.CriticalSection.Leave(); - return MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); + return KernelResult.InvalidMemState; } if (shouldDecrement) { while (currentValue < value) { - if (currentProcess.CpuMemory.TestExclusive(0, address)) + if (currentProcess.CpuMemory.TestExclusive(0, (long)address)) { - currentProcess.CpuMemory.WriteInt32(address, currentValue - 1); + currentProcess.CpuMemory.WriteInt32((long)address, currentValue - 1); currentProcess.CpuMemory.ClearExclusiveForStore(0); break; } - currentProcess.CpuMemory.SetExclusive(0, address); + currentProcess.CpuMemory.SetExclusive(0, (long)address); - currentValue = currentProcess.CpuMemory.ReadInt32(address); + currentValue = currentProcess.CpuMemory.ReadInt32((long)address); } } @@ -425,7 +429,7 @@ namespace Ryujinx.HLE.HOS.Kernel { _system.CriticalSection.Leave(); - return MakeError(ErrorModule.Kernel, KernelErr.Timeout); + return KernelResult.TimedOut; } currentThread.MutexAddress = address; @@ -458,12 +462,12 @@ namespace Ryujinx.HLE.HOS.Kernel _system.CriticalSection.Leave(); - return currentThread.ObjSyncResult; + return (KernelResult)currentThread.ObjSyncResult; } _system.CriticalSection.Leave(); - return MakeError(ErrorModule.Kernel, KernelErr.InvalidState); + return KernelResult.InvalidState; } private void InsertSortedByPriority(List threads, KThread thread) @@ -490,7 +494,7 @@ namespace Ryujinx.HLE.HOS.Kernel } } - public long Signal(long address, int count) + public KernelResult Signal(ulong address, int count) { _system.CriticalSection.Enter(); @@ -498,38 +502,38 @@ namespace Ryujinx.HLE.HOS.Kernel _system.CriticalSection.Leave(); - return 0; + return KernelResult.Success; } - public long SignalAndIncrementIfEqual(long address, int value, int count) + public KernelResult SignalAndIncrementIfEqual(ulong address, int value, int count) { _system.CriticalSection.Enter(); KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - currentProcess.CpuMemory.SetExclusive(0, address); + currentProcess.CpuMemory.SetExclusive(0, (long)address); if (!KernelTransfer.UserToKernelInt32(_system, address, out int currentValue)) { _system.CriticalSection.Leave(); - return MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); + return KernelResult.InvalidMemState; } while (currentValue == value) { - if (currentProcess.CpuMemory.TestExclusive(0, address)) + if (currentProcess.CpuMemory.TestExclusive(0, (long)address)) { - currentProcess.CpuMemory.WriteInt32(address, currentValue + 1); + currentProcess.CpuMemory.WriteInt32((long)address, currentValue + 1); currentProcess.CpuMemory.ClearExclusiveForStore(0); break; } - currentProcess.CpuMemory.SetExclusive(0, address); + currentProcess.CpuMemory.SetExclusive(0, (long)address); - currentValue = currentProcess.CpuMemory.ReadInt32(address); + currentValue = currentProcess.CpuMemory.ReadInt32((long)address); } currentProcess.CpuMemory.ClearExclusive(0); @@ -538,17 +542,17 @@ namespace Ryujinx.HLE.HOS.Kernel { _system.CriticalSection.Leave(); - return MakeError(ErrorModule.Kernel, KernelErr.InvalidState); + return KernelResult.InvalidState; } WakeArbiterThreads(address, count); _system.CriticalSection.Leave(); - return 0; + return KernelResult.Success; } - public long SignalAndModifyIfEqual(long address, int value, int count) + public KernelResult SignalAndModifyIfEqual(ulong address, int value, int count) { _system.CriticalSection.Enter(); @@ -578,29 +582,29 @@ namespace Ryujinx.HLE.HOS.Kernel KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - currentProcess.CpuMemory.SetExclusive(0, address); + currentProcess.CpuMemory.SetExclusive(0, (long)address); if (!KernelTransfer.UserToKernelInt32(_system, address, out int currentValue)) { _system.CriticalSection.Leave(); - return MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); + return KernelResult.InvalidMemState; } while (currentValue == value) { - if (currentProcess.CpuMemory.TestExclusive(0, address)) + if (currentProcess.CpuMemory.TestExclusive(0, (long)address)) { - currentProcess.CpuMemory.WriteInt32(address, currentValue + offset); + currentProcess.CpuMemory.WriteInt32((long)address, currentValue + offset); currentProcess.CpuMemory.ClearExclusiveForStore(0); break; } - currentProcess.CpuMemory.SetExclusive(0, address); + currentProcess.CpuMemory.SetExclusive(0, (long)address); - currentValue = currentProcess.CpuMemory.ReadInt32(address); + currentValue = currentProcess.CpuMemory.ReadInt32((long)address); } currentProcess.CpuMemory.ClearExclusive(0); @@ -609,17 +613,17 @@ namespace Ryujinx.HLE.HOS.Kernel { _system.CriticalSection.Leave(); - return MakeError(ErrorModule.Kernel, KernelErr.InvalidState); + return KernelResult.InvalidState; } WakeArbiterThreads(address, count); _system.CriticalSection.Leave(); - return 0; + return KernelResult.Success; } - private void WakeArbiterThreads(long address, int count) + private void WakeArbiterThreads(ulong address, int count) { Queue signaledThreads = new Queue(); @@ -637,7 +641,7 @@ namespace Ryujinx.HLE.HOS.Kernel while (signaledThreads.TryDequeue(out KThread thread)) { thread.SignaledObj = null; - thread.ObjSyncResult = 0; + thread.ObjSyncResult = KernelResult.Success; thread.ReleaseAndResume(); diff --git a/Ryujinx.HLE/HOS/Kernel/KConditionVariable.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KConditionVariable.cs similarity index 97% rename from Ryujinx.HLE/HOS/Kernel/KConditionVariable.cs rename to Ryujinx.HLE/HOS/Kernel/Threading/KConditionVariable.cs index 15c96c24d2..414736438a 100644 --- a/Ryujinx.HLE/HOS/Kernel/KConditionVariable.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KConditionVariable.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Threading; -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Threading { static class KConditionVariable { diff --git a/Ryujinx.HLE/HOS/Kernel/KCoreContext.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KCoreContext.cs similarity index 98% rename from Ryujinx.HLE/HOS/Kernel/KCoreContext.cs rename to Ryujinx.HLE/HOS/Kernel/Threading/KCoreContext.cs index 4ca3c25a06..81cd88834f 100644 --- a/Ryujinx.HLE/HOS/Kernel/KCoreContext.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KCoreContext.cs @@ -1,6 +1,6 @@ using Ryujinx.Common; -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Threading { class KCoreContext { diff --git a/Ryujinx.HLE/HOS/Kernel/KCriticalSection.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KCriticalSection.cs similarity index 98% rename from Ryujinx.HLE/HOS/Kernel/KCriticalSection.cs rename to Ryujinx.HLE/HOS/Kernel/Threading/KCriticalSection.cs index a54dc6cbc1..841d0d69b1 100644 --- a/Ryujinx.HLE/HOS/Kernel/KCriticalSection.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KCriticalSection.cs @@ -1,7 +1,7 @@ using ChocolArm64; using System.Threading; -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Threading { class KCriticalSection { diff --git a/Ryujinx.HLE/HOS/Kernel/KEvent.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KEvent.cs similarity index 88% rename from Ryujinx.HLE/HOS/Kernel/KEvent.cs rename to Ryujinx.HLE/HOS/Kernel/Threading/KEvent.cs index aa2124ec4e..5bdb9c1d6e 100644 --- a/Ryujinx.HLE/HOS/Kernel/KEvent.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KEvent.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Threading { class KEvent { diff --git a/Ryujinx.HLE/HOS/Kernel/KReadableEvent.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KReadableEvent.cs similarity index 93% rename from Ryujinx.HLE/HOS/Kernel/KReadableEvent.cs rename to Ryujinx.HLE/HOS/Kernel/Threading/KReadableEvent.cs index e1a3e63fc8..9821de35b1 100644 --- a/Ryujinx.HLE/HOS/Kernel/KReadableEvent.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KReadableEvent.cs @@ -1,4 +1,6 @@ -namespace Ryujinx.HLE.HOS.Kernel +using Ryujinx.HLE.HOS.Kernel.Common; + +namespace Ryujinx.HLE.HOS.Kernel.Threading { class KReadableEvent : KSynchronizationObject { diff --git a/Ryujinx.HLE/HOS/Kernel/KScheduler.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs similarity index 98% rename from Ryujinx.HLE/HOS/Kernel/KScheduler.cs rename to Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs index f85b9e8c41..60e15efa08 100644 --- a/Ryujinx.HLE/HOS/Kernel/KScheduler.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs @@ -1,8 +1,9 @@ +using Ryujinx.HLE.HOS.Kernel.Process; using System; using System.Collections.Generic; using System.Linq; -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Threading { partial class KScheduler : IDisposable { diff --git a/Ryujinx.HLE/HOS/Kernel/KSchedulingData.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KSchedulingData.cs similarity index 99% rename from Ryujinx.HLE/HOS/Kernel/KSchedulingData.cs rename to Ryujinx.HLE/HOS/Kernel/Threading/KSchedulingData.cs index 651160361d..83c4a0791f 100644 --- a/Ryujinx.HLE/HOS/Kernel/KSchedulingData.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KSchedulingData.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Threading { class KSchedulingData { diff --git a/Ryujinx.HLE/HOS/Kernel/KSynchronization.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs similarity index 82% rename from Ryujinx.HLE/HOS/Kernel/KSynchronization.cs rename to Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs index 51b74a03db..450155ce0e 100644 --- a/Ryujinx.HLE/HOS/Kernel/KSynchronization.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs @@ -1,8 +1,7 @@ +using Ryujinx.HLE.HOS.Kernel.Common; using System.Collections.Generic; -using static Ryujinx.HLE.HOS.ErrorCode; - -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Threading { class KSynchronization { @@ -13,9 +12,11 @@ namespace Ryujinx.HLE.HOS.Kernel _system = system; } - public long WaitFor(KSynchronizationObject[] syncObjs, long timeout, ref int hndIndex) + public KernelResult WaitFor(KSynchronizationObject[] syncObjs, long timeout, out int handleIndex) { - long result = MakeError(ErrorModule.Kernel, KernelErr.Timeout); + handleIndex = 0; + + KernelResult result = KernelResult.TimedOut; _system.CriticalSection.Enter(); @@ -27,7 +28,7 @@ namespace Ryujinx.HLE.HOS.Kernel continue; } - hndIndex = index; + handleIndex = index; _system.CriticalSection.Leave(); @@ -46,13 +47,13 @@ namespace Ryujinx.HLE.HOS.Kernel if (currentThread.ShallBeTerminated || currentThread.SchedFlags == ThreadSchedState.TerminationPending) { - result = MakeError(ErrorModule.Kernel, KernelErr.ThreadTerminating); + result = KernelResult.ThreadTerminating; } else if (currentThread.SyncCancelled) { currentThread.SyncCancelled = false; - result = MakeError(ErrorModule.Kernel, KernelErr.Cancelled); + result = KernelResult.Cancelled; } else { @@ -65,7 +66,7 @@ namespace Ryujinx.HLE.HOS.Kernel currentThread.WaitingSync = true; currentThread.SignaledObj = null; - currentThread.ObjSyncResult = (int)result; + currentThread.ObjSyncResult = result; currentThread.Reschedule(ThreadSchedState.Paused); @@ -85,9 +86,9 @@ namespace Ryujinx.HLE.HOS.Kernel _system.CriticalSection.Enter(); - result = (uint)currentThread.ObjSyncResult; + result = currentThread.ObjSyncResult; - hndIndex = -1; + handleIndex = -1; for (int index = 0; index < syncObjs.Length; index++) { @@ -95,7 +96,7 @@ namespace Ryujinx.HLE.HOS.Kernel if (syncObjs[index] == currentThread.SignaledObj) { - hndIndex = index; + handleIndex = index; } } } @@ -120,7 +121,7 @@ namespace Ryujinx.HLE.HOS.Kernel if ((thread.SchedFlags & ThreadSchedState.LowMask) == ThreadSchedState.Paused) { thread.SignaledObj = syncObj; - thread.ObjSyncResult = 0; + thread.ObjSyncResult = KernelResult.Success; thread.Reschedule(ThreadSchedState.Running); } diff --git a/Ryujinx.HLE/HOS/Kernel/KThread.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs similarity index 97% rename from Ryujinx.HLE/HOS/Kernel/KThread.cs rename to Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs index 846b41aa33..3ad6402457 100644 --- a/Ryujinx.HLE/HOS/Kernel/KThread.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs @@ -1,12 +1,12 @@ using ChocolArm64; using ChocolArm64.Memory; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Process; using System; using System.Collections.Generic; using System.Linq; -using static Ryujinx.HLE.HOS.ErrorCode; - -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Threading { class KThread : KSynchronizationObject, IKFutureSchedulerObject { @@ -20,11 +20,11 @@ namespace Ryujinx.HLE.HOS.Kernel public KSynchronizationObject SignaledObj { get; set; } - public long CondVarAddress { get; set; } + public ulong CondVarAddress { get; set; } private ulong _entrypoint; - public long MutexAddress { get; set; } + public ulong MutexAddress { get; set; } public KProcess Owner { get; private set; } @@ -48,7 +48,7 @@ namespace Ryujinx.HLE.HOS.Kernel private ThreadSchedState _forcePauseFlags; - public int ObjSyncResult { get; set; } + public KernelResult ObjSyncResult { get; set; } public int DynamicPriority { get; set; } public int CurrentCore { get; set; } @@ -113,7 +113,7 @@ namespace Ryujinx.HLE.HOS.Kernel DynamicPriority = priority; BasePriority = priority; - ObjSyncResult = 0x7201; + ObjSyncResult = KernelResult.ThreadNotStarted; _entrypoint = entrypoint; @@ -274,7 +274,7 @@ namespace Ryujinx.HLE.HOS.Kernel System.CriticalSection.Leave(); } - public long Sleep(long timeout) + public KernelResult Sleep(long timeout) { System.CriticalSection.Enter(); @@ -282,7 +282,7 @@ namespace Ryujinx.HLE.HOS.Kernel { System.CriticalSection.Leave(); - return MakeError(ErrorModule.Kernel, KernelErr.ThreadTerminating); + return KernelResult.ThreadTerminating; } SetNewSchedFlags(ThreadSchedState.Paused); @@ -468,9 +468,9 @@ namespace Ryujinx.HLE.HOS.Kernel System.CriticalSection.Leave(); } - public long SetActivity(bool pause) + public KernelResult SetActivity(bool pause) { - long result = 0; + KernelResult result = KernelResult.Success; System.CriticalSection.Enter(); @@ -480,7 +480,7 @@ namespace Ryujinx.HLE.HOS.Kernel { System.CriticalSection.Leave(); - return MakeError(ErrorModule.Kernel, KernelErr.InvalidState); + return KernelResult.InvalidState; } System.CriticalSection.Enter(); @@ -498,7 +498,7 @@ namespace Ryujinx.HLE.HOS.Kernel } else { - result = MakeError(ErrorModule.Kernel, KernelErr.InvalidState); + result = KernelResult.InvalidState; } } else @@ -521,7 +521,7 @@ namespace Ryujinx.HLE.HOS.Kernel } else { - result = MakeError(ErrorModule.Kernel, KernelErr.InvalidState); + result = KernelResult.InvalidState; } } } @@ -553,7 +553,7 @@ namespace Ryujinx.HLE.HOS.Kernel else { SignaledObj = null; - ObjSyncResult = (int)MakeError(ErrorModule.Kernel, KernelErr.Cancelled); + ObjSyncResult = KernelResult.Cancelled; SetNewSchedFlags(ThreadSchedState.Running); @@ -716,7 +716,7 @@ namespace Ryujinx.HLE.HOS.Kernel UpdatePriorityInheritance(); } - public KThread RelinquishMutex(long mutexAddress, out int count) + public KThread RelinquishMutex(ulong mutexAddress, out int count) { count = 0; @@ -1017,7 +1017,7 @@ namespace Ryujinx.HLE.HOS.Kernel { thread.MutexOwner = null; thread._preferredCoreOverride = 0; - thread.ObjSyncResult = 0xfa01; + thread.ObjSyncResult = KernelResult.InvalidState; thread.ReleaseAndResume(); } diff --git a/Ryujinx.HLE/HOS/Kernel/KWritableEvent.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KWritableEvent.cs similarity index 82% rename from Ryujinx.HLE/HOS/Kernel/KWritableEvent.cs rename to Ryujinx.HLE/HOS/Kernel/Threading/KWritableEvent.cs index 4d56a92d28..c9b2f40db2 100644 --- a/Ryujinx.HLE/HOS/Kernel/KWritableEvent.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KWritableEvent.cs @@ -1,4 +1,6 @@ -namespace Ryujinx.HLE.HOS.Kernel +using Ryujinx.HLE.HOS.Kernel.Common; + +namespace Ryujinx.HLE.HOS.Kernel.Threading { class KWritableEvent { diff --git a/Ryujinx.HLE/HOS/Kernel/SignalType.cs b/Ryujinx.HLE/HOS/Kernel/Threading/SignalType.cs similarity index 77% rename from Ryujinx.HLE/HOS/Kernel/SignalType.cs rename to Ryujinx.HLE/HOS/Kernel/Threading/SignalType.cs index 0580315103..e72b719b4c 100644 --- a/Ryujinx.HLE/HOS/Kernel/SignalType.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/SignalType.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Threading { enum SignalType { diff --git a/Ryujinx.HLE/HOS/Kernel/ThreadSchedState.cs b/Ryujinx.HLE/HOS/Kernel/Threading/ThreadSchedState.cs similarity index 90% rename from Ryujinx.HLE/HOS/Kernel/ThreadSchedState.cs rename to Ryujinx.HLE/HOS/Kernel/Threading/ThreadSchedState.cs index 37e5908a9c..c9eaa6b333 100644 --- a/Ryujinx.HLE/HOS/Kernel/ThreadSchedState.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/ThreadSchedState.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Threading { enum ThreadSchedState : ushort { diff --git a/Ryujinx.HLE/HOS/Kernel/ThreadType.cs b/Ryujinx.HLE/HOS/Kernel/Threading/ThreadType.cs similarity index 69% rename from Ryujinx.HLE/HOS/Kernel/ThreadType.cs rename to Ryujinx.HLE/HOS/Kernel/Threading/ThreadType.cs index 0fe83423cf..0b44b57ff1 100644 --- a/Ryujinx.HLE/HOS/Kernel/ThreadType.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/ThreadType.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.HLE.HOS.Kernel +namespace Ryujinx.HLE.HOS.Kernel.Threading { enum ThreadType { diff --git a/Ryujinx.HLE/HOS/ProgramLoader.cs b/Ryujinx.HLE/HOS/ProgramLoader.cs index 00fc6b9354..bb09db6ef4 100644 --- a/Ryujinx.HLE/HOS/ProgramLoader.cs +++ b/Ryujinx.HLE/HOS/ProgramLoader.cs @@ -1,7 +1,9 @@ using ChocolArm64.Memory; using Ryujinx.Common; using Ryujinx.Common.Logging; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Memory; +using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.Loaders.Executables; using Ryujinx.HLE.Loaders.Npdm; diff --git a/Ryujinx.HLE/HOS/ServiceCtx.cs b/Ryujinx.HLE/HOS/ServiceCtx.cs index f55e454615..005d16f34f 100644 --- a/Ryujinx.HLE/HOS/ServiceCtx.cs +++ b/Ryujinx.HLE/HOS/ServiceCtx.cs @@ -1,6 +1,7 @@ using ChocolArm64.Memory; using Ryujinx.HLE.HOS.Ipc; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Ipc; +using Ryujinx.HLE.HOS.Kernel.Process; using System.IO; namespace Ryujinx.HLE.HOS diff --git a/Ryujinx.HLE/HOS/Services/Am/ICommonStateGetter.cs b/Ryujinx.HLE/HOS/Services/Am/ICommonStateGetter.cs index 8ec4215298..f143db2c26 100644 --- a/Ryujinx.HLE/HOS/Services/Am/ICommonStateGetter.cs +++ b/Ryujinx.HLE/HOS/Services/Am/ICommonStateGetter.cs @@ -1,6 +1,7 @@ using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Ipc; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Threading; using System; using System.Collections.Generic; diff --git a/Ryujinx.HLE/HOS/Services/Am/IHomeMenuFunctions.cs b/Ryujinx.HLE/HOS/Services/Am/IHomeMenuFunctions.cs index db116f3343..fdcd923db1 100644 --- a/Ryujinx.HLE/HOS/Services/Am/IHomeMenuFunctions.cs +++ b/Ryujinx.HLE/HOS/Services/Am/IHomeMenuFunctions.cs @@ -1,6 +1,7 @@ using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Ipc; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Threading; using System; using System.Collections.Generic; diff --git a/Ryujinx.HLE/HOS/Services/Am/ILibraryAppletAccessor.cs b/Ryujinx.HLE/HOS/Services/Am/ILibraryAppletAccessor.cs index 7c4aa16c1d..faf522e411 100644 --- a/Ryujinx.HLE/HOS/Services/Am/ILibraryAppletAccessor.cs +++ b/Ryujinx.HLE/HOS/Services/Am/ILibraryAppletAccessor.cs @@ -1,6 +1,7 @@ using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Ipc; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Threading; using System; using System.Collections.Generic; diff --git a/Ryujinx.HLE/HOS/Services/Am/ISelfController.cs b/Ryujinx.HLE/HOS/Services/Am/ISelfController.cs index dc9220373e..e30e8d0d2c 100644 --- a/Ryujinx.HLE/HOS/Services/Am/ISelfController.cs +++ b/Ryujinx.HLE/HOS/Services/Am/ISelfController.cs @@ -1,6 +1,7 @@ using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Ipc; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Threading; using System; using System.Collections.Generic; diff --git a/Ryujinx.HLE/HOS/Services/Aud/AudioOut/IAudioOut.cs b/Ryujinx.HLE/HOS/Services/Aud/AudioOut/IAudioOut.cs index 93bda210e3..5270a0411a 100644 --- a/Ryujinx.HLE/HOS/Services/Aud/AudioOut/IAudioOut.cs +++ b/Ryujinx.HLE/HOS/Services/Aud/AudioOut/IAudioOut.cs @@ -1,7 +1,8 @@ using ChocolArm64.Memory; using Ryujinx.Audio; using Ryujinx.HLE.HOS.Ipc; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Threading; using System; using System.Collections.Generic; diff --git a/Ryujinx.HLE/HOS/Services/Aud/AudioRenderer/IAudioRenderer.cs b/Ryujinx.HLE/HOS/Services/Aud/AudioRenderer/IAudioRenderer.cs index 0ad193ca92..bc069436bb 100644 --- a/Ryujinx.HLE/HOS/Services/Aud/AudioRenderer/IAudioRenderer.cs +++ b/Ryujinx.HLE/HOS/Services/Aud/AudioRenderer/IAudioRenderer.cs @@ -3,7 +3,8 @@ using Ryujinx.Audio; using Ryujinx.Audio.Adpcm; using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Ipc; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.Utilities; using System; using System.Collections.Generic; diff --git a/Ryujinx.HLE/HOS/Services/Aud/IAudioDevice.cs b/Ryujinx.HLE/HOS/Services/Aud/IAudioDevice.cs index 585d7e43aa..0d68fe1380 100644 --- a/Ryujinx.HLE/HOS/Services/Aud/IAudioDevice.cs +++ b/Ryujinx.HLE/HOS/Services/Aud/IAudioDevice.cs @@ -1,6 +1,7 @@ using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Ipc; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.SystemState; using System; using System.Collections.Generic; diff --git a/Ryujinx.HLE/HOS/Services/Aud/IAudioOutManager.cs b/Ryujinx.HLE/HOS/Services/Aud/IAudioOutManager.cs index 4b1440a027..a276c96e36 100644 --- a/Ryujinx.HLE/HOS/Services/Aud/IAudioOutManager.cs +++ b/Ryujinx.HLE/HOS/Services/Aud/IAudioOutManager.cs @@ -2,7 +2,7 @@ using ChocolArm64.Memory; using Ryujinx.Audio; using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Ipc; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.Services.Aud.AudioOut; using System.Collections.Generic; using System.Text; diff --git a/Ryujinx.HLE/HOS/Services/Hid/IAppletResource.cs b/Ryujinx.HLE/HOS/Services/Hid/IAppletResource.cs index e82b824eb0..c92252d82c 100644 --- a/Ryujinx.HLE/HOS/Services/Hid/IAppletResource.cs +++ b/Ryujinx.HLE/HOS/Services/Hid/IAppletResource.cs @@ -1,5 +1,6 @@ using Ryujinx.HLE.HOS.Ipc; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Memory; using System; using System.Collections.Generic; diff --git a/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs b/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs index 4e14943bcb..cc75e99be6 100644 --- a/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs +++ b/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs @@ -1,6 +1,7 @@ using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Ipc; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.Input; using System; using System.Collections.Generic; @@ -1216,7 +1217,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid long appletResourceUserId = context.RequestData.ReadInt64(); Logger.PrintStub(LogClass.ServiceHid, $"Stubbed. AppletResourceUserId: {appletResourceUserId}"); - + return 0; } diff --git a/Ryujinx.HLE/HOS/Services/IpcService.cs b/Ryujinx.HLE/HOS/Services/IpcService.cs index ec43430e3f..8d2036ea05 100644 --- a/Ryujinx.HLE/HOS/Services/IpcService.cs +++ b/Ryujinx.HLE/HOS/Services/IpcService.cs @@ -1,6 +1,7 @@ using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Ipc; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Ipc; using System; using System.Collections.Generic; using System.IO; diff --git a/Ryujinx.HLE/HOS/Services/Ldr/IRoInterface.cs b/Ryujinx.HLE/HOS/Services/Ldr/IRoInterface.cs index 1ee30a6c05..202e6df5c7 100644 --- a/Ryujinx.HLE/HOS/Services/Ldr/IRoInterface.cs +++ b/Ryujinx.HLE/HOS/Services/Ldr/IRoInterface.cs @@ -1,7 +1,9 @@ using ChocolArm64.Memory; using Ryujinx.Common; using Ryujinx.HLE.HOS.Ipc; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Memory; +using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.Loaders.Executables; using Ryujinx.HLE.Utilities; using System.Collections.Generic; diff --git a/Ryujinx.HLE/HOS/Services/Nfp/IUser.cs b/Ryujinx.HLE/HOS/Services/Nfp/IUser.cs index 9e19e77f89..42ef482970 100644 --- a/Ryujinx.HLE/HOS/Services/Nfp/IUser.cs +++ b/Ryujinx.HLE/HOS/Services/Nfp/IUser.cs @@ -1,6 +1,7 @@ using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Ipc; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.Input; using System; using System.Collections.Generic; diff --git a/Ryujinx.HLE/HOS/Services/Nifm/IRequest.cs b/Ryujinx.HLE/HOS/Services/Nifm/IRequest.cs index 52adce9e75..d2c646be96 100644 --- a/Ryujinx.HLE/HOS/Services/Nifm/IRequest.cs +++ b/Ryujinx.HLE/HOS/Services/Nifm/IRequest.cs @@ -1,6 +1,7 @@ using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Ipc; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Threading; using System; using System.Collections.Generic; diff --git a/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs b/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs index 1ed97ddea2..3a00f51454 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs @@ -1,7 +1,9 @@ using ChocolArm64.Memory; using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Ipc; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Process; +using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.Services.Nv.NvGpuAS; using Ryujinx.HLE.HOS.Services.Nv.NvGpuGpu; using Ryujinx.HLE.HOS.Services.Nv.NvHostChannel; diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvGpuAS/NvGpuASIoctl.cs b/Ryujinx.HLE/HOS/Services/Nv/NvGpuAS/NvGpuASIoctl.cs index 8e128a0d3a..2a5f1b180b 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvGpuAS/NvGpuASIoctl.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/NvGpuAS/NvGpuASIoctl.cs @@ -1,7 +1,7 @@ using ChocolArm64.Memory; using Ryujinx.Common.Logging; using Ryujinx.Graphics.Memory; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.HOS.Services.Nv.NvMap; using System; using System.Collections.Concurrent; diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvHostChannel/NvHostChannelIoctl.cs b/Ryujinx.HLE/HOS/Services/Nv/NvHostChannel/NvHostChannelIoctl.cs index a3b553098f..a6681441f3 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvHostChannel/NvHostChannelIoctl.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/NvHostChannel/NvHostChannelIoctl.cs @@ -1,7 +1,7 @@ using ChocolArm64.Memory; using Ryujinx.Common.Logging; using Ryujinx.Graphics.Memory; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.HOS.Services.Nv.NvGpuAS; using Ryujinx.HLE.HOS.Services.Nv.NvMap; using System; diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvHostCtrl/NvHostCtrlIoctl.cs b/Ryujinx.HLE/HOS/Services/Nv/NvHostCtrl/NvHostCtrlIoctl.cs index f13f7a68d3..ddef456cc7 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvHostCtrl/NvHostCtrlIoctl.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/NvHostCtrl/NvHostCtrlIoctl.cs @@ -1,6 +1,6 @@ using ChocolArm64.Memory; using Ryujinx.Common.Logging; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Process; using System; using System.Collections.Concurrent; using System.Text; diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvMap/NvMapIoctl.cs b/Ryujinx.HLE/HOS/Services/Nv/NvMap/NvMapIoctl.cs index 75a76b91da..b1ae830782 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvMap/NvMapIoctl.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/NvMap/NvMapIoctl.cs @@ -1,7 +1,7 @@ using ChocolArm64.Memory; using Ryujinx.Common.Logging; using Ryujinx.Graphics.Memory; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.Utilities; using System.Collections.Concurrent; diff --git a/Ryujinx.HLE/HOS/Services/Pl/ISharedFontManager.cs b/Ryujinx.HLE/HOS/Services/Pl/ISharedFontManager.cs index c555c504ef..1bdff31ac8 100644 --- a/Ryujinx.HLE/HOS/Services/Pl/ISharedFontManager.cs +++ b/Ryujinx.HLE/HOS/Services/Pl/ISharedFontManager.cs @@ -1,6 +1,6 @@ using Ryujinx.HLE.HOS.Font; using Ryujinx.HLE.HOS.Ipc; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Common; using System; using System.Collections.Generic; diff --git a/Ryujinx.HLE/HOS/Services/Psm/IPsmSession.cs b/Ryujinx.HLE/HOS/Services/Psm/IPsmSession.cs index 4763f2d5cf..0c304b4177 100644 --- a/Ryujinx.HLE/HOS/Services/Psm/IPsmSession.cs +++ b/Ryujinx.HLE/HOS/Services/Psm/IPsmSession.cs @@ -1,6 +1,7 @@ using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Ipc; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Threading; using System.Collections.Generic; namespace Ryujinx.HLE.HOS.Services.Psm diff --git a/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs b/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs index 2bfafd9556..df551a41b9 100644 --- a/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs +++ b/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs @@ -1,5 +1,6 @@ using Ryujinx.HLE.HOS.Ipc; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Ipc; using System; using System.Collections.Generic; diff --git a/Ryujinx.HLE/HOS/Services/Vi/IApplicationDisplayService.cs b/Ryujinx.HLE/HOS/Services/Vi/IApplicationDisplayService.cs index 63e542d24f..0b5705b934 100644 --- a/Ryujinx.HLE/HOS/Services/Vi/IApplicationDisplayService.cs +++ b/Ryujinx.HLE/HOS/Services/Vi/IApplicationDisplayService.cs @@ -1,6 +1,6 @@ using ChocolArm64.Memory; using Ryujinx.HLE.HOS.Ipc; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Common; using System.Collections.Generic; using System; using System.IO; diff --git a/Ryujinx.HLE/HOS/Services/Vi/IHOSBinderDriver.cs b/Ryujinx.HLE/HOS/Services/Vi/IHOSBinderDriver.cs index 7ca3053d93..adcedf4e4d 100644 --- a/Ryujinx.HLE/HOS/Services/Vi/IHOSBinderDriver.cs +++ b/Ryujinx.HLE/HOS/Services/Vi/IHOSBinderDriver.cs @@ -1,6 +1,7 @@ using Ryujinx.Graphics.Gal; using Ryujinx.HLE.HOS.Ipc; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.Services.Android; using System; using System.Collections.Generic; diff --git a/Ryujinx.HLE/HOS/Services/Vi/NvFlinger.cs b/Ryujinx.HLE/HOS/Services/Vi/NvFlinger.cs index 1b57b3319a..cce1b2b90e 100644 --- a/Ryujinx.HLE/HOS/Services/Vi/NvFlinger.cs +++ b/Ryujinx.HLE/HOS/Services/Vi/NvFlinger.cs @@ -1,7 +1,7 @@ using Ryujinx.Common.Logging; using Ryujinx.Graphics.Gal; using Ryujinx.Graphics.Memory; -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.Services.Nv.NvGpuAS; using Ryujinx.HLE.HOS.Services.Nv.NvMap; using System; diff --git a/Ryujinx.HLE/HOS/SystemState/AppletStateMgr.cs b/Ryujinx.HLE/HOS/SystemState/AppletStateMgr.cs index f46a7c30e9..1fd27505cc 100644 --- a/Ryujinx.HLE/HOS/SystemState/AppletStateMgr.cs +++ b/Ryujinx.HLE/HOS/SystemState/AppletStateMgr.cs @@ -1,4 +1,4 @@ -using Ryujinx.HLE.HOS.Kernel; +using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.Services.Am; using System.Collections.Concurrent;