diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2018-08-16 20:47:36 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-08-16 20:47:36 -0300 |
| commit | 521751795a1c97c0d97f6f8904a3be69b13d3a9d (patch) | |
| tree | 942a05899c40e2de6d92a38b93a494bd96ee64b8 /Ryujinx.HLE/OsHle/Kernel | |
| parent | 182d716867ae477c2b15a5332430dc2641fa1cc3 (diff) | |
Code style fixes and nits on the HLE project (#355)
* Some style fixes and nits on ITimeZoneService
* Remove some unneeded usings
* Remove the Ryujinx.HLE.OsHle.Handles namespace
* Remove hbmenu automatic load on process exit
* Rename Ns to Device, rename Os to System, rename SystemState to State
* Move Exceptions and Utilities out of OsHle
* Rename OsHle to HOS
* Rename OsHle folder to HOS
* IManagerDisplayService and ISystemDisplayService style fixes
* BsdError shouldn't be public
* Add a empty new line before using static
* Remove unused file
* Some style fixes on NPDM
* Exit gracefully when the application is closed
* Code style fixes on IGeneralService
* Add 0x prefix on values printed as hex
* Small improvements on finalization code
* Move ProcessId and ThreadId out of AThreadState
* Rename VFs to FileSystem
* FsAccessHeader shouldn't be public. Also fix file names casing
* More case changes on NPDM
* Remove unused files
* Move using to the correct place on NPDM
* Use properties on KernelAccessControlMmio
* Address PR feedback
Diffstat (limited to 'Ryujinx.HLE/OsHle/Kernel')
| -rw-r--r-- | Ryujinx.HLE/OsHle/Kernel/AddressArbiter.cs | 112 | ||||
| -rw-r--r-- | Ryujinx.HLE/OsHle/Kernel/KernelErr.cs | 22 | ||||
| -rw-r--r-- | Ryujinx.HLE/OsHle/Kernel/NsTimeConverter.cs | 19 | ||||
| -rw-r--r-- | Ryujinx.HLE/OsHle/Kernel/SvcHandler.cs | 124 | ||||
| -rw-r--r-- | Ryujinx.HLE/OsHle/Kernel/SvcMemory.cs | 578 | ||||
| -rw-r--r-- | Ryujinx.HLE/OsHle/Kernel/SvcSystem.cs | 374 | ||||
| -rw-r--r-- | Ryujinx.HLE/OsHle/Kernel/SvcThread.cs | 386 | ||||
| -rw-r--r-- | Ryujinx.HLE/OsHle/Kernel/SvcThreadSync.cs | 524 |
8 files changed, 0 insertions, 2139 deletions
diff --git a/Ryujinx.HLE/OsHle/Kernel/AddressArbiter.cs b/Ryujinx.HLE/OsHle/Kernel/AddressArbiter.cs deleted file mode 100644 index ce9ef0cd..00000000 --- a/Ryujinx.HLE/OsHle/Kernel/AddressArbiter.cs +++ /dev/null @@ -1,112 +0,0 @@ -using ChocolArm64.Memory; -using ChocolArm64.State; -using Ryujinx.HLE.OsHle.Handles; - -using static Ryujinx.HLE.OsHle.ErrorCode; - -namespace Ryujinx.HLE.OsHle.Kernel -{ - static class AddressArbiter - { - static ulong WaitForAddress(Process Process, AThreadState ThreadState, long Address, ulong Timeout) - { - KThread CurrentThread = Process.GetThread(ThreadState.Tpidr); - - Process.Scheduler.SetReschedule(CurrentThread.ProcessorId); - - CurrentThread.ArbiterWaitAddress = Address; - CurrentThread.ArbiterSignaled = false; - - Process.Scheduler.EnterWait(CurrentThread, NsTimeConverter.GetTimeMs(Timeout)); - - if (!CurrentThread.ArbiterSignaled) - { - return MakeError(ErrorModule.Kernel, KernelErr.Timeout); - } - - return 0; - } - - public static ulong WaitForAddressIfLessThan(Process Process, - AThreadState ThreadState, - AMemory Memory, - long Address, - int Value, - ulong Timeout, - bool ShouldDecrement) - { - Memory.SetExclusive(ThreadState, Address); - - int CurrentValue = Memory.ReadInt32(Address); - - while (true) - { - if (Memory.TestExclusive(ThreadState, Address)) - { - if (CurrentValue < Value) - { - if (ShouldDecrement) - { - Memory.WriteInt32(Address, CurrentValue - 1); - } - - Memory.ClearExclusiveForStore(ThreadState); - } - else - { - Memory.ClearExclusiveForStore(ThreadState); - - return MakeError(ErrorModule.Kernel, KernelErr.InvalidState); - } - - break; - } - - Memory.SetExclusive(ThreadState, Address); - - CurrentValue = Memory.ReadInt32(Address); - } - - if (Timeout == 0) - { - return MakeError(ErrorModule.Kernel, KernelErr.Timeout); - } - - return WaitForAddress(Process, ThreadState, Address, Timeout); - } - - public static ulong WaitForAddressIfEqual(Process Process, - AThreadState ThreadState, - AMemory Memory, - long Address, - int Value, - ulong Timeout) - { - if (Memory.ReadInt32(Address) != Value) - { - return MakeError(ErrorModule.Kernel, KernelErr.InvalidState); - } - - if (Timeout == 0) - { - return MakeError(ErrorModule.Kernel, KernelErr.Timeout); - } - - return WaitForAddress(Process, ThreadState, Address, Timeout); - } - } - - enum ArbitrationType : int - { - WaitIfLessThan, - DecrementAndWaitIfLessThan, - WaitIfEqual - } - - enum SignalType : int - { - Signal, - IncrementAndSignalIfEqual, - ModifyByWaitingCountAndSignalIfEqual - } -} diff --git a/Ryujinx.HLE/OsHle/Kernel/KernelErr.cs b/Ryujinx.HLE/OsHle/Kernel/KernelErr.cs deleted file mode 100644 index a62fc1bf..00000000 --- a/Ryujinx.HLE/OsHle/Kernel/KernelErr.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace Ryujinx.HLE.OsHle.Kernel -{ - static class KernelErr - { - public const int InvalidSize = 101; - public const int InvalidAddress = 102; - public const int OutOfMemory = 104; - 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 Canceled = 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/OsHle/Kernel/NsTimeConverter.cs b/Ryujinx.HLE/OsHle/Kernel/NsTimeConverter.cs deleted file mode 100644 index 966fdaca..00000000 --- a/Ryujinx.HLE/OsHle/Kernel/NsTimeConverter.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace Ryujinx.HLE.OsHle.Kernel -{ - static class NsTimeConverter - { - public static int GetTimeMs(ulong Ns) - { - ulong Ms = Ns / 1_000_000; - - if (Ms < int.MaxValue) - { - return (int)Ms; - } - else - { - return int.MaxValue; - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.HLE/OsHle/Kernel/SvcHandler.cs b/Ryujinx.HLE/OsHle/Kernel/SvcHandler.cs deleted file mode 100644 index a33ffe5e..00000000 --- a/Ryujinx.HLE/OsHle/Kernel/SvcHandler.cs +++ /dev/null @@ -1,124 +0,0 @@ -using ChocolArm64.Events; -using ChocolArm64.Memory; -using ChocolArm64.State; -using Ryujinx.HLE.Logging; -using Ryujinx.HLE.OsHle.Handles; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Threading; - -namespace Ryujinx.HLE.OsHle.Kernel -{ - partial class SvcHandler - { - private delegate void SvcFunc(AThreadState ThreadState); - - private Dictionary<int, SvcFunc> SvcFuncs; - - private Switch Ns; - private Process Process; - private AMemory Memory; - - private ConcurrentDictionary<KThread, AutoResetEvent> SyncWaits; - - private const uint SelfThreadHandle = 0xffff8000; - private const uint SelfProcessHandle = 0xffff8001; - - private static Random Rng; - - public SvcHandler(Switch Ns, Process Process) - { - SvcFuncs = new Dictionary<int, SvcFunc>() - { - { 0x01, SvcSetHeapSize }, - { 0x03, SvcSetMemoryAttribute }, - { 0x04, SvcMapMemory }, - { 0x05, SvcUnmapMemory }, - { 0x06, SvcQueryMemory }, - { 0x07, SvcExitProcess }, - { 0x08, SvcCreateThread }, - { 0x09, SvcStartThread }, - { 0x0a, SvcExitThread }, - { 0x0b, SvcSleepThread }, - { 0x0c, SvcGetThreadPriority }, - { 0x0d, SvcSetThreadPriority }, - { 0x0e, SvcGetThreadCoreMask }, - { 0x0f, SvcSetThreadCoreMask }, - { 0x10, SvcGetCurrentProcessorNumber }, - { 0x12, SvcClearEvent }, - { 0x13, SvcMapSharedMemory }, - { 0x14, SvcUnmapSharedMemory }, - { 0x15, SvcCreateTransferMemory }, - { 0x16, SvcCloseHandle }, - { 0x17, SvcResetSignal }, - { 0x18, SvcWaitSynchronization }, - { 0x19, SvcCancelSynchronization }, - { 0x1a, SvcArbitrateLock }, - { 0x1b, SvcArbitrateUnlock }, - { 0x1c, SvcWaitProcessWideKeyAtomic }, - { 0x1d, SvcSignalProcessWideKey }, - { 0x1e, SvcGetSystemTick }, - { 0x1f, SvcConnectToNamedPort }, - { 0x21, SvcSendSyncRequest }, - { 0x22, SvcSendSyncRequestWithUserBuffer }, - { 0x25, SvcGetThreadId }, - { 0x26, SvcBreak }, - { 0x27, SvcOutputDebugString }, - { 0x29, SvcGetInfo }, - { 0x2c, SvcMapPhysicalMemory }, - { 0x2d, SvcUnmapPhysicalMemory }, - { 0x32, SvcSetThreadActivity }, - { 0x33, SvcGetThreadContext3 }, - { 0x34, SvcWaitForAddress } - }; - - this.Ns = Ns; - this.Process = Process; - this.Memory = Process.Memory; - - SyncWaits = new ConcurrentDictionary<KThread, AutoResetEvent>(); - } - - static SvcHandler() - { - Rng = new Random(); - } - - public void SvcCall(object sender, AInstExceptionEventArgs e) - { - AThreadState ThreadState = (AThreadState)sender; - - Process.GetThread(ThreadState.Tpidr).LastPc = e.Position; - - if (SvcFuncs.TryGetValue(e.Id, out SvcFunc Func)) - { - Ns.Log.PrintDebug(LogClass.KernelSvc, $"{Func.Method.Name} called."); - - Func(ThreadState); - - Process.Scheduler.Reschedule(Process.GetThread(ThreadState.Tpidr)); - - Ns.Log.PrintDebug(LogClass.KernelSvc, $"{Func.Method.Name} ended."); - } - else - { - Process.PrintStackTrace(ThreadState); - - throw new NotImplementedException(e.Id.ToString("x4")); - } - } - - private KThread GetThread(long Tpidr, int Handle) - { - if ((uint)Handle == SelfThreadHandle) - { - return Process.GetThread(Tpidr); - } - else - { - return Process.HandleTable.GetData<KThread>(Handle); - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.HLE/OsHle/Kernel/SvcMemory.cs b/Ryujinx.HLE/OsHle/Kernel/SvcMemory.cs deleted file mode 100644 index 68d87293..00000000 --- a/Ryujinx.HLE/OsHle/Kernel/SvcMemory.cs +++ /dev/null @@ -1,578 +0,0 @@ -using ChocolArm64.State; -using Ryujinx.HLE.Logging; -using Ryujinx.HLE.OsHle.Handles; - -using static Ryujinx.HLE.OsHle.ErrorCode; - -namespace Ryujinx.HLE.OsHle.Kernel -{ - partial class SvcHandler - { - private void SvcSetHeapSize(AThreadState ThreadState) - { - long Size = (long)ThreadState.X1; - - if ((Size & 0x1fffff) != 0 || Size != (uint)Size) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Heap size 0x{Size:x16} is not aligned!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize); - - return; - } - - long Result = Process.MemoryManager.TrySetHeapSize(Size, out long Position); - - ThreadState.X0 = (ulong)Result; - - if (Result == 0) - { - ThreadState.X1 = (ulong)Position; - } - else - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!"); - } - } - - private void SvcSetMemoryAttribute(AThreadState ThreadState) - { - long Position = (long)ThreadState.X0; - long Size = (long)ThreadState.X1; - - if (!PageAligned(Position)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Address 0x{Position:x16} is not page aligned!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - if (!PageAligned(Size) || Size == 0) - { - Ns.Log.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) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, "Invalid memory attributes!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMaskValue); - - return; - } - - long Result = Process.MemoryManager.SetMemoryAttribute( - Position, - Size, - AttributeMask, - AttributeValue); - - if (Result != 0) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!"); - } - else - { - Memory.StopObservingRegion(Position, Size); - } - - ThreadState.X0 = (ulong)Result; - } - - private void SvcMapMemory(AThreadState ThreadState) - { - long Dst = (long)ThreadState.X0; - long Src = (long)ThreadState.X1; - long Size = (long)ThreadState.X2; - - if (!PageAligned(Src | Dst)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, "Addresses are not page aligned!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - if (!PageAligned(Size) || Size == 0) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Size 0x{Size:x16} is not page aligned or is zero!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize); - - return; - } - - if ((ulong)(Src + Size) <= (ulong)Src || (ulong)(Dst + Size) <= (ulong)Dst) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, "Addresses outside of range!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - if (!InsideAddrSpace(Src, Size)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Src address 0x{Src:x16} out of range!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - if (!InsideNewMapRegion(Dst, Size)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Dst address 0x{Dst:x16} out of range!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange); - - return; - } - - long Result = Process.MemoryManager.Map(Src, Dst, Size); - - if (Result != 0) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!"); - } - - ThreadState.X0 = (ulong)Result; - } - - private void SvcUnmapMemory(AThreadState ThreadState) - { - long Dst = (long)ThreadState.X0; - long Src = (long)ThreadState.X1; - long Size = (long)ThreadState.X2; - - if (!PageAligned(Src | Dst)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, "Addresses are not page aligned!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - if (!PageAligned(Size) || Size == 0) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Size 0x{Size:x16} is not page aligned or is zero!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize); - - return; - } - - if ((ulong)(Src + Size) <= (ulong)Src || (ulong)(Dst + Size) <= (ulong)Dst) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, "Addresses outside of range!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - if (!InsideAddrSpace(Src, Size)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Src address 0x{Src:x16} out of range!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - if (!InsideNewMapRegion(Dst, Size)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Dst address 0x{Dst:x16} out of range!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange); - - return; - } - - long Result = Process.MemoryManager.Unmap(Src, Dst, Size); - - if (Result != 0) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!"); - } - - ThreadState.X0 = (ulong)Result; - } - - private void SvcQueryMemory(AThreadState ThreadState) - { - long InfoPtr = (long)ThreadState.X0; - long Position = (long)ThreadState.X2; - - KMemoryInfo BlkInfo = Process.MemoryManager.QueryMemory(Position); - - Memory.WriteInt64(InfoPtr + 0x00, BlkInfo.Position); - Memory.WriteInt64(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(AThreadState ThreadState) - { - int Handle = (int)ThreadState.X0; - long Position = (long)ThreadState.X1; - long Size = (long)ThreadState.X2; - - if (!PageAligned(Position)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Address 0x{Position:x16} is not page aligned!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - if (!PageAligned(Size) || Size == 0) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Size 0x{Size:x16} is not page aligned or is zero!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize); - - return; - } - - if ((ulong)(Position + Size) <= (ulong)Position) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{Position:x16} / size 0x{Size:x16}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - MemoryPermission Permission = (MemoryPermission)ThreadState.X3; - - if ((Permission | MemoryPermission.Write) != MemoryPermission.ReadAndWrite) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid permission {Permission}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidPermission); - - return; - } - - KSharedMemory SharedMemory = Process.HandleTable.GetData<KSharedMemory>(Handle); - - if (SharedMemory == null) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid shared memory handle 0x{Handle:x8}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - - return; - } - - if (!InsideAddrSpace(Position, Size) || InsideMapRegion(Position, Size) || InsideHeapRegion(Position, Size)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Address 0x{Position:x16} out of range!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - if (SharedMemory.Size != Size) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Size 0x{Size:x16} does not match shared memory size 0x{SharedMemory.Size:16}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize); - - return; - } - - long Result = Process.MemoryManager.MapSharedMemory(SharedMemory, Permission, Position); - - if (Result != 0) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!"); - } - - ThreadState.X0 = (ulong)Result; - } - - private void SvcUnmapSharedMemory(AThreadState ThreadState) - { - int Handle = (int)ThreadState.X0; - long Position = (long)ThreadState.X1; - long Size = (long)ThreadState.X2; - - if (!PageAligned(Position)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Address 0x{Position:x16} is not page aligned!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - if (!PageAligned(Size) || Size == 0) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Size 0x{Size:x16} is not page aligned or is zero!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize); - - return; - } - - if ((ulong)(Position + Size) <= (ulong)Position) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{Position:x16} / size 0x{Size:x16}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - KSharedMemory SharedMemory = Process.HandleTable.GetData<KSharedMemory>(Handle); - - if (SharedMemory == null) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid shared memory handle 0x{Handle:x8}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - - return; - } - - if (!InsideAddrSpace(Position, Size) || InsideMapRegion(Position, Size) || InsideHeapRegion(Position, Size)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Address 0x{Position:x16} out of range!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - long Result = Process.MemoryManager.UnmapSharedMemory(Position, Size); - - if (Result != 0) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!"); - } - - ThreadState.X0 = (ulong)Result; - } - - private void SvcCreateTransferMemory(AThreadState ThreadState) - { - long Position = (long)ThreadState.X1; - long Size = (long)ThreadState.X2; - - if (!PageAligned(Position)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Address 0x{Position:x16} is not page aligned!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - if (!PageAligned(Size) || Size == 0) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Size 0x{Size:x16} is not page aligned or is zero!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - if ((ulong)(Position + Size) <= (ulong)Position) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{Position: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) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid permission {Permission}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidPermission); - - return; - } - - Process.MemoryManager.ReserveTransferMemory(Position, Size, Permission); - - KTransferMemory TransferMemory = new KTransferMemory(Position, Size); - - int Handle = Process.HandleTable.OpenHandle(TransferMemory); - - ThreadState.X0 = 0; - ThreadState.X1 = (ulong)Handle; - } - - private void SvcMapPhysicalMemory(AThreadState ThreadState) - { - long Position = (long)ThreadState.X0; - long Size = (long)ThreadState.X1; - - if (!PageAligned(Position)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Address 0x{Position:x16} is not page aligned!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - if (!PageAligned(Size) || Size == 0) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Size 0x{Size:x16} is not page aligned or is zero!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize); - - return; - } - - if ((ulong)(Position + Size) <= (ulong)Position) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{Position:x16} / size 0x{Size:x16}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - if (!InsideAddrSpace(Position, Size)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid address {Position:x16}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - long Result = Process.MemoryManager.MapPhysicalMemory(Position, Size); - - if (Result != 0) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!"); - } - - ThreadState.X0 = (ulong)Result; - } - - private void SvcUnmapPhysicalMemory(AThreadState ThreadState) - { - long Position = (long)ThreadState.X0; - long Size = (long)ThreadState.X1; - - if (!PageAligned(Position)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Address 0x{Position:x16} is not page aligned!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - if (!PageAligned(Size) || Size == 0) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Size 0x{Size:x16} is not page aligned or is zero!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize); - - return; - } - - if ((ulong)(Position + Size) <= (ulong)Position) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{Position:x16} / size 0x{Size:x16}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - if (!InsideAddrSpace(Position, Size)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid address {Position:x16}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - long Result = Process.MemoryManager.UnmapPhysicalMemory(Position, Size); - - if (Result != 0) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!"); - } - - ThreadState.X0 = (ulong)Result; - } - - private static bool PageAligned(long Position) - { - return (Position & (KMemoryManager.PageSize - 1)) == 0; - } - - private bool InsideAddrSpace(long Position, long Size) - { - ulong Start = (ulong)Position; - ulong End = (ulong)Size + Start; - - return Start >= (ulong)Process.MemoryManager.AddrSpaceStart && - End < (ulong)Process.MemoryManager.AddrSpaceEnd; - } - - private bool InsideMapRegion(long Position, long Size) - { - ulong Start = (ulong)Position; - ulong End = (ulong)Size + Start; - - return Start >= (ulong)Process.MemoryManager.MapRegionStart && - End < (ulong)Process.MemoryManager.MapRegionEnd; - } - - private bool InsideHeapRegion(long Position, long Size) - { - ulong Start = (ulong)Position; - ulong End = (ulong)Size + Start; - - return Start >= (ulong)Process.MemoryManager.HeapRegionStart && - End < (ulong)Process.MemoryManager.HeapRegionEnd; - } - - private bool InsideNewMapRegion(long Position, long Size) - { - ulong Start = (ulong)Position; - ulong End = (ulong)Size + Start; - - return Start >= (ulong)Process.MemoryManager.NewMapRegionStart && - End < (ulong)Process.MemoryManager.NewMapRegionEnd; - } - } -}
\ No newline at end of file diff --git a/Ryujinx.HLE/OsHle/Kernel/SvcSystem.cs b/Ryujinx.HLE/OsHle/Kernel/SvcSystem.cs deleted file mode 100644 index f833745b..00000000 --- a/Ryujinx.HLE/OsHle/Kernel/SvcSystem.cs +++ /dev/null @@ -1,374 +0,0 @@ -using ChocolArm64.Memory; -using ChocolArm64.State; -using Ryujinx.HLE.Logging; -using Ryujinx.HLE.OsHle.Exceptions; -using Ryujinx.HLE.OsHle.Handles; -using Ryujinx.HLE.OsHle.Ipc; -using Ryujinx.HLE.OsHle.Services; -using System; -using System.Threading; - -using static Ryujinx.HLE.OsHle.ErrorCode; - -namespace Ryujinx.HLE.OsHle.Kernel -{ - partial class SvcHandler - { - private const int AllowedCpuIdBitmask = 0b1111; - - private const bool EnableProcessDebugging = false; - - private void SvcExitProcess(AThreadState ThreadState) - { - Ns.Os.ExitProcess(ThreadState.ProcessId); - } - - private void SvcClearEvent(AThreadState ThreadState) - { - int Handle = (int)ThreadState.X0; - - //TODO: Implement events. - - ThreadState.X0 = 0; - } - - private void SvcCloseHandle(AThreadState ThreadState) - { - int Handle = (int)ThreadState.X0; - - object Obj = Process.HandleTable.CloseHandle(Handle); - - if (Obj == null) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid handle 0x{Handle:x8}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - - return; - } - - if (Obj is KSession Session) - { - Session.Dispose(); - } - else if (Obj is KTransferMemory TransferMemory) - { - Process.MemoryManager.ResetTransferMemory( - TransferMemory.Position, - TransferMemory.Size); - } - - ThreadState.X0 = 0; - } - - private void SvcResetSignal(AThreadState ThreadState) - { - int Handle = (int)ThreadState.X0; - - KEvent Event = Process.HandleTable.GetData<KEvent>(Handle); - - if (Event != null) - { - Event.WaitEvent.Reset(); - - ThreadState.X0 = 0; - } - else - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid event handle 0x{Handle:x8}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - } - } - - private void SvcWaitSynchronization(AThreadState ThreadState) - { - long HandlesPtr = (long)ThreadState.X1; - int HandlesCount = (int)ThreadState.X2; - ulong Timeout = ThreadState.X3; - - Ns.Log.PrintDebug(LogClass.KernelSvc, - "HandlesPtr = " + HandlesPtr .ToString("x16") + ", " + - "HandlesCount = " + HandlesCount.ToString("x8") + ", " + - "Timeout = " + Timeout .ToString("x16")); - - if ((uint)HandlesCount > 0x40) - { - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.CountOutOfRange); - - return; - } - - KThread CurrThread = Process.GetThread(ThreadState.Tpidr); - - WaitHandle[] Handles = new WaitHandle[HandlesCount + 1]; - - for (int Index = 0; Index < HandlesCount; Index++) - { - int Handle = Memory.ReadInt32(HandlesPtr + Index * 4); - - KSynchronizationObject SyncObj = Process.HandleTable.GetData<KSynchronizationObject>(Handle); - - if (SyncObj == null) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid handle 0x{Handle:x8}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - - return; - } - - Handles[Index] = SyncObj.WaitEvent; - } - - using (AutoResetEvent WaitEvent = new AutoResetEvent(false)) - { - if (!SyncWaits.TryAdd(CurrThread, WaitEvent)) - { - throw new InvalidOperationException(); - } - - Handles[HandlesCount] = WaitEvent; - - Process.Scheduler.Suspend(CurrThread); - - int HandleIndex; - - ulong Result = 0; - - if (Timeout != ulong.MaxValue) - { - HandleIndex = WaitHandle.WaitAny(Handles, NsTimeConverter.GetTimeMs(Timeout)); - } - else - { - HandleIndex = WaitHandle.WaitAny(Handles); - } - - if (HandleIndex == WaitHandle.WaitTimeout) - { - Result = MakeError(ErrorModule.Kernel, KernelErr.Timeout); - } - else if (HandleIndex == HandlesCount) - { - Result = MakeError(ErrorModule.Kernel, KernelErr.Canceled); - } - - SyncWaits.TryRemove(CurrThread, out _); - - Process.Scheduler.Resume(CurrThread); - - ThreadState.X0 = Result; - - if (Result == 0) - { - ThreadState.X1 = (ulong)HandleIndex; - } - } - } - - private void SvcCancelSynchronization(AThreadState ThreadState) - { - int ThreadHandle = (int)ThreadState.X0; - - KThread Thread = GetThread(ThreadState.Tpidr, ThreadHandle); - - if (Thread == null) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{ThreadHandle:x8}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - - return; - } - - if (SyncWaits.TryRemove(Thread, out AutoResetEvent WaitEvent)) - { - WaitEvent.Set(); - } - - ThreadState.X0 = 0; - } - - private void SvcGetSystemTick(AThreadState ThreadState) - { - ThreadState.X0 = ThreadState.CntpctEl0; - } - - private void SvcConnectToNamedPort(AThreadState ThreadState) - { - long StackPtr = (long)ThreadState.X0; - long NamePtr = (long)ThreadState.X1; - - string Name = AMemoryHelper.ReadAsciiString(Memory, 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(Name), Name); - - ulong Handle = (ulong)Process.HandleTable.OpenHandle(Session); - - ThreadState.X0 = 0; - ThreadState.X1 = Handle; - } - - private void SvcSendSyncRequest(AThreadState ThreadState) - { - SendSyncRequest(ThreadState, ThreadState.Tpidr, 0x100, (int)ThreadState.X0); - } - - private void SvcSendSyncRequestWithUserBuffer(AThreadState ThreadState) - { - SendSyncRequest( - ThreadState, - (long)ThreadState.X0, - (long)ThreadState.X1, - (int)ThreadState.X2); - } - - private void SendSyncRequest(AThreadState ThreadState, long CmdPtr, long Size, int Handle) - { - KThread CurrThread = Process.GetThread(ThreadState.Tpidr); - - byte[] CmdData = Memory.ReadBytes(CmdPtr, Size); - - KSession Session = Process.HandleTable.GetData<KSession>(Handle); - - if (Session != null) - { - Process.Scheduler.Suspend(CurrThread); - - IpcMessage Cmd = new IpcMessage(CmdData, CmdPtr); - - long Result = IpcHandler.IpcCall(Ns, Process, Memory, Session, Cmd, CmdPtr); - - Thread.Yield(); - - Process.Scheduler.Resume(CurrThread); - - ThreadState.X0 = (ulong)Result; - } - else - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid session handle 0x{Handle:x8}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - } - } - - private void SvcBreak(AThreadState ThreadState) - { - long Reason = (long)ThreadState.X0; - long Unknown = (long)ThreadState.X1; - long Info = (long)ThreadState.X2; - - Process.PrintStackTrace(ThreadState); - - throw new GuestBrokeExecutionException(); - } - - private void SvcOutputDebugString(AThreadState ThreadState) - { - long Position = (long)ThreadState.X0; - long Size = (long)ThreadState.X1; - - string Str = AMemoryHelper.ReadAsciiString(Memory, Position, Size); - - Ns.Log.PrintWarning(LogClass.KernelSvc, Str); - - ThreadState.X0 = 0; - } - - private void SvcGetInfo(AThreadState ThreadState) - { - long StackPtr = (long)ThreadState.X0; - int InfoType = (int)ThreadState.X1; - long Handle = (long)ThreadState.X2; - int InfoId = (int)ThreadState.X3; - - //Fail for info not available on older Kernel versions. - if (InfoType == 18 || - InfoType == 19 || - InfoType == 20) - { - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidEnumValue); - - return; - } - - switch (InfoType) - { - case 0: - ThreadState.X1 = AllowedCpuIdBitmask; - break; - - case 2: - ThreadState.X1 = (ulong)Process.MemoryManager.MapRegionStart; - break; - - case 3: - ThreadState.X1 = (ulong)Process.MemoryManager.MapRegionEnd - - (ulong)Process.MemoryManager.MapRegionStart; - break; - - case 4: - ThreadState.X1 = (ulong)Process.MemoryManager.HeapRegionStart; - break; - - case 5: - ThreadState.X1 = (ulong)Process.MemoryManager.HeapRegionEnd - - (ulong)Process.MemoryManager.HeapRegionStart; - break; - - case 6: - ThreadState.X1 = (ulong)Process.Ns.Memory.Allocator.TotalAvailableSize; - break; - - case 7: - ThreadState.X1 = (ulong)Process.Ns.Memory.Allocator.TotalUsedSize; - break; - - case 8: - ThreadState.X1 = EnableProcessDebugging ? 1 : 0; - break; - - case 11: - ThreadState.X1 = (ulong)Rng.Next() + ((ulong)Rng.Next() << 32); - break; - - case 12: - ThreadState.X1 = (ulong)Process.MemoryManager.AddrSpaceStart; - break; - - case 13: - ThreadState.X1 = (ulong)Process.MemoryManager.AddrSpaceEnd - - (ulong)Process.MemoryManager.AddrSpaceStart; - break; - - case 14: - ThreadState.X1 = (ulong)Process.MemoryManager.NewMapRegionStart; - break; - - case 15: - ThreadState.X1 = (ulong)Process.MemoryManager.NewMapRegionEnd - - (ulong)Process.MemoryManager.NewMapRegionStart; - break; - - case 16: - ThreadState.X1 = (ulong)(Process.MetaData?.SystemResourceSize ?? 0); - break; - - case 17: - ThreadState.X1 = (ulong)Process.MemoryManager.PersonalMmHeapUsage; - break; - - default: - Process.PrintStackTrace(ThreadState); - - throw new NotImplementedException($"SvcGetInfo: {InfoType} {Handle:x8} {InfoId}"); - } - - ThreadState.X0 = 0; - } - } -} diff --git a/Ryujinx.HLE/OsHle/Kernel/SvcThread.cs b/Ryujinx.HLE/OsHle/Kernel/SvcThread.cs deleted file mode 100644 index 04524850..00000000 --- a/Ryujinx.HLE/OsHle/Kernel/SvcThread.cs +++ /dev/null @@ -1,386 +0,0 @@ -using ChocolArm64.State; -using Ryujinx.HLE.Logging; -using Ryujinx.HLE.OsHle.Handles; -using System.Threading; - -using static Ryujinx.HLE.OsHle.ErrorCode; - -namespace Ryujinx.HLE.OsHle.Kernel -{ - partial class SvcHandler - { - private void SvcCreateThread(AThreadState ThreadState) - { - long EntryPoint = (long)ThreadState.X1; - long ArgsPtr = (long)ThreadState.X2; - long StackTop = (long)ThreadState.X3; - int Priority = (int)ThreadState.X4; - int ProcessorId = (int)ThreadState.X5; - - if ((uint)Priority > 0x3f) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid priority 0x{Priority:x8}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidPriority); - - return; - } - - if (ProcessorId == -2) - { - //TODO: Get this value from the NPDM file. - ProcessorId = 0; - } - else if ((uint)ProcessorId > 3) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid core id 0x{ProcessorId:x8}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidCoreId); - - return; - } - - int Handle = Process.MakeThread( - EntryPoint, - StackTop, - ArgsPtr, - Priority, - ProcessorId); - - ThreadState.X0 = 0; - ThreadState.X1 = (ulong)Handle; - } - - private void SvcStartThread(AThreadState ThreadState) - { - int Handle = (int)ThreadState.X0; - - KThread NewThread = Process.HandleTable.GetData<KThread>(Handle); - - if (NewThread != null) - { - Process.Scheduler.StartThread(NewThread); - Process.Scheduler.SetReschedule(NewThread.ProcessorId); - - ThreadState.X0 = 0; - } - else - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - } - } - - private void SvcExitThread(AThreadState ThreadState) - { - KThread CurrThread = Process.GetThread(ThreadState.Tpidr); - - CurrThread.Thread.StopExecution(); - } - - private void SvcSleepThread(AThreadState ThreadState) - { - ulong TimeoutNs = ThreadState.X0; - - Ns.Log.PrintDebug(LogClass.KernelSvc, "Timeout = " + TimeoutNs.ToString("x16")); - - KThread CurrThread = Process.GetThread(ThreadState.Tpidr); - - if (TimeoutNs == 0 || TimeoutNs == ulong.MaxValue) - { - Process.Scheduler.Yield(CurrThread); - } - else - { - Process.Scheduler.Suspend(CurrThread); - - Thread.Sleep(NsTimeConverter.GetTimeMs(TimeoutNs)); - - Process.Scheduler.Resume(CurrThread); - } - } - - private void SvcGetThreadPriority(AThreadState ThreadState) - { - int Handle = (int)ThreadState.X1; - - KThread Thread = GetThread(ThreadState.Tpidr, Handle); - - if (Thread != null) - { - ThreadState.X0 = 0; - ThreadState.X1 = (ulong)Thread.ActualPriority; - } - else - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - } - } - - private void SvcSetThreadPriority(AThreadState ThreadState) - { - int Handle = (int)ThreadState.X0; - int Priority = (int)ThreadState.X1; - - Ns.Log.PrintDebug(LogClass.KernelSvc, - "Handle = " + Handle .ToString("x8") + ", " + - "Priority = " + Priority.ToString("x8")); - - KThread Thread = GetThread(ThreadState.Tpidr, Handle); - - if (Thread != null) - { - Thread.SetPriority(Priority); - - ThreadState.X0 = 0; - } - else - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - } - } - - private void SvcGetThreadCoreMask(AThreadState ThreadState) - { - int Handle = (int)ThreadState.X2; - - Ns.Log.PrintDebug(LogClass.KernelSvc, "Handle = " + Handle.ToString("x8")); - - KThread Thread = GetThread(ThreadState.Tpidr, Handle); - - if (Thread != null) - { - ThreadState.X0 = 0; - ThreadState.X1 = (ulong)Thread.IdealCore; - ThreadState.X2 = (ulong)Thread.CoreMask; - } - else - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - } - } - - private void SvcSetThreadCoreMask(AThreadState ThreadState) - { - int Handle = (int)ThreadState.X0; - int IdealCore = (int)ThreadState.X1; - long CoreMask = (long)ThreadState.X2; - - Ns.Log.PrintDebug(LogClass.KernelSvc, - "Handle = " + Handle .ToString("x8") + ", " + - "IdealCore = " + IdealCore.ToString("x8") + ", " + - "CoreMask = " + CoreMask .ToString("x16")); - - KThread Thread = GetThread(ThreadState.Tpidr, Handle); - - if (IdealCore == -2) - { - //TODO: Get this value from the NPDM file. - IdealCore = 0; - - CoreMask = 1 << IdealCore; - } - else - { - if ((uint)IdealCore > 3) - { - if ((IdealCore | 2) != -1) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid core id 0x{IdealCore:x8}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidCoreId); - - return; - } - } - else if ((CoreMask & (1 << IdealCore)) == 0) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid core mask 0x{CoreMask:x8}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMaskValue); - - return; - } - } - - if (Thread == null) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - - return; - } - - //-1 is used as "don't care", so the IdealCore value is ignored. - //-2 is used as "use NPDM default core id" (handled above). - //-3 is used as "don't update", the old IdealCore value is kept. - if (IdealCore == -3 && (CoreMask & (1 << Thread.IdealCore)) == 0) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid core mask 0x{CoreMask:x8}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMaskValue); - - return; - } - - Process.Scheduler.ChangeCore(Thread, IdealCore, (int)CoreMask); - - ThreadState.X0 = 0; - } - - private void SvcGetCurrentProcessorNumber(AThreadState ThreadState) - { - ThreadState.X0 = (ulong)Process.GetThread(ThreadState.Tpidr).ActualCore; - } - - private void SvcGetThreadId(AThreadState ThreadState) - { - int Handle = (int)ThreadState.X1; - - KThread Thread = GetThread(ThreadState.Tpidr, Handle); - - if (Thread != null) - { - ThreadState.X0 = 0; - ThreadState.X1 = (ulong)Thread.ThreadId; - } - else - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - } - } - - private void SvcSetThreadActivity(AThreadState ThreadState) - { - int Handle = (int)ThreadState.X0; - bool Active = (int)ThreadState.X1 == 0; - - KThread Thread = Process.HandleTable.GetData<KThread>(Handle); - - if (Thread != null) - { - Process.Scheduler.SetThreadActivity(Thread, Active); - - ThreadState.X0 = 0; - } - else - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - } - } - - private void SvcGetThreadContext3(AThreadState ThreadState) - { - long Position = (long)ThreadState.X0; - int Handle = (int)ThreadState.X1; - - KThread Thread = Process.HandleTable.GetData<KThread>(Handle); - - if (Thread == null) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - - return; - } - - if (Process.GetThread(ThreadState.Tpidr) == Thread) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Thread handle 0x{Handle:x8} is current thread!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidThread); - - return; - } - - Memory.WriteUInt64(Position + 0x0, ThreadState.X0); - Memory.WriteUInt64(Position + 0x8, ThreadState.X1); - Memory.WriteUInt64(Position + 0x10, ThreadState.X2); - Memory.WriteUInt64(Position + 0x18, ThreadState.X3); - Memory.WriteUInt64(Position + 0x20, ThreadState.X4); - Memory.WriteUInt64(Position + 0x28, ThreadState.X5); - Memory.WriteUInt64(Position + 0x30, ThreadState.X6); - Memory.WriteUInt64(Position + 0x38, ThreadState.X7); - Memory.WriteUInt64(Position + 0x40, ThreadState.X8); - Memory.WriteUInt64(Position + 0x48, ThreadState.X9); - Memory.WriteUInt64(Position + 0x50, ThreadState.X10); - Memory.WriteUInt64(Position + 0x58, ThreadState.X11); - Memory.WriteUInt64(Position + 0x60, ThreadState.X12); - Memory.WriteUInt64(Position + 0x68, ThreadState.X13); - Memory.WriteUInt64(Position + 0x70, ThreadState.X14); - Memory.WriteUInt64(Position + 0x78, ThreadState.X15); - Memory.WriteUInt64(Position + 0x80, ThreadState.X16); - Memory.WriteUInt64(Position + 0x88, ThreadState.X17); - Memory.WriteUInt64(Position + 0x90, ThreadState.X18); - Memory.WriteUInt64(Position + 0x98, ThreadState.X19); - Memory.WriteUInt64(Position + 0xa0, ThreadState.X20); - Memory.WriteUInt64(Position + 0xa8, ThreadState.X21); - Memory.WriteUInt64(Position + 0xb0, ThreadState.X22); - Memory.WriteUInt64(Position + 0xb8, ThreadState.X23); - Memory.WriteUInt64(Position + 0xc0, ThreadState.X24); - Memory.WriteUInt64(Position + 0xc8, ThreadState.X25); - Memory.WriteUInt64(Position + 0xd0, ThreadState.X26); - Memory.WriteUInt64(Position + 0xd8, ThreadState.X27); - Memory.WriteUInt64(Position + 0xe0, ThreadState.X28); - Memory.WriteUInt64(Position + 0xe8, ThreadState.X29); - Memory.WriteUInt64(Position + 0xf0, ThreadState.X30); - Memory.WriteUInt64(Position + 0xf8, ThreadState.X31); - - Memory.WriteInt64(Position + 0x100, Thread.LastPc); - - Memory.WriteUInt64(Position + 0x108, (ulong)ThreadState.Psr); - - Memory.WriteVector128(Position + 0x110, ThreadState.V0); - Memory.WriteVector128(Position + 0x120, ThreadState.V1); - Memory.WriteVector128(Position + 0x130, ThreadState.V2); - Memory.WriteVector128(Position + 0x140, ThreadState.V3); - Memory.WriteVector128(Position + 0x150, ThreadState.V4); - Memory.WriteVector128(Position + 0x160, ThreadState.V5); - Memory.WriteVector128(Position + 0x170, ThreadState.V6); - Memory.WriteVector128(Position + 0x180, ThreadState.V7); - Memory.WriteVector128(Position + 0x190, ThreadState.V8); - Memory.WriteVector128(Position + 0x1a0, ThreadState.V9); - Memory.WriteVector128(Position + 0x1b0, ThreadState.V10); - Memory.WriteVector128(Position + 0x1c0, ThreadState.V11); - Memory.WriteVector128(Position + 0x1d0, ThreadState.V12); - Memory.WriteVector128(Position + 0x1e0, ThreadState.V13); - Memory.WriteVector128(Position + 0x1f0, ThreadState.V14); - Memory.WriteVector128(Position + 0x200, ThreadState.V15); - Memory.WriteVector128(Position + 0x210, ThreadState.V16); - Memory.WriteVector128(Position + 0x220, ThreadState.V17); - Memory.WriteVector128(Position + 0x230, ThreadState.V18); - Memory.WriteVector128(Position + 0x240, ThreadState.V19); - Memory.WriteVector128(Position + 0x250, ThreadState.V20); - Memory.WriteVector128(Position + 0x260, ThreadState.V21); - Memory.WriteVector128(Position + 0x270, ThreadState.V22); - Memory.WriteVector128(Position + 0x280, ThreadState.V23); - Memory.WriteVector128(Position + 0x290, ThreadState.V24); - Memory.WriteVector128(Position + 0x2a0, ThreadState.V25); - Memory.WriteVector128(Position + 0x2b0, ThreadState.V26); - Memory.WriteVector128(Position + 0x2c0, ThreadState.V27); - Memory.WriteVector128(Position + 0x2d0, ThreadState.V28); - Memory.WriteVector128(Position + 0x2e0, ThreadState.V29); - Memory.WriteVector128(Position + 0x2f0, ThreadState.V30); - Memory.WriteVector128(Position + 0x300, ThreadState.V31); - - Memory.WriteInt32(Position + 0x310, ThreadState.Fpcr); - Memory.WriteInt32(Position + 0x314, ThreadState.Fpsr); - Memory.WriteInt64(Position + 0x318, ThreadState.Tpidr); - - ThreadState.X0 = 0; - } - } -}
\ No newline at end of file diff --git a/Ryujinx.HLE/OsHle/Kernel/SvcThreadSync.cs b/Ryujinx.HLE/OsHle/Kernel/SvcThreadSync.cs deleted file mode 100644 index 164a85ca..00000000 --- a/Ryujinx.HLE/OsHle/Kernel/SvcThreadSync.cs +++ /dev/null @@ -1,524 +0,0 @@ -using ChocolArm64.State; -using Ryujinx.HLE.Logging; -using Ryujinx.HLE.OsHle.Handles; -using System; - -using static Ryujinx.HLE.OsHle.ErrorCode; - -namespace Ryujinx.HLE.OsHle.Kernel -{ - partial class SvcHandler - { - private const int MutexHasListenersMask = 0x40000000; - - private void SvcArbitrateLock(AThreadState ThreadState) - { - int OwnerThreadHandle = (int)ThreadState.X0; - long MutexAddress = (long)ThreadState.X1; - int WaitThreadHandle = (int)ThreadState.X2; - - Ns.Log.PrintDebug(LogClass.KernelSvc, - "OwnerThreadHandle = " + OwnerThreadHandle.ToString("x8") + ", " + - "MutexAddress = " + MutexAddress .ToString("x16") + ", " + - "WaitThreadHandle = " + WaitThreadHandle .ToString("x8")); - - if (IsPointingInsideKernel(MutexAddress)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid mutex address 0x{MutexAddress:x16}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - if (IsWordAddressUnaligned(MutexAddress)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Unaligned mutex address 0x{MutexAddress:x16}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - KThread OwnerThread = Process.HandleTable.GetData<KThread>(OwnerThreadHandle); - - if (OwnerThread == null) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid owner thread handle 0x{OwnerThreadHandle:x8}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - - return; - } - - KThread WaitThread = Process.HandleTable.GetData<KThread>(WaitThreadHandle); - - if (WaitThread == null) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid requesting thread handle 0x{WaitThreadHandle:x8}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - - return; - } - - KThread CurrThread = Process.GetThread(ThreadState.Tpidr); - - MutexLock(CurrThread, WaitThread, OwnerThreadHandle, WaitThreadHandle, MutexAddress); - - ThreadState.X0 = 0; - } - - private void SvcArbitrateUnlock(AThreadState ThreadState) - { - long MutexAddress = (long)ThreadState.X0; - - Ns.Log.PrintDebug(LogClass.KernelSvc, "MutexAddress = " + MutexAddress.ToString("x16")); - - if (IsPointingInsideKernel(MutexAddress)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid mutex address 0x{MutexAddress:x16}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - if (IsWordAddressUnaligned(MutexAddress)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Unaligned mutex address 0x{MutexAddress:x16}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - MutexUnlock(Process.GetThread(ThreadState.Tpidr), MutexAddress); - - ThreadState.X0 = 0; - } - - private void SvcWaitProcessWideKeyAtomic(AThreadState ThreadState) - { - long MutexAddress = (long)ThreadState.X0; - long CondVarAddress = (long)ThreadState.X1; - int ThreadHandle = (int)ThreadState.X2; - ulong Timeout = ThreadState.X3; - - Ns.Log.PrintDebug(LogClass.KernelSvc, - "MutexAddress = " + MutexAddress .ToString("x16") + ", " + - "CondVarAddress = " + CondVarAddress.ToString("x16") + ", " + - "ThreadHandle = " + ThreadHandle .ToString("x8") + ", " + - "Timeout = " + Timeout .ToString("x16")); - - if (IsPointingInsideKernel(MutexAddress)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid mutex address 0x{MutexAddress:x16}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - if (IsWordAddressUnaligned(MutexAddress)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Unaligned mutex address 0x{MutexAddress:x16}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - KThread Thread = Process.HandleTable.GetData<KThread>(ThreadHandle); - - if (Thread == null) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{ThreadHandle:x8}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); - - return; - } - - KThread WaitThread = Process.GetThread(ThreadState.Tpidr); - - if (!CondVarWait(WaitThread, ThreadHandle, MutexAddress, CondVarAddress, Timeout)) - { - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.Timeout); - - return; - } - - ThreadState.X0 = 0; - } - - private void SvcSignalProcessWideKey(AThreadState ThreadState) - { - long CondVarAddress = (long)ThreadState.X0; - int Count = (int)ThreadState.X1; - - Ns.Log.PrintDebug(LogClass.KernelSvc, - "CondVarAddress = " + CondVarAddress.ToString("x16") + ", " + - "Count = " + Count .ToString("x8")); - - KThread CurrThread = Process.GetThread(ThreadState.Tpidr); - - CondVarSignal(ThreadState, CurrThread, CondVarAddress, Count); - - ThreadState.X0 = 0; - } - - private void MutexLock( - KThread CurrThread, - KThread WaitThread, - int OwnerThreadHandle, - int WaitThreadHandle, - long MutexAddress) - { - lock (Process.ThreadSyncLock) - { - int MutexValue = Memory.ReadInt32(MutexAddress); - - Ns.Log.PrintDebug(LogClass.KernelSvc, "MutexValue = " + MutexValue.ToString("x8")); - - if (MutexValue != (OwnerThreadHandle | MutexHasListenersMask)) - { - return; - } - - CurrThread.WaitHandle = WaitThreadHandle; - CurrThread.MutexAddress = MutexAddress; - - InsertWaitingMutexThreadUnsafe(OwnerThreadHandle, WaitThread); - } - - Ns.Log.PrintDebug(LogClass.KernelSvc, "Entering wait state..."); - - Process.Scheduler.EnterWait(CurrThread); - } - - private void SvcWaitForAddress(AThreadState ThreadState) - { - long Address = (long)ThreadState.X0; - ArbitrationType Type = (ArbitrationType)ThreadState.X1; - int Value = (int)ThreadState.X2; - ulong Timeout = ThreadState.X3; - - Ns.Log.PrintDebug(LogClass.KernelSvc, - "Address = " + Address.ToString("x16") + ", " + - "ArbitrationType = " + Type .ToString() + ", " + - "Value = " + Value .ToString("x8") + ", " + - "Timeout = " + Timeout.ToString("x16")); - - if (IsPointingInsideKernel(Address)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid address 0x{Address:x16}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); - - return; - } - - if (IsWordAddressUnaligned(Address)) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Unaligned address 0x{Address:x16}!"); - - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); - - return; - } - - switch (Type) - { - case ArbitrationType.WaitIfLessThan: - ThreadState.X0 = AddressArbiter.WaitForAddressIfLessThan(Process, ThreadState, Memory, Address, Value, Timeout, false); - break; - - case ArbitrationType.DecrementAndWaitIfLessThan: - ThreadState.X0 = AddressArbiter.WaitForAddressIfLessThan(Process, ThreadState, Memory, Address, Value, Timeout, true); - break; - - case ArbitrationType.WaitIfEqual: - ThreadState.X0 = AddressArbiter.WaitForAddressIfEqual(Process, ThreadState, Memory, Address, Value, Timeout); - break; - - default: - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidEnumValue); - break; - } - } - - private void MutexUnlock(KThread CurrThread, long MutexAddress) - { - lock (Process.ThreadSyncLock) - { - //This is the new thread that will now own the mutex. - //If no threads are waiting for the lock, then it should be null. - (KThread OwnerThread, int Count) = PopMutexThreadUnsafe(CurrThread, MutexAddress); - - if (OwnerThread == CurrThread) - { - throw new InvalidOperationException(); - } - - if (OwnerThread != null) - { - //Remove all waiting mutex from the old owner, - //and insert then on the new owner. - UpdateMutexOwnerUnsafe(CurrThread, OwnerThread, MutexAddress); - - CurrThread.UpdatePriority(); - - int HasListeners = Count >= 2 ? MutexHasListenersMask : 0; - - Memory.WriteInt32ToSharedAddr(MutexAddress, HasListeners | OwnerThread.WaitHandle); - - OwnerThread.WaitHandle = 0; - OwnerThread.MutexAddress = 0; - OwnerThread.CondVarAddress = 0; - OwnerThread.MutexOwner = null; - - OwnerThread.UpdatePriority(); - - Process.Scheduler.WakeUp(OwnerThread); - - Ns.Log.PrintDebug(LogClass.KernelSvc, "Gave mutex to thread id " + OwnerThread.ThreadId + "!"); - } - else - { - Memory.WriteInt32ToSharedAddr(MutexAddress, 0); - - Ns.Log.PrintDebug(LogClass.KernelSvc, "No threads waiting mutex!"); - } - } - } - - private bool CondVarWait( - KThread WaitThread, - int WaitThreadHandle, - long MutexAddress, - long CondVarAddress, - ulong Timeout) - { - WaitThread.WaitHandle = WaitThreadHandle; - WaitThread.MutexAddress = MutexAddress; - WaitThread.CondVarAddress = CondVarAddress; - - lock (Process.ThreadSyncLock) - { - MutexUnlock(WaitThread, MutexAddress); - - WaitThread.CondVarSignaled = false; - - Process.ThreadArbiterList.Add(WaitThread); - } - - Ns.Log.PrintDebug(LogClass.KernelSvc, "Entering wait state..."); - - if (Timeout != ulong.MaxValue) - { - Process.Scheduler.EnterWait(WaitThread, NsTimeConverter.GetTimeMs(Timeout)); - - lock (Process.ThreadSyncLock) - { - if (!WaitThread.CondVarSignaled || WaitThread.MutexOwner != null) - { - if (WaitThread.MutexOwner != null) - { - WaitThread.MutexOwner.MutexWaiters.Remove(WaitThread); - WaitThread.MutexOwner.UpdatePriority(); - - WaitThread.MutexOwner = null; - } - - Process.ThreadArbiterList.Remove(WaitThread); - - Ns.Log.PrintDebug(LogClass.KernelSvc, "Timed out..."); - - return false; - } - } - } - else - { - Process.Scheduler.EnterWait(WaitThread); - } - - return true; - } - - private void CondVarSignal( - AThreadState ThreadState, - KThread CurrThread, - long CondVarAddress, - int Count) - { - lock (Process.ThreadSyncLock) - { - while (Count == -1 || Count-- > 0) - { - KThread WaitThread = PopCondVarThreadUnsafe(CondVarAddress); - - if (WaitThread == null) - { - Ns.Log.PrintDebug(LogClass.KernelSvc, "No more threads to wake up!"); - - break; - } - - WaitThread.CondVarSignaled = true; - - long MutexAddress = WaitThread.MutexAddress; - - Memory.SetExclusive(ThreadState, MutexAddress); - - int MutexValue = Memory.ReadInt32(MutexAddress); - - while (MutexValue != 0) - { - if (Memory.TestExclusive(ThreadState, MutexAddress)) - { - //Wait until the lock is released. - InsertWaitingMutexThreadUnsafe(MutexValue & ~MutexHasListenersMask, WaitThread); - - Memory.WriteInt32(MutexAddress, MutexValue | MutexHasListenersMask); - - Memory.ClearExclusiveForStore(ThreadState); - - break; - } - - Memory.SetExclusive(ThreadState, MutexAddress); - - MutexValue = Memory.ReadInt32(MutexAddress); - } - - Ns.Log.PrintDebug(LogClass.KernelSvc, "MutexValue = " + MutexValue.ToString("x8")); - - if (MutexValue == 0) - { - //Give the lock to this thread. - Memory.WriteInt32ToSharedAddr(MutexAddress, WaitThread.WaitHandle); - - WaitThread.WaitHandle = 0; - WaitThread.MutexAddress = 0; - WaitThread.CondVarAddress = 0; - - WaitThread.MutexOwner?.UpdatePriority(); - - WaitThread.MutexOwner = null; - - Process.Scheduler.WakeUp(WaitThread); - } - } - } - } - - private void UpdateMutexOwnerUnsafe(KThread CurrThread, KThread NewOwner, long MutexAddress) - { - //Go through all threads waiting for the mutex, - //and update the MutexOwner field to point to the new owner. - for (int Index = 0; Index < CurrThread.MutexWaiters.Count; Index++) - { - KThread Thread = CurrThread.MutexWaiters[Index]; - - if (Thread.MutexAddress == MutexAddress) - { - CurrThread.MutexWaiters.RemoveAt(Index--); - - InsertWaitingMutexThreadUnsafe(NewOwner, Thread); - } - } - } - - private void InsertWaitingMutexThreadUnsafe(int OwnerThreadHandle, KThread WaitThread) - { - KThread OwnerThread = Process.HandleTable.GetData<KThread>(OwnerThreadHandle); - - if (OwnerThread == null) - { - Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{OwnerThreadHandle:x8}!"); - - return; - } - - InsertWaitingMutexThreadUnsafe(OwnerThread, WaitThread); - } - - private void InsertWaitingMutexThreadUnsafe(KThread OwnerThread, KThread WaitThread) - { - WaitThread.MutexOwner = OwnerThread; - - if (!OwnerThread.MutexWaiters.Contains(WaitThread)) - { - OwnerThread.MutexWaiters.Add(WaitThread); - - OwnerThread.UpdatePriority(); - } - } - - private (KThread, int) PopMutexThreadUnsafe(KThread OwnerThread, long MutexAddress) - { - int Count = 0; - - KThread WakeThread = null; - - foreach (KThread Thread in OwnerThread.MutexWaiters) - { - if (Thread.MutexAddress != MutexAddress) - { - continue; - } - - if (WakeThread == null || Thread.ActualPriority < WakeThread.ActualPriority) - { - WakeThread = Thread; - } - - Count++; - } - - if (WakeThread != null) - { - OwnerThread.MutexWaiters.Remove(WakeThread); - } - - return (WakeThread, Count); - } - - private KThread PopCondVarThreadUnsafe(long CondVarAddress) - { - KThread WakeThread = null; - - foreach (KThread Thread in Process.ThreadArbiterList) - { - if (Thread.CondVarAddress != CondVarAddress) - { - continue; - } - - if (WakeThread == null || Thread.ActualPriority < WakeThread.ActualPriority) - { - WakeThread = Thread; - } - } - - if (WakeThread != null) - { - Process.ThreadArbiterList.Remove(WakeThread); - } - - return WakeThread; - } - - private bool IsPointingInsideKernel(long Address) - { - return ((ulong)Address + 0x1000000000) < 0xffffff000; - } - - private bool IsWordAddressUnaligned(long Address) - { - return (Address & 3) != 0; - } - } -}
\ No newline at end of file |
