diff options
| author | TSR Berry <20988865+TSRBerry@users.noreply.github.com> | 2023-04-08 01:22:00 +0200 |
|---|---|---|
| committer | Mary <thog@protonmail.com> | 2023-04-27 23:51:14 +0200 |
| commit | cee712105850ac3385cd0091a923438167433f9f (patch) | |
| tree | 4a5274b21d8b7f938c0d0ce18736d3f2993b11b1 /Ryujinx.HLE/HOS/Kernel/SupervisorCall | |
| parent | cd124bda587ef09668a971fa1cac1c3f0cfc9f21 (diff) | |
Move solution and projects to src
Diffstat (limited to 'Ryujinx.HLE/HOS/Kernel/SupervisorCall')
9 files changed, 0 insertions, 3190 deletions
diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/CodeMemoryOperation.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/CodeMemoryOperation.cs deleted file mode 100644 index 511ee99a..00000000 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/CodeMemoryOperation.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall -{ - enum CodeMemoryOperation : uint - { - Map, - MapToOwner, - Unmap, - UnmapFromOwner - }; -}
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/InfoType.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/InfoType.cs deleted file mode 100644 index 3cf7ba74..00000000 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/InfoType.cs +++ /dev/null @@ -1,34 +0,0 @@ -namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall -{ - enum InfoType : uint - { - CoreMask, - PriorityMask, - AliasRegionAddress, - AliasRegionSize, - HeapRegionAddress, - HeapRegionSize, - TotalMemorySize, - UsedMemorySize, - DebuggerAttached, - ResourceLimit, - IdleTickCount, - RandomEntropy, - AslrRegionAddress, - AslrRegionSize, - StackRegionAddress, - StackRegionSize, - SystemResourceSizeTotal, - SystemResourceSizeUsed, - ProgramId, - // NOTE: Added in 4.0.0, removed in 5.0.0. - InitialProcessIdRange, - UserExceptionContextAddress, - TotalNonSystemMemorySize, - UsedNonSystemMemorySize, - IsApplication, - FreeThreadCount, - ThreadTickCount, - MesosphereCurrentProcess = 65001 - } -} diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/MemoryInfo.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/MemoryInfo.cs deleted file mode 100644 index a71cce1f..00000000 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/MemoryInfo.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Ryujinx.HLE.HOS.Kernel.Memory; - -namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall -{ - struct MemoryInfo - { - public ulong Address; - public ulong Size; - public MemoryState State; - public MemoryAttribute Attribute; - public KMemoryPermission Permission; - public int IpcRefCount; - public int DeviceRefCount; -#pragma warning disable CS0414 - private int _padding; -#pragma warning restore CS0414 - - public MemoryInfo( - ulong address, - ulong size, - MemoryState state, - MemoryAttribute attribute, - KMemoryPermission permission, - int ipcRefCount, - int deviceRefCount) - { - Address = address; - Size = size; - State = state; - Attribute = attribute; - Permission = permission; - IpcRefCount = ipcRefCount; - DeviceRefCount = deviceRefCount; - _padding = 0; - } - } -}
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/PointerSizedAttribute.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/PointerSizedAttribute.cs deleted file mode 100644 index 154164fb..00000000 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/PointerSizedAttribute.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System; - -namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall -{ - [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] - class PointerSizedAttribute : Attribute - { - } -} diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcAttribute.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcAttribute.cs deleted file mode 100644 index b8839d1d..00000000 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcAttribute.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; - -namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall -{ - [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] - class SvcAttribute : Attribute - { - public int Id { get; } - - public SvcAttribute(int id) - { - Id = id; - } - } -} diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcImplAttribute.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcImplAttribute.cs deleted file mode 100644 index a32d851f..00000000 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcImplAttribute.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System; - -namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall -{ - [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] - class SvcImplAttribute : Attribute - { - } -} diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs deleted file mode 100644 index 3163c348..00000000 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs +++ /dev/null @@ -1,3010 +0,0 @@ -using Ryujinx.Common; -using Ryujinx.Common.Logging; -using Ryujinx.Cpu; -using Ryujinx.HLE.Exceptions; -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.Horizon.Common; -using System; -using System.Buffers; -using System.Threading; - -namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall -{ - [SvcImpl] - class Syscall : ISyscallApi - { - private readonly KernelContext _context; - - public Syscall(KernelContext context) - { - _context = context; - } - - // Process - - [Svc(0x24)] - public Result GetProcessId(out ulong pid, int handle) - { - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - KProcess process = currentProcess.HandleTable.GetKProcess(handle); - - if (process == null) - { - KThread thread = currentProcess.HandleTable.GetKThread(handle); - - if (thread != null) - { - process = thread.Owner; - } - - // TODO: KDebugEvent. - } - - pid = process?.Pid ?? 0; - - return process != null - ? Result.Success - : KernelResult.InvalidHandle; - } - - public Result CreateProcess( - out int handle, - ProcessCreationInfo info, - ReadOnlySpan<uint> capabilities, - IProcessContextFactory contextFactory, - ThreadStart customThreadStart = null) - { - handle = 0; - - if ((info.Flags & ~ProcessCreationFlags.All) != 0) - { - return KernelResult.InvalidEnumValue; - } - - // TODO: Address space check. - - if ((info.Flags & ProcessCreationFlags.PoolPartitionMask) > ProcessCreationFlags.PoolPartitionSystemNonSecure) - { - return KernelResult.InvalidEnumValue; - } - - if ((info.CodeAddress & 0x1fffff) != 0) - { - return KernelResult.InvalidAddress; - } - - if (info.CodePagesCount < 0 || info.SystemResourcePagesCount < 0) - { - return KernelResult.InvalidSize; - } - - if (info.Flags.HasFlag(ProcessCreationFlags.OptimizeMemoryAllocation) && - !info.Flags.HasFlag(ProcessCreationFlags.IsApplication)) - { - return KernelResult.InvalidThread; - } - - KHandleTable handleTable = KernelStatic.GetCurrentProcess().HandleTable; - - KProcess process = new KProcess(_context); - - using var _ = new OnScopeExit(process.DecrementReferenceCount); - - KResourceLimit resourceLimit; - - if (info.ResourceLimitHandle != 0) - { - resourceLimit = handleTable.GetObject<KResourceLimit>(info.ResourceLimitHandle); - - if (resourceLimit == null) - { - return KernelResult.InvalidHandle; - } - } - else - { - resourceLimit = _context.ResourceLimit; - } - - MemoryRegion memRegion = (info.Flags & ProcessCreationFlags.PoolPartitionMask) switch - { - ProcessCreationFlags.PoolPartitionApplication => MemoryRegion.Application, - ProcessCreationFlags.PoolPartitionApplet => MemoryRegion.Applet, - ProcessCreationFlags.PoolPartitionSystem => MemoryRegion.Service, - ProcessCreationFlags.PoolPartitionSystemNonSecure => MemoryRegion.NvServices, - _ => MemoryRegion.NvServices - }; - - Result result = process.Initialize( - info, - capabilities, - resourceLimit, - memRegion, - contextFactory, - customThreadStart); - - if (result != Result.Success) - { - return result; - } - - _context.Processes.TryAdd(process.Pid, process); - - return handleTable.GenerateHandle(process, out handle); - } - - public Result StartProcess(int handle, int priority, int cpuCore, ulong mainThreadStackSize) - { - KProcess process = KernelStatic.GetCurrentProcess().HandleTable.GetObject<KProcess>(handle); - - if (process == null) - { - return KernelResult.InvalidHandle; - } - - if ((uint)cpuCore >= KScheduler.CpuCoresCount || !process.IsCpuCoreAllowed(cpuCore)) - { - return KernelResult.InvalidCpuCore; - } - - if ((uint)priority >= KScheduler.PrioritiesCount || !process.IsPriorityAllowed(priority)) - { - return KernelResult.InvalidPriority; - } - - process.DefaultCpuCore = cpuCore; - - Result result = process.Start(priority, mainThreadStackSize); - - if (result != Result.Success) - { - return result; - } - - process.IncrementReferenceCount(); - - return Result.Success; - } - - [Svc(0x5f)] - public Result FlushProcessDataCache(int processHandle, ulong address, ulong size) - { - // FIXME: This needs to be implemented as ARMv7 doesn't have any way to do cache maintenance operations on EL0. - // As we don't support (and don't actually need) to flush the cache, this is stubbed. - return Result.Success; - } - - // IPC - - [Svc(0x1f)] - public Result ConnectToNamedPort(out int handle, [PointerSized] ulong namePtr) - { - handle = 0; - - if (!KernelTransfer.UserToKernelString(out string name, namePtr, 12)) - { - return KernelResult.UserCopyFailed; - } - - return ConnectToNamedPort(out handle, name); - } - - public Result ConnectToNamedPort(out int handle, string name) - { - handle = 0; - - if (name.Length > 11) - { - return KernelResult.MaximumExceeded; - } - - KAutoObject autoObj = KAutoObject.FindNamedObject(_context, name); - - if (autoObj is not KClientPort clientPort) - { - return KernelResult.NotFound; - } - - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - Result result = currentProcess.HandleTable.ReserveHandle(out handle); - - if (result != Result.Success) - { - return result; - } - - result = clientPort.Connect(out KClientSession clientSession); - - if (result != Result.Success) - { - currentProcess.HandleTable.CancelHandleReservation(handle); - - return result; - } - - currentProcess.HandleTable.SetReservedHandleObj(handle, clientSession); - - clientSession.DecrementReferenceCount(); - - return result; - } - - [Svc(0x21)] - public Result SendSyncRequest(int handle) - { - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - KClientSession session = currentProcess.HandleTable.GetObject<KClientSession>(handle); - - if (session == null) - { - return KernelResult.InvalidHandle; - } - - return session.SendSyncRequest(); - } - - [Svc(0x22)] - public Result SendSyncRequestWithUserBuffer( - [PointerSized] ulong messagePtr, - [PointerSized] ulong messageSize, - int handle) - { - if (!PageAligned(messagePtr)) - { - return KernelResult.InvalidAddress; - } - - if (!PageAligned(messageSize) || messageSize == 0) - { - return KernelResult.InvalidSize; - } - - if (messagePtr + messageSize <= messagePtr) - { - return KernelResult.InvalidMemState; - } - - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - Result result = currentProcess.MemoryManager.BorrowIpcBuffer(messagePtr, messageSize); - - if (result != Result.Success) - { - return result; - } - - KClientSession session = currentProcess.HandleTable.GetObject<KClientSession>(handle); - - if (session == null) - { - result = KernelResult.InvalidHandle; - } - else - { - result = session.SendSyncRequest(messagePtr, messageSize); - } - - Result result2 = currentProcess.MemoryManager.UnborrowIpcBuffer(messagePtr, messageSize); - - if (result == Result.Success) - { - result = result2; - } - - return result; - } - - [Svc(0x23)] - public Result SendAsyncRequestWithUserBuffer( - out int doneEventHandle, - [PointerSized] ulong messagePtr, - [PointerSized] ulong messageSize, - int handle) - { - doneEventHandle = 0; - - if (!PageAligned(messagePtr)) - { - return KernelResult.InvalidAddress; - } - - if (!PageAligned(messageSize) || messageSize == 0) - { - return KernelResult.InvalidSize; - } - - if (messagePtr + messageSize <= messagePtr) - { - return KernelResult.InvalidMemState; - } - - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - Result result = currentProcess.MemoryManager.BorrowIpcBuffer(messagePtr, messageSize); - - if (result != Result.Success) - { - return result; - } - - KResourceLimit resourceLimit = currentProcess.ResourceLimit; - - if (resourceLimit != null && !resourceLimit.Reserve(LimitableResource.Event, 1)) - { - currentProcess.MemoryManager.UnborrowIpcBuffer(messagePtr, messageSize); - - return KernelResult.ResLimitExceeded; - } - - KClientSession session = currentProcess.HandleTable.GetObject<KClientSession>(handle); - - if (session == null) - { - result = KernelResult.InvalidHandle; - } - else - { - KEvent doneEvent = new KEvent(_context); - - result = currentProcess.HandleTable.GenerateHandle(doneEvent.ReadableEvent, out doneEventHandle); - - if (result == Result.Success) - { - result = session.SendAsyncRequest(doneEvent.WritableEvent, messagePtr, messageSize); - - if (result != Result.Success) - { - currentProcess.HandleTable.CloseHandle(doneEventHandle); - } - } - } - - if (result != Result.Success) - { - resourceLimit?.Release(LimitableResource.Event, 1); - - currentProcess.MemoryManager.UnborrowIpcBuffer(messagePtr, messageSize); - } - - return result; - } - - [Svc(0x40)] - public Result CreateSession( - out int serverSessionHandle, - out int clientSessionHandle, - bool isLight, - [PointerSized] ulong namePtr) - { - return CreateSession(out serverSessionHandle, out clientSessionHandle, isLight, null); - } - - public Result CreateSession( - out int serverSessionHandle, - out int clientSessionHandle, - bool isLight, - string name) - { - serverSessionHandle = 0; - clientSessionHandle = 0; - - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - KResourceLimit resourceLimit = currentProcess.ResourceLimit; - - if (resourceLimit != null && !resourceLimit.Reserve(LimitableResource.Session, 1)) - { - return KernelResult.ResLimitExceeded; - } - - Result result; - - if (isLight) - { - KLightSession session = new KLightSession(_context); - - result = currentProcess.HandleTable.GenerateHandle(session.ServerSession, out serverSessionHandle); - - if (result == Result.Success) - { - result = currentProcess.HandleTable.GenerateHandle(session.ClientSession, out clientSessionHandle); - - if (result != Result.Success) - { - currentProcess.HandleTable.CloseHandle(serverSessionHandle); - - serverSessionHandle = 0; - } - } - - session.ServerSession.DecrementReferenceCount(); - session.ClientSession.DecrementReferenceCount(); - } - else - { - KSession session = new KSession(_context); - - result = currentProcess.HandleTable.GenerateHandle(session.ServerSession, out serverSessionHandle); - - if (result == Result.Success) - { - result = currentProcess.HandleTable.GenerateHandle(session.ClientSession, out clientSessionHandle); - - if (result != Result.Success) - { - currentProcess.HandleTable.CloseHandle(serverSessionHandle); - - serverSessionHandle = 0; - } - } - - session.ServerSession.DecrementReferenceCount(); - session.ClientSession.DecrementReferenceCount(); - } - - return result; - } - - [Svc(0x41)] - public Result AcceptSession(out int sessionHandle, int portHandle) - { - sessionHandle = 0; - - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - KServerPort serverPort = currentProcess.HandleTable.GetObject<KServerPort>(portHandle); - - if (serverPort == null) - { - return KernelResult.InvalidHandle; - } - - Result result = currentProcess.HandleTable.ReserveHandle(out int handle); - - if (result != Result.Success) - { - return result; - } - - KAutoObject session; - - if (serverPort.IsLight) - { - session = serverPort.AcceptIncomingLightConnection(); - } - else - { - session = serverPort.AcceptIncomingConnection(); - } - - if (session != null) - { - currentProcess.HandleTable.SetReservedHandleObj(handle, session); - - session.DecrementReferenceCount(); - - sessionHandle = handle; - - result = Result.Success; - } - else - { - currentProcess.HandleTable.CancelHandleReservation(handle); - - result = KernelResult.NotFound; - } - - return result; - } - - [Svc(0x43)] - public Result ReplyAndReceive( - out int handleIndex, - [PointerSized] ulong handlesPtr, - int handlesCount, - int replyTargetHandle, - long timeout) - { - handleIndex = 0; - - if ((uint)handlesCount > 0x40) - { - return KernelResult.MaximumExceeded; - } - - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - ulong copySize = (ulong)((long)handlesCount * 4); - - if (!currentProcess.MemoryManager.InsideAddrSpace(handlesPtr, copySize)) - { - return KernelResult.UserCopyFailed; - } - - if (handlesPtr + copySize < handlesPtr) - { - return KernelResult.UserCopyFailed; - } - - int[] handles = new int[handlesCount]; - - if (!KernelTransfer.UserToKernelArray<int>(handlesPtr, handles)) - { - return KernelResult.UserCopyFailed; - } - - if (timeout > 0) - { - timeout += KTimeManager.DefaultTimeIncrementNanoseconds; - } - - return ReplyAndReceive(out handleIndex, handles, replyTargetHandle, timeout); - } - - public Result ReplyAndReceive(out int handleIndex, ReadOnlySpan<int> handles, int replyTargetHandle, long timeout) - { - handleIndex = 0; - - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - KSynchronizationObject[] syncObjsArray = ArrayPool<KSynchronizationObject>.Shared.Rent(handles.Length); - - Span<KSynchronizationObject> syncObjs = syncObjsArray.AsSpan(0, handles.Length); - - for (int index = 0; index < handles.Length; index++) - { - KSynchronizationObject obj = currentProcess.HandleTable.GetObject<KSynchronizationObject>(handles[index]); - - if (obj == null) - { - return KernelResult.InvalidHandle; - } - - syncObjs[index] = obj; - } - - Result result = Result.Success; - - if (replyTargetHandle != 0) - { - KServerSession replyTarget = currentProcess.HandleTable.GetObject<KServerSession>(replyTargetHandle); - - if (replyTarget == null) - { - result = KernelResult.InvalidHandle; - } - else - { - result = replyTarget.Reply(); - } - } - - if (result == Result.Success) - { - if (timeout > 0) - { - timeout += KTimeManager.DefaultTimeIncrementNanoseconds; - } - - while ((result = _context.Synchronization.WaitFor(syncObjs, timeout, out handleIndex)) == Result.Success) - { - KServerSession session = currentProcess.HandleTable.GetObject<KServerSession>(handles[handleIndex]); - - if (session == null) - { - break; - } - - if ((result = session.Receive()) != KernelResult.NotFound) - { - break; - } - } - } - - ArrayPool<KSynchronizationObject>.Shared.Return(syncObjsArray); - - return result; - } - - [Svc(0x44)] - public Result ReplyAndReceiveWithUserBuffer( - out int handleIndex, - [PointerSized] ulong messagePtr, - [PointerSized] ulong messageSize, - [PointerSized] ulong handlesPtr, - int handlesCount, - int replyTargetHandle, - long timeout) - { - handleIndex = 0; - - if ((uint)handlesCount > 0x40) - { - return KernelResult.MaximumExceeded; - } - - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - ulong copySize = (ulong)((long)handlesCount * 4); - - if (!currentProcess.MemoryManager.InsideAddrSpace(handlesPtr, copySize)) - { - return KernelResult.UserCopyFailed; - } - - if (handlesPtr + copySize < handlesPtr) - { - return KernelResult.UserCopyFailed; - } - - Result result = currentProcess.MemoryManager.BorrowIpcBuffer(messagePtr, messageSize); - - if (result != Result.Success) - { - return result; - } - - int[] handles = new int[handlesCount]; - - if (!KernelTransfer.UserToKernelArray<int>(handlesPtr, handles)) - { - currentProcess.MemoryManager.UnborrowIpcBuffer(messagePtr, messageSize); - - return KernelResult.UserCopyFailed; - } - - KSynchronizationObject[] syncObjs = new KSynchronizationObject[handlesCount]; - - for (int index = 0; index < handlesCount; index++) - { - KSynchronizationObject obj = currentProcess.HandleTable.GetObject<KSynchronizationObject>(handles[index]); - - if (obj == null) - { - currentProcess.MemoryManager.UnborrowIpcBuffer(messagePtr, messageSize); - - return KernelResult.InvalidHandle; - } - - syncObjs[index] = obj; - } - - if (replyTargetHandle != 0) - { - KServerSession replyTarget = currentProcess.HandleTable.GetObject<KServerSession>(replyTargetHandle); - - if (replyTarget == null) - { - result = KernelResult.InvalidHandle; - } - else - { - result = replyTarget.Reply(messagePtr, messageSize); - } - } - - if (result == Result.Success) - { - if (timeout > 0) - { - timeout += KTimeManager.DefaultTimeIncrementNanoseconds; - } - - while ((result = _context.Synchronization.WaitFor(syncObjs, timeout, out handleIndex)) == Result.Success) - { - KServerSession session = currentProcess.HandleTable.GetObject<KServerSession>(handles[handleIndex]); - - if (session == null) - { - break; - } - - if ((result = session.Receive(messagePtr, messageSize)) != KernelResult.NotFound) - { - break; - } - } - } - - currentProcess.MemoryManager.UnborrowIpcBuffer(messagePtr, messageSize); - - return result; - } - - [Svc(0x70)] - public Result CreatePort( - out int serverPortHandle, - out int clientPortHandle, - int maxSessions, - bool isLight, - [PointerSized] ulong namePtr) - { - // The kernel doesn't use the name pointer, so we can just pass null as the name. - return CreatePort(out serverPortHandle, out clientPortHandle, maxSessions, isLight, null); - } - - public Result CreatePort( - out int serverPortHandle, - out int clientPortHandle, - int maxSessions, - bool isLight, - string name) - { - serverPortHandle = clientPortHandle = 0; - - if (maxSessions < 1) - { - return KernelResult.MaximumExceeded; - } - - KPort port = new KPort(_context, maxSessions, isLight, name); - - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - Result result = currentProcess.HandleTable.GenerateHandle(port.ClientPort, out clientPortHandle); - - if (result != Result.Success) - { - return result; - } - - result = currentProcess.HandleTable.GenerateHandle(port.ServerPort, out serverPortHandle); - - if (result != Result.Success) - { - currentProcess.HandleTable.CloseHandle(clientPortHandle); - } - - return result; - } - - [Svc(0x71)] - public Result ManageNamedPort(out int handle, [PointerSized] ulong namePtr, int maxSessions) - { - handle = 0; - - if (!KernelTransfer.UserToKernelString(out string name, namePtr, 12)) - { - return KernelResult.UserCopyFailed; - } - - if (name.Length > 11) - { - return KernelResult.MaximumExceeded; - } - - return ManageNamedPort(out handle, name, maxSessions); - } - - public Result ManageNamedPort(out int handle, string name, int maxSessions) - { - handle = 0; - - if (maxSessions < 0) - { - return KernelResult.MaximumExceeded; - } - - if (maxSessions == 0) - { - return KAutoObject.RemoveName(_context, name); - } - - KPort port = new KPort(_context, maxSessions, false, null); - - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - Result result = currentProcess.HandleTable.GenerateHandle(port.ServerPort, out handle); - - if (result != Result.Success) - { - return result; - } - - result = port.ClientPort.SetName(name); - - if (result != Result.Success) - { - currentProcess.HandleTable.CloseHandle(handle); - } - - return result; - } - - [Svc(0x72)] - public Result ConnectToPort(out int clientSessionHandle, int clientPortHandle) - { - clientSessionHandle = 0; - - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - KClientPort clientPort = currentProcess.HandleTable.GetObject<KClientPort>(clientPortHandle); - - if (clientPort == null) - { - return KernelResult.InvalidHandle; - } - - Result result = currentProcess.HandleTable.ReserveHandle(out int handle); - - if (result != Result.Success) - { - return result; - } - - KAutoObject session; - - if (clientPort.IsLight) - { - result = clientPort.ConnectLight(out KLightClientSession clientSession); - - session = clientSession; - } - else - { - result = clientPort.Connect(out KClientSession clientSession); - - session = clientSession; - } - - if (result != Result.Success) - { - currentProcess.HandleTable.CancelHandleReservation(handle); - - return result; - } - - currentProcess.HandleTable.SetReservedHandleObj(handle, session); - - session.DecrementReferenceCount(); - - clientSessionHandle = handle; - - return result; - } - - // Memory - - [Svc(1)] - public Result SetHeapSize([PointerSized] out ulong address, [PointerSized] ulong size) - { - if ((size & 0xfffffffe001fffff) != 0) - { - address = 0; - - return KernelResult.InvalidSize; - } - - KProcess process = KernelStatic.GetCurrentProcess(); - - return process.MemoryManager.SetHeapSize(size, out address); - } - - [Svc(2)] - public Result SetMemoryPermission([PointerSized] ulong address, [PointerSized] ulong size, KMemoryPermission permission) - { - if (!PageAligned(address)) - { - return KernelResult.InvalidAddress; - } - - if (!PageAligned(size) || size == 0) - { - return KernelResult.InvalidSize; - } - - if (address + size <= address) - { - return KernelResult.InvalidMemState; - } - - if (permission != KMemoryPermission.None && (permission | KMemoryPermission.Write) != KMemoryPermission.ReadAndWrite) - { - return KernelResult.InvalidPermission; - } - - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - if (!currentProcess.MemoryManager.InsideAddrSpace(address, size)) - { - return KernelResult.InvalidMemState; - } - - return currentProcess.MemoryManager.SetMemoryPermission(address, size, permission); - } - - [Svc(3)] - public Result SetMemoryAttribute( - [PointerSized] ulong address, - [PointerSized] ulong size, - MemoryAttribute attributeMask, - MemoryAttribute attributeValue) - { - if (!PageAligned(address)) - { - 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; - } - - KProcess process = KernelStatic.GetCurrentProcess(); - - if (!process.MemoryManager.InsideAddrSpace(address, size)) - { - return KernelResult.InvalidMemState; - } - - Result result = process.MemoryManager.SetMemoryAttribute( - address, - size, - attributeMask, - attributeValue); - - return result; - } - - [Svc(4)] - public Result MapMemory([PointerSized] ulong dst, [PointerSized] ulong src, [PointerSized] 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 = KernelStatic.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; - } - - KProcess process = KernelStatic.GetCurrentProcess(); - - return process.MemoryManager.Map(dst, src, size); - } - - [Svc(5)] - public Result UnmapMemory([PointerSized] ulong dst, [PointerSized] ulong src, [PointerSized] 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 = KernelStatic.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; - } - - KProcess process = KernelStatic.GetCurrentProcess(); - - return process.MemoryManager.Unmap(dst, src, size); - } - - [Svc(6)] - public Result QueryMemory([PointerSized] ulong infoPtr, [PointerSized] out ulong pageInfo, [PointerSized] ulong address) - { - Result result = QueryMemory(out MemoryInfo info, out pageInfo, address); - - if (result == Result.Success) - { - return KernelTransfer.KernelToUser(infoPtr, info) - ? Result.Success - : KernelResult.InvalidMemState; - } - - return result; - } - - public Result QueryMemory(out MemoryInfo info, out ulong pageInfo, ulong address) - { - KProcess process = KernelStatic.GetCurrentProcess(); - - KMemoryInfo blockInfo = process.MemoryManager.QueryMemory(address); - - info = new MemoryInfo( - blockInfo.Address, - blockInfo.Size, - blockInfo.State & MemoryState.UserMask, - blockInfo.Attribute, - blockInfo.Permission & KMemoryPermission.UserMask, - blockInfo.IpcRefCount, - blockInfo.DeviceRefCount); - - pageInfo = 0; - - return Result.Success; - } - - [Svc(0x13)] - public Result MapSharedMemory(int handle, [PointerSized] ulong address, [PointerSized] ulong size, KMemoryPermission permission) - { - if (!PageAligned(address)) - { - return KernelResult.InvalidAddress; - } - - if (!PageAligned(size) || size == 0) - { - return KernelResult.InvalidSize; - } - - if (address + size <= address) - { - return KernelResult.InvalidMemState; - } - - if ((permission | KMemoryPermission.Write) != KMemoryPermission.ReadAndWrite) - { - return KernelResult.InvalidPermission; - } - - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - KSharedMemory sharedMemory = currentProcess.HandleTable.GetObject<KSharedMemory>(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); - } - - [Svc(0x14)] - public Result UnmapSharedMemory(int handle, [PointerSized] ulong address, [PointerSized] 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 = KernelStatic.GetCurrentProcess(); - - KSharedMemory sharedMemory = currentProcess.HandleTable.GetObject<KSharedMemory>(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); - } - - [Svc(0x15)] - public Result CreateTransferMemory(out int handle, [PointerSized] ulong address, [PointerSized] ulong size, KMemoryPermission permission) - { - 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 > KMemoryPermission.ReadAndWrite || permission == KMemoryPermission.Write) - { - return KernelResult.InvalidPermission; - } - - KProcess process = KernelStatic.GetCurrentProcess(); - - KResourceLimit resourceLimit = process.ResourceLimit; - - if (resourceLimit != null && !resourceLimit.Reserve(LimitableResource.TransferMemory, 1)) - { - return KernelResult.ResLimitExceeded; - } - - void CleanUpForError() - { - resourceLimit?.Release(LimitableResource.TransferMemory, 1); - } - - if (!process.MemoryManager.InsideAddrSpace(address, size)) - { - CleanUpForError(); - - return KernelResult.InvalidMemState; - } - - KTransferMemory transferMemory = new KTransferMemory(_context); - - Result result = transferMemory.Initialize(address, size, permission); - - if (result != Result.Success) - { - CleanUpForError(); - - return result; - } - - result = process.HandleTable.GenerateHandle(transferMemory, out handle); - - transferMemory.DecrementReferenceCount(); - - return result; - } - - [Svc(0x51)] - public Result MapTransferMemory(int handle, [PointerSized] ulong address, [PointerSized] ulong size, KMemoryPermission permission) - { - if (!PageAligned(address)) - { - return KernelResult.InvalidAddress; - } - - if (!PageAligned(size) || size == 0) - { - return KernelResult.InvalidSize; - } - - if (address + size <= address) - { - return KernelResult.InvalidMemState; - } - - if (permission > KMemoryPermission.ReadAndWrite || permission == KMemoryPermission.Write) - { - return KernelResult.InvalidPermission; - } - - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - KTransferMemory transferMemory = currentProcess.HandleTable.GetObject<KTransferMemory>(handle); - - if (transferMemory == null) - { - return KernelResult.InvalidHandle; - } - - if (currentProcess.MemoryManager.IsInvalidRegion(address, size) || - currentProcess.MemoryManager.InsideHeapRegion(address, size) || - currentProcess.MemoryManager.InsideAliasRegion(address, size)) - { - return KernelResult.InvalidMemRange; - } - - return transferMemory.MapIntoProcess( - currentProcess.MemoryManager, - address, - size, - currentProcess, - permission); - } - - [Svc(0x52)] - public Result UnmapTransferMemory(int handle, [PointerSized] ulong address, [PointerSized] 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 = KernelStatic.GetCurrentProcess(); - - KTransferMemory transferMemory = currentProcess.HandleTable.GetObject<KTransferMemory>(handle); - - if (transferMemory == null) - { - return KernelResult.InvalidHandle; - } - - if (currentProcess.MemoryManager.IsInvalidRegion(address, size) || - currentProcess.MemoryManager.InsideHeapRegion(address, size) || - currentProcess.MemoryManager.InsideAliasRegion(address, size)) - { - return KernelResult.InvalidMemRange; - } - - return transferMemory.UnmapFromProcess( - currentProcess.MemoryManager, - address, - size, - currentProcess); - } - - [Svc(0x2c)] - public Result MapPhysicalMemory([PointerSized] ulong address, [PointerSized] 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 = KernelStatic.GetCurrentProcess(); - - if ((currentProcess.PersonalMmHeapPagesCount & 0xfffffffffffff) == 0) - { - return KernelResult.InvalidState; - } - - if (!currentProcess.MemoryManager.InsideAddrSpace(address, size) || - currentProcess.MemoryManager.OutsideAliasRegion(address, size)) - { - return KernelResult.InvalidMemRange; - } - - KProcess process = KernelStatic.GetCurrentProcess(); - - return process.MemoryManager.MapPhysicalMemory(address, size); - } - - [Svc(0x2d)] - public Result UnmapPhysicalMemory([PointerSized] ulong address, [PointerSized] 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 = KernelStatic.GetCurrentProcess(); - - if ((currentProcess.PersonalMmHeapPagesCount & 0xfffffffffffff) == 0) - { - return KernelResult.InvalidState; - } - - if (!currentProcess.MemoryManager.InsideAddrSpace(address, size) || - currentProcess.MemoryManager.OutsideAliasRegion(address, size)) - { - return KernelResult.InvalidMemRange; - } - - KProcess process = KernelStatic.GetCurrentProcess(); - - return process.MemoryManager.UnmapPhysicalMemory(address, size); - } - - [Svc(0x4b)] - public Result CreateCodeMemory(out int handle, [PointerSized] ulong address, [PointerSized] ulong size) - { - handle = 0; - - if (!PageAligned(address)) - { - return KernelResult.InvalidAddress; - } - - if (!PageAligned(size) || size == 0) - { - return KernelResult.InvalidSize; - } - - if (size + address <= address) - { - return KernelResult.InvalidMemState; - } - - KCodeMemory codeMemory = new KCodeMemory(_context); - - using var _ = new OnScopeExit(codeMemory.DecrementReferenceCount); - - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - if (!currentProcess.MemoryManager.InsideAddrSpace(address, size)) - { - return KernelResult.InvalidMemState; - } - - Result result = codeMemory.Initialize(address, size); - - if (result != Result.Success) - { - return result; - } - - return currentProcess.HandleTable.GenerateHandle(codeMemory, out handle); - } - - [Svc(0x4c)] - public Result ControlCodeMemory( - int handle, - CodeMemoryOperation op, - ulong address, - ulong size, - KMemoryPermission permission) - { - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - KCodeMemory codeMemory = currentProcess.HandleTable.GetObject<KCodeMemory>(handle); - - // Newer versions of the kernel also returns an error here if the owner and process - // where the operation will happen are the same. We do not return an error here - // for homebrew because some of them requires this to be patched out to work (for JIT). - if (codeMemory == null || (!currentProcess.AllowCodeMemoryForJit && codeMemory.Owner == currentProcess)) - { - return KernelResult.InvalidHandle; - } - - switch (op) - { - case CodeMemoryOperation.Map: - if (!currentProcess.MemoryManager.CanContain(address, size, MemoryState.CodeWritable)) - { - return KernelResult.InvalidMemRange; - } - - if (permission != KMemoryPermission.ReadAndWrite) - { - return KernelResult.InvalidPermission; - } - - return codeMemory.Map(address, size, permission); - - case CodeMemoryOperation.MapToOwner: - if (!currentProcess.MemoryManager.CanContain(address, size, MemoryState.CodeReadOnly)) - { - return KernelResult.InvalidMemRange; - } - - if (permission != KMemoryPermission.Read && permission != KMemoryPermission.ReadAndExecute) - { - return KernelResult.InvalidPermission; - } - - return codeMemory.MapToOwner(address, size, permission); - - case CodeMemoryOperation.Unmap: - if (!currentProcess.MemoryManager.CanContain(address, size, MemoryState.CodeWritable)) - { - return KernelResult.InvalidMemRange; - } - - if (permission != KMemoryPermission.None) - { - return KernelResult.InvalidPermission; - } - - return codeMemory.Unmap(address, size); - - case CodeMemoryOperation.UnmapFromOwner: - if (!currentProcess.MemoryManager.CanContain(address, size, MemoryState.CodeReadOnly)) - { - return KernelResult.InvalidMemRange; - } - - if (permission != KMemoryPermission.None) - { - return KernelResult.InvalidPermission; - } - - return codeMemory.UnmapFromOwner(address, size); - - default: return KernelResult.InvalidEnumValue; - } - } - - [Svc(0x73)] - public Result SetProcessMemoryPermission( - int handle, - [PointerSized] ulong src, - [PointerSized] ulong size, - KMemoryPermission permission) - { - if (!PageAligned(src)) - { - return KernelResult.InvalidAddress; - } - - if (!PageAligned(size) || size == 0) - { - return KernelResult.InvalidSize; - } - - if (permission != KMemoryPermission.None && - permission != KMemoryPermission.Read && - permission != KMemoryPermission.ReadAndWrite && - permission != KMemoryPermission.ReadAndExecute) - { - return KernelResult.InvalidPermission; - } - - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - KProcess targetProcess = currentProcess.HandleTable.GetObject<KProcess>(handle); - - if (targetProcess == null) - { - return KernelResult.InvalidHandle; - } - - if (targetProcess.MemoryManager.OutsideAddrSpace(src, size)) - { - return KernelResult.InvalidMemState; - } - - return targetProcess.MemoryManager.SetProcessMemoryPermission(src, size, permission); - } - - [Svc(0x74)] - public Result MapProcessMemory( - [PointerSized] ulong dst, - int handle, - ulong src, - [PointerSized] ulong size) - { - if (!PageAligned(src) || !PageAligned(dst)) - { - return KernelResult.InvalidAddress; - } - - if (!PageAligned(size) || size == 0) - { - return KernelResult.InvalidSize; - } - - if (dst + size <= dst || src + size <= src) - { - return KernelResult.InvalidMemRange; - } - - KProcess dstProcess = KernelStatic.GetCurrentProcess(); - KProcess srcProcess = dstProcess.HandleTable.GetObject<KProcess>(handle); - - if (srcProcess == null) - { - return KernelResult.InvalidHandle; - } - - if (!srcProcess.MemoryManager.InsideAddrSpace(src, size) || - !dstProcess.MemoryManager.CanContain(dst, size, MemoryState.ProcessMemory)) - { - return KernelResult.InvalidMemRange; - } - - KPageList pageList = new KPageList(); - - Result result = srcProcess.MemoryManager.GetPagesIfStateEquals( - src, - size, - MemoryState.MapProcessAllowed, - MemoryState.MapProcessAllowed, - KMemoryPermission.None, - KMemoryPermission.None, - MemoryAttribute.Mask, - MemoryAttribute.None, - pageList); - - if (result != Result.Success) - { - return result; - } - - return dstProcess.MemoryManager.MapPages(dst, pageList, MemoryState.ProcessMemory, KMemoryPermission.ReadAndWrite); - } - - [Svc(0x75)] - public Result UnmapProcessMemory( - [PointerSized] ulong dst, - int handle, - ulong src, - [PointerSized] ulong size) - { - if (!PageAligned(src) || !PageAligned(dst)) - { - return KernelResult.InvalidAddress; - } - - if (!PageAligned(size) || size == 0) - { - return KernelResult.InvalidSize; - } - - if (dst + size <= dst || src + size <= src) - { - return KernelResult.InvalidMemRange; - } - - KProcess dstProcess = KernelStatic.GetCurrentProcess(); - KProcess srcProcess = dstProcess.HandleTable.GetObject<KProcess>(handle); - - if (srcProcess == null) - { - return KernelResult.InvalidHandle; - } - - if (!srcProcess.MemoryManager.InsideAddrSpace(src, size) || - !dstProcess.MemoryManager.CanContain(dst, size, MemoryState.ProcessMemory)) - { - return KernelResult.InvalidMemRange; - } - - Result result = dstProcess.MemoryManager.UnmapProcessMemory(dst, size, srcProcess.MemoryManager, src); - - if (result != Result.Success) - { - return result; - } - - return Result.Success; - } - - [Svc(0x77)] - public Result MapProcessCodeMemory(int handle, ulong dst, ulong src, ulong size) - { - if (!PageAligned(dst) || !PageAligned(src)) - { - return KernelResult.InvalidAddress; - } - - if (!PageAligned(size) || size == 0) - { - return KernelResult.InvalidSize; - } - - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - KProcess targetProcess = currentProcess.HandleTable.GetObject<KProcess>(handle); - - if (targetProcess == null) - { - return KernelResult.InvalidHandle; - } - - if (targetProcess.MemoryManager.OutsideAddrSpace(dst, size) || - targetProcess.MemoryManager.OutsideAddrSpace(src, size) || - targetProcess.MemoryManager.InsideAliasRegion(dst, size) || - targetProcess.MemoryManager.InsideHeapRegion(dst, size)) - { - return KernelResult.InvalidMemRange; - } - - if (size + dst <= dst || size + src <= src) - { - return KernelResult.InvalidMemState; - } - - return targetProcess.MemoryManager.MapProcessCodeMemory(dst, src, size); - } - - [Svc(0x78)] - public Result UnmapProcessCodeMemory(int handle, ulong dst, ulong src, ulong size) - { - if (!PageAligned(dst) || !PageAligned(src)) - { - return KernelResult.InvalidAddress; - } - - if (!PageAligned(size) || size == 0) - { - return KernelResult.InvalidSize; - } - - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - KProcess targetProcess = currentProcess.HandleTable.GetObject<KProcess>(handle); - - if (targetProcess == null) - { - return KernelResult.InvalidHandle; - } - - if (targetProcess.MemoryManager.OutsideAddrSpace(dst, size) || - targetProcess.MemoryManager.OutsideAddrSpace(src, size) || - targetProcess.MemoryManager.InsideAliasRegion(dst, size) || - targetProcess.MemoryManager.InsideHeapRegion(dst, size)) - { - return KernelResult.InvalidMemRange; - } - - if (size + dst <= dst || size + src <= src) - { - return KernelResult.InvalidMemState; - } - - return targetProcess.MemoryManager.UnmapProcessCodeMemory(dst, src, size); - } - - private static bool PageAligned(ulong address) - { - return (address & (KPageTableBase.PageSize - 1)) == 0; - } - - // System - - [Svc(0x7b)] - public Result TerminateProcess(int handle) - { - KProcess process = KernelStatic.GetCurrentProcess(); - - process = process.HandleTable.GetObject<KProcess>(handle); - - Result result; - - if (process != null) - { - if (process == KernelStatic.GetCurrentProcess()) - { - result = Result.Success; - process.DecrementToZeroWhileTerminatingCurrent(); - } - else - { - result = process.Terminate(); - process.DecrementReferenceCount(); - } - } - else - { - result = KernelResult.InvalidHandle; - } - - return result; - } - - [Svc(7)] - public void ExitProcess() - { - KernelStatic.GetCurrentProcess().TerminateCurrentProcess(); - } - - [Svc(0x11)] - public Result SignalEvent(int handle) - { - KProcess process = KernelStatic.GetCurrentProcess(); - - KWritableEvent writableEvent = process.HandleTable.GetObject<KWritableEvent>(handle); - - Result result; - - if (writableEvent != null) - { - writableEvent.Signal(); - - result = Result.Success; - } - else - { - result = KernelResult.InvalidHandle; - } - - return result; - } - - [Svc(0x12)] - public Result ClearEvent(int handle) - { - Result result; - - KProcess process = KernelStatic.GetCurrentProcess(); - - KWritableEvent writableEvent = process.HandleTable.GetObject<KWritableEvent>(handle); - - if (writableEvent == null) - { - KReadableEvent readableEvent = process.HandleTable.GetObject<KReadableEvent>(handle); - - result = readableEvent?.Clear() ?? KernelResult.InvalidHandle; - } - else - { - result = writableEvent.Clear(); - } - - return result; - } - - [Svc(0x16)] - public Result CloseHandle(int handle) - { - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - return currentProcess.HandleTable.CloseHandle(handle) ? Result.Success : KernelResult.InvalidHandle; - } - - [Svc(0x17)] - public Result ResetSignal(int handle) - { - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - KReadableEvent readableEvent = currentProcess.HandleTable.GetObject<KReadableEvent>(handle); - - Result result; - - if (readableEvent != null) - { - result = readableEvent.ClearIfSignaled(); - } - else - { - KProcess process = currentProcess.HandleTable.GetKProcess(handle); - - if (process != null) - { - result = process.ClearIfNotExited(); - } - else - { - result = KernelResult.InvalidHandle; - } - } - - return result; - } - - [Svc(0x1e)] - public ulong GetSystemTick() - { - return _context.TickSource.Counter; - } - - [Svc(0x26)] - public void Break(ulong reason) - { - KThread currentThread = KernelStatic.GetCurrentThread(); - - if ((reason & (1UL << 31)) == 0) - { - currentThread.PrintGuestStackTrace(); - currentThread.PrintGuestRegisterPrintout(); - - // As the process is exiting, this is probably caused by emulation termination. - if (currentThread.Owner.State == ProcessState.Exiting) - { - return; - } - - // TODO: Debug events. - currentThread.Owner.TerminateCurrentProcess(); - - throw new GuestBrokeExecutionException(); - } - else - { - Logger.Debug?.Print(LogClass.KernelSvc, "Debugger triggered."); - } - } - - [Svc(0x27)] - public void OutputDebugString([PointerSized] ulong strPtr, [PointerSized] ulong size) - { - KProcess process = KernelStatic.GetCurrentProcess(); - - string str = MemoryHelper.ReadAsciiString(process.CpuMemory, strPtr, (long)size); - - Logger.Warning?.Print(LogClass.KernelSvc, str); - } - - [Svc(0x29)] - public Result GetInfo(out ulong value, InfoType id, int handle, long subId) - { - value = 0; - - switch (id) - { - case InfoType.CoreMask: - case InfoType.PriorityMask: - case InfoType.AliasRegionAddress: - case InfoType.AliasRegionSize: - case InfoType.HeapRegionAddress: - case InfoType.HeapRegionSize: - case InfoType.TotalMemorySize: - case InfoType.UsedMemorySize: - case InfoType.AslrRegionAddress: - case InfoType.AslrRegionSize: - case InfoType.StackRegionAddress: - case InfoType.StackRegionSize: - case InfoType.SystemResourceSizeTotal: - case InfoType.SystemResourceSizeUsed: - case InfoType.ProgramId: - case InfoType.UserExceptionContextAddress: - case InfoType.TotalNonSystemMemorySize: - case InfoType.UsedNonSystemMemorySize: - case InfoType.IsApplication: - case InfoType.FreeThreadCount: - { - if (subId != 0) - { - return KernelResult.InvalidCombination; - } - - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - KProcess process = currentProcess.HandleTable.GetKProcess(handle); - - if (process == null) - { - return KernelResult.InvalidHandle; - } - - switch (id) - { - case InfoType.CoreMask: value = process.Capabilities.AllowedCpuCoresMask; break; - case InfoType.PriorityMask: value = process.Capabilities.AllowedThreadPriosMask; break; - - case InfoType.AliasRegionAddress: value = process.MemoryManager.AliasRegionStart; break; - case InfoType.AliasRegionSize: - value = (process.MemoryManager.AliasRegionEnd - - process.MemoryManager.AliasRegionStart); break; - - case InfoType.HeapRegionAddress: value = process.MemoryManager.HeapRegionStart; break; - case InfoType.HeapRegionSize: - value = (process.MemoryManager.HeapRegionEnd - - process.MemoryManager.HeapRegionStart); break; - - case InfoType.TotalMemorySize: value = process.GetMemoryCapacity(); break; - - case InfoType.UsedMemorySize: value = process.GetMemoryUsage(); break; - - case InfoType.AslrRegionAddress: value = process.MemoryManager.GetAddrSpaceBaseAddr(); break; - - case InfoType.AslrRegionSize: value = process.MemoryManager.GetAddrSpaceSize(); break; - - case InfoType.StackRegionAddress: value = process.MemoryManager.StackRegionStart; break; - case InfoType.StackRegionSize: - value = (process.MemoryManager.StackRegionEnd - - process.MemoryManager.StackRegionStart); break; - - case InfoType.SystemResourceSizeTotal: value = process.PersonalMmHeapPagesCount * KPageTableBase.PageSize; break; - - case InfoType.SystemResourceSizeUsed: - if (process.PersonalMmHeapPagesCount != 0) - { - value = process.MemoryManager.GetMmUsedPages() * KPageTableBase.PageSize; - } - - break; - - case InfoType.ProgramId: value = process.TitleId; break; - - case InfoType.UserExceptionContextAddress: value = process.UserExceptionContextAddress; break; - - case InfoType.TotalNonSystemMemorySize: value = process.GetMemoryCapacityWithoutPersonalMmHeap(); break; - - case InfoType.UsedNonSystemMemorySize: value = process.GetMemoryUsageWithoutPersonalMmHeap(); break; - - case InfoType.IsApplication: value = process.IsApplication ? 1UL : 0UL; break; - - case InfoType.FreeThreadCount: - if (process.ResourceLimit != null) - { - value = (ulong)(process.ResourceLimit.GetLimitValue(LimitableResource.Thread) - - process.ResourceLimit.GetCurrentValue(LimitableResource.Thread)); - } - else - { - value = 0; - } - - break; - } - - break; - } - - case InfoType.DebuggerAttached: - { - if (handle != 0) - { - return KernelResult.InvalidHandle; - } - - if (subId != 0) - { - return KernelResult.InvalidCombination; - } - - value = KernelStatic.GetCurrentProcess().Debug ? 1UL : 0UL; - - break; - } - - case InfoType.ResourceLimit: - { - if (handle != 0) - { - return KernelResult.InvalidHandle; - } - - if (subId != 0) - { - return KernelResult.InvalidCombination; - } - - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - if (currentProcess.ResourceLimit != null) - { - KHandleTable handleTable = currentProcess.HandleTable; - KResourceLimit resourceLimit = currentProcess.ResourceLimit; - - Result result = handleTable.GenerateHandle(resourceLimit, out int resLimHandle); - - if (result != Result.Success) - { - return result; - } - - value = (uint)resLimHandle; - } - - break; - } - - case InfoType.IdleTickCount: - { - if (handle != 0) - { - return KernelResult.InvalidHandle; - } - - int currentCore = KernelStatic.GetCurrentThread().CurrentCore; - - if (subId != -1 && subId != currentCore) - { - return KernelResult.InvalidCombination; - } - - value = (ulong)KTimeManager.ConvertHostTicksToTicks(_context.Schedulers[currentCore].TotalIdleTimeTicks); - - break; - } - - case InfoType.RandomEntropy: - { - if (handle != 0) - { - return KernelResult.InvalidHandle; - } - - if ((ulong)subId > 3) - { - return KernelResult.InvalidCombination; - } - - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - value = currentProcess.RandomEntropy[subId]; - - break; - } - - case InfoType.ThreadTickCount: - { - if (subId < -1 || subId > 3) - { - return KernelResult.InvalidCombination; - } - - KThread thread = KernelStatic.GetCurrentProcess().HandleTable.GetKThread(handle); - - if (thread == null) - { - return KernelResult.InvalidHandle; - } - - KThread currentThread = KernelStatic.GetCurrentThread(); - - int currentCore = currentThread.CurrentCore; - - if (subId != -1 && subId != currentCore) - { - return Result.Success; - } - - KScheduler scheduler = _context.Schedulers[currentCore]; - - long timeDelta = PerformanceCounter.ElapsedTicks - scheduler.LastContextSwitchTime; - - if (subId != -1) - { - value = (ulong)KTimeManager.ConvertHostTicksToTicks(timeDelta); - } - else - { - long totalTimeRunning = thread.TotalTimeRunning; - - if (thread == currentThread) - { - totalTimeRunning += timeDelta; - } - - value = (ulong)KTimeManager.ConvertHostTicksToTicks(totalTimeRunning); - } - - break; - } - - case InfoType.MesosphereCurrentProcess: - { - if (handle != 0) - { - return KernelResult.InvalidHandle; - } - - if ((ulong)subId != 0) - { - return KernelResult.InvalidCombination; - } - - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - KHandleTable handleTable = currentProcess.HandleTable; - - Result result = handleTable.GenerateHandle(currentProcess, out int outHandle); - - if (result != Result.Success) - { - return result; - } - - value = (ulong)outHandle; - - break; - } - - default: return KernelResult.InvalidEnumValue; - } - - return Result.Success; - } - - [Svc(0x45)] - public Result CreateEvent(out int wEventHandle, out int rEventHandle) - { - KEvent Event = new KEvent(_context); - - KProcess process = KernelStatic.GetCurrentProcess(); - - Result result = process.HandleTable.GenerateHandle(Event.WritableEvent, out wEventHandle); - - if (result == Result.Success) - { - result = process.HandleTable.GenerateHandle(Event.ReadableEvent, out rEventHandle); - - if (result != Result.Success) - { - process.HandleTable.CloseHandle(wEventHandle); - } - } - else - { - rEventHandle = 0; - } - - return result; - } - - [Svc(0x65)] - public Result GetProcessList(out int count, [PointerSized] ulong address, int maxCount) - { - count = 0; - - if ((maxCount >> 28) != 0) - { - return KernelResult.MaximumExceeded; - } - - if (maxCount != 0) - { - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - ulong copySize = (ulong)maxCount * 8; - - if (address + copySize <= address) - { - return KernelResult.InvalidMemState; - } - - if (currentProcess.MemoryManager.OutsideAddrSpace(address, copySize)) - { - return KernelResult.InvalidMemState; - } - } - - int copyCount = 0; - - lock (_context.Processes) - { - foreach (KProcess process in _context.Processes.Values) - { - if (copyCount < maxCount) - { - if (!KernelTransfer.KernelToUser(address + (ulong)copyCount * 8, process.Pid)) - { - return KernelResult.UserCopyFailed; - } - } - - copyCount++; - } - } - - count = copyCount; - - return Result.Success; - } - - [Svc(0x6f)] - public Result GetSystemInfo(out long value, uint id, int handle, long subId) - { - value = 0; - - if (id > 2) - { - return KernelResult.InvalidEnumValue; - } - - if (handle != 0) - { - return KernelResult.InvalidHandle; - } - - if (id < 2) - { - if ((ulong)subId > 3) - { - return KernelResult.InvalidCombination; - } - - KMemoryRegionManager region = _context.MemoryManager.MemoryRegions[subId]; - - switch (id) - { - // Memory region capacity. - case 0: value = (long)region.Size; break; - - // Memory region free space. - case 1: - { - ulong freePagesCount = region.GetFreePages(); - - value = (long)(freePagesCount * KPageTableBase.PageSize); - - break; - } - } - } - else /* if (Id == 2) */ - { - if ((ulong)subId > 1) - { - return KernelResult.InvalidCombination; - } - - switch (subId) - { - case 0: value = _context.PrivilegedProcessLowestId; break; - case 1: value = _context.PrivilegedProcessHighestId; break; - } - } - - return Result.Success; - } - - [Svc(0x30)] - public Result GetResourceLimitLimitValue(out long limitValue, int handle, LimitableResource resource) - { - limitValue = 0; - - if (resource >= LimitableResource.Count) - { - return KernelResult.InvalidEnumValue; - } - - KResourceLimit resourceLimit = KernelStatic.GetCurrentProcess().HandleTable.GetObject<KResourceLimit>(handle); - - if (resourceLimit == null) - { - return KernelResult.InvalidHandle; - } - - limitValue = resourceLimit.GetLimitValue(resource); - - return Result.Success; - } - - [Svc(0x31)] - public Result GetResourceLimitCurrentValue(out long limitValue, int handle, LimitableResource resource) - { - limitValue = 0; - - if (resource >= LimitableResource.Count) - { - return KernelResult.InvalidEnumValue; - } - - KResourceLimit resourceLimit = KernelStatic.GetCurrentProcess().HandleTable.GetObject<KResourceLimit>(handle); - - if (resourceLimit == null) - { - return KernelResult.InvalidHandle; - } - - limitValue = resourceLimit.GetCurrentValue(resource); - - return Result.Success; - } - - [Svc(0x37)] - public Result GetResourceLimitPeakValue(out long peak, int handle, LimitableResource resource) - { - peak = 0; - - if (resource >= LimitableResource.Count) - { - return KernelResult.InvalidEnumValue; - } - - KResourceLimit resourceLimit = KernelStatic.GetCurrentProcess().HandleTable.GetObject<KResourceLimit>(handle); - - if (resourceLimit == null) - { - return KernelResult.InvalidHandle; - } - - peak = resourceLimit.GetPeakValue(resource); - - return Result.Success; - } - - [Svc(0x7d)] - public Result CreateResourceLimit(out int handle) - { - KResourceLimit limit = new KResourceLimit(_context); - - KProcess process = KernelStatic.GetCurrentProcess(); - - return process.HandleTable.GenerateHandle(limit, out handle); - } - - [Svc(0x7e)] - public Result SetResourceLimitLimitValue(int handle, LimitableResource resource, long limitValue) - { - if (resource >= LimitableResource.Count) - { - return KernelResult.InvalidEnumValue; - } - - KResourceLimit resourceLimit = KernelStatic.GetCurrentProcess().HandleTable.GetObject<KResourceLimit>(handle); - - if (resourceLimit == null) - { - return KernelResult.InvalidHandle; - } - - return resourceLimit.SetLimitValue(resource, limitValue); - } - - // Thread - - [Svc(8)] - public Result CreateThread( - out int handle, - [PointerSized] ulong entrypoint, - [PointerSized] ulong argsPtr, - [PointerSized] ulong stackTop, - int priority, - int cpuCore) - { - return CreateThread(out handle, entrypoint, argsPtr, stackTop, priority, cpuCore, null); - } - - public Result CreateThread( - out int handle, - ulong entrypoint, - ulong argsPtr, - ulong stackTop, - int priority, - int cpuCore, - ThreadStart customThreadStart) - { - handle = 0; - - KProcess currentProcess = KernelStatic.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(_context); - - Result result = currentProcess.InitializeThread( - thread, - entrypoint, - argsPtr, - stackTop, - priority, - cpuCore, - customThreadStart); - - if (result == Result.Success) - { - KProcess process = KernelStatic.GetCurrentProcess(); - - result = process.HandleTable.GenerateHandle(thread, out handle); - } - else - { - currentProcess.ResourceLimit?.Release(LimitableResource.Thread, 1); - } - - thread.DecrementReferenceCount(); - - return result; - } - - [Svc(9)] - public Result StartThread(int handle) - { - KProcess process = KernelStatic.GetCurrentProcess(); - - KThread thread = process.HandleTable.GetKThread(handle); - - if (thread != null) - { - thread.IncrementReferenceCount(); - - Result result = thread.Start(); - - if (result == Result.Success) - { - thread.IncrementReferenceCount(); - } - - thread.DecrementReferenceCount(); - - return result; - } - else - { - return KernelResult.InvalidHandle; - } - } - - [Svc(0xa)] - public void ExitThread() - { - KThread currentThread = KernelStatic.GetCurrentThread(); - - currentThread.Exit(); - } - - [Svc(0xb)] - public void SleepThread(long timeout) - { - if (timeout < 1) - { - switch (timeout) - { - case 0: KScheduler.Yield(_context); break; - case -1: KScheduler.YieldWithLoadBalancing(_context); break; - case -2: KScheduler.YieldToAnyThread(_context); break; - } - } - else - { - KernelStatic.GetCurrentThread().Sleep(timeout + KTimeManager.DefaultTimeIncrementNanoseconds); - } - } - - [Svc(0xc)] - public Result GetThreadPriority(out int priority, int handle) - { - KProcess process = KernelStatic.GetCurrentProcess(); - - KThread thread = process.HandleTable.GetKThread(handle); - - if (thread != null) - { - priority = thread.DynamicPriority; - - return Result.Success; - } - else - { - priority = 0; - - return KernelResult.InvalidHandle; - } - } - - [Svc(0xd)] - public Result SetThreadPriority(int handle, int priority) - { - // TODO: NPDM check. - - KProcess process = KernelStatic.GetCurrentProcess(); - - KThread thread = process.HandleTable.GetKThread(handle); - - if (thread == null) - { - return KernelResult.InvalidHandle; - } - - thread.SetPriority(priority); - - return Result.Success; - } - - [Svc(0xe)] - public Result GetThreadCoreMask(out int preferredCore, out ulong affinityMask, int handle) - { - KProcess process = KernelStatic.GetCurrentProcess(); - - KThread thread = process.HandleTable.GetKThread(handle); - - if (thread != null) - { - preferredCore = thread.PreferredCore; - affinityMask = thread.AffinityMask; - - return Result.Success; - } - else - { - preferredCore = 0; - affinityMask = 0; - - return KernelResult.InvalidHandle; - } - } - - [Svc(0xf)] - public Result SetThreadCoreMask(int handle, int preferredCore, ulong affinityMask) - { - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - if (preferredCore == -2) - { - preferredCore = currentProcess.DefaultCpuCore; - - affinityMask = 1UL << 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 & (1UL << preferredCore)) == 0) - { - return KernelResult.InvalidCombination; - } - } - - KProcess process = KernelStatic.GetCurrentProcess(); - - KThread thread = process.HandleTable.GetKThread(handle); - - if (thread == null) - { - return KernelResult.InvalidHandle; - } - - return thread.SetCoreAndAffinityMask(preferredCore, affinityMask); - } - - [Svc(0x10)] - public int GetCurrentProcessorNumber() - { - return KernelStatic.GetCurrentThread().CurrentCore; - } - - [Svc(0x25)] - public Result GetThreadId(out ulong threadUid, int handle) - { - KProcess process = KernelStatic.GetCurrentProcess(); - - KThread thread = process.HandleTable.GetKThread(handle); - - if (thread != null) - { - threadUid = thread.ThreadUid; - - return Result.Success; - } - else - { - threadUid = 0; - - return KernelResult.InvalidHandle; - } - } - - [Svc(0x32)] - public Result SetThreadActivity(int handle, bool pause) - { - KProcess process = KernelStatic.GetCurrentProcess(); - - KThread thread = process.HandleTable.GetObject<KThread>(handle); - - if (thread == null) - { - return KernelResult.InvalidHandle; - } - - if (thread.Owner != process) - { - return KernelResult.InvalidHandle; - } - - if (thread == KernelStatic.GetCurrentThread()) - { - return KernelResult.InvalidThread; - } - - return thread.SetActivity(pause); - } - - [Svc(0x33)] - public Result GetThreadContext3([PointerSized] ulong address, int handle) - { - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - KThread currentThread = KernelStatic.GetCurrentThread(); - - KThread thread = currentProcess.HandleTable.GetObject<KThread>(handle); - - if (thread == null) - { - return KernelResult.InvalidHandle; - } - - if (thread.Owner != currentProcess) - { - return KernelResult.InvalidHandle; - } - - if (currentThread == thread) - { - return KernelResult.InvalidThread; - } - - Result result = thread.GetThreadContext3(out ThreadContext context); - - if (result == Result.Success) - { - return KernelTransfer.KernelToUser(address, context) - ? Result.Success - : KernelResult.InvalidMemState; - } - - return result; - } - - // Thread synchronization - - [Svc(0x18)] - public Result WaitSynchronization(out int handleIndex, [PointerSized] ulong handlesPtr, int handlesCount, long timeout) - { - handleIndex = 0; - - if ((uint)handlesCount > KThread.MaxWaitSyncObjects) - { - return KernelResult.MaximumExceeded; - } - - KThread currentThread = KernelStatic.GetCurrentThread(); - - if (handlesCount != 0) - { - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - if (currentProcess.MemoryManager.AddrSpaceStart > handlesPtr) - { - return KernelResult.UserCopyFailed; - } - - long handlesSize = handlesCount * 4; - - if (handlesPtr + (ulong)handlesSize <= handlesPtr) - { - return KernelResult.UserCopyFailed; - } - - if (handlesPtr + (ulong)handlesSize - 1 > currentProcess.MemoryManager.AddrSpaceEnd - 1) - { - return KernelResult.UserCopyFailed; - } - - Span<int> handles = new Span<int>(currentThread.WaitSyncHandles).Slice(0, handlesCount); - - if (!KernelTransfer.UserToKernelArray(handlesPtr, handles)) - { - return KernelResult.UserCopyFailed; - } - - return WaitSynchronization(out handleIndex, handles, timeout); - } - - return WaitSynchronization(out handleIndex, ReadOnlySpan<int>.Empty, timeout); - } - - public Result WaitSynchronization(out int handleIndex, ReadOnlySpan<int> handles, long timeout) - { - handleIndex = 0; - - if ((uint)handles.Length > KThread.MaxWaitSyncObjects) - { - return KernelResult.MaximumExceeded; - } - - KThread currentThread = KernelStatic.GetCurrentThread(); - - var syncObjs = new Span<KSynchronizationObject>(currentThread.WaitSyncObjects).Slice(0, handles.Length); - - if (handles.Length != 0) - { - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - int processedHandles = 0; - - for (; processedHandles < handles.Length; processedHandles++) - { - KSynchronizationObject syncObj = currentProcess.HandleTable.GetObject<KSynchronizationObject>(handles[processedHandles]); - - if (syncObj == null) - { - break; - } - - syncObjs[processedHandles] = syncObj; - - syncObj.IncrementReferenceCount(); - } - - if (processedHandles != handles.Length) - { - // One or more handles are invalid. - for (int index = 0; index < processedHandles; index++) - { - currentThread.WaitSyncObjects[index].DecrementReferenceCount(); - } - - return KernelResult.InvalidHandle; - } - } - - if (timeout > 0) - { - timeout += KTimeManager.DefaultTimeIncrementNanoseconds; - } - - Result result = _context.Synchronization.WaitFor(syncObjs, timeout, out handleIndex); - - if (result == KernelResult.PortRemoteClosed) - { - result = Result.Success; - } - - for (int index = 0; index < handles.Length; index++) - { - currentThread.WaitSyncObjects[index].DecrementReferenceCount(); - } - - return result; - } - - [Svc(0x19)] - public Result CancelSynchronization(int handle) - { - KProcess process = KernelStatic.GetCurrentProcess(); - - KThread thread = process.HandleTable.GetKThread(handle); - - if (thread == null) - { - return KernelResult.InvalidHandle; - } - - thread.CancelSynchronization(); - - return Result.Success; - } - - [Svc(0x1a)] - public Result ArbitrateLock(int ownerHandle, [PointerSized] ulong mutexAddress, int requesterHandle) - { - if (IsPointingInsideKernel(mutexAddress)) - { - return KernelResult.InvalidMemState; - } - - if (IsAddressNotWordAligned(mutexAddress)) - { - return KernelResult.InvalidAddress; - } - - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - return currentProcess.AddressArbiter.ArbitrateLock(ownerHandle, mutexAddress, requesterHandle); - } - - [Svc(0x1b)] - public Result ArbitrateUnlock([PointerSized] ulong mutexAddress) - { - if (IsPointingInsideKernel(mutexAddress)) - { - return KernelResult.InvalidMemState; - } - - if (IsAddressNotWordAligned(mutexAddress)) - { - return KernelResult.InvalidAddress; - } - - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - return currentProcess.AddressArbiter.ArbitrateUnlock(mutexAddress); - } - - [Svc(0x1c)] - public Result WaitProcessWideKeyAtomic( - [PointerSized] ulong mutexAddress, - [PointerSized] ulong condVarAddress, - int handle, - long timeout) - { - if (IsPointingInsideKernel(mutexAddress)) - { - return KernelResult.InvalidMemState; - } - - if (IsAddressNotWordAligned(mutexAddress)) - { - return KernelResult.InvalidAddress; - } - - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - if (timeout > 0) - { - timeout += KTimeManager.DefaultTimeIncrementNanoseconds; - } - - return currentProcess.AddressArbiter.WaitProcessWideKeyAtomic( - mutexAddress, - condVarAddress, - handle, - timeout); - } - - [Svc(0x1d)] - public Result SignalProcessWideKey([PointerSized] ulong address, int count) - { - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - currentProcess.AddressArbiter.SignalProcessWideKey(address, count); - - return Result.Success; - } - - [Svc(0x34)] - public Result WaitForAddress([PointerSized] ulong address, ArbitrationType type, int value, long timeout) - { - if (IsPointingInsideKernel(address)) - { - return KernelResult.InvalidMemState; - } - - if (IsAddressNotWordAligned(address)) - { - return KernelResult.InvalidAddress; - } - - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - if (timeout > 0) - { - timeout += KTimeManager.DefaultTimeIncrementNanoseconds; - } - - return type switch - { - ArbitrationType.WaitIfLessThan - => currentProcess.AddressArbiter.WaitForAddressIfLessThan(address, value, false, timeout), - ArbitrationType.DecrementAndWaitIfLessThan - => currentProcess.AddressArbiter.WaitForAddressIfLessThan(address, value, true, timeout), - ArbitrationType.WaitIfEqual - => currentProcess.AddressArbiter.WaitForAddressIfEqual(address, value, timeout), - _ => KernelResult.InvalidEnumValue, - }; - } - - [Svc(0x35)] - public Result SignalToAddress([PointerSized] ulong address, SignalType type, int value, int count) - { - if (IsPointingInsideKernel(address)) - { - return KernelResult.InvalidMemState; - } - - if (IsAddressNotWordAligned(address)) - { - return KernelResult.InvalidAddress; - } - - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - return type switch - { - SignalType.Signal - => currentProcess.AddressArbiter.Signal(address, count), - SignalType.SignalAndIncrementIfEqual - => currentProcess.AddressArbiter.SignalAndIncrementIfEqual(address, value, count), - SignalType.SignalAndModifyIfEqual - => currentProcess.AddressArbiter.SignalAndModifyIfEqual(address, value, count), - _ => KernelResult.InvalidEnumValue - }; - } - - [Svc(0x36)] - public Result SynchronizePreemptionState() - { - KernelStatic.GetCurrentThread().SynchronizePreemptionState(); - - return Result.Success; - } - - private static bool IsPointingInsideKernel(ulong address) - { - return (address + 0x1000000000) < 0xffffff000; - } - - private static bool IsAddressNotWordAligned(ulong address) - { - return (address & 3) != 0; - } - } -}
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SyscallHandler.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SyscallHandler.cs deleted file mode 100644 index 710bac94..00000000 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SyscallHandler.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Ryujinx.Cpu; -using Ryujinx.HLE.HOS.Kernel.Threading; - -namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall -{ - partial class SyscallHandler - { - private readonly KernelContext _context; - - public SyscallHandler(KernelContext context) - { - _context = context; - } - - public void SvcCall(IExecutionContext context, ulong address, int id) - { - KThread currentThread = KernelStatic.GetCurrentThread(); - - if (currentThread.Owner != null && - currentThread.GetUserDisableCount() != 0 && - currentThread.Owner.PinnedThreads[currentThread.CurrentCore] == null) - { - _context.CriticalSection.Enter(); - - currentThread.Owner.PinThread(currentThread); - - currentThread.SetUserInterruptFlag(); - - _context.CriticalSection.Leave(); - } - - if (context.IsAarch32) - { - SyscallDispatch.Dispatch32(_context.Syscall, context, id); - } - else - { - SyscallDispatch.Dispatch64(_context.Syscall, context, id); - } - - currentThread.HandlePostSyscall(); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/ThreadContext.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/ThreadContext.cs deleted file mode 100644 index b524406a..00000000 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/ThreadContext.cs +++ /dev/null @@ -1,22 +0,0 @@ -using ARMeilleure.State; -using Ryujinx.Common.Memory; - -namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall -{ - struct ThreadContext - { - public Array29<ulong> Registers; - public ulong Fp; - public ulong Lr; - public ulong Sp; - public ulong Pc; - public uint Pstate; -#pragma warning disable CS0169 - private uint _padding; -#pragma warning restore CS0169 - public Array32<V128> FpuRegisters; - public uint Fpcr; - public uint Fpsr; - public ulong Tpidr; - } -} |
